Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/wpi/wpi.c
+++ new/usr/src/uts/common/io/wpi/wpi.c
1 1 /*
2 2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 4 */
5 5
6 6 /*
7 7 * Copyright (c) 2006
8 8 * Damien Bergamini <damien.bergamini@free.fr>
9 9 *
10 10 * Permission to use, copy, modify, and distribute this software for any
11 11 * purpose with or without fee is hereby granted, provided that the above
12 12 * copyright notice and this permission notice appear in all copies.
13 13 *
14 14 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17 17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 20 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 21 */
22 22
23 23 /*
24 24 * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters.
25 25 */
26 26
27 27 #include <sys/types.h>
28 28 #include <sys/byteorder.h>
29 29 #include <sys/conf.h>
30 30 #include <sys/cmn_err.h>
31 31 #include <sys/stat.h>
32 32 #include <sys/ddi.h>
33 33 #include <sys/sunddi.h>
34 34 #include <sys/strsubr.h>
35 35 #include <sys/ethernet.h>
36 36 #include <inet/common.h>
37 37 #include <inet/nd.h>
38 38 #include <inet/mi.h>
39 39 #include <sys/note.h>
40 40 #include <sys/stream.h>
41 41 #include <sys/strsun.h>
42 42 #include <sys/modctl.h>
43 43 #include <sys/devops.h>
44 44 #include <sys/dlpi.h>
45 45 #include <sys/mac_provider.h>
46 46 #include <sys/mac_wifi.h>
47 47 #include <sys/net80211.h>
48 48 #include <sys/net80211_proto.h>
49 49 #include <sys/varargs.h>
50 50 #include <sys/policy.h>
51 51 #include <sys/pci.h>
52 52
53 53 #include "wpireg.h"
54 54 #include "wpivar.h"
55 55 #include <inet/wifi_ioctl.h>
56 56
57 57 #ifdef DEBUG
58 58 #define WPI_DEBUG_80211 (1 << 0)
59 59 #define WPI_DEBUG_CMD (1 << 1)
60 60 #define WPI_DEBUG_DMA (1 << 2)
61 61 #define WPI_DEBUG_EEPROM (1 << 3)
62 62 #define WPI_DEBUG_FW (1 << 4)
63 63 #define WPI_DEBUG_HW (1 << 5)
64 64 #define WPI_DEBUG_INTR (1 << 6)
65 65 #define WPI_DEBUG_MRR (1 << 7)
66 66 #define WPI_DEBUG_PIO (1 << 8)
67 67 #define WPI_DEBUG_RX (1 << 9)
68 68 #define WPI_DEBUG_SCAN (1 << 10)
69 69 #define WPI_DEBUG_TX (1 << 11)
70 70 #define WPI_DEBUG_RATECTL (1 << 12)
71 71 #define WPI_DEBUG_RADIO (1 << 13)
72 72 #define WPI_DEBUG_RESUME (1 << 14)
73 73 uint32_t wpi_dbg_flags = 0;
74 74 #define WPI_DBG(x) \
75 75 wpi_dbg x
76 76 #else
77 77 #define WPI_DBG(x)
78 78 #endif
79 79
80 80 static void *wpi_soft_state_p = NULL;
81 81 static uint8_t wpi_fw_bin [] = {
82 82 #include "fw-wpi/ipw3945.ucode.hex"
83 83 };
84 84
85 85 /* DMA attributes for a shared page */
86 86 static ddi_dma_attr_t sh_dma_attr = {
87 87 DMA_ATTR_V0, /* version of this structure */
88 88 0, /* lowest usable address */
89 89 0xffffffffU, /* highest usable address */
90 90 0xffffffffU, /* maximum DMAable byte count */
91 91 0x1000, /* alignment in bytes */
92 92 0x1000, /* burst sizes (any?) */
93 93 1, /* minimum transfer */
94 94 0xffffffffU, /* maximum transfer */
95 95 0xffffffffU, /* maximum segment length */
96 96 1, /* maximum number of segments */
97 97 1, /* granularity */
98 98 0, /* flags (reserved) */
99 99 };
100 100
101 101 /* DMA attributes for a ring descriptor */
102 102 static ddi_dma_attr_t ring_desc_dma_attr = {
103 103 DMA_ATTR_V0, /* version of this structure */
104 104 0, /* lowest usable address */
105 105 0xffffffffU, /* highest usable address */
106 106 0xffffffffU, /* maximum DMAable byte count */
107 107 0x4000, /* alignment in bytes */
108 108 0x100, /* burst sizes (any?) */
109 109 1, /* minimum transfer */
110 110 0xffffffffU, /* maximum transfer */
111 111 0xffffffffU, /* maximum segment length */
112 112 1, /* maximum number of segments */
113 113 1, /* granularity */
114 114 0, /* flags (reserved) */
115 115 };
116 116
117 117
118 118 /* DMA attributes for a tx cmd */
119 119 static ddi_dma_attr_t tx_cmd_dma_attr = {
120 120 DMA_ATTR_V0, /* version of this structure */
121 121 0, /* lowest usable address */
122 122 0xffffffffU, /* highest usable address */
123 123 0xffffffffU, /* maximum DMAable byte count */
124 124 4, /* alignment in bytes */
125 125 0x100, /* burst sizes (any?) */
126 126 1, /* minimum transfer */
127 127 0xffffffffU, /* maximum transfer */
128 128 0xffffffffU, /* maximum segment length */
129 129 1, /* maximum number of segments */
130 130 1, /* granularity */
131 131 0, /* flags (reserved) */
132 132 };
133 133
134 134 /* DMA attributes for a rx buffer */
135 135 static ddi_dma_attr_t rx_buffer_dma_attr = {
136 136 DMA_ATTR_V0, /* version of this structure */
137 137 0, /* lowest usable address */
138 138 0xffffffffU, /* highest usable address */
139 139 0xffffffffU, /* maximum DMAable byte count */
140 140 1, /* alignment in bytes */
141 141 0x100, /* burst sizes (any?) */
142 142 1, /* minimum transfer */
143 143 0xffffffffU, /* maximum transfer */
144 144 0xffffffffU, /* maximum segment length */
145 145 1, /* maximum number of segments */
146 146 1, /* granularity */
147 147 0, /* flags (reserved) */
148 148 };
149 149
150 150 /*
151 151 * DMA attributes for a tx buffer.
152 152 * the maximum number of segments is 4 for the hardware.
153 153 * now all the wifi drivers put the whole frame in a single
154 154 * descriptor, so we define the maximum number of segments 4,
155 155 * just the same as the rx_buffer. we consider leverage the HW
156 156 * ability in the future, that is why we don't define rx and tx
157 157 * buffer_dma_attr as the same.
158 158 */
159 159 static ddi_dma_attr_t tx_buffer_dma_attr = {
160 160 DMA_ATTR_V0, /* version of this structure */
161 161 0, /* lowest usable address */
162 162 0xffffffffU, /* highest usable address */
163 163 0xffffffffU, /* maximum DMAable byte count */
164 164 1, /* alignment in bytes */
165 165 0x100, /* burst sizes (any?) */
166 166 1, /* minimum transfer */
167 167 0xffffffffU, /* maximum transfer */
168 168 0xffffffffU, /* maximum segment length */
169 169 1, /* maximum number of segments */
170 170 1, /* granularity */
171 171 0, /* flags (reserved) */
172 172 };
173 173
174 174 /* DMA attributes for a load firmware */
175 175 static ddi_dma_attr_t fw_buffer_dma_attr = {
176 176 DMA_ATTR_V0, /* version of this structure */
177 177 0, /* lowest usable address */
178 178 0xffffffffU, /* highest usable address */
179 179 0x7fffffff, /* maximum DMAable byte count */
180 180 4, /* alignment in bytes */
181 181 0x100, /* burst sizes (any?) */
182 182 1, /* minimum transfer */
183 183 0xffffffffU, /* maximum transfer */
184 184 0xffffffffU, /* maximum segment length */
185 185 4, /* maximum number of segments */
186 186 1, /* granularity */
187 187 0, /* flags (reserved) */
188 188 };
189 189
190 190 /* regs access attributes */
191 191 static ddi_device_acc_attr_t wpi_reg_accattr = {
192 192 DDI_DEVICE_ATTR_V0,
193 193 DDI_STRUCTURE_LE_ACC,
194 194 DDI_STRICTORDER_ACC,
195 195 DDI_DEFAULT_ACC
196 196 };
197 197
198 198 /* DMA access attributes */
199 199 static ddi_device_acc_attr_t wpi_dma_accattr = {
200 200 DDI_DEVICE_ATTR_V0,
201 201 DDI_NEVERSWAP_ACC,
202 202 DDI_STRICTORDER_ACC,
203 203 DDI_DEFAULT_ACC
204 204 };
205 205
206 206 static int wpi_ring_init(wpi_sc_t *);
207 207 static void wpi_ring_free(wpi_sc_t *);
208 208 static int wpi_alloc_shared(wpi_sc_t *);
209 209 static void wpi_free_shared(wpi_sc_t *);
210 210 static int wpi_alloc_fw_dma(wpi_sc_t *);
211 211 static void wpi_free_fw_dma(wpi_sc_t *);
212 212 static int wpi_alloc_rx_ring(wpi_sc_t *);
213 213 static void wpi_reset_rx_ring(wpi_sc_t *);
214 214 static void wpi_free_rx_ring(wpi_sc_t *);
215 215 static int wpi_alloc_tx_ring(wpi_sc_t *, wpi_tx_ring_t *, int, int);
216 216 static void wpi_reset_tx_ring(wpi_sc_t *, wpi_tx_ring_t *);
217 217 static void wpi_free_tx_ring(wpi_sc_t *, wpi_tx_ring_t *);
218 218
219 219 static ieee80211_node_t *wpi_node_alloc(ieee80211com_t *);
220 220 static void wpi_node_free(ieee80211_node_t *);
221 221 static int wpi_newstate(ieee80211com_t *, enum ieee80211_state, int);
222 222 static int wpi_key_set(ieee80211com_t *, const struct ieee80211_key *,
223 223 const uint8_t mac[IEEE80211_ADDR_LEN]);
224 224 static void wpi_mem_lock(wpi_sc_t *);
225 225 static void wpi_mem_unlock(wpi_sc_t *);
226 226 static uint32_t wpi_mem_read(wpi_sc_t *, uint16_t);
227 227 static void wpi_mem_write(wpi_sc_t *, uint16_t, uint32_t);
228 228 static void wpi_mem_write_region_4(wpi_sc_t *, uint16_t,
229 229 const uint32_t *, int);
230 230 static uint16_t wpi_read_prom_word(wpi_sc_t *, uint32_t);
231 231 static int wpi_load_microcode(wpi_sc_t *);
232 232 static int wpi_load_firmware(wpi_sc_t *, uint32_t);
233 233 static void wpi_rx_intr(wpi_sc_t *, wpi_rx_desc_t *,
234 234 wpi_rx_data_t *);
235 235 static void wpi_tx_intr(wpi_sc_t *, wpi_rx_desc_t *,
236 236 wpi_rx_data_t *);
237 237 static void wpi_cmd_intr(wpi_sc_t *, wpi_rx_desc_t *);
238 238 static uint_t wpi_intr(caddr_t);
239 239 static uint_t wpi_notif_softintr(caddr_t);
240 240 static uint8_t wpi_plcp_signal(int);
241 241 static void wpi_read_eeprom(wpi_sc_t *);
242 242 static int wpi_cmd(wpi_sc_t *, int, const void *, int, int);
243 243 static int wpi_mrr_setup(wpi_sc_t *);
244 244 static void wpi_set_led(wpi_sc_t *, uint8_t, uint8_t, uint8_t);
245 245 static int wpi_auth(wpi_sc_t *);
246 246 static int wpi_scan(wpi_sc_t *);
247 247 static int wpi_config(wpi_sc_t *);
248 248 static void wpi_stop_master(wpi_sc_t *);
249 249 static int wpi_power_up(wpi_sc_t *);
250 250 static int wpi_reset(wpi_sc_t *);
251 251 static void wpi_hw_config(wpi_sc_t *);
252 252 static int wpi_init(wpi_sc_t *);
253 253 static void wpi_stop(wpi_sc_t *);
254 254 static int wpi_quiesce(dev_info_t *dip);
255 255 static void wpi_amrr_init(wpi_amrr_t *);
256 256 static void wpi_amrr_timeout(wpi_sc_t *);
257 257 static void wpi_amrr_ratectl(void *, ieee80211_node_t *);
258 258
259 259 static int wpi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
260 260 static int wpi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
261 261
262 262 /*
263 263 * GLD specific operations
264 264 */
265 265 static int wpi_m_stat(void *arg, uint_t stat, uint64_t *val);
266 266 static int wpi_m_start(void *arg);
267 267 static void wpi_m_stop(void *arg);
268 268 static int wpi_m_unicst(void *arg, const uint8_t *macaddr);
269 269 static int wpi_m_multicst(void *arg, boolean_t add, const uint8_t *m);
270 270 static int wpi_m_promisc(void *arg, boolean_t on);
271 271 static mblk_t *wpi_m_tx(void *arg, mblk_t *mp);
272 272 static void wpi_m_ioctl(void *arg, queue_t *wq, mblk_t *mp);
273 273 static int wpi_m_setprop(void *arg, const char *pr_name,
274 274 mac_prop_id_t wldp_pr_num, uint_t wldp_length, const void *wldp_buf);
275 275 static int wpi_m_getprop(void *arg, const char *pr_name,
276 276 mac_prop_id_t wldp_pr_num, uint_t wldp_lenth, void *wldp_buf);
277 277 static void wpi_m_propinfo(void *arg, const char *pr_name,
278 278 mac_prop_id_t wldp_pr_num, mac_prop_info_handle_t mph);
279 279 static void wpi_destroy_locks(wpi_sc_t *sc);
280 280 static int wpi_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type);
281 281 static void wpi_thread(wpi_sc_t *sc);
282 282 static int wpi_fast_recover(wpi_sc_t *sc);
283 283
284 284 /*
285 285 * Supported rates for 802.11a/b/g modes (in 500Kbps unit).
286 286 */
287 287 static const struct ieee80211_rateset wpi_rateset_11b =
288 288 { 4, { 2, 4, 11, 22 } };
289 289
290 290 static const struct ieee80211_rateset wpi_rateset_11g =
291 291 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
292 292
293 293 static const uint8_t wpi_ridx_to_signal[] = {
294 294 /* OFDM: IEEE Std 802.11a-1999, pp. 14 Table 80 */
295 295 /* R1-R4 (ral/ural is R4-R1) */
296 296 0xd, 0xf, 0x5, 0x7, 0x9, 0xb, 0x1, 0x3,
297 297 /* CCK: device-dependent */
298 298 10, 20, 55, 110
299 299 };
300 300
301 301 /*
302 302 * For mfthread only
303 303 */
304 304 extern pri_t minclsyspri;
305 305
306 306 /*
307 307 * Module Loading Data & Entry Points
308 308 */
309 309 DDI_DEFINE_STREAM_OPS(wpi_devops, nulldev, nulldev, wpi_attach,
↓ open down ↓ |
309 lines elided |
↑ open up ↑ |
310 310 wpi_detach, nodev, NULL, D_MP, NULL, wpi_quiesce);
311 311
312 312 static struct modldrv wpi_modldrv = {
313 313 &mod_driverops,
314 314 "Intel(R) PRO/Wireless 3945ABG driver",
315 315 &wpi_devops
316 316 };
317 317
318 318 static struct modlinkage wpi_modlinkage = {
319 319 MODREV_1,
320 - &wpi_modldrv,
321 - NULL
320 + { &wpi_modldrv, NULL }
322 321 };
323 322
324 323 int
325 324 _init(void)
326 325 {
327 326 int status;
328 327
329 328 status = ddi_soft_state_init(&wpi_soft_state_p,
330 329 sizeof (wpi_sc_t), 1);
331 330 if (status != DDI_SUCCESS)
332 331 return (status);
333 332
334 333 mac_init_ops(&wpi_devops, "wpi");
335 334 status = mod_install(&wpi_modlinkage);
336 335 if (status != DDI_SUCCESS) {
337 336 mac_fini_ops(&wpi_devops);
338 337 ddi_soft_state_fini(&wpi_soft_state_p);
339 338 }
340 339
341 340 return (status);
342 341 }
343 342
344 343 int
345 344 _fini(void)
346 345 {
347 346 int status;
348 347
349 348 status = mod_remove(&wpi_modlinkage);
350 349 if (status == DDI_SUCCESS) {
351 350 mac_fini_ops(&wpi_devops);
352 351 ddi_soft_state_fini(&wpi_soft_state_p);
353 352 }
354 353
355 354 return (status);
356 355 }
357 356
358 357 int
359 358 _info(struct modinfo *mip)
360 359 {
361 360 return (mod_info(&wpi_modlinkage, mip));
362 361 }
363 362
364 363 /*
365 364 * Mac Call Back entries
366 365 */
367 366 mac_callbacks_t wpi_m_callbacks = {
368 367 MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
369 368 wpi_m_stat,
370 369 wpi_m_start,
371 370 wpi_m_stop,
372 371 wpi_m_promisc,
373 372 wpi_m_multicst,
374 373 wpi_m_unicst,
375 374 wpi_m_tx,
376 375 NULL,
377 376 wpi_m_ioctl,
378 377 NULL,
379 378 NULL,
380 379 NULL,
381 380 wpi_m_setprop,
382 381 wpi_m_getprop,
383 382 wpi_m_propinfo
384 383 };
385 384
386 385 #ifdef DEBUG
387 386 void
388 387 wpi_dbg(uint32_t flags, const char *fmt, ...)
389 388 {
390 389 va_list ap;
391 390
392 391 if (flags & wpi_dbg_flags) {
393 392 va_start(ap, fmt);
394 393 vcmn_err(CE_NOTE, fmt, ap);
395 394 va_end(ap);
396 395 }
397 396 }
398 397 #endif
399 398 /*
400 399 * device operations
401 400 */
402 401 int
403 402 wpi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
404 403 {
405 404 wpi_sc_t *sc;
406 405 ddi_acc_handle_t cfg_handle;
407 406 caddr_t cfg_base;
408 407 ieee80211com_t *ic;
409 408 int instance, err, i;
410 409 char strbuf[32];
411 410 wifi_data_t wd = { 0 };
412 411 mac_register_t *macp;
413 412
414 413 switch (cmd) {
415 414 case DDI_ATTACH:
416 415 break;
417 416 case DDI_RESUME:
418 417 sc = ddi_get_soft_state(wpi_soft_state_p,
419 418 ddi_get_instance(dip));
420 419 ASSERT(sc != NULL);
421 420
422 421 mutex_enter(&sc->sc_glock);
423 422 sc->sc_flags &= ~WPI_F_SUSPEND;
424 423 mutex_exit(&sc->sc_glock);
425 424
426 425 if (sc->sc_flags & WPI_F_RUNNING)
427 426 (void) wpi_init(sc);
428 427
429 428 mutex_enter(&sc->sc_glock);
430 429 sc->sc_flags |= WPI_F_LAZY_RESUME;
431 430 mutex_exit(&sc->sc_glock);
432 431
433 432 WPI_DBG((WPI_DEBUG_RESUME, "wpi: resume \n"));
434 433 return (DDI_SUCCESS);
435 434 default:
436 435 err = DDI_FAILURE;
437 436 goto attach_fail1;
438 437 }
439 438
440 439 instance = ddi_get_instance(dip);
441 440 err = ddi_soft_state_zalloc(wpi_soft_state_p, instance);
442 441 if (err != DDI_SUCCESS) {
443 442 cmn_err(CE_WARN,
444 443 "wpi_attach(): failed to allocate soft state\n");
445 444 goto attach_fail1;
446 445 }
447 446 sc = ddi_get_soft_state(wpi_soft_state_p, instance);
448 447 sc->sc_dip = dip;
449 448
450 449 err = ddi_regs_map_setup(dip, 0, &cfg_base, 0, 0,
451 450 &wpi_reg_accattr, &cfg_handle);
452 451 if (err != DDI_SUCCESS) {
453 452 cmn_err(CE_WARN,
454 453 "wpi_attach(): failed to map config spaces regs\n");
455 454 goto attach_fail2;
456 455 }
457 456 sc->sc_rev = ddi_get8(cfg_handle,
458 457 (uint8_t *)(cfg_base + PCI_CONF_REVID));
459 458 ddi_put8(cfg_handle, (uint8_t *)(cfg_base + 0x41), 0);
460 459 sc->sc_clsz = ddi_get16(cfg_handle,
461 460 (uint16_t *)(cfg_base + PCI_CONF_CACHE_LINESZ));
462 461 ddi_regs_map_free(&cfg_handle);
463 462 if (!sc->sc_clsz)
464 463 sc->sc_clsz = 16;
465 464 sc->sc_clsz = (sc->sc_clsz << 2);
466 465 sc->sc_dmabuf_sz = roundup(0x1000 + sizeof (struct ieee80211_frame) +
467 466 IEEE80211_MTU + IEEE80211_CRC_LEN +
468 467 (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
469 468 IEEE80211_WEP_CRCLEN), sc->sc_clsz);
470 469 /*
471 470 * Map operating registers
472 471 */
473 472 err = ddi_regs_map_setup(dip, 1, &sc->sc_base,
474 473 0, 0, &wpi_reg_accattr, &sc->sc_handle);
475 474 if (err != DDI_SUCCESS) {
476 475 cmn_err(CE_WARN,
477 476 "wpi_attach(): failed to map device regs\n");
478 477 goto attach_fail2;
479 478 }
480 479
481 480 /*
482 481 * Allocate shared page.
483 482 */
484 483 err = wpi_alloc_shared(sc);
485 484 if (err != DDI_SUCCESS) {
486 485 cmn_err(CE_WARN, "failed to allocate shared page\n");
487 486 goto attach_fail3;
488 487 }
489 488
490 489 /*
491 490 * Get the hw conf, including MAC address, then init all rings.
492 491 */
493 492 wpi_read_eeprom(sc);
494 493 err = wpi_ring_init(sc);
495 494 if (err != DDI_SUCCESS) {
496 495 cmn_err(CE_WARN, "wpi_attach(): "
497 496 "failed to allocate and initialize ring\n");
498 497 goto attach_fail4;
499 498 }
500 499
501 500 sc->sc_hdr = (const wpi_firmware_hdr_t *)wpi_fw_bin;
502 501
503 502 /* firmware image layout: |HDR|<--TEXT-->|<--DATA-->|<--BOOT-->| */
504 503 sc->sc_text = (const char *)(sc->sc_hdr + 1);
505 504 sc->sc_data = sc->sc_text + LE_32(sc->sc_hdr->textsz);
506 505 sc->sc_boot = sc->sc_data + LE_32(sc->sc_hdr->datasz);
507 506 err = wpi_alloc_fw_dma(sc);
508 507 if (err != DDI_SUCCESS) {
509 508 cmn_err(CE_WARN, "wpi_attach(): "
510 509 "failed to allocate firmware dma\n");
511 510 goto attach_fail5;
512 511 }
513 512
514 513 /*
515 514 * Initialize mutexs and condvars
516 515 */
517 516 err = ddi_get_iblock_cookie(dip, 0, &sc->sc_iblk);
518 517 if (err != DDI_SUCCESS) {
519 518 cmn_err(CE_WARN,
520 519 "wpi_attach(): failed to do ddi_get_iblock_cookie()\n");
521 520 goto attach_fail6;
522 521 }
523 522 mutex_init(&sc->sc_glock, NULL, MUTEX_DRIVER, sc->sc_iblk);
524 523 mutex_init(&sc->sc_tx_lock, NULL, MUTEX_DRIVER, sc->sc_iblk);
525 524 cv_init(&sc->sc_fw_cv, NULL, CV_DRIVER, NULL);
526 525 cv_init(&sc->sc_cmd_cv, NULL, CV_DRIVER, NULL);
527 526
528 527 /*
529 528 * initialize the mfthread
530 529 */
531 530 mutex_init(&sc->sc_mt_lock, NULL, MUTEX_DRIVER,
532 531 (void *) sc->sc_iblk);
533 532 cv_init(&sc->sc_mt_cv, NULL, CV_DRIVER, NULL);
534 533 sc->sc_mf_thread = NULL;
535 534 sc->sc_mf_thread_switch = 0;
536 535 /*
537 536 * Initialize the wifi part, which will be used by
538 537 * generic layer
539 538 */
540 539 ic = &sc->sc_ic;
541 540 ic->ic_phytype = IEEE80211_T_OFDM;
542 541 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
543 542 ic->ic_state = IEEE80211_S_INIT;
544 543 ic->ic_maxrssi = 70; /* experimental number */
545 544 ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_TXPMGT |
546 545 IEEE80211_C_PMGT | IEEE80211_C_SHSLOT;
547 546
548 547 /*
549 548 * use software WEP and TKIP, hardware CCMP;
550 549 */
551 550 ic->ic_caps |= IEEE80211_C_AES_CCM;
552 551 ic->ic_caps |= IEEE80211_C_WPA; /* Support WPA/WPA2 */
553 552
554 553 /* set supported .11b and .11g rates */
555 554 ic->ic_sup_rates[IEEE80211_MODE_11B] = wpi_rateset_11b;
556 555 ic->ic_sup_rates[IEEE80211_MODE_11G] = wpi_rateset_11g;
557 556
558 557 /* set supported .11b and .11g channels (1 through 14) */
559 558 for (i = 1; i <= 14; i++) {
560 559 ic->ic_sup_channels[i].ich_freq =
561 560 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
562 561 ic->ic_sup_channels[i].ich_flags =
563 562 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
564 563 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ |
565 564 IEEE80211_CHAN_PASSIVE;
566 565 }
567 566 ic->ic_ibss_chan = &ic->ic_sup_channels[0];
568 567 ic->ic_xmit = wpi_send;
569 568 /*
570 569 * init Wifi layer
571 570 */
572 571 ieee80211_attach(ic);
573 572
574 573 /* register WPA door */
575 574 ieee80211_register_door(ic, ddi_driver_name(dip),
576 575 ddi_get_instance(dip));
577 576
578 577 /*
579 578 * Override 80211 default routines
580 579 */
581 580 sc->sc_newstate = ic->ic_newstate;
582 581 ic->ic_newstate = wpi_newstate;
583 582 ic->ic_node_alloc = wpi_node_alloc;
584 583 ic->ic_node_free = wpi_node_free;
585 584 ic->ic_crypto.cs_key_set = wpi_key_set;
586 585 ieee80211_media_init(ic);
587 586 /*
588 587 * initialize default tx key
589 588 */
590 589 ic->ic_def_txkey = 0;
591 590
592 591 err = ddi_add_softintr(dip, DDI_SOFTINT_LOW,
593 592 &sc->sc_notif_softint_id, &sc->sc_iblk, NULL, wpi_notif_softintr,
594 593 (caddr_t)sc);
595 594 if (err != DDI_SUCCESS) {
596 595 cmn_err(CE_WARN,
597 596 "wpi_attach(): failed to do ddi_add_softintr()\n");
598 597 goto attach_fail7;
599 598 }
600 599
601 600 /*
602 601 * Add the interrupt handler
603 602 */
604 603 err = ddi_add_intr(dip, 0, &sc->sc_iblk, NULL,
605 604 wpi_intr, (caddr_t)sc);
606 605 if (err != DDI_SUCCESS) {
607 606 cmn_err(CE_WARN,
608 607 "wpi_attach(): failed to do ddi_add_intr()\n");
609 608 goto attach_fail8;
610 609 }
611 610
612 611 /*
613 612 * Initialize pointer to device specific functions
614 613 */
615 614 wd.wd_secalloc = WIFI_SEC_NONE;
616 615 wd.wd_opmode = ic->ic_opmode;
617 616 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_macaddr);
618 617
619 618 macp = mac_alloc(MAC_VERSION);
620 619 if (err != DDI_SUCCESS) {
621 620 cmn_err(CE_WARN,
622 621 "wpi_attach(): failed to do mac_alloc()\n");
623 622 goto attach_fail9;
624 623 }
625 624
626 625 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
627 626 macp->m_driver = sc;
628 627 macp->m_dip = dip;
629 628 macp->m_src_addr = ic->ic_macaddr;
630 629 macp->m_callbacks = &wpi_m_callbacks;
631 630 macp->m_min_sdu = 0;
632 631 macp->m_max_sdu = IEEE80211_MTU;
633 632 macp->m_pdata = &wd;
634 633 macp->m_pdata_size = sizeof (wd);
635 634
636 635 /*
637 636 * Register the macp to mac
638 637 */
639 638 err = mac_register(macp, &ic->ic_mach);
640 639 mac_free(macp);
641 640 if (err != DDI_SUCCESS) {
642 641 cmn_err(CE_WARN,
643 642 "wpi_attach(): failed to do mac_register()\n");
644 643 goto attach_fail9;
645 644 }
646 645
647 646 /*
648 647 * Create minor node of type DDI_NT_NET_WIFI
649 648 */
650 649 (void) snprintf(strbuf, sizeof (strbuf), "wpi%d", instance);
651 650 err = ddi_create_minor_node(dip, strbuf, S_IFCHR,
652 651 instance + 1, DDI_NT_NET_WIFI, 0);
653 652 if (err != DDI_SUCCESS)
654 653 cmn_err(CE_WARN,
655 654 "wpi_attach(): failed to do ddi_create_minor_node()\n");
656 655
657 656 /*
658 657 * Notify link is down now
659 658 */
660 659 mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
661 660
662 661 /*
663 662 * create the mf thread to handle the link status,
664 663 * recovery fatal error, etc.
665 664 */
666 665
667 666 sc->sc_mf_thread_switch = 1;
668 667 if (sc->sc_mf_thread == NULL)
669 668 sc->sc_mf_thread = thread_create((caddr_t)NULL, 0,
670 669 wpi_thread, sc, 0, &p0, TS_RUN, minclsyspri);
671 670
672 671 sc->sc_flags |= WPI_F_ATTACHED;
673 672
674 673 return (DDI_SUCCESS);
675 674 attach_fail9:
676 675 ddi_remove_intr(dip, 0, sc->sc_iblk);
677 676 attach_fail8:
678 677 ddi_remove_softintr(sc->sc_notif_softint_id);
679 678 sc->sc_notif_softint_id = NULL;
680 679 attach_fail7:
681 680 ieee80211_detach(ic);
682 681 wpi_destroy_locks(sc);
683 682 attach_fail6:
684 683 wpi_free_fw_dma(sc);
685 684 attach_fail5:
686 685 wpi_ring_free(sc);
687 686 attach_fail4:
688 687 wpi_free_shared(sc);
689 688 attach_fail3:
690 689 ddi_regs_map_free(&sc->sc_handle);
691 690 attach_fail2:
692 691 ddi_soft_state_free(wpi_soft_state_p, instance);
693 692 attach_fail1:
694 693 return (err);
695 694 }
696 695
697 696 int
698 697 wpi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
699 698 {
700 699 wpi_sc_t *sc;
701 700 int err;
702 701
703 702 sc = ddi_get_soft_state(wpi_soft_state_p, ddi_get_instance(dip));
704 703 ASSERT(sc != NULL);
705 704
706 705 switch (cmd) {
707 706 case DDI_DETACH:
708 707 break;
709 708 case DDI_SUSPEND:
710 709 mutex_enter(&sc->sc_glock);
711 710 sc->sc_flags |= WPI_F_SUSPEND;
712 711 mutex_exit(&sc->sc_glock);
713 712
714 713 if (sc->sc_flags & WPI_F_RUNNING) {
715 714 wpi_stop(sc);
716 715 }
717 716
718 717 WPI_DBG((WPI_DEBUG_RESUME, "wpi: suspend \n"));
719 718 return (DDI_SUCCESS);
720 719 default:
721 720 return (DDI_FAILURE);
722 721 }
723 722 if (!(sc->sc_flags & WPI_F_ATTACHED))
724 723 return (DDI_FAILURE);
725 724
726 725 err = mac_disable(sc->sc_ic.ic_mach);
727 726 if (err != DDI_SUCCESS)
728 727 return (err);
729 728
730 729 /*
731 730 * Destroy the mf_thread
732 731 */
733 732 mutex_enter(&sc->sc_mt_lock);
734 733 sc->sc_mf_thread_switch = 0;
735 734 while (sc->sc_mf_thread != NULL) {
736 735 if (cv_wait_sig(&sc->sc_mt_cv, &sc->sc_mt_lock) == 0)
737 736 break;
738 737 }
739 738 mutex_exit(&sc->sc_mt_lock);
740 739
741 740 wpi_stop(sc);
742 741
743 742 /*
744 743 * Unregiste from the MAC layer subsystem
745 744 */
746 745 (void) mac_unregister(sc->sc_ic.ic_mach);
747 746
748 747 mutex_enter(&sc->sc_glock);
749 748 wpi_free_fw_dma(sc);
750 749 wpi_ring_free(sc);
751 750 wpi_free_shared(sc);
752 751 mutex_exit(&sc->sc_glock);
753 752
754 753 ddi_remove_intr(dip, 0, sc->sc_iblk);
755 754 ddi_remove_softintr(sc->sc_notif_softint_id);
756 755 sc->sc_notif_softint_id = NULL;
757 756
758 757 /*
759 758 * detach ieee80211
760 759 */
761 760 ieee80211_detach(&sc->sc_ic);
762 761
763 762 wpi_destroy_locks(sc);
764 763
765 764 ddi_regs_map_free(&sc->sc_handle);
766 765 ddi_remove_minor_node(dip, NULL);
767 766 ddi_soft_state_free(wpi_soft_state_p, ddi_get_instance(dip));
768 767
769 768 return (DDI_SUCCESS);
770 769 }
771 770
772 771 static void
773 772 wpi_destroy_locks(wpi_sc_t *sc)
774 773 {
775 774 cv_destroy(&sc->sc_mt_cv);
776 775 mutex_destroy(&sc->sc_mt_lock);
777 776 cv_destroy(&sc->sc_cmd_cv);
778 777 cv_destroy(&sc->sc_fw_cv);
779 778 mutex_destroy(&sc->sc_tx_lock);
780 779 mutex_destroy(&sc->sc_glock);
781 780 }
782 781
783 782 /*
784 783 * Allocate an area of memory and a DMA handle for accessing it
785 784 */
786 785 static int
787 786 wpi_alloc_dma_mem(wpi_sc_t *sc, size_t memsize, ddi_dma_attr_t *dma_attr_p,
788 787 ddi_device_acc_attr_t *acc_attr_p, uint_t dma_flags, wpi_dma_t *dma_p)
789 788 {
790 789 caddr_t vaddr;
791 790 int err;
792 791
793 792 /*
794 793 * Allocate handle
795 794 */
796 795 err = ddi_dma_alloc_handle(sc->sc_dip, dma_attr_p,
797 796 DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
798 797 if (err != DDI_SUCCESS) {
799 798 dma_p->dma_hdl = NULL;
800 799 return (DDI_FAILURE);
801 800 }
802 801
803 802 /*
804 803 * Allocate memory
805 804 */
806 805 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p,
807 806 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
808 807 DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl);
809 808 if (err != DDI_SUCCESS) {
810 809 ddi_dma_free_handle(&dma_p->dma_hdl);
811 810 dma_p->dma_hdl = NULL;
812 811 dma_p->acc_hdl = NULL;
813 812 return (DDI_FAILURE);
814 813 }
815 814
816 815 /*
817 816 * Bind the two together
818 817 */
819 818 dma_p->mem_va = vaddr;
820 819 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
821 820 vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL,
822 821 &dma_p->cookie, &dma_p->ncookies);
823 822 if (err != DDI_DMA_MAPPED) {
824 823 ddi_dma_mem_free(&dma_p->acc_hdl);
825 824 ddi_dma_free_handle(&dma_p->dma_hdl);
826 825 dma_p->acc_hdl = NULL;
827 826 dma_p->dma_hdl = NULL;
828 827 return (DDI_FAILURE);
829 828 }
830 829
831 830 dma_p->nslots = ~0U;
832 831 dma_p->size = ~0U;
833 832 dma_p->token = ~0U;
834 833 dma_p->offset = 0;
835 834 return (DDI_SUCCESS);
836 835 }
837 836
838 837 /*
839 838 * Free one allocated area of DMAable memory
840 839 */
841 840 static void
842 841 wpi_free_dma_mem(wpi_dma_t *dma_p)
843 842 {
844 843 if (dma_p->dma_hdl != NULL) {
845 844 if (dma_p->ncookies) {
846 845 (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
847 846 dma_p->ncookies = 0;
848 847 }
849 848 ddi_dma_free_handle(&dma_p->dma_hdl);
850 849 dma_p->dma_hdl = NULL;
851 850 }
852 851
853 852 if (dma_p->acc_hdl != NULL) {
854 853 ddi_dma_mem_free(&dma_p->acc_hdl);
855 854 dma_p->acc_hdl = NULL;
856 855 }
857 856 }
858 857
859 858 /*
860 859 * Allocate an area of dma memory for firmware load.
861 860 * Idealy, this allocation should be a one time action, that is,
862 861 * the memory will be freed after the firmware is uploaded to the
863 862 * card. but since a recovery mechanism for the fatal firmware need
864 863 * reload the firmware, and re-allocate dma at run time may be failed,
865 864 * so we allocate it at attach and keep it in the whole lifecycle of
866 865 * the driver.
867 866 */
868 867 static int
869 868 wpi_alloc_fw_dma(wpi_sc_t *sc)
870 869 {
871 870 int i, err = DDI_SUCCESS;
872 871 wpi_dma_t *dma_p;
873 872
874 873 err = wpi_alloc_dma_mem(sc, LE_32(sc->sc_hdr->textsz),
875 874 &fw_buffer_dma_attr, &wpi_dma_accattr,
876 875 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
877 876 &sc->sc_dma_fw_text);
878 877 dma_p = &sc->sc_dma_fw_text;
879 878 WPI_DBG((WPI_DEBUG_DMA, "ncookies:%d addr1:%x size1:%x\n",
880 879 dma_p->ncookies, dma_p->cookie.dmac_address,
881 880 dma_p->cookie.dmac_size));
882 881 if (err != DDI_SUCCESS) {
883 882 cmn_err(CE_WARN, "wpi_alloc_fw_dma(): failed to alloc"
884 883 "text dma memory");
885 884 goto fail;
886 885 }
887 886 for (i = 0; i < dma_p->ncookies; i++) {
888 887 sc->sc_fw_text_cookie[i] = dma_p->cookie;
889 888 ddi_dma_nextcookie(dma_p->dma_hdl, &dma_p->cookie);
890 889 }
891 890 err = wpi_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz),
892 891 &fw_buffer_dma_attr, &wpi_dma_accattr,
893 892 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
894 893 &sc->sc_dma_fw_data);
895 894 dma_p = &sc->sc_dma_fw_data;
896 895 WPI_DBG((WPI_DEBUG_DMA, "ncookies:%d addr1:%x size1:%x\n",
897 896 dma_p->ncookies, dma_p->cookie.dmac_address,
898 897 dma_p->cookie.dmac_size));
899 898 if (err != DDI_SUCCESS) {
900 899 cmn_err(CE_WARN, "wpi_alloc_fw_dma(): failed to alloc"
901 900 "data dma memory");
902 901 goto fail;
903 902 }
904 903 for (i = 0; i < dma_p->ncookies; i++) {
905 904 sc->sc_fw_data_cookie[i] = dma_p->cookie;
906 905 ddi_dma_nextcookie(dma_p->dma_hdl, &dma_p->cookie);
907 906 }
908 907 fail:
909 908 return (err);
910 909 }
911 910
912 911 static void
913 912 wpi_free_fw_dma(wpi_sc_t *sc)
914 913 {
915 914 wpi_free_dma_mem(&sc->sc_dma_fw_text);
916 915 wpi_free_dma_mem(&sc->sc_dma_fw_data);
917 916 }
918 917
919 918 /*
920 919 * Allocate a shared page between host and NIC.
921 920 */
922 921 static int
923 922 wpi_alloc_shared(wpi_sc_t *sc)
924 923 {
925 924 int err = DDI_SUCCESS;
926 925
927 926 /* must be aligned on a 4K-page boundary */
928 927 err = wpi_alloc_dma_mem(sc, sizeof (wpi_shared_t),
929 928 &sh_dma_attr, &wpi_dma_accattr,
930 929 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
931 930 &sc->sc_dma_sh);
932 931 if (err != DDI_SUCCESS)
933 932 goto fail;
934 933 sc->sc_shared = (wpi_shared_t *)sc->sc_dma_sh.mem_va;
935 934 return (err);
936 935
937 936 fail:
938 937 wpi_free_shared(sc);
939 938 return (err);
940 939 }
941 940
942 941 static void
943 942 wpi_free_shared(wpi_sc_t *sc)
944 943 {
945 944 wpi_free_dma_mem(&sc->sc_dma_sh);
946 945 }
947 946
948 947 static int
949 948 wpi_alloc_rx_ring(wpi_sc_t *sc)
950 949 {
951 950 wpi_rx_ring_t *ring;
952 951 wpi_rx_data_t *data;
953 952 int i, err = DDI_SUCCESS;
954 953
955 954 ring = &sc->sc_rxq;
956 955 ring->cur = 0;
957 956
958 957 err = wpi_alloc_dma_mem(sc, WPI_RX_RING_COUNT * sizeof (uint32_t),
959 958 &ring_desc_dma_attr, &wpi_dma_accattr,
960 959 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
961 960 &ring->dma_desc);
962 961 if (err != DDI_SUCCESS) {
963 962 WPI_DBG((WPI_DEBUG_DMA, "dma alloc rx ring desc failed\n"));
964 963 goto fail;
965 964 }
966 965 ring->desc = (uint32_t *)ring->dma_desc.mem_va;
967 966
968 967 /*
969 968 * Allocate Rx buffers.
970 969 */
971 970 for (i = 0; i < WPI_RX_RING_COUNT; i++) {
972 971 data = &ring->data[i];
973 972 err = wpi_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
974 973 &rx_buffer_dma_attr, &wpi_dma_accattr,
975 974 DDI_DMA_READ | DDI_DMA_STREAMING,
976 975 &data->dma_data);
977 976 if (err != DDI_SUCCESS) {
978 977 WPI_DBG((WPI_DEBUG_DMA, "dma alloc rx ring buf[%d] "
979 978 "failed\n", i));
980 979 goto fail;
981 980 }
982 981
983 982 ring->desc[i] = LE_32(data->dma_data.cookie.dmac_address);
984 983 }
985 984
986 985 WPI_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
987 986
988 987 return (err);
989 988
990 989 fail:
991 990 wpi_free_rx_ring(sc);
992 991 return (err);
993 992 }
994 993
995 994 static void
996 995 wpi_reset_rx_ring(wpi_sc_t *sc)
997 996 {
998 997 int ntries;
999 998
1000 999 wpi_mem_lock(sc);
1001 1000
1002 1001 WPI_WRITE(sc, WPI_RX_CONFIG, 0);
1003 1002 for (ntries = 0; ntries < 2000; ntries++) {
1004 1003 if (WPI_READ(sc, WPI_RX_STATUS) & WPI_RX_IDLE)
1005 1004 break;
1006 1005 DELAY(1000);
1007 1006 }
1008 1007 if (ntries == 2000)
1009 1008 WPI_DBG((WPI_DEBUG_DMA, "timeout resetting Rx ring\n"));
1010 1009
1011 1010 wpi_mem_unlock(sc);
1012 1011
1013 1012 sc->sc_rxq.cur = 0;
1014 1013 }
1015 1014
1016 1015 static void
1017 1016 wpi_free_rx_ring(wpi_sc_t *sc)
1018 1017 {
1019 1018 int i;
1020 1019
1021 1020 for (i = 0; i < WPI_RX_RING_COUNT; i++) {
1022 1021 if (sc->sc_rxq.data[i].dma_data.dma_hdl)
1023 1022 WPI_DMA_SYNC(sc->sc_rxq.data[i].dma_data,
1024 1023 DDI_DMA_SYNC_FORCPU);
1025 1024 wpi_free_dma_mem(&sc->sc_rxq.data[i].dma_data);
1026 1025 }
1027 1026
1028 1027 if (sc->sc_rxq.dma_desc.dma_hdl)
1029 1028 WPI_DMA_SYNC(sc->sc_rxq.dma_desc, DDI_DMA_SYNC_FORDEV);
1030 1029 wpi_free_dma_mem(&sc->sc_rxq.dma_desc);
1031 1030 }
1032 1031
1033 1032 static int
1034 1033 wpi_alloc_tx_ring(wpi_sc_t *sc, wpi_tx_ring_t *ring, int count, int qid)
1035 1034 {
1036 1035 wpi_tx_data_t *data;
1037 1036 wpi_tx_desc_t *desc_h;
1038 1037 uint32_t paddr_desc_h;
1039 1038 wpi_tx_cmd_t *cmd_h;
1040 1039 uint32_t paddr_cmd_h;
1041 1040 int i, err = DDI_SUCCESS;
1042 1041
1043 1042 ring->qid = qid;
1044 1043 ring->count = count;
1045 1044 ring->queued = 0;
1046 1045 ring->cur = 0;
1047 1046
1048 1047 err = wpi_alloc_dma_mem(sc, count * sizeof (wpi_tx_desc_t),
1049 1048 &ring_desc_dma_attr, &wpi_dma_accattr,
1050 1049 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1051 1050 &ring->dma_desc);
1052 1051 if (err != DDI_SUCCESS) {
1053 1052 WPI_DBG((WPI_DEBUG_DMA, "dma alloc tx ring desc[%d] failed\n",
1054 1053 qid));
1055 1054 goto fail;
1056 1055 }
1057 1056
1058 1057 /* update shared page with ring's base address */
1059 1058 sc->sc_shared->txbase[qid] = ring->dma_desc.cookie.dmac_address;
1060 1059
1061 1060 desc_h = (wpi_tx_desc_t *)ring->dma_desc.mem_va;
1062 1061 paddr_desc_h = ring->dma_desc.cookie.dmac_address;
1063 1062
1064 1063 err = wpi_alloc_dma_mem(sc, count * sizeof (wpi_tx_cmd_t),
1065 1064 &tx_cmd_dma_attr, &wpi_dma_accattr,
1066 1065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1067 1066 &ring->dma_cmd);
1068 1067 if (err != DDI_SUCCESS) {
1069 1068 WPI_DBG((WPI_DEBUG_DMA, "dma alloc tx ring cmd[%d] failed\n",
1070 1069 qid));
1071 1070 goto fail;
1072 1071 }
1073 1072
1074 1073 cmd_h = (wpi_tx_cmd_t *)ring->dma_cmd.mem_va;
1075 1074 paddr_cmd_h = ring->dma_cmd.cookie.dmac_address;
1076 1075
1077 1076 /*
1078 1077 * Allocate Tx buffers.
1079 1078 */
1080 1079 ring->data = kmem_zalloc(sizeof (wpi_tx_data_t) * count, KM_NOSLEEP);
1081 1080 if (ring->data == NULL) {
1082 1081 WPI_DBG((WPI_DEBUG_DMA, "could not allocate tx data slots\n"));
1083 1082 goto fail;
1084 1083 }
1085 1084
1086 1085 for (i = 0; i < count; i++) {
1087 1086 data = &ring->data[i];
1088 1087 err = wpi_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
1089 1088 &tx_buffer_dma_attr, &wpi_dma_accattr,
1090 1089 DDI_DMA_WRITE | DDI_DMA_STREAMING,
1091 1090 &data->dma_data);
1092 1091 if (err != DDI_SUCCESS) {
1093 1092 WPI_DBG((WPI_DEBUG_DMA, "dma alloc tx ring buf[%d] "
1094 1093 "failed\n", i));
1095 1094 goto fail;
1096 1095 }
1097 1096
1098 1097 data->desc = desc_h + i;
1099 1098 data->paddr_desc = paddr_desc_h +
1100 1099 ((uintptr_t)data->desc - (uintptr_t)desc_h);
1101 1100 data->cmd = cmd_h + i;
1102 1101 data->paddr_cmd = paddr_cmd_h +
1103 1102 ((uintptr_t)data->cmd - (uintptr_t)cmd_h);
1104 1103 }
1105 1104
1106 1105 return (err);
1107 1106
1108 1107 fail:
1109 1108 wpi_free_tx_ring(sc, ring);
1110 1109 return (err);
1111 1110 }
1112 1111
1113 1112 static void
1114 1113 wpi_reset_tx_ring(wpi_sc_t *sc, wpi_tx_ring_t *ring)
1115 1114 {
1116 1115 wpi_tx_data_t *data;
1117 1116 int i, ntries;
1118 1117
1119 1118 wpi_mem_lock(sc);
1120 1119
1121 1120 WPI_WRITE(sc, WPI_TX_CONFIG(ring->qid), 0);
1122 1121 for (ntries = 0; ntries < 100; ntries++) {
1123 1122 if (WPI_READ(sc, WPI_TX_STATUS) & WPI_TX_IDLE(ring->qid))
1124 1123 break;
1125 1124 DELAY(10);
1126 1125 }
1127 1126 #ifdef DEBUG
1128 1127 if (ntries == 100 && wpi_dbg_flags > 0) {
1129 1128 WPI_DBG((WPI_DEBUG_DMA, "timeout resetting Tx ring %d\n",
1130 1129 ring->qid));
1131 1130 }
1132 1131 #endif
1133 1132 wpi_mem_unlock(sc);
1134 1133
1135 1134 if (!(sc->sc_flags & WPI_F_QUIESCED)) {
1136 1135 for (i = 0; i < ring->count; i++) {
1137 1136 data = &ring->data[i];
1138 1137 WPI_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
1139 1138 }
1140 1139 }
1141 1140
1142 1141 ring->queued = 0;
1143 1142 ring->cur = 0;
1144 1143 }
1145 1144
1146 1145 /*ARGSUSED*/
1147 1146 static void
1148 1147 wpi_free_tx_ring(wpi_sc_t *sc, wpi_tx_ring_t *ring)
1149 1148 {
1150 1149 int i;
1151 1150
1152 1151 if (ring->dma_desc.dma_hdl != NULL)
1153 1152 WPI_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
1154 1153 wpi_free_dma_mem(&ring->dma_desc);
1155 1154
1156 1155 if (ring->dma_cmd.dma_hdl != NULL)
1157 1156 WPI_DMA_SYNC(ring->dma_cmd, DDI_DMA_SYNC_FORDEV);
1158 1157 wpi_free_dma_mem(&ring->dma_cmd);
1159 1158
1160 1159 if (ring->data != NULL) {
1161 1160 for (i = 0; i < ring->count; i++) {
1162 1161 if (ring->data[i].dma_data.dma_hdl)
1163 1162 WPI_DMA_SYNC(ring->data[i].dma_data,
1164 1163 DDI_DMA_SYNC_FORDEV);
1165 1164 wpi_free_dma_mem(&ring->data[i].dma_data);
1166 1165 }
1167 1166 kmem_free(ring->data, ring->count * sizeof (wpi_tx_data_t));
1168 1167 ring->data = NULL;
1169 1168 }
1170 1169 }
1171 1170
1172 1171 static int
1173 1172 wpi_ring_init(wpi_sc_t *sc)
1174 1173 {
1175 1174 int i, err = DDI_SUCCESS;
1176 1175
1177 1176 for (i = 0; i < 4; i++) {
1178 1177 err = wpi_alloc_tx_ring(sc, &sc->sc_txq[i], WPI_TX_RING_COUNT,
1179 1178 i);
1180 1179 if (err != DDI_SUCCESS)
1181 1180 goto fail;
1182 1181 }
1183 1182 err = wpi_alloc_tx_ring(sc, &sc->sc_cmdq, WPI_CMD_RING_COUNT, 4);
1184 1183 if (err != DDI_SUCCESS)
1185 1184 goto fail;
1186 1185 err = wpi_alloc_tx_ring(sc, &sc->sc_svcq, WPI_SVC_RING_COUNT, 5);
1187 1186 if (err != DDI_SUCCESS)
1188 1187 goto fail;
1189 1188 err = wpi_alloc_rx_ring(sc);
1190 1189 if (err != DDI_SUCCESS)
1191 1190 goto fail;
1192 1191 return (err);
1193 1192
1194 1193 fail:
1195 1194 return (err);
1196 1195 }
1197 1196
1198 1197 static void
1199 1198 wpi_ring_free(wpi_sc_t *sc)
1200 1199 {
1201 1200 int i = 4;
1202 1201
1203 1202 wpi_free_rx_ring(sc);
1204 1203 wpi_free_tx_ring(sc, &sc->sc_svcq);
1205 1204 wpi_free_tx_ring(sc, &sc->sc_cmdq);
1206 1205 while (--i >= 0) {
1207 1206 wpi_free_tx_ring(sc, &sc->sc_txq[i]);
1208 1207 }
1209 1208 }
1210 1209
1211 1210 /* ARGSUSED */
1212 1211 static ieee80211_node_t *
1213 1212 wpi_node_alloc(ieee80211com_t *ic)
1214 1213 {
1215 1214 wpi_amrr_t *amrr;
1216 1215
1217 1216 amrr = kmem_zalloc(sizeof (wpi_amrr_t), KM_SLEEP);
1218 1217 if (amrr != NULL)
1219 1218 wpi_amrr_init(amrr);
1220 1219 return (&amrr->in);
1221 1220 }
1222 1221
1223 1222 static void
1224 1223 wpi_node_free(ieee80211_node_t *in)
1225 1224 {
1226 1225 ieee80211com_t *ic = in->in_ic;
1227 1226
1228 1227 ic->ic_node_cleanup(in);
1229 1228 if (in->in_wpa_ie != NULL)
1230 1229 ieee80211_free(in->in_wpa_ie);
1231 1230 kmem_free(in, sizeof (wpi_amrr_t));
1232 1231 }
1233 1232
1234 1233 /*ARGSUSED*/
1235 1234 static int
1236 1235 wpi_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
1237 1236 {
1238 1237 wpi_sc_t *sc = (wpi_sc_t *)ic;
1239 1238 ieee80211_node_t *in = ic->ic_bss;
1240 1239 enum ieee80211_state ostate;
1241 1240 int i, err = WPI_SUCCESS;
1242 1241
1243 1242 mutex_enter(&sc->sc_glock);
1244 1243 ostate = ic->ic_state;
1245 1244 switch (nstate) {
1246 1245 case IEEE80211_S_SCAN:
1247 1246 switch (ostate) {
1248 1247 case IEEE80211_S_INIT:
1249 1248 {
1250 1249 wpi_node_t node;
1251 1250
1252 1251 sc->sc_flags |= WPI_F_SCANNING;
1253 1252 sc->sc_scan_next = 0;
1254 1253
1255 1254 /* make the link LED blink while we're scanning */
1256 1255 wpi_set_led(sc, WPI_LED_LINK, 20, 2);
1257 1256
1258 1257 /*
1259 1258 * clear association to receive beacons from all
1260 1259 * BSS'es
1261 1260 */
1262 1261 sc->sc_config.state = 0;
1263 1262 sc->sc_config.filter &= ~LE_32(WPI_FILTER_BSS);
1264 1263
1265 1264 WPI_DBG((WPI_DEBUG_80211, "config chan %d flags %x "
1266 1265 "filter %x\n",
1267 1266 sc->sc_config.chan, sc->sc_config.flags,
1268 1267 sc->sc_config.filter));
1269 1268
1270 1269 err = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->sc_config,
1271 1270 sizeof (wpi_config_t), 1);
1272 1271 if (err != WPI_SUCCESS) {
1273 1272 cmn_err(CE_WARN,
1274 1273 "could not clear association\n");
1275 1274 sc->sc_flags &= ~WPI_F_SCANNING;
1276 1275 mutex_exit(&sc->sc_glock);
1277 1276 return (err);
1278 1277 }
1279 1278
1280 1279 /* add broadcast node to send probe request */
1281 1280 (void) memset(&node, 0, sizeof (node));
1282 1281 (void) memset(&node.bssid, 0xff, IEEE80211_ADDR_LEN);
1283 1282 node.id = WPI_ID_BROADCAST;
1284 1283
1285 1284 err = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node,
1286 1285 sizeof (node), 1);
1287 1286 if (err != WPI_SUCCESS) {
1288 1287 cmn_err(CE_WARN,
1289 1288 "could not add broadcast node\n");
1290 1289 sc->sc_flags &= ~WPI_F_SCANNING;
1291 1290 mutex_exit(&sc->sc_glock);
1292 1291 return (err);
1293 1292 }
1294 1293 break;
1295 1294 }
1296 1295 case IEEE80211_S_SCAN:
1297 1296 mutex_exit(&sc->sc_glock);
1298 1297 /* step to next channel before actual FW scan */
1299 1298 err = sc->sc_newstate(ic, nstate, arg);
1300 1299 mutex_enter(&sc->sc_glock);
1301 1300 if ((err != 0) || ((err = wpi_scan(sc)) != 0)) {
1302 1301 cmn_err(CE_WARN,
1303 1302 "could not initiate scan\n");
1304 1303 sc->sc_flags &= ~WPI_F_SCANNING;
1305 1304 ieee80211_cancel_scan(ic);
1306 1305 }
1307 1306 mutex_exit(&sc->sc_glock);
1308 1307 return (err);
1309 1308 default:
1310 1309 break;
1311 1310 }
1312 1311 sc->sc_clk = 0;
1313 1312 break;
1314 1313
1315 1314 case IEEE80211_S_AUTH:
1316 1315 if (ostate == IEEE80211_S_SCAN) {
1317 1316 sc->sc_flags &= ~WPI_F_SCANNING;
1318 1317 }
1319 1318
1320 1319 /* reset state to handle reassociations correctly */
1321 1320 sc->sc_config.state = 0;
1322 1321 sc->sc_config.filter &= ~LE_32(WPI_FILTER_BSS);
1323 1322
1324 1323 if ((err = wpi_auth(sc)) != 0) {
1325 1324 WPI_DBG((WPI_DEBUG_80211,
1326 1325 "could not send authentication request\n"));
1327 1326 mutex_exit(&sc->sc_glock);
1328 1327 return (err);
1329 1328 }
1330 1329 break;
1331 1330
1332 1331 case IEEE80211_S_RUN:
1333 1332 if (ostate == IEEE80211_S_SCAN) {
1334 1333 sc->sc_flags &= ~WPI_F_SCANNING;
1335 1334 }
1336 1335
1337 1336 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
1338 1337 /* link LED blinks while monitoring */
1339 1338 wpi_set_led(sc, WPI_LED_LINK, 5, 5);
1340 1339 break;
1341 1340 }
1342 1341
1343 1342 if (ic->ic_opmode != IEEE80211_M_STA) {
1344 1343 (void) wpi_auth(sc);
1345 1344 /* need setup beacon here */
1346 1345 }
1347 1346 WPI_DBG((WPI_DEBUG_80211, "wpi: associated."));
1348 1347
1349 1348 /* update adapter's configuration */
1350 1349 sc->sc_config.state = LE_16(WPI_CONFIG_ASSOCIATED);
1351 1350 /* short preamble/slot time are negotiated when associating */
1352 1351 sc->sc_config.flags &= ~LE_32(WPI_CONFIG_SHPREAMBLE |
1353 1352 WPI_CONFIG_SHSLOT);
1354 1353 if (ic->ic_flags & IEEE80211_F_SHSLOT)
1355 1354 sc->sc_config.flags |= LE_32(WPI_CONFIG_SHSLOT);
1356 1355 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
1357 1356 sc->sc_config.flags |= LE_32(WPI_CONFIG_SHPREAMBLE);
1358 1357 sc->sc_config.filter |= LE_32(WPI_FILTER_BSS);
1359 1358 if (ic->ic_opmode != IEEE80211_M_STA)
1360 1359 sc->sc_config.filter |= LE_32(WPI_FILTER_BEACON);
1361 1360
1362 1361 WPI_DBG((WPI_DEBUG_80211, "config chan %d flags %x\n",
1363 1362 sc->sc_config.chan, sc->sc_config.flags));
1364 1363 err = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->sc_config,
1365 1364 sizeof (wpi_config_t), 1);
1366 1365 if (err != WPI_SUCCESS) {
1367 1366 WPI_DBG((WPI_DEBUG_80211,
1368 1367 "could not update configuration\n"));
1369 1368 mutex_exit(&sc->sc_glock);
1370 1369 return (err);
1371 1370 }
1372 1371
1373 1372 /* start automatic rate control */
1374 1373 mutex_enter(&sc->sc_mt_lock);
1375 1374 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
1376 1375 sc->sc_flags |= WPI_F_RATE_AUTO_CTL;
1377 1376 /* set rate to some reasonable initial value */
1378 1377 i = in->in_rates.ir_nrates - 1;
1379 1378 while (i > 0 && IEEE80211_RATE(i) > 72)
1380 1379 i--;
1381 1380 in->in_txrate = i;
1382 1381 } else {
1383 1382 sc->sc_flags &= ~WPI_F_RATE_AUTO_CTL;
1384 1383 }
1385 1384 mutex_exit(&sc->sc_mt_lock);
1386 1385
1387 1386 /* link LED always on while associated */
1388 1387 wpi_set_led(sc, WPI_LED_LINK, 0, 1);
1389 1388 break;
1390 1389
1391 1390 case IEEE80211_S_INIT:
1392 1391 sc->sc_flags &= ~WPI_F_SCANNING;
1393 1392 break;
1394 1393
1395 1394 case IEEE80211_S_ASSOC:
1396 1395 sc->sc_flags &= ~WPI_F_SCANNING;
1397 1396 break;
1398 1397 }
1399 1398
1400 1399 mutex_exit(&sc->sc_glock);
1401 1400 return (sc->sc_newstate(ic, nstate, arg));
1402 1401 }
1403 1402
1404 1403 /*ARGSUSED*/
1405 1404 static int wpi_key_set(ieee80211com_t *ic, const struct ieee80211_key *k,
1406 1405 const uint8_t mac[IEEE80211_ADDR_LEN])
1407 1406 {
1408 1407 wpi_sc_t *sc = (wpi_sc_t *)ic;
1409 1408 wpi_node_t node;
1410 1409 int err;
1411 1410
1412 1411 switch (k->wk_cipher->ic_cipher) {
1413 1412 case IEEE80211_CIPHER_WEP:
1414 1413 case IEEE80211_CIPHER_TKIP:
1415 1414 return (1); /* sofeware do it. */
1416 1415 case IEEE80211_CIPHER_AES_CCM:
1417 1416 break;
1418 1417 default:
1419 1418 return (0);
1420 1419 }
1421 1420 sc->sc_config.filter &= ~(WPI_FILTER_NODECRYPTUNI |
1422 1421 WPI_FILTER_NODECRYPTMUL);
1423 1422
1424 1423 mutex_enter(&sc->sc_glock);
1425 1424
1426 1425 /* update ap/multicast node */
1427 1426 (void) memset(&node, 0, sizeof (node));
1428 1427 if (IEEE80211_IS_MULTICAST(mac)) {
1429 1428 (void) memset(node.bssid, 0xff, 6);
1430 1429 node.id = WPI_ID_BROADCAST;
1431 1430 } else {
1432 1431 IEEE80211_ADDR_COPY(node.bssid, ic->ic_bss->in_bssid);
1433 1432 node.id = WPI_ID_BSS;
1434 1433 }
1435 1434 if (k->wk_flags & IEEE80211_KEY_XMIT) {
1436 1435 node.key_flags = 0;
1437 1436 node.keyp = k->wk_keyix;
1438 1437 } else {
1439 1438 node.key_flags = (1 << 14);
1440 1439 node.keyp = k->wk_keyix + 4;
1441 1440 }
1442 1441 (void) memcpy(node.key, k->wk_key, k->wk_keylen);
1443 1442 node.key_flags |= (2 | (1 << 3) | (k->wk_keyix << 8));
1444 1443 node.sta_mask = 1;
1445 1444 node.control = 1;
1446 1445 err = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof (node), 1);
1447 1446 if (err != WPI_SUCCESS) {
1448 1447 cmn_err(CE_WARN, "wpi_key_set():"
1449 1448 "failed to update ap node\n");
1450 1449 mutex_exit(&sc->sc_glock);
1451 1450 return (0);
1452 1451 }
1453 1452 mutex_exit(&sc->sc_glock);
1454 1453 return (1);
1455 1454 }
1456 1455
1457 1456 /*
1458 1457 * Grab exclusive access to NIC memory.
1459 1458 */
1460 1459 static void
1461 1460 wpi_mem_lock(wpi_sc_t *sc)
1462 1461 {
1463 1462 uint32_t tmp;
1464 1463 int ntries;
1465 1464
1466 1465 tmp = WPI_READ(sc, WPI_GPIO_CTL);
1467 1466 WPI_WRITE(sc, WPI_GPIO_CTL, tmp | WPI_GPIO_MAC);
1468 1467
1469 1468 /* spin until we actually get the lock */
1470 1469 for (ntries = 0; ntries < 1000; ntries++) {
1471 1470 if ((WPI_READ(sc, WPI_GPIO_CTL) &
1472 1471 (WPI_GPIO_CLOCK | WPI_GPIO_SLEEP)) == WPI_GPIO_CLOCK)
1473 1472 break;
1474 1473 DELAY(10);
1475 1474 }
1476 1475 if (ntries == 1000)
1477 1476 WPI_DBG((WPI_DEBUG_PIO, "could not lock memory\n"));
1478 1477 }
1479 1478
1480 1479 /*
1481 1480 * Release lock on NIC memory.
1482 1481 */
1483 1482 static void
1484 1483 wpi_mem_unlock(wpi_sc_t *sc)
1485 1484 {
1486 1485 uint32_t tmp = WPI_READ(sc, WPI_GPIO_CTL);
1487 1486 WPI_WRITE(sc, WPI_GPIO_CTL, tmp & ~WPI_GPIO_MAC);
1488 1487 }
1489 1488
1490 1489 static uint32_t
1491 1490 wpi_mem_read(wpi_sc_t *sc, uint16_t addr)
1492 1491 {
1493 1492 WPI_WRITE(sc, WPI_READ_MEM_ADDR, WPI_MEM_4 | addr);
1494 1493 return (WPI_READ(sc, WPI_READ_MEM_DATA));
1495 1494 }
1496 1495
1497 1496 static void
1498 1497 wpi_mem_write(wpi_sc_t *sc, uint16_t addr, uint32_t data)
1499 1498 {
1500 1499 WPI_WRITE(sc, WPI_WRITE_MEM_ADDR, WPI_MEM_4 | addr);
1501 1500 WPI_WRITE(sc, WPI_WRITE_MEM_DATA, data);
1502 1501 }
1503 1502
1504 1503 static void
1505 1504 wpi_mem_write_region_4(wpi_sc_t *sc, uint16_t addr,
1506 1505 const uint32_t *data, int wlen)
1507 1506 {
1508 1507 for (; wlen > 0; wlen--, data++, addr += 4)
1509 1508 wpi_mem_write(sc, addr, *data);
1510 1509 }
1511 1510
1512 1511 /*
1513 1512 * Read 16 bits from the EEPROM. We access EEPROM through the MAC instead of
1514 1513 * using the traditional bit-bang method.
1515 1514 */
1516 1515 static uint16_t
1517 1516 wpi_read_prom_word(wpi_sc_t *sc, uint32_t addr)
1518 1517 {
1519 1518 uint32_t val;
1520 1519 int ntries;
1521 1520
1522 1521 WPI_WRITE(sc, WPI_EEPROM_CTL, addr << 2);
1523 1522
1524 1523 wpi_mem_lock(sc);
1525 1524 for (ntries = 0; ntries < 10; ntries++) {
1526 1525 if ((val = WPI_READ(sc, WPI_EEPROM_CTL)) & WPI_EEPROM_READY)
1527 1526 break;
1528 1527 DELAY(10);
1529 1528 }
1530 1529 wpi_mem_unlock(sc);
1531 1530
1532 1531 if (ntries == 10) {
1533 1532 WPI_DBG((WPI_DEBUG_PIO, "could not read EEPROM\n"));
1534 1533 return (0xdead);
1535 1534 }
1536 1535 return (val >> 16);
1537 1536 }
1538 1537
1539 1538 /*
1540 1539 * The firmware boot code is small and is intended to be copied directly into
1541 1540 * the NIC internal memory.
1542 1541 */
1543 1542 static int
1544 1543 wpi_load_microcode(wpi_sc_t *sc)
1545 1544 {
1546 1545 const char *ucode;
1547 1546 int size;
1548 1547
1549 1548 ucode = sc->sc_boot;
1550 1549 size = LE_32(sc->sc_hdr->bootsz);
1551 1550 /* check that microcode size is a multiple of 4 */
1552 1551 if (size & 3)
1553 1552 return (EINVAL);
1554 1553
1555 1554 size /= sizeof (uint32_t);
1556 1555
1557 1556 wpi_mem_lock(sc);
1558 1557
1559 1558 /* copy microcode image into NIC memory */
1560 1559 wpi_mem_write_region_4(sc, WPI_MEM_UCODE_BASE, (const uint32_t *)ucode,
1561 1560 size);
1562 1561
1563 1562 wpi_mem_write(sc, WPI_MEM_UCODE_SRC, 0);
1564 1563 wpi_mem_write(sc, WPI_MEM_UCODE_DST, WPI_FW_TEXT);
1565 1564 wpi_mem_write(sc, WPI_MEM_UCODE_SIZE, size);
1566 1565
1567 1566 /* run microcode */
1568 1567 wpi_mem_write(sc, WPI_MEM_UCODE_CTL, WPI_UC_RUN);
1569 1568
1570 1569 wpi_mem_unlock(sc);
1571 1570
1572 1571 return (WPI_SUCCESS);
1573 1572 }
1574 1573
1575 1574 /*
1576 1575 * The firmware text and data segments are transferred to the NIC using DMA.
1577 1576 * The driver just copies the firmware into DMA-safe memory and tells the NIC
1578 1577 * where to find it. Once the NIC has copied the firmware into its internal
1579 1578 * memory, we can free our local copy in the driver.
1580 1579 */
1581 1580 static int
1582 1581 wpi_load_firmware(wpi_sc_t *sc, uint32_t target)
1583 1582 {
1584 1583 const char *fw;
1585 1584 int size;
1586 1585 wpi_dma_t *dma_p;
1587 1586 ddi_dma_cookie_t *cookie;
1588 1587 wpi_tx_desc_t desc;
1589 1588 int i, ntries, err = WPI_SUCCESS;
1590 1589
1591 1590 /* only text and data here */
1592 1591 if (target == WPI_FW_TEXT) {
1593 1592 fw = sc->sc_text;
1594 1593 size = LE_32(sc->sc_hdr->textsz);
1595 1594 dma_p = &sc->sc_dma_fw_text;
1596 1595 cookie = sc->sc_fw_text_cookie;
1597 1596 } else {
1598 1597 fw = sc->sc_data;
1599 1598 size = LE_32(sc->sc_hdr->datasz);
1600 1599 dma_p = &sc->sc_dma_fw_data;
1601 1600 cookie = sc->sc_fw_data_cookie;
1602 1601 }
1603 1602
1604 1603 /* copy firmware image to DMA-safe memory */
1605 1604 (void) memcpy(dma_p->mem_va, fw, size);
1606 1605
1607 1606 /* make sure the adapter will get up-to-date values */
1608 1607 (void) ddi_dma_sync(dma_p->dma_hdl, 0, size, DDI_DMA_SYNC_FORDEV);
1609 1608
1610 1609 (void) memset(&desc, 0, sizeof (desc));
1611 1610 desc.flags = LE_32(WPI_PAD32(size) << 28 | dma_p->ncookies << 24);
1612 1611 for (i = 0; i < dma_p->ncookies; i++) {
1613 1612 WPI_DBG((WPI_DEBUG_DMA, "cookie%d addr:%x size:%x\n",
1614 1613 i, cookie[i].dmac_address, cookie[i].dmac_size));
1615 1614 desc.segs[i].addr = cookie[i].dmac_address;
1616 1615 desc.segs[i].len = (uint32_t)cookie[i].dmac_size;
1617 1616 }
1618 1617
1619 1618 wpi_mem_lock(sc);
1620 1619
1621 1620 /* tell adapter where to copy image in its internal memory */
1622 1621 WPI_WRITE(sc, WPI_FW_TARGET, target);
1623 1622
1624 1623 WPI_WRITE(sc, WPI_TX_CONFIG(6), 0);
1625 1624
1626 1625 /* copy firmware descriptor into NIC memory */
1627 1626 WPI_WRITE_REGION_4(sc, WPI_TX_DESC(6), (uint32_t *)&desc,
1628 1627 sizeof desc / sizeof (uint32_t));
1629 1628
1630 1629 WPI_WRITE(sc, WPI_TX_CREDIT(6), 0xfffff);
1631 1630 WPI_WRITE(sc, WPI_TX_STATE(6), 0x4001);
1632 1631 WPI_WRITE(sc, WPI_TX_CONFIG(6), 0x80000001);
1633 1632
1634 1633 /* wait while the adapter is busy copying the firmware */
1635 1634 for (ntries = 0; ntries < 100; ntries++) {
1636 1635 if (WPI_READ(sc, WPI_TX_STATUS) & WPI_TX_IDLE(6))
1637 1636 break;
1638 1637 DELAY(1000);
1639 1638 }
1640 1639 if (ntries == 100) {
1641 1640 WPI_DBG((WPI_DEBUG_FW, "timeout transferring firmware\n"));
1642 1641 err = ETIMEDOUT;
1643 1642 }
1644 1643
1645 1644 WPI_WRITE(sc, WPI_TX_CREDIT(6), 0);
1646 1645
1647 1646 wpi_mem_unlock(sc);
1648 1647
1649 1648 return (err);
1650 1649 }
1651 1650
1652 1651 /*ARGSUSED*/
1653 1652 static void
1654 1653 wpi_rx_intr(wpi_sc_t *sc, wpi_rx_desc_t *desc, wpi_rx_data_t *data)
1655 1654 {
1656 1655 ieee80211com_t *ic = &sc->sc_ic;
1657 1656 wpi_rx_ring_t *ring = &sc->sc_rxq;
1658 1657 wpi_rx_stat_t *stat;
1659 1658 wpi_rx_head_t *head;
1660 1659 wpi_rx_tail_t *tail;
1661 1660 ieee80211_node_t *in;
1662 1661 struct ieee80211_frame *wh;
1663 1662 mblk_t *mp;
1664 1663 uint16_t len;
1665 1664
1666 1665 stat = (wpi_rx_stat_t *)(desc + 1);
1667 1666
1668 1667 if (stat->len > WPI_STAT_MAXLEN) {
1669 1668 WPI_DBG((WPI_DEBUG_RX, "invalid rx statistic header\n"));
1670 1669 return;
1671 1670 }
1672 1671
1673 1672 head = (wpi_rx_head_t *)((caddr_t)(stat + 1) + stat->len);
1674 1673 tail = (wpi_rx_tail_t *)((caddr_t)(head + 1) + LE_16(head->len));
1675 1674
1676 1675 len = LE_16(head->len);
1677 1676
1678 1677 WPI_DBG((WPI_DEBUG_RX, "rx intr: idx=%d len=%d stat len=%d rssi=%d "
1679 1678 "rate=%x chan=%d tstamp=%llu", ring->cur, LE_32(desc->len),
1680 1679 len, (int8_t)stat->rssi, head->rate, head->chan,
1681 1680 LE_64(tail->tstamp)));
1682 1681
1683 1682 if ((len < 20) || (len > sc->sc_dmabuf_sz)) {
1684 1683 sc->sc_rx_err++;
1685 1684 return;
1686 1685 }
1687 1686
1688 1687 /*
1689 1688 * Discard Rx frames with bad CRC early
1690 1689 */
1691 1690 if ((LE_32(tail->flags) & WPI_RX_NOERROR) != WPI_RX_NOERROR) {
1692 1691 WPI_DBG((WPI_DEBUG_RX, "rx tail flags error %x\n",
1693 1692 LE_32(tail->flags)));
1694 1693 sc->sc_rx_err++;
1695 1694 return;
1696 1695 }
1697 1696
1698 1697 /* update Rx descriptor */
1699 1698 /* ring->desc[ring->cur] = LE_32(data->dma_data.cookie.dmac_address); */
1700 1699
1701 1700 #ifdef WPI_BPF
1702 1701 #ifndef WPI_CURRENT
1703 1702 if (sc->sc_drvbpf != NULL) {
1704 1703 #else
1705 1704 if (bpf_peers_present(sc->sc_drvbpf)) {
1706 1705 #endif
1707 1706 struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap;
1708 1707
1709 1708 tap->wr_flags = 0;
1710 1709 tap->wr_rate = head->rate;
1711 1710 tap->wr_chan_freq =
1712 1711 LE_16(ic->ic_channels[head->chan].ic_freq);
1713 1712 tap->wr_chan_flags =
1714 1713 LE_16(ic->ic_channels[head->chan].ic_flags);
1715 1714 tap->wr_dbm_antsignal = (int8_t)(stat->rssi - WPI_RSSI_OFFSET);
1716 1715 tap->wr_dbm_antnoise = (int8_t)LE_16(stat->noise);
1717 1716 tap->wr_tsft = tail->tstamp;
1718 1717 tap->wr_antenna = (LE_16(head->flags) >> 4) & 0xf;
1719 1718 switch (head->rate) {
1720 1719 /* CCK rates */
1721 1720 case 10: tap->wr_rate = 2; break;
1722 1721 case 20: tap->wr_rate = 4; break;
1723 1722 case 55: tap->wr_rate = 11; break;
1724 1723 case 110: tap->wr_rate = 22; break;
1725 1724 /* OFDM rates */
1726 1725 case 0xd: tap->wr_rate = 12; break;
1727 1726 case 0xf: tap->wr_rate = 18; break;
1728 1727 case 0x5: tap->wr_rate = 24; break;
1729 1728 case 0x7: tap->wr_rate = 36; break;
1730 1729 case 0x9: tap->wr_rate = 48; break;
1731 1730 case 0xb: tap->wr_rate = 72; break;
1732 1731 case 0x1: tap->wr_rate = 96; break;
1733 1732 case 0x3: tap->wr_rate = 108; break;
1734 1733 /* unknown rate: should not happen */
1735 1734 default: tap->wr_rate = 0;
1736 1735 }
1737 1736 if (LE_16(head->flags) & 0x4)
1738 1737 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
1739 1738
1740 1739 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
1741 1740 }
1742 1741 #endif
1743 1742 /* grab a reference to the source node */
1744 1743 wh = (struct ieee80211_frame *)(head + 1);
1745 1744
1746 1745 #ifdef DEBUG
1747 1746 if (wpi_dbg_flags & WPI_DEBUG_RX)
1748 1747 ieee80211_dump_pkt((uint8_t *)wh, len, 0, 0);
1749 1748 #endif
1750 1749
1751 1750 in = ieee80211_find_rxnode(ic, wh);
1752 1751 mp = allocb(len, BPRI_MED);
1753 1752 if (mp) {
1754 1753 (void) memcpy(mp->b_wptr, wh, len);
1755 1754 mp->b_wptr += len;
1756 1755
1757 1756 /* send the frame to the 802.11 layer */
1758 1757 (void) ieee80211_input(ic, mp, in, stat->rssi, 0);
1759 1758 } else {
1760 1759 sc->sc_rx_nobuf++;
1761 1760 WPI_DBG((WPI_DEBUG_RX,
1762 1761 "wpi_rx_intr(): alloc rx buf failed\n"));
1763 1762 }
1764 1763 /* release node reference */
1765 1764 ieee80211_free_node(in);
1766 1765 }
1767 1766
1768 1767 /*ARGSUSED*/
1769 1768 static void
1770 1769 wpi_tx_intr(wpi_sc_t *sc, wpi_rx_desc_t *desc, wpi_rx_data_t *data)
1771 1770 {
1772 1771 ieee80211com_t *ic = &sc->sc_ic;
1773 1772 wpi_tx_ring_t *ring = &sc->sc_txq[desc->qid & 0x3];
1774 1773 /* wpi_tx_data_t *txdata = &ring->data[desc->idx]; */
1775 1774 wpi_tx_stat_t *stat = (wpi_tx_stat_t *)(desc + 1);
1776 1775 wpi_amrr_t *amrr = (wpi_amrr_t *)ic->ic_bss;
1777 1776
1778 1777 WPI_DBG((WPI_DEBUG_TX, "tx done: qid=%d idx=%d retries=%d nkill=%d "
1779 1778 "rate=%x duration=%d status=%x\n",
1780 1779 desc->qid, desc->idx, stat->ntries, stat->nkill, stat->rate,
1781 1780 LE_32(stat->duration), LE_32(stat->status)));
1782 1781
1783 1782 amrr->txcnt++;
1784 1783 WPI_DBG((WPI_DEBUG_RATECTL, "tx: %d cnt\n", amrr->txcnt));
1785 1784 if (stat->ntries > 0) {
1786 1785 amrr->retrycnt++;
1787 1786 sc->sc_tx_retries++;
1788 1787 WPI_DBG((WPI_DEBUG_RATECTL, "tx: %d retries\n",
1789 1788 amrr->retrycnt));
1790 1789 }
1791 1790
1792 1791 sc->sc_tx_timer = 0;
1793 1792
1794 1793 mutex_enter(&sc->sc_tx_lock);
1795 1794 ring->queued--;
1796 1795 if (ring->queued < 0)
1797 1796 ring->queued = 0;
1798 1797 if ((sc->sc_need_reschedule) && (ring->queued <= (ring->count << 3))) {
1799 1798 sc->sc_need_reschedule = 0;
1800 1799 mutex_exit(&sc->sc_tx_lock);
1801 1800 mac_tx_update(ic->ic_mach);
1802 1801 mutex_enter(&sc->sc_tx_lock);
1803 1802 }
1804 1803 mutex_exit(&sc->sc_tx_lock);
1805 1804 }
1806 1805
1807 1806 static void
1808 1807 wpi_cmd_intr(wpi_sc_t *sc, wpi_rx_desc_t *desc)
1809 1808 {
1810 1809 if ((desc->qid & 7) != 4) {
1811 1810 return; /* not a command ack */
1812 1811 }
1813 1812 mutex_enter(&sc->sc_glock);
1814 1813 sc->sc_flags |= WPI_F_CMD_DONE;
1815 1814 cv_signal(&sc->sc_cmd_cv);
1816 1815 mutex_exit(&sc->sc_glock);
1817 1816 }
1818 1817
1819 1818 static uint_t
1820 1819 wpi_notif_softintr(caddr_t arg)
1821 1820 {
1822 1821 wpi_sc_t *sc = (wpi_sc_t *)arg;
1823 1822 wpi_rx_desc_t *desc;
1824 1823 wpi_rx_data_t *data;
1825 1824 uint32_t hw;
1826 1825
1827 1826 mutex_enter(&sc->sc_glock);
1828 1827 if (sc->sc_notif_softint_pending != 1) {
1829 1828 mutex_exit(&sc->sc_glock);
1830 1829 return (DDI_INTR_UNCLAIMED);
1831 1830 }
1832 1831 mutex_exit(&sc->sc_glock);
1833 1832
1834 1833 hw = LE_32(sc->sc_shared->next);
1835 1834
1836 1835 while (sc->sc_rxq.cur != hw) {
1837 1836 data = &sc->sc_rxq.data[sc->sc_rxq.cur];
1838 1837 desc = (wpi_rx_desc_t *)data->dma_data.mem_va;
1839 1838
1840 1839 WPI_DBG((WPI_DEBUG_INTR, "rx notification hw = %d cur = %d "
1841 1840 "qid=%x idx=%d flags=%x type=%d len=%d\n",
1842 1841 hw, sc->sc_rxq.cur, desc->qid, desc->idx, desc->flags,
1843 1842 desc->type, LE_32(desc->len)));
1844 1843
1845 1844 if (!(desc->qid & 0x80)) /* reply to a command */
1846 1845 wpi_cmd_intr(sc, desc);
1847 1846
1848 1847 switch (desc->type) {
1849 1848 case WPI_RX_DONE:
1850 1849 /* a 802.11 frame was received */
1851 1850 wpi_rx_intr(sc, desc, data);
1852 1851 break;
1853 1852
1854 1853 case WPI_TX_DONE:
1855 1854 /* a 802.11 frame has been transmitted */
1856 1855 wpi_tx_intr(sc, desc, data);
1857 1856 break;
1858 1857
1859 1858 case WPI_UC_READY:
1860 1859 {
1861 1860 wpi_ucode_info_t *uc =
1862 1861 (wpi_ucode_info_t *)(desc + 1);
1863 1862
1864 1863 /* the microcontroller is ready */
1865 1864 WPI_DBG((WPI_DEBUG_FW,
1866 1865 "microcode alive notification version %x "
1867 1866 "alive %x\n", LE_32(uc->version),
1868 1867 LE_32(uc->valid)));
1869 1868
1870 1869 if (LE_32(uc->valid) != 1) {
1871 1870 WPI_DBG((WPI_DEBUG_FW,
1872 1871 "microcontroller initialization failed\n"));
1873 1872 }
1874 1873 break;
1875 1874 }
1876 1875 case WPI_STATE_CHANGED:
1877 1876 {
1878 1877 uint32_t *status = (uint32_t *)(desc + 1);
1879 1878
1880 1879 /* enabled/disabled notification */
1881 1880 WPI_DBG((WPI_DEBUG_RADIO, "state changed to %x\n",
1882 1881 LE_32(*status)));
1883 1882
1884 1883 if (LE_32(*status) & 1) {
1885 1884 /*
1886 1885 * the radio button has to be pushed(OFF). It
1887 1886 * is considered as a hw error, the
1888 1887 * wpi_thread() tries to recover it after the
1889 1888 * button is pushed again(ON)
1890 1889 */
1891 1890 cmn_err(CE_NOTE,
1892 1891 "wpi: Radio transmitter is off\n");
1893 1892 sc->sc_ostate = sc->sc_ic.ic_state;
1894 1893 ieee80211_new_state(&sc->sc_ic,
1895 1894 IEEE80211_S_INIT, -1);
1896 1895 sc->sc_flags |=
1897 1896 (WPI_F_HW_ERR_RECOVER | WPI_F_RADIO_OFF);
1898 1897 }
1899 1898 break;
1900 1899 }
1901 1900 case WPI_START_SCAN:
1902 1901 {
1903 1902 wpi_start_scan_t *scan =
1904 1903 (wpi_start_scan_t *)(desc + 1);
1905 1904
1906 1905 WPI_DBG((WPI_DEBUG_SCAN,
1907 1906 "scanning channel %d status %x\n",
1908 1907 scan->chan, LE_32(scan->status)));
1909 1908
1910 1909 break;
1911 1910 }
1912 1911 case WPI_STOP_SCAN:
1913 1912 {
1914 1913 wpi_stop_scan_t *scan =
1915 1914 (wpi_stop_scan_t *)(desc + 1);
1916 1915
1917 1916 WPI_DBG((WPI_DEBUG_SCAN,
1918 1917 "completed channel %d (burst of %d) status %02x\n",
1919 1918 scan->chan, scan->nchan, scan->status));
1920 1919
1921 1920 sc->sc_scan_pending = 0;
1922 1921 sc->sc_scan_next++;
1923 1922 break;
1924 1923 }
1925 1924 default:
1926 1925 break;
1927 1926 }
1928 1927
1929 1928 sc->sc_rxq.cur = (sc->sc_rxq.cur + 1) % WPI_RX_RING_COUNT;
1930 1929 }
1931 1930
1932 1931 /* tell the firmware what we have processed */
1933 1932 hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1;
1934 1933 WPI_WRITE(sc, WPI_RX_WIDX, hw & (~7));
1935 1934 mutex_enter(&sc->sc_glock);
1936 1935 sc->sc_notif_softint_pending = 0;
1937 1936 mutex_exit(&sc->sc_glock);
1938 1937
1939 1938 return (DDI_INTR_CLAIMED);
1940 1939 }
1941 1940
1942 1941 static uint_t
1943 1942 wpi_intr(caddr_t arg)
1944 1943 {
1945 1944 wpi_sc_t *sc = (wpi_sc_t *)arg;
1946 1945 uint32_t r, rfh;
1947 1946
1948 1947 mutex_enter(&sc->sc_glock);
1949 1948 if (sc->sc_flags & WPI_F_SUSPEND) {
1950 1949 mutex_exit(&sc->sc_glock);
1951 1950 return (DDI_INTR_UNCLAIMED);
1952 1951 }
1953 1952
1954 1953 r = WPI_READ(sc, WPI_INTR);
1955 1954 if (r == 0 || r == 0xffffffff) {
1956 1955 mutex_exit(&sc->sc_glock);
1957 1956 return (DDI_INTR_UNCLAIMED);
1958 1957 }
1959 1958
1960 1959 WPI_DBG((WPI_DEBUG_INTR, "interrupt reg %x\n", r));
1961 1960
1962 1961 rfh = WPI_READ(sc, WPI_INTR_STATUS);
1963 1962 /* disable interrupts */
1964 1963 WPI_WRITE(sc, WPI_MASK, 0);
1965 1964 /* ack interrupts */
1966 1965 WPI_WRITE(sc, WPI_INTR, r);
1967 1966 WPI_WRITE(sc, WPI_INTR_STATUS, rfh);
1968 1967
1969 1968 if (sc->sc_notif_softint_id == NULL) {
1970 1969 mutex_exit(&sc->sc_glock);
1971 1970 return (DDI_INTR_CLAIMED);
1972 1971 }
1973 1972
1974 1973 if (r & (WPI_SW_ERROR | WPI_HW_ERROR)) {
1975 1974 WPI_DBG((WPI_DEBUG_FW, "fatal firmware error\n"));
1976 1975 mutex_exit(&sc->sc_glock);
1977 1976 wpi_stop(sc);
1978 1977 if (!(sc->sc_flags & WPI_F_HW_ERR_RECOVER)) {
1979 1978 sc->sc_ostate = sc->sc_ic.ic_state;
1980 1979 }
1981 1980
1982 1981 /* not capable of fast recovery */
1983 1982 if (!WPI_CHK_FAST_RECOVER(sc))
1984 1983 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
1985 1984
1986 1985 sc->sc_flags |= WPI_F_HW_ERR_RECOVER;
1987 1986 return (DDI_INTR_CLAIMED);
1988 1987 }
1989 1988
1990 1989 if ((r & (WPI_RX_INTR | WPI_RX_SWINT)) ||
1991 1990 (rfh & 0x40070000)) {
1992 1991 sc->sc_notif_softint_pending = 1;
1993 1992 ddi_trigger_softintr(sc->sc_notif_softint_id);
1994 1993 }
1995 1994
1996 1995 if (r & WPI_ALIVE_INTR) { /* firmware initialized */
1997 1996 sc->sc_flags |= WPI_F_FW_INIT;
1998 1997 cv_signal(&sc->sc_fw_cv);
1999 1998 }
2000 1999
2001 2000 /* re-enable interrupts */
2002 2001 WPI_WRITE(sc, WPI_MASK, WPI_INTR_MASK);
2003 2002 mutex_exit(&sc->sc_glock);
2004 2003
2005 2004 return (DDI_INTR_CLAIMED);
2006 2005 }
2007 2006
2008 2007 static uint8_t
2009 2008 wpi_plcp_signal(int rate)
2010 2009 {
2011 2010 switch (rate) {
2012 2011 /* CCK rates (returned values are device-dependent) */
2013 2012 case 2: return (10);
2014 2013 case 4: return (20);
2015 2014 case 11: return (55);
2016 2015 case 22: return (110);
2017 2016
2018 2017 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
2019 2018 /* R1-R4 (ral/ural is R4-R1) */
2020 2019 case 12: return (0xd);
2021 2020 case 18: return (0xf);
2022 2021 case 24: return (0x5);
2023 2022 case 36: return (0x7);
2024 2023 case 48: return (0x9);
2025 2024 case 72: return (0xb);
2026 2025 case 96: return (0x1);
2027 2026 case 108: return (0x3);
2028 2027
2029 2028 /* unsupported rates (should not get there) */
2030 2029 default: return (0);
2031 2030 }
2032 2031 }
2033 2032
2034 2033 static mblk_t *
2035 2034 wpi_m_tx(void *arg, mblk_t *mp)
2036 2035 {
2037 2036 wpi_sc_t *sc = (wpi_sc_t *)arg;
2038 2037 ieee80211com_t *ic = &sc->sc_ic;
2039 2038 mblk_t *next;
2040 2039
2041 2040 if (sc->sc_flags & WPI_F_SUSPEND) {
2042 2041 freemsgchain(mp);
2043 2042 return (NULL);
2044 2043 }
2045 2044
2046 2045 if (ic->ic_state != IEEE80211_S_RUN) {
2047 2046 freemsgchain(mp);
2048 2047 return (NULL);
2049 2048 }
2050 2049
2051 2050 if ((sc->sc_flags & WPI_F_HW_ERR_RECOVER) &&
2052 2051 WPI_CHK_FAST_RECOVER(sc)) {
2053 2052 WPI_DBG((WPI_DEBUG_FW, "wpi_m_tx(): hold queue\n"));
2054 2053 return (mp);
2055 2054 }
2056 2055
2057 2056 while (mp != NULL) {
2058 2057 next = mp->b_next;
2059 2058 mp->b_next = NULL;
2060 2059 if (wpi_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != 0) {
2061 2060 mp->b_next = next;
2062 2061 break;
2063 2062 }
2064 2063 mp = next;
2065 2064 }
2066 2065 return (mp);
2067 2066 }
2068 2067
2069 2068 /* ARGSUSED */
2070 2069 static int
2071 2070 wpi_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
2072 2071 {
2073 2072 wpi_sc_t *sc = (wpi_sc_t *)ic;
2074 2073 wpi_tx_ring_t *ring;
2075 2074 wpi_tx_desc_t *desc;
2076 2075 wpi_tx_data_t *data;
2077 2076 wpi_tx_cmd_t *cmd;
2078 2077 wpi_cmd_data_t *tx;
2079 2078 ieee80211_node_t *in;
2080 2079 struct ieee80211_frame *wh;
2081 2080 struct ieee80211_key *k;
2082 2081 mblk_t *m, *m0;
2083 2082 int rate, hdrlen, len, mblen, off, err = WPI_SUCCESS;
2084 2083
2085 2084 ring = ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA) ?
2086 2085 (&sc->sc_txq[0]) : (&sc->sc_txq[1]);
2087 2086 data = &ring->data[ring->cur];
2088 2087 desc = data->desc;
2089 2088 cmd = data->cmd;
2090 2089 bzero(desc, sizeof (*desc));
2091 2090 bzero(cmd, sizeof (*cmd));
2092 2091
2093 2092 mutex_enter(&sc->sc_tx_lock);
2094 2093 if (sc->sc_flags & WPI_F_SUSPEND) {
2095 2094 mutex_exit(&sc->sc_tx_lock);
2096 2095 if ((type & IEEE80211_FC0_TYPE_MASK) !=
2097 2096 IEEE80211_FC0_TYPE_DATA) {
2098 2097 freemsg(mp);
2099 2098 }
2100 2099 err = ENXIO;
2101 2100 goto exit;
2102 2101 }
2103 2102
2104 2103 if (ring->queued > ring->count - 64) {
2105 2104 WPI_DBG((WPI_DEBUG_TX, "wpi_send(): no txbuf\n"));
2106 2105 sc->sc_need_reschedule = 1;
2107 2106 mutex_exit(&sc->sc_tx_lock);
2108 2107 if ((type & IEEE80211_FC0_TYPE_MASK) !=
2109 2108 IEEE80211_FC0_TYPE_DATA) {
2110 2109 freemsg(mp);
2111 2110 }
2112 2111 sc->sc_tx_nobuf++;
2113 2112 err = ENOMEM;
2114 2113 goto exit;
2115 2114 }
2116 2115 mutex_exit(&sc->sc_tx_lock);
2117 2116
2118 2117 hdrlen = sizeof (struct ieee80211_frame);
2119 2118
2120 2119 m = allocb(msgdsize(mp) + 32, BPRI_MED);
2121 2120 if (m == NULL) { /* can not alloc buf, drop this package */
2122 2121 cmn_err(CE_WARN,
2123 2122 "wpi_send(): failed to allocate msgbuf\n");
2124 2123 freemsg(mp);
2125 2124 err = WPI_SUCCESS;
2126 2125 goto exit;
2127 2126 }
2128 2127 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
2129 2128 mblen = MBLKL(m0);
2130 2129 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen);
2131 2130 off += mblen;
2132 2131 }
2133 2132 m->b_wptr += off;
2134 2133 freemsg(mp);
2135 2134
2136 2135 wh = (struct ieee80211_frame *)m->b_rptr;
2137 2136
2138 2137 in = ieee80211_find_txnode(ic, wh->i_addr1);
2139 2138 if (in == NULL) {
2140 2139 cmn_err(CE_WARN, "wpi_send(): failed to find tx node\n");
2141 2140 freemsg(m);
2142 2141 sc->sc_tx_err++;
2143 2142 err = WPI_SUCCESS;
2144 2143 goto exit;
2145 2144 }
2146 2145
2147 2146 (void) ieee80211_encap(ic, m, in);
2148 2147
2149 2148 cmd->code = WPI_CMD_TX_DATA;
2150 2149 cmd->flags = 0;
2151 2150 cmd->qid = ring->qid;
2152 2151 cmd->idx = ring->cur;
2153 2152
2154 2153 tx = (wpi_cmd_data_t *)cmd->data;
2155 2154 tx->flags = 0;
2156 2155 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2157 2156 tx->flags |= LE_32(WPI_TX_NEED_ACK);
2158 2157 } else {
2159 2158 tx->flags &= ~(LE_32(WPI_TX_NEED_ACK));
2160 2159 }
2161 2160
2162 2161 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
2163 2162 k = ieee80211_crypto_encap(ic, m);
2164 2163 if (k == NULL) {
2165 2164 freemsg(m);
2166 2165 sc->sc_tx_err++;
2167 2166 err = WPI_SUCCESS;
2168 2167 goto exit;
2169 2168 }
2170 2169
2171 2170 if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_AES_CCM) {
2172 2171 tx->security = 2; /* for CCMP */
2173 2172 tx->flags |= LE_32(WPI_TX_NEED_ACK);
2174 2173 (void) memcpy(&tx->key, k->wk_key, k->wk_keylen);
2175 2174 }
2176 2175
2177 2176 /* packet header may have moved, reset our local pointer */
2178 2177 wh = (struct ieee80211_frame *)m->b_rptr;
2179 2178 }
2180 2179
2181 2180 len = msgdsize(m);
2182 2181
2183 2182 #ifdef DEBUG
2184 2183 if (wpi_dbg_flags & WPI_DEBUG_TX)
2185 2184 ieee80211_dump_pkt((uint8_t *)wh, hdrlen, 0, 0);
2186 2185 #endif
2187 2186
2188 2187 /* pickup a rate */
2189 2188 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
2190 2189 IEEE80211_FC0_TYPE_MGT) {
2191 2190 /* mgmt frames are sent at the lowest available bit-rate */
2192 2191 rate = 2;
2193 2192 } else {
2194 2193 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
2195 2194 rate = ic->ic_fixed_rate;
2196 2195 } else
2197 2196 rate = in->in_rates.ir_rates[in->in_txrate];
2198 2197 }
2199 2198 rate &= IEEE80211_RATE_VAL;
2200 2199 WPI_DBG((WPI_DEBUG_RATECTL, "tx rate[%d of %d] = %x",
2201 2200 in->in_txrate, in->in_rates.ir_nrates, rate));
2202 2201 #ifdef WPI_BPF
2203 2202 #ifndef WPI_CURRENT
2204 2203 if (sc->sc_drvbpf != NULL) {
2205 2204 #else
2206 2205 if (bpf_peers_present(sc->sc_drvbpf)) {
2207 2206 #endif
2208 2207 struct wpi_tx_radiotap_header *tap = &sc->sc_txtap;
2209 2208
2210 2209 tap->wt_flags = 0;
2211 2210 tap->wt_chan_freq = LE_16(ic->ic_curchan->ic_freq);
2212 2211 tap->wt_chan_flags = LE_16(ic->ic_curchan->ic_flags);
2213 2212 tap->wt_rate = rate;
2214 2213 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
2215 2214 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
2216 2215
2217 2216 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
2218 2217 }
2219 2218 #endif
2220 2219
2221 2220 tx->flags |= (LE_32(WPI_TX_AUTO_SEQ));
2222 2221 tx->flags |= LE_32(WPI_TX_BT_DISABLE | WPI_TX_CALIBRATION);
2223 2222
2224 2223 /* retrieve destination node's id */
2225 2224 tx->id = IEEE80211_IS_MULTICAST(wh->i_addr1) ? WPI_ID_BROADCAST :
2226 2225 WPI_ID_BSS;
2227 2226
2228 2227 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
2229 2228 IEEE80211_FC0_TYPE_MGT) {
2230 2229 /* tell h/w to set timestamp in probe responses */
2231 2230 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2232 2231 IEEE80211_FC0_SUBTYPE_PROBE_RESP)
2233 2232 tx->flags |= LE_32(WPI_TX_INSERT_TSTAMP);
2234 2233
2235 2234 if (((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2236 2235 IEEE80211_FC0_SUBTYPE_ASSOC_REQ) ||
2237 2236 ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2238 2237 IEEE80211_FC0_SUBTYPE_REASSOC_REQ))
2239 2238 tx->timeout = 3;
2240 2239 else
2241 2240 tx->timeout = 2;
2242 2241 } else
2243 2242 tx->timeout = 0;
2244 2243
2245 2244 tx->rate = wpi_plcp_signal(rate);
2246 2245
2247 2246 /* be very persistant at sending frames out */
2248 2247 tx->rts_ntries = 7;
2249 2248 tx->data_ntries = 15;
2250 2249
2251 2250 tx->cck_mask = 0x0f;
2252 2251 tx->ofdm_mask = 0xff;
2253 2252 tx->lifetime = LE_32(0xffffffff);
2254 2253
2255 2254 tx->len = LE_16(len);
2256 2255
2257 2256 /* save and trim IEEE802.11 header */
2258 2257 (void) memcpy(tx + 1, m->b_rptr, hdrlen);
2259 2258 m->b_rptr += hdrlen;
2260 2259 (void) memcpy(data->dma_data.mem_va, m->b_rptr, len - hdrlen);
2261 2260
2262 2261 WPI_DBG((WPI_DEBUG_TX, "sending data: qid=%d idx=%d len=%d", ring->qid,
2263 2262 ring->cur, len));
2264 2263
2265 2264 /* first scatter/gather segment is used by the tx data command */
2266 2265 desc->flags = LE_32(WPI_PAD32(len) << 28 | (2) << 24);
2267 2266 desc->segs[0].addr = LE_32(data->paddr_cmd);
2268 2267 desc->segs[0].len = LE_32(
2269 2268 roundup(4 + sizeof (wpi_cmd_data_t) + hdrlen, 4));
2270 2269 desc->segs[1].addr = LE_32(data->dma_data.cookie.dmac_address);
2271 2270 desc->segs[1].len = LE_32(len - hdrlen);
2272 2271
2273 2272 WPI_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
2274 2273 WPI_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
2275 2274
2276 2275 mutex_enter(&sc->sc_tx_lock);
2277 2276 ring->queued++;
2278 2277 mutex_exit(&sc->sc_tx_lock);
2279 2278
2280 2279 /* kick ring */
2281 2280 ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT;
2282 2281 WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur);
2283 2282 freemsg(m);
2284 2283 /* release node reference */
2285 2284 ieee80211_free_node(in);
2286 2285
2287 2286 ic->ic_stats.is_tx_bytes += len;
2288 2287 ic->ic_stats.is_tx_frags++;
2289 2288
2290 2289 if (sc->sc_tx_timer == 0)
2291 2290 sc->sc_tx_timer = 5;
2292 2291 exit:
2293 2292 return (err);
2294 2293 }
2295 2294
2296 2295 static void
2297 2296 wpi_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
2298 2297 {
2299 2298 wpi_sc_t *sc = (wpi_sc_t *)arg;
2300 2299 ieee80211com_t *ic = &sc->sc_ic;
2301 2300 int err;
2302 2301
2303 2302 err = ieee80211_ioctl(ic, wq, mp);
2304 2303 if (err == ENETRESET) {
2305 2304 /*
2306 2305 * This is special for the hidden AP connection.
2307 2306 * In any case, we should make sure only one 'scan'
2308 2307 * in the driver for a 'connect' CLI command. So
2309 2308 * when connecting to a hidden AP, the scan is just
2310 2309 * sent out to the air when we know the desired
2311 2310 * essid of the AP we want to connect.
2312 2311 */
2313 2312 if (ic->ic_des_esslen) {
2314 2313 if (sc->sc_flags & WPI_F_RUNNING) {
2315 2314 wpi_m_stop(sc);
2316 2315 (void) wpi_m_start(sc);
2317 2316 (void) ieee80211_new_state(ic,
2318 2317 IEEE80211_S_SCAN, -1);
2319 2318 }
2320 2319 }
2321 2320 }
2322 2321 }
2323 2322
2324 2323 /*
2325 2324 * Callback functions for get/set properties
2326 2325 */
2327 2326 /* ARGSUSED */
2328 2327 static int
2329 2328 wpi_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_name,
2330 2329 uint_t wldp_length, void *wldp_buf)
2331 2330 {
2332 2331 int err = 0;
2333 2332 wpi_sc_t *sc = (wpi_sc_t *)arg;
2334 2333
2335 2334 err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_name,
2336 2335 wldp_length, wldp_buf);
2337 2336
2338 2337 return (err);
2339 2338 }
2340 2339
2341 2340 static void
2342 2341 wpi_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
2343 2342 mac_prop_info_handle_t mph)
2344 2343 {
2345 2344 wpi_sc_t *sc = (wpi_sc_t *)arg;
2346 2345
2347 2346 ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, mph);
2348 2347 }
2349 2348
2350 2349 static int
2351 2350 wpi_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_name,
2352 2351 uint_t wldp_length, const void *wldp_buf)
2353 2352 {
2354 2353 int err;
2355 2354 wpi_sc_t *sc = (wpi_sc_t *)arg;
2356 2355 ieee80211com_t *ic = &sc->sc_ic;
2357 2356
2358 2357 err = ieee80211_setprop(ic, pr_name, wldp_pr_name,
2359 2358 wldp_length, wldp_buf);
2360 2359
2361 2360 if (err == ENETRESET) {
2362 2361 if (ic->ic_des_esslen) {
2363 2362 if (sc->sc_flags & WPI_F_RUNNING) {
2364 2363 wpi_m_stop(sc);
2365 2364 (void) wpi_m_start(sc);
2366 2365 (void) ieee80211_new_state(ic,
2367 2366 IEEE80211_S_SCAN, -1);
2368 2367 }
2369 2368 }
2370 2369
2371 2370 err = 0;
2372 2371 }
2373 2372
2374 2373 return (err);
2375 2374 }
2376 2375
2377 2376 /*ARGSUSED*/
2378 2377 static int
2379 2378 wpi_m_stat(void *arg, uint_t stat, uint64_t *val)
2380 2379 {
2381 2380 wpi_sc_t *sc = (wpi_sc_t *)arg;
2382 2381 ieee80211com_t *ic = &sc->sc_ic;
2383 2382 ieee80211_node_t *in;
2384 2383
2385 2384 mutex_enter(&sc->sc_glock);
2386 2385 switch (stat) {
2387 2386 case MAC_STAT_IFSPEED:
2388 2387 in = ic->ic_bss;
2389 2388 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
2390 2389 IEEE80211_RATE(in->in_txrate) :
2391 2390 ic->ic_fixed_rate) / 2 * 1000000;
2392 2391 break;
2393 2392 case MAC_STAT_NOXMTBUF:
2394 2393 *val = sc->sc_tx_nobuf;
2395 2394 break;
2396 2395 case MAC_STAT_NORCVBUF:
2397 2396 *val = sc->sc_rx_nobuf;
2398 2397 break;
2399 2398 case MAC_STAT_IERRORS:
2400 2399 *val = sc->sc_rx_err;
2401 2400 break;
2402 2401 case MAC_STAT_RBYTES:
2403 2402 *val = ic->ic_stats.is_rx_bytes;
2404 2403 break;
2405 2404 case MAC_STAT_IPACKETS:
2406 2405 *val = ic->ic_stats.is_rx_frags;
2407 2406 break;
2408 2407 case MAC_STAT_OBYTES:
2409 2408 *val = ic->ic_stats.is_tx_bytes;
2410 2409 break;
2411 2410 case MAC_STAT_OPACKETS:
2412 2411 *val = ic->ic_stats.is_tx_frags;
2413 2412 break;
2414 2413 case MAC_STAT_OERRORS:
2415 2414 case WIFI_STAT_TX_FAILED:
2416 2415 *val = sc->sc_tx_err;
2417 2416 break;
2418 2417 case WIFI_STAT_TX_RETRANS:
2419 2418 *val = sc->sc_tx_retries;
2420 2419 break;
2421 2420 case WIFI_STAT_FCS_ERRORS:
2422 2421 case WIFI_STAT_WEP_ERRORS:
2423 2422 case WIFI_STAT_TX_FRAGS:
2424 2423 case WIFI_STAT_MCAST_TX:
2425 2424 case WIFI_STAT_RTS_SUCCESS:
2426 2425 case WIFI_STAT_RTS_FAILURE:
2427 2426 case WIFI_STAT_ACK_FAILURE:
2428 2427 case WIFI_STAT_RX_FRAGS:
2429 2428 case WIFI_STAT_MCAST_RX:
2430 2429 case WIFI_STAT_RX_DUPS:
2431 2430 mutex_exit(&sc->sc_glock);
2432 2431 return (ieee80211_stat(ic, stat, val));
2433 2432 default:
2434 2433 mutex_exit(&sc->sc_glock);
2435 2434 return (ENOTSUP);
2436 2435 }
2437 2436 mutex_exit(&sc->sc_glock);
2438 2437
2439 2438 return (WPI_SUCCESS);
2440 2439
2441 2440 }
2442 2441
2443 2442 static int
2444 2443 wpi_m_start(void *arg)
2445 2444 {
2446 2445 wpi_sc_t *sc = (wpi_sc_t *)arg;
2447 2446 ieee80211com_t *ic = &sc->sc_ic;
2448 2447 int err;
2449 2448
2450 2449 err = wpi_init(sc);
2451 2450 if (err != WPI_SUCCESS) {
2452 2451 wpi_stop(sc);
2453 2452 DELAY(1000000);
2454 2453 err = wpi_init(sc);
2455 2454 }
2456 2455
2457 2456 if (err) {
2458 2457 /*
2459 2458 * The hw init err(eg. RF is OFF). Return Success to make
2460 2459 * the 'plumb' succeed. The wpi_thread() tries to re-init
2461 2460 * background.
2462 2461 */
2463 2462 mutex_enter(&sc->sc_glock);
2464 2463 sc->sc_flags |= WPI_F_HW_ERR_RECOVER;
2465 2464 mutex_exit(&sc->sc_glock);
2466 2465 return (WPI_SUCCESS);
2467 2466 }
2468 2467 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
2469 2468 mutex_enter(&sc->sc_glock);
2470 2469 sc->sc_flags |= WPI_F_RUNNING;
2471 2470 mutex_exit(&sc->sc_glock);
2472 2471
2473 2472 return (WPI_SUCCESS);
2474 2473 }
2475 2474
2476 2475 static void
2477 2476 wpi_m_stop(void *arg)
2478 2477 {
2479 2478 wpi_sc_t *sc = (wpi_sc_t *)arg;
2480 2479 ieee80211com_t *ic = &sc->sc_ic;
2481 2480
2482 2481 wpi_stop(sc);
2483 2482 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
2484 2483 mutex_enter(&sc->sc_mt_lock);
2485 2484 sc->sc_flags &= ~WPI_F_HW_ERR_RECOVER;
2486 2485 sc->sc_flags &= ~WPI_F_RATE_AUTO_CTL;
2487 2486 mutex_exit(&sc->sc_mt_lock);
2488 2487 mutex_enter(&sc->sc_glock);
2489 2488 sc->sc_flags &= ~WPI_F_RUNNING;
2490 2489 mutex_exit(&sc->sc_glock);
2491 2490 }
2492 2491
2493 2492 /*ARGSUSED*/
2494 2493 static int
2495 2494 wpi_m_unicst(void *arg, const uint8_t *macaddr)
2496 2495 {
2497 2496 wpi_sc_t *sc = (wpi_sc_t *)arg;
2498 2497 ieee80211com_t *ic = &sc->sc_ic;
2499 2498 int err;
2500 2499
2501 2500 if (!IEEE80211_ADDR_EQ(ic->ic_macaddr, macaddr)) {
2502 2501 IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
2503 2502 mutex_enter(&sc->sc_glock);
2504 2503 err = wpi_config(sc);
2505 2504 mutex_exit(&sc->sc_glock);
2506 2505 if (err != WPI_SUCCESS) {
2507 2506 cmn_err(CE_WARN,
2508 2507 "wpi_m_unicst(): "
2509 2508 "failed to configure device\n");
2510 2509 goto fail;
2511 2510 }
2512 2511 }
2513 2512 return (WPI_SUCCESS);
2514 2513 fail:
2515 2514 return (err);
2516 2515 }
2517 2516
2518 2517 /*ARGSUSED*/
2519 2518 static int
2520 2519 wpi_m_multicst(void *arg, boolean_t add, const uint8_t *m)
2521 2520 {
2522 2521 return (WPI_SUCCESS);
2523 2522 }
2524 2523
2525 2524 /*ARGSUSED*/
2526 2525 static int
2527 2526 wpi_m_promisc(void *arg, boolean_t on)
2528 2527 {
2529 2528 return (WPI_SUCCESS);
2530 2529 }
2531 2530
2532 2531 static void
2533 2532 wpi_thread(wpi_sc_t *sc)
2534 2533 {
2535 2534 ieee80211com_t *ic = &sc->sc_ic;
2536 2535 clock_t clk;
2537 2536 int times = 0, err, n = 0, timeout = 0;
2538 2537 uint32_t tmp;
2539 2538
2540 2539 mutex_enter(&sc->sc_mt_lock);
2541 2540 while (sc->sc_mf_thread_switch) {
2542 2541 tmp = WPI_READ(sc, WPI_GPIO_CTL);
2543 2542 if (tmp & WPI_GPIO_HW_RF_KILL) {
2544 2543 sc->sc_flags &= ~WPI_F_RADIO_OFF;
2545 2544 } else {
2546 2545 sc->sc_flags |= WPI_F_RADIO_OFF;
2547 2546 }
2548 2547 /*
2549 2548 * If in SUSPEND or the RF is OFF, do nothing
2550 2549 */
2551 2550 if ((sc->sc_flags & WPI_F_SUSPEND) ||
2552 2551 (sc->sc_flags & WPI_F_RADIO_OFF)) {
2553 2552 mutex_exit(&sc->sc_mt_lock);
2554 2553 delay(drv_usectohz(100000));
2555 2554 mutex_enter(&sc->sc_mt_lock);
2556 2555 continue;
2557 2556 }
2558 2557
2559 2558 /*
2560 2559 * recovery fatal error
2561 2560 */
2562 2561 if (ic->ic_mach &&
2563 2562 (sc->sc_flags & WPI_F_HW_ERR_RECOVER)) {
2564 2563
2565 2564 WPI_DBG((WPI_DEBUG_FW,
2566 2565 "wpi_thread(): "
2567 2566 "try to recover fatal hw error: %d\n", times++));
2568 2567
2569 2568 wpi_stop(sc);
2570 2569
2571 2570 if (WPI_CHK_FAST_RECOVER(sc)) {
2572 2571 /* save runtime configuration */
2573 2572 bcopy(&sc->sc_config, &sc->sc_config_save,
2574 2573 sizeof (sc->sc_config));
2575 2574 } else {
2576 2575 mutex_exit(&sc->sc_mt_lock);
2577 2576 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
2578 2577 delay(drv_usectohz(2000000));
2579 2578 mutex_enter(&sc->sc_mt_lock);
2580 2579 }
2581 2580
2582 2581 err = wpi_init(sc);
2583 2582 if (err != WPI_SUCCESS) {
2584 2583 n++;
2585 2584 if (n < 3)
2586 2585 continue;
2587 2586 }
2588 2587 n = 0;
2589 2588 if (!err)
2590 2589 sc->sc_flags |= WPI_F_RUNNING;
2591 2590
2592 2591 if (!WPI_CHK_FAST_RECOVER(sc) ||
2593 2592 wpi_fast_recover(sc) != WPI_SUCCESS) {
2594 2593 sc->sc_flags &= ~WPI_F_HW_ERR_RECOVER;
2595 2594
2596 2595 mutex_exit(&sc->sc_mt_lock);
2597 2596 delay(drv_usectohz(2000000));
2598 2597 if (sc->sc_ostate != IEEE80211_S_INIT)
2599 2598 ieee80211_new_state(ic,
2600 2599 IEEE80211_S_SCAN, 0);
2601 2600 mutex_enter(&sc->sc_mt_lock);
2602 2601 }
2603 2602 }
2604 2603
2605 2604 if (ic->ic_mach && (sc->sc_flags & WPI_F_LAZY_RESUME)) {
2606 2605 WPI_DBG((WPI_DEBUG_RESUME,
2607 2606 "wpi_thread(): "
2608 2607 "lazy resume\n"));
2609 2608 sc->sc_flags &= ~WPI_F_LAZY_RESUME;
2610 2609 mutex_exit(&sc->sc_mt_lock);
2611 2610 /*
2612 2611 * NB: under WPA mode, this call hangs (door problem?)
2613 2612 * when called in wpi_attach() and wpi_detach() while
2614 2613 * system is in the procedure of CPR. To be safe, let
2615 2614 * the thread do this.
2616 2615 */
2617 2616 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
2618 2617 mutex_enter(&sc->sc_mt_lock);
2619 2618 }
2620 2619
2621 2620 /*
2622 2621 * scan next channel
2623 2622 */
2624 2623 if (ic->ic_mach &&
2625 2624 (sc->sc_flags & WPI_F_SCANNING) && sc->sc_scan_next) {
2626 2625
2627 2626 WPI_DBG((WPI_DEBUG_SCAN,
2628 2627 "wpi_thread(): "
2629 2628 "wait for probe response\n"));
2630 2629
2631 2630 sc->sc_scan_next--;
2632 2631 mutex_exit(&sc->sc_mt_lock);
2633 2632 delay(drv_usectohz(200000));
2634 2633 if (sc->sc_flags & WPI_F_SCANNING)
2635 2634 ieee80211_next_scan(ic);
2636 2635 mutex_enter(&sc->sc_mt_lock);
2637 2636 }
2638 2637
2639 2638 /*
2640 2639 * rate ctl
2641 2640 */
2642 2641 if (ic->ic_mach &&
2643 2642 (sc->sc_flags & WPI_F_RATE_AUTO_CTL)) {
2644 2643 clk = ddi_get_lbolt();
2645 2644 if (clk > sc->sc_clk + drv_usectohz(500000)) {
2646 2645 wpi_amrr_timeout(sc);
2647 2646 }
2648 2647 }
2649 2648 mutex_exit(&sc->sc_mt_lock);
2650 2649 delay(drv_usectohz(100000));
2651 2650 mutex_enter(&sc->sc_mt_lock);
2652 2651 if (sc->sc_tx_timer) {
2653 2652 timeout++;
2654 2653 if (timeout == 10) {
2655 2654 sc->sc_tx_timer--;
2656 2655 if (sc->sc_tx_timer == 0) {
2657 2656 sc->sc_flags |= WPI_F_HW_ERR_RECOVER;
2658 2657 sc->sc_ostate = IEEE80211_S_RUN;
2659 2658 WPI_DBG((WPI_DEBUG_FW,
2660 2659 "wpi_thread(): send fail\n"));
2661 2660 }
2662 2661 timeout = 0;
2663 2662 }
2664 2663 }
2665 2664 }
2666 2665 sc->sc_mf_thread = NULL;
2667 2666 cv_signal(&sc->sc_mt_cv);
2668 2667 mutex_exit(&sc->sc_mt_lock);
2669 2668 }
2670 2669
2671 2670 /*
2672 2671 * Extract various information from EEPROM.
2673 2672 */
2674 2673 static void
2675 2674 wpi_read_eeprom(wpi_sc_t *sc)
2676 2675 {
2677 2676 ieee80211com_t *ic = &sc->sc_ic;
2678 2677 uint16_t val;
2679 2678 int i;
2680 2679
2681 2680 /* read MAC address */
2682 2681 val = wpi_read_prom_word(sc, WPI_EEPROM_MAC + 0);
2683 2682 ic->ic_macaddr[0] = val & 0xff;
2684 2683 ic->ic_macaddr[1] = val >> 8;
2685 2684 val = wpi_read_prom_word(sc, WPI_EEPROM_MAC + 1);
2686 2685 ic->ic_macaddr[2] = val & 0xff;
2687 2686 ic->ic_macaddr[3] = val >> 8;
2688 2687 val = wpi_read_prom_word(sc, WPI_EEPROM_MAC + 2);
2689 2688 ic->ic_macaddr[4] = val & 0xff;
2690 2689 ic->ic_macaddr[5] = val >> 8;
2691 2690
2692 2691 WPI_DBG((WPI_DEBUG_EEPROM,
2693 2692 "mac:%2x:%2x:%2x:%2x:%2x:%2x\n",
2694 2693 ic->ic_macaddr[0], ic->ic_macaddr[1],
2695 2694 ic->ic_macaddr[2], ic->ic_macaddr[3],
2696 2695 ic->ic_macaddr[4], ic->ic_macaddr[5]));
2697 2696 /* read power settings for 2.4GHz channels */
2698 2697 for (i = 0; i < 14; i++) {
2699 2698 sc->sc_pwr1[i] = wpi_read_prom_word(sc, WPI_EEPROM_PWR1 + i);
2700 2699 sc->sc_pwr2[i] = wpi_read_prom_word(sc, WPI_EEPROM_PWR2 + i);
2701 2700 WPI_DBG((WPI_DEBUG_EEPROM,
2702 2701 "channel %d pwr1 0x%04x pwr2 0x%04x\n", i + 1,
2703 2702 sc->sc_pwr1[i], sc->sc_pwr2[i]));
2704 2703 }
2705 2704 }
2706 2705
2707 2706 /*
2708 2707 * Send a command to the firmware.
2709 2708 */
2710 2709 static int
2711 2710 wpi_cmd(wpi_sc_t *sc, int code, const void *buf, int size, int async)
2712 2711 {
2713 2712 wpi_tx_ring_t *ring = &sc->sc_cmdq;
2714 2713 wpi_tx_desc_t *desc;
2715 2714 wpi_tx_cmd_t *cmd;
2716 2715
2717 2716 ASSERT(size <= sizeof (cmd->data));
2718 2717 ASSERT(mutex_owned(&sc->sc_glock));
2719 2718
2720 2719 WPI_DBG((WPI_DEBUG_CMD, "wpi_cmd() # code[%d]", code));
2721 2720 desc = ring->data[ring->cur].desc;
2722 2721 cmd = ring->data[ring->cur].cmd;
2723 2722
2724 2723 cmd->code = (uint8_t)code;
2725 2724 cmd->flags = 0;
2726 2725 cmd->qid = ring->qid;
2727 2726 cmd->idx = ring->cur;
2728 2727 (void) memcpy(cmd->data, buf, size);
2729 2728
2730 2729 desc->flags = LE_32(WPI_PAD32(size) << 28 | 1 << 24);
2731 2730 desc->segs[0].addr = ring->data[ring->cur].paddr_cmd;
2732 2731 desc->segs[0].len = 4 + size;
2733 2732
2734 2733 /* kick cmd ring */
2735 2734 ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT;
2736 2735 WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur);
2737 2736
2738 2737 if (async)
2739 2738 return (WPI_SUCCESS);
2740 2739 else {
2741 2740 clock_t clk;
2742 2741 sc->sc_flags &= ~WPI_F_CMD_DONE;
2743 2742 clk = ddi_get_lbolt() + drv_usectohz(2000000);
2744 2743 while (!(sc->sc_flags & WPI_F_CMD_DONE)) {
2745 2744 if (cv_timedwait(&sc->sc_cmd_cv, &sc->sc_glock, clk)
2746 2745 < 0)
2747 2746 break;
2748 2747 }
2749 2748 if (sc->sc_flags & WPI_F_CMD_DONE)
2750 2749 return (WPI_SUCCESS);
2751 2750 else
2752 2751 return (WPI_FAIL);
2753 2752 }
2754 2753 }
2755 2754
2756 2755 /*
2757 2756 * Configure h/w multi-rate retries.
2758 2757 */
2759 2758 static int
2760 2759 wpi_mrr_setup(wpi_sc_t *sc)
2761 2760 {
2762 2761 wpi_mrr_setup_t mrr;
2763 2762 int i, err;
2764 2763
2765 2764 /* CCK rates (not used with 802.11a) */
2766 2765 for (i = WPI_CCK1; i <= WPI_CCK11; i++) {
2767 2766 mrr.rates[i].flags = 0;
2768 2767 mrr.rates[i].signal = wpi_ridx_to_signal[i];
2769 2768 /* fallback to the immediate lower CCK rate (if any) */
2770 2769 mrr.rates[i].next = (i == WPI_CCK1) ? WPI_CCK1 : i - 1;
2771 2770 /* try one time at this rate before falling back to "next" */
2772 2771 mrr.rates[i].ntries = 1;
2773 2772 }
2774 2773
2775 2774 /* OFDM rates (not used with 802.11b) */
2776 2775 for (i = WPI_OFDM6; i <= WPI_OFDM54; i++) {
2777 2776 mrr.rates[i].flags = 0;
2778 2777 mrr.rates[i].signal = wpi_ridx_to_signal[i];
2779 2778 /* fallback to the immediate lower OFDM rate (if any) */
2780 2779 mrr.rates[i].next = (i == WPI_OFDM6) ? WPI_OFDM6 : i - 1;
2781 2780 /* try one time at this rate before falling back to "next" */
2782 2781 mrr.rates[i].ntries = 1;
2783 2782 }
2784 2783
2785 2784 /* setup MRR for control frames */
2786 2785 mrr.which = LE_32(WPI_MRR_CTL);
2787 2786 err = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof (mrr), 1);
2788 2787 if (err != WPI_SUCCESS) {
2789 2788 WPI_DBG((WPI_DEBUG_MRR,
2790 2789 "could not setup MRR for control frames\n"));
2791 2790 return (err);
2792 2791 }
2793 2792
2794 2793 /* setup MRR for data frames */
2795 2794 mrr.which = LE_32(WPI_MRR_DATA);
2796 2795 err = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof (mrr), 1);
2797 2796 if (err != WPI_SUCCESS) {
2798 2797 WPI_DBG((WPI_DEBUG_MRR,
2799 2798 "could not setup MRR for data frames\n"));
2800 2799 return (err);
2801 2800 }
2802 2801
2803 2802 return (WPI_SUCCESS);
2804 2803 }
2805 2804
2806 2805 static void
2807 2806 wpi_set_led(wpi_sc_t *sc, uint8_t which, uint8_t off, uint8_t on)
2808 2807 {
2809 2808 wpi_cmd_led_t led;
2810 2809
2811 2810 led.which = which;
2812 2811 led.unit = LE_32(100000); /* on/off in unit of 100ms */
2813 2812 led.off = off;
2814 2813 led.on = on;
2815 2814
2816 2815 (void) wpi_cmd(sc, WPI_CMD_SET_LED, &led, sizeof (led), 1);
2817 2816 }
2818 2817
2819 2818 static int
2820 2819 wpi_auth(wpi_sc_t *sc)
2821 2820 {
2822 2821 ieee80211com_t *ic = &sc->sc_ic;
2823 2822 ieee80211_node_t *in = ic->ic_bss;
2824 2823 wpi_node_t node;
2825 2824 int err;
2826 2825
2827 2826 /* update adapter's configuration */
2828 2827 IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid);
2829 2828 sc->sc_config.chan = ieee80211_chan2ieee(ic, in->in_chan);
2830 2829 if (ic->ic_curmode == IEEE80211_MODE_11B) {
2831 2830 sc->sc_config.cck_mask = 0x03;
2832 2831 sc->sc_config.ofdm_mask = 0;
2833 2832 } else if ((in->in_chan != IEEE80211_CHAN_ANYC) &&
2834 2833 (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) {
2835 2834 sc->sc_config.cck_mask = 0;
2836 2835 sc->sc_config.ofdm_mask = 0x15;
2837 2836 } else { /* assume 802.11b/g */
2838 2837 sc->sc_config.cck_mask = 0x0f;
2839 2838 sc->sc_config.ofdm_mask = 0xff;
2840 2839 }
2841 2840
2842 2841 WPI_DBG((WPI_DEBUG_80211, "config chan %d flags %x cck %x ofdm %x"
2843 2842 " bssid:%02x:%02x:%02x:%02x:%02x:%2x\n",
2844 2843 sc->sc_config.chan, sc->sc_config.flags,
2845 2844 sc->sc_config.cck_mask, sc->sc_config.ofdm_mask,
2846 2845 sc->sc_config.bssid[0], sc->sc_config.bssid[1],
2847 2846 sc->sc_config.bssid[2], sc->sc_config.bssid[3],
2848 2847 sc->sc_config.bssid[4], sc->sc_config.bssid[5]));
2849 2848 err = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->sc_config,
2850 2849 sizeof (wpi_config_t), 1);
2851 2850 if (err != WPI_SUCCESS) {
2852 2851 cmn_err(CE_WARN, "wpi_auth(): failed to configurate chan%d\n",
2853 2852 sc->sc_config.chan);
2854 2853 return (err);
2855 2854 }
2856 2855
2857 2856 /* add default node */
2858 2857 (void) memset(&node, 0, sizeof (node));
2859 2858 IEEE80211_ADDR_COPY(node.bssid, in->in_bssid);
2860 2859 node.id = WPI_ID_BSS;
2861 2860 node.rate = wpi_plcp_signal(2);
2862 2861 err = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof (node), 1);
2863 2862 if (err != WPI_SUCCESS) {
2864 2863 cmn_err(CE_WARN, "wpi_auth(): failed to add BSS node\n");
2865 2864 return (err);
2866 2865 }
2867 2866
2868 2867 err = wpi_mrr_setup(sc);
2869 2868 if (err != WPI_SUCCESS) {
2870 2869 cmn_err(CE_WARN, "wpi_auth(): failed to setup MRR\n");
2871 2870 return (err);
2872 2871 }
2873 2872
2874 2873 return (WPI_SUCCESS);
2875 2874 }
2876 2875
2877 2876 /*
2878 2877 * Send a scan request to the firmware.
2879 2878 */
2880 2879 static int
2881 2880 wpi_scan(wpi_sc_t *sc)
2882 2881 {
2883 2882 ieee80211com_t *ic = &sc->sc_ic;
2884 2883 wpi_tx_ring_t *ring = &sc->sc_cmdq;
2885 2884 wpi_tx_desc_t *desc;
2886 2885 wpi_tx_data_t *data;
2887 2886 wpi_tx_cmd_t *cmd;
2888 2887 wpi_scan_hdr_t *hdr;
2889 2888 wpi_scan_chan_t *chan;
2890 2889 struct ieee80211_frame *wh;
2891 2890 ieee80211_node_t *in = ic->ic_bss;
2892 2891 uint8_t essid[IEEE80211_NWID_LEN+1];
2893 2892 struct ieee80211_rateset *rs;
2894 2893 enum ieee80211_phymode mode;
2895 2894 uint8_t *frm;
2896 2895 int i, pktlen, nrates;
2897 2896
2898 2897 /* previous scan not completed */
2899 2898 if (sc->sc_scan_pending) {
2900 2899 WPI_DBG((WPI_DEBUG_SCAN, "previous scan not completed\n"));
2901 2900 return (WPI_SUCCESS);
2902 2901 }
2903 2902
2904 2903 data = &ring->data[ring->cur];
2905 2904 desc = data->desc;
2906 2905 cmd = (wpi_tx_cmd_t *)data->dma_data.mem_va;
2907 2906
2908 2907 cmd->code = WPI_CMD_SCAN;
2909 2908 cmd->flags = 0;
2910 2909 cmd->qid = ring->qid;
2911 2910 cmd->idx = ring->cur;
2912 2911
2913 2912 hdr = (wpi_scan_hdr_t *)cmd->data;
2914 2913 (void) memset(hdr, 0, sizeof (wpi_scan_hdr_t));
2915 2914 hdr->first = 1;
2916 2915 hdr->nchan = 1;
2917 2916 hdr->len = hdr->nchan * sizeof (wpi_scan_chan_t);
2918 2917 hdr->quiet = LE_16(50);
2919 2918 hdr->threshold = LE_16(1);
2920 2919 hdr->filter = LE_32(5);
2921 2920 hdr->rate = wpi_plcp_signal(2);
2922 2921 hdr->id = WPI_ID_BROADCAST;
2923 2922 hdr->mask = LE_32(0xffffffff);
2924 2923 hdr->esslen = ic->ic_des_esslen;
2925 2924
2926 2925 if (ic->ic_des_esslen) {
2927 2926 bcopy(ic->ic_des_essid, essid, ic->ic_des_esslen);
2928 2927 essid[ic->ic_des_esslen] = '\0';
2929 2928 WPI_DBG((WPI_DEBUG_SCAN, "directed scan %s\n", essid));
2930 2929
2931 2930 bcopy(ic->ic_des_essid, hdr->essid, ic->ic_des_esslen);
2932 2931 } else {
2933 2932 bzero(hdr->essid, sizeof (hdr->essid));
2934 2933 }
2935 2934
2936 2935 /*
2937 2936 * Build a probe request frame. Most of the following code is a
2938 2937 * copy & paste of what is done in net80211. Unfortunately, the
2939 2938 * functions to add IEs are static and thus can't be reused here.
2940 2939 */
2941 2940 wh = (struct ieee80211_frame *)(hdr + 1);
2942 2941 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
2943 2942 IEEE80211_FC0_SUBTYPE_PROBE_REQ;
2944 2943 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
2945 2944 (void) memset(wh->i_addr1, 0xff, 6);
2946 2945 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_macaddr);
2947 2946 (void) memset(wh->i_addr3, 0xff, 6);
2948 2947 *(uint16_t *)&wh->i_dur[0] = 0; /* filled by h/w */
2949 2948 *(uint16_t *)&wh->i_seq[0] = 0; /* filled by h/w */
2950 2949
2951 2950 frm = (uint8_t *)(wh + 1);
2952 2951
2953 2952 /* add essid IE */
2954 2953 if (in->in_esslen) {
2955 2954 bcopy(in->in_essid, essid, in->in_esslen);
2956 2955 essid[in->in_esslen] = '\0';
2957 2956 WPI_DBG((WPI_DEBUG_SCAN, "probe with ESSID %s\n",
2958 2957 essid));
2959 2958 }
2960 2959 *frm++ = IEEE80211_ELEMID_SSID;
2961 2960 *frm++ = in->in_esslen;
2962 2961 (void) memcpy(frm, in->in_essid, in->in_esslen);
2963 2962 frm += in->in_esslen;
2964 2963
2965 2964 mode = ieee80211_chan2mode(ic, ic->ic_curchan);
2966 2965 rs = &ic->ic_sup_rates[mode];
2967 2966
2968 2967 /* add supported rates IE */
2969 2968 *frm++ = IEEE80211_ELEMID_RATES;
2970 2969 nrates = rs->ir_nrates;
2971 2970 if (nrates > IEEE80211_RATE_SIZE)
2972 2971 nrates = IEEE80211_RATE_SIZE;
2973 2972 *frm++ = (uint8_t)nrates;
2974 2973 (void) memcpy(frm, rs->ir_rates, nrates);
2975 2974 frm += nrates;
2976 2975
2977 2976 /* add supported xrates IE */
2978 2977 if (rs->ir_nrates > IEEE80211_RATE_SIZE) {
2979 2978 nrates = rs->ir_nrates - IEEE80211_RATE_SIZE;
2980 2979 *frm++ = IEEE80211_ELEMID_XRATES;
2981 2980 *frm++ = (uint8_t)nrates;
2982 2981 (void) memcpy(frm, rs->ir_rates + IEEE80211_RATE_SIZE, nrates);
2983 2982 frm += nrates;
2984 2983 }
2985 2984
2986 2985 /* add optionnal IE (usually an RSN IE) */
2987 2986 if (ic->ic_opt_ie != NULL) {
2988 2987 (void) memcpy(frm, ic->ic_opt_ie, ic->ic_opt_ie_len);
2989 2988 frm += ic->ic_opt_ie_len;
2990 2989 }
2991 2990
2992 2991 /* setup length of probe request */
2993 2992 hdr->pbrlen = LE_16((uintptr_t)frm - (uintptr_t)wh);
2994 2993
2995 2994 /* align on a 4-byte boundary */
2996 2995 chan = (wpi_scan_chan_t *)frm;
2997 2996 for (i = 1; i <= hdr->nchan; i++, chan++) {
2998 2997 if (ic->ic_des_esslen) {
2999 2998 chan->flags = 0x3;
3000 2999 } else {
3001 3000 chan->flags = 0x1;
3002 3001 }
3003 3002 chan->chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
3004 3003 chan->magic = LE_16(0x62ab);
3005 3004 chan->active = LE_16(50);
3006 3005 chan->passive = LE_16(120);
3007 3006
3008 3007 frm += sizeof (wpi_scan_chan_t);
3009 3008 }
3010 3009
3011 3010 pktlen = (uintptr_t)frm - (uintptr_t)cmd;
3012 3011
3013 3012 desc->flags = LE_32(WPI_PAD32(pktlen) << 28 | 1 << 24);
3014 3013 desc->segs[0].addr = LE_32(data->dma_data.cookie.dmac_address);
3015 3014 desc->segs[0].len = LE_32(pktlen);
3016 3015
3017 3016 WPI_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
3018 3017 WPI_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
3019 3018
3020 3019 /* kick cmd ring */
3021 3020 ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT;
3022 3021 WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur);
3023 3022
3024 3023 sc->sc_scan_pending = 1;
3025 3024
3026 3025 return (WPI_SUCCESS); /* will be notified async. of failure/success */
3027 3026 }
3028 3027
3029 3028 static int
3030 3029 wpi_config(wpi_sc_t *sc)
3031 3030 {
3032 3031 ieee80211com_t *ic = &sc->sc_ic;
3033 3032 wpi_txpower_t txpower;
3034 3033 wpi_power_t power;
3035 3034 #ifdef WPI_BLUE_COEXISTENCE
3036 3035 wpi_bluetooth_t bluetooth;
3037 3036 #endif
3038 3037 wpi_node_t node;
3039 3038 int err;
3040 3039
3041 3040 /* Intel's binary only daemon is a joke.. */
3042 3041
3043 3042 /* set Tx power for 2.4GHz channels (values read from EEPROM) */
3044 3043 (void) memset(&txpower, 0, sizeof (txpower));
3045 3044 (void) memcpy(txpower.pwr1, sc->sc_pwr1, 14 * sizeof (uint16_t));
3046 3045 (void) memcpy(txpower.pwr2, sc->sc_pwr2, 14 * sizeof (uint16_t));
3047 3046 err = wpi_cmd(sc, WPI_CMD_TXPOWER, &txpower, sizeof (txpower), 0);
3048 3047 if (err != WPI_SUCCESS) {
3049 3048 cmn_err(CE_WARN, "wpi_config(): failed to set txpower\n");
3050 3049 return (err);
3051 3050 }
3052 3051
3053 3052 /* set power mode */
3054 3053 (void) memset(&power, 0, sizeof (power));
3055 3054 power.flags = LE_32(0x8);
3056 3055 err = wpi_cmd(sc, WPI_CMD_SET_POWER_MODE, &power, sizeof (power), 0);
3057 3056 if (err != WPI_SUCCESS) {
3058 3057 cmn_err(CE_WARN, "wpi_config(): failed to set power mode\n");
3059 3058 return (err);
3060 3059 }
3061 3060 #ifdef WPI_BLUE_COEXISTENCE
3062 3061 /* configure bluetooth coexistence */
3063 3062 (void) memset(&bluetooth, 0, sizeof (bluetooth));
3064 3063 bluetooth.flags = 3;
3065 3064 bluetooth.lead = 0xaa;
3066 3065 bluetooth.kill = 1;
3067 3066 err = wpi_cmd(sc, WPI_CMD_BLUETOOTH, &bluetooth,
3068 3067 sizeof (bluetooth), 0);
3069 3068 if (err != WPI_SUCCESS) {
3070 3069 cmn_err(CE_WARN,
3071 3070 "wpi_config(): "
3072 3071 "failed to configurate bluetooth coexistence\n");
3073 3072 return (err);
3074 3073 }
3075 3074 #endif
3076 3075 /* configure adapter */
3077 3076 (void) memset(&sc->sc_config, 0, sizeof (wpi_config_t));
3078 3077 IEEE80211_ADDR_COPY(sc->sc_config.myaddr, ic->ic_macaddr);
3079 3078 sc->sc_config.chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
3080 3079 sc->sc_config.flags = LE_32(WPI_CONFIG_TSF | WPI_CONFIG_AUTO |
3081 3080 WPI_CONFIG_24GHZ);
3082 3081 sc->sc_config.filter = 0;
3083 3082 switch (ic->ic_opmode) {
3084 3083 case IEEE80211_M_STA:
3085 3084 sc->sc_config.mode = WPI_MODE_STA;
3086 3085 sc->sc_config.filter |= LE_32(WPI_FILTER_MULTICAST);
3087 3086 break;
3088 3087 case IEEE80211_M_IBSS:
3089 3088 case IEEE80211_M_AHDEMO:
3090 3089 sc->sc_config.mode = WPI_MODE_IBSS;
3091 3090 break;
3092 3091 case IEEE80211_M_HOSTAP:
3093 3092 sc->sc_config.mode = WPI_MODE_HOSTAP;
3094 3093 break;
3095 3094 case IEEE80211_M_MONITOR:
3096 3095 sc->sc_config.mode = WPI_MODE_MONITOR;
3097 3096 sc->sc_config.filter |= LE_32(WPI_FILTER_MULTICAST |
3098 3097 WPI_FILTER_CTL | WPI_FILTER_PROMISC);
3099 3098 break;
3100 3099 }
3101 3100 sc->sc_config.cck_mask = 0x0f; /* not yet negotiated */
3102 3101 sc->sc_config.ofdm_mask = 0xff; /* not yet negotiated */
3103 3102 err = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->sc_config,
3104 3103 sizeof (wpi_config_t), 0);
3105 3104 if (err != WPI_SUCCESS) {
3106 3105 cmn_err(CE_WARN, "wpi_config(): "
3107 3106 "failed to set configure command\n");
3108 3107 return (err);
3109 3108 }
3110 3109
3111 3110 /* add broadcast node */
3112 3111 (void) memset(&node, 0, sizeof (node));
3113 3112 (void) memset(node.bssid, 0xff, 6);
3114 3113 node.id = WPI_ID_BROADCAST;
3115 3114 node.rate = wpi_plcp_signal(2);
3116 3115 err = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof (node), 0);
3117 3116 if (err != WPI_SUCCESS) {
3118 3117 cmn_err(CE_WARN, "wpi_config(): "
3119 3118 "failed to add broadcast node\n");
3120 3119 return (err);
3121 3120 }
3122 3121
3123 3122 return (WPI_SUCCESS);
3124 3123 }
3125 3124
3126 3125 static void
3127 3126 wpi_stop_master(wpi_sc_t *sc)
3128 3127 {
3129 3128 uint32_t tmp;
3130 3129 int ntries;
3131 3130
3132 3131 tmp = WPI_READ(sc, WPI_RESET);
3133 3132 WPI_WRITE(sc, WPI_RESET, tmp | WPI_STOP_MASTER);
3134 3133
3135 3134 tmp = WPI_READ(sc, WPI_GPIO_CTL);
3136 3135 if ((tmp & WPI_GPIO_PWR_STATUS) == WPI_GPIO_PWR_SLEEP)
3137 3136 return; /* already asleep */
3138 3137
3139 3138 for (ntries = 0; ntries < 2000; ntries++) {
3140 3139 if (WPI_READ(sc, WPI_RESET) & WPI_MASTER_DISABLED)
3141 3140 break;
3142 3141 DELAY(1000);
3143 3142 }
3144 3143 if (ntries == 2000)
3145 3144 WPI_DBG((WPI_DEBUG_HW, "timeout waiting for master\n"));
3146 3145 }
3147 3146
3148 3147 static int
3149 3148 wpi_power_up(wpi_sc_t *sc)
3150 3149 {
3151 3150 uint32_t tmp;
3152 3151 int ntries;
3153 3152
3154 3153 wpi_mem_lock(sc);
3155 3154 tmp = wpi_mem_read(sc, WPI_MEM_POWER);
3156 3155 wpi_mem_write(sc, WPI_MEM_POWER, tmp & ~0x03000000);
3157 3156 wpi_mem_unlock(sc);
3158 3157
3159 3158 for (ntries = 0; ntries < 5000; ntries++) {
3160 3159 if (WPI_READ(sc, WPI_GPIO_STATUS) & WPI_POWERED)
3161 3160 break;
3162 3161 DELAY(10);
3163 3162 }
3164 3163 if (ntries == 5000) {
3165 3164 cmn_err(CE_WARN,
3166 3165 "wpi_power_up(): timeout waiting for NIC to power up\n");
3167 3166 return (ETIMEDOUT);
3168 3167 }
3169 3168 return (WPI_SUCCESS);
3170 3169 }
3171 3170
3172 3171 static int
3173 3172 wpi_reset(wpi_sc_t *sc)
3174 3173 {
3175 3174 uint32_t tmp;
3176 3175 int ntries;
3177 3176
3178 3177 /* clear any pending interrupts */
3179 3178 WPI_WRITE(sc, WPI_INTR, 0xffffffff);
3180 3179
3181 3180 tmp = WPI_READ(sc, WPI_PLL_CTL);
3182 3181 WPI_WRITE(sc, WPI_PLL_CTL, tmp | WPI_PLL_INIT);
3183 3182
3184 3183 tmp = WPI_READ(sc, WPI_CHICKEN);
3185 3184 WPI_WRITE(sc, WPI_CHICKEN, tmp | WPI_CHICKEN_RXNOLOS);
3186 3185
3187 3186 tmp = WPI_READ(sc, WPI_GPIO_CTL);
3188 3187 WPI_WRITE(sc, WPI_GPIO_CTL, tmp | WPI_GPIO_INIT);
3189 3188
3190 3189 /* wait for clock stabilization */
3191 3190 for (ntries = 0; ntries < 1000; ntries++) {
3192 3191 if (WPI_READ(sc, WPI_GPIO_CTL) & WPI_GPIO_CLOCK)
3193 3192 break;
3194 3193 DELAY(10);
3195 3194 }
3196 3195 if (ntries == 1000) {
3197 3196 cmn_err(CE_WARN,
3198 3197 "wpi_reset(): timeout waiting for clock stabilization\n");
3199 3198 return (ETIMEDOUT);
3200 3199 }
3201 3200
3202 3201 /* initialize EEPROM */
3203 3202 tmp = WPI_READ(sc, WPI_EEPROM_STATUS);
3204 3203 if ((tmp & WPI_EEPROM_VERSION) == 0) {
3205 3204 cmn_err(CE_WARN, "wpi_reset(): EEPROM not found\n");
3206 3205 return (EIO);
3207 3206 }
3208 3207 WPI_WRITE(sc, WPI_EEPROM_STATUS, tmp & ~WPI_EEPROM_LOCKED);
3209 3208
3210 3209 return (WPI_SUCCESS);
3211 3210 }
3212 3211
3213 3212 static void
3214 3213 wpi_hw_config(wpi_sc_t *sc)
3215 3214 {
3216 3215 uint16_t val;
3217 3216 uint32_t hw;
3218 3217
3219 3218 /* voodoo from the Linux "driver".. */
3220 3219 hw = WPI_READ(sc, WPI_HWCONFIG);
3221 3220
3222 3221 if ((sc->sc_rev & 0xc0) == 0x40)
3223 3222 hw |= WPI_HW_ALM_MB;
3224 3223 else if (!(sc->sc_rev & 0x80))
3225 3224 hw |= WPI_HW_ALM_MM;
3226 3225
3227 3226 val = wpi_read_prom_word(sc, WPI_EEPROM_CAPABILITIES);
3228 3227 if ((val & 0xff) == 0x80)
3229 3228 hw |= WPI_HW_SKU_MRC;
3230 3229
3231 3230 val = wpi_read_prom_word(sc, WPI_EEPROM_REVISION);
3232 3231 hw &= ~WPI_HW_REV_D;
3233 3232 if ((val & 0xf0) == 0xd0)
3234 3233 hw |= WPI_HW_REV_D;
3235 3234
3236 3235 val = wpi_read_prom_word(sc, WPI_EEPROM_TYPE);
3237 3236 if ((val & 0xff) > 1)
3238 3237 hw |= WPI_HW_TYPE_B;
3239 3238
3240 3239 WPI_DBG((WPI_DEBUG_HW, "setting h/w config %x\n", hw));
3241 3240 WPI_WRITE(sc, WPI_HWCONFIG, hw);
3242 3241 }
3243 3242
3244 3243 static int
3245 3244 wpi_init(wpi_sc_t *sc)
3246 3245 {
3247 3246 uint32_t tmp;
3248 3247 int qid, ntries, err;
3249 3248 clock_t clk;
3250 3249
3251 3250 mutex_enter(&sc->sc_glock);
3252 3251 sc->sc_flags &= ~WPI_F_FW_INIT;
3253 3252
3254 3253 (void) wpi_reset(sc);
3255 3254
3256 3255 wpi_mem_lock(sc);
3257 3256 wpi_mem_write(sc, WPI_MEM_CLOCK1, 0xa00);
3258 3257 DELAY(20);
3259 3258 tmp = wpi_mem_read(sc, WPI_MEM_PCIDEV);
3260 3259 wpi_mem_write(sc, WPI_MEM_PCIDEV, tmp | 0x800);
3261 3260 wpi_mem_unlock(sc);
3262 3261
3263 3262 (void) wpi_power_up(sc);
3264 3263 wpi_hw_config(sc);
3265 3264
3266 3265 tmp = WPI_READ(sc, WPI_GPIO_CTL);
3267 3266 if (!(tmp & WPI_GPIO_HW_RF_KILL)) {
3268 3267 cmn_err(CE_WARN, "wpi_init(): Radio transmitter is off\n");
3269 3268 goto fail1;
3270 3269 }
3271 3270
3272 3271 /* init Rx ring */
3273 3272 wpi_mem_lock(sc);
3274 3273 WPI_WRITE(sc, WPI_RX_BASE, sc->sc_rxq.dma_desc.cookie.dmac_address);
3275 3274 WPI_WRITE(sc, WPI_RX_RIDX_PTR,
3276 3275 (uint32_t)(sc->sc_dma_sh.cookie.dmac_address +
3277 3276 offsetof(wpi_shared_t, next)));
3278 3277 WPI_WRITE(sc, WPI_RX_WIDX, (WPI_RX_RING_COUNT - 1) & (~7));
3279 3278 WPI_WRITE(sc, WPI_RX_CONFIG, 0xa9601010);
3280 3279 wpi_mem_unlock(sc);
3281 3280
3282 3281 /* init Tx rings */
3283 3282 wpi_mem_lock(sc);
3284 3283 wpi_mem_write(sc, WPI_MEM_MODE, 2); /* bypass mode */
3285 3284 wpi_mem_write(sc, WPI_MEM_RA, 1); /* enable RA0 */
3286 3285 wpi_mem_write(sc, WPI_MEM_TXCFG, 0x3f); /* enable all 6 Tx rings */
3287 3286 wpi_mem_write(sc, WPI_MEM_BYPASS1, 0x10000);
3288 3287 wpi_mem_write(sc, WPI_MEM_BYPASS2, 0x30002);
3289 3288 wpi_mem_write(sc, WPI_MEM_MAGIC4, 4);
3290 3289 wpi_mem_write(sc, WPI_MEM_MAGIC5, 5);
3291 3290
3292 3291 WPI_WRITE(sc, WPI_TX_BASE_PTR, sc->sc_dma_sh.cookie.dmac_address);
3293 3292 WPI_WRITE(sc, WPI_MSG_CONFIG, 0xffff05a5);
3294 3293
3295 3294 for (qid = 0; qid < 6; qid++) {
3296 3295 WPI_WRITE(sc, WPI_TX_CTL(qid), 0);
3297 3296 WPI_WRITE(sc, WPI_TX_BASE(qid), 0);
3298 3297 WPI_WRITE(sc, WPI_TX_CONFIG(qid), 0x80200008);
3299 3298 }
3300 3299 wpi_mem_unlock(sc);
3301 3300
3302 3301 /* clear "radio off" and "disable command" bits (reversed logic) */
3303 3302 WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF);
3304 3303 WPI_WRITE(sc, WPI_UCODE_CLR, WPI_DISABLE_CMD);
3305 3304
3306 3305 /* clear any pending interrupts */
3307 3306 WPI_WRITE(sc, WPI_INTR, 0xffffffff);
3308 3307
3309 3308 /* enable interrupts */
3310 3309 WPI_WRITE(sc, WPI_MASK, WPI_INTR_MASK);
3311 3310
3312 3311 /* load firmware boot code into NIC */
3313 3312 err = wpi_load_microcode(sc);
3314 3313 if (err != WPI_SUCCESS) {
3315 3314 cmn_err(CE_WARN, "wpi_init(): failed to load microcode\n");
3316 3315 goto fail1;
3317 3316 }
3318 3317
3319 3318 /* load firmware .text segment into NIC */
3320 3319 err = wpi_load_firmware(sc, WPI_FW_TEXT);
3321 3320 if (err != WPI_SUCCESS) {
3322 3321 cmn_err(CE_WARN, "wpi_init(): "
3323 3322 "failed to load firmware(text)\n");
3324 3323 goto fail1;
3325 3324 }
3326 3325
3327 3326 /* load firmware .data segment into NIC */
3328 3327 err = wpi_load_firmware(sc, WPI_FW_DATA);
3329 3328 if (err != WPI_SUCCESS) {
3330 3329 cmn_err(CE_WARN, "wpi_init(): "
3331 3330 "failed to load firmware(data)\n");
3332 3331 goto fail1;
3333 3332 }
3334 3333
3335 3334 /* now press "execute" ;-) */
3336 3335 tmp = WPI_READ(sc, WPI_RESET);
3337 3336 tmp &= ~(WPI_MASTER_DISABLED | WPI_STOP_MASTER | WPI_NEVO_RESET);
3338 3337 WPI_WRITE(sc, WPI_RESET, tmp);
3339 3338
3340 3339 /* ..and wait at most one second for adapter to initialize */
3341 3340 clk = ddi_get_lbolt() + drv_usectohz(2000000);
3342 3341 while (!(sc->sc_flags & WPI_F_FW_INIT)) {
3343 3342 if (cv_timedwait(&sc->sc_fw_cv, &sc->sc_glock, clk) < 0)
3344 3343 break;
3345 3344 }
3346 3345 if (!(sc->sc_flags & WPI_F_FW_INIT)) {
3347 3346 cmn_err(CE_WARN,
3348 3347 "wpi_init(): timeout waiting for firmware init\n");
3349 3348 goto fail1;
3350 3349 }
3351 3350
3352 3351 /* wait for thermal sensors to calibrate */
3353 3352 for (ntries = 0; ntries < 1000; ntries++) {
3354 3353 if (WPI_READ(sc, WPI_TEMPERATURE) != 0)
3355 3354 break;
3356 3355 DELAY(10);
3357 3356 }
3358 3357
3359 3358 if (ntries == 1000) {
3360 3359 WPI_DBG((WPI_DEBUG_HW,
3361 3360 "wpi_init(): timeout waiting for thermal sensors "
3362 3361 "calibration\n"));
3363 3362 }
3364 3363
3365 3364 WPI_DBG((WPI_DEBUG_HW, "temperature %d\n",
3366 3365 (int)WPI_READ(sc, WPI_TEMPERATURE)));
3367 3366
3368 3367 err = wpi_config(sc);
3369 3368 if (err) {
3370 3369 cmn_err(CE_WARN, "wpi_init(): failed to configure device\n");
3371 3370 goto fail1;
3372 3371 }
3373 3372
3374 3373 mutex_exit(&sc->sc_glock);
3375 3374 return (WPI_SUCCESS);
3376 3375
3377 3376 fail1:
3378 3377 err = WPI_FAIL;
3379 3378 mutex_exit(&sc->sc_glock);
3380 3379 return (err);
3381 3380 }
3382 3381
3383 3382 static int
3384 3383 wpi_fast_recover(wpi_sc_t *sc)
3385 3384 {
3386 3385 ieee80211com_t *ic = &sc->sc_ic;
3387 3386 int err;
3388 3387
3389 3388 mutex_enter(&sc->sc_glock);
3390 3389
3391 3390 /* restore runtime configuration */
3392 3391 bcopy(&sc->sc_config_save, &sc->sc_config,
3393 3392 sizeof (sc->sc_config));
3394 3393
3395 3394 sc->sc_config.state = 0;
3396 3395 sc->sc_config.filter &= ~LE_32(WPI_FILTER_BSS);
3397 3396
3398 3397 if ((err = wpi_auth(sc)) != 0) {
3399 3398 cmn_err(CE_WARN, "wpi_fast_recover(): "
3400 3399 "failed to setup authentication\n");
3401 3400 mutex_exit(&sc->sc_glock);
3402 3401 return (err);
3403 3402 }
3404 3403
3405 3404 sc->sc_config.state = LE_16(WPI_CONFIG_ASSOCIATED);
3406 3405 sc->sc_config.flags &= ~LE_32(WPI_CONFIG_SHPREAMBLE |
3407 3406 WPI_CONFIG_SHSLOT);
3408 3407 if (ic->ic_flags & IEEE80211_F_SHSLOT)
3409 3408 sc->sc_config.flags |= LE_32(WPI_CONFIG_SHSLOT);
3410 3409 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
3411 3410 sc->sc_config.flags |= LE_32(WPI_CONFIG_SHPREAMBLE);
3412 3411 sc->sc_config.filter |= LE_32(WPI_FILTER_BSS);
3413 3412 if (ic->ic_opmode != IEEE80211_M_STA)
3414 3413 sc->sc_config.filter |= LE_32(WPI_FILTER_BEACON);
3415 3414
3416 3415 WPI_DBG((WPI_DEBUG_80211, "config chan %d flags %x\n",
3417 3416 sc->sc_config.chan, sc->sc_config.flags));
3418 3417 err = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->sc_config,
3419 3418 sizeof (wpi_config_t), 1);
3420 3419 if (err != WPI_SUCCESS) {
3421 3420 cmn_err(CE_WARN, "failed to setup association\n");
3422 3421 mutex_exit(&sc->sc_glock);
3423 3422 return (err);
3424 3423 }
3425 3424 /* link LED on */
3426 3425 wpi_set_led(sc, WPI_LED_LINK, 0, 1);
3427 3426
3428 3427 mutex_exit(&sc->sc_glock);
3429 3428
3430 3429 /* update keys */
3431 3430 if (ic->ic_flags & IEEE80211_F_PRIVACY) {
3432 3431 for (int i = 0; i < IEEE80211_KEY_MAX; i++) {
3433 3432 if (ic->ic_nw_keys[i].wk_keyix == IEEE80211_KEYIX_NONE)
3434 3433 continue;
3435 3434 err = wpi_key_set(ic, &ic->ic_nw_keys[i],
3436 3435 ic->ic_bss->in_macaddr);
3437 3436 /* failure */
3438 3437 if (err == 0) {
3439 3438 cmn_err(CE_WARN, "wpi_fast_recover(): "
3440 3439 "failed to setup hardware keys\n");
3441 3440 return (WPI_FAIL);
3442 3441 }
3443 3442 }
3444 3443 }
3445 3444
3446 3445 sc->sc_flags &= ~WPI_F_HW_ERR_RECOVER;
3447 3446
3448 3447 /* start queue */
3449 3448 WPI_DBG((WPI_DEBUG_FW, "wpi_fast_recover(): resume xmit\n"));
3450 3449 mac_tx_update(ic->ic_mach);
3451 3450
3452 3451 return (WPI_SUCCESS);
3453 3452 }
3454 3453
3455 3454 /*
3456 3455 * quiesce(9E) entry point.
3457 3456 * This function is called when the system is single-threaded at high
3458 3457 * PIL with preemption disabled. Therefore, this function must not be
3459 3458 * blocked.
3460 3459 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
3461 3460 * DDI_FAILURE indicates an error condition and should almost never happen.
3462 3461 */
3463 3462 static int
3464 3463 wpi_quiesce(dev_info_t *dip)
3465 3464 {
3466 3465 wpi_sc_t *sc;
3467 3466
3468 3467 sc = ddi_get_soft_state(wpi_soft_state_p, ddi_get_instance(dip));
3469 3468 if (sc == NULL)
3470 3469 return (DDI_FAILURE);
3471 3470
3472 3471 #ifdef DEBUG
3473 3472 /* by pass any messages, if it's quiesce */
3474 3473 wpi_dbg_flags = 0;
3475 3474 #endif
3476 3475
3477 3476 /*
3478 3477 * No more blocking is allowed while we are in the
3479 3478 * quiesce(9E) entry point.
3480 3479 */
3481 3480 sc->sc_flags |= WPI_F_QUIESCED;
3482 3481
3483 3482 /*
3484 3483 * Disable and mask all interrupts.
3485 3484 */
3486 3485 wpi_stop(sc);
3487 3486 return (DDI_SUCCESS);
3488 3487 }
3489 3488
3490 3489 static void
3491 3490 wpi_stop(wpi_sc_t *sc)
3492 3491 {
3493 3492 uint32_t tmp;
3494 3493 int ac;
3495 3494
3496 3495 /* no mutex operation, if it's quiesced */
3497 3496 if (!(sc->sc_flags & WPI_F_QUIESCED))
3498 3497 mutex_enter(&sc->sc_glock);
3499 3498
3500 3499 /* disable interrupts */
3501 3500 WPI_WRITE(sc, WPI_MASK, 0);
3502 3501 WPI_WRITE(sc, WPI_INTR, WPI_INTR_MASK);
3503 3502 WPI_WRITE(sc, WPI_INTR_STATUS, 0xff);
3504 3503 WPI_WRITE(sc, WPI_INTR_STATUS, 0x00070000);
3505 3504
3506 3505 wpi_mem_lock(sc);
3507 3506 wpi_mem_write(sc, WPI_MEM_MODE, 0);
3508 3507 wpi_mem_unlock(sc);
3509 3508
3510 3509 /* reset all Tx rings */
3511 3510 for (ac = 0; ac < 4; ac++)
3512 3511 wpi_reset_tx_ring(sc, &sc->sc_txq[ac]);
3513 3512 wpi_reset_tx_ring(sc, &sc->sc_cmdq);
3514 3513 wpi_reset_tx_ring(sc, &sc->sc_svcq);
3515 3514
3516 3515 /* reset Rx ring */
3517 3516 wpi_reset_rx_ring(sc);
3518 3517
3519 3518 wpi_mem_lock(sc);
3520 3519 wpi_mem_write(sc, WPI_MEM_CLOCK2, 0x200);
3521 3520 wpi_mem_unlock(sc);
3522 3521
3523 3522 DELAY(5);
3524 3523
3525 3524 wpi_stop_master(sc);
3526 3525
3527 3526 sc->sc_tx_timer = 0;
3528 3527 sc->sc_flags &= ~WPI_F_SCANNING;
3529 3528 sc->sc_scan_pending = 0;
3530 3529 sc->sc_scan_next = 0;
3531 3530
3532 3531 tmp = WPI_READ(sc, WPI_RESET);
3533 3532 WPI_WRITE(sc, WPI_RESET, tmp | WPI_SW_RESET);
3534 3533
3535 3534 /* no mutex operation, if it's quiesced */
3536 3535 if (!(sc->sc_flags & WPI_F_QUIESCED))
3537 3536 mutex_exit(&sc->sc_glock);
3538 3537 }
3539 3538
3540 3539 /*
3541 3540 * Naive implementation of the Adaptive Multi Rate Retry algorithm:
3542 3541 * "IEEE 802.11 Rate Adaptation: A Practical Approach"
3543 3542 * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
3544 3543 * INRIA Sophia - Projet Planete
3545 3544 * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
3546 3545 */
3547 3546 #define is_success(amrr) \
3548 3547 ((amrr)->retrycnt < (amrr)->txcnt / 10)
3549 3548 #define is_failure(amrr) \
3550 3549 ((amrr)->retrycnt > (amrr)->txcnt / 3)
3551 3550 #define is_enough(amrr) \
3552 3551 ((amrr)->txcnt > 100)
3553 3552 #define is_min_rate(in) \
3554 3553 ((in)->in_txrate == 0)
3555 3554 #define is_max_rate(in) \
3556 3555 ((in)->in_txrate == (in)->in_rates.ir_nrates - 1)
3557 3556 #define increase_rate(in) \
3558 3557 ((in)->in_txrate++)
3559 3558 #define decrease_rate(in) \
3560 3559 ((in)->in_txrate--)
3561 3560 #define reset_cnt(amrr) \
3562 3561 { (amrr)->txcnt = (amrr)->retrycnt = 0; }
3563 3562
3564 3563 #define WPI_AMRR_MIN_SUCCESS_THRESHOLD 1
3565 3564 #define WPI_AMRR_MAX_SUCCESS_THRESHOLD 15
3566 3565
3567 3566 static void
3568 3567 wpi_amrr_init(wpi_amrr_t *amrr)
3569 3568 {
3570 3569 amrr->success = 0;
3571 3570 amrr->recovery = 0;
3572 3571 amrr->txcnt = amrr->retrycnt = 0;
3573 3572 amrr->success_threshold = WPI_AMRR_MIN_SUCCESS_THRESHOLD;
3574 3573 }
3575 3574
3576 3575 static void
3577 3576 wpi_amrr_timeout(wpi_sc_t *sc)
3578 3577 {
3579 3578 ieee80211com_t *ic = &sc->sc_ic;
3580 3579
3581 3580 WPI_DBG((WPI_DEBUG_RATECTL, "wpi_amrr_timeout() enter\n"));
3582 3581 if (ic->ic_opmode == IEEE80211_M_STA)
3583 3582 wpi_amrr_ratectl(NULL, ic->ic_bss);
3584 3583 else
3585 3584 ieee80211_iterate_nodes(&ic->ic_sta, wpi_amrr_ratectl, NULL);
3586 3585 sc->sc_clk = ddi_get_lbolt();
3587 3586 }
3588 3587
3589 3588 /* ARGSUSED */
3590 3589 static void
3591 3590 wpi_amrr_ratectl(void *arg, ieee80211_node_t *in)
3592 3591 {
3593 3592 wpi_amrr_t *amrr = (wpi_amrr_t *)in;
3594 3593 int need_change = 0;
3595 3594
3596 3595 if (is_success(amrr) && is_enough(amrr)) {
3597 3596 amrr->success++;
3598 3597 if (amrr->success >= amrr->success_threshold &&
3599 3598 !is_max_rate(in)) {
3600 3599 amrr->recovery = 1;
3601 3600 amrr->success = 0;
3602 3601 increase_rate(in);
3603 3602 WPI_DBG((WPI_DEBUG_RATECTL,
3604 3603 "AMRR increasing rate %d (txcnt=%d retrycnt=%d)\n",
3605 3604 in->in_txrate, amrr->txcnt, amrr->retrycnt));
3606 3605 need_change = 1;
3607 3606 } else {
3608 3607 amrr->recovery = 0;
3609 3608 }
3610 3609 } else if (is_failure(amrr)) {
3611 3610 amrr->success = 0;
3612 3611 if (!is_min_rate(in)) {
3613 3612 if (amrr->recovery) {
3614 3613 amrr->success_threshold++;
3615 3614 if (amrr->success_threshold >
3616 3615 WPI_AMRR_MAX_SUCCESS_THRESHOLD)
3617 3616 amrr->success_threshold =
3618 3617 WPI_AMRR_MAX_SUCCESS_THRESHOLD;
3619 3618 } else {
3620 3619 amrr->success_threshold =
3621 3620 WPI_AMRR_MIN_SUCCESS_THRESHOLD;
3622 3621 }
3623 3622 decrease_rate(in);
3624 3623 WPI_DBG((WPI_DEBUG_RATECTL,
3625 3624 "AMRR decreasing rate %d (txcnt=%d retrycnt=%d)\n",
3626 3625 in->in_txrate, amrr->txcnt, amrr->retrycnt));
3627 3626 need_change = 1;
3628 3627 }
3629 3628 amrr->recovery = 0; /* paper is incorrect */
3630 3629 }
3631 3630
3632 3631 if (is_enough(amrr) || need_change)
3633 3632 reset_cnt(amrr);
3634 3633 }
↓ open down ↓ |
3303 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX