1 /*
2 * Copyright (c) 2018, Joyent, Inc.
3 */
4
5 /*
6 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
8 */
9
10 /*
11 * Copyright (c) 2009, Intel Corporation
12 * All rights reserved.
13 */
14
15 /*
16 * Copyright (c) 2006
17 * Copyright (c) 2007
18 * Damien Bergamini <damien.bergamini@free.fr>
19 *
20 * Permission to use, copy, modify, and distribute this software for any
21 * purpose with or without fee is hereby granted, provided that the above
22 * copyright notice and this permission notice appear in all copies.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
25 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
27 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
28 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
29 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
30 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 */
32
33 /*
34 * Intel(R) WiFi Link 6000 Driver
35 */
36
37 #include <sys/types.h>
38 #include <sys/byteorder.h>
39 #include <sys/conf.h>
40 #include <sys/cmn_err.h>
41 #include <sys/stat.h>
42 #include <sys/ddi.h>
43 #include <sys/sunddi.h>
44 #include <sys/strsubr.h>
45 #include <sys/ethernet.h>
46 #include <inet/common.h>
47 #include <inet/nd.h>
48 #include <inet/mi.h>
49 #include <sys/note.h>
50 #include <sys/stream.h>
51 #include <sys/strsun.h>
52 #include <sys/modctl.h>
53 #include <sys/devops.h>
54 #include <sys/dlpi.h>
55 #include <sys/mac_provider.h>
56 #include <sys/mac_wifi.h>
57 #include <sys/net80211.h>
58 #include <sys/net80211_proto.h>
59 #include <sys/varargs.h>
60 #include <sys/policy.h>
61 #include <sys/pci.h>
62
63 #include "iwp_calibration.h"
64 #include "iwp_hw.h"
65 #include "iwp_eeprom.h"
66 #include "iwp_var.h"
67 #include <inet/wifi_ioctl.h>
68
69 #ifdef DEBUG
70 #define IWP_DEBUG_80211 (1 << 0)
71 #define IWP_DEBUG_CMD (1 << 1)
72 #define IWP_DEBUG_DMA (1 << 2)
73 #define IWP_DEBUG_EEPROM (1 << 3)
74 #define IWP_DEBUG_FW (1 << 4)
75 #define IWP_DEBUG_HW (1 << 5)
76 #define IWP_DEBUG_INTR (1 << 6)
77 #define IWP_DEBUG_MRR (1 << 7)
78 #define IWP_DEBUG_PIO (1 << 8)
79 #define IWP_DEBUG_RX (1 << 9)
80 #define IWP_DEBUG_SCAN (1 << 10)
81 #define IWP_DEBUG_TX (1 << 11)
82 #define IWP_DEBUG_RATECTL (1 << 12)
83 #define IWP_DEBUG_RADIO (1 << 13)
84 #define IWP_DEBUG_RESUME (1 << 14)
85 #define IWP_DEBUG_CALIBRATION (1 << 15)
86 /*
87 * if want to see debug message of a given section,
88 * please set this flag to one of above values
89 */
90 uint32_t iwp_dbg_flags = 0;
91 #define IWP_DBG(x) \
92 iwp_dbg x
93 #else
94 #define IWP_DBG(x)
95 #endif
96
97 static void *iwp_soft_state_p = NULL;
98
99 /*
100 * ucode will be compiled into driver image
101 */
102 static uint8_t iwp_fw_bin [] = {
103 #include "fw-iw/iwp.ucode"
104 };
105
106 /*
107 * DMA attributes for a shared page
108 */
109 static ddi_dma_attr_t sh_dma_attr = {
110 DMA_ATTR_V0, /* version of this structure */
111 0, /* lowest usable address */
112 0xffffffffU, /* highest usable address */
113 0xffffffffU, /* maximum DMAable byte count */
114 0x1000, /* alignment in bytes */
115 0x1000, /* burst sizes (any?) */
116 1, /* minimum transfer */
117 0xffffffffU, /* maximum transfer */
118 0xffffffffU, /* maximum segment length */
119 1, /* maximum number of segments */
120 1, /* granularity */
121 0, /* flags (reserved) */
122 };
123
124 /*
125 * DMA attributes for a keep warm DRAM descriptor
126 */
127 static ddi_dma_attr_t kw_dma_attr = {
128 DMA_ATTR_V0, /* version of this structure */
129 0, /* lowest usable address */
130 0xffffffffU, /* highest usable address */
131 0xffffffffU, /* maximum DMAable byte count */
132 0x1000, /* alignment in bytes */
133 0x1000, /* burst sizes (any?) */
134 1, /* minimum transfer */
135 0xffffffffU, /* maximum transfer */
136 0xffffffffU, /* maximum segment length */
137 1, /* maximum number of segments */
138 1, /* granularity */
139 0, /* flags (reserved) */
140 };
141
142 /*
143 * DMA attributes for a ring descriptor
144 */
145 static ddi_dma_attr_t ring_desc_dma_attr = {
146 DMA_ATTR_V0, /* version of this structure */
147 0, /* lowest usable address */
148 0xffffffffU, /* highest usable address */
149 0xffffffffU, /* maximum DMAable byte count */
150 0x100, /* alignment in bytes */
151 0x100, /* burst sizes (any?) */
152 1, /* minimum transfer */
153 0xffffffffU, /* maximum transfer */
154 0xffffffffU, /* maximum segment length */
155 1, /* maximum number of segments */
156 1, /* granularity */
157 0, /* flags (reserved) */
158 };
159
160 /*
161 * DMA attributes for a cmd
162 */
163 static ddi_dma_attr_t cmd_dma_attr = {
164 DMA_ATTR_V0, /* version of this structure */
165 0, /* lowest usable address */
166 0xffffffffU, /* highest usable address */
167 0xffffffffU, /* maximum DMAable byte count */
168 4, /* alignment in bytes */
169 0x100, /* burst sizes (any?) */
170 1, /* minimum transfer */
171 0xffffffffU, /* maximum transfer */
172 0xffffffffU, /* maximum segment length */
173 1, /* maximum number of segments */
174 1, /* granularity */
175 0, /* flags (reserved) */
176 };
177
178 /*
179 * DMA attributes for a rx buffer
180 */
181 static ddi_dma_attr_t rx_buffer_dma_attr = {
182 DMA_ATTR_V0, /* version of this structure */
183 0, /* lowest usable address */
184 0xffffffffU, /* highest usable address */
185 0xffffffffU, /* maximum DMAable byte count */
186 0x100, /* alignment in bytes */
187 0x100, /* burst sizes (any?) */
188 1, /* minimum transfer */
189 0xffffffffU, /* maximum transfer */
190 0xffffffffU, /* maximum segment length */
191 1, /* maximum number of segments */
192 1, /* granularity */
193 0, /* flags (reserved) */
194 };
195
196 /*
197 * DMA attributes for a tx buffer.
198 * the maximum number of segments is 4 for the hardware.
199 * now all the wifi drivers put the whole frame in a single
200 * descriptor, so we define the maximum number of segments 1,
201 * just the same as the rx_buffer. we consider leverage the HW
202 * ability in the future, that is why we don't define rx and tx
203 * buffer_dma_attr as the same.
204 */
205 static ddi_dma_attr_t tx_buffer_dma_attr = {
206 DMA_ATTR_V0, /* version of this structure */
207 0, /* lowest usable address */
208 0xffffffffU, /* highest usable address */
209 0xffffffffU, /* maximum DMAable byte count */
210 4, /* alignment in bytes */
211 0x100, /* burst sizes (any?) */
212 1, /* minimum transfer */
213 0xffffffffU, /* maximum transfer */
214 0xffffffffU, /* maximum segment length */
215 1, /* maximum number of segments */
216 1, /* granularity */
217 0, /* flags (reserved) */
218 };
219
220 /*
221 * DMA attributes for text and data part in the firmware
222 */
223 static ddi_dma_attr_t fw_dma_attr = {
224 DMA_ATTR_V0, /* version of this structure */
225 0, /* lowest usable address */
226 0xffffffffU, /* highest usable address */
227 0x7fffffff, /* maximum DMAable byte count */
228 0x10, /* alignment in bytes */
229 0x100, /* burst sizes (any?) */
230 1, /* minimum transfer */
231 0xffffffffU, /* maximum transfer */
232 0xffffffffU, /* maximum segment length */
233 1, /* maximum number of segments */
234 1, /* granularity */
235 0, /* flags (reserved) */
236 };
237
238 /*
239 * regs access attributes
240 */
241 static ddi_device_acc_attr_t iwp_reg_accattr = {
242 DDI_DEVICE_ATTR_V0,
243 DDI_STRUCTURE_LE_ACC,
244 DDI_STRICTORDER_ACC,
245 DDI_DEFAULT_ACC
246 };
247
248 /*
249 * DMA access attributes for descriptor
250 */
251 static ddi_device_acc_attr_t iwp_dma_descattr = {
252 DDI_DEVICE_ATTR_V0,
253 DDI_STRUCTURE_LE_ACC,
254 DDI_STRICTORDER_ACC,
255 DDI_DEFAULT_ACC
256 };
257
258 /*
259 * DMA access attributes
260 */
261 static ddi_device_acc_attr_t iwp_dma_accattr = {
262 DDI_DEVICE_ATTR_V0,
263 DDI_NEVERSWAP_ACC,
264 DDI_STRICTORDER_ACC,
265 DDI_DEFAULT_ACC
266 };
267
268 static int iwp_ring_init(iwp_sc_t *);
269 static void iwp_ring_free(iwp_sc_t *);
270 static int iwp_alloc_shared(iwp_sc_t *);
271 static void iwp_free_shared(iwp_sc_t *);
272 static int iwp_alloc_kw(iwp_sc_t *);
273 static void iwp_free_kw(iwp_sc_t *);
274 static int iwp_alloc_fw_dma(iwp_sc_t *);
275 static void iwp_free_fw_dma(iwp_sc_t *);
276 static int iwp_alloc_rx_ring(iwp_sc_t *);
277 static void iwp_reset_rx_ring(iwp_sc_t *);
278 static void iwp_free_rx_ring(iwp_sc_t *);
279 static int iwp_alloc_tx_ring(iwp_sc_t *, iwp_tx_ring_t *,
280 int, int);
281 static void iwp_reset_tx_ring(iwp_sc_t *, iwp_tx_ring_t *);
282 static void iwp_free_tx_ring(iwp_tx_ring_t *);
283 static ieee80211_node_t *iwp_node_alloc(ieee80211com_t *);
284 static void iwp_node_free(ieee80211_node_t *);
285 static int iwp_newstate(ieee80211com_t *, enum ieee80211_state, int);
286 static void iwp_mac_access_enter(iwp_sc_t *);
287 static void iwp_mac_access_exit(iwp_sc_t *);
288 static uint32_t iwp_reg_read(iwp_sc_t *, uint32_t);
289 static void iwp_reg_write(iwp_sc_t *, uint32_t, uint32_t);
290 static int iwp_load_init_firmware(iwp_sc_t *);
291 static int iwp_load_run_firmware(iwp_sc_t *);
292 static void iwp_tx_intr(iwp_sc_t *, iwp_rx_desc_t *);
293 static void iwp_cmd_intr(iwp_sc_t *, iwp_rx_desc_t *);
294 static uint_t iwp_intr(caddr_t, caddr_t);
295 static int iwp_eep_load(iwp_sc_t *);
296 static void iwp_get_mac_from_eep(iwp_sc_t *);
297 static int iwp_eep_sem_down(iwp_sc_t *);
298 static void iwp_eep_sem_up(iwp_sc_t *);
299 static uint_t iwp_rx_softintr(caddr_t, caddr_t);
300 static uint8_t iwp_rate_to_plcp(int);
301 static int iwp_cmd(iwp_sc_t *, int, const void *, int, int);
302 static void iwp_set_led(iwp_sc_t *, uint8_t, uint8_t, uint8_t);
303 static int iwp_hw_set_before_auth(iwp_sc_t *);
304 static int iwp_scan(iwp_sc_t *);
305 static int iwp_config(iwp_sc_t *);
306 static void iwp_stop_master(iwp_sc_t *);
307 static int iwp_power_up(iwp_sc_t *);
308 static int iwp_preinit(iwp_sc_t *);
309 static int iwp_init(iwp_sc_t *);
310 static void iwp_stop(iwp_sc_t *);
311 static int iwp_quiesce(dev_info_t *t);
312 static void iwp_amrr_init(iwp_amrr_t *);
313 static void iwp_amrr_timeout(iwp_sc_t *);
314 static void iwp_amrr_ratectl(void *, ieee80211_node_t *);
315 static void iwp_ucode_alive(iwp_sc_t *, iwp_rx_desc_t *);
316 static void iwp_rx_phy_intr(iwp_sc_t *, iwp_rx_desc_t *);
317 static void iwp_rx_mpdu_intr(iwp_sc_t *, iwp_rx_desc_t *);
318 static void iwp_release_calib_buffer(iwp_sc_t *);
319 static int iwp_init_common(iwp_sc_t *);
320 static uint8_t *iwp_eep_addr_trans(iwp_sc_t *, uint32_t);
321 static int iwp_put_seg_fw(iwp_sc_t *, uint32_t, uint32_t, uint32_t);
322 static int iwp_alive_common(iwp_sc_t *);
323 static void iwp_save_calib_result(iwp_sc_t *, iwp_rx_desc_t *);
324 static int iwp_attach(dev_info_t *, ddi_attach_cmd_t);
325 static int iwp_detach(dev_info_t *, ddi_detach_cmd_t);
326 static void iwp_destroy_locks(iwp_sc_t *);
327 static int iwp_send(ieee80211com_t *, mblk_t *, uint8_t);
328 static void iwp_thread(iwp_sc_t *);
329 static int iwp_run_state_config(iwp_sc_t *);
330 static int iwp_fast_recover(iwp_sc_t *);
331 static void iwp_overwrite_ic_default(iwp_sc_t *);
332 static int iwp_add_ap_sta(iwp_sc_t *);
333 static int iwp_alloc_dma_mem(iwp_sc_t *, size_t,
334 ddi_dma_attr_t *, ddi_device_acc_attr_t *,
335 uint_t, iwp_dma_t *);
336 static void iwp_free_dma_mem(iwp_dma_t *);
337 static int iwp_eep_ver_chk(iwp_sc_t *);
338 static void iwp_set_chip_param(iwp_sc_t *);
339
340 /*
341 * GLD specific operations
342 */
343 static int iwp_m_stat(void *, uint_t, uint64_t *);
344 static int iwp_m_start(void *);
345 static void iwp_m_stop(void *);
346 static int iwp_m_unicst(void *, const uint8_t *);
347 static int iwp_m_multicst(void *, boolean_t, const uint8_t *);
348 static int iwp_m_promisc(void *, boolean_t);
349 static mblk_t *iwp_m_tx(void *, mblk_t *);
350 static void iwp_m_ioctl(void *, queue_t *, mblk_t *);
351 static int iwp_m_setprop(void *arg, const char *pr_name,
352 mac_prop_id_t wldp_pr_num, uint_t wldp_length, const void *wldp_buf);
353 static int iwp_m_getprop(void *arg, const char *pr_name,
354 mac_prop_id_t wldp_pr_num, uint_t wldp_length, void *wldp_buf);
355 static void iwp_m_propinfo(void *, const char *, mac_prop_id_t,
356 mac_prop_info_handle_t);
357
358 /*
359 * Supported rates for 802.11b/g modes (in 500Kbps unit).
360 */
361 static const struct ieee80211_rateset iwp_rateset_11b =
362 { 4, { 2, 4, 11, 22 } };
363
364 static const struct ieee80211_rateset iwp_rateset_11g =
365 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
366
367 /*
368 * For mfthread only
369 */
370 extern pri_t minclsyspri;
371
372 #define DRV_NAME_SP "iwp"
373
374 /*
375 * Module Loading Data & Entry Points
376 */
377 DDI_DEFINE_STREAM_OPS(iwp_devops, nulldev, nulldev, iwp_attach,
378 iwp_detach, nodev, NULL, D_MP, NULL, iwp_quiesce);
379
380 static struct modldrv iwp_modldrv = {
381 &mod_driverops,
382 "Intel(R) PumaPeak driver(N)",
383 &iwp_devops
384 };
385
386 static struct modlinkage iwp_modlinkage = {
387 MODREV_1,
388 &iwp_modldrv,
389 NULL
390 };
391
392 int
_init(void)393 _init(void)
394 {
395 int status;
396
397 status = ddi_soft_state_init(&iwp_soft_state_p,
398 sizeof (iwp_sc_t), 1);
399 if (status != DDI_SUCCESS) {
400 return (status);
401 }
402
403 mac_init_ops(&iwp_devops, DRV_NAME_SP);
404 status = mod_install(&iwp_modlinkage);
405 if (status != DDI_SUCCESS) {
406 mac_fini_ops(&iwp_devops);
407 ddi_soft_state_fini(&iwp_soft_state_p);
408 }
409
410 return (status);
411 }
412
413 int
_fini(void)414 _fini(void)
415 {
416 int status;
417
418 status = mod_remove(&iwp_modlinkage);
419 if (DDI_SUCCESS == status) {
420 mac_fini_ops(&iwp_devops);
421 ddi_soft_state_fini(&iwp_soft_state_p);
422 }
423
424 return (status);
425 }
426
427 int
_info(struct modinfo * mip)428 _info(struct modinfo *mip)
429 {
430 return (mod_info(&iwp_modlinkage, mip));
431 }
432
433 /*
434 * Mac Call Back entries
435 */
436 mac_callbacks_t iwp_m_callbacks = {
437 MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
438 iwp_m_stat,
439 iwp_m_start,
440 iwp_m_stop,
441 iwp_m_promisc,
442 iwp_m_multicst,
443 iwp_m_unicst,
444 iwp_m_tx,
445 NULL,
446 iwp_m_ioctl,
447 NULL,
448 NULL,
449 NULL,
450 iwp_m_setprop,
451 iwp_m_getprop,
452 iwp_m_propinfo
453 };
454
455 #ifdef DEBUG
456 void
iwp_dbg(uint32_t flags,const char * fmt,...)457 iwp_dbg(uint32_t flags, const char *fmt, ...)
458 {
459 va_list ap;
460
461 if (flags & iwp_dbg_flags) {
462 va_start(ap, fmt);
463 vcmn_err(CE_NOTE, fmt, ap);
464 va_end(ap);
465 }
466 }
467 #endif /* DEBUG */
468
469 /*
470 * device operations
471 */
472 int
iwp_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)473 iwp_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
474 {
475 iwp_sc_t *sc;
476 ieee80211com_t *ic;
477 int instance, i;
478 char strbuf[32];
479 wifi_data_t wd = { 0 };
480 mac_register_t *macp;
481 int intr_type;
482 int intr_count;
483 int intr_actual;
484 int err = DDI_FAILURE;
485
486 switch (cmd) {
487 case DDI_ATTACH:
488 break;
489 case DDI_RESUME:
490 instance = ddi_get_instance(dip);
491 sc = ddi_get_soft_state(iwp_soft_state_p,
492 instance);
493 ASSERT(sc != NULL);
494
495 if (sc->sc_flags & IWP_F_RUNNING) {
496 (void) iwp_init(sc);
497 }
498
499 atomic_and_32(&sc->sc_flags, ~IWP_F_SUSPEND);
500
501 IWP_DBG((IWP_DEBUG_RESUME, "iwp_attach(): "
502 "resume\n"));
503 return (DDI_SUCCESS);
504 default:
505 goto attach_fail1;
506 }
507
508 instance = ddi_get_instance(dip);
509 err = ddi_soft_state_zalloc(iwp_soft_state_p, instance);
510 if (err != DDI_SUCCESS) {
511 cmn_err(CE_WARN, "iwp_attach(): "
512 "failed to allocate soft state\n");
513 goto attach_fail1;
514 }
515
516 sc = ddi_get_soft_state(iwp_soft_state_p, instance);
517 ASSERT(sc != NULL);
518
519 sc->sc_dip = dip;
520
521 /*
522 * map configure space
523 */
524 err = ddi_regs_map_setup(dip, 0, &sc->sc_cfg_base, 0, 0,
525 &iwp_reg_accattr, &sc->sc_cfg_handle);
526 if (err != DDI_SUCCESS) {
527 cmn_err(CE_WARN, "iwp_attach(): "
528 "failed to map config spaces regs\n");
529 goto attach_fail2;
530 }
531
532 sc->sc_dev_id = ddi_get16(sc->sc_cfg_handle,
533 (uint16_t *)(sc->sc_cfg_base + PCI_CONF_DEVID));
534 if ((sc->sc_dev_id != 0x422B) &&
535 (sc->sc_dev_id != 0x422C) &&
536 (sc->sc_dev_id != 0x4238) &&
537 (sc->sc_dev_id != 0x4239) &&
538 (sc->sc_dev_id != 0x008d) &&
539 (sc->sc_dev_id != 0x008e)) {
540 cmn_err(CE_WARN, "iwp_attach(): "
541 "Do not support this device\n");
542 goto attach_fail3;
543 }
544
545 iwp_set_chip_param(sc);
546
547 sc->sc_rev = ddi_get8(sc->sc_cfg_handle,
548 (uint8_t *)(sc->sc_cfg_base + PCI_CONF_REVID));
549
550 /*
551 * keep from disturbing C3 state of CPU
552 */
553 ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base +
554 PCI_CFG_RETRY_TIMEOUT), 0);
555
556 /*
557 * determine the size of buffer for frame and command to ucode
558 */
559 sc->sc_clsz = ddi_get16(sc->sc_cfg_handle,
560 (uint16_t *)(sc->sc_cfg_base + PCI_CONF_CACHE_LINESZ));
561 if (!sc->sc_clsz) {
562 sc->sc_clsz = 16;
563 }
564 sc->sc_clsz = (sc->sc_clsz << 2);
565
566 sc->sc_dmabuf_sz = roundup(0x1000 + sizeof (struct ieee80211_frame) +
567 IEEE80211_MTU + IEEE80211_CRC_LEN +
568 (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
569 IEEE80211_WEP_CRCLEN), sc->sc_clsz);
570
571 /*
572 * Map operating registers
573 */
574 err = ddi_regs_map_setup(dip, 1, &sc->sc_base,
575 0, 0, &iwp_reg_accattr, &sc->sc_handle);
576 if (err != DDI_SUCCESS) {
577 cmn_err(CE_WARN, "iwp_attach(): "
578 "failed to map device regs\n");
579 goto attach_fail3;
580 }
581
582 /*
583 * this is used to differentiate type of hardware
584 */
585 sc->sc_hw_rev = IWP_READ(sc, CSR_HW_REV);
586
587 err = ddi_intr_get_supported_types(dip, &intr_type);
588 if ((err != DDI_SUCCESS) || (!(intr_type & DDI_INTR_TYPE_FIXED))) {
589 cmn_err(CE_WARN, "iwp_attach(): "
590 "fixed type interrupt is not supported\n");
591 goto attach_fail4;
592 }
593
594 err = ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &intr_count);
595 if ((err != DDI_SUCCESS) || (intr_count != 1)) {
596 cmn_err(CE_WARN, "iwp_attach(): "
597 "no fixed interrupts\n");
598 goto attach_fail4;
599 }
600
601 sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP);
602
603 err = ddi_intr_alloc(dip, sc->sc_intr_htable, DDI_INTR_TYPE_FIXED, 0,
604 intr_count, &intr_actual, 0);
605 if ((err != DDI_SUCCESS) || (intr_actual != 1)) {
606 cmn_err(CE_WARN, "iwp_attach(): "
607 "ddi_intr_alloc() failed 0x%x\n", err);
608 goto attach_fail5;
609 }
610
611 err = ddi_intr_get_pri(sc->sc_intr_htable[0], &sc->sc_intr_pri);
612 if (err != DDI_SUCCESS) {
613 cmn_err(CE_WARN, "iwp_attach(): "
614 "ddi_intr_get_pri() failed 0x%x\n", err);
615 goto attach_fail6;
616 }
617
618 mutex_init(&sc->sc_glock, NULL, MUTEX_DRIVER,
619 DDI_INTR_PRI(sc->sc_intr_pri));
620 mutex_init(&sc->sc_tx_lock, NULL, MUTEX_DRIVER,
621 DDI_INTR_PRI(sc->sc_intr_pri));
622 mutex_init(&sc->sc_mt_lock, NULL, MUTEX_DRIVER,
623 DDI_INTR_PRI(sc->sc_intr_pri));
624
625 cv_init(&sc->sc_cmd_cv, NULL, CV_DRIVER, NULL);
626 cv_init(&sc->sc_put_seg_cv, NULL, CV_DRIVER, NULL);
627 cv_init(&sc->sc_ucode_cv, NULL, CV_DRIVER, NULL);
628
629 /*
630 * initialize the mfthread
631 */
632 cv_init(&sc->sc_mt_cv, NULL, CV_DRIVER, NULL);
633 sc->sc_mf_thread = NULL;
634 sc->sc_mf_thread_switch = 0;
635
636 /*
637 * Allocate shared buffer for communication between driver and ucode.
638 */
639 err = iwp_alloc_shared(sc);
640 if (err != DDI_SUCCESS) {
641 cmn_err(CE_WARN, "iwp_attach(): "
642 "failed to allocate shared page\n");
643 goto attach_fail7;
644 }
645
646 (void) memset(sc->sc_shared, 0, sizeof (iwp_shared_t));
647
648 /*
649 * Allocate keep warm page.
650 */
651 err = iwp_alloc_kw(sc);
652 if (err != DDI_SUCCESS) {
653 cmn_err(CE_WARN, "iwp_attach(): "
654 "failed to allocate keep warm page\n");
655 goto attach_fail8;
656 }
657
658 /*
659 * Do some necessary hardware initializations.
660 */
661 err = iwp_preinit(sc);
662 if (err != IWP_SUCCESS) {
663 cmn_err(CE_WARN, "iwp_attach(): "
664 "failed to initialize hardware\n");
665 goto attach_fail9;
666 }
667
668 /*
669 * get hardware configurations from eeprom
670 */
671 err = iwp_eep_load(sc);
672 if (err != IWP_SUCCESS) {
673 cmn_err(CE_WARN, "iwp_attach(): "
674 "failed to load eeprom\n");
675 goto attach_fail9;
676 }
677
678 /*
679 * calibration information from EEPROM
680 */
681 sc->sc_eep_calib = (struct iwp_eep_calibration *)
682 iwp_eep_addr_trans(sc, EEP_CALIBRATION);
683
684 err = iwp_eep_ver_chk(sc);
685 if (err != IWP_SUCCESS) {
686 goto attach_fail9;
687 }
688
689 /*
690 * get MAC address of this chipset
691 */
692 iwp_get_mac_from_eep(sc);
693
694
695 /*
696 * initialize TX and RX ring buffers
697 */
698 err = iwp_ring_init(sc);
699 if (err != DDI_SUCCESS) {
700 cmn_err(CE_WARN, "iwp_attach(): "
701 "failed to allocate and initialize ring\n");
702 goto attach_fail9;
703 }
704
705 sc->sc_hdr = (iwp_firmware_hdr_t *)iwp_fw_bin;
706
707 /*
708 * copy ucode to dma buffer
709 */
710 err = iwp_alloc_fw_dma(sc);
711 if (err != DDI_SUCCESS) {
712 cmn_err(CE_WARN, "iwp_attach(): "
713 "failed to allocate firmware dma\n");
714 goto attach_fail10;
715 }
716
717 /*
718 * Initialize the wifi part, which will be used by
719 * 802.11 module
720 */
721 ic = &sc->sc_ic;
722 ic->ic_phytype = IEEE80211_T_OFDM;
723 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
724 ic->ic_state = IEEE80211_S_INIT;
725 ic->ic_maxrssi = 100; /* experimental number */
726 ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_TXPMGT |
727 IEEE80211_C_PMGT | IEEE80211_C_SHSLOT;
728
729 /*
730 * Support WPA/WPA2
731 */
732 ic->ic_caps |= IEEE80211_C_WPA;
733
734 /*
735 * set supported .11b and .11g rates
736 */
737 ic->ic_sup_rates[IEEE80211_MODE_11B] = iwp_rateset_11b;
738 ic->ic_sup_rates[IEEE80211_MODE_11G] = iwp_rateset_11g;
739
740 /*
741 * set supported .11b and .11g channels (1 through 11)
742 */
743 for (i = 1; i <= 11; i++) {
744 ic->ic_sup_channels[i].ich_freq =
745 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
746 ic->ic_sup_channels[i].ich_flags =
747 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
748 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ |
749 IEEE80211_CHAN_PASSIVE;
750 }
751
752 ic->ic_ibss_chan = &ic->ic_sup_channels[0];
753 ic->ic_xmit = iwp_send;
754
755 /*
756 * attach to 802.11 module
757 */
758 ieee80211_attach(ic);
759
760 /*
761 * different instance has different WPA door
762 */
763 (void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", WPA_DOOR,
764 ddi_driver_name(dip),
765 ddi_get_instance(dip));
766
767 /*
768 * Overwrite 80211 default configurations.
769 */
770 iwp_overwrite_ic_default(sc);
771
772 /*
773 * initialize 802.11 module
774 */
775 ieee80211_media_init(ic);
776
777 /*
778 * initialize default tx key
779 */
780 ic->ic_def_txkey = 0;
781
782 err = ddi_intr_add_softint(dip, &sc->sc_soft_hdl, DDI_INTR_SOFTPRI_MAX,
783 iwp_rx_softintr, (caddr_t)sc);
784 if (err != DDI_SUCCESS) {
785 cmn_err(CE_WARN, "iwp_attach(): "
786 "add soft interrupt failed\n");
787 goto attach_fail12;
788 }
789
790 err = ddi_intr_add_handler(sc->sc_intr_htable[0], iwp_intr,
791 (caddr_t)sc, NULL);
792 if (err != DDI_SUCCESS) {
793 cmn_err(CE_WARN, "iwp_attach(): "
794 "ddi_intr_add_handle() failed\n");
795 goto attach_fail13;
796 }
797
798 err = ddi_intr_enable(sc->sc_intr_htable[0]);
799 if (err != DDI_SUCCESS) {
800 cmn_err(CE_WARN, "iwp_attach(): "
801 "ddi_intr_enable() failed\n");
802 goto attach_fail14;
803 }
804
805 /*
806 * Initialize pointer to device specific functions
807 */
808 wd.wd_secalloc = WIFI_SEC_NONE;
809 wd.wd_opmode = ic->ic_opmode;
810 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_macaddr);
811
812 /*
813 * create relation to GLD
814 */
815 macp = mac_alloc(MAC_VERSION);
816 if (NULL == macp) {
817 cmn_err(CE_WARN, "iwp_attach(): "
818 "failed to do mac_alloc()\n");
819 goto attach_fail15;
820 }
821
822 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
823 macp->m_driver = sc;
824 macp->m_dip = dip;
825 macp->m_src_addr = ic->ic_macaddr;
826 macp->m_callbacks = &iwp_m_callbacks;
827 macp->m_min_sdu = 0;
828 macp->m_max_sdu = IEEE80211_MTU;
829 macp->m_pdata = &wd;
830 macp->m_pdata_size = sizeof (wd);
831
832 /*
833 * Register the macp to mac
834 */
835 err = mac_register(macp, &ic->ic_mach);
836 mac_free(macp);
837 if (err != DDI_SUCCESS) {
838 cmn_err(CE_WARN, "iwp_attach(): "
839 "failed to do mac_register()\n");
840 goto attach_fail15;
841 }
842
843 /*
844 * Create minor node of type DDI_NT_NET_WIFI
845 */
846 (void) snprintf(strbuf, sizeof (strbuf), DRV_NAME_SP"%d", instance);
847 err = ddi_create_minor_node(dip, strbuf, S_IFCHR,
848 instance + 1, DDI_NT_NET_WIFI, 0);
849 if (err != DDI_SUCCESS) {
850 cmn_err(CE_WARN, "iwp_attach(): "
851 "failed to do ddi_create_minor_node()\n");
852 }
853
854 /*
855 * Notify link is down now
856 */
857 mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
858
859 /*
860 * create the mf thread to handle the link status,
861 * recovery fatal error, etc.
862 */
863 sc->sc_mf_thread_switch = 1;
864 if (NULL == sc->sc_mf_thread) {
865 sc->sc_mf_thread = thread_create((caddr_t)NULL, 0,
866 iwp_thread, sc, 0, &p0, TS_RUN, minclsyspri);
867 }
868
869 atomic_or_32(&sc->sc_flags, IWP_F_ATTACHED);
870
871 return (DDI_SUCCESS);
872
873 attach_fail15:
874 (void) ddi_intr_disable(sc->sc_intr_htable[0]);
875 attach_fail14:
876 (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
877 attach_fail13:
878 (void) ddi_intr_remove_softint(sc->sc_soft_hdl);
879 sc->sc_soft_hdl = NULL;
880 attach_fail12:
881 ieee80211_detach(ic);
882 attach_fail11:
883 iwp_free_fw_dma(sc);
884 attach_fail10:
885 iwp_ring_free(sc);
886 attach_fail9:
887 iwp_free_kw(sc);
888 attach_fail8:
889 iwp_free_shared(sc);
890 attach_fail7:
891 iwp_destroy_locks(sc);
892 attach_fail6:
893 (void) ddi_intr_free(sc->sc_intr_htable[0]);
894 attach_fail5:
895 kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
896 attach_fail4:
897 ddi_regs_map_free(&sc->sc_handle);
898 attach_fail3:
899 ddi_regs_map_free(&sc->sc_cfg_handle);
900 attach_fail2:
901 ddi_soft_state_free(iwp_soft_state_p, instance);
902 attach_fail1:
903 return (DDI_FAILURE);
904 }
905
906 int
iwp_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)907 iwp_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
908 {
909 iwp_sc_t *sc;
910 ieee80211com_t *ic;
911 int err;
912
913 sc = ddi_get_soft_state(iwp_soft_state_p, ddi_get_instance(dip));
914 ASSERT(sc != NULL);
915 ic = &sc->sc_ic;
916
917 switch (cmd) {
918 case DDI_DETACH:
919 break;
920 case DDI_SUSPEND:
921 atomic_and_32(&sc->sc_flags, ~IWP_F_HW_ERR_RECOVER);
922 atomic_and_32(&sc->sc_flags, ~IWP_F_RATE_AUTO_CTL);
923
924 atomic_or_32(&sc->sc_flags, IWP_F_SUSPEND);
925
926 if (sc->sc_flags & IWP_F_RUNNING) {
927 iwp_stop(sc);
928 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
929
930 }
931
932 IWP_DBG((IWP_DEBUG_RESUME, "iwp_detach(): "
933 "suspend\n"));
934 return (DDI_SUCCESS);
935 default:
936 return (DDI_FAILURE);
937 }
938
939 if (!(sc->sc_flags & IWP_F_ATTACHED)) {
940 return (DDI_FAILURE);
941 }
942
943 /*
944 * Destroy the mf_thread
945 */
946 sc->sc_mf_thread_switch = 0;
947
948 mutex_enter(&sc->sc_mt_lock);
949 while (sc->sc_mf_thread != NULL) {
950 if (cv_wait_sig(&sc->sc_mt_cv, &sc->sc_mt_lock) == 0) {
951 break;
952 }
953 }
954 mutex_exit(&sc->sc_mt_lock);
955
956 err = mac_disable(sc->sc_ic.ic_mach);
957 if (err != DDI_SUCCESS) {
958 return (err);
959 }
960
961 /*
962 * stop chipset
963 */
964 iwp_stop(sc);
965
966 DELAY(500000);
967
968 /*
969 * release buffer for calibration
970 */
971 iwp_release_calib_buffer(sc);
972
973 /*
974 * Unregiste from GLD
975 */
976 (void) mac_unregister(sc->sc_ic.ic_mach);
977
978 mutex_enter(&sc->sc_glock);
979 iwp_free_fw_dma(sc);
980 iwp_ring_free(sc);
981 iwp_free_kw(sc);
982 iwp_free_shared(sc);
983 mutex_exit(&sc->sc_glock);
984
985 (void) ddi_intr_disable(sc->sc_intr_htable[0]);
986 (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
987 (void) ddi_intr_free(sc->sc_intr_htable[0]);
988 kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
989
990 (void) ddi_intr_remove_softint(sc->sc_soft_hdl);
991 sc->sc_soft_hdl = NULL;
992
993 /*
994 * detach from 80211 module
995 */
996 ieee80211_detach(&sc->sc_ic);
997
998 iwp_destroy_locks(sc);
999
1000 ddi_regs_map_free(&sc->sc_handle);
1001 ddi_regs_map_free(&sc->sc_cfg_handle);
1002 ddi_remove_minor_node(dip, NULL);
1003 ddi_soft_state_free(iwp_soft_state_p, ddi_get_instance(dip));
1004
1005 return (DDI_SUCCESS);
1006 }
1007
1008 /*
1009 * destroy all locks
1010 */
1011 static void
iwp_destroy_locks(iwp_sc_t * sc)1012 iwp_destroy_locks(iwp_sc_t *sc)
1013 {
1014 cv_destroy(&sc->sc_mt_cv);
1015 cv_destroy(&sc->sc_cmd_cv);
1016 cv_destroy(&sc->sc_put_seg_cv);
1017 cv_destroy(&sc->sc_ucode_cv);
1018 mutex_destroy(&sc->sc_mt_lock);
1019 mutex_destroy(&sc->sc_tx_lock);
1020 mutex_destroy(&sc->sc_glock);
1021 }
1022
1023 /*
1024 * Allocate an area of memory and a DMA handle for accessing it
1025 */
1026 static int
iwp_alloc_dma_mem(iwp_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,iwp_dma_t * dma_p)1027 iwp_alloc_dma_mem(iwp_sc_t *sc, size_t memsize,
1028 ddi_dma_attr_t *dma_attr_p, ddi_device_acc_attr_t *acc_attr_p,
1029 uint_t dma_flags, iwp_dma_t *dma_p)
1030 {
1031 caddr_t vaddr;
1032 int err = DDI_FAILURE;
1033
1034 /*
1035 * Allocate handle
1036 */
1037 err = ddi_dma_alloc_handle(sc->sc_dip, dma_attr_p,
1038 DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
1039 if (err != DDI_SUCCESS) {
1040 dma_p->dma_hdl = NULL;
1041 return (DDI_FAILURE);
1042 }
1043
1044 /*
1045 * Allocate memory
1046 */
1047 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p,
1048 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
1049 DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl);
1050 if (err != DDI_SUCCESS) {
1051 ddi_dma_free_handle(&dma_p->dma_hdl);
1052 dma_p->dma_hdl = NULL;
1053 dma_p->acc_hdl = NULL;
1054 return (DDI_FAILURE);
1055 }
1056
1057 /*
1058 * Bind the two together
1059 */
1060 dma_p->mem_va = vaddr;
1061 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
1062 vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL,
1063 &dma_p->cookie, &dma_p->ncookies);
1064 if (err != DDI_DMA_MAPPED) {
1065 ddi_dma_mem_free(&dma_p->acc_hdl);
1066 ddi_dma_free_handle(&dma_p->dma_hdl);
1067 dma_p->acc_hdl = NULL;
1068 dma_p->dma_hdl = NULL;
1069 return (DDI_FAILURE);
1070 }
1071
1072 dma_p->nslots = ~0U;
1073 dma_p->size = ~0U;
1074 dma_p->token = ~0U;
1075 dma_p->offset = 0;
1076 return (DDI_SUCCESS);
1077 }
1078
1079 /*
1080 * Free one allocated area of DMAable memory
1081 */
1082 static void
iwp_free_dma_mem(iwp_dma_t * dma_p)1083 iwp_free_dma_mem(iwp_dma_t *dma_p)
1084 {
1085 if (dma_p->dma_hdl != NULL) {
1086 if (dma_p->ncookies) {
1087 (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
1088 dma_p->ncookies = 0;
1089 }
1090 ddi_dma_free_handle(&dma_p->dma_hdl);
1091 dma_p->dma_hdl = NULL;
1092 }
1093
1094 if (dma_p->acc_hdl != NULL) {
1095 ddi_dma_mem_free(&dma_p->acc_hdl);
1096 dma_p->acc_hdl = NULL;
1097 }
1098 }
1099
1100 /*
1101 * copy ucode into dma buffers
1102 */
1103 static int
iwp_alloc_fw_dma(iwp_sc_t * sc)1104 iwp_alloc_fw_dma(iwp_sc_t *sc)
1105 {
1106 int err = DDI_FAILURE;
1107 iwp_dma_t *dma_p;
1108 char *t;
1109
1110 /*
1111 * firmware image layout:
1112 * |HDR|<-TEXT->|<-DATA->|<-INIT_TEXT->|<-INIT_DATA->|<-BOOT->|
1113 */
1114
1115 /*
1116 * Check firmware image size.
1117 */
1118 if (LE_32(sc->sc_hdr->init_textsz) > RTC_INST_SIZE) {
1119 cmn_err(CE_WARN, "iwp_alloc_fw_dma(): "
1120 "firmware init text size 0x%x is too large\n",
1121 LE_32(sc->sc_hdr->init_textsz));
1122
1123 goto fail;
1124 }
1125
1126 if (LE_32(sc->sc_hdr->init_datasz) > RTC_DATA_SIZE) {
1127 cmn_err(CE_WARN, "iwp_alloc_fw_dma(): "
1128 "firmware init data size 0x%x is too large\n",
1129 LE_32(sc->sc_hdr->init_datasz));
1130
1131 goto fail;
1132 }
1133
1134 if (LE_32(sc->sc_hdr->textsz) > RTC_INST_SIZE) {
1135 cmn_err(CE_WARN, "iwp_alloc_fw_dma(): "
1136 "firmware text size 0x%x is too large\n",
1137 LE_32(sc->sc_hdr->textsz));
1138
1139 goto fail;
1140 }
1141
1142 if (LE_32(sc->sc_hdr->datasz) > RTC_DATA_SIZE) {
1143 cmn_err(CE_WARN, "iwp_alloc_fw_dma(): "
1144 "firmware data size 0x%x is too large\n",
1145 LE_32(sc->sc_hdr->datasz));
1146
1147 goto fail;
1148 }
1149
1150 /*
1151 * copy text of runtime ucode
1152 */
1153 t = (char *)(sc->sc_hdr + 1);
1154 err = iwp_alloc_dma_mem(sc, LE_32(sc->sc_hdr->textsz),
1155 &fw_dma_attr, &iwp_dma_accattr,
1156 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1157 &sc->sc_dma_fw_text);
1158 if (err != DDI_SUCCESS) {
1159 cmn_err(CE_WARN, "iwp_alloc_fw_dma(): "
1160 "failed to allocate text dma memory.\n");
1161 goto fail;
1162 }
1163
1164 dma_p = &sc->sc_dma_fw_text;
1165
1166 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_fw_dma(): "
1167 "text[ncookies:%d addr:%lx size:%lx]\n",
1168 dma_p->ncookies, dma_p->cookie.dmac_address,
1169 dma_p->cookie.dmac_size));
1170
1171 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->textsz));
1172
1173 /*
1174 * copy data and bak-data of runtime ucode
1175 */
1176 t += LE_32(sc->sc_hdr->textsz);
1177 err = iwp_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz),
1178 &fw_dma_attr, &iwp_dma_accattr,
1179 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1180 &sc->sc_dma_fw_data);
1181 if (err != DDI_SUCCESS) {
1182 cmn_err(CE_WARN, "iwp_alloc_fw_dma(): "
1183 "failed to allocate data dma memory\n");
1184 goto fail;
1185 }
1186
1187 dma_p = &sc->sc_dma_fw_data;
1188
1189 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_fw_dma(): "
1190 "data[ncookies:%d addr:%lx size:%lx]\n",
1191 dma_p->ncookies, dma_p->cookie.dmac_address,
1192 dma_p->cookie.dmac_size));
1193
1194 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->datasz));
1195
1196 err = iwp_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz),
1197 &fw_dma_attr, &iwp_dma_accattr,
1198 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1199 &sc->sc_dma_fw_data_bak);
1200 if (err != DDI_SUCCESS) {
1201 cmn_err(CE_WARN, "iwp_alloc_fw_dma(): "
1202 "failed to allocate data bakup dma memory\n");
1203 goto fail;
1204 }
1205
1206 dma_p = &sc->sc_dma_fw_data_bak;
1207
1208 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_fw_dma(): "
1209 "data_bak[ncookies:%d addr:%lx "
1210 "size:%lx]\n",
1211 dma_p->ncookies, dma_p->cookie.dmac_address,
1212 dma_p->cookie.dmac_size));
1213
1214 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->datasz));
1215
1216 /*
1217 * copy text of init ucode
1218 */
1219 t += LE_32(sc->sc_hdr->datasz);
1220 err = iwp_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_textsz),
1221 &fw_dma_attr, &iwp_dma_accattr,
1222 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1223 &sc->sc_dma_fw_init_text);
1224 if (err != DDI_SUCCESS) {
1225 cmn_err(CE_WARN, "iwp_alloc_fw_dma(): "
1226 "failed to allocate init text dma memory\n");
1227 goto fail;
1228 }
1229
1230 dma_p = &sc->sc_dma_fw_init_text;
1231
1232 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_fw_dma(): "
1233 "init_text[ncookies:%d addr:%lx "
1234 "size:%lx]\n",
1235 dma_p->ncookies, dma_p->cookie.dmac_address,
1236 dma_p->cookie.dmac_size));
1237
1238 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->init_textsz));
1239
1240 /*
1241 * copy data of init ucode
1242 */
1243 t += LE_32(sc->sc_hdr->init_textsz);
1244 err = iwp_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_datasz),
1245 &fw_dma_attr, &iwp_dma_accattr,
1246 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1247 &sc->sc_dma_fw_init_data);
1248 if (err != DDI_SUCCESS) {
1249 cmn_err(CE_WARN, "iwp_alloc_fw_dma(): "
1250 "failed to allocate init data dma memory\n");
1251 goto fail;
1252 }
1253
1254 dma_p = &sc->sc_dma_fw_init_data;
1255
1256 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_fw_dma(): "
1257 "init_data[ncookies:%d addr:%lx "
1258 "size:%lx]\n",
1259 dma_p->ncookies, dma_p->cookie.dmac_address,
1260 dma_p->cookie.dmac_size));
1261
1262 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->init_datasz));
1263
1264 sc->sc_boot = t + LE_32(sc->sc_hdr->init_datasz);
1265 fail:
1266 return (err);
1267 }
1268
1269 static void
iwp_free_fw_dma(iwp_sc_t * sc)1270 iwp_free_fw_dma(iwp_sc_t *sc)
1271 {
1272 iwp_free_dma_mem(&sc->sc_dma_fw_text);
1273 iwp_free_dma_mem(&sc->sc_dma_fw_data);
1274 iwp_free_dma_mem(&sc->sc_dma_fw_data_bak);
1275 iwp_free_dma_mem(&sc->sc_dma_fw_init_text);
1276 iwp_free_dma_mem(&sc->sc_dma_fw_init_data);
1277 }
1278
1279 /*
1280 * Allocate a shared buffer between host and NIC.
1281 */
1282 static int
iwp_alloc_shared(iwp_sc_t * sc)1283 iwp_alloc_shared(iwp_sc_t *sc)
1284 {
1285 #ifdef DEBUG
1286 iwp_dma_t *dma_p;
1287 #endif
1288 int err = DDI_FAILURE;
1289
1290 /*
1291 * must be aligned on a 4K-page boundary
1292 */
1293 err = iwp_alloc_dma_mem(sc, sizeof (iwp_shared_t),
1294 &sh_dma_attr, &iwp_dma_descattr,
1295 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1296 &sc->sc_dma_sh);
1297 if (err != DDI_SUCCESS) {
1298 goto fail;
1299 }
1300
1301 sc->sc_shared = (iwp_shared_t *)sc->sc_dma_sh.mem_va;
1302
1303 #ifdef DEBUG
1304 dma_p = &sc->sc_dma_sh;
1305 #endif
1306 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_shared(): "
1307 "sh[ncookies:%d addr:%lx size:%lx]\n",
1308 dma_p->ncookies, dma_p->cookie.dmac_address,
1309 dma_p->cookie.dmac_size));
1310
1311 return (err);
1312 fail:
1313 iwp_free_shared(sc);
1314 return (err);
1315 }
1316
1317 static void
iwp_free_shared(iwp_sc_t * sc)1318 iwp_free_shared(iwp_sc_t *sc)
1319 {
1320 iwp_free_dma_mem(&sc->sc_dma_sh);
1321 }
1322
1323 /*
1324 * Allocate a keep warm page.
1325 */
1326 static int
iwp_alloc_kw(iwp_sc_t * sc)1327 iwp_alloc_kw(iwp_sc_t *sc)
1328 {
1329 #ifdef DEBUG
1330 iwp_dma_t *dma_p;
1331 #endif
1332 int err = DDI_FAILURE;
1333
1334 /*
1335 * must be aligned on a 4K-page boundary
1336 */
1337 err = iwp_alloc_dma_mem(sc, IWP_KW_SIZE,
1338 &kw_dma_attr, &iwp_dma_descattr,
1339 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1340 &sc->sc_dma_kw);
1341 if (err != DDI_SUCCESS) {
1342 goto fail;
1343 }
1344
1345 #ifdef DEBUG
1346 dma_p = &sc->sc_dma_kw;
1347 #endif
1348 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_kw(): "
1349 "kw[ncookies:%d addr:%lx size:%lx]\n",
1350 dma_p->ncookies, dma_p->cookie.dmac_address,
1351 dma_p->cookie.dmac_size));
1352
1353 return (err);
1354 fail:
1355 iwp_free_kw(sc);
1356 return (err);
1357 }
1358
1359 static void
iwp_free_kw(iwp_sc_t * sc)1360 iwp_free_kw(iwp_sc_t *sc)
1361 {
1362 iwp_free_dma_mem(&sc->sc_dma_kw);
1363 }
1364
1365 /*
1366 * initialize RX ring buffers
1367 */
1368 static int
iwp_alloc_rx_ring(iwp_sc_t * sc)1369 iwp_alloc_rx_ring(iwp_sc_t *sc)
1370 {
1371 iwp_rx_ring_t *ring;
1372 iwp_rx_data_t *data;
1373 #ifdef DEBUG
1374 iwp_dma_t *dma_p;
1375 #endif
1376 int i, err = DDI_FAILURE;
1377
1378 ring = &sc->sc_rxq;
1379 ring->cur = 0;
1380
1381 /*
1382 * allocate RX description ring buffer
1383 */
1384 err = iwp_alloc_dma_mem(sc, RX_QUEUE_SIZE * sizeof (uint32_t),
1385 &ring_desc_dma_attr, &iwp_dma_descattr,
1386 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1387 &ring->dma_desc);
1388 if (err != DDI_SUCCESS) {
1389 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_rx_ring(): "
1390 "dma alloc rx ring desc "
1391 "failed\n"));
1392 goto fail;
1393 }
1394
1395 ring->desc = (uint32_t *)ring->dma_desc.mem_va;
1396 #ifdef DEBUG
1397 dma_p = &ring->dma_desc;
1398 #endif
1399 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_rx_ring(): "
1400 "rx bd[ncookies:%d addr:%lx size:%lx]\n",
1401 dma_p->ncookies, dma_p->cookie.dmac_address,
1402 dma_p->cookie.dmac_size));
1403
1404 /*
1405 * Allocate Rx frame buffers.
1406 */
1407 for (i = 0; i < RX_QUEUE_SIZE; i++) {
1408 data = &ring->data[i];
1409 err = iwp_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
1410 &rx_buffer_dma_attr, &iwp_dma_accattr,
1411 DDI_DMA_READ | DDI_DMA_STREAMING,
1412 &data->dma_data);
1413 if (err != DDI_SUCCESS) {
1414 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_rx_ring(): "
1415 "dma alloc rx ring "
1416 "buf[%d] failed\n", i));
1417 goto fail;
1418 }
1419 /*
1420 * the physical address bit [8-36] are used,
1421 * instead of bit [0-31] in 3945.
1422 */
1423 ring->desc[i] = (uint32_t)
1424 (data->dma_data.cookie.dmac_address >> 8);
1425 }
1426
1427 #ifdef DEBUG
1428 dma_p = &ring->data[0].dma_data;
1429 #endif
1430 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_rx_ring(): "
1431 "rx buffer[0][ncookies:%d addr:%lx "
1432 "size:%lx]\n",
1433 dma_p->ncookies, dma_p->cookie.dmac_address,
1434 dma_p->cookie.dmac_size));
1435
1436 IWP_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
1437
1438 return (err);
1439
1440 fail:
1441 iwp_free_rx_ring(sc);
1442 return (err);
1443 }
1444
1445 /*
1446 * disable RX ring
1447 */
1448 static void
iwp_reset_rx_ring(iwp_sc_t * sc)1449 iwp_reset_rx_ring(iwp_sc_t *sc)
1450 {
1451 int n;
1452
1453 iwp_mac_access_enter(sc);
1454 IWP_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
1455 for (n = 0; n < 2000; n++) {
1456 if (IWP_READ(sc, FH_MEM_RSSR_RX_STATUS_REG) & (1 << 24)) {
1457 break;
1458 }
1459 DELAY(1000);
1460 }
1461 #ifdef DEBUG
1462 if (2000 == n) {
1463 IWP_DBG((IWP_DEBUG_DMA, "iwp_reset_rx_ring(): "
1464 "timeout resetting Rx ring\n"));
1465 }
1466 #endif
1467 iwp_mac_access_exit(sc);
1468
1469 sc->sc_rxq.cur = 0;
1470 }
1471
1472 static void
iwp_free_rx_ring(iwp_sc_t * sc)1473 iwp_free_rx_ring(iwp_sc_t *sc)
1474 {
1475 int i;
1476
1477 for (i = 0; i < RX_QUEUE_SIZE; i++) {
1478 if (sc->sc_rxq.data[i].dma_data.dma_hdl) {
1479 IWP_DMA_SYNC(sc->sc_rxq.data[i].dma_data,
1480 DDI_DMA_SYNC_FORCPU);
1481 }
1482
1483 iwp_free_dma_mem(&sc->sc_rxq.data[i].dma_data);
1484 }
1485
1486 if (sc->sc_rxq.dma_desc.dma_hdl) {
1487 IWP_DMA_SYNC(sc->sc_rxq.dma_desc, DDI_DMA_SYNC_FORDEV);
1488 }
1489
1490 iwp_free_dma_mem(&sc->sc_rxq.dma_desc);
1491 }
1492
1493 /*
1494 * initialize TX ring buffers
1495 */
1496 static int
iwp_alloc_tx_ring(iwp_sc_t * sc,iwp_tx_ring_t * ring,int slots,int qid)1497 iwp_alloc_tx_ring(iwp_sc_t *sc, iwp_tx_ring_t *ring,
1498 int slots, int qid)
1499 {
1500 iwp_tx_data_t *data;
1501 iwp_tx_desc_t *desc_h;
1502 uint32_t paddr_desc_h;
1503 iwp_cmd_t *cmd_h;
1504 uint32_t paddr_cmd_h;
1505 #ifdef DEBUG
1506 iwp_dma_t *dma_p;
1507 #endif
1508 int i, err = DDI_FAILURE;
1509 ring->qid = qid;
1510 ring->count = TFD_QUEUE_SIZE_MAX;
1511 ring->window = slots;
1512 ring->queued = 0;
1513 ring->cur = 0;
1514 ring->desc_cur = 0;
1515
1516 /*
1517 * allocate buffer for TX descriptor ring
1518 */
1519 err = iwp_alloc_dma_mem(sc,
1520 TFD_QUEUE_SIZE_MAX * sizeof (iwp_tx_desc_t),
1521 &ring_desc_dma_attr, &iwp_dma_descattr,
1522 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1523 &ring->dma_desc);
1524 if (err != DDI_SUCCESS) {
1525 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_tx_ring(): "
1526 "dma alloc tx ring desc[%d] "
1527 "failed\n", qid));
1528 goto fail;
1529 }
1530
1531 #ifdef DEBUG
1532 dma_p = &ring->dma_desc;
1533 #endif
1534 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_tx_ring(): "
1535 "tx bd[ncookies:%d addr:%lx size:%lx]\n",
1536 dma_p->ncookies, dma_p->cookie.dmac_address,
1537 dma_p->cookie.dmac_size));
1538
1539 desc_h = (iwp_tx_desc_t *)ring->dma_desc.mem_va;
1540 paddr_desc_h = ring->dma_desc.cookie.dmac_address;
1541
1542 /*
1543 * allocate buffer for ucode command
1544 */
1545 err = iwp_alloc_dma_mem(sc,
1546 TFD_QUEUE_SIZE_MAX * sizeof (iwp_cmd_t),
1547 &cmd_dma_attr, &iwp_dma_accattr,
1548 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1549 &ring->dma_cmd);
1550 if (err != DDI_SUCCESS) {
1551 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_tx_ring(): "
1552 "dma alloc tx ring cmd[%d]"
1553 " failed\n", qid));
1554 goto fail;
1555 }
1556
1557 #ifdef DEBUG
1558 dma_p = &ring->dma_cmd;
1559 #endif
1560 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_tx_ring(): "
1561 "tx cmd[ncookies:%d addr:%lx size:%lx]\n",
1562 dma_p->ncookies, dma_p->cookie.dmac_address,
1563 dma_p->cookie.dmac_size));
1564
1565 cmd_h = (iwp_cmd_t *)ring->dma_cmd.mem_va;
1566 paddr_cmd_h = ring->dma_cmd.cookie.dmac_address;
1567
1568 /*
1569 * Allocate Tx frame buffers.
1570 */
1571 ring->data = kmem_zalloc(sizeof (iwp_tx_data_t) * TFD_QUEUE_SIZE_MAX,
1572 KM_NOSLEEP);
1573 if (NULL == ring->data) {
1574 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_tx_ring(): "
1575 "could not allocate "
1576 "tx data slots\n"));
1577 goto fail;
1578 }
1579
1580 for (i = 0; i < TFD_QUEUE_SIZE_MAX; i++) {
1581 data = &ring->data[i];
1582 err = iwp_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
1583 &tx_buffer_dma_attr, &iwp_dma_accattr,
1584 DDI_DMA_WRITE | DDI_DMA_STREAMING,
1585 &data->dma_data);
1586 if (err != DDI_SUCCESS) {
1587 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_tx_ring(): "
1588 "dma alloc tx "
1589 "ring buf[%d] failed\n", i));
1590 goto fail;
1591 }
1592
1593 data->desc = desc_h + i;
1594 data->paddr_desc = paddr_desc_h +
1595 _PTRDIFF(data->desc, desc_h);
1596 data->cmd = cmd_h + i;
1597 data->paddr_cmd = paddr_cmd_h +
1598 _PTRDIFF(data->cmd, cmd_h);
1599 }
1600 #ifdef DEBUG
1601 dma_p = &ring->data[0].dma_data;
1602 #endif
1603 IWP_DBG((IWP_DEBUG_DMA, "iwp_alloc_tx_ring(): "
1604 "tx buffer[0][ncookies:%d addr:%lx "
1605 "size:%lx]\n",
1606 dma_p->ncookies, dma_p->cookie.dmac_address,
1607 dma_p->cookie.dmac_size));
1608
1609 return (err);
1610
1611 fail:
1612 iwp_free_tx_ring(ring);
1613
1614 return (err);
1615 }
1616
1617 /*
1618 * disable TX ring
1619 */
1620 static void
iwp_reset_tx_ring(iwp_sc_t * sc,iwp_tx_ring_t * ring)1621 iwp_reset_tx_ring(iwp_sc_t *sc, iwp_tx_ring_t *ring)
1622 {
1623 iwp_tx_data_t *data;
1624 int i, n;
1625
1626 iwp_mac_access_enter(sc);
1627
1628 IWP_WRITE(sc, IWP_FH_TCSR_CHNL_TX_CONFIG_REG(ring->qid), 0);
1629 for (n = 0; n < 200; n++) {
1630 if (IWP_READ(sc, IWP_FH_TSSR_TX_STATUS_REG) &
1631 IWP_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ring->qid)) {
1632 break;
1633 }
1634 DELAY(10);
1635 }
1636
1637 #ifdef DEBUG
1638 if (200 == n) {
1639 IWP_DBG((IWP_DEBUG_DMA, "iwp_reset_tx_ring(): "
1640 "timeout reset tx ring %d\n",
1641 ring->qid));
1642 }
1643 #endif
1644
1645 iwp_mac_access_exit(sc);
1646
1647 /* by pass, if it's quiesce */
1648 if (!(sc->sc_flags & IWP_F_QUIESCED)) {
1649 for (i = 0; i < ring->count; i++) {
1650 data = &ring->data[i];
1651 IWP_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
1652 }
1653 }
1654
1655 ring->queued = 0;
1656 ring->cur = 0;
1657 ring->desc_cur = 0;
1658 }
1659
1660 static void
iwp_free_tx_ring(iwp_tx_ring_t * ring)1661 iwp_free_tx_ring(iwp_tx_ring_t *ring)
1662 {
1663 int i;
1664
1665 if (ring->dma_desc.dma_hdl != NULL) {
1666 IWP_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
1667 }
1668 iwp_free_dma_mem(&ring->dma_desc);
1669
1670 if (ring->dma_cmd.dma_hdl != NULL) {
1671 IWP_DMA_SYNC(ring->dma_cmd, DDI_DMA_SYNC_FORDEV);
1672 }
1673 iwp_free_dma_mem(&ring->dma_cmd);
1674
1675 if (ring->data != NULL) {
1676 for (i = 0; i < ring->count; i++) {
1677 if (ring->data[i].dma_data.dma_hdl) {
1678 IWP_DMA_SYNC(ring->data[i].dma_data,
1679 DDI_DMA_SYNC_FORDEV);
1680 }
1681 iwp_free_dma_mem(&ring->data[i].dma_data);
1682 }
1683 kmem_free(ring->data, ring->count * sizeof (iwp_tx_data_t));
1684 }
1685 }
1686
1687 /*
1688 * initialize TX and RX ring
1689 */
1690 static int
iwp_ring_init(iwp_sc_t * sc)1691 iwp_ring_init(iwp_sc_t *sc)
1692 {
1693 int i, err = DDI_FAILURE;
1694
1695 for (i = 0; i < IWP_NUM_QUEUES; i++) {
1696 if (IWP_CMD_QUEUE_NUM == i) {
1697 continue;
1698 }
1699
1700 err = iwp_alloc_tx_ring(sc, &sc->sc_txq[i], TFD_TX_CMD_SLOTS,
1701 i);
1702 if (err != DDI_SUCCESS) {
1703 goto fail;
1704 }
1705 }
1706
1707 /*
1708 * initialize command queue
1709 */
1710 err = iwp_alloc_tx_ring(sc, &sc->sc_txq[IWP_CMD_QUEUE_NUM],
1711 TFD_CMD_SLOTS, IWP_CMD_QUEUE_NUM);
1712 if (err != DDI_SUCCESS) {
1713 goto fail;
1714 }
1715
1716 err = iwp_alloc_rx_ring(sc);
1717 if (err != DDI_SUCCESS) {
1718 goto fail;
1719 }
1720
1721 fail:
1722 return (err);
1723 }
1724
1725 static void
iwp_ring_free(iwp_sc_t * sc)1726 iwp_ring_free(iwp_sc_t *sc)
1727 {
1728 int i = IWP_NUM_QUEUES;
1729
1730 iwp_free_rx_ring(sc);
1731 while (--i >= 0) {
1732 iwp_free_tx_ring(&sc->sc_txq[i]);
1733 }
1734 }
1735
1736 /* ARGSUSED */
1737 static ieee80211_node_t *
iwp_node_alloc(ieee80211com_t * ic)1738 iwp_node_alloc(ieee80211com_t *ic)
1739 {
1740 iwp_amrr_t *amrr;
1741
1742 amrr = kmem_zalloc(sizeof (iwp_amrr_t), KM_SLEEP);
1743 if (NULL == amrr) {
1744 cmn_err(CE_WARN, "iwp_node_alloc(): "
1745 "failed to allocate memory for amrr structure\n");
1746 return (NULL);
1747 }
1748
1749 iwp_amrr_init(amrr);
1750
1751 return (&amrr->in);
1752 }
1753
1754 static void
iwp_node_free(ieee80211_node_t * in)1755 iwp_node_free(ieee80211_node_t *in)
1756 {
1757 ieee80211com_t *ic;
1758
1759 if ((NULL == in) ||
1760 (NULL == in->in_ic)) {
1761 cmn_err(CE_WARN, "iwp_node_free() "
1762 "Got a NULL point from Net80211 module\n");
1763 return;
1764 }
1765 ic = in->in_ic;
1766
1767 if (ic->ic_node_cleanup != NULL) {
1768 ic->ic_node_cleanup(in);
1769 }
1770
1771 if (in->in_wpa_ie != NULL) {
1772 ieee80211_free(in->in_wpa_ie);
1773 }
1774
1775 if (in->in_wme_ie != NULL) {
1776 ieee80211_free(in->in_wme_ie);
1777 }
1778
1779 if (in->in_htcap_ie != NULL) {
1780 ieee80211_free(in->in_htcap_ie);
1781 }
1782
1783 kmem_free(in, sizeof (iwp_amrr_t));
1784 }
1785
1786
1787 /*
1788 * change station's state. this function will be invoked by 80211 module
1789 * when need to change staton's state.
1790 */
1791 static int
iwp_newstate(ieee80211com_t * ic,enum ieee80211_state nstate,int arg)1792 iwp_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
1793 {
1794 iwp_sc_t *sc;
1795 ieee80211_node_t *in;
1796 enum ieee80211_state ostate;
1797 iwp_add_sta_t node;
1798 int i, err = IWP_FAIL;
1799
1800 if (NULL == ic) {
1801 return (err);
1802 }
1803 sc = (iwp_sc_t *)ic;
1804 in = ic->ic_bss;
1805 ostate = ic->ic_state;
1806
1807 mutex_enter(&sc->sc_glock);
1808
1809 switch (nstate) {
1810 case IEEE80211_S_SCAN:
1811 switch (ostate) {
1812 case IEEE80211_S_INIT:
1813 atomic_or_32(&sc->sc_flags, IWP_F_SCANNING);
1814 iwp_set_led(sc, 2, 10, 2);
1815
1816 /*
1817 * clear association to receive beacons from
1818 * all BSS'es
1819 */
1820 sc->sc_config.assoc_id = 0;
1821 sc->sc_config.filter_flags &=
1822 ~LE_32(RXON_FILTER_ASSOC_MSK);
1823
1824 IWP_DBG((IWP_DEBUG_80211, "iwp_newstate(): "
1825 "config chan %d "
1826 "flags %x filter_flags %x\n",
1827 LE_16(sc->sc_config.chan),
1828 LE_32(sc->sc_config.flags),
1829 LE_32(sc->sc_config.filter_flags)));
1830
1831 err = iwp_cmd(sc, REPLY_RXON, &sc->sc_config,
1832 sizeof (iwp_rxon_cmd_t), 1);
1833 if (err != IWP_SUCCESS) {
1834 cmn_err(CE_WARN, "iwp_newstate(): "
1835 "could not clear association\n");
1836 atomic_and_32(&sc->sc_flags, ~IWP_F_SCANNING);
1837 mutex_exit(&sc->sc_glock);
1838 return (err);
1839 }
1840
1841 /* add broadcast node to send probe request */
1842 (void) memset(&node, 0, sizeof (node));
1843 (void) memset(&node.sta.addr, 0xff, IEEE80211_ADDR_LEN);
1844 node.sta.sta_id = IWP_BROADCAST_ID;
1845 err = iwp_cmd(sc, REPLY_ADD_STA, &node,
1846 sizeof (node), 1);
1847 if (err != IWP_SUCCESS) {
1848 cmn_err(CE_WARN, "iwp_newstate(): "
1849 "could not add broadcast node\n");
1850 atomic_and_32(&sc->sc_flags, ~IWP_F_SCANNING);
1851 mutex_exit(&sc->sc_glock);
1852 return (err);
1853 }
1854 break;
1855 case IEEE80211_S_SCAN:
1856 mutex_exit(&sc->sc_glock);
1857 /* step to next channel before actual FW scan */
1858 err = sc->sc_newstate(ic, nstate, arg);
1859 mutex_enter(&sc->sc_glock);
1860 if ((err != 0) || ((err = iwp_scan(sc)) != 0)) {
1861 cmn_err(CE_WARN, "iwp_newstate(): "
1862 "could not initiate scan\n");
1863 atomic_and_32(&sc->sc_flags, ~IWP_F_SCANNING);
1864 ieee80211_cancel_scan(ic);
1865 }
1866 mutex_exit(&sc->sc_glock);
1867 return (err);
1868 default:
1869 break;
1870 }
1871 sc->sc_clk = 0;
1872 break;
1873
1874 case IEEE80211_S_AUTH:
1875 if (ostate == IEEE80211_S_SCAN) {
1876 atomic_and_32(&sc->sc_flags, ~IWP_F_SCANNING);
1877 }
1878
1879 /*
1880 * reset state to handle reassociations correctly
1881 */
1882 sc->sc_config.assoc_id = 0;
1883 sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_ASSOC_MSK);
1884
1885 /*
1886 * before sending authentication and association request frame,
1887 * we need do something in the hardware, such as setting the
1888 * channel same to the target AP...
1889 */
1890 if ((err = iwp_hw_set_before_auth(sc)) != 0) {
1891 IWP_DBG((IWP_DEBUG_80211, "iwp_newstate(): "
1892 "could not send authentication request\n"));
1893 mutex_exit(&sc->sc_glock);
1894 return (err);
1895 }
1896 break;
1897
1898 case IEEE80211_S_RUN:
1899 if (ostate == IEEE80211_S_SCAN) {
1900 atomic_and_32(&sc->sc_flags, ~IWP_F_SCANNING);
1901 }
1902
1903 if (IEEE80211_M_MONITOR == ic->ic_opmode) {
1904 /* let LED blink when monitoring */
1905 iwp_set_led(sc, 2, 10, 10);
1906 break;
1907 }
1908
1909 IWP_DBG((IWP_DEBUG_80211, "iwp_newstate(): "
1910 "associated.\n"));
1911
1912 err = iwp_run_state_config(sc);
1913 if (err != IWP_SUCCESS) {
1914 cmn_err(CE_WARN, "iwp_newstate(): "
1915 "failed to set up association\n");
1916 mutex_exit(&sc->sc_glock);
1917 return (err);
1918 }
1919
1920 /*
1921 * start automatic rate control
1922 */
1923 if (IEEE80211_FIXED_RATE_NONE == ic->ic_fixed_rate) {
1924 atomic_or_32(&sc->sc_flags, IWP_F_RATE_AUTO_CTL);
1925
1926 /*
1927 * set rate to some reasonable initial value
1928 */
1929 i = in->in_rates.ir_nrates - 1;
1930 while (i > 0 && IEEE80211_RATE(i) > 72) {
1931 i--;
1932 }
1933 in->in_txrate = i;
1934
1935 } else {
1936 atomic_and_32(&sc->sc_flags, ~IWP_F_RATE_AUTO_CTL);
1937 }
1938
1939 /*
1940 * set LED on after associated
1941 */
1942 iwp_set_led(sc, 2, 0, 1);
1943 break;
1944
1945 case IEEE80211_S_INIT:
1946 if (ostate == IEEE80211_S_SCAN) {
1947 atomic_and_32(&sc->sc_flags, ~IWP_F_SCANNING);
1948 }
1949 /*
1950 * set LED off after init
1951 */
1952 iwp_set_led(sc, 2, 1, 0);
1953 break;
1954
1955 case IEEE80211_S_ASSOC:
1956 if (ostate == IEEE80211_S_SCAN) {
1957 atomic_and_32(&sc->sc_flags, ~IWP_F_SCANNING);
1958 }
1959 break;
1960 }
1961
1962 mutex_exit(&sc->sc_glock);
1963
1964 return (sc->sc_newstate(ic, nstate, arg));
1965 }
1966
1967 /*
1968 * exclusive access to mac begin.
1969 */
1970 static void
iwp_mac_access_enter(iwp_sc_t * sc)1971 iwp_mac_access_enter(iwp_sc_t *sc)
1972 {
1973 uint32_t tmp;
1974 int n;
1975
1976 tmp = IWP_READ(sc, CSR_GP_CNTRL);
1977 IWP_WRITE(sc, CSR_GP_CNTRL,
1978 tmp | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1979
1980 /* wait until we succeed */
1981 for (n = 0; n < 1000; n++) {
1982 if ((IWP_READ(sc, CSR_GP_CNTRL) &
1983 (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
1984 CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP)) ==
1985 CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN) {
1986 break;
1987 }
1988 DELAY(10);
1989 }
1990
1991 #ifdef DEBUG
1992 if (1000 == n) {
1993 IWP_DBG((IWP_DEBUG_PIO, "iwp_mac_access_enter(): "
1994 "could not lock memory\n"));
1995 }
1996 #endif
1997 }
1998
1999 /*
2000 * exclusive access to mac end.
2001 */
2002 static void
iwp_mac_access_exit(iwp_sc_t * sc)2003 iwp_mac_access_exit(iwp_sc_t *sc)
2004 {
2005 uint32_t tmp = IWP_READ(sc, CSR_GP_CNTRL);
2006 IWP_WRITE(sc, CSR_GP_CNTRL,
2007 tmp & ~CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
2008 }
2009
2010 /*
2011 * this function defined here for future use.
2012 * static uint32_t
2013 * iwp_mem_read(iwp_sc_t *sc, uint32_t addr)
2014 * {
2015 * IWP_WRITE(sc, HBUS_TARG_MEM_RADDR, addr);
2016 * return (IWP_READ(sc, HBUS_TARG_MEM_RDAT));
2017 * }
2018 */
2019
2020 /*
2021 * write mac memory
2022 */
2023 static void
iwp_mem_write(iwp_sc_t * sc,uint32_t addr,uint32_t data)2024 iwp_mem_write(iwp_sc_t *sc, uint32_t addr, uint32_t data)
2025 {
2026 IWP_WRITE(sc, HBUS_TARG_MEM_WADDR, addr);
2027 IWP_WRITE(sc, HBUS_TARG_MEM_WDAT, data);
2028 }
2029
2030 /*
2031 * read mac register
2032 */
2033 static uint32_t
iwp_reg_read(iwp_sc_t * sc,uint32_t addr)2034 iwp_reg_read(iwp_sc_t *sc, uint32_t addr)
2035 {
2036 IWP_WRITE(sc, HBUS_TARG_PRPH_RADDR, addr | (3 << 24));
2037 return (IWP_READ(sc, HBUS_TARG_PRPH_RDAT));
2038 }
2039
2040 /*
2041 * write mac register
2042 */
2043 static void
iwp_reg_write(iwp_sc_t * sc,uint32_t addr,uint32_t data)2044 iwp_reg_write(iwp_sc_t *sc, uint32_t addr, uint32_t data)
2045 {
2046 IWP_WRITE(sc, HBUS_TARG_PRPH_WADDR, addr | (3 << 24));
2047 IWP_WRITE(sc, HBUS_TARG_PRPH_WDAT, data);
2048 }
2049
2050
2051 /*
2052 * steps of loading ucode:
2053 * load init ucode=>init alive=>calibrate=>
2054 * receive calibration result=>reinitialize NIC=>
2055 * load runtime ucode=>runtime alive=>
2056 * send calibration result=>running.
2057 */
2058 static int
iwp_load_init_firmware(iwp_sc_t * sc)2059 iwp_load_init_firmware(iwp_sc_t *sc)
2060 {
2061 int err = IWP_FAIL;
2062 clock_t clk;
2063
2064 atomic_and_32(&sc->sc_flags, ~IWP_F_PUT_SEG);
2065
2066 /*
2067 * load init_text section of uCode to hardware
2068 */
2069 err = iwp_put_seg_fw(sc, sc->sc_dma_fw_init_text.cookie.dmac_address,
2070 RTC_INST_LOWER_BOUND, sc->sc_dma_fw_init_text.cookie.dmac_size);
2071 if (err != IWP_SUCCESS) {
2072 cmn_err(CE_WARN, "iwp_load_init_firmware(): "
2073 "failed to write init uCode.\n");
2074 return (err);
2075 }
2076
2077 clk = ddi_get_lbolt() + drv_usectohz(1000000);
2078
2079 /* wait loading init_text until completed or timeout */
2080 while (!(sc->sc_flags & IWP_F_PUT_SEG)) {
2081 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) {
2082 break;
2083 }
2084 }
2085
2086 if (!(sc->sc_flags & IWP_F_PUT_SEG)) {
2087 cmn_err(CE_WARN, "iwp_load_init_firmware(): "
2088 "timeout waiting for init uCode load.\n");
2089 return (IWP_FAIL);
2090 }
2091
2092 atomic_and_32(&sc->sc_flags, ~IWP_F_PUT_SEG);
2093
2094 /*
2095 * load init_data section of uCode to hardware
2096 */
2097 err = iwp_put_seg_fw(sc, sc->sc_dma_fw_init_data.cookie.dmac_address,
2098 RTC_DATA_LOWER_BOUND, sc->sc_dma_fw_init_data.cookie.dmac_size);
2099 if (err != IWP_SUCCESS) {
2100 cmn_err(CE_WARN, "iwp_load_init_firmware(): "
2101 "failed to write init_data uCode.\n");
2102 return (err);
2103 }
2104
2105 clk = ddi_get_lbolt() + drv_usectohz(1000000);
2106
2107 /*
2108 * wait loading init_data until completed or timeout
2109 */
2110 while (!(sc->sc_flags & IWP_F_PUT_SEG)) {
2111 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) {
2112 break;
2113 }
2114 }
2115
2116 if (!(sc->sc_flags & IWP_F_PUT_SEG)) {
2117 cmn_err(CE_WARN, "iwp_load_init_firmware(): "
2118 "timeout waiting for init_data uCode load.\n");
2119 return (IWP_FAIL);
2120 }
2121
2122 atomic_and_32(&sc->sc_flags, ~IWP_F_PUT_SEG);
2123
2124 return (err);
2125 }
2126
2127 static int
iwp_load_run_firmware(iwp_sc_t * sc)2128 iwp_load_run_firmware(iwp_sc_t *sc)
2129 {
2130 int err = IWP_FAIL;
2131 clock_t clk;
2132
2133 atomic_and_32(&sc->sc_flags, ~IWP_F_PUT_SEG);
2134
2135 /*
2136 * load init_text section of uCode to hardware
2137 */
2138 err = iwp_put_seg_fw(sc, sc->sc_dma_fw_text.cookie.dmac_address,
2139 RTC_INST_LOWER_BOUND, sc->sc_dma_fw_text.cookie.dmac_size);
2140 if (err != IWP_SUCCESS) {
2141 cmn_err(CE_WARN, "iwp_load_run_firmware(): "
2142 "failed to write run uCode.\n");
2143 return (err);
2144 }
2145
2146 clk = ddi_get_lbolt() + drv_usectohz(1000000);
2147
2148 /* wait loading run_text until completed or timeout */
2149 while (!(sc->sc_flags & IWP_F_PUT_SEG)) {
2150 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) {
2151 break;
2152 }
2153 }
2154
2155 if (!(sc->sc_flags & IWP_F_PUT_SEG)) {
2156 cmn_err(CE_WARN, "iwp_load_run_firmware(): "
2157 "timeout waiting for run uCode load.\n");
2158 return (IWP_FAIL);
2159 }
2160
2161 atomic_and_32(&sc->sc_flags, ~IWP_F_PUT_SEG);
2162
2163 /*
2164 * load run_data section of uCode to hardware
2165 */
2166 err = iwp_put_seg_fw(sc, sc->sc_dma_fw_data_bak.cookie.dmac_address,
2167 RTC_DATA_LOWER_BOUND, sc->sc_dma_fw_data.cookie.dmac_size);
2168 if (err != IWP_SUCCESS) {
2169 cmn_err(CE_WARN, "iwp_load_run_firmware(): "
2170 "failed to write run_data uCode.\n");
2171 return (err);
2172 }
2173
2174 clk = ddi_get_lbolt() + drv_usectohz(1000000);
2175
2176 /*
2177 * wait loading run_data until completed or timeout
2178 */
2179 while (!(sc->sc_flags & IWP_F_PUT_SEG)) {
2180 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) {
2181 break;
2182 }
2183 }
2184
2185 if (!(sc->sc_flags & IWP_F_PUT_SEG)) {
2186 cmn_err(CE_WARN, "iwp_load_run_firmware(): "
2187 "timeout waiting for run_data uCode load.\n");
2188 return (IWP_FAIL);
2189 }
2190
2191 atomic_and_32(&sc->sc_flags, ~IWP_F_PUT_SEG);
2192
2193 return (err);
2194 }
2195
2196 /*
2197 * this function will be invoked to receive phy information
2198 * when a frame is received.
2199 */
2200 static void
iwp_rx_phy_intr(iwp_sc_t * sc,iwp_rx_desc_t * desc)2201 iwp_rx_phy_intr(iwp_sc_t *sc, iwp_rx_desc_t *desc)
2202 {
2203
2204 sc->sc_rx_phy_res.flag = 1;
2205
2206 (void) memcpy(sc->sc_rx_phy_res.buf, (uint8_t *)(desc + 1),
2207 sizeof (iwp_rx_phy_res_t));
2208 }
2209
2210 /*
2211 * this function will be invoked to receive body of frame when
2212 * a frame is received.
2213 */
2214 static void
iwp_rx_mpdu_intr(iwp_sc_t * sc,iwp_rx_desc_t * desc)2215 iwp_rx_mpdu_intr(iwp_sc_t *sc, iwp_rx_desc_t *desc)
2216 {
2217 ieee80211com_t *ic = &sc->sc_ic;
2218 #ifdef DEBUG
2219 iwp_rx_ring_t *ring = &sc->sc_rxq;
2220 #endif
2221 struct ieee80211_frame *wh;
2222 struct iwp_rx_non_cfg_phy *phyinfo;
2223 struct iwp_rx_mpdu_body_size *mpdu_size;
2224
2225 mblk_t *mp;
2226 int16_t t;
2227 uint16_t len, rssi, agc;
2228 uint32_t temp, crc, *tail;
2229 uint32_t arssi, brssi, crssi, mrssi;
2230 iwp_rx_phy_res_t *stat;
2231 ieee80211_node_t *in;
2232
2233 /*
2234 * assuming not 11n here. cope with 11n in phase-II
2235 */
2236 mpdu_size = (struct iwp_rx_mpdu_body_size *)(desc + 1);
2237 stat = (iwp_rx_phy_res_t *)sc->sc_rx_phy_res.buf;
2238 if (stat->cfg_phy_cnt > 20) {
2239 return;
2240 }
2241
2242 phyinfo = (struct iwp_rx_non_cfg_phy *)stat->non_cfg_phy;
2243 temp = LE_32(phyinfo->non_cfg_phy[IWP_RX_RES_AGC_IDX]);
2244 agc = (temp & IWP_OFDM_AGC_MSK) >> IWP_OFDM_AGC_BIT_POS;
2245
2246 temp = LE_32(phyinfo->non_cfg_phy[IWP_RX_RES_RSSI_AB_IDX]);
2247 arssi = (temp & IWP_OFDM_RSSI_A_MSK) >> IWP_OFDM_RSSI_A_BIT_POS;
2248 brssi = (temp & IWP_OFDM_RSSI_B_MSK) >> IWP_OFDM_RSSI_B_BIT_POS;
2249
2250 temp = LE_32(phyinfo->non_cfg_phy[IWP_RX_RES_RSSI_C_IDX]);
2251 crssi = (temp & IWP_OFDM_RSSI_C_MSK) >> IWP_OFDM_RSSI_C_BIT_POS;
2252
2253 mrssi = MAX(arssi, brssi);
2254 mrssi = MAX(mrssi, crssi);
2255
2256 t = mrssi - agc - IWP_RSSI_OFFSET;
2257 /*
2258 * convert dBm to percentage
2259 */
2260 rssi = (100 * 75 * 75 - (-20 - t) * (15 * 75 + 62 * (-20 - t)))
2261 / (75 * 75);
2262 if (rssi > 100) {
2263 rssi = 100;
2264 }
2265 if (rssi < 1) {
2266 rssi = 1;
2267 }
2268
2269 /*
2270 * size of frame, not include FCS
2271 */
2272 len = LE_16(mpdu_size->byte_count);
2273 tail = (uint32_t *)((uint8_t *)(desc + 1) +
2274 sizeof (struct iwp_rx_mpdu_body_size) + len);
2275 bcopy(tail, &crc, 4);
2276
2277 IWP_DBG((IWP_DEBUG_RX, "iwp_rx_mpdu_intr(): "
2278 "rx intr: idx=%d phy_len=%x len=%d "
2279 "rate=%x chan=%d tstamp=%x non_cfg_phy_count=%x "
2280 "cfg_phy_count=%x tail=%x", ring->cur, sizeof (*stat),
2281 len, stat->rate.r.s.rate, stat->channel,
2282 LE_32(stat->timestampl), stat->non_cfg_phy_cnt,
2283 stat->cfg_phy_cnt, LE_32(crc)));
2284
2285 if ((len < 16) || (len > sc->sc_dmabuf_sz)) {
2286 IWP_DBG((IWP_DEBUG_RX, "iwp_rx_mpdu_intr(): "
2287 "rx frame oversize\n"));
2288 return;
2289 }
2290
2291 /*
2292 * discard Rx frames with bad CRC
2293 */
2294 if ((LE_32(crc) &
2295 (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) !=
2296 (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) {
2297 IWP_DBG((IWP_DEBUG_RX, "iwp_rx_mpdu_intr(): "
2298 "rx crc error tail: %x\n",
2299 LE_32(crc)));
2300 sc->sc_rx_err++;
2301 return;
2302 }
2303
2304 wh = (struct ieee80211_frame *)
2305 ((uint8_t *)(desc + 1)+ sizeof (struct iwp_rx_mpdu_body_size));
2306
2307 if (IEEE80211_FC0_SUBTYPE_ASSOC_RESP == *(uint8_t *)wh) {
2308 sc->sc_assoc_id = *((uint16_t *)(wh + 1) + 2);
2309 IWP_DBG((IWP_DEBUG_RX, "iwp_rx_mpdu_intr(): "
2310 "rx : association id = %x\n",
2311 sc->sc_assoc_id));
2312 }
2313
2314 #ifdef DEBUG
2315 if (iwp_dbg_flags & IWP_DEBUG_RX) {
2316 ieee80211_dump_pkt((uint8_t *)wh, len, 0, 0);
2317 }
2318 #endif
2319
2320 in = ieee80211_find_rxnode(ic, wh);
2321 mp = allocb(len, BPRI_MED);
2322 if (mp) {
2323 (void) memcpy(mp->b_wptr, wh, len);
2324 mp->b_wptr += len;
2325
2326 /*
2327 * send the frame to the 802.11 layer
2328 */
2329 (void) ieee80211_input(ic, mp, in, rssi, 0);
2330 } else {
2331 sc->sc_rx_nobuf++;
2332 IWP_DBG((IWP_DEBUG_RX, "iwp_rx_mpdu_intr(): "
2333 "alloc rx buf failed\n"));
2334 }
2335
2336 /*
2337 * release node reference
2338 */
2339 ieee80211_free_node(in);
2340 }
2341
2342 /*
2343 * process correlative affairs after a frame is sent.
2344 */
2345 static void
iwp_tx_intr(iwp_sc_t * sc,iwp_rx_desc_t * desc)2346 iwp_tx_intr(iwp_sc_t *sc, iwp_rx_desc_t *desc)
2347 {
2348 ieee80211com_t *ic = &sc->sc_ic;
2349 iwp_tx_ring_t *ring = &sc->sc_txq[desc->hdr.qid & 0x3];
2350 iwp_tx_stat_t *stat = (iwp_tx_stat_t *)(desc + 1);
2351 iwp_amrr_t *amrr;
2352
2353 if (NULL == ic->ic_bss) {
2354 return;
2355 }
2356
2357 amrr = (iwp_amrr_t *)ic->ic_bss;
2358
2359 amrr->txcnt++;
2360 IWP_DBG((IWP_DEBUG_RATECTL, "iwp_tx_intr(): "
2361 "tx: %d cnt\n", amrr->txcnt));
2362
2363 if (stat->ntries > 0) {
2364 amrr->retrycnt++;
2365 sc->sc_tx_retries++;
2366 IWP_DBG((IWP_DEBUG_TX, "iwp_tx_intr(): "
2367 "tx: %d retries\n",
2368 sc->sc_tx_retries));
2369 }
2370
2371 mutex_enter(&sc->sc_mt_lock);
2372 sc->sc_tx_timer = 0;
2373 mutex_exit(&sc->sc_mt_lock);
2374
2375 mutex_enter(&sc->sc_tx_lock);
2376
2377 ring->queued--;
2378 if (ring->queued < 0) {
2379 ring->queued = 0;
2380 }
2381
2382 if ((sc->sc_need_reschedule) && (ring->queued <= (ring->count >> 3))) {
2383 sc->sc_need_reschedule = 0;
2384 mutex_exit(&sc->sc_tx_lock);
2385 mac_tx_update(ic->ic_mach);
2386 mutex_enter(&sc->sc_tx_lock);
2387 }
2388
2389 mutex_exit(&sc->sc_tx_lock);
2390 }
2391
2392 /*
2393 * inform a given command has been executed
2394 */
2395 static void
iwp_cmd_intr(iwp_sc_t * sc,iwp_rx_desc_t * desc)2396 iwp_cmd_intr(iwp_sc_t *sc, iwp_rx_desc_t *desc)
2397 {
2398 if ((desc->hdr.qid & 7) != 4) {
2399 return;
2400 }
2401
2402 if (sc->sc_cmd_accum > 0) {
2403 sc->sc_cmd_accum--;
2404 return;
2405 }
2406
2407 mutex_enter(&sc->sc_glock);
2408
2409 sc->sc_cmd_flag = SC_CMD_FLG_DONE;
2410
2411 cv_signal(&sc->sc_cmd_cv);
2412
2413 mutex_exit(&sc->sc_glock);
2414
2415 IWP_DBG((IWP_DEBUG_CMD, "iwp_cmd_intr(): "
2416 "qid=%x idx=%d flags=%x type=0x%x\n",
2417 desc->hdr.qid, desc->hdr.idx, desc->hdr.flags,
2418 desc->hdr.type));
2419 }
2420
2421 /*
2422 * this function will be invoked when alive notification occur.
2423 */
2424 static void
iwp_ucode_alive(iwp_sc_t * sc,iwp_rx_desc_t * desc)2425 iwp_ucode_alive(iwp_sc_t *sc, iwp_rx_desc_t *desc)
2426 {
2427 uint32_t rv;
2428 struct iwp_calib_cfg_cmd cmd;
2429 struct iwp_alive_resp *ar =
2430 (struct iwp_alive_resp *)(desc + 1);
2431 struct iwp_calib_results *res_p = &sc->sc_calib_results;
2432
2433 /*
2434 * the microcontroller is ready
2435 */
2436 IWP_DBG((IWP_DEBUG_FW, "iwp_ucode_alive(): "
2437 "microcode alive notification minor: %x major: %x type: "
2438 "%x subtype: %x\n",
2439 ar->ucode_minor, ar->ucode_minor, ar->ver_type, ar->ver_subtype));
2440
2441 #ifdef DEBUG
2442 if (LE_32(ar->is_valid) != UCODE_VALID_OK) {
2443 IWP_DBG((IWP_DEBUG_FW, "iwp_ucode_alive(): "
2444 "microcontroller initialization failed\n"));
2445 }
2446 #endif
2447
2448 /*
2449 * determine if init alive or runtime alive.
2450 */
2451 if (INITIALIZE_SUBTYPE == ar->ver_subtype) {
2452 IWP_DBG((IWP_DEBUG_FW, "iwp_ucode_alive(): "
2453 "initialization alive received.\n"));
2454
2455 (void) memcpy(&sc->sc_card_alive_init, ar,
2456 sizeof (struct iwp_init_alive_resp));
2457
2458 /*
2459 * necessary configuration to NIC
2460 */
2461 mutex_enter(&sc->sc_glock);
2462
2463 rv = iwp_alive_common(sc);
2464 if (rv != IWP_SUCCESS) {
2465 cmn_err(CE_WARN, "iwp_ucode_alive(): "
2466 "common alive process failed in init alive.\n");
2467 mutex_exit(&sc->sc_glock);
2468 return;
2469 }
2470
2471 (void) memset(&cmd, 0, sizeof (cmd));
2472
2473 cmd.ucd_calib_cfg.once.is_enable = IWP_CALIB_INIT_CFG_ALL;
2474 cmd.ucd_calib_cfg.once.start = IWP_CALIB_INIT_CFG_ALL;
2475 cmd.ucd_calib_cfg.once.send_res = IWP_CALIB_INIT_CFG_ALL;
2476 cmd.ucd_calib_cfg.flags = IWP_CALIB_INIT_CFG_ALL;
2477
2478 /*
2479 * require ucode execute calibration
2480 */
2481 rv = iwp_cmd(sc, CALIBRATION_CFG_CMD, &cmd, sizeof (cmd), 1);
2482 if (rv != IWP_SUCCESS) {
2483 cmn_err(CE_WARN, "iwp_ucode_alive(): "
2484 "failed to send calibration configure command.\n");
2485 mutex_exit(&sc->sc_glock);
2486 return;
2487 }
2488
2489 mutex_exit(&sc->sc_glock);
2490
2491 } else { /* runtime alive */
2492
2493 IWP_DBG((IWP_DEBUG_FW, "iwp_ucode_alive(): "
2494 "runtime alive received.\n"));
2495
2496 (void) memcpy(&sc->sc_card_alive_run, ar,
2497 sizeof (struct iwp_alive_resp));
2498
2499 mutex_enter(&sc->sc_glock);
2500
2501 /*
2502 * necessary configuration to NIC
2503 */
2504 rv = iwp_alive_common(sc);
2505 if (rv != IWP_SUCCESS) {
2506 cmn_err(CE_WARN, "iwp_ucode_alive(): "
2507 "common alive process failed in run alive.\n");
2508 mutex_exit(&sc->sc_glock);
2509 return;
2510 }
2511
2512 /*
2513 * send the result of local oscilator calibration to uCode.
2514 */
2515 if (res_p->lo_res != NULL) {
2516 rv = iwp_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
2517 res_p->lo_res, res_p->lo_res_len, 1);
2518 if (rv != IWP_SUCCESS) {
2519 cmn_err(CE_WARN, "iwp_ucode_alive(): "
2520 "failed to send local"
2521 "oscilator calibration command.\n");
2522 mutex_exit(&sc->sc_glock);
2523 return;
2524 }
2525
2526 DELAY(1000);
2527 }
2528
2529 /*
2530 * send the result of TX IQ calibration to uCode.
2531 */
2532 if (res_p->tx_iq_res != NULL) {
2533 rv = iwp_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
2534 res_p->tx_iq_res, res_p->tx_iq_res_len, 1);
2535 if (rv != IWP_SUCCESS) {
2536 cmn_err(CE_WARN, "iwp_ucode_alive(): "
2537 "failed to send TX IQ"
2538 "calibration command.\n");
2539 mutex_exit(&sc->sc_glock);
2540 return;
2541 }
2542
2543 DELAY(1000);
2544 }
2545
2546 /*
2547 * send the result of TX IQ perd calibration to uCode.
2548 */
2549 if (res_p->tx_iq_perd_res != NULL) {
2550 rv = iwp_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
2551 res_p->tx_iq_perd_res,
2552 res_p->tx_iq_perd_res_len, 1);
2553 if (rv != IWP_SUCCESS) {
2554 cmn_err(CE_WARN, "iwp_ucode_alive(): "
2555 "failed to send TX IQ perd"
2556 "calibration command.\n");
2557 mutex_exit(&sc->sc_glock);
2558 return;
2559 }
2560
2561 DELAY(1000);
2562 }
2563
2564 /*
2565 * send the result of Base Band calibration to uCode.
2566 */
2567 if (res_p->base_band_res != NULL) {
2568 rv = iwp_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
2569 res_p->base_band_res,
2570 res_p->base_band_res_len, 1);
2571 if (rv != IWP_SUCCESS) {
2572 cmn_err(CE_WARN, "iwp_ucode_alive(): "
2573 "failed to send Base Band"
2574 "calibration command.\n");
2575 mutex_exit(&sc->sc_glock);
2576 return;
2577 }
2578
2579 DELAY(1000);
2580 }
2581
2582 atomic_or_32(&sc->sc_flags, IWP_F_FW_INIT);
2583 cv_signal(&sc->sc_ucode_cv);
2584
2585 mutex_exit(&sc->sc_glock);
2586 }
2587
2588 }
2589
2590 /*
2591 * deal with receiving frames, command response
2592 * and all notifications from ucode.
2593 */
2594 /* ARGSUSED */
2595 static uint_t
iwp_rx_softintr(caddr_t arg,caddr_t unused)2596 iwp_rx_softintr(caddr_t arg, caddr_t unused)
2597 {
2598 iwp_sc_t *sc;
2599 ieee80211com_t *ic;
2600 iwp_rx_desc_t *desc;
2601 iwp_rx_data_t *data;
2602 uint32_t index;
2603
2604 if (NULL == arg) {
2605 return (DDI_INTR_UNCLAIMED);
2606 }
2607 sc = (iwp_sc_t *)arg;
2608 ic = &sc->sc_ic;
2609
2610 /*
2611 * firmware has moved the index of the rx queue, driver get it,
2612 * and deal with it.
2613 */
2614 index = (sc->sc_shared->val0) & 0xfff;
2615
2616 while (sc->sc_rxq.cur != index) {
2617 data = &sc->sc_rxq.data[sc->sc_rxq.cur];
2618 desc = (iwp_rx_desc_t *)data->dma_data.mem_va;
2619
2620 IWP_DBG((IWP_DEBUG_INTR, "iwp_rx_softintr(): "
2621 "rx notification index = %d"
2622 " cur = %d qid=%x idx=%d flags=%x type=%x len=%d\n",
2623 index, sc->sc_rxq.cur, desc->hdr.qid, desc->hdr.idx,
2624 desc->hdr.flags, desc->hdr.type, LE_32(desc->len)));
2625
2626 /*
2627 * a command other than a tx need to be replied
2628 */
2629 if (!(desc->hdr.qid & 0x80) &&
2630 (desc->hdr.type != REPLY_SCAN_CMD) &&
2631 (desc->hdr.type != REPLY_TX)) {
2632 iwp_cmd_intr(sc, desc);
2633 }
2634
2635 switch (desc->hdr.type) {
2636 case REPLY_RX_PHY_CMD:
2637 iwp_rx_phy_intr(sc, desc);
2638 break;
2639
2640 case REPLY_RX_MPDU_CMD:
2641 iwp_rx_mpdu_intr(sc, desc);
2642 break;
2643
2644 case REPLY_TX:
2645 iwp_tx_intr(sc, desc);
2646 break;
2647
2648 case REPLY_ALIVE:
2649 iwp_ucode_alive(sc, desc);
2650 break;
2651
2652 case CARD_STATE_NOTIFICATION:
2653 {
2654 uint32_t *status = (uint32_t *)(desc + 1);
2655
2656 IWP_DBG((IWP_DEBUG_RADIO, "iwp_rx_softintr(): "
2657 "state changed to %x\n",
2658 LE_32(*status)));
2659
2660 if (LE_32(*status) & 1) {
2661 /*
2662 * the radio button has to be pushed(OFF). It
2663 * is considered as a hw error, the
2664 * iwp_thread() tries to recover it after the
2665 * button is pushed again(ON)
2666 */
2667 cmn_err(CE_NOTE, "iwp_rx_softintr(): "
2668 "radio transmitter is off\n");
2669 sc->sc_ostate = sc->sc_ic.ic_state;
2670 ieee80211_new_state(&sc->sc_ic,
2671 IEEE80211_S_INIT, -1);
2672 atomic_or_32(&sc->sc_flags,
2673 IWP_F_HW_ERR_RECOVER | IWP_F_RADIO_OFF);
2674 }
2675
2676 break;
2677 }
2678
2679 case SCAN_START_NOTIFICATION:
2680 {
2681 iwp_start_scan_t *scan =
2682 (iwp_start_scan_t *)(desc + 1);
2683
2684 IWP_DBG((IWP_DEBUG_SCAN, "iwp_rx_softintr(): "
2685 "scanning channel %d status %x\n",
2686 scan->chan, LE_32(scan->status)));
2687
2688 ic->ic_curchan = &ic->ic_sup_channels[scan->chan];
2689 break;
2690 }
2691
2692 case SCAN_COMPLETE_NOTIFICATION:
2693 {
2694 #ifdef DEBUG
2695 iwp_stop_scan_t *scan =
2696 (iwp_stop_scan_t *)(desc + 1);
2697
2698 IWP_DBG((IWP_DEBUG_SCAN, "iwp_rx_softintr(): "
2699 "completed channel %d (burst of %d) status %02x\n",
2700 scan->chan, scan->nchan, scan->status));
2701 #endif
2702
2703 sc->sc_scan_pending++;
2704 break;
2705 }
2706
2707 case STATISTICS_NOTIFICATION:
2708 {
2709 /*
2710 * handle statistics notification
2711 */
2712 break;
2713 }
2714
2715 case CALIBRATION_RES_NOTIFICATION:
2716 iwp_save_calib_result(sc, desc);
2717 break;
2718
2719 case CALIBRATION_COMPLETE_NOTIFICATION:
2720 mutex_enter(&sc->sc_glock);
2721 atomic_or_32(&sc->sc_flags, IWP_F_FW_INIT);
2722 cv_signal(&sc->sc_ucode_cv);
2723 mutex_exit(&sc->sc_glock);
2724 break;
2725
2726 case MISSED_BEACONS_NOTIFICATION:
2727 {
2728 struct iwp_beacon_missed *miss =
2729 (struct iwp_beacon_missed *)(desc + 1);
2730
2731 if ((ic->ic_state == IEEE80211_S_RUN) &&
2732 (LE_32(miss->consecutive) > 50)) {
2733 cmn_err(CE_NOTE, "iwp: iwp_rx_softintr(): "
2734 "beacon missed %d/%d\n",
2735 LE_32(miss->consecutive),
2736 LE_32(miss->total));
2737 (void) ieee80211_new_state(ic,
2738 IEEE80211_S_INIT, -1);
2739 }
2740 break;
2741 }
2742 }
2743
2744 sc->sc_rxq.cur = (sc->sc_rxq.cur + 1) % RX_QUEUE_SIZE;
2745 }
2746
2747 /*
2748 * driver dealt with what received in rx queue and tell the information
2749 * to the firmware.
2750 */
2751 index = (0 == index) ? RX_QUEUE_SIZE - 1 : index - 1;
2752 IWP_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, index & (~7));
2753
2754 /*
2755 * re-enable interrupts
2756 */
2757 IWP_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
2758
2759 return (DDI_INTR_CLAIMED);
2760 }
2761
2762 /*
2763 * the handle of interrupt
2764 */
2765 /* ARGSUSED */
2766 static uint_t
iwp_intr(caddr_t arg,caddr_t unused)2767 iwp_intr(caddr_t arg, caddr_t unused)
2768 {
2769 iwp_sc_t *sc;
2770 uint32_t r, rfh;
2771
2772 if (NULL == arg) {
2773 return (DDI_INTR_UNCLAIMED);
2774 }
2775 sc = (iwp_sc_t *)arg;
2776
2777 r = IWP_READ(sc, CSR_INT);
2778 if (0 == r || 0xffffffff == r) {
2779 return (DDI_INTR_UNCLAIMED);
2780 }
2781
2782 IWP_DBG((IWP_DEBUG_INTR, "iwp_intr(): "
2783 "interrupt reg %x\n", r));
2784
2785 rfh = IWP_READ(sc, CSR_FH_INT_STATUS);
2786
2787 IWP_DBG((IWP_DEBUG_INTR, "iwp_intr(): "
2788 "FH interrupt reg %x\n", rfh));
2789
2790 /*
2791 * disable interrupts
2792 */
2793 IWP_WRITE(sc, CSR_INT_MASK, 0);
2794
2795 /*
2796 * ack interrupts
2797 */
2798 IWP_WRITE(sc, CSR_INT, r);
2799 IWP_WRITE(sc, CSR_FH_INT_STATUS, rfh);
2800
2801 if (r & (BIT_INT_SWERROR | BIT_INT_ERR)) {
2802 IWP_DBG((IWP_DEBUG_FW, "iwp_intr(): "
2803 "fatal firmware error\n"));
2804 iwp_stop(sc);
2805 sc->sc_ostate = sc->sc_ic.ic_state;
2806
2807 /* notify upper layer */
2808 if (!IWP_CHK_FAST_RECOVER(sc)) {
2809 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
2810 }
2811
2812 atomic_or_32(&sc->sc_flags, IWP_F_HW_ERR_RECOVER);
2813 return (DDI_INTR_CLAIMED);
2814 }
2815
2816 if (r & BIT_INT_RF_KILL) {
2817 uint32_t tmp = IWP_READ(sc, CSR_GP_CNTRL);
2818 if (tmp & (1 << 27)) {
2819 cmn_err(CE_NOTE, "RF switch: radio on\n");
2820 }
2821 }
2822
2823 if ((r & (BIT_INT_FH_RX | BIT_INT_SW_RX)) ||
2824 (rfh & FH_INT_RX_MASK)) {
2825 (void) ddi_intr_trigger_softint(sc->sc_soft_hdl, NULL);
2826 return (DDI_INTR_CLAIMED);
2827 }
2828
2829 if (r & BIT_INT_FH_TX) {
2830 mutex_enter(&sc->sc_glock);
2831 atomic_or_32(&sc->sc_flags, IWP_F_PUT_SEG);
2832 cv_signal(&sc->sc_put_seg_cv);
2833 mutex_exit(&sc->sc_glock);
2834 }
2835
2836 #ifdef DEBUG
2837 if (r & BIT_INT_ALIVE) {
2838 IWP_DBG((IWP_DEBUG_FW, "iwp_intr(): "
2839 "firmware initialized.\n"));
2840 }
2841 #endif
2842
2843 /*
2844 * re-enable interrupts
2845 */
2846 IWP_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
2847
2848 return (DDI_INTR_CLAIMED);
2849 }
2850
2851 static uint8_t
iwp_rate_to_plcp(int rate)2852 iwp_rate_to_plcp(int rate)
2853 {
2854 uint8_t ret;
2855
2856 switch (rate) {
2857 /*
2858 * CCK rates
2859 */
2860 case 2:
2861 ret = 0xa;
2862 break;
2863
2864 case 4:
2865 ret = 0x14;
2866 break;
2867
2868 case 11:
2869 ret = 0x37;
2870 break;
2871
2872 case 22:
2873 ret = 0x6e;
2874 break;
2875
2876 /*
2877 * OFDM rates
2878 */
2879 case 12:
2880 ret = 0xd;
2881 break;
2882
2883 case 18:
2884 ret = 0xf;
2885 break;
2886
2887 case 24:
2888 ret = 0x5;
2889 break;
2890
2891 case 36:
2892 ret = 0x7;
2893 break;
2894
2895 case 48:
2896 ret = 0x9;
2897 break;
2898
2899 case 72:
2900 ret = 0xb;
2901 break;
2902
2903 case 96:
2904 ret = 0x1;
2905 break;
2906
2907 case 108:
2908 ret = 0x3;
2909 break;
2910
2911 default:
2912 ret = 0;
2913 break;
2914 }
2915
2916 return (ret);
2917 }
2918
2919 /*
2920 * invoked by GLD send frames
2921 */
2922 static mblk_t *
iwp_m_tx(void * arg,mblk_t * mp)2923 iwp_m_tx(void *arg, mblk_t *mp)
2924 {
2925 iwp_sc_t *sc;
2926 ieee80211com_t *ic;
2927 mblk_t *next;
2928
2929 if (NULL == arg) {
2930 return (NULL);
2931 }
2932 sc = (iwp_sc_t *)arg;
2933 ic = &sc->sc_ic;
2934
2935 if (sc->sc_flags & IWP_F_SUSPEND) {
2936 freemsgchain(mp);
2937 return (NULL);
2938 }
2939
2940 if (ic->ic_state != IEEE80211_S_RUN) {
2941 freemsgchain(mp);
2942 return (NULL);
2943 }
2944
2945 if ((sc->sc_flags & IWP_F_HW_ERR_RECOVER) &&
2946 IWP_CHK_FAST_RECOVER(sc)) {
2947 IWP_DBG((IWP_DEBUG_FW, "iwp_m_tx(): "
2948 "hold queue\n"));
2949 return (mp);
2950 }
2951
2952
2953 while (mp != NULL) {
2954 next = mp->b_next;
2955 mp->b_next = NULL;
2956 if (iwp_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != 0) {
2957 mp->b_next = next;
2958 break;
2959 }
2960 mp = next;
2961 }
2962
2963 return (mp);
2964 }
2965
2966 /*
2967 * send frames
2968 */
2969 static int
iwp_send(ieee80211com_t * ic,mblk_t * mp,uint8_t type)2970 iwp_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
2971 {
2972 iwp_sc_t *sc;
2973 iwp_tx_ring_t *ring;
2974 iwp_tx_desc_t *desc;
2975 iwp_tx_data_t *data;
2976 iwp_tx_data_t *desc_data;
2977 iwp_cmd_t *cmd;
2978 iwp_tx_cmd_t *tx;
2979 ieee80211_node_t *in;
2980 struct ieee80211_frame *wh;
2981 struct ieee80211_key *k = NULL;
2982 mblk_t *m, *m0;
2983 int hdrlen, len, len0, mblen, off, err = IWP_SUCCESS;
2984 uint16_t masks = 0;
2985 uint32_t rate, s_id = 0;
2986
2987 if (NULL == ic) {
2988 return (IWP_FAIL);
2989 }
2990 sc = (iwp_sc_t *)ic;
2991
2992 if (sc->sc_flags & IWP_F_SUSPEND) {
2993 if ((type & IEEE80211_FC0_TYPE_MASK) !=
2994 IEEE80211_FC0_TYPE_DATA) {
2995 freemsg(mp);
2996 }
2997 err = IWP_FAIL;
2998 goto exit;
2999 }
3000
3001 mutex_enter(&sc->sc_tx_lock);
3002 ring = &sc->sc_txq[0];
3003 data = &ring->data[ring->cur];
3004 cmd = data->cmd;
3005 bzero(cmd, sizeof (*cmd));
3006
3007 ring->cur = (ring->cur + 1) % ring->count;
3008
3009 /*
3010 * Need reschedule TX if TX buffer is full.
3011 */
3012 if (ring->queued > ring->count - IWP_MAX_WIN_SIZE) {
3013 IWP_DBG((IWP_DEBUG_TX, "iwp_send(): "
3014 "no txbuf\n"));
3015
3016 sc->sc_need_reschedule = 1;
3017 mutex_exit(&sc->sc_tx_lock);
3018
3019 if ((type & IEEE80211_FC0_TYPE_MASK) !=
3020 IEEE80211_FC0_TYPE_DATA) {
3021 freemsg(mp);
3022 }
3023 sc->sc_tx_nobuf++;
3024 err = IWP_FAIL;
3025 goto exit;
3026 }
3027
3028 ring->queued++;
3029
3030 mutex_exit(&sc->sc_tx_lock);
3031
3032 hdrlen = ieee80211_hdrspace(ic, mp->b_rptr);
3033
3034 m = allocb(msgdsize(mp) + 32, BPRI_MED);
3035 if (NULL == m) { /* can not alloc buf, drop this package */
3036 cmn_err(CE_WARN, "iwp_send(): "
3037 "failed to allocate msgbuf\n");
3038 freemsg(mp);
3039
3040 mutex_enter(&sc->sc_tx_lock);
3041 ring->queued--;
3042 if ((sc->sc_need_reschedule) && (ring->queued <= 0)) {
3043 sc->sc_need_reschedule = 0;
3044 mutex_exit(&sc->sc_tx_lock);
3045 mac_tx_update(ic->ic_mach);
3046 mutex_enter(&sc->sc_tx_lock);
3047 }
3048 mutex_exit(&sc->sc_tx_lock);
3049
3050 err = IWP_SUCCESS;
3051 goto exit;
3052 }
3053
3054 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
3055 mblen = MBLKL(m0);
3056 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen);
3057 off += mblen;
3058 }
3059
3060 m->b_wptr += off;
3061
3062 wh = (struct ieee80211_frame *)m->b_rptr;
3063
3064 /*
3065 * determine send which AP or station in IBSS
3066 */
3067 in = ieee80211_find_txnode(ic, wh->i_addr1);
3068 if (NULL == in) {
3069 cmn_err(CE_WARN, "iwp_send(): "
3070 "failed to find tx node\n");
3071 freemsg(mp);
3072 freemsg(m);
3073 sc->sc_tx_err++;
3074
3075 mutex_enter(&sc->sc_tx_lock);
3076 ring->queued--;
3077 if ((sc->sc_need_reschedule) && (ring->queued <= 0)) {
3078 sc->sc_need_reschedule = 0;
3079 mutex_exit(&sc->sc_tx_lock);
3080 mac_tx_update(ic->ic_mach);
3081 mutex_enter(&sc->sc_tx_lock);
3082 }
3083 mutex_exit(&sc->sc_tx_lock);
3084
3085 err = IWP_SUCCESS;
3086 goto exit;
3087 }
3088
3089 /*
3090 * Net80211 module encapsulate outbound data frames.
3091 * Add some feilds of 80211 frame.
3092 */
3093 if ((type & IEEE80211_FC0_TYPE_MASK) ==
3094 IEEE80211_FC0_TYPE_DATA) {
3095 (void) ieee80211_encap(ic, m, in);
3096 }
3097
3098 freemsg(mp);
3099
3100 cmd->hdr.type = REPLY_TX;
3101 cmd->hdr.flags = 0;
3102 cmd->hdr.qid = ring->qid;
3103
3104 tx = (iwp_tx_cmd_t *)cmd->data;
3105 tx->tx_flags = 0;
3106
3107 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3108 tx->tx_flags &= ~(LE_32(TX_CMD_FLG_ACK_MSK));
3109 } else {
3110 tx->tx_flags |= LE_32(TX_CMD_FLG_ACK_MSK);
3111 }
3112
3113 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
3114 k = ieee80211_crypto_encap(ic, m);
3115 if (NULL == k) {
3116 freemsg(m);
3117 sc->sc_tx_err++;
3118
3119 mutex_enter(&sc->sc_tx_lock);
3120 ring->queued--;
3121 if ((sc->sc_need_reschedule) && (ring->queued <= 0)) {
3122 sc->sc_need_reschedule = 0;
3123 mutex_exit(&sc->sc_tx_lock);
3124 mac_tx_update(ic->ic_mach);
3125 mutex_enter(&sc->sc_tx_lock);
3126 }
3127 mutex_exit(&sc->sc_tx_lock);
3128
3129 err = IWP_SUCCESS;
3130 goto exit;
3131 }
3132
3133 /* packet header may have moved, reset our local pointer */
3134 wh = (struct ieee80211_frame *)m->b_rptr;
3135 }
3136
3137 len = msgdsize(m);
3138
3139 #ifdef DEBUG
3140 if (iwp_dbg_flags & IWP_DEBUG_TX) {
3141 ieee80211_dump_pkt((uint8_t *)wh, hdrlen, 0, 0);
3142 }
3143 #endif
3144
3145 tx->rts_retry_limit = IWP_TX_RTS_RETRY_LIMIT;
3146 tx->data_retry_limit = IWP_TX_DATA_RETRY_LIMIT;
3147
3148 /*
3149 * specific TX parameters for management frames
3150 */
3151 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
3152 IEEE80211_FC0_TYPE_MGT) {
3153 /*
3154 * mgmt frames are sent at 1M
3155 */
3156 if ((in->in_rates.ir_rates[0] &
3157 IEEE80211_RATE_VAL) != 0) {
3158 rate = in->in_rates.ir_rates[0] & IEEE80211_RATE_VAL;
3159 } else {
3160 rate = 2;
3161 }
3162
3163 tx->tx_flags |= LE_32(TX_CMD_FLG_SEQ_CTL_MSK);
3164
3165 /*
3166 * tell h/w to set timestamp in probe responses
3167 */
3168 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
3169 IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
3170 tx->tx_flags |= LE_32(TX_CMD_FLG_TSF_MSK);
3171
3172 tx->data_retry_limit = 3;
3173 if (tx->data_retry_limit < tx->rts_retry_limit) {
3174 tx->rts_retry_limit = tx->data_retry_limit;
3175 }
3176 }
3177
3178 if (((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
3179 IEEE80211_FC0_SUBTYPE_ASSOC_REQ) ||
3180 ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
3181 IEEE80211_FC0_SUBTYPE_REASSOC_REQ)) {
3182 tx->timeout.pm_frame_timeout = LE_16(3);
3183 } else {
3184 tx->timeout.pm_frame_timeout = LE_16(2);
3185 }
3186
3187 } else {
3188 /*
3189 * do it here for the software way rate scaling.
3190 * later for rate scaling in hardware.
3191 *
3192 * now the txrate is determined in tx cmd flags, set to the
3193 * max value 54M for 11g and 11M for 11b originally.
3194 */
3195 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
3196 rate = ic->ic_fixed_rate;
3197 } else {
3198 if ((in->in_rates.ir_rates[in->in_txrate] &
3199 IEEE80211_RATE_VAL) != 0) {
3200 rate = in->in_rates.
3201 ir_rates[in->in_txrate] &
3202 IEEE80211_RATE_VAL;
3203 }
3204 }
3205
3206 tx->tx_flags |= LE_32(TX_CMD_FLG_SEQ_CTL_MSK);
3207
3208 tx->timeout.pm_frame_timeout = 0;
3209 }
3210
3211 IWP_DBG((IWP_DEBUG_TX, "iwp_send(): "
3212 "tx rate[%d of %d] = %x",
3213 in->in_txrate, in->in_rates.ir_nrates, rate));
3214
3215 len0 = roundup(4 + sizeof (iwp_tx_cmd_t) + hdrlen, 4);
3216 if (len0 != (4 + sizeof (iwp_tx_cmd_t) + hdrlen)) {
3217 tx->tx_flags |= LE_32(TX_CMD_FLG_MH_PAD_MSK);
3218 }
3219
3220 /*
3221 * retrieve destination node's id
3222 */
3223 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3224 tx->sta_id = IWP_BROADCAST_ID;
3225 } else {
3226 tx->sta_id = IWP_AP_ID;
3227 }
3228
3229 if (2 == rate || 4 == rate || 11 == rate || 22 == rate) {
3230 masks |= RATE_MCS_CCK_MSK;
3231 }
3232
3233 masks |= RATE_MCS_ANT_B_MSK;
3234 tx->rate.r.rate_n_flags = LE_32(iwp_rate_to_plcp(rate) | masks);
3235
3236 IWP_DBG((IWP_DEBUG_TX, "iwp_send(): "
3237 "tx flag = %x",
3238 tx->tx_flags));
3239
3240 tx->stop_time.life_time = LE_32(0xffffffff);
3241
3242 tx->len = LE_16(len);
3243
3244 tx->dram_lsb_ptr =
3245 LE_32(data->paddr_cmd + 4 + offsetof(iwp_tx_cmd_t, scratch));
3246 tx->dram_msb_ptr = 0;
3247 tx->driver_txop = 0;
3248 tx->next_frame_len = 0;
3249
3250 (void) memcpy(tx + 1, m->b_rptr, hdrlen);
3251 m->b_rptr += hdrlen;
3252 (void) memcpy(data->dma_data.mem_va, m->b_rptr, len - hdrlen);
3253
3254 IWP_DBG((IWP_DEBUG_TX, "iwp_send(): "
3255 "sending data: qid=%d idx=%d len=%d",
3256 ring->qid, ring->cur, len));
3257
3258 /*
3259 * first segment includes the tx cmd plus the 802.11 header,
3260 * the second includes the remaining of the 802.11 frame.
3261 */
3262 mutex_enter(&sc->sc_tx_lock);
3263
3264 cmd->hdr.idx = ring->desc_cur;
3265
3266 desc_data = &ring->data[ring->desc_cur];
3267 desc = desc_data->desc;
3268 bzero(desc, sizeof (*desc));
3269 desc->val0 = 2 << 24;
3270 desc->pa[0].tb1_addr = data->paddr_cmd;
3271 desc->pa[0].val1 = ((len0 << 4) & 0xfff0) |
3272 ((data->dma_data.cookie.dmac_address & 0xffff) << 16);
3273 desc->pa[0].val2 =
3274 ((data->dma_data.cookie.dmac_address & 0xffff0000) >> 16) |
3275 ((len - hdrlen) << 20);
3276 IWP_DBG((IWP_DEBUG_TX, "iwp_send(): "
3277 "phy addr1 = 0x%x phy addr2 = 0x%x "
3278 "len1 = 0x%x, len2 = 0x%x val1 = 0x%x val2 = 0x%x",
3279 data->paddr_cmd, data->dma_data.cookie.dmac_address,
3280 len0, len - hdrlen, desc->pa[0].val1, desc->pa[0].val2));
3281
3282 /*
3283 * kick ring
3284 */
3285 s_id = tx->sta_id;
3286
3287 sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3288 tfd_offset[ring->desc_cur].val =
3289 (8 + len) | (s_id << 12);
3290 if (ring->desc_cur < IWP_MAX_WIN_SIZE) {
3291 sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3292 tfd_offset[IWP_QUEUE_SIZE + ring->desc_cur].val =
3293 (8 + len) | (s_id << 12);
3294 }
3295
3296 IWP_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
3297 IWP_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
3298
3299 ring->desc_cur = (ring->desc_cur + 1) % ring->count;
3300 IWP_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->desc_cur);
3301
3302 mutex_exit(&sc->sc_tx_lock);
3303 freemsg(m);
3304
3305 /*
3306 * release node reference
3307 */
3308 ieee80211_free_node(in);
3309
3310 ic->ic_stats.is_tx_bytes += len;
3311 ic->ic_stats.is_tx_frags++;
3312
3313 mutex_enter(&sc->sc_mt_lock);
3314 if (0 == sc->sc_tx_timer) {
3315 sc->sc_tx_timer = 4;
3316 }
3317 mutex_exit(&sc->sc_mt_lock);
3318
3319 exit:
3320 return (err);
3321 }
3322
3323 /*
3324 * invoked by GLD to deal with IOCTL affaires
3325 */
3326 static void
iwp_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)3327 iwp_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
3328 {
3329 iwp_sc_t *sc;
3330 ieee80211com_t *ic;
3331 int err = EINVAL;
3332
3333 if (NULL == arg) {
3334 return;
3335 }
3336 sc = (iwp_sc_t *)arg;
3337 ic = &sc->sc_ic;
3338
3339 err = ieee80211_ioctl(ic, wq, mp);
3340 if (ENETRESET == err) {
3341 /*
3342 * This is special for the hidden AP connection.
3343 * In any case, we should make sure only one 'scan'
3344 * in the driver for a 'connect' CLI command. So
3345 * when connecting to a hidden AP, the scan is just
3346 * sent out to the air when we know the desired
3347 * essid of the AP we want to connect.
3348 */
3349 if (ic->ic_des_esslen) {
3350 if (sc->sc_flags & IWP_F_RUNNING) {
3351 iwp_m_stop(sc);
3352 (void) iwp_m_start(sc);
3353 (void) ieee80211_new_state(ic,
3354 IEEE80211_S_SCAN, -1);
3355 }
3356 }
3357 }
3358 }
3359
3360 /*
3361 * Call back functions for get/set proporty
3362 */
3363 static int
iwp_m_getprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,void * wldp_buf)3364 iwp_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
3365 uint_t wldp_length, void *wldp_buf)
3366 {
3367 iwp_sc_t *sc;
3368 int err = EINVAL;
3369
3370 if (NULL == arg) {
3371 return (EINVAL);
3372 }
3373 sc = (iwp_sc_t *)arg;
3374
3375 err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num,
3376 wldp_length, wldp_buf);
3377
3378 return (err);
3379 }
3380
3381 static void
iwp_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,mac_prop_info_handle_t prh)3382 iwp_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
3383 mac_prop_info_handle_t prh)
3384 {
3385 iwp_sc_t *sc;
3386
3387 sc = (iwp_sc_t *)arg;
3388 ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, prh);
3389 }
3390
3391 static int
iwp_m_setprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,const void * wldp_buf)3392 iwp_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
3393 uint_t wldp_length, const void *wldp_buf)
3394 {
3395 iwp_sc_t *sc;
3396 ieee80211com_t *ic;
3397 int err = EINVAL;
3398
3399 if (NULL == arg) {
3400 return (EINVAL);
3401 }
3402 sc = (iwp_sc_t *)arg;
3403 ic = &sc->sc_ic;
3404
3405 err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length,
3406 wldp_buf);
3407
3408 if (err == ENETRESET) {
3409 if (ic->ic_des_esslen) {
3410 if (sc->sc_flags & IWP_F_RUNNING) {
3411 iwp_m_stop(sc);
3412 (void) iwp_m_start(sc);
3413 (void) ieee80211_new_state(ic,
3414 IEEE80211_S_SCAN, -1);
3415 }
3416 }
3417 err = 0;
3418 }
3419 return (err);
3420 }
3421
3422 /*
3423 * invoked by GLD supply statistics NIC and driver
3424 */
3425 static int
iwp_m_stat(void * arg,uint_t stat,uint64_t * val)3426 iwp_m_stat(void *arg, uint_t stat, uint64_t *val)
3427 {
3428 iwp_sc_t *sc;
3429 ieee80211com_t *ic;
3430 ieee80211_node_t *in;
3431
3432 if (NULL == arg) {
3433 return (EINVAL);
3434 }
3435 sc = (iwp_sc_t *)arg;
3436 ic = &sc->sc_ic;
3437
3438 mutex_enter(&sc->sc_glock);
3439
3440 switch (stat) {
3441 case MAC_STAT_IFSPEED:
3442 in = ic->ic_bss;
3443 *val = ((IEEE80211_FIXED_RATE_NONE == ic->ic_fixed_rate) ?
3444 IEEE80211_RATE(in->in_txrate) :
3445 ic->ic_fixed_rate) / 2 * 1000000;
3446 break;
3447 case MAC_STAT_NOXMTBUF:
3448 *val = sc->sc_tx_nobuf;
3449 break;
3450 case MAC_STAT_NORCVBUF:
3451 *val = sc->sc_rx_nobuf;
3452 break;
3453 case MAC_STAT_IERRORS:
3454 *val = sc->sc_rx_err;
3455 break;
3456 case MAC_STAT_RBYTES:
3457 *val = ic->ic_stats.is_rx_bytes;
3458 break;
3459 case MAC_STAT_IPACKETS:
3460 *val = ic->ic_stats.is_rx_frags;
3461 break;
3462 case MAC_STAT_OBYTES:
3463 *val = ic->ic_stats.is_tx_bytes;
3464 break;
3465 case MAC_STAT_OPACKETS:
3466 *val = ic->ic_stats.is_tx_frags;
3467 break;
3468 case MAC_STAT_OERRORS:
3469 case WIFI_STAT_TX_FAILED:
3470 *val = sc->sc_tx_err;
3471 break;
3472 case WIFI_STAT_TX_RETRANS:
3473 *val = sc->sc_tx_retries;
3474 break;
3475 case WIFI_STAT_FCS_ERRORS:
3476 case WIFI_STAT_WEP_ERRORS:
3477 case WIFI_STAT_TX_FRAGS:
3478 case WIFI_STAT_MCAST_TX:
3479 case WIFI_STAT_RTS_SUCCESS:
3480 case WIFI_STAT_RTS_FAILURE:
3481 case WIFI_STAT_ACK_FAILURE:
3482 case WIFI_STAT_RX_FRAGS:
3483 case WIFI_STAT_MCAST_RX:
3484 case WIFI_STAT_RX_DUPS:
3485 mutex_exit(&sc->sc_glock);
3486 return (ieee80211_stat(ic, stat, val));
3487 default:
3488 mutex_exit(&sc->sc_glock);
3489 return (ENOTSUP);
3490 }
3491
3492 mutex_exit(&sc->sc_glock);
3493
3494 return (IWP_SUCCESS);
3495
3496 }
3497
3498 /*
3499 * invoked by GLD to start or open NIC
3500 */
3501 static int
iwp_m_start(void * arg)3502 iwp_m_start(void *arg)
3503 {
3504 iwp_sc_t *sc;
3505 ieee80211com_t *ic;
3506 int err = IWP_FAIL;
3507
3508 if (NULL == arg) {
3509 return (EINVAL);
3510 }
3511 sc = (iwp_sc_t *)arg;
3512 ic = &sc->sc_ic;
3513
3514 err = iwp_init(sc);
3515 if (err != IWP_SUCCESS) {
3516 /*
3517 * The hw init err(eg. RF is OFF). Return Success to make
3518 * the 'plumb' succeed. The iwp_thread() tries to re-init
3519 * background.
3520 */
3521 atomic_or_32(&sc->sc_flags, IWP_F_HW_ERR_RECOVER);
3522 return (IWP_SUCCESS);
3523 }
3524
3525 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3526
3527 atomic_or_32(&sc->sc_flags, IWP_F_RUNNING);
3528
3529 return (IWP_SUCCESS);
3530 }
3531
3532 /*
3533 * invoked by GLD to stop or down NIC
3534 */
3535 static void
iwp_m_stop(void * arg)3536 iwp_m_stop(void *arg)
3537 {
3538 iwp_sc_t *sc;
3539 ieee80211com_t *ic;
3540
3541 if (NULL == arg) {
3542 return;
3543 }
3544 sc = (iwp_sc_t *)arg;
3545 ic = &sc->sc_ic;
3546
3547 iwp_stop(sc);
3548
3549 /*
3550 * release buffer for calibration
3551 */
3552 iwp_release_calib_buffer(sc);
3553
3554 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3555
3556 atomic_and_32(&sc->sc_flags, ~IWP_F_HW_ERR_RECOVER);
3557 atomic_and_32(&sc->sc_flags, ~IWP_F_RATE_AUTO_CTL);
3558
3559 atomic_and_32(&sc->sc_flags, ~IWP_F_RUNNING);
3560 atomic_and_32(&sc->sc_flags, ~IWP_F_SCANNING);
3561 }
3562
3563 /*
3564 * invoked by GLD to configure NIC
3565 */
3566 static int
iwp_m_unicst(void * arg,const uint8_t * macaddr)3567 iwp_m_unicst(void *arg, const uint8_t *macaddr)
3568 {
3569 iwp_sc_t *sc;
3570 ieee80211com_t *ic;
3571 int err = IWP_SUCCESS;
3572
3573 if (NULL == arg) {
3574 return (EINVAL);
3575 }
3576 sc = (iwp_sc_t *)arg;
3577 ic = &sc->sc_ic;
3578
3579 if (!IEEE80211_ADDR_EQ(ic->ic_macaddr, macaddr)) {
3580 IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
3581 mutex_enter(&sc->sc_glock);
3582 err = iwp_config(sc);
3583 mutex_exit(&sc->sc_glock);
3584 if (err != IWP_SUCCESS) {
3585 cmn_err(CE_WARN, "iwp_m_unicst(): "
3586 "failed to configure device\n");
3587 goto fail;
3588 }
3589 }
3590
3591 return (err);
3592
3593 fail:
3594 return (err);
3595 }
3596
3597 /* ARGSUSED */
3598 static int
iwp_m_multicst(void * arg,boolean_t add,const uint8_t * m)3599 iwp_m_multicst(void *arg, boolean_t add, const uint8_t *m)
3600 {
3601 return (IWP_SUCCESS);
3602 }
3603
3604 /* ARGSUSED */
3605 static int
iwp_m_promisc(void * arg,boolean_t on)3606 iwp_m_promisc(void *arg, boolean_t on)
3607 {
3608 return (IWP_SUCCESS);
3609 }
3610
3611 /*
3612 * kernel thread to deal with exceptional situation
3613 */
3614 static void
iwp_thread(iwp_sc_t * sc)3615 iwp_thread(iwp_sc_t *sc)
3616 {
3617 ieee80211com_t *ic = &sc->sc_ic;
3618 clock_t clk;
3619 int err, n = 0, timeout = 0;
3620 uint32_t tmp;
3621 #ifdef DEBUG
3622 int times = 0;
3623 #endif
3624
3625 while (sc->sc_mf_thread_switch) {
3626 tmp = IWP_READ(sc, CSR_GP_CNTRL);
3627 if (tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) {
3628 atomic_and_32(&sc->sc_flags, ~IWP_F_RADIO_OFF);
3629 } else {
3630 atomic_or_32(&sc->sc_flags, IWP_F_RADIO_OFF);
3631 }
3632
3633 /*
3634 * If in SUSPEND or the RF is OFF, do nothing.
3635 */
3636 if (sc->sc_flags & IWP_F_RADIO_OFF) {
3637 delay(drv_usectohz(100000));
3638 continue;
3639 }
3640
3641 /*
3642 * recovery fatal error
3643 */
3644 if (ic->ic_mach &&
3645 (sc->sc_flags & IWP_F_HW_ERR_RECOVER)) {
3646
3647 IWP_DBG((IWP_DEBUG_FW, "iwp_thread(): "
3648 "try to recover fatal hw error: %d\n", times++));
3649
3650 iwp_stop(sc);
3651
3652 if (IWP_CHK_FAST_RECOVER(sc)) {
3653 /* save runtime configuration */
3654 bcopy(&sc->sc_config, &sc->sc_config_save,
3655 sizeof (sc->sc_config));
3656 } else {
3657 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3658 delay(drv_usectohz(2000000 + n*500000));
3659 }
3660
3661 err = iwp_init(sc);
3662 if (err != IWP_SUCCESS) {
3663 n++;
3664 if (n < 20) {
3665 continue;
3666 }
3667 }
3668
3669 n = 0;
3670 if (!err) {
3671 atomic_or_32(&sc->sc_flags, IWP_F_RUNNING);
3672 }
3673
3674
3675 if (!IWP_CHK_FAST_RECOVER(sc) ||
3676 iwp_fast_recover(sc) != IWP_SUCCESS) {
3677 atomic_and_32(&sc->sc_flags,
3678 ~IWP_F_HW_ERR_RECOVER);
3679
3680 delay(drv_usectohz(2000000));
3681 if (sc->sc_ostate != IEEE80211_S_INIT) {
3682 ieee80211_new_state(ic,
3683 IEEE80211_S_SCAN, 0);
3684 }
3685 }
3686 }
3687
3688 if (ic->ic_mach &&
3689 (sc->sc_flags & IWP_F_SCANNING) && sc->sc_scan_pending) {
3690 IWP_DBG((IWP_DEBUG_SCAN, "iwp_thread(): "
3691 "wait for probe response\n"));
3692
3693 sc->sc_scan_pending--;
3694 delay(drv_usectohz(200000));
3695 ieee80211_next_scan(ic);
3696 }
3697
3698 /*
3699 * rate ctl
3700 */
3701 if (ic->ic_mach &&
3702 (sc->sc_flags & IWP_F_RATE_AUTO_CTL)) {
3703 clk = ddi_get_lbolt();
3704 if (clk > sc->sc_clk + drv_usectohz(1000000)) {
3705 iwp_amrr_timeout(sc);
3706 }
3707 }
3708
3709 delay(drv_usectohz(100000));
3710
3711 mutex_enter(&sc->sc_mt_lock);
3712 if (sc->sc_tx_timer) {
3713 timeout++;
3714 if (10 == timeout) {
3715 sc->sc_tx_timer--;
3716 if (0 == sc->sc_tx_timer) {
3717 atomic_or_32(&sc->sc_flags,
3718 IWP_F_HW_ERR_RECOVER);
3719 sc->sc_ostate = IEEE80211_S_RUN;
3720 IWP_DBG((IWP_DEBUG_FW, "iwp_thread(): "
3721 "try to recover from "
3722 "send fail\n"));
3723 }
3724 timeout = 0;
3725 }
3726 }
3727 mutex_exit(&sc->sc_mt_lock);
3728 }
3729
3730 mutex_enter(&sc->sc_mt_lock);
3731 sc->sc_mf_thread = NULL;
3732 cv_signal(&sc->sc_mt_cv);
3733 mutex_exit(&sc->sc_mt_lock);
3734 }
3735
3736
3737 /*
3738 * Send a command to the ucode.
3739 */
3740 static int
iwp_cmd(iwp_sc_t * sc,int code,const void * buf,int size,int async)3741 iwp_cmd(iwp_sc_t *sc, int code, const void *buf, int size, int async)
3742 {
3743 iwp_tx_ring_t *ring = &sc->sc_txq[IWP_CMD_QUEUE_NUM];
3744 iwp_tx_desc_t *desc;
3745 iwp_cmd_t *cmd;
3746
3747 ASSERT(size <= sizeof (cmd->data));
3748 ASSERT(mutex_owned(&sc->sc_glock));
3749
3750 IWP_DBG((IWP_DEBUG_CMD, "iwp_cmd() "
3751 "code[%d]", code));
3752 desc = ring->data[ring->cur].desc;
3753 cmd = ring->data[ring->cur].cmd;
3754
3755 cmd->hdr.type = (uint8_t)code;
3756 cmd->hdr.flags = 0;
3757 cmd->hdr.qid = ring->qid;
3758 cmd->hdr.idx = ring->cur;
3759 (void) memcpy(cmd->data, buf, size);
3760 (void) memset(desc, 0, sizeof (*desc));
3761
3762 desc->val0 = 1 << 24;
3763 desc->pa[0].tb1_addr =
3764 (uint32_t)(ring->data[ring->cur].paddr_cmd & 0xffffffff);
3765 desc->pa[0].val1 = ((4 + size) << 4) & 0xfff0;
3766
3767 if (async) {
3768 sc->sc_cmd_accum++;
3769 }
3770
3771 /*
3772 * kick cmd ring XXX
3773 */
3774 sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3775 tfd_offset[ring->cur].val = 8;
3776 if (ring->cur < IWP_MAX_WIN_SIZE) {
3777 sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3778 tfd_offset[IWP_QUEUE_SIZE + ring->cur].val = 8;
3779 }
3780 ring->cur = (ring->cur + 1) % ring->count;
3781 IWP_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
3782
3783 if (async) {
3784 return (IWP_SUCCESS);
3785 } else {
3786 clock_t clk;
3787
3788 clk = ddi_get_lbolt() + drv_usectohz(2000000);
3789 while (sc->sc_cmd_flag != SC_CMD_FLG_DONE) {
3790 if (cv_timedwait(&sc->sc_cmd_cv,
3791 &sc->sc_glock, clk) < 0) {
3792 break;
3793 }
3794 }
3795
3796 if (SC_CMD_FLG_DONE == sc->sc_cmd_flag) {
3797 sc->sc_cmd_flag = SC_CMD_FLG_NONE;
3798 return (IWP_SUCCESS);
3799 } else {
3800 sc->sc_cmd_flag = SC_CMD_FLG_NONE;
3801 return (IWP_FAIL);
3802 }
3803 }
3804 }
3805
3806 /*
3807 * require ucode seting led of NIC
3808 */
3809 static void
iwp_set_led(iwp_sc_t * sc,uint8_t id,uint8_t off,uint8_t on)3810 iwp_set_led(iwp_sc_t *sc, uint8_t id, uint8_t off, uint8_t on)
3811 {
3812 iwp_led_cmd_t led;
3813
3814 led.interval = LE_32(100000); /* unit: 100ms */
3815 led.id = id;
3816 led.off = off;
3817 led.on = on;
3818
3819 (void) iwp_cmd(sc, REPLY_LEDS_CMD, &led, sizeof (led), 1);
3820 }
3821
3822 /*
3823 * necessary setting to NIC before authentication
3824 */
3825 static int
iwp_hw_set_before_auth(iwp_sc_t * sc)3826 iwp_hw_set_before_auth(iwp_sc_t *sc)
3827 {
3828 ieee80211com_t *ic = &sc->sc_ic;
3829 ieee80211_node_t *in = ic->ic_bss;
3830 int err = IWP_FAIL;
3831
3832 /*
3833 * update adapter's configuration according
3834 * the info of target AP
3835 */
3836 IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid);
3837 sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic, in->in_chan));
3838
3839 sc->sc_config.ofdm_ht_triple_stream_basic_rates = 0;
3840 sc->sc_config.ofdm_ht_dual_stream_basic_rates = 0;
3841 sc->sc_config.ofdm_ht_single_stream_basic_rates = 0;
3842
3843 if (IEEE80211_MODE_11B == ic->ic_curmode) {
3844 sc->sc_config.cck_basic_rates = 0x03;
3845 sc->sc_config.ofdm_basic_rates = 0;
3846 } else if ((in->in_chan != IEEE80211_CHAN_ANYC) &&
3847 (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) {
3848 sc->sc_config.cck_basic_rates = 0;
3849 sc->sc_config.ofdm_basic_rates = 0x15;
3850 } else { /* assume 802.11b/g */
3851 sc->sc_config.cck_basic_rates = 0x0f;
3852 sc->sc_config.ofdm_basic_rates = 0xff;
3853 }
3854
3855 sc->sc_config.flags &= ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
3856 RXON_FLG_SHORT_SLOT_MSK);
3857
3858 if (ic->ic_flags & IEEE80211_F_SHSLOT) {
3859 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_SLOT_MSK);
3860 } else {
3861 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_SLOT_MSK);
3862 }
3863
3864 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) {
3865 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
3866 } else {
3867 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_PREAMBLE_MSK);
3868 }
3869
3870 IWP_DBG((IWP_DEBUG_80211, "iwp_hw_set_before_auth(): "
3871 "config chan %d flags %x "
3872 "filter_flags %x cck %x ofdm %x"
3873 " bssid:%02x:%02x:%02x:%02x:%02x:%2x\n",
3874 LE_16(sc->sc_config.chan), LE_32(sc->sc_config.flags),
3875 LE_32(sc->sc_config.filter_flags),
3876 sc->sc_config.cck_basic_rates, sc->sc_config.ofdm_basic_rates,
3877 sc->sc_config.bssid[0], sc->sc_config.bssid[1],
3878 sc->sc_config.bssid[2], sc->sc_config.bssid[3],
3879 sc->sc_config.bssid[4], sc->sc_config.bssid[5]));
3880
3881 err = iwp_cmd(sc, REPLY_RXON, &sc->sc_config,
3882 sizeof (iwp_rxon_cmd_t), 1);
3883 if (err != IWP_SUCCESS) {
3884 cmn_err(CE_WARN, "iwp_hw_set_before_auth(): "
3885 "failed to config chan%d\n", sc->sc_config.chan);
3886 return (err);
3887 }
3888
3889 /*
3890 * add default AP node
3891 */
3892 err = iwp_add_ap_sta(sc);
3893 if (err != IWP_SUCCESS) {
3894 return (err);
3895 }
3896
3897
3898 return (err);
3899 }
3900
3901 /*
3902 * Send a scan request(assembly scan cmd) to the firmware.
3903 */
3904 static int
iwp_scan(iwp_sc_t * sc)3905 iwp_scan(iwp_sc_t *sc)
3906 {
3907 ieee80211com_t *ic = &sc->sc_ic;
3908 iwp_tx_ring_t *ring = &sc->sc_txq[IWP_CMD_QUEUE_NUM];
3909 iwp_tx_desc_t *desc;
3910 iwp_tx_data_t *data;
3911 iwp_cmd_t *cmd;
3912 iwp_scan_hdr_t *hdr;
3913 iwp_scan_chan_t chan;
3914 struct ieee80211_frame *wh;
3915 ieee80211_node_t *in = ic->ic_bss;
3916 uint8_t essid[IEEE80211_NWID_LEN+1];
3917 struct ieee80211_rateset *rs;
3918 enum ieee80211_phymode mode;
3919 uint8_t *frm;
3920 int i, pktlen, nrates;
3921
3922 data = &ring->data[ring->cur];
3923 desc = data->desc;
3924 cmd = (iwp_cmd_t *)data->dma_data.mem_va;
3925
3926 cmd->hdr.type = REPLY_SCAN_CMD;
3927 cmd->hdr.flags = 0;
3928 cmd->hdr.qid = ring->qid;
3929 cmd->hdr.idx = ring->cur | 0x40;
3930
3931 hdr = (iwp_scan_hdr_t *)cmd->data;
3932 (void) memset(hdr, 0, sizeof (iwp_scan_hdr_t));
3933 hdr->nchan = 1;
3934 hdr->quiet_time = LE_16(50);
3935 hdr->quiet_plcp_th = LE_16(1);
3936
3937 hdr->flags = LE_32(RXON_FLG_BAND_24G_MSK);
3938 hdr->rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK |
3939 (0x7 << RXON_RX_CHAIN_VALID_POS) |
3940 (0x2 << RXON_RX_CHAIN_FORCE_SEL_POS) |
3941 (0x2 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
3942
3943 hdr->tx_cmd.tx_flags = LE_32(TX_CMD_FLG_SEQ_CTL_MSK);
3944 hdr->tx_cmd.sta_id = IWP_BROADCAST_ID;
3945 hdr->tx_cmd.stop_time.life_time = LE_32(0xffffffff);
3946 hdr->tx_cmd.rate.r.rate_n_flags = LE_32(iwp_rate_to_plcp(2));
3947 hdr->tx_cmd.rate.r.rate_n_flags |=
3948 LE_32(RATE_MCS_ANT_B_MSK |RATE_MCS_CCK_MSK);
3949 hdr->direct_scan[0].len = ic->ic_des_esslen;
3950 hdr->direct_scan[0].id = IEEE80211_ELEMID_SSID;
3951
3952 hdr->filter_flags = LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
3953 RXON_FILTER_BCON_AWARE_MSK);
3954
3955 if (ic->ic_des_esslen) {
3956 bcopy(ic->ic_des_essid, essid, ic->ic_des_esslen);
3957 essid[ic->ic_des_esslen] = '\0';
3958 IWP_DBG((IWP_DEBUG_SCAN, "iwp_scan(): "
3959 "directed scan %s\n", essid));
3960
3961 bcopy(ic->ic_des_essid, hdr->direct_scan[0].ssid,
3962 ic->ic_des_esslen);
3963 } else {
3964 bzero(hdr->direct_scan[0].ssid,
3965 sizeof (hdr->direct_scan[0].ssid));
3966 }
3967
3968 /*
3969 * a probe request frame is required after the REPLY_SCAN_CMD
3970 */
3971 wh = (struct ieee80211_frame *)(hdr + 1);
3972 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
3973 IEEE80211_FC0_SUBTYPE_PROBE_REQ;
3974 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
3975 (void) memset(wh->i_addr1, 0xff, 6);
3976 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_macaddr);
3977 (void) memset(wh->i_addr3, 0xff, 6);
3978 *(uint16_t *)&wh->i_dur[0] = 0;
3979 *(uint16_t *)&wh->i_seq[0] = 0;
3980
3981 frm = (uint8_t *)(wh + 1);
3982
3983 /*
3984 * essid IE
3985 */
3986 if (in->in_esslen) {
3987 bcopy(in->in_essid, essid, in->in_esslen);
3988 essid[in->in_esslen] = '\0';
3989 IWP_DBG((IWP_DEBUG_SCAN, "iwp_scan(): "
3990 "probe with ESSID %s\n",
3991 essid));
3992 }
3993 *frm++ = IEEE80211_ELEMID_SSID;
3994 *frm++ = in->in_esslen;
3995 (void) memcpy(frm, in->in_essid, in->in_esslen);
3996 frm += in->in_esslen;
3997
3998 mode = ieee80211_chan2mode(ic, ic->ic_curchan);
3999 rs = &ic->ic_sup_rates[mode];
4000
4001 /*
4002 * supported rates IE
4003 */
4004 *frm++ = IEEE80211_ELEMID_RATES;
4005 nrates = rs->ir_nrates;
4006 if (nrates > IEEE80211_RATE_SIZE) {
4007 nrates = IEEE80211_RATE_SIZE;
4008 }
4009
4010 *frm++ = (uint8_t)nrates;
4011 (void) memcpy(frm, rs->ir_rates, nrates);
4012 frm += nrates;
4013
4014 /*
4015 * supported xrates IE
4016 */
4017 if (rs->ir_nrates > IEEE80211_RATE_SIZE) {
4018 nrates = rs->ir_nrates - IEEE80211_RATE_SIZE;
4019 *frm++ = IEEE80211_ELEMID_XRATES;
4020 *frm++ = (uint8_t)nrates;
4021 (void) memcpy(frm, rs->ir_rates + IEEE80211_RATE_SIZE, nrates);
4022 frm += nrates;
4023 }
4024
4025 /*
4026 * optionnal IE (usually for wpa)
4027 */
4028 if (ic->ic_opt_ie != NULL) {
4029 (void) memcpy(frm, ic->ic_opt_ie, ic->ic_opt_ie_len);
4030 frm += ic->ic_opt_ie_len;
4031 }
4032
4033 /* setup length of probe request */
4034 hdr->tx_cmd.len = LE_16(_PTRDIFF(frm, wh));
4035 hdr->len = LE_16(hdr->nchan * sizeof (iwp_scan_chan_t) +
4036 LE_16(hdr->tx_cmd.len) + sizeof (iwp_scan_hdr_t));
4037
4038 /*
4039 * the attribute of the scan channels are required after the probe
4040 * request frame.
4041 */
4042 for (i = 1; i <= hdr->nchan; i++) {
4043 if (ic->ic_des_esslen) {
4044 chan.type = LE_32(3);
4045 } else {
4046 chan.type = LE_32(1);
4047 }
4048
4049 chan.chan = LE_16(ieee80211_chan2ieee(ic, ic->ic_curchan));
4050 chan.tpc.tx_gain = 0x28;
4051 chan.tpc.dsp_atten = 110;
4052 chan.active_dwell = LE_16(50);
4053 chan.passive_dwell = LE_16(120);
4054
4055 bcopy(&chan, frm, sizeof (iwp_scan_chan_t));
4056 frm += sizeof (iwp_scan_chan_t);
4057 }
4058
4059 pktlen = _PTRDIFF(frm, cmd);
4060
4061 (void) memset(desc, 0, sizeof (*desc));
4062 desc->val0 = 1 << 24;
4063 desc->pa[0].tb1_addr =
4064 (uint32_t)(data->dma_data.cookie.dmac_address & 0xffffffff);
4065 desc->pa[0].val1 = (pktlen << 4) & 0xfff0;
4066
4067 /*
4068 * maybe for cmd, filling the byte cnt table is not necessary.
4069 * anyway, we fill it here.
4070 */
4071 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]
4072 .tfd_offset[ring->cur].val = 8;
4073 if (ring->cur < IWP_MAX_WIN_SIZE) {
4074 sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
4075 tfd_offset[IWP_QUEUE_SIZE + ring->cur].val = 8;
4076 }
4077
4078 /*
4079 * kick cmd ring
4080 */
4081 ring->cur = (ring->cur + 1) % ring->count;
4082 IWP_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
4083
4084 return (IWP_SUCCESS);
4085 }
4086
4087 /*
4088 * configure NIC by using ucode commands after loading ucode.
4089 */
4090 static int
iwp_config(iwp_sc_t * sc)4091 iwp_config(iwp_sc_t *sc)
4092 {
4093 ieee80211com_t *ic = &sc->sc_ic;
4094 iwp_powertable_cmd_t powertable;
4095 iwp_bt_cmd_t bt;
4096 iwp_add_sta_t node;
4097 iwp_rem_sta_t rm_sta;
4098 const uint8_t bcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
4099 int err = IWP_FAIL;
4100
4101 /*
4102 * set power mode. Disable power management at present, do it later
4103 */
4104 (void) memset(&powertable, 0, sizeof (powertable));
4105 powertable.flags = LE_16(0x8);
4106 err = iwp_cmd(sc, POWER_TABLE_CMD, &powertable,
4107 sizeof (powertable), 0);
4108 if (err != IWP_SUCCESS) {
4109 cmn_err(CE_WARN, "iwp_config(): "
4110 "failed to set power mode\n");
4111 return (err);
4112 }
4113
4114 /*
4115 * configure bt coexistence
4116 */
4117 (void) memset(&bt, 0, sizeof (bt));
4118 bt.flags = 3;
4119 bt.lead_time = 0xaa;
4120 bt.max_kill = 1;
4121 err = iwp_cmd(sc, REPLY_BT_CONFIG, &bt,
4122 sizeof (bt), 0);
4123 if (err != IWP_SUCCESS) {
4124 cmn_err(CE_WARN, "iwp_config(): "
4125 "failed to configurate bt coexistence\n");
4126 return (err);
4127 }
4128
4129 /*
4130 * configure rxon
4131 */
4132 (void) memset(&sc->sc_config, 0, sizeof (iwp_rxon_cmd_t));
4133 IEEE80211_ADDR_COPY(sc->sc_config.node_addr, ic->ic_macaddr);
4134 IEEE80211_ADDR_COPY(sc->sc_config.wlap_bssid, ic->ic_macaddr);
4135 sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic, ic->ic_curchan));
4136 sc->sc_config.flags = LE_32(RXON_FLG_BAND_24G_MSK);
4137 sc->sc_config.flags &= LE_32(~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
4138 RXON_FLG_CHANNEL_MODE_PURE_40_MSK));
4139
4140 switch (ic->ic_opmode) {
4141 case IEEE80211_M_STA:
4142 sc->sc_config.dev_type = RXON_DEV_TYPE_ESS;
4143 sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
4144 RXON_FILTER_DIS_DECRYPT_MSK |
4145 RXON_FILTER_DIS_GRP_DECRYPT_MSK);
4146 break;
4147 case IEEE80211_M_IBSS:
4148 case IEEE80211_M_AHDEMO:
4149 sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS;
4150
4151 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
4152 sc->sc_config.filter_flags = LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
4153 RXON_FILTER_DIS_DECRYPT_MSK |
4154 RXON_FILTER_DIS_GRP_DECRYPT_MSK);
4155 break;
4156 case IEEE80211_M_HOSTAP:
4157 sc->sc_config.dev_type = RXON_DEV_TYPE_AP;
4158 break;
4159 case IEEE80211_M_MONITOR:
4160 sc->sc_config.dev_type = RXON_DEV_TYPE_SNIFFER;
4161 sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
4162 RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
4163 break;
4164 }
4165
4166 /*
4167 * Support all CCK rates.
4168 */
4169 sc->sc_config.cck_basic_rates = 0x0f;
4170
4171 /*
4172 * Support all OFDM rates.
4173 */
4174 sc->sc_config.ofdm_basic_rates = 0xff;
4175
4176 sc->sc_config.rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK |
4177 (0x7 << RXON_RX_CHAIN_VALID_POS) |
4178 (0x2 << RXON_RX_CHAIN_FORCE_SEL_POS) |
4179 (0x2 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
4180
4181 err = iwp_cmd(sc, REPLY_RXON, &sc->sc_config,
4182 sizeof (iwp_rxon_cmd_t), 0);
4183 if (err != IWP_SUCCESS) {
4184 cmn_err(CE_WARN, "iwp_config(): "
4185 "failed to set configure command\n");
4186 return (err);
4187 }
4188
4189 /*
4190 * remove all nodes in NIC
4191 */
4192 (void) memset(&rm_sta, 0, sizeof (rm_sta));
4193 rm_sta.num_sta = 1;
4194 (void) memcpy(rm_sta.addr, bcast, 6);
4195
4196 err = iwp_cmd(sc, REPLY_REMOVE_STA, &rm_sta, sizeof (iwp_rem_sta_t), 0);
4197 if (err != IWP_SUCCESS) {
4198 cmn_err(CE_WARN, "iwp_config(): "
4199 "failed to remove broadcast node in hardware.\n");
4200 return (err);
4201 }
4202
4203 /*
4204 * add broadcast node so that we can send broadcast frame
4205 */
4206 (void) memset(&node, 0, sizeof (node));
4207 (void) memset(node.sta.addr, 0xff, 6);
4208 node.mode = 0;
4209 node.sta.sta_id = IWP_BROADCAST_ID;
4210 node.station_flags = 0;
4211
4212 err = iwp_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 0);
4213 if (err != IWP_SUCCESS) {
4214 cmn_err(CE_WARN, "iwp_config(): "
4215 "failed to add broadcast node\n");
4216 return (err);
4217 }
4218
4219 return (err);
4220 }
4221
4222 /*
4223 * quiesce(9E) entry point.
4224 * This function is called when the system is single-threaded at high
4225 * PIL with preemption disabled. Therefore, this function must not be
4226 * blocked.
4227 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
4228 * DDI_FAILURE indicates an error condition and should almost never happen.
4229 */
4230 static int
iwp_quiesce(dev_info_t * dip)4231 iwp_quiesce(dev_info_t *dip)
4232 {
4233 iwp_sc_t *sc;
4234
4235 sc = ddi_get_soft_state(iwp_soft_state_p, ddi_get_instance(dip));
4236 if (NULL == sc) {
4237 return (DDI_FAILURE);
4238 }
4239
4240 #ifdef DEBUG
4241 /* by pass any messages, if it's quiesce */
4242 iwp_dbg_flags = 0;
4243 #endif
4244
4245 /*
4246 * No more blocking is allowed while we are in the
4247 * quiesce(9E) entry point.
4248 */
4249 atomic_or_32(&sc->sc_flags, IWP_F_QUIESCED);
4250
4251 /*
4252 * Disable and mask all interrupts.
4253 */
4254 iwp_stop(sc);
4255
4256 return (DDI_SUCCESS);
4257 }
4258
4259 static void
iwp_stop_master(iwp_sc_t * sc)4260 iwp_stop_master(iwp_sc_t *sc)
4261 {
4262 uint32_t tmp;
4263 int n;
4264
4265 tmp = IWP_READ(sc, CSR_RESET);
4266 IWP_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_STOP_MASTER);
4267
4268 tmp = IWP_READ(sc, CSR_GP_CNTRL);
4269 if ((tmp & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE) ==
4270 CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE) {
4271 return;
4272 }
4273
4274 for (n = 0; n < 2000; n++) {
4275 if (IWP_READ(sc, CSR_RESET) &
4276 CSR_RESET_REG_FLAG_MASTER_DISABLED) {
4277 break;
4278 }
4279 DELAY(1000);
4280 }
4281
4282 #ifdef DEBUG
4283 if (2000 == n) {
4284 IWP_DBG((IWP_DEBUG_HW, "iwp_stop_master(): "
4285 "timeout waiting for master stop\n"));
4286 }
4287 #endif
4288 }
4289
4290 static int
iwp_power_up(iwp_sc_t * sc)4291 iwp_power_up(iwp_sc_t *sc)
4292 {
4293 uint32_t tmp;
4294
4295 iwp_mac_access_enter(sc);
4296 tmp = iwp_reg_read(sc, ALM_APMG_PS_CTL);
4297 tmp &= ~APMG_PS_CTRL_REG_MSK_POWER_SRC;
4298 tmp |= APMG_PS_CTRL_REG_VAL_POWER_SRC_VMAIN;
4299 iwp_reg_write(sc, ALM_APMG_PS_CTL, tmp);
4300 iwp_mac_access_exit(sc);
4301
4302 DELAY(5000);
4303 return (IWP_SUCCESS);
4304 }
4305
4306 /*
4307 * hardware initialization
4308 */
4309 static int
iwp_preinit(iwp_sc_t * sc)4310 iwp_preinit(iwp_sc_t *sc)
4311 {
4312 int n;
4313 uint8_t vlink;
4314 uint16_t radio_cfg;
4315 uint32_t tmp;
4316
4317 /*
4318 * clear any pending interrupts
4319 */
4320 IWP_WRITE(sc, CSR_INT, 0xffffffff);
4321
4322 tmp = IWP_READ(sc, CSR_GIO_CHICKEN_BITS);
4323 IWP_WRITE(sc, CSR_GIO_CHICKEN_BITS,
4324 tmp | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
4325
4326 tmp = IWP_READ(sc, CSR_GP_CNTRL);
4327 IWP_WRITE(sc, CSR_GP_CNTRL, tmp | CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
4328
4329 /*
4330 * wait for clock ready
4331 */
4332 for (n = 0; n < 1000; n++) {
4333 if (IWP_READ(sc, CSR_GP_CNTRL) &
4334 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
4335 break;
4336 }
4337 DELAY(10);
4338 }
4339
4340 if (1000 == n) {
4341 return (ETIMEDOUT);
4342 }
4343
4344 iwp_mac_access_enter(sc);
4345
4346 iwp_reg_write(sc, ALM_APMG_CLK_EN, APMG_CLK_REG_VAL_DMA_CLK_RQT);
4347
4348 DELAY(20);
4349 tmp = iwp_reg_read(sc, ALM_APMG_PCIDEV_STT);
4350 iwp_reg_write(sc, ALM_APMG_PCIDEV_STT, tmp |
4351 APMG_DEV_STATE_REG_VAL_L1_ACTIVE_DISABLE);
4352 iwp_mac_access_exit(sc);
4353
4354 radio_cfg = IWP_READ_EEP_SHORT(sc, EEP_SP_RADIO_CONFIGURATION);
4355 if (SP_RADIO_TYPE_MSK(radio_cfg) < SP_RADIO_TYPE_MAX) {
4356 tmp = IWP_READ(sc, CSR_HW_IF_CONFIG_REG);
4357 IWP_WRITE(sc, CSR_HW_IF_CONFIG_REG,
4358 tmp | SP_RADIO_TYPE_MSK(radio_cfg) |
4359 SP_RADIO_STEP_MSK(radio_cfg) |
4360 SP_RADIO_DASH_MSK(radio_cfg));
4361 } else {
4362 cmn_err(CE_WARN, "iwp_preinit(): "
4363 "radio configuration information in eeprom is wrong\n");
4364 return (IWP_FAIL);
4365 }
4366
4367
4368 IWP_WRITE(sc, CSR_INT_COALESCING, 512 / 32);
4369
4370 (void) iwp_power_up(sc);
4371
4372 if ((sc->sc_rev & 0x80) == 0x80 && (sc->sc_rev & 0x7f) < 8) {
4373 tmp = ddi_get32(sc->sc_cfg_handle,
4374 (uint32_t *)(sc->sc_cfg_base + 0xe8));
4375 ddi_put32(sc->sc_cfg_handle,
4376 (uint32_t *)(sc->sc_cfg_base + 0xe8),
4377 tmp & ~(1 << 11));
4378 }
4379
4380 vlink = ddi_get8(sc->sc_cfg_handle,
4381 (uint8_t *)(sc->sc_cfg_base + 0xf0));
4382 ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base + 0xf0),
4383 vlink & ~2);
4384
4385 tmp = IWP_READ(sc, CSR_HW_IF_CONFIG_REG);
4386 tmp |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
4387 CSR_HW_IF_CONFIG_REG_BIT_MAC_SI;
4388 IWP_WRITE(sc, CSR_HW_IF_CONFIG_REG, tmp);
4389
4390 /*
4391 * make sure power supply on each part of the hardware
4392 */
4393 iwp_mac_access_enter(sc);
4394 tmp = iwp_reg_read(sc, ALM_APMG_PS_CTL);
4395 tmp |= APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ;
4396 iwp_reg_write(sc, ALM_APMG_PS_CTL, tmp);
4397 DELAY(5);
4398
4399 tmp = iwp_reg_read(sc, ALM_APMG_PS_CTL);
4400 tmp &= ~APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ;
4401 iwp_reg_write(sc, ALM_APMG_PS_CTL, tmp);
4402 iwp_mac_access_exit(sc);
4403
4404 if (PA_TYPE_MIX == sc->sc_chip_param.pa_type) {
4405 IWP_WRITE(sc, CSR_GP_DRIVER_REG,
4406 CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_MIX);
4407 }
4408
4409 if (PA_TYPE_INTER == sc->sc_chip_param.pa_type) {
4410
4411 IWP_WRITE(sc, CSR_GP_DRIVER_REG,
4412 CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
4413 }
4414
4415 return (IWP_SUCCESS);
4416 }
4417
4418 /*
4419 * set up semphore flag to own EEPROM
4420 */
4421 static int
iwp_eep_sem_down(iwp_sc_t * sc)4422 iwp_eep_sem_down(iwp_sc_t *sc)
4423 {
4424 int count1, count2;
4425 uint32_t tmp;
4426
4427 for (count1 = 0; count1 < 1000; count1++) {
4428 tmp = IWP_READ(sc, CSR_HW_IF_CONFIG_REG);
4429 IWP_WRITE(sc, CSR_HW_IF_CONFIG_REG,
4430 tmp | CSR_HW_IF_CONFIG_REG_EEP_SEM);
4431
4432 for (count2 = 0; count2 < 2; count2++) {
4433 if (IWP_READ(sc, CSR_HW_IF_CONFIG_REG) &
4434 CSR_HW_IF_CONFIG_REG_EEP_SEM) {
4435 return (IWP_SUCCESS);
4436 }
4437 DELAY(10000);
4438 }
4439 }
4440 return (IWP_FAIL);
4441 }
4442
4443 /*
4444 * reset semphore flag to release EEPROM
4445 */
4446 static void
iwp_eep_sem_up(iwp_sc_t * sc)4447 iwp_eep_sem_up(iwp_sc_t *sc)
4448 {
4449 uint32_t tmp;
4450
4451 tmp = IWP_READ(sc, CSR_HW_IF_CONFIG_REG);
4452 IWP_WRITE(sc, CSR_HW_IF_CONFIG_REG,
4453 tmp & (~CSR_HW_IF_CONFIG_REG_EEP_SEM));
4454 }
4455
4456 /*
4457 * This function read all infomation from eeprom
4458 */
4459 static int
iwp_eep_load(iwp_sc_t * sc)4460 iwp_eep_load(iwp_sc_t *sc)
4461 {
4462 int i, rr;
4463 uint32_t rv, tmp, eep_gp;
4464 uint16_t addr, eep_sz = sizeof (sc->sc_eep_map);
4465 uint16_t *eep_p = (uint16_t *)&sc->sc_eep_map;
4466
4467 /*
4468 * read eeprom gp register in CSR
4469 */
4470 eep_gp = IWP_READ(sc, CSR_EEPROM_GP);
4471 if ((eep_gp & CSR_EEPROM_GP_VALID_MSK) ==
4472 CSR_EEPROM_GP_BAD_SIGNATURE) {
4473 IWP_DBG((IWP_DEBUG_EEPROM, "iwp_eep_load(): "
4474 "not find eeprom\n"));
4475 return (IWP_FAIL);
4476 }
4477
4478 rr = iwp_eep_sem_down(sc);
4479 if (rr != 0) {
4480 IWP_DBG((IWP_DEBUG_EEPROM, "iwp_eep_load(): "
4481 "driver failed to own EEPROM\n"));
4482 return (IWP_FAIL);
4483 }
4484
4485 for (addr = 0; addr < eep_sz; addr += 2) {
4486 IWP_WRITE(sc, CSR_EEPROM_REG, addr<<1);
4487 tmp = IWP_READ(sc, CSR_EEPROM_REG);
4488 IWP_WRITE(sc, CSR_EEPROM_REG, tmp & ~(0x2));
4489
4490 for (i = 0; i < 10; i++) {
4491 rv = IWP_READ(sc, CSR_EEPROM_REG);
4492 if (rv & 1) {
4493 break;
4494 }
4495 DELAY(10);
4496 }
4497
4498 if (!(rv & 1)) {
4499 IWP_DBG((IWP_DEBUG_EEPROM, "iwp_eep_load(): "
4500 "time out when read eeprome\n"));
4501 iwp_eep_sem_up(sc);
4502 return (IWP_FAIL);
4503 }
4504
4505 eep_p[addr/2] = LE_16(rv >> 16);
4506 }
4507
4508 iwp_eep_sem_up(sc);
4509 return (IWP_SUCCESS);
4510 }
4511
4512 /*
4513 * initialize mac address in ieee80211com_t struct
4514 */
4515 static void
iwp_get_mac_from_eep(iwp_sc_t * sc)4516 iwp_get_mac_from_eep(iwp_sc_t *sc)
4517 {
4518 ieee80211com_t *ic = &sc->sc_ic;
4519
4520 IEEE80211_ADDR_COPY(ic->ic_macaddr, &sc->sc_eep_map[EEP_MAC_ADDRESS]);
4521
4522 IWP_DBG((IWP_DEBUG_EEPROM, "iwp_get_mac_from_eep(): "
4523 "mac:%2x:%2x:%2x:%2x:%2x:%2x\n",
4524 ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2],
4525 ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5]));
4526 }
4527
4528 /*
4529 * main initialization function
4530 */
4531 static int
iwp_init(iwp_sc_t * sc)4532 iwp_init(iwp_sc_t *sc)
4533 {
4534 int err = IWP_FAIL;
4535 clock_t clk;
4536
4537 /*
4538 * release buffer for calibration
4539 */
4540 iwp_release_calib_buffer(sc);
4541
4542 mutex_enter(&sc->sc_glock);
4543 atomic_and_32(&sc->sc_flags, ~IWP_F_FW_INIT);
4544
4545 err = iwp_init_common(sc);
4546 if (err != IWP_SUCCESS) {
4547 mutex_exit(&sc->sc_glock);
4548 return (IWP_FAIL);
4549 }
4550
4551 /*
4552 * backup ucode data part for future use.
4553 */
4554 (void) memcpy(sc->sc_dma_fw_data_bak.mem_va,
4555 sc->sc_dma_fw_data.mem_va,
4556 sc->sc_dma_fw_data.alength);
4557
4558 /* load firmware init segment into NIC */
4559 err = iwp_load_init_firmware(sc);
4560 if (err != IWP_SUCCESS) {
4561 cmn_err(CE_WARN, "iwp_init(): "
4562 "failed to setup init firmware\n");
4563 mutex_exit(&sc->sc_glock);
4564 return (IWP_FAIL);
4565 }
4566
4567 /*
4568 * now press "execute" start running
4569 */
4570 IWP_WRITE(sc, CSR_RESET, 0);
4571
4572 clk = ddi_get_lbolt() + drv_usectohz(1000000);
4573 while (!(sc->sc_flags & IWP_F_FW_INIT)) {
4574 if (cv_timedwait(&sc->sc_ucode_cv,
4575 &sc->sc_glock, clk) < 0) {
4576 break;
4577 }
4578 }
4579
4580 if (!(sc->sc_flags & IWP_F_FW_INIT)) {
4581 cmn_err(CE_WARN, "iwp_init(): "
4582 "failed to process init alive.\n");
4583 mutex_exit(&sc->sc_glock);
4584 return (IWP_FAIL);
4585 }
4586
4587 mutex_exit(&sc->sc_glock);
4588
4589 /*
4590 * stop chipset for initializing chipset again
4591 */
4592 iwp_stop(sc);
4593
4594 mutex_enter(&sc->sc_glock);
4595 atomic_and_32(&sc->sc_flags, ~IWP_F_FW_INIT);
4596
4597 err = iwp_init_common(sc);
4598 if (err != IWP_SUCCESS) {
4599 mutex_exit(&sc->sc_glock);
4600 return (IWP_FAIL);
4601 }
4602
4603 /*
4604 * load firmware run segment into NIC
4605 */
4606 err = iwp_load_run_firmware(sc);
4607 if (err != IWP_SUCCESS) {
4608 cmn_err(CE_WARN, "iwp_init(): "
4609 "failed to setup run firmware\n");
4610 mutex_exit(&sc->sc_glock);
4611 return (IWP_FAIL);
4612 }
4613
4614 /*
4615 * now press "execute" start running
4616 */
4617 IWP_WRITE(sc, CSR_RESET, 0);
4618
4619 clk = ddi_get_lbolt() + drv_usectohz(1000000);
4620 while (!(sc->sc_flags & IWP_F_FW_INIT)) {
4621 if (cv_timedwait(&sc->sc_ucode_cv,
4622 &sc->sc_glock, clk) < 0) {
4623 break;
4624 }
4625 }
4626
4627 if (!(sc->sc_flags & IWP_F_FW_INIT)) {
4628 cmn_err(CE_WARN, "iwp_init(): "
4629 "failed to process runtime alive.\n");
4630 mutex_exit(&sc->sc_glock);
4631 return (IWP_FAIL);
4632 }
4633
4634 mutex_exit(&sc->sc_glock);
4635
4636 DELAY(1000);
4637
4638 mutex_enter(&sc->sc_glock);
4639 atomic_and_32(&sc->sc_flags, ~IWP_F_FW_INIT);
4640
4641 /*
4642 * at this point, the firmware is loaded OK, then config the hardware
4643 * with the ucode API, including rxon, txpower, etc.
4644 */
4645 err = iwp_config(sc);
4646 if (err) {
4647 cmn_err(CE_WARN, "iwp_init(): "
4648 "failed to configure device\n");
4649 mutex_exit(&sc->sc_glock);
4650 return (IWP_FAIL);
4651 }
4652
4653 /*
4654 * at this point, hardware may receive beacons :)
4655 */
4656 mutex_exit(&sc->sc_glock);
4657 return (IWP_SUCCESS);
4658 }
4659
4660 /*
4661 * stop or disable NIC
4662 */
4663 static void
iwp_stop(iwp_sc_t * sc)4664 iwp_stop(iwp_sc_t *sc)
4665 {
4666 uint32_t tmp;
4667 int i;
4668
4669 /* by pass if it's quiesced */
4670 if (!(sc->sc_flags & IWP_F_QUIESCED)) {
4671 mutex_enter(&sc->sc_glock);
4672 }
4673
4674 IWP_WRITE(sc, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
4675 /*
4676 * disable interrupts
4677 */
4678 IWP_WRITE(sc, CSR_INT_MASK, 0);
4679 IWP_WRITE(sc, CSR_INT, CSR_INI_SET_MASK);
4680 IWP_WRITE(sc, CSR_FH_INT_STATUS, 0xffffffff);
4681
4682 /*
4683 * reset all Tx rings
4684 */
4685 for (i = 0; i < IWP_NUM_QUEUES; i++) {
4686 iwp_reset_tx_ring(sc, &sc->sc_txq[i]);
4687 }
4688
4689 /*
4690 * reset Rx ring
4691 */
4692 iwp_reset_rx_ring(sc);
4693
4694 iwp_mac_access_enter(sc);
4695 iwp_reg_write(sc, ALM_APMG_CLK_DIS, APMG_CLK_REG_VAL_DMA_CLK_RQT);
4696 iwp_mac_access_exit(sc);
4697
4698 DELAY(5);
4699
4700 iwp_stop_master(sc);
4701
4702 mutex_enter(&sc->sc_mt_lock);
4703 sc->sc_tx_timer = 0;
4704 mutex_exit(&sc->sc_mt_lock);
4705
4706 tmp = IWP_READ(sc, CSR_RESET);
4707 IWP_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_SW_RESET);
4708
4709 /* by pass if it's quiesced */
4710 if (!(sc->sc_flags & IWP_F_QUIESCED)) {
4711 mutex_exit(&sc->sc_glock);
4712 }
4713 }
4714
4715 /*
4716 * Naive implementation of the Adaptive Multi Rate Retry algorithm:
4717 * "IEEE 802.11 Rate Adaptation: A Practical Approach"
4718 * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
4719 * INRIA Sophia - Projet Planete
4720 * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
4721 */
4722 #define is_success(amrr) \
4723 ((amrr)->retrycnt < (amrr)->txcnt / 10)
4724 #define is_failure(amrr) \
4725 ((amrr)->retrycnt > (amrr)->txcnt / 3)
4726 #define is_enough(amrr) \
4727 ((amrr)->txcnt > 200)
4728 #define not_very_few(amrr) \
4729 ((amrr)->txcnt > 40)
4730 #define is_min_rate(in) \
4731 (0 == (in)->in_txrate)
4732 #define is_max_rate(in) \
4733 ((in)->in_rates.ir_nrates - 1 == (in)->in_txrate)
4734 #define increase_rate(in) \
4735 ((in)->in_txrate++)
4736 #define decrease_rate(in) \
4737 ((in)->in_txrate--)
4738 #define reset_cnt(amrr) \
4739 { (amrr)->txcnt = (amrr)->retrycnt = 0; }
4740
4741 #define IWP_AMRR_MIN_SUCCESS_THRESHOLD 1
4742 #define IWP_AMRR_MAX_SUCCESS_THRESHOLD 15
4743
4744 static void
iwp_amrr_init(iwp_amrr_t * amrr)4745 iwp_amrr_init(iwp_amrr_t *amrr)
4746 {
4747 amrr->success = 0;
4748 amrr->recovery = 0;
4749 amrr->txcnt = amrr->retrycnt = 0;
4750 amrr->success_threshold = IWP_AMRR_MIN_SUCCESS_THRESHOLD;
4751 }
4752
4753 static void
iwp_amrr_timeout(iwp_sc_t * sc)4754 iwp_amrr_timeout(iwp_sc_t *sc)
4755 {
4756 ieee80211com_t *ic = &sc->sc_ic;
4757
4758 IWP_DBG((IWP_DEBUG_RATECTL, "iwp_amrr_timeout(): "
4759 "enter\n"));
4760
4761 if (IEEE80211_M_STA == ic->ic_opmode) {
4762 iwp_amrr_ratectl(NULL, ic->ic_bss);
4763 } else {
4764 ieee80211_iterate_nodes(&ic->ic_sta, iwp_amrr_ratectl, NULL);
4765 }
4766
4767 sc->sc_clk = ddi_get_lbolt();
4768 }
4769
4770 /* ARGSUSED */
4771 static void
iwp_amrr_ratectl(void * arg,ieee80211_node_t * in)4772 iwp_amrr_ratectl(void *arg, ieee80211_node_t *in)
4773 {
4774 iwp_amrr_t *amrr = (iwp_amrr_t *)in;
4775 int need_change = 0;
4776
4777 if (is_success(amrr) && is_enough(amrr)) {
4778 amrr->success++;
4779 if (amrr->success >= amrr->success_threshold &&
4780 !is_max_rate(in)) {
4781 amrr->recovery = 1;
4782 amrr->success = 0;
4783 increase_rate(in);
4784 IWP_DBG((IWP_DEBUG_RATECTL, "iwp_amrr_ratectl(): "
4785 "AMRR increasing rate %d "
4786 "(txcnt=%d retrycnt=%d)\n",
4787 in->in_txrate, amrr->txcnt,
4788 amrr->retrycnt));
4789 need_change = 1;
4790 } else {
4791 amrr->recovery = 0;
4792 }
4793 } else if (not_very_few(amrr) && is_failure(amrr)) {
4794 amrr->success = 0;
4795 if (!is_min_rate(in)) {
4796 if (amrr->recovery) {
4797 amrr->success_threshold++;
4798 if (amrr->success_threshold >
4799 IWP_AMRR_MAX_SUCCESS_THRESHOLD) {
4800 amrr->success_threshold =
4801 IWP_AMRR_MAX_SUCCESS_THRESHOLD;
4802 }
4803 } else {
4804 amrr->success_threshold =
4805 IWP_AMRR_MIN_SUCCESS_THRESHOLD;
4806 }
4807 decrease_rate(in);
4808 IWP_DBG((IWP_DEBUG_RATECTL, "iwp_amrr_ratectl(): "
4809 "AMRR decreasing rate %d "
4810 "(txcnt=%d retrycnt=%d)\n",
4811 in->in_txrate, amrr->txcnt,
4812 amrr->retrycnt));
4813 need_change = 1;
4814 }
4815 amrr->recovery = 0; /* paper is incorrect */
4816 }
4817
4818 if (is_enough(amrr) || need_change) {
4819 reset_cnt(amrr);
4820 }
4821 }
4822
4823 /*
4824 * translate indirect address in eeprom to direct address
4825 * in eeprom and return address of entry whos indirect address
4826 * is indi_addr
4827 */
4828 static uint8_t *
iwp_eep_addr_trans(iwp_sc_t * sc,uint32_t indi_addr)4829 iwp_eep_addr_trans(iwp_sc_t *sc, uint32_t indi_addr)
4830 {
4831 uint32_t di_addr;
4832 uint16_t temp;
4833
4834 if (!(indi_addr & INDIRECT_ADDRESS)) {
4835 di_addr = indi_addr;
4836 return (&sc->sc_eep_map[di_addr]);
4837 }
4838
4839 switch (indi_addr & INDIRECT_TYPE_MSK) {
4840 case INDIRECT_GENERAL:
4841 temp = IWP_READ_EEP_SHORT(sc, EEP_LINK_GENERAL);
4842 break;
4843 case INDIRECT_HOST:
4844 temp = IWP_READ_EEP_SHORT(sc, EEP_LINK_HOST);
4845 break;
4846 case INDIRECT_REGULATORY:
4847 temp = IWP_READ_EEP_SHORT(sc, EEP_LINK_REGULATORY);
4848 break;
4849 case INDIRECT_CALIBRATION:
4850 temp = IWP_READ_EEP_SHORT(sc, EEP_LINK_CALIBRATION);
4851 break;
4852 case INDIRECT_PROCESS_ADJST:
4853 temp = IWP_READ_EEP_SHORT(sc, EEP_LINK_PROCESS_ADJST);
4854 break;
4855 case INDIRECT_OTHERS:
4856 temp = IWP_READ_EEP_SHORT(sc, EEP_LINK_OTHERS);
4857 break;
4858 default:
4859 temp = 0;
4860 cmn_err(CE_WARN, "iwp_eep_addr_trans(): "
4861 "incorrect indirect eeprom address.\n");
4862 break;
4863 }
4864
4865 di_addr = (indi_addr & ADDRESS_MSK) + (temp << 1);
4866
4867 return (&sc->sc_eep_map[di_addr]);
4868 }
4869
4870 /*
4871 * loade a section of ucode into NIC
4872 */
4873 static int
iwp_put_seg_fw(iwp_sc_t * sc,uint32_t addr_s,uint32_t addr_d,uint32_t len)4874 iwp_put_seg_fw(iwp_sc_t *sc, uint32_t addr_s, uint32_t addr_d, uint32_t len)
4875 {
4876
4877 iwp_mac_access_enter(sc);
4878
4879 IWP_WRITE(sc, IWP_FH_TCSR_CHNL_TX_CONFIG_REG(IWP_FH_SRVC_CHNL),
4880 IWP_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);
4881
4882 IWP_WRITE(sc, IWP_FH_SRVC_CHNL_SRAM_ADDR_REG(IWP_FH_SRVC_CHNL), addr_d);
4883
4884 IWP_WRITE(sc, IWP_FH_TFDIB_CTRL0_REG(IWP_FH_SRVC_CHNL),
4885 (addr_s & FH_MEM_TFDIB_DRAM_ADDR_LSB_MASK));
4886
4887 IWP_WRITE(sc, IWP_FH_TFDIB_CTRL1_REG(IWP_FH_SRVC_CHNL), len);
4888
4889 IWP_WRITE(sc, IWP_FH_TCSR_CHNL_TX_BUF_STS_REG(IWP_FH_SRVC_CHNL),
4890 (1 << IWP_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM) |
4891 (1 << IWP_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX) |
4892 IWP_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID);
4893
4894 IWP_WRITE(sc, IWP_FH_TCSR_CHNL_TX_CONFIG_REG(IWP_FH_SRVC_CHNL),
4895 IWP_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
4896 IWP_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL |
4897 IWP_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
4898
4899 iwp_mac_access_exit(sc);
4900
4901 return (IWP_SUCCESS);
4902 }
4903
4904 /*
4905 * necessary setting during alive notification
4906 */
4907 static int
iwp_alive_common(iwp_sc_t * sc)4908 iwp_alive_common(iwp_sc_t *sc)
4909 {
4910 uint32_t base;
4911 uint32_t i;
4912 iwp_wimax_coex_cmd_t w_cmd;
4913 iwp_calibration_crystal_cmd_t c_cmd;
4914 uint32_t rv = IWP_FAIL;
4915
4916 /*
4917 * initialize SCD related registers to make TX work.
4918 */
4919 iwp_mac_access_enter(sc);
4920
4921 /*
4922 * read sram address of data base.
4923 */
4924 sc->sc_scd_base = iwp_reg_read(sc, IWP_SCD_SRAM_BASE_ADDR);
4925
4926 for (base = sc->sc_scd_base + IWP_SCD_CONTEXT_DATA_OFFSET;
4927 base < sc->sc_scd_base + IWP_SCD_TX_STTS_BITMAP_OFFSET;
4928 base += 4) {
4929 iwp_mem_write(sc, base, 0);
4930 }
4931
4932 for (; base < sc->sc_scd_base + IWP_SCD_TRANSLATE_TBL_OFFSET;
4933 base += 4) {
4934 iwp_mem_write(sc, base, 0);
4935 }
4936
4937 for (i = 0; i < sizeof (uint16_t) * IWP_NUM_QUEUES; i += 4) {
4938 iwp_mem_write(sc, base + i, 0);
4939 }
4940
4941 iwp_reg_write(sc, IWP_SCD_DRAM_BASE_ADDR,
4942 sc->sc_dma_sh.cookie.dmac_address >> 10);
4943
4944 iwp_reg_write(sc, IWP_SCD_QUEUECHAIN_SEL,
4945 IWP_SCD_QUEUECHAIN_SEL_ALL(IWP_NUM_QUEUES));
4946
4947 iwp_reg_write(sc, IWP_SCD_AGGR_SEL, 0);
4948
4949 for (i = 0; i < IWP_NUM_QUEUES; i++) {
4950 iwp_reg_write(sc, IWP_SCD_QUEUE_RDPTR(i), 0);
4951 IWP_WRITE(sc, HBUS_TARG_WRPTR, 0 | (i << 8));
4952 iwp_mem_write(sc, sc->sc_scd_base +
4953 IWP_SCD_CONTEXT_QUEUE_OFFSET(i), 0);
4954 iwp_mem_write(sc, sc->sc_scd_base +
4955 IWP_SCD_CONTEXT_QUEUE_OFFSET(i) +
4956 sizeof (uint32_t),
4957 ((SCD_WIN_SIZE << IWP_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
4958 IWP_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
4959 ((SCD_FRAME_LIMIT <<
4960 IWP_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
4961 IWP_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
4962 }
4963
4964 iwp_reg_write(sc, IWP_SCD_INTERRUPT_MASK, (1 << IWP_NUM_QUEUES) - 1);
4965
4966 iwp_reg_write(sc, (IWP_SCD_BASE + 0x10),
4967 SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
4968
4969 IWP_WRITE(sc, HBUS_TARG_WRPTR, (IWP_CMD_QUEUE_NUM << 8));
4970 iwp_reg_write(sc, IWP_SCD_QUEUE_RDPTR(IWP_CMD_QUEUE_NUM), 0);
4971
4972 /*
4973 * queue 0-7 map to FIFO 0-7 and
4974 * all queues work under FIFO mode(none-scheduler_ack)
4975 */
4976 for (i = 0; i < 4; i++) {
4977 iwp_reg_write(sc, IWP_SCD_QUEUE_STATUS_BITS(i),
4978 (1 << IWP_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
4979 ((3-i) << IWP_SCD_QUEUE_STTS_REG_POS_TXF) |
4980 (1 << IWP_SCD_QUEUE_STTS_REG_POS_WSL) |
4981 IWP_SCD_QUEUE_STTS_REG_MSK);
4982 }
4983
4984 iwp_reg_write(sc, IWP_SCD_QUEUE_STATUS_BITS(IWP_CMD_QUEUE_NUM),
4985 (1 << IWP_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
4986 (IWP_CMD_FIFO_NUM << IWP_SCD_QUEUE_STTS_REG_POS_TXF) |
4987 (1 << IWP_SCD_QUEUE_STTS_REG_POS_WSL) |
4988 IWP_SCD_QUEUE_STTS_REG_MSK);
4989
4990 for (i = 5; i < 7; i++) {
4991 iwp_reg_write(sc, IWP_SCD_QUEUE_STATUS_BITS(i),
4992 (1 << IWP_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
4993 (i << IWP_SCD_QUEUE_STTS_REG_POS_TXF) |
4994 (1 << IWP_SCD_QUEUE_STTS_REG_POS_WSL) |
4995 IWP_SCD_QUEUE_STTS_REG_MSK);
4996 }
4997
4998 iwp_mac_access_exit(sc);
4999
5000 (void) memset(&w_cmd, 0, sizeof (w_cmd));
5001
5002 rv = iwp_cmd(sc, COEX_PRIORITY_TABLE_CMD, &w_cmd, sizeof (w_cmd), 1);
5003 if (rv != IWP_SUCCESS) {
5004 cmn_err(CE_WARN, "iwp_alive_common(): "
5005 "failed to send wimax coexist command.\n");
5006 return (rv);
5007 }
5008
5009 (void) memset(&c_cmd, 0, sizeof (c_cmd));
5010
5011 c_cmd.opCode = PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
5012 c_cmd.data.cap_pin1 = LE_16(sc->sc_eep_calib->xtal_calib[0]);
5013 c_cmd.data.cap_pin2 = LE_16(sc->sc_eep_calib->xtal_calib[1]);
5014
5015 rv = iwp_cmd(sc, REPLY_PHY_CALIBRATION_CMD, &c_cmd, sizeof (c_cmd), 1);
5016 if (rv != IWP_SUCCESS) {
5017 cmn_err(CE_WARN, "iwp_alive_common(): "
5018 "failed to send crystal frq calibration command.\n");
5019 return (rv);
5020 }
5021
5022 /*
5023 * make sure crystal frequency calibration ready
5024 * before next operations.
5025 */
5026 DELAY(1000);
5027
5028 return (IWP_SUCCESS);
5029 }
5030
5031 /*
5032 * save results of calibration from ucode
5033 */
5034 static void
iwp_save_calib_result(iwp_sc_t * sc,iwp_rx_desc_t * desc)5035 iwp_save_calib_result(iwp_sc_t *sc, iwp_rx_desc_t *desc)
5036 {
5037 struct iwp_calib_results *res_p = &sc->sc_calib_results;
5038 struct iwp_calib_hdr *calib_hdr = (struct iwp_calib_hdr *)(desc + 1);
5039 int len = LE_32(desc->len);
5040
5041 /*
5042 * ensure the size of buffer is not too big
5043 */
5044 len = (len & FH_RSCSR_FRAME_SIZE_MASK) - 4;
5045
5046 switch (calib_hdr->op_code) {
5047 case PHY_CALIBRATE_LO_CMD:
5048 if (NULL == res_p->lo_res) {
5049 res_p->lo_res = kmem_alloc(len, KM_NOSLEEP);
5050 }
5051
5052 if (NULL == res_p->lo_res) {
5053 cmn_err(CE_WARN, "iwp_save_calib_result(): "
5054 "failed to allocate memory.\n");
5055 return;
5056 }
5057
5058 res_p->lo_res_len = len;
5059 (void) memcpy(res_p->lo_res, calib_hdr, len);
5060 break;
5061 case PHY_CALIBRATE_TX_IQ_CMD:
5062 if (NULL == res_p->tx_iq_res) {
5063 res_p->tx_iq_res = kmem_alloc(len, KM_NOSLEEP);
5064 }
5065
5066 if (NULL == res_p->tx_iq_res) {
5067 cmn_err(CE_WARN, "iwp_save_calib_result(): "
5068 "failed to allocate memory.\n");
5069 return;
5070 }
5071
5072 res_p->tx_iq_res_len = len;
5073 (void) memcpy(res_p->tx_iq_res, calib_hdr, len);
5074 break;
5075 case PHY_CALIBRATE_TX_IQ_PERD_CMD:
5076 if (NULL == res_p->tx_iq_perd_res) {
5077 res_p->tx_iq_perd_res = kmem_alloc(len, KM_NOSLEEP);
5078 }
5079
5080 if (NULL == res_p->tx_iq_perd_res) {
5081 cmn_err(CE_WARN, "iwp_save_calib_result(): "
5082 "failed to allocate memory.\n");
5083 }
5084
5085 res_p->tx_iq_perd_res_len = len;
5086 (void) memcpy(res_p->tx_iq_perd_res, calib_hdr, len);
5087 break;
5088 case PHY_CALIBRATE_BASE_BAND_CMD:
5089 if (NULL == res_p->base_band_res) {
5090 res_p->base_band_res = kmem_alloc(len, KM_NOSLEEP);
5091 }
5092
5093 if (NULL == res_p->base_band_res) {
5094 cmn_err(CE_WARN, "iwp_save_calib_result(): "
5095 "failed to allocate memory.\n");
5096 }
5097
5098 res_p->base_band_res_len = len;
5099 (void) memcpy(res_p->base_band_res, calib_hdr, len);
5100 break;
5101 default:
5102 cmn_err(CE_WARN, "iwp_save_calib_result(): "
5103 "incorrect calibration type(%d).\n", calib_hdr->op_code);
5104 break;
5105 }
5106
5107 }
5108
5109 static void
iwp_release_calib_buffer(iwp_sc_t * sc)5110 iwp_release_calib_buffer(iwp_sc_t *sc)
5111 {
5112 if (sc->sc_calib_results.lo_res != NULL) {
5113 kmem_free(sc->sc_calib_results.lo_res,
5114 sc->sc_calib_results.lo_res_len);
5115 sc->sc_calib_results.lo_res = NULL;
5116 }
5117
5118 if (sc->sc_calib_results.tx_iq_res != NULL) {
5119 kmem_free(sc->sc_calib_results.tx_iq_res,
5120 sc->sc_calib_results.tx_iq_res_len);
5121 sc->sc_calib_results.tx_iq_res = NULL;
5122 }
5123
5124 if (sc->sc_calib_results.tx_iq_perd_res != NULL) {
5125 kmem_free(sc->sc_calib_results.tx_iq_perd_res,
5126 sc->sc_calib_results.tx_iq_perd_res_len);
5127 sc->sc_calib_results.tx_iq_perd_res = NULL;
5128 }
5129
5130 if (sc->sc_calib_results.base_band_res != NULL) {
5131 kmem_free(sc->sc_calib_results.base_band_res,
5132 sc->sc_calib_results.base_band_res_len);
5133 sc->sc_calib_results.base_band_res = NULL;
5134 }
5135
5136 }
5137
5138 /*
5139 * common section of intialization
5140 */
5141 static int
iwp_init_common(iwp_sc_t * sc)5142 iwp_init_common(iwp_sc_t *sc)
5143 {
5144 int32_t qid;
5145 uint32_t tmp;
5146
5147 (void) iwp_preinit(sc);
5148
5149 tmp = IWP_READ(sc, CSR_GP_CNTRL);
5150 if (!(tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) {
5151 cmn_err(CE_NOTE, "iwp_init_common(): "
5152 "radio transmitter is off\n");
5153 return (IWP_FAIL);
5154 }
5155
5156 /*
5157 * init Rx ring
5158 */
5159 iwp_mac_access_enter(sc);
5160 IWP_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
5161
5162 IWP_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
5163 IWP_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
5164 sc->sc_rxq.dma_desc.cookie.dmac_address >> 8);
5165
5166 IWP_WRITE(sc, FH_RSCSR_CHNL0_STTS_WPTR_REG,
5167 ((uint32_t)(sc->sc_dma_sh.cookie.dmac_address +
5168 offsetof(struct iwp_shared, val0)) >> 4));
5169
5170 IWP_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG,
5171 FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
5172 FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
5173 IWP_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K |
5174 (RX_QUEUE_SIZE_LOG <<
5175 FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
5176 iwp_mac_access_exit(sc);
5177 IWP_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG,
5178 (RX_QUEUE_SIZE - 1) & ~0x7);
5179
5180 /*
5181 * init Tx rings
5182 */
5183 iwp_mac_access_enter(sc);
5184 iwp_reg_write(sc, IWP_SCD_TXFACT, 0);
5185
5186 /*
5187 * keep warm page
5188 */
5189 IWP_WRITE(sc, IWP_FH_KW_MEM_ADDR_REG,
5190 sc->sc_dma_kw.cookie.dmac_address >> 4);
5191
5192 for (qid = 0; qid < IWP_NUM_QUEUES; qid++) {
5193 IWP_WRITE(sc, FH_MEM_CBBC_QUEUE(qid),
5194 sc->sc_txq[qid].dma_desc.cookie.dmac_address >> 8);
5195 IWP_WRITE(sc, IWP_FH_TCSR_CHNL_TX_CONFIG_REG(qid),
5196 IWP_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
5197 IWP_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
5198 }
5199
5200 iwp_mac_access_exit(sc);
5201
5202 /*
5203 * clear "radio off" and "disable command" bits
5204 */
5205 IWP_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
5206 IWP_WRITE(sc, CSR_UCODE_DRV_GP1_CLR,
5207 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
5208
5209 /*
5210 * clear any pending interrupts
5211 */
5212 IWP_WRITE(sc, CSR_INT, 0xffffffff);
5213
5214 /*
5215 * enable interrupts
5216 */
5217 IWP_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
5218
5219 IWP_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
5220 IWP_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
5221
5222 return (IWP_SUCCESS);
5223 }
5224
5225 static int
iwp_fast_recover(iwp_sc_t * sc)5226 iwp_fast_recover(iwp_sc_t *sc)
5227 {
5228 ieee80211com_t *ic = &sc->sc_ic;
5229 int err = IWP_FAIL;
5230
5231 mutex_enter(&sc->sc_glock);
5232
5233 /* restore runtime configuration */
5234 bcopy(&sc->sc_config_save, &sc->sc_config,
5235 sizeof (sc->sc_config));
5236
5237 sc->sc_config.assoc_id = 0;
5238 sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_ASSOC_MSK);
5239
5240 if ((err = iwp_hw_set_before_auth(sc)) != IWP_SUCCESS) {
5241 cmn_err(CE_WARN, "iwp_fast_recover(): "
5242 "could not setup authentication\n");
5243 mutex_exit(&sc->sc_glock);
5244 return (err);
5245 }
5246
5247 bcopy(&sc->sc_config_save, &sc->sc_config,
5248 sizeof (sc->sc_config));
5249
5250 /* update adapter's configuration */
5251 err = iwp_run_state_config(sc);
5252 if (err != IWP_SUCCESS) {
5253 cmn_err(CE_WARN, "iwp_fast_recover(): "
5254 "failed to setup association\n");
5255 mutex_exit(&sc->sc_glock);
5256 return (err);
5257 }
5258 /* set LED on */
5259 iwp_set_led(sc, 2, 0, 1);
5260
5261 mutex_exit(&sc->sc_glock);
5262
5263 atomic_and_32(&sc->sc_flags, ~IWP_F_HW_ERR_RECOVER);
5264
5265 /* start queue */
5266 IWP_DBG((IWP_DEBUG_FW, "iwp_fast_recover(): "
5267 "resume xmit\n"));
5268 mac_tx_update(ic->ic_mach);
5269
5270 return (IWP_SUCCESS);
5271 }
5272
5273 static int
iwp_run_state_config(iwp_sc_t * sc)5274 iwp_run_state_config(iwp_sc_t *sc)
5275 {
5276 struct ieee80211com *ic = &sc->sc_ic;
5277 ieee80211_node_t *in = ic->ic_bss;
5278 int err = IWP_FAIL;
5279
5280 /*
5281 * update adapter's configuration
5282 */
5283 sc->sc_config.assoc_id = in->in_associd & 0x3fff;
5284
5285 /*
5286 * short preamble/slot time are
5287 * negotiated when associating
5288 */
5289 sc->sc_config.flags &=
5290 ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
5291 RXON_FLG_SHORT_SLOT_MSK);
5292
5293 if (ic->ic_flags & IEEE80211_F_SHSLOT) {
5294 sc->sc_config.flags |=
5295 LE_32(RXON_FLG_SHORT_SLOT_MSK);
5296 }
5297
5298 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) {
5299 sc->sc_config.flags |=
5300 LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
5301 }
5302
5303 sc->sc_config.filter_flags |=
5304 LE_32(RXON_FILTER_ASSOC_MSK);
5305
5306 if (ic->ic_opmode != IEEE80211_M_STA) {
5307 sc->sc_config.filter_flags |=
5308 LE_32(RXON_FILTER_BCON_AWARE_MSK);
5309 }
5310
5311 IWP_DBG((IWP_DEBUG_80211, "iwp_run_state_config(): "
5312 "config chan %d flags %x"
5313 " filter_flags %x\n",
5314 sc->sc_config.chan, sc->sc_config.flags,
5315 sc->sc_config.filter_flags));
5316
5317 err = iwp_cmd(sc, REPLY_RXON, &sc->sc_config,
5318 sizeof (iwp_rxon_cmd_t), 1);
5319 if (err != IWP_SUCCESS) {
5320 cmn_err(CE_WARN, "iwp_run_state_config(): "
5321 "could not update configuration\n");
5322 return (err);
5323 }
5324
5325 return (err);
5326 }
5327
5328 /*
5329 * This function overwrites default configurations of
5330 * ieee80211com structure in Net80211 module.
5331 */
5332 static void
iwp_overwrite_ic_default(iwp_sc_t * sc)5333 iwp_overwrite_ic_default(iwp_sc_t *sc)
5334 {
5335 ieee80211com_t *ic = &sc->sc_ic;
5336
5337 sc->sc_newstate = ic->ic_newstate;
5338 ic->ic_newstate = iwp_newstate;
5339 ic->ic_node_alloc = iwp_node_alloc;
5340 ic->ic_node_free = iwp_node_free;
5341 }
5342
5343
5344 /*
5345 * This function adds AP station into hardware.
5346 */
5347 static int
iwp_add_ap_sta(iwp_sc_t * sc)5348 iwp_add_ap_sta(iwp_sc_t *sc)
5349 {
5350 ieee80211com_t *ic = &sc->sc_ic;
5351 ieee80211_node_t *in = ic->ic_bss;
5352 iwp_add_sta_t node;
5353 int err = IWP_FAIL;
5354
5355 /*
5356 * Add AP node into hardware.
5357 */
5358 (void) memset(&node, 0, sizeof (node));
5359 IEEE80211_ADDR_COPY(node.sta.addr, in->in_bssid);
5360 node.mode = STA_MODE_ADD_MSK;
5361 node.sta.sta_id = IWP_AP_ID;
5362
5363 err = iwp_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
5364 if (err != IWP_SUCCESS) {
5365 cmn_err(CE_WARN, "iwp_add_ap_sta(): "
5366 "failed to add AP node\n");
5367 return (err);
5368 }
5369
5370 return (err);
5371 }
5372
5373 /*
5374 * Check EEPROM version and Calibration version.
5375 */
5376 static int
iwp_eep_ver_chk(iwp_sc_t * sc)5377 iwp_eep_ver_chk(iwp_sc_t *sc)
5378 {
5379 if ((IWP_READ_EEP_SHORT(sc, EEP_VERSION) < 0x011a) ||
5380 (sc->sc_eep_calib->tx_pow_calib_hdr.calib_version < 4)) {
5381 cmn_err(CE_WARN, "iwp_eep_ver_chk(): "
5382 "unsupported eeprom detected\n");
5383 return (IWP_FAIL);
5384 }
5385
5386 return (IWP_SUCCESS);
5387 }
5388
5389 /*
5390 * Determine parameters for all supported chips.
5391 */
5392 static void
iwp_set_chip_param(iwp_sc_t * sc)5393 iwp_set_chip_param(iwp_sc_t *sc)
5394 {
5395 if ((0x008d == sc->sc_dev_id) ||
5396 (0x008e == sc->sc_dev_id)) {
5397 sc->sc_chip_param.phy_mode = PHY_MODE_G |
5398 PHY_MODE_A | PHY_MODE_N;
5399
5400 sc->sc_chip_param.tx_ant = ANT_A | ANT_B;
5401 sc->sc_chip_param.rx_ant = ANT_A | ANT_B;
5402
5403 sc->sc_chip_param.pa_type = PA_TYPE_MIX;
5404 }
5405
5406 if ((0x422c == sc->sc_dev_id) ||
5407 (0x4239 == sc->sc_dev_id)) {
5408 sc->sc_chip_param.phy_mode = PHY_MODE_G |
5409 PHY_MODE_A | PHY_MODE_N;
5410
5411 sc->sc_chip_param.tx_ant = ANT_B | ANT_C;
5412 sc->sc_chip_param.rx_ant = ANT_B | ANT_C;
5413
5414 sc->sc_chip_param.pa_type = PA_TYPE_INTER;
5415 }
5416
5417 if ((0x422b == sc->sc_dev_id) ||
5418 (0x4238 == sc->sc_dev_id)) {
5419 sc->sc_chip_param.phy_mode = PHY_MODE_G |
5420 PHY_MODE_A | PHY_MODE_N;
5421
5422 sc->sc_chip_param.tx_ant = ANT_A | ANT_B | ANT_C;
5423 sc->sc_chip_param.rx_ant = ANT_A | ANT_B | ANT_C;
5424
5425 sc->sc_chip_param.pa_type = PA_TYPE_SYSTEM;
5426 }
5427 }
5428