Print this page
10886 smatch debug macro cleanup in usr/src/uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/rwd/rt2661.c
+++ new/usr/src/uts/common/io/rwd/rt2661.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
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
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 * Ralink Technology RT2561, RT2561S and RT2661 chipset driver
25 25 * http://www.ralinktech.com/
26 26 */
27 27
28 +/*
29 + * Copyright 2019 Joyent, Inc.
30 + */
31 +
28 32 #include <sys/types.h>
29 33 #include <sys/byteorder.h>
30 34 #include <sys/conf.h>
31 35 #include <sys/cmn_err.h>
32 36 #include <sys/stat.h>
33 37 #include <sys/ddi.h>
34 38 #include <sys/sunddi.h>
35 39 #include <sys/strsubr.h>
36 40 #include <sys/ethernet.h>
37 41 #include <inet/common.h>
38 42 #include <inet/nd.h>
39 43 #include <inet/mi.h>
40 44 #include <sys/note.h>
41 45 #include <sys/stream.h>
42 46 #include <sys/strsun.h>
43 47 #include <sys/modctl.h>
44 48 #include <sys/devops.h>
45 49 #include <sys/dlpi.h>
46 50 #include <sys/mac_provider.h>
47 51 #include <sys/mac_wifi.h>
48 52 #include <sys/net80211.h>
49 53 #include <sys/net80211_proto.h>
50 54 #include <sys/varargs.h>
51 55 #include <sys/policy.h>
52 56 #include <sys/pci.h>
53 57 #include <sys/crypto/common.h>
54 58 #include <sys/crypto/api.h>
55 59 #include <inet/wifi_ioctl.h>
56 60
57 61 #include "rt2661_reg.h"
58 62 #include "rt2661_var.h"
59 63 #include "rt2661_ucode.h"
60 64
61 65 #define RT2661_DBG_80211 (1 << 0)
62 66 #define RT2661_DBG_DMA (1 << 1)
63 67 #define RT2661_DBG_EEPROM (1 << 2)
64 68 #define RT2661_DBG_FW (1 << 3)
65 69 #define RT2661_DBG_HW (1 << 4)
66 70 #define RT2661_DBG_INTR (1 << 5)
67 71 #define RT2661_DBG_RX (1 << 6)
68 72 #define RT2661_DBG_SCAN (1 << 7)
69 73 #define RT2661_DBG_TX (1 << 8)
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
70 74 #define RT2661_DBG_RADIO (1 << 9)
71 75 #define RT2661_DBG_RESUME (1 << 10)
72 76 #define RT2661_DBG_MSG (1 << 11)
73 77
74 78 uint32_t rt2661_dbg_flags = 0;
75 79
76 80 #ifdef DEBUG
77 81 #define RWD_DEBUG \
78 82 rt2661_debug
79 83 #else
80 -#define RWD_DEBUG
84 +#define RWD_DEBUG(...) (void)(0)
81 85 #endif
82 86
83 87 static void *rt2661_soft_state_p = NULL;
84 88
85 89 static const uint8_t *ucode = NULL;
86 90 int usize;
87 91
88 92 static const struct {
89 93 uint32_t reg;
90 94 uint32_t val;
91 95 } rt2661_def_mac[] = {
92 96 RT2661_DEF_MAC
93 97 };
94 98
95 99 static const struct {
96 100 uint8_t reg;
97 101 uint8_t val;
98 102 } rt2661_def_bbp[] = {
99 103 RT2661_DEF_BBP
100 104 };
101 105
102 106 static const struct rfprog {
103 107 uint8_t chan;
104 108 uint32_t r1, r2, r3, r4;
105 109 } rt2661_rf5225_1[] = {
106 110 RT2661_RF5225_1
107 111 }, rt2661_rf5225_2[] = {
108 112 RT2661_RF5225_2
109 113 };
110 114
111 115 /*
112 116 * PIO access attributes for registers
113 117 */
114 118 static ddi_device_acc_attr_t rt2661_csr_accattr = {
115 119 DDI_DEVICE_ATTR_V0,
116 120 DDI_STRUCTURE_LE_ACC,
117 121 DDI_STRICTORDER_ACC
118 122 };
119 123
120 124 /*
121 125 * DMA access attributes for descriptors: NOT to be byte swapped.
122 126 */
123 127 static ddi_device_acc_attr_t rt2661_desc_accattr = {
124 128 DDI_DEVICE_ATTR_V0,
125 129 DDI_STRUCTURE_LE_ACC,
126 130 DDI_STRICTORDER_ACC
127 131 };
128 132
129 133 static ddi_device_acc_attr_t rt2661_buf_accattr = {
130 134 DDI_DEVICE_ATTR_V0,
131 135 DDI_NEVERSWAP_ACC,
132 136 DDI_STRICTORDER_ACC,
133 137 DDI_DEFAULT_ACC
134 138 };
135 139
136 140 /*
137 141 * Describes the chip's DMA engine
138 142 */
139 143 static ddi_dma_attr_t rt2661_dma_attr = {
140 144 DMA_ATTR_V0, /* dma_attr version */
141 145 0x0, /* dma_attr_addr_lo */
142 146 0xffffffffU, /* dma_attr_addr_hi */
143 147 0xffffffffU, /* dma_attr_count_max */
144 148 1, /* dma_attr_align */
145 149 0x00000fff, /* dma_attr_burstsizes */
146 150 1, /* dma_attr_minxfer */
147 151 0xffffffffU, /* dma_attr_maxxfer */
148 152 0xffffffffU, /* dma_attr_seg */
149 153 1, /* dma_attr_sgllen */
150 154 1, /* dma_attr_granular */
151 155 0 /* dma_attr_flags */
152 156 };
153 157
154 158 static const struct ieee80211_rateset rt2661_rateset_11b =
155 159 { 4, { 2, 4, 11, 22 } };
156 160
157 161 static const struct ieee80211_rateset rt2661_rateset_11g =
158 162 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
159 163
160 164
161 165 static const char *rt2661_get_rf(int);
162 166
163 167 static void rt2661_read_eeprom(struct rt2661_softc *);
164 168 static uint16_t rt2661_eeprom_read(struct rt2661_softc *, uint8_t);
165 169 static int rt2661_load_microcode(struct rt2661_softc *,
166 170 const uint8_t *, int);
167 171
168 172 static int rt2661_alloc_dma_mem(dev_info_t *, ddi_dma_attr_t *, size_t,
169 173 ddi_device_acc_attr_t *, uint_t, uint_t, struct dma_area *);
170 174 static void rt2661_free_dma_mem(struct dma_area *);
171 175 static int rt2661_alloc_tx_ring(struct rt2661_softc *,
172 176 struct rt2661_tx_ring *, int);
173 177 static void rt2661_reset_tx_ring(struct rt2661_softc *,
174 178 struct rt2661_tx_ring *);
175 179 static void rt2661_free_tx_ring(struct rt2661_softc *,
176 180 struct rt2661_tx_ring *);
177 181 static int rt2661_alloc_rx_ring(struct rt2661_softc *,
178 182 struct rt2661_rx_ring *, int);
179 183 static void rt2661_reset_rx_ring(struct rt2661_softc *,
180 184 struct rt2661_rx_ring *);
181 185 static void rt2661_free_rx_ring(struct rt2661_softc *,
182 186 struct rt2661_rx_ring *);
183 187 static void rt2661_tx_dma_intr(struct rt2661_softc *,
184 188 struct rt2661_tx_ring *);
185 189 static void rt2661_tx_intr(struct rt2661_softc *);
186 190 static void rt2661_rx_intr(struct rt2661_softc *);
187 191 static uint_t rt2661_softintr(caddr_t, caddr_t);
188 192 static void rt2661_mcu_wakeup(struct rt2661_softc *);
189 193 static void rt2661_mcu_cmd_intr(struct rt2661_softc *);
190 194 static uint_t rt2661_intr(caddr_t, caddr_t);
191 195
192 196 static uint16_t rt2661_txtime(int, int, uint32_t);
193 197 static int rt2661_ack_rate(struct ieee80211com *, int);
194 198 static uint8_t rt2661_plcp_signal(int);
195 199 static void rt2661_setup_tx_desc(struct rt2661_softc *,
196 200 struct rt2661_tx_desc *, uint32_t, uint16_t, int,
197 201 int, int);
198 202
199 203 static int rt2661_get_rssi(struct rt2661_softc *, uint8_t);
200 204
201 205 static int rt2661_send(ieee80211com_t *, mblk_t *);
202 206 static int rt2661_mgmt_send(ieee80211com_t *, mblk_t *, uint8_t);
203 207
204 208 static void rt2661_amrr_node_init(const struct rt2661_amrr *,
205 209 struct rt2661_amrr_node *);
206 210 static void rt2661_amrr_choose(struct rt2661_amrr *,
207 211 struct ieee80211_node *, struct rt2661_amrr_node *);
208 212
209 213 static void rt2661_update_promisc(struct rt2661_softc *);
210 214 static void rt2661_updateslot(struct ieee80211com *, int);
211 215 static void rt2661_set_slottime(struct rt2661_softc *);
212 216 static void rt2661_enable_mrr(struct rt2661_softc *);
213 217 static void rt2661_set_txpreamble(struct rt2661_softc *);
214 218 static void rt2661_set_basicrates(struct rt2661_softc *);
215 219 static void rt2661_set_bssid(struct rt2661_softc *, const uint8_t *);
216 220 static void rt2661_newassoc(struct ieee80211com *, struct ieee80211_node *);
217 221 static void rt2661_updatestats(void *);
218 222 static void rt2661_rx_tune(struct rt2661_softc *);
219 223 static void rt2661_enable_tsf_sync(struct rt2661_softc *);
220 224 static int rt2661_newstate(struct ieee80211com *,
221 225 enum ieee80211_state, int);
222 226
223 227 static void rt2661_set_macaddr(struct rt2661_softc *, const uint8_t *);
224 228 static int rt2661_bbp_init(struct rt2661_softc *);
225 229 static uint8_t rt2661_bbp_read(struct rt2661_softc *, uint8_t);
226 230 static void rt2661_bbp_write(struct rt2661_softc *, uint8_t, uint8_t);
227 231 static void rt2661_select_band(struct rt2661_softc *,
228 232 struct ieee80211_channel *);
229 233 static void rt2661_select_antenna(struct rt2661_softc *);
230 234 static void rt2661_rf_write(struct rt2661_softc *, uint8_t, uint32_t);
231 235 static void rt2661_set_chan(struct rt2661_softc *,
232 236 struct ieee80211_channel *);
233 237
234 238 static void rt2661_stop_locked(struct rt2661_softc *);
235 239 static int rt2661_init(struct rt2661_softc *);
236 240 static void rt2661_stop(struct rt2661_softc *);
237 241 /*
238 242 * device operations
239 243 */
240 244 static int rt2661_attach(dev_info_t *, ddi_attach_cmd_t);
241 245 static int rt2661_detach(dev_info_t *, ddi_detach_cmd_t);
242 246 static int rt2661_quiesce(dev_info_t *);
243 247
244 248 /*
245 249 * Module Loading Data & Entry Points
246 250 */
247 251 DDI_DEFINE_STREAM_OPS(rwd_dev_ops, nulldev, nulldev, rt2661_attach,
248 252 rt2661_detach, nodev, NULL, D_MP, NULL, rt2661_quiesce);
249 253
250 254 static struct modldrv rwd_modldrv = {
251 255 &mod_driverops, /* Type of module. This one is a driver */
252 256 "Ralink RT2661 driver v1.1", /* short description */
253 257 &rwd_dev_ops /* driver specific ops */
254 258 };
255 259
256 260 static struct modlinkage modlinkage = {
257 261 MODREV_1,
258 262 (void *)&rwd_modldrv,
259 263 NULL
260 264 };
261 265
262 266 static int rt2661_m_stat(void *, uint_t, uint64_t *);
263 267 static int rt2661_m_start(void *);
264 268 static void rt2661_m_stop(void *);
265 269 static int rt2661_m_promisc(void *, boolean_t);
266 270 static int rt2661_m_multicst(void *, boolean_t, const uint8_t *);
267 271 static int rt2661_m_unicst(void *, const uint8_t *);
268 272 static mblk_t *rt2661_m_tx(void *, mblk_t *);
269 273 static void rt2661_m_ioctl(void *, queue_t *, mblk_t *);
270 274 static int rt2661_m_setprop(void *arg, const char *pr_name,
271 275 mac_prop_id_t wldp_pr_num,
272 276 uint_t wldp_length, const void *wldp_buf);
273 277 static int rt2661_m_getprop(void *arg, const char *pr_name,
274 278 mac_prop_id_t wldp_pr_num, uint_t wldp_length,
275 279 void *wldp_buf);
276 280 static void rt2661_m_propinfo(void *arg, const char *pr_name,
277 281 mac_prop_id_t wldp_pr_num, mac_prop_info_handle_t mph);
278 282
279 283 static mac_callbacks_t rt2661_m_callbacks = {
280 284 MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
281 285 rt2661_m_stat,
282 286 rt2661_m_start,
283 287 rt2661_m_stop,
284 288 rt2661_m_promisc,
285 289 rt2661_m_multicst,
286 290 rt2661_m_unicst,
287 291 rt2661_m_tx,
288 292 NULL,
289 293 rt2661_m_ioctl,
290 294 NULL,
291 295 NULL,
292 296 NULL,
293 297 rt2661_m_setprop,
294 298 rt2661_m_getprop,
295 299 rt2661_m_propinfo
296 300 };
297 301
298 302 #ifdef DEBUG
299 303 void
300 304 rt2661_debug(uint32_t dbg_flags, const int8_t *fmt, ...)
301 305 {
302 306 va_list args;
303 307
304 308 if (dbg_flags & rt2661_dbg_flags) {
305 309 va_start(args, fmt);
306 310 vcmn_err(CE_CONT, fmt, args);
307 311 va_end(args);
308 312 }
309 313 }
310 314 #endif
311 315
312 316 /*
313 317 * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46 or
314 318 * 93C66).
315 319 */
316 320 static uint16_t
317 321 rt2661_eeprom_read(struct rt2661_softc *sc, uint8_t addr)
318 322 {
319 323 uint32_t tmp;
320 324 uint16_t val;
321 325 int n;
322 326
323 327 /* clock C once before the first command */
324 328 RT2661_EEPROM_CTL(sc, 0);
325 329
326 330 RT2661_EEPROM_CTL(sc, RT2661_S);
327 331 RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
328 332 RT2661_EEPROM_CTL(sc, RT2661_S);
329 333
330 334 /* write start bit (1) */
331 335 RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D);
332 336 RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D | RT2661_C);
333 337
334 338 /* write READ opcode (10) */
335 339 RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D);
336 340 RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D | RT2661_C);
337 341 RT2661_EEPROM_CTL(sc, RT2661_S);
338 342 RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
339 343
340 344 /* write address (A5-A0 or A7-A0) */
341 345 n = (RT2661_READ(sc, RT2661_E2PROM_CSR) & RT2661_93C46) ? 5 : 7;
342 346 for (; n >= 0; n--) {
343 347 RT2661_EEPROM_CTL(sc, RT2661_S |
344 348 (((addr >> n) & 1) << RT2661_SHIFT_D));
345 349 RT2661_EEPROM_CTL(sc, RT2661_S |
346 350 (((addr >> n) & 1) << RT2661_SHIFT_D) | RT2661_C);
347 351 }
348 352
349 353 RT2661_EEPROM_CTL(sc, RT2661_S);
350 354
351 355 /* read data Q15-Q0 */
352 356 val = 0;
353 357 for (n = 15; n >= 0; n--) {
354 358 RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
355 359 tmp = RT2661_READ(sc, RT2661_E2PROM_CSR);
356 360 val |= ((tmp & RT2661_Q) >> RT2661_SHIFT_Q) << n;
357 361 RT2661_EEPROM_CTL(sc, RT2661_S);
358 362 }
359 363
360 364 RT2661_EEPROM_CTL(sc, 0);
361 365
362 366 /* clear Chip Select and clock C */
363 367 RT2661_EEPROM_CTL(sc, RT2661_S);
364 368 RT2661_EEPROM_CTL(sc, 0);
365 369 RT2661_EEPROM_CTL(sc, RT2661_C);
366 370
367 371 return (val);
368 372 }
369 373
370 374
371 375 static void
372 376 rt2661_read_eeprom(struct rt2661_softc *sc)
373 377 {
374 378 struct ieee80211com *ic = &sc->sc_ic;
375 379 uint16_t val;
376 380 int i;
377 381
378 382 /* read MAC address */
379 383 val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC01);
380 384 ic->ic_macaddr[0] = val & 0xff;
381 385 ic->ic_macaddr[1] = val >> 8;
382 386
383 387 val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC23);
384 388 ic->ic_macaddr[2] = val & 0xff;
385 389 ic->ic_macaddr[3] = val >> 8;
386 390
387 391 val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC45);
388 392 ic->ic_macaddr[4] = val & 0xff;
389 393 ic->ic_macaddr[5] = val >> 8;
390 394
391 395 val = rt2661_eeprom_read(sc, RT2661_EEPROM_ANTENNA);
392 396 /* XXX: test if different from 0xffff? */
393 397 sc->rf_rev = (val >> 11) & 0x1f;
394 398 sc->hw_radio = (val >> 10) & 0x1;
395 399 sc->rx_ant = (val >> 4) & 0x3;
396 400 sc->tx_ant = (val >> 2) & 0x3;
397 401 sc->nb_ant = val & 0x3;
398 402
399 403 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
400 404 "RF revision=%d\n", sc->rf_rev);
401 405
402 406 val = rt2661_eeprom_read(sc, RT2661_EEPROM_CONFIG2);
403 407 sc->ext_5ghz_lna = (val >> 6) & 0x1;
404 408 sc->ext_2ghz_lna = (val >> 4) & 0x1;
405 409
406 410 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
407 411 "External 2GHz LNA=%d\nExternal 5GHz LNA=%d\n",
408 412 sc->ext_2ghz_lna, sc->ext_5ghz_lna);
409 413
410 414 val = rt2661_eeprom_read(sc, RT2661_EEPROM_RSSI_2GHZ_OFFSET);
411 415 if ((val & 0xff) != 0xff)
412 416 sc->rssi_2ghz_corr = (int8_t)(val & 0xff);
413 417
414 418 val = rt2661_eeprom_read(sc, RT2661_EEPROM_RSSI_5GHZ_OFFSET);
415 419 if ((val & 0xff) != 0xff)
416 420 sc->rssi_5ghz_corr = (int8_t)(val & 0xff);
417 421
418 422 /* adjust RSSI correction for external low-noise amplifier */
419 423 if (sc->ext_2ghz_lna)
420 424 sc->rssi_2ghz_corr -= 14;
421 425 if (sc->ext_5ghz_lna)
422 426 sc->rssi_5ghz_corr -= 14;
423 427
424 428 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
425 429 "RSSI 2GHz corr=%d\nRSSI 5GHz corr=%d\n",
426 430 sc->rssi_2ghz_corr, sc->rssi_5ghz_corr);
427 431
428 432 val = rt2661_eeprom_read(sc, RT2661_EEPROM_FREQ_OFFSET);
429 433 if ((val >> 8) != 0xff)
430 434 sc->rfprog = (val >> 8) & 0x3;
431 435 if ((val & 0xff) != 0xff)
432 436 sc->rffreq = val & 0xff;
433 437
434 438 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
435 439 "RF prog=%d\nRF freq=%d\n", sc->rfprog, sc->rffreq);
436 440
437 441 /* read Tx power for all a/b/g channels */
438 442 for (i = 0; i < 19; i++) {
439 443 val = rt2661_eeprom_read(sc, RT2661_EEPROM_TXPOWER + i);
440 444 sc->txpow[i * 2] = (int8_t)(val >> 8);
441 445 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
442 446 "Channel=%d Tx power=%d\n",
443 447 rt2661_rf5225_1[i * 2].chan, sc->txpow[i * 2]);
444 448 sc->txpow[i * 2 + 1] = (int8_t)(val & 0xff);
445 449 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
446 450 "Channel=%d Tx power=%d\n",
447 451 rt2661_rf5225_1[i * 2 + 1].chan, sc->txpow[i * 2 + 1]);
448 452 }
449 453
450 454 /* read vendor-specific BBP values */
451 455 for (i = 0; i < 16; i++) {
452 456 val = rt2661_eeprom_read(sc, RT2661_EEPROM_BBP_BASE + i);
453 457 if (val == 0 || val == 0xffff)
454 458 continue;
455 459 sc->bbp_prom[i].reg = val >> 8;
456 460 sc->bbp_prom[i].val = val & 0xff;
457 461 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
458 462 "BBP R%d=%02x\n", sc->bbp_prom[i].reg,
459 463 sc->bbp_prom[i].val);
460 464 }
461 465 }
462 466
463 467 static const char *
464 468 rt2661_get_rf(int rev)
465 469 {
466 470 switch (rev) {
467 471 case RT2661_RF_5225: return "RT5225";
468 472 case RT2661_RF_5325: return "RT5325 (MIMO XR)";
469 473 case RT2661_RF_2527: return "RT2527";
470 474 case RT2661_RF_2529: return "RT2529 (MIMO XR)";
471 475 default: return "unknown";
472 476 }
473 477 }
474 478
475 479 static int
476 480 rt2661_load_microcode(struct rt2661_softc *sc, const uint8_t *ucode_p, int size)
477 481 {
478 482 int ntries;
479 483 uint32_t off, i;
480 484 const uint8_t *fptr;
481 485
482 486 fptr = ucode_p;
483 487 off = RT2661_MCU_CODE_BASE;
484 488
485 489 /* reset 8051 */
486 490 RT2661_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET);
487 491
488 492 /* cancel any pending Host to MCU command */
489 493 RT2661_WRITE(sc, RT2661_H2M_MAILBOX_CSR, 0);
490 494 RT2661_WRITE(sc, RT2661_M2H_CMD_DONE_CSR, 0xffffffff);
491 495 RT2661_WRITE(sc, RT2661_HOST_CMD_CSR, 0);
492 496
493 497 /* write 8051's microcode */
494 498 RT2661_WRITE(sc, RT2661_MCU_CNTL_CSR,
495 499 RT2661_MCU_RESET | RT2661_MCU_SEL);
496 500 /* RT2661_WRITE_REGION_1(sc, RT2661_MCU_CODE_BASE, ucode, size); */
497 501
498 502 for (i = 0; i < size; i++) {
499 503 RT2661_MEM_WRITE1(sc, off++, *fptr++);
500 504 }
501 505
502 506 RT2661_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET);
503 507
504 508 /* kick 8051's ass */
505 509 RT2661_WRITE(sc, RT2661_MCU_CNTL_CSR, 0);
506 510
507 511 /* wait for 8051 to initialize */
508 512 for (ntries = 0; ntries < 500; ntries++) {
509 513 if (RT2661_READ(sc, RT2661_MCU_CNTL_CSR) & RT2661_MCU_READY)
510 514 break;
511 515 DELAY(100);
512 516 }
513 517 if (ntries == 500) {
514 518 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_load_microcode(): "
515 519 "timeout waiting for MCU to initialize\n");
516 520 return (RT2661_FAILURE);
517 521 }
518 522
519 523 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_load_microcode(): "
520 524 "MCU initialized successfully\n");
521 525 return (RT2661_SUCCESS);
522 526 }
523 527
524 528 /*
525 529 * Allocate an DMA memory and a DMA handle for accessing it
526 530 */
527 531 static int
528 532 rt2661_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr,
529 533 size_t memsize, ddi_device_acc_attr_t *attr_p, uint_t alloc_flags,
530 534 uint_t bind_flags, struct dma_area *dma_p)
531 535 {
532 536 int err;
533 537
534 538 /*
535 539 * Allocate handle
536 540 */
537 541 err = ddi_dma_alloc_handle(devinfo, dma_attr,
538 542 DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
539 543 if (err != DDI_SUCCESS) {
540 544 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rwd_allo_dma_mem(): "
541 545 "failed to alloc handle\n");
542 546 goto fail1;
543 547 }
544 548
545 549 /*
546 550 * Allocate memory
547 551 */
548 552 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p,
549 553 alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va,
550 554 &dma_p->alength, &dma_p->acc_hdl);
551 555 if (err != DDI_SUCCESS) {
552 556 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rwd_alloc_dma_mem(): "
553 557 "failed to alloc mem\n");
554 558 goto fail2;
555 559 }
556 560
557 561 /*
558 562 * Bind the two together
559 563 */
560 564 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
561 565 dma_p->mem_va, dma_p->alength, bind_flags,
562 566 DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies);
563 567 if (err != DDI_DMA_MAPPED) {
564 568 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rwd_alloc_dma_mem(): "
565 569 "failed to bind handle\n");
566 570 goto fail3;
567 571 }
568 572
569 573 if (dma_p->ncookies != 1) {
570 574 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rwd_alloc_dma_mem(): "
571 575 "failed to alloc cookies\n");
572 576 goto fail4;
573 577 }
574 578
575 579 dma_p->nslots = ~0U;
576 580 dma_p->size = ~0U;
577 581 dma_p->token = ~0U;
578 582 dma_p->offset = 0;
579 583 return (DDI_SUCCESS);
580 584
581 585 fail4:
582 586 (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
583 587 fail3:
584 588 ddi_dma_mem_free(&dma_p->acc_hdl);
585 589 fail2:
586 590 ddi_dma_free_handle(&dma_p->dma_hdl);
587 591 fail1:
588 592 return (err);
589 593 }
590 594
591 595 static void
592 596 rt2661_free_dma_mem(struct dma_area *dma_p)
593 597 {
594 598 if (dma_p->dma_hdl != NULL) {
595 599 (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
596 600 if (dma_p->acc_hdl != NULL) {
597 601 ddi_dma_mem_free(&dma_p->acc_hdl);
598 602 dma_p->acc_hdl = NULL;
599 603 }
600 604 ddi_dma_free_handle(&dma_p->dma_hdl);
601 605 dma_p->ncookies = 0;
602 606 dma_p->dma_hdl = NULL;
603 607 }
604 608 }
605 609
606 610 /*ARGSUSED*/
607 611 static int
608 612 rt2661_alloc_tx_ring(struct rt2661_softc *sc,
609 613 struct rt2661_tx_ring *ring, int count)
610 614 {
611 615 struct rt2661_tx_desc *desc;
612 616 struct rt2661_tx_data *data;
613 617 int i, err, size, len;
614 618
615 619 size = count * RT2661_TX_DESC_SIZE;
616 620 len = count * sizeof (struct rt2661_tx_data);
617 621
618 622 ring->count = count;
619 623 ring->queued = 0;
620 624 ring->cur = 0;
621 625 ring->next = 0;
622 626 ring->stat = 0;
623 627
624 628 err = rt2661_alloc_dma_mem(sc->sc_dev, &rt2661_dma_attr, size,
625 629 &rt2661_desc_accattr, DDI_DMA_CONSISTENT,
626 630 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
627 631 &ring->txdesc_dma);
628 632 if (err != DDI_SUCCESS) {
629 633 RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_alloc_tx_ring(): "
630 634 "failed to alloc dma mem\n");
631 635 goto fail1;
632 636 }
633 637
634 638 ring->desc = (struct rt2661_tx_desc *)ring->txdesc_dma.mem_va;
635 639 (void) bzero(ring->desc, size);
636 640 ring->paddr = ring->txdesc_dma.cookie.dmac_address;
637 641
638 642 ring->data = kmem_zalloc(len, KM_NOSLEEP);
639 643 if (ring->data == NULL) {
640 644 RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_alloc_tx_ring(): "
641 645 "failed to alloc tx buffer\n");
642 646 goto fail2;
643 647 }
644 648
645 649 for (i = 0; i < count; i++) {
646 650 desc = &ring->desc[i];
647 651 data = &ring->data[i];
648 652 err = rt2661_alloc_dma_mem(sc->sc_dev,
649 653 &rt2661_dma_attr, sc->sc_dmabuf_size,
650 654 &rt2661_buf_accattr, DDI_DMA_CONSISTENT,
651 655 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
652 656 &data->txdata_dma);
653 657 if (err != DDI_SUCCESS) {
654 658 RWD_DEBUG(RT2661_DBG_DMA,
655 659 "rwd: rt2661_alloc_tx_ring(): "
656 660 "failed to alloc tx buffer dma\n");
657 661 while (i >= 0) {
658 662 rt2661_free_dma_mem(&ring->data[i].txdata_dma);
659 663 i--;
660 664 }
661 665 goto fail3;
662 666 }
663 667 desc->addr[0] = data->txdata_dma.cookie.dmac_address;
664 668 data->buf = data->txdata_dma.mem_va;
665 669 data->paddr = data->txdata_dma.cookie.dmac_address;
666 670 }
667 671
668 672 (void) ddi_dma_sync(ring->txdesc_dma.dma_hdl,
669 673 0, size, DDI_DMA_SYNC_FORDEV);
670 674 return (DDI_SUCCESS);
671 675 fail3:
672 676 if (ring->data)
673 677 kmem_free(ring->data,
674 678 count * sizeof (struct rt2661_tx_data));
675 679 fail2:
676 680 rt2661_free_dma_mem(&ring->txdesc_dma);
677 681 fail1:
678 682 return (err);
679 683 }
680 684
681 685 static void
682 686 rt2661_reset_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
683 687 {
684 688 struct rt2661_tx_desc *desc;
685 689 struct rt2661_tx_data *data;
686 690 int i;
687 691
688 692 for (i = 0; i < ring->count; i++) {
689 693 desc = &ring->desc[i];
690 694 data = &ring->data[i];
691 695
692 696 if (data->ni != NULL) {
693 697 ieee80211_free_node(data->ni);
694 698 data->ni = NULL;
695 699 }
696 700
697 701 desc->flags = 0;
698 702 }
699 703
700 704 if (!RT2661_IS_FASTREBOOT(sc))
701 705 (void) ddi_dma_sync(ring->txdesc_dma.dma_hdl, 0,
702 706 ring->count * sizeof (struct rt2661_tx_desc),
703 707 DDI_DMA_SYNC_FORDEV);
704 708
705 709 ring->queued = 0;
706 710 ring->cur = ring->next = ring->stat = 0;
707 711 }
708 712
709 713
710 714 /*ARGSUSED*/
711 715 static void
712 716 rt2661_free_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
713 717 {
714 718 struct rt2661_tx_data *data;
715 719 int i;
716 720
717 721 if (ring->desc != NULL) {
718 722 rt2661_free_dma_mem(&ring->txdesc_dma);
719 723 }
720 724
721 725 if (ring->data != NULL) {
722 726 for (i = 0; i < ring->count; i++) {
723 727 data = &ring->data[i];
724 728 rt2661_free_dma_mem(&data->txdata_dma);
725 729 if (data->ni != NULL) {
726 730 ieee80211_free_node(data->ni);
727 731 data->ni = NULL;
728 732 }
729 733 }
730 734 kmem_free(ring->data,
731 735 ring->count * sizeof (struct rt2661_tx_data));
732 736 }
733 737 }
734 738
735 739 /*ARGSUSED*/
736 740 static int
737 741 rt2661_alloc_rx_ring(struct rt2661_softc *sc,
738 742 struct rt2661_rx_ring *ring, int count)
739 743 {
740 744 struct rt2661_rx_desc *desc;
741 745 struct rt2661_rx_data *data;
742 746 int i, err, len, size;
743 747
744 748 size = count * RT2661_RX_DESC_SIZE;
745 749 len = count * sizeof (struct rt2661_rx_data);
746 750
747 751 ring->count = count;
748 752 ring->cur = 0;
749 753 ring->next = 0;
750 754
751 755 err = rt2661_alloc_dma_mem(sc->sc_dev, &rt2661_dma_attr, size,
752 756 &rt2661_desc_accattr, DDI_DMA_CONSISTENT,
753 757 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
754 758 &ring->rxdesc_dma);
755 759 if (err != DDI_SUCCESS) {
756 760 RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_alloc_rx_ring(): "
757 761 "failed to alloc dma mem\n");
758 762 goto fail1;
759 763 }
760 764
761 765 ring->desc = (struct rt2661_rx_desc *)ring->rxdesc_dma.mem_va;
762 766 (void) bzero(ring->desc, size);
763 767 ring->paddr = ring->rxdesc_dma.cookie.dmac_address;
764 768
765 769 ring->data = kmem_zalloc(len, KM_NOSLEEP);
766 770 if (ring->data == NULL) {
767 771 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_alloc_rx_ring(): "
768 772 "failed to alloc rx buffer\n");
769 773 goto fail2;
770 774 }
771 775
772 776 for (i = 0; i < count; i++) {
773 777 desc = &ring->desc[i];
774 778 data = &ring->data[i];
775 779 err = rt2661_alloc_dma_mem(sc->sc_dev,
776 780 &rt2661_dma_attr, sc->sc_dmabuf_size,
777 781 &rt2661_buf_accattr, DDI_DMA_CONSISTENT,
778 782 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
779 783 &data->rxdata_dma);
780 784 if (err != DDI_SUCCESS) {
781 785 RWD_DEBUG(RT2661_DBG_DMA,
782 786 "rwd: rt2661_alloc_rx_ring(): "
783 787 "failed to alloc rx buffer dma\n");
784 788 while (i >= 0) {
785 789 rt2661_free_dma_mem(&ring->data[i].rxdata_dma);
786 790 i--;
787 791 }
788 792 goto fail3;
789 793 }
790 794 data->buf = data->rxdata_dma.mem_va;
791 795 data->paddr = data->rxdata_dma.cookie.dmac_address;
792 796 desc->flags = LE_32(RT2661_RX_BUSY);
793 797 desc->physaddr = LE_32(data->paddr);
794 798 }
795 799
796 800 (void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl,
797 801 0, size, DDI_DMA_SYNC_FORDEV);
798 802 return (DDI_SUCCESS);
799 803 fail3:
800 804 if (ring->data)
801 805 kmem_free(ring->data,
802 806 count * sizeof (struct rt2661_rx_data));
803 807 fail2:
804 808 rt2661_free_dma_mem(&ring->rxdesc_dma);
805 809 fail1:
806 810 return (err);
807 811 }
808 812
809 813 static void
810 814 rt2661_reset_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring)
811 815 {
812 816 int i;
813 817
814 818 for (i = 0; i < ring->count; i++)
815 819 ring->desc[i].flags = LE_32(RT2661_RX_BUSY);
816 820
817 821 if (!RT2661_IS_FASTREBOOT(sc))
818 822 (void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl, 0,
819 823 ring->count * sizeof (struct rt2661_rx_ring),
820 824 DDI_DMA_SYNC_FORKERNEL);
821 825
822 826 ring->cur = ring->next = 0;
823 827 }
824 828
825 829 /*ARGSUSED*/
826 830 static void
827 831 rt2661_free_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring)
828 832 {
829 833 struct rt2661_rx_data *data;
830 834 int i;
831 835
832 836 if (ring->desc != NULL) {
833 837 rt2661_free_dma_mem(&ring->rxdesc_dma);
834 838 }
835 839
836 840 if (ring->data != NULL) {
837 841 for (i = 0; i < ring->count; i++) {
838 842 data = &ring->data[i];
839 843 rt2661_free_dma_mem(&data->rxdata_dma);
840 844 }
841 845 kmem_free(ring->data,
842 846 ring->count * sizeof (struct rt2661_rx_data));
843 847 }
844 848 }
845 849
846 850 static void
847 851 rt2661_tx_dma_intr(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
848 852 {
849 853 struct rt2661_tx_desc *desc;
850 854 struct rt2661_tx_data *data;
851 855
852 856 for (;;) {
853 857 desc = &ring->desc[ring->next];
854 858 data = &ring->data[ring->next];
855 859
856 860 (void) ddi_dma_sync(ring->txdesc_dma.dma_hdl,
857 861 ring->next * RT2661_TX_DESC_SIZE,
858 862 RT2661_TX_DESC_SIZE,
859 863 DDI_DMA_SYNC_FORKERNEL);
860 864
861 865 if ((LE_32(desc->flags) & RT2661_TX_BUSY) ||
862 866 !(LE_32(desc->flags) & RT2661_TX_VALID))
863 867 break;
864 868
865 869 (void) ddi_dma_sync(data->txdata_dma.dma_hdl,
866 870 0, sc->sc_dmabuf_size,
867 871 DDI_DMA_SYNC_FORDEV);
868 872
869 873 /* descriptor is no longer valid */
870 874 desc->flags &= ~LE_32(RT2661_TX_VALID);
871 875
872 876 (void) ddi_dma_sync(ring->txdesc_dma.dma_hdl,
873 877 ring->next * RT2661_TX_DESC_SIZE,
874 878 RT2661_TX_DESC_SIZE,
875 879 DDI_DMA_SYNC_FORDEV);
876 880
877 881 RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_dma_intr(): "
878 882 "tx dma done q=%p idx=%u\n", ring, ring->next);
879 883
880 884 if (++ring->next >= ring->count) /* faster than % count */
881 885 ring->next = 0;
882 886 }
883 887 }
884 888
885 889 static void
886 890 rt2661_tx_intr(struct rt2661_softc *sc)
887 891 {
888 892 struct ieee80211com *ic = &sc->sc_ic;
889 893 struct rt2661_tx_ring *ring;
890 894 struct rt2661_tx_data *data;
891 895 struct rt2661_node *rn;
892 896
893 897 uint32_t val;
894 898 int qid, retrycnt;
895 899
896 900 for (;;) {
897 901 val = RT2661_READ(sc, RT2661_STA_CSR4);
898 902 if (!(val & RT2661_TX_STAT_VALID))
899 903 break;
900 904
901 905 /* retrieve the queue in which this frame was send */
902 906 qid = RT2661_TX_QID(val);
903 907 ring = (qid <= 3) ? &sc->txq[qid] : &sc->mgtq;
904 908
905 909 /* retrieve rate control algorithm context */
906 910 data = &ring->data[ring->stat];
907 911 rn = (struct rt2661_node *)data->ni;
908 912
909 913 /* if no frame has been sent, ignore */
910 914 if (rn == NULL) {
911 915 RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_intr(): "
912 916 "no frame has been send, ignore\n");
913 917 continue;
914 918 }
915 919
916 920 switch (RT2661_TX_RESULT(val)) {
917 921 case RT2661_TX_SUCCESS:
918 922 retrycnt = RT2661_TX_RETRYCNT(val);
919 923
920 924 RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_intr(): "
921 925 "data frame sent successfully after "
922 926 "%d retries\n", retrycnt);
923 927 rn->amn.amn_txcnt++;
924 928 if (retrycnt > 0) {
925 929 rn->amn.amn_retrycnt++;
926 930 sc->sc_tx_retries++;
927 931 }
928 932 break;
929 933 case RT2661_TX_RETRY_FAIL:
930 934 RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_intr(): "
931 935 "sending data frame failed (too much retries)\n");
932 936 rn->amn.amn_txcnt++;
933 937 rn->amn.amn_retrycnt++;
934 938 break;
935 939 default:
936 940 /* other failure */
937 941 RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_intr():"
938 942 "sending data frame failed 0x%08x\n", val);
939 943 }
940 944
941 945 RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_intr(): "
942 946 "tx done q=%d idx=%u\n", qid, ring->stat);
943 947
944 948 ieee80211_free_node(data->ni);
945 949 data->ni = NULL;
946 950
947 951 ring->queued--;
948 952
949 953 /* faster than % count */
950 954 if (++ring->stat >= ring->count)
951 955 ring->stat = 0;
952 956
953 957 if (sc->sc_need_sched) {
954 958 sc->sc_need_sched = 0;
955 959 mac_tx_update(ic->ic_mach);
956 960 }
957 961 }
958 962 sc->sc_tx_timer = 0;
959 963 }
960 964
961 965 static void
962 966 rt2661_rx_intr(struct rt2661_softc *sc)
963 967 {
964 968 struct ieee80211com *ic = &sc->sc_ic;
965 969 struct rt2661_rx_ring *ring;
966 970 struct rt2661_rx_desc *desc;
967 971 struct rt2661_rx_data *data;
968 972 struct ieee80211_frame *wh;
969 973 struct ieee80211_node *ni;
970 974
971 975 mblk_t *m;
972 976 uint8_t *rxbuf;
973 977 uint32_t pktlen;
974 978
975 979 mutex_enter(&sc->sc_rxlock);
976 980 ring = &sc->rxq;
977 981
978 982 for (;;) {
979 983 int rssi;
980 984
981 985 desc = &ring->desc[ring->cur];
982 986 data = &ring->data[ring->cur];
983 987
984 988 (void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl,
985 989 ring->cur * RT2661_RX_DESC_SIZE,
986 990 RT2661_RX_DESC_SIZE,
987 991 DDI_DMA_SYNC_FORKERNEL);
988 992
989 993
990 994 if (LE_32(desc->flags) & RT2661_RX_BUSY)
991 995 break;
992 996
993 997 if ((LE_32(desc->flags) & RT2661_RX_PHY_ERROR) ||
994 998 (LE_32(desc->flags) & RT2661_RX_CRC_ERROR)) {
995 999 /*
996 1000 * This should not happen since we did not request
997 1001 * to receive those frames when we filled TXRX_CSR0.
998 1002 */
999 1003 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_rx_intr(): "
1000 1004 "PHY or CRC error flags 0x%08x\n",
1001 1005 LE_32(desc->flags));
1002 1006 sc->sc_rx_err++;
1003 1007 goto skip;
1004 1008 }
1005 1009
1006 1010 if ((LE_32(desc->flags) & RT2661_RX_CIPHER_MASK) != 0) {
1007 1011 sc->sc_rx_err++;
1008 1012 goto skip;
1009 1013 }
1010 1014
1011 1015 (void) ddi_dma_sync(data->rxdata_dma.dma_hdl,
1012 1016 0, sc->sc_dmabuf_size,
1013 1017 DDI_DMA_SYNC_FORCPU);
1014 1018
1015 1019 rxbuf = (uint8_t *)data->rxdata_dma.mem_va;
1016 1020 desc->physaddr = LE_32(data->rxdata_dma.cookie.dmac_address);
1017 1021 pktlen = (LE_32(desc->flags) >> 16) & 0xfff;
1018 1022 if ((pktlen < sizeof (struct ieee80211_frame_min)) ||
1019 1023 (pktlen > sc->sc_dmabuf_size)) {
1020 1024 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_rx_intr(): "
1021 1025 "bad fram length=%u\n", pktlen);
1022 1026 sc->sc_rx_err++;
1023 1027 goto skip;
1024 1028 }
1025 1029
1026 1030 if ((m = allocb(pktlen, BPRI_MED)) == NULL) {
1027 1031 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_rx_intr(): "
1028 1032 "allocate mblk failed.\n");
1029 1033 sc->sc_rx_nobuf++;
1030 1034 goto skip;
1031 1035 }
1032 1036
1033 1037 bcopy(rxbuf, m->b_rptr, pktlen);
1034 1038 m->b_wptr += pktlen;
1035 1039
1036 1040 wh = (struct ieee80211_frame *)m->b_rptr;
1037 1041 ni = ieee80211_find_rxnode(ic, wh);
1038 1042
1039 1043 rssi = rt2661_get_rssi(sc, desc->rssi);
1040 1044 /* send the frame to the 802.11 layer */
1041 1045 (void) ieee80211_input(ic, m, ni, rssi + 95, 0);
1042 1046
1043 1047 sc->avg_rssi = (rssi + 7 * sc->avg_rssi) / 8;
1044 1048
1045 1049 /* node is no longer needed */
1046 1050 ieee80211_free_node(ni);
1047 1051 skip:
1048 1052 desc->flags |= LE_32(RT2661_RX_BUSY);
1049 1053
1050 1054 (void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl,
1051 1055 ring->cur * RT2661_RX_DESC_SIZE,
1052 1056 RT2661_RX_DESC_SIZE,
1053 1057 DDI_DMA_SYNC_FORDEV);
1054 1058
1055 1059 RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_rx_intr(): "
1056 1060 "rx intr idx=%u\n", sc->rxq.cur);
1057 1061 ring->cur = (ring->cur + 1) % RT2661_RX_RING_COUNT;
1058 1062 }
1059 1063 mutex_exit(&sc->sc_rxlock);
1060 1064 }
1061 1065
1062 1066 /*ARGSUSED*/
1063 1067 static uint_t
1064 1068 rt2661_softintr(caddr_t data, caddr_t unused)
1065 1069 {
1066 1070 struct rt2661_softc *sc = (struct rt2661_softc *)data;
1067 1071
1068 1072 if (sc->sc_rx_pend) {
1069 1073 sc->sc_rx_pend = 0;
1070 1074 rt2661_rx_intr(sc);
1071 1075 return (DDI_INTR_CLAIMED);
1072 1076 }
1073 1077 return (DDI_INTR_UNCLAIMED);
1074 1078 }
1075 1079
1076 1080 static int
1077 1081 rt2661_tx_cmd(struct rt2661_softc *sc, uint8_t cmd, uint16_t arg)
1078 1082 {
1079 1083 if (RT2661_READ(sc, RT2661_H2M_MAILBOX_CSR) & RT2661_H2M_BUSY)
1080 1084 return (EIO); /* there is already a command pending */
1081 1085
1082 1086 RT2661_WRITE(sc, RT2661_H2M_MAILBOX_CSR,
1083 1087 RT2661_H2M_BUSY | RT2661_TOKEN_NO_INTR << 16 | arg);
1084 1088
1085 1089 RT2661_WRITE(sc, RT2661_HOST_CMD_CSR, RT2661_KICK_CMD | cmd);
1086 1090
1087 1091 return (0);
1088 1092 }
1089 1093
1090 1094 static void
1091 1095 rt2661_mcu_wakeup(struct rt2661_softc *sc)
1092 1096 {
1093 1097 RT2661_WRITE(sc, RT2661_MAC_CSR11, 5 << 16);
1094 1098
1095 1099 RT2661_WRITE(sc, RT2661_SOFT_RESET_CSR, 0x7);
1096 1100 RT2661_WRITE(sc, RT2661_IO_CNTL_CSR, 0x18);
1097 1101 RT2661_WRITE(sc, RT2661_PCI_USEC_CSR, 0x20);
1098 1102
1099 1103 /* send wakeup command to MCU */
1100 1104 (void) rt2661_tx_cmd(sc, RT2661_MCU_CMD_WAKEUP, 0);
1101 1105 }
1102 1106
1103 1107 static void
1104 1108 rt2661_mcu_cmd_intr(struct rt2661_softc *sc)
1105 1109 {
1106 1110 (void) RT2661_READ(sc, RT2661_M2H_CMD_DONE_CSR);
1107 1111 RT2661_WRITE(sc, RT2661_M2H_CMD_DONE_CSR, 0xffffffff);
1108 1112 }
1109 1113
1110 1114 /*ARGSUSED*/
1111 1115 static uint_t
1112 1116 rt2661_intr(caddr_t arg, caddr_t unused)
1113 1117 {
1114 1118 struct rt2661_softc *sc = (struct rt2661_softc *)arg;
1115 1119 uint32_t r1, r2;
1116 1120
1117 1121 RT2661_GLOCK(sc);
1118 1122
1119 1123 if (!RT2661_IS_RUNNING(sc) || RT2661_IS_SUSPEND(sc)) {
1120 1124 RT2661_GUNLOCK(sc);
1121 1125 return (DDI_INTR_UNCLAIMED);
1122 1126 }
1123 1127
1124 1128 r1 = RT2661_READ(sc, RT2661_INT_SOURCE_CSR);
1125 1129 r2 = RT2661_READ(sc, RT2661_MCU_INT_SOURCE_CSR);
1126 1130 if (r1 == 0 && r2 == 0) {
1127 1131 RT2661_GUNLOCK(sc);
1128 1132 return (DDI_INTR_UNCLAIMED); /* not for us */
1129 1133 }
1130 1134
1131 1135 /* disable MAC and MCU interrupts */
1132 1136 RT2661_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f);
1133 1137 RT2661_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff);
1134 1138
1135 1139 /* acknowledge interrupts */
1136 1140 RT2661_WRITE(sc, RT2661_INT_SOURCE_CSR, r1);
1137 1141 RT2661_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, r2);
1138 1142
1139 1143 if (r1 & RT2661_MGT_DONE) {
1140 1144 RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
1141 1145 "RT2661_MGT_DONE\n");
1142 1146 rt2661_tx_dma_intr(sc, &sc->mgtq);
1143 1147 }
1144 1148
1145 1149 if (r1 & RT2661_RX_DONE) {
1146 1150 RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
1147 1151 "RT2661_RX_DONE\n");
1148 1152 sc->sc_rx_pend = 1;
1149 1153 (void) ddi_intr_trigger_softint(sc->sc_softintr_hdl, NULL);
1150 1154 }
1151 1155
1152 1156 if (r1 & RT2661_TX0_DMA_DONE) {
1153 1157 RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
1154 1158 "RT2661_TX0_DMA_DONE\n");
1155 1159 rt2661_tx_dma_intr(sc, &sc->txq[0]);
1156 1160 }
1157 1161
1158 1162 if (r1 & RT2661_TX1_DMA_DONE) {
1159 1163 RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
1160 1164 "RT2661_TX1_DMA_DONE\n");
1161 1165 rt2661_tx_dma_intr(sc, &sc->txq[1]);
1162 1166 }
1163 1167
1164 1168 if (r1 & RT2661_TX2_DMA_DONE) {
1165 1169 RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
1166 1170 "RT2661_TX2_DMA_DONE\n");
1167 1171 rt2661_tx_dma_intr(sc, &sc->txq[2]);
1168 1172 }
1169 1173
1170 1174 if (r1 & RT2661_TX3_DMA_DONE) {
1171 1175 RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
1172 1176 "RT2661_TX3_DMA_DONE\n");
1173 1177 rt2661_tx_dma_intr(sc, &sc->txq[3]);
1174 1178 }
1175 1179
1176 1180 if (r1 & RT2661_TX_DONE) {
1177 1181 RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
1178 1182 "RT2661_TX_DONE\n");
1179 1183 rt2661_tx_intr(sc);
1180 1184 }
1181 1185
1182 1186 if (r2 & RT2661_MCU_CMD_DONE) {
1183 1187 RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
1184 1188 "RT2661_MCU_CMD_DONE\n");
1185 1189 rt2661_mcu_cmd_intr(sc);
1186 1190 }
1187 1191
1188 1192 if (r2 & RT2661_MCU_WAKEUP) {
1189 1193 RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
1190 1194 "RT2661_MCU_WAKEUP\n");
1191 1195 rt2661_mcu_wakeup(sc);
1192 1196 }
1193 1197
1194 1198 /* re-enable MAC and MCU interrupts */
1195 1199 RT2661_WRITE(sc, RT2661_INT_MASK_CSR, 0x0000ff10);
1196 1200 RT2661_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0);
1197 1201
1198 1202 RT2661_GUNLOCK(sc);
1199 1203 return (RT2661_SUCCESS);
1200 1204 }
1201 1205
1202 1206 /*
1203 1207 * Retrieve the "Received Signal Strength Indicator" from the raw values
1204 1208 * contained in Rx descriptors. The computation depends on which band the
1205 1209 * frame was received. Correction values taken from the reference driver.
1206 1210 */
1207 1211 static int
1208 1212 rt2661_get_rssi(struct rt2661_softc *sc, uint8_t raw)
1209 1213 {
1210 1214 int lna, agc, rssi;
1211 1215
1212 1216 lna = (raw >> 5) & 0x3;
1213 1217 agc = raw & 0x1f;
1214 1218
1215 1219 rssi = 2 * agc;
1216 1220
1217 1221 if (IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan)) {
1218 1222 rssi += sc->rssi_2ghz_corr;
1219 1223
1220 1224 if (lna == 1)
1221 1225 rssi -= 64;
1222 1226 else if (lna == 2)
1223 1227 rssi -= 74;
1224 1228 else if (lna == 3)
1225 1229 rssi -= 90;
1226 1230 } else {
1227 1231 rssi += sc->rssi_5ghz_corr;
1228 1232
1229 1233 if (lna == 1)
1230 1234 rssi -= 64;
1231 1235 else if (lna == 2)
1232 1236 rssi -= 86;
1233 1237 else if (lna == 3)
1234 1238 rssi -= 100;
1235 1239 }
1236 1240 return (rssi);
1237 1241 }
1238 1242
1239 1243 /* quickly determine if a given rate is CCK or OFDM */
1240 1244 #define RT2661_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)
1241 1245
1242 1246 #define RT2661_ACK_SIZE 14 /* 10 + 4(FCS) */
1243 1247 #define RT2661_CTS_SIZE 14 /* 10 + 4(FCS) */
1244 1248
1245 1249 #define RT2661_SIFS 10 /* us */
1246 1250
1247 1251 /*
1248 1252 * Return the expected ack rate for a frame transmitted at rate `rate'.
1249 1253 * XXX: this should depend on the destination node basic rate set.
1250 1254 */
1251 1255 static int
1252 1256 rt2661_ack_rate(struct ieee80211com *ic, int rate)
1253 1257 {
1254 1258 switch (rate) {
1255 1259 /* CCK rates */
1256 1260 case 2:
1257 1261 return (2);
1258 1262 case 4:
1259 1263 case 11:
1260 1264 case 22:
1261 1265 return ((ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate);
1262 1266
1263 1267 /* OFDM rates */
1264 1268 case 12:
1265 1269 case 18:
1266 1270 return (12);
1267 1271 case 24:
1268 1272 case 36:
1269 1273 return (24);
1270 1274 case 48:
1271 1275 case 72:
1272 1276 case 96:
1273 1277 case 108:
1274 1278 return (48);
1275 1279 }
1276 1280
1277 1281 /* default to 1Mbps */
1278 1282 return (2);
1279 1283 }
1280 1284
1281 1285 /*
1282 1286 * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
1283 1287 * The function automatically determines the operating mode depending on the
1284 1288 * given rate. `flags' indicates whether short preamble is in use or not.
1285 1289 */
1286 1290 static uint16_t
1287 1291 rt2661_txtime(int len, int rate, uint32_t flags)
1288 1292 {
1289 1293 uint16_t txtime;
1290 1294
1291 1295 if (RT2661_RATE_IS_OFDM(rate)) {
1292 1296 /* IEEE Std 802.11a-1999, pp. 37 */
1293 1297 txtime = (8 + 4 * len + 3 + rate - 1) / rate;
1294 1298 txtime = 16 + 4 + 4 * txtime + 6;
1295 1299 } else {
1296 1300 /* IEEE Std 802.11b-1999, pp. 28 */
1297 1301 txtime = (16 * len + rate - 1) / rate;
1298 1302 if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE))
1299 1303 txtime += 72 + 24;
1300 1304 else
1301 1305 txtime += 144 + 48;
1302 1306 }
1303 1307
1304 1308 return (txtime);
1305 1309 }
1306 1310
1307 1311 static uint8_t
1308 1312 rt2661_plcp_signal(int rate)
1309 1313 {
1310 1314 switch (rate) {
1311 1315 /* CCK rates (returned values are device-dependent) */
1312 1316 case 2:
1313 1317 return (0x0);
1314 1318 case 4:
1315 1319 return (0x1);
1316 1320 case 11:
1317 1321 return (0x2);
1318 1322 case 22:
1319 1323 return (0x3);
1320 1324
1321 1325 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
1322 1326 case 12:
1323 1327 return (0xb);
1324 1328 case 18:
1325 1329 return (0xf);
1326 1330 case 24:
1327 1331 return (0xa);
1328 1332 case 36:
1329 1333 return (0xe);
1330 1334 case 48:
1331 1335 return (0x9);
1332 1336 case 72:
1333 1337 return (0xd);
1334 1338 case 96:
1335 1339 return (0x8);
1336 1340 case 108:
1337 1341 return (0xc);
1338 1342
1339 1343 /* unsupported rates (should not get there) */
1340 1344 default:
1341 1345 return (0xff);
1342 1346 }
1343 1347 }
1344 1348
1345 1349 static void
1346 1350 rt2661_setup_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_desc *desc,
1347 1351 uint32_t flags, uint16_t xflags, int len, int rate, int ac)
1348 1352 {
1349 1353 struct ieee80211com *ic = &sc->sc_ic;
1350 1354 uint16_t plcp_length;
1351 1355 int remainder;
1352 1356
1353 1357 desc->flags = LE_32(flags);
1354 1358 desc->flags |= LE_32(len << 16);
1355 1359 desc->flags |= LE_32(RT2661_TX_BUSY | RT2661_TX_VALID);
1356 1360
1357 1361 desc->xflags = LE_16(xflags);
1358 1362 desc->xflags |= LE_16(1 << 13);
1359 1363
1360 1364 desc->wme = LE_16(
1361 1365 RT2661_QID(ac) |
1362 1366 RT2661_AIFSN(2) |
1363 1367 RT2661_LOGCWMIN(4) |
1364 1368 RT2661_LOGCWMAX(10));
1365 1369
1366 1370 /*
1367 1371 * Remember in which queue this frame was sent. This field is driver
1368 1372 * private data only. It will be made available by the NIC in STA_CSR4
1369 1373 * on Tx interrupts.
1370 1374 */
1371 1375 desc->qid = (uint8_t)ac;
1372 1376
1373 1377 /* setup PLCP fields */
1374 1378 desc->plcp_signal = rt2661_plcp_signal(rate);
1375 1379 desc->plcp_service = 4;
1376 1380
1377 1381 len += IEEE80211_CRC_LEN;
1378 1382
1379 1383 if (RT2661_RATE_IS_OFDM(rate)) {
1380 1384 desc->flags |= LE_32(RT2661_TX_OFDM);
1381 1385
1382 1386 plcp_length = len & 0xfff;
1383 1387 desc->plcp_length_hi = plcp_length >> 6;
1384 1388 desc->plcp_length_lo = plcp_length & 0x3f;
1385 1389 } else {
1386 1390 plcp_length = (16 * len + rate - 1) / rate;
1387 1391 if (rate == 22) {
1388 1392 remainder = (16 * len) % 22;
1389 1393 if (remainder != 0 && remainder < 7)
1390 1394 desc->plcp_service |= RT2661_PLCP_LENGEXT;
1391 1395 }
1392 1396 desc->plcp_length_hi = plcp_length >> 8;
1393 1397 desc->plcp_length_lo = plcp_length & 0xff;
1394 1398
1395 1399 if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
1396 1400 desc->plcp_signal |= 0x08;
1397 1401 }
1398 1402
1399 1403 /* RT2x61 supports scatter with up to 5 segments */
1400 1404 desc->len [0] = LE_16(len);
1401 1405 }
1402 1406
1403 1407 static int
1404 1408 rt2661_send(ieee80211com_t *ic, mblk_t *mp)
1405 1409 {
1406 1410 struct rt2661_softc *sc = (struct rt2661_softc *)ic;
1407 1411 struct rt2661_tx_ring *ring;
1408 1412 struct rt2661_tx_desc *desc;
1409 1413 struct rt2661_tx_data *data;
1410 1414 struct ieee80211_frame *wh;
1411 1415 struct ieee80211_node *ni;
1412 1416
1413 1417 int err, off, rate;
1414 1418 int mblen, pktlen;
1415 1419 mblk_t *m, *m0;
1416 1420 uint16_t dur;
1417 1421 uint32_t flags = 0;
1418 1422
1419 1423 mutex_enter(&sc->sc_txlock);
1420 1424 ring = &sc->txq[0];
1421 1425 err = DDI_SUCCESS;
1422 1426
1423 1427 if (ring->queued > RT2661_TX_RING_COUNT - 8) {
1424 1428 sc->sc_need_sched = 1;
1425 1429 sc->sc_tx_nobuf++;
1426 1430 err = ENOMEM;
1427 1431 goto fail1;
1428 1432 }
1429 1433
1430 1434 m = allocb(msgdsize(mp) + 32, BPRI_MED);
1431 1435 if (m == NULL) {
1432 1436 RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_send():"
1433 1437 "can't alloc mblk.\n");
1434 1438 err = DDI_FAILURE;
1435 1439 goto fail1;
1436 1440 }
1437 1441
1438 1442 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
1439 1443 mblen = MBLKL(m0);
1440 1444 (void) bcopy(m0->b_rptr, m->b_rptr + off, mblen);
1441 1445 off += mblen;
1442 1446 }
1443 1447 m->b_wptr += off;
1444 1448
1445 1449 wh = (struct ieee80211_frame *)m->b_rptr;
1446 1450 ni = ieee80211_find_txnode(ic, wh->i_addr1);
1447 1451 if (ni == NULL) {
1448 1452 err = DDI_FAILURE;
1449 1453 sc->sc_tx_err++;
1450 1454 goto fail2;
1451 1455 }
1452 1456
1453 1457 (void) ieee80211_encap(ic, m, ni);
1454 1458
1455 1459 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1456 1460 struct ieee80211_key *k;
1457 1461 k = ieee80211_crypto_encap(ic, m);
1458 1462 if (k == NULL) {
1459 1463 sc->sc_tx_err++;
1460 1464 err = DDI_FAILURE;
1461 1465 goto fail3;
1462 1466 }
1463 1467 /* packet header may have moved, reset our local pointer */
1464 1468 wh = (struct ieee80211_frame *)m->b_rptr;
1465 1469 }
1466 1470
1467 1471 pktlen = msgdsize(m);
1468 1472
1469 1473 desc = &ring->desc[ring->cur];
1470 1474 data = &ring->data[ring->cur];
1471 1475 data->ni = ieee80211_ref_node(ni);
1472 1476
1473 1477 /* pickup a rate */
1474 1478 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1475 1479 /* multicast frames are sent at the lowest avail. rate */
1476 1480 rate = ni->in_rates.ir_rates[0];
1477 1481 } else if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
1478 1482 rate = ic->ic_sup_rates[ic->ic_curmode].
1479 1483 ir_rates[ic->ic_fixed_rate];
1480 1484 } else
1481 1485 rate = ni->in_rates.ir_rates[ni->in_txrate];
1482 1486 if (rate == 0)
1483 1487 rate = 2; /* XXX should not happen */
1484 1488 rate &= IEEE80211_RATE_VAL;
1485 1489
1486 1490 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1487 1491 flags |= RT2661_TX_NEED_ACK;
1488 1492
1489 1493 dur = rt2661_txtime(RT2661_ACK_SIZE,
1490 1494 rt2661_ack_rate(ic, rate), ic->ic_flags) + sc->sifs;
1491 1495 *(uint16_t *)wh->i_dur = LE_16(dur);
1492 1496 }
1493 1497
1494 1498 bcopy(m->b_rptr, data->buf, pktlen);
1495 1499 rt2661_setup_tx_desc(sc, desc, flags, 0, pktlen, rate, 0);
1496 1500
1497 1501 (void) ddi_dma_sync(data->txdata_dma.dma_hdl,
1498 1502 0, pktlen,
1499 1503 DDI_DMA_SYNC_FORDEV);
1500 1504
1501 1505 (void) ddi_dma_sync(ring->txdesc_dma.dma_hdl,
1502 1506 ring->cur * RT2661_TX_DESC_SIZE,
1503 1507 RT2661_TX_DESC_SIZE,
1504 1508 DDI_DMA_SYNC_FORDEV);
1505 1509
1506 1510 RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_send(): "
1507 1511 "sending data frame len=%u idx=%u rate=%u\n",
1508 1512 pktlen, ring->cur, rate);
1509 1513
1510 1514 /* kick Tx */
1511 1515 ring->queued++;
1512 1516 ring->cur = (ring->cur + 1) % RT2661_TX_RING_COUNT;
1513 1517 RT2661_WRITE(sc, RT2661_TX_CNTL_CSR, 1 << 0);
1514 1518
1515 1519 ic->ic_stats.is_tx_frags++;
1516 1520 ic->ic_stats.is_tx_bytes += pktlen;
1517 1521 fail3:
1518 1522 ieee80211_free_node(ni);
1519 1523 fail2:
1520 1524 freemsg(m);
1521 1525 fail1:
1522 1526 if (err == DDI_SUCCESS)
1523 1527 freemsg(mp);
1524 1528 mutex_exit(&sc->sc_txlock);
1525 1529 return (err);
1526 1530 }
1527 1531
1528 1532 /*ARGSUSED*/
1529 1533 static int
1530 1534 rt2661_mgmt_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
1531 1535 {
1532 1536 struct rt2661_softc *sc = (struct rt2661_softc *)ic;
1533 1537 struct rt2661_tx_ring *ring;
1534 1538 struct rt2661_tx_desc *desc;
1535 1539 struct rt2661_tx_data *data;
1536 1540 struct ieee80211_frame *wh;
1537 1541 struct ieee80211_node *ni;
1538 1542
1539 1543 int err, off, rate;
1540 1544 int mblen, pktlen;
1541 1545 mblk_t *m, *m0;
1542 1546 uint16_t dur;
1543 1547 uint32_t flags = 0;
1544 1548
1545 1549 if ((!RT2661_IS_RUNNING(sc)) || RT2661_IS_SUSPEND(sc)) {
1546 1550 err = ENXIO;
1547 1551 goto fail1;
1548 1552 }
1549 1553
1550 1554 ring = &sc->mgtq;
1551 1555 err = DDI_SUCCESS;
1552 1556
1553 1557 if (ring->queued >= RT2661_MGT_RING_COUNT) {
1554 1558 sc->sc_tx_nobuf++;
1555 1559 err = ENOMEM;
1556 1560 goto fail1;
1557 1561 }
1558 1562
1559 1563 m = allocb(msgdsize(mp) + 32, BPRI_MED);
1560 1564 if (m == NULL) {
1561 1565 RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_mgmt_send():"
1562 1566 "can't alloc mblk.\n");
1563 1567 err = DDI_FAILURE;
1564 1568 goto fail1;
1565 1569 }
1566 1570
1567 1571 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
1568 1572 mblen = MBLKL(m0);
1569 1573 (void) bcopy(m0->b_rptr, m->b_rptr + off, mblen);
1570 1574 off += mblen;
1571 1575 }
1572 1576 m->b_wptr += off;
1573 1577
1574 1578 wh = (struct ieee80211_frame *)m->b_rptr;
1575 1579 ni = ieee80211_find_txnode(ic, wh->i_addr1);
1576 1580 if (ni == NULL) {
1577 1581 err = DDI_FAILURE;
1578 1582 sc->sc_tx_err++;
1579 1583 goto fail2;
1580 1584 }
1581 1585
1582 1586 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1583 1587 struct ieee80211_key *k;
1584 1588 k = ieee80211_crypto_encap(ic, m);
1585 1589 if (k == NULL) {
1586 1590 sc->sc_tx_err++;
1587 1591 err = DDI_FAILURE;
1588 1592 goto fail3;
1589 1593 }
1590 1594 /* packet header may have moved, reset our local pointer */
1591 1595 wh = (struct ieee80211_frame *)m->b_rptr;
1592 1596 }
1593 1597
1594 1598 pktlen = msgdsize(m);
1595 1599
1596 1600 desc = &ring->desc[ring->cur];
1597 1601 data = &ring->data[ring->cur];
1598 1602 data->ni = ieee80211_ref_node(ni);
1599 1603
1600 1604 /* send mgt frames at the lowest available rate */
1601 1605 rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2;
1602 1606
1603 1607 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1604 1608 flags |= RT2661_TX_NEED_ACK;
1605 1609
1606 1610 dur = rt2661_txtime(RT2661_ACK_SIZE,
1607 1611 rate, ic->ic_flags) + sc->sifs;
1608 1612 *(uint16_t *)wh->i_dur = LE_16(dur);
1609 1613
1610 1614 /* tell hardware to add timestamp in probe responses */
1611 1615 if ((wh->i_fc[0] &
1612 1616 (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
1613 1617 (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP))
1614 1618 flags |= RT2661_TX_TIMESTAMP;
1615 1619 }
1616 1620
1617 1621 bcopy(m->b_rptr, data->buf, pktlen);
1618 1622 rt2661_setup_tx_desc(sc, desc, flags, 0, pktlen, rate, RT2661_QID_MGT);
1619 1623
1620 1624 (void) ddi_dma_sync(data->txdata_dma.dma_hdl,
1621 1625 0, pktlen,
1622 1626 DDI_DMA_SYNC_FORDEV);
1623 1627
1624 1628 (void) ddi_dma_sync(ring->txdesc_dma.dma_hdl,
1625 1629 ring->cur * RT2661_TX_DESC_SIZE,
1626 1630 RT2661_TX_DESC_SIZE,
1627 1631 DDI_DMA_SYNC_FORDEV);
1628 1632
1629 1633 RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_mgmt_send(): "
1630 1634 "sending mgmt frame len=%u idx=%u rate=%u\n",
1631 1635 pktlen, ring->cur, rate);
1632 1636
1633 1637 /* kick Tx */
1634 1638 ring->queued++;
1635 1639 ring->cur = (ring->cur + 1) % RT2661_MGT_RING_COUNT;
1636 1640 RT2661_WRITE(sc, RT2661_TX_CNTL_CSR, RT2661_KICK_MGT);
1637 1641
1638 1642 ic->ic_stats.is_tx_frags++;
1639 1643 ic->ic_stats.is_tx_bytes += pktlen;
1640 1644
1641 1645 fail3:
1642 1646 ieee80211_free_node(ni);
1643 1647 fail2:
1644 1648 freemsg(m);
1645 1649 fail1:
1646 1650 freemsg(mp);
1647 1651 return (err);
1648 1652 }
1649 1653
1650 1654 static void
1651 1655 rt2661_amrr_node_init(const struct rt2661_amrr *amrr,
1652 1656 struct rt2661_amrr_node *amn)
1653 1657 {
1654 1658 amn->amn_success = 0;
1655 1659 amn->amn_recovery = 0;
1656 1660 amn->amn_txcnt = amn->amn_retrycnt = 0;
1657 1661 amn->amn_success_threshold = amrr->amrr_min_success_threshold;
1658 1662 }
1659 1663
1660 1664 static void
1661 1665 rt2661_amrr_choose(struct rt2661_amrr *amrr, struct ieee80211_node *ni,
1662 1666 struct rt2661_amrr_node *amn)
1663 1667 {
1664 1668 #define RV(rate) ((rate) & IEEE80211_RATE_VAL)
1665 1669 #define is_success(amn) \
1666 1670 ((amn)->amn_retrycnt < (amn)->amn_txcnt / 10)
1667 1671 #define is_failure(amn) \
1668 1672 ((amn)->amn_retrycnt > (amn)->amn_txcnt / 3)
1669 1673 #define is_enough(amn) \
1670 1674 ((amn)->amn_txcnt > 10)
1671 1675 #define is_min_rate(ni) \
1672 1676 ((ni)->in_txrate == 0)
1673 1677 #define is_max_rate(ni) \
1674 1678 ((ni)->in_txrate == (ni)->in_rates.ir_nrates - 1)
1675 1679 #define increase_rate(ni) \
1676 1680 ((ni)->in_txrate++)
1677 1681 #define decrease_rate(ni) \
1678 1682 ((ni)->in_txrate--)
1679 1683 #define reset_cnt(amn) \
1680 1684 { (amn)->amn_txcnt = (amn)->amn_retrycnt = 0; }
1681 1685
1682 1686 int need_change = 0;
1683 1687
1684 1688 if (is_success(amn) && is_enough(amn)) {
1685 1689 amn->amn_success++;
1686 1690 if (amn->amn_success >= amn->amn_success_threshold &&
1687 1691 !is_max_rate(ni)) {
1688 1692 amn->amn_recovery = 1;
1689 1693 amn->amn_success = 0;
1690 1694 increase_rate(ni);
1691 1695 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_amrr_choose(): "
1692 1696 "increase rate = %d, #tx = %d, #retries = %d\n",
1693 1697 RV(ni->in_rates.ir_rates[ni->in_txrate]),
1694 1698 amn->amn_txcnt, amn->amn_retrycnt);
1695 1699 need_change = 1;
1696 1700 } else
1697 1701 amn->amn_recovery = 0;
1698 1702 } else if (is_failure(amn)) {
1699 1703 amn->amn_success = 0;
1700 1704 if (!is_min_rate(ni)) {
1701 1705 if (amn->amn_recovery) {
1702 1706 amn->amn_success_threshold *= 2;
1703 1707 if (amn->amn_success_threshold >
1704 1708 amrr->amrr_max_success_threshold)
1705 1709 amn->amn_success_threshold =
1706 1710 amrr->amrr_max_success_threshold;
1707 1711 } else {
1708 1712 amn->amn_success_threshold =
1709 1713 amrr->amrr_min_success_threshold;
1710 1714 }
1711 1715 decrease_rate(ni);
1712 1716 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_amrr_choose(): "
1713 1717 "decrease rate = %d, #tx = %d, #retries = %d\n",
1714 1718 RV(ni->in_rates.ir_rates[ni->in_txrate]),
1715 1719 amn->amn_txcnt, amn->amn_retrycnt);
1716 1720 need_change = 1;
1717 1721 }
1718 1722 amn->amn_recovery = 0;
1719 1723 }
1720 1724
1721 1725 if (is_enough(amn) || need_change)
1722 1726 reset_cnt(amn);
1723 1727 #undef RV
1724 1728
1725 1729 }
1726 1730
1727 1731 static void
1728 1732 rt2661_update_promisc(struct rt2661_softc *sc)
1729 1733 {
1730 1734 uint32_t tmp;
1731 1735
1732 1736 tmp = RT2661_READ(sc, RT2661_TXRX_CSR0);
1733 1737
1734 1738 tmp &= ~RT2661_DROP_NOT_TO_ME;
1735 1739 if (!(sc->sc_rcr & RT2661_RCR_PROMISC))
1736 1740 tmp |= RT2661_DROP_NOT_TO_ME;
1737 1741
1738 1742 RT2661_WRITE(sc, RT2661_TXRX_CSR0, tmp);
1739 1743 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_update_promisc(): "
1740 1744 "%s promiscuous mode\n",
1741 1745 (sc->sc_rcr & RT2661_RCR_PROMISC) ? "entering" : "leaving");
1742 1746 }
1743 1747
1744 1748 static void
1745 1749 rt2661_updateslot(struct ieee80211com *ic, int onoff)
1746 1750 {
1747 1751 struct rt2661_softc *sc = (struct rt2661_softc *)ic;
1748 1752 uint8_t slottime;
1749 1753 uint32_t tmp;
1750 1754
1751 1755 slottime = (onoff ? 9 : 20);
1752 1756
1753 1757 tmp = RT2661_READ(sc, RT2661_MAC_CSR9);
1754 1758 tmp = (tmp & ~0xff) | slottime;
1755 1759 RT2661_WRITE(sc, RT2661_MAC_CSR9, tmp);
1756 1760
1757 1761 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_updateslot(): "
1758 1762 "setting slot time to %uus\n", slottime);
1759 1763 }
1760 1764
1761 1765 static void
1762 1766 rt2661_set_slottime(struct rt2661_softc *sc)
1763 1767 {
1764 1768 struct ieee80211com *ic = &sc->sc_ic;
1765 1769 uint8_t slottime;
1766 1770 uint32_t tmp;
1767 1771
1768 1772 slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
1769 1773
1770 1774 tmp = RT2661_READ(sc, RT2661_MAC_CSR9);
1771 1775 tmp = (tmp & ~0xff) | slottime;
1772 1776 RT2661_WRITE(sc, RT2661_MAC_CSR9, tmp);
1773 1777
1774 1778 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_set_slottime(): "
1775 1779 "setting slot time to %uus\n", slottime);
1776 1780 }
1777 1781
1778 1782
1779 1783 /*
1780 1784 * Enable multi-rate retries for frames sent at OFDM rates.
1781 1785 * In 802.11b/g mode, allow fallback to CCK rates.
1782 1786 */
1783 1787 static void
1784 1788 rt2661_enable_mrr(struct rt2661_softc *sc)
1785 1789 {
1786 1790 struct ieee80211com *ic = &sc->sc_ic;
1787 1791 uint32_t tmp;
1788 1792
1789 1793 tmp = RT2661_READ(sc, RT2661_TXRX_CSR4);
1790 1794
1791 1795 tmp &= ~RT2661_MRR_CCK_FALLBACK;
1792 1796 if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
1793 1797 tmp |= RT2661_MRR_CCK_FALLBACK;
1794 1798 tmp |= RT2661_MRR_ENABLED;
1795 1799
1796 1800 RT2661_WRITE(sc, RT2661_TXRX_CSR4, tmp);
1797 1801 }
1798 1802
1799 1803 static void
1800 1804 rt2661_set_txpreamble(struct rt2661_softc *sc)
1801 1805 {
1802 1806 uint32_t tmp;
1803 1807
1804 1808 tmp = RT2661_READ(sc, RT2661_TXRX_CSR4);
1805 1809
1806 1810 tmp &= ~RT2661_SHORT_PREAMBLE;
1807 1811 if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
1808 1812 tmp |= RT2661_SHORT_PREAMBLE;
1809 1813
1810 1814 RT2661_WRITE(sc, RT2661_TXRX_CSR4, tmp);
1811 1815 }
1812 1816
1813 1817 static void
1814 1818 rt2661_set_basicrates(struct rt2661_softc *sc)
1815 1819 {
1816 1820 struct ieee80211com *ic = &sc->sc_ic;
1817 1821
1818 1822 /* update basic rate set */
1819 1823 if (ic->ic_curmode == IEEE80211_MODE_11B) {
1820 1824 /* 11b basic rates: 1, 2Mbps */
1821 1825 RT2661_WRITE(sc, RT2661_TXRX_CSR5, 0x3);
1822 1826 } else if (ic->ic_curmode == IEEE80211_MODE_11A) {
1823 1827 /* 11a basic rates: 6, 12, 24Mbps */
1824 1828 RT2661_WRITE(sc, RT2661_TXRX_CSR5, 0x150);
1825 1829 } else {
1826 1830 /* 11b/g basic rates: 1, 2, 5.5, 11Mbps */
1827 1831 RT2661_WRITE(sc, RT2661_TXRX_CSR5, 0xf);
1828 1832 }
1829 1833 }
1830 1834
1831 1835 static void
1832 1836 rt2661_set_bssid(struct rt2661_softc *sc, const uint8_t *bssid)
1833 1837 {
1834 1838 uint32_t tmp;
1835 1839
1836 1840 tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24;
1837 1841 RT2661_WRITE(sc, RT2661_MAC_CSR4, tmp);
1838 1842
1839 1843 tmp = bssid[4] | bssid[5] << 8 | RT2661_ONE_BSSID << 16;
1840 1844 RT2661_WRITE(sc, RT2661_MAC_CSR5, tmp);
1841 1845 }
1842 1846
1843 1847 /*
1844 1848 * Enable TSF synchronization and tell h/w to start sending beacons for IBSS
1845 1849 * and HostAP operating modes.
1846 1850 */
1847 1851 static void
1848 1852 rt2661_enable_tsf_sync(struct rt2661_softc *sc)
1849 1853 {
1850 1854 struct ieee80211com *ic = &sc->sc_ic;
1851 1855 uint32_t tmp;
1852 1856
1853 1857 tmp = RT2661_READ(sc, RT2661_TXRX_CSR9) & 0xff000000;
1854 1858
1855 1859 /* set beacon interval (in 1/16ms unit) */
1856 1860 tmp |= ic->ic_bss->in_intval * 16;
1857 1861
1858 1862 tmp |= RT2661_TSF_TICKING | RT2661_ENABLE_TBTT;
1859 1863 if (ic->ic_opmode == IEEE80211_M_STA)
1860 1864 tmp |= RT2661_TSF_MODE(1);
1861 1865
1862 1866 RT2661_WRITE(sc, RT2661_TXRX_CSR9, tmp);
1863 1867 }
1864 1868
1865 1869
1866 1870 static void
1867 1871 rt2661_next_scan(void *arg)
1868 1872 {
1869 1873 struct rt2661_softc *sc = arg;
1870 1874 struct ieee80211com *ic = &sc->sc_ic;
1871 1875
1872 1876 if (ic->ic_state == IEEE80211_S_SCAN)
1873 1877 (void) ieee80211_next_scan(ic);
1874 1878 }
1875 1879
1876 1880 static void
1877 1881 rt2661_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni)
1878 1882 {
1879 1883 struct rt2661_softc *sc = (struct rt2661_softc *)ic;
1880 1884 int i;
1881 1885
1882 1886 rt2661_amrr_node_init(&sc->amrr, &((struct rt2661_node *)ni)->amn);
1883 1887
1884 1888 /* set rate to some reasonable initial value */
1885 1889 i = ni->in_rates.ir_nrates - 1;
1886 1890 while (i > 0 && ((ni->in_rates.ir_rates[i] & IEEE80211_RATE_VAL) > 72))
1887 1891 i--;
1888 1892
1889 1893 ni->in_txrate = i;
1890 1894 }
1891 1895
1892 1896 static void
1893 1897 rt2661_iter_func(void *arg, struct ieee80211_node *ni)
1894 1898 {
1895 1899 struct rt2661_softc *sc = arg;
1896 1900 struct rt2661_node *rn = (struct rt2661_node *)ni;
1897 1901
1898 1902 rt2661_amrr_choose(&sc->amrr, ni, &rn->amn);
1899 1903
1900 1904 }
1901 1905
1902 1906 /*
1903 1907 * Dynamically tune Rx sensitivity (BBP register 17) based on average RSSI and
1904 1908 * false CCA count. This function is called periodically (every seconds) when
1905 1909 * in the RUN state. Values taken from the reference driver.
1906 1910 */
1907 1911 static void
1908 1912 rt2661_rx_tune(struct rt2661_softc *sc)
1909 1913 {
1910 1914 uint8_t bbp17;
1911 1915 uint16_t cca;
1912 1916 int lo, hi, dbm;
1913 1917
1914 1918 /*
1915 1919 * Tuning range depends on operating band and on the presence of an
1916 1920 * external low-noise amplifier.
1917 1921 */
1918 1922 lo = 0x20;
1919 1923 if (IEEE80211_IS_CHAN_5GHZ(sc->sc_curchan))
1920 1924 lo += 0x08;
1921 1925 if ((IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) && sc->ext_2ghz_lna) ||
1922 1926 (IEEE80211_IS_CHAN_5GHZ(sc->sc_curchan) && sc->ext_5ghz_lna))
1923 1927 lo += 0x10;
1924 1928 hi = lo + 0x20;
1925 1929
1926 1930 dbm = sc->avg_rssi;
1927 1931 /* retrieve false CCA count since last call (clear on read) */
1928 1932 cca = RT2661_READ(sc, RT2661_STA_CSR1) & 0xffff;
1929 1933
1930 1934 RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_rx_tune(): "
1931 1935 "RSSI=%ddBm false CCA=%d\n", dbm, cca);
1932 1936
1933 1937 if (dbm < -74) {
1934 1938 /* very bad RSSI, tune using false CCA count */
1935 1939 bbp17 = sc->bbp17; /* current value */
1936 1940
1937 1941 hi -= 2 * (-74 - dbm);
1938 1942 if (hi < lo)
1939 1943 hi = lo;
1940 1944
1941 1945 if (bbp17 > hi)
1942 1946 bbp17 = (uint8_t)hi;
1943 1947 else if (cca > 512)
1944 1948 bbp17 = (uint8_t)min(bbp17 + 1, hi);
1945 1949 else if (cca < 100)
1946 1950 bbp17 = (uint8_t)max(bbp17 - 1, lo);
1947 1951
1948 1952 } else if (dbm < -66) {
1949 1953 bbp17 = lo + 0x08;
1950 1954 } else if (dbm < -58) {
1951 1955 bbp17 = lo + 0x10;
1952 1956 } else if (dbm < -35) {
1953 1957 bbp17 = (uint8_t)hi;
1954 1958 } else { /* very good RSSI >= -35dBm */
1955 1959 bbp17 = 0x60; /* very low sensitivity */
1956 1960 }
1957 1961
1958 1962 if (bbp17 != sc->bbp17) {
1959 1963 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_rx_tune(): "
1960 1964 "BBP17 %x->%x\n", sc->bbp17, bbp17);
1961 1965 rt2661_bbp_write(sc, 17, bbp17);
1962 1966 sc->bbp17 = bbp17;
1963 1967 }
1964 1968 }
1965 1969
1966 1970 /*
1967 1971 * This function is called periodically (every 500ms) in RUN state to update
1968 1972 * various settings like rate control statistics or Rx sensitivity.
1969 1973 */
1970 1974 static void
1971 1975 rt2661_updatestats(void *arg)
1972 1976 {
1973 1977 struct rt2661_softc *sc = arg;
1974 1978 struct ieee80211com *ic = &sc->sc_ic;
1975 1979
1976 1980 if (ic->ic_opmode == IEEE80211_M_STA)
1977 1981 rt2661_iter_func(sc, ic->ic_bss);
1978 1982 else
1979 1983 ieee80211_iterate_nodes(&ic->ic_sta, rt2661_iter_func, arg);
1980 1984
1981 1985 /* update rx sensitivity every 1 sec */
1982 1986 if (++sc->ncalls & 1)
1983 1987 rt2661_rx_tune(sc);
1984 1988
1985 1989 sc->sc_rssadapt_id = timeout(rt2661_updatestats, (void *)sc,
1986 1990 drv_usectohz(200 * 1000));
1987 1991 }
1988 1992
1989 1993 static int
1990 1994 rt2661_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1991 1995 {
1992 1996 struct rt2661_softc *sc = (struct rt2661_softc *)ic;
1993 1997 enum ieee80211_state ostate;
1994 1998 struct ieee80211_node *ni;
1995 1999 uint32_t tmp;
1996 2000 int err;
1997 2001
1998 2002 RT2661_GLOCK(sc);
1999 2003
2000 2004 ostate = ic->ic_state;
2001 2005 sc->sc_ostate = ostate;
2002 2006
2003 2007 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt26661_newstate(): "
2004 2008 "%x -> %x\n", ostate, nstate);
2005 2009
2006 2010 if (sc->sc_scan_id != 0) {
2007 2011 (void) untimeout(sc->sc_scan_id);
2008 2012 sc->sc_scan_id = 0;
2009 2013 }
2010 2014
2011 2015 if (sc->sc_rssadapt_id) {
2012 2016 (void) untimeout(sc->sc_rssadapt_id);
2013 2017 sc->sc_rssadapt_id = 0;
2014 2018 }
2015 2019
2016 2020 switch (nstate) {
2017 2021 case IEEE80211_S_INIT:
2018 2022 if (ostate == IEEE80211_S_RUN) {
2019 2023 /* abort TSF synchronization */
2020 2024 tmp = RT2661_READ(sc, RT2661_TXRX_CSR9);
2021 2025 RT2661_WRITE(sc, RT2661_TXRX_CSR9, tmp & ~0x00ffffff);
2022 2026 }
2023 2027 break;
2024 2028 case IEEE80211_S_SCAN:
2025 2029 rt2661_set_chan(sc, ic->ic_curchan);
2026 2030 sc->sc_scan_id = timeout(rt2661_next_scan, (void *)sc,
2027 2031 drv_usectohz(200000));
2028 2032 break;
2029 2033 case IEEE80211_S_AUTH:
2030 2034 case IEEE80211_S_ASSOC:
2031 2035 rt2661_set_chan(sc, ic->ic_curchan);
2032 2036 break;
2033 2037 case IEEE80211_S_RUN:
2034 2038 rt2661_set_chan(sc, ic->ic_curchan);
2035 2039
2036 2040 ni = ic->ic_bss;
2037 2041 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
2038 2042 rt2661_set_slottime(sc);
2039 2043 rt2661_enable_mrr(sc);
2040 2044 rt2661_set_txpreamble(sc);
2041 2045 rt2661_set_basicrates(sc);
2042 2046 rt2661_set_bssid(sc, ni->in_bssid);
2043 2047 }
2044 2048
2045 2049 if (ic->ic_opmode == IEEE80211_M_STA) {
2046 2050 /* fake a join to init the tx rate */
2047 2051 rt2661_newassoc(ic, ni);
2048 2052 }
2049 2053
2050 2054 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
2051 2055 sc->ncalls = 0;
2052 2056 sc->avg_rssi = -95; /* reset EMA */
2053 2057 sc->sc_rssadapt_id = timeout(rt2661_updatestats,
2054 2058 (void *)sc, drv_usectohz(200 * 1000));
2055 2059 rt2661_enable_tsf_sync(sc);
2056 2060 }
2057 2061 break;
2058 2062 default:
2059 2063 break;
2060 2064 }
2061 2065
2062 2066 RT2661_GUNLOCK(sc);
2063 2067
2064 2068 err = sc->sc_newstate(ic, nstate, arg);
2065 2069 return (err);
2066 2070 }
2067 2071
2068 2072 /*ARGSUSED*/
2069 2073 static struct ieee80211_node *
2070 2074 rt2661_node_alloc(ieee80211com_t *ic)
2071 2075 {
2072 2076 struct rt2661_node *rn;
2073 2077
2074 2078 rn = kmem_zalloc(sizeof (struct rt2661_node), KM_SLEEP);
2075 2079 return ((rn != NULL) ? &rn->ni : NULL);
2076 2080 }
2077 2081
2078 2082 static void
2079 2083 rt2661_node_free(struct ieee80211_node *in)
2080 2084 {
2081 2085 struct ieee80211com *ic = in->in_ic;
2082 2086
2083 2087 ic->ic_node_cleanup(in);
2084 2088 if (in->in_wpa_ie != NULL)
2085 2089 ieee80211_free(in->in_wpa_ie);
2086 2090 kmem_free(in, sizeof (struct rt2661_node));
2087 2091 }
2088 2092
2089 2093 static void
2090 2094 rt2661_stop_locked(struct rt2661_softc *sc)
2091 2095 {
2092 2096 uint32_t tmp;
2093 2097
2094 2098 if (RT2661_IS_RUNNING(sc)) {
2095 2099 sc->sc_tx_timer = 0;
2096 2100
2097 2101 /* abort Tx (for all 5 Tx rings) */
2098 2102 RT2661_WRITE(sc, RT2661_TX_CNTL_CSR, 0x1f << 16);
2099 2103
2100 2104 /* disable Rx (value remains after reset!) */
2101 2105 tmp = RT2661_READ(sc, RT2661_TXRX_CSR0);
2102 2106 RT2661_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX);
2103 2107
2104 2108 /* reset ASIC */
2105 2109 RT2661_WRITE(sc, RT2661_MAC_CSR1, 3);
2106 2110 RT2661_WRITE(sc, RT2661_MAC_CSR1, 0);
2107 2111
2108 2112 /* disable interrupts */
2109 2113 RT2661_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f);
2110 2114 RT2661_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff);
2111 2115
2112 2116 /* clear any pending interrupt */
2113 2117 RT2661_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff);
2114 2118 RT2661_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, 0xffffffff);
2115 2119
2116 2120 /* reset Tx and Rx rings */
2117 2121 rt2661_reset_tx_ring(sc, &sc->txq[0]);
2118 2122 rt2661_reset_tx_ring(sc, &sc->txq[1]);
2119 2123 rt2661_reset_tx_ring(sc, &sc->txq[2]);
2120 2124 rt2661_reset_tx_ring(sc, &sc->txq[3]);
2121 2125 rt2661_reset_tx_ring(sc, &sc->mgtq);
2122 2126 rt2661_reset_rx_ring(sc, &sc->rxq);
2123 2127 }
2124 2128 }
2125 2129
2126 2130 static void
2127 2131 rt2661_set_macaddr(struct rt2661_softc *sc, const uint8_t *addr)
2128 2132 {
2129 2133 uint32_t tmp;
2130 2134
2131 2135 tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24;
2132 2136 RT2661_WRITE(sc, RT2661_MAC_CSR2, tmp);
2133 2137
2134 2138 tmp = addr[4] | addr[5] << 8 | 0xff << 16;
2135 2139 RT2661_WRITE(sc, RT2661_MAC_CSR3, tmp);
2136 2140 }
2137 2141
2138 2142 static uint8_t
2139 2143 rt2661_bbp_read(struct rt2661_softc *sc, uint8_t reg)
2140 2144 {
2141 2145 uint32_t val;
2142 2146 int ntries;
2143 2147
2144 2148 for (ntries = 0; ntries < 100; ntries++) {
2145 2149 if (!(RT2661_READ(sc, RT2661_PHY_CSR3) & RT2661_BBP_BUSY))
2146 2150 break;
2147 2151 DELAY(1);
2148 2152 }
2149 2153 if (ntries == 100) {
2150 2154 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_bbp_read(): "
2151 2155 "could not read from BBP\n");
2152 2156 return (0);
2153 2157 }
2154 2158
2155 2159 val = RT2661_BBP_BUSY | RT2661_BBP_READ | reg << 8;
2156 2160 RT2661_WRITE(sc, RT2661_PHY_CSR3, val);
2157 2161
2158 2162 for (ntries = 0; ntries < 100; ntries++) {
2159 2163 val = RT2661_READ(sc, RT2661_PHY_CSR3);
2160 2164 if (!(val & RT2661_BBP_BUSY))
2161 2165 return (val & 0xff);
2162 2166 DELAY(1);
2163 2167 }
2164 2168
2165 2169 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_bbp_read(): "
2166 2170 "could not read from BBP\n");
2167 2171 return (0);
2168 2172 }
2169 2173
2170 2174 static int
2171 2175 rt2661_bbp_init(struct rt2661_softc *sc)
2172 2176 {
2173 2177 #define N(a) (sizeof (a) / sizeof ((a)[0]))
2174 2178
2175 2179 int i, ntries;
2176 2180 uint8_t val;
2177 2181
2178 2182 /* wait for BBP to be ready */
2179 2183 for (ntries = 0; ntries < 100; ntries++) {
2180 2184 val = rt2661_bbp_read(sc, 0);
2181 2185 if (val != 0 && val != 0xff)
2182 2186 break;
2183 2187 DELAY(100);
2184 2188 }
2185 2189 if (ntries == 100) {
2186 2190 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_bbp_init(): "
2187 2191 "timeout waiting for BBP\n");
2188 2192 return (RT2661_FAILURE);
2189 2193 }
2190 2194
2191 2195 /* initialize BBP registers to default values */
2192 2196 for (i = 0; i < N(rt2661_def_bbp); i++) {
2193 2197 rt2661_bbp_write(sc, rt2661_def_bbp[i].reg,
2194 2198 rt2661_def_bbp[i].val);
2195 2199 }
2196 2200
2197 2201 /* write vendor-specific BBP values (from EEPROM) */
2198 2202 for (i = 0; i < 16; i++) {
2199 2203 if (sc->bbp_prom[i].reg == 0)
2200 2204 continue;
2201 2205 rt2661_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val);
2202 2206 }
2203 2207
2204 2208 return (RT2661_SUCCESS);
2205 2209 #undef N
2206 2210 }
2207 2211
2208 2212 static void
2209 2213 rt2661_bbp_write(struct rt2661_softc *sc, uint8_t reg, uint8_t val)
2210 2214 {
2211 2215 uint32_t tmp;
2212 2216 int ntries;
2213 2217
2214 2218 for (ntries = 0; ntries < 100; ntries++) {
2215 2219 if (!(RT2661_READ(sc, RT2661_PHY_CSR3) & RT2661_BBP_BUSY))
2216 2220 break;
2217 2221 DELAY(1);
2218 2222 }
2219 2223 if (ntries == 100) {
2220 2224 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_bbp_write(): "
2221 2225 "could not write to BBP\n");
2222 2226 return;
2223 2227 }
2224 2228
2225 2229 tmp = RT2661_BBP_BUSY | (reg & 0x7f) << 8 | val;
2226 2230 RT2661_WRITE(sc, RT2661_PHY_CSR3, tmp);
2227 2231
2228 2232 RWD_DEBUG(RT2661_DBG_HW, "rwd: rt2661_bbp_write(): "
2229 2233 "BBP R%u <- 0x%02x\n", reg, val);
2230 2234 }
2231 2235
2232 2236 /*
2233 2237 * Reprogram MAC/BBP to switch to a new band. Values taken from the reference
2234 2238 * driver.
2235 2239 */
2236 2240 static void
2237 2241 rt2661_select_band(struct rt2661_softc *sc, struct ieee80211_channel *c)
2238 2242 {
2239 2243 uint8_t bbp17, bbp35, bbp96, bbp97, bbp98, bbp104;
2240 2244 uint32_t tmp;
2241 2245
2242 2246 /* update all BBP registers that depend on the band */
2243 2247 bbp17 = 0x20; bbp96 = 0x48; bbp104 = 0x2c;
2244 2248 bbp35 = 0x50; bbp97 = 0x48; bbp98 = 0x48;
2245 2249 if (IEEE80211_IS_CHAN_5GHZ(c)) {
2246 2250 bbp17 += 0x08; bbp96 += 0x10; bbp104 += 0x0c;
2247 2251 bbp35 += 0x10; bbp97 += 0x10; bbp98 += 0x10;
2248 2252 }
2249 2253 if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
2250 2254 (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
2251 2255 bbp17 += 0x10; bbp96 += 0x10; bbp104 += 0x10;
2252 2256 }
2253 2257
2254 2258 sc->bbp17 = bbp17;
2255 2259 rt2661_bbp_write(sc, 17, bbp17);
2256 2260 rt2661_bbp_write(sc, 96, bbp96);
2257 2261 rt2661_bbp_write(sc, 104, bbp104);
2258 2262
2259 2263 if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
2260 2264 (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
2261 2265 rt2661_bbp_write(sc, 75, 0x80);
2262 2266 rt2661_bbp_write(sc, 86, 0x80);
2263 2267 rt2661_bbp_write(sc, 88, 0x80);
2264 2268 }
2265 2269
2266 2270 rt2661_bbp_write(sc, 35, bbp35);
2267 2271 rt2661_bbp_write(sc, 97, bbp97);
2268 2272 rt2661_bbp_write(sc, 98, bbp98);
2269 2273
2270 2274 tmp = RT2661_READ(sc, RT2661_PHY_CSR0);
2271 2275 tmp &= ~(RT2661_PA_PE_2GHZ | RT2661_PA_PE_5GHZ);
2272 2276 if (IEEE80211_IS_CHAN_2GHZ(c))
2273 2277 tmp |= RT2661_PA_PE_2GHZ;
2274 2278 else
2275 2279 tmp |= RT2661_PA_PE_5GHZ;
2276 2280 RT2661_WRITE(sc, RT2661_PHY_CSR0, tmp);
2277 2281
2278 2282 /* 802.11a uses a 16 microseconds short interframe space */
2279 2283 sc->sifs = IEEE80211_IS_CHAN_5GHZ(c) ? 16 : 10;
2280 2284 }
2281 2285
2282 2286 static void
2283 2287 rt2661_select_antenna(struct rt2661_softc *sc)
2284 2288 {
2285 2289 uint8_t bbp4, bbp77;
2286 2290 uint32_t tmp;
2287 2291
2288 2292 bbp4 = rt2661_bbp_read(sc, 4);
2289 2293 bbp77 = rt2661_bbp_read(sc, 77);
2290 2294
2291 2295 /* TBD */
2292 2296
2293 2297 /* make sure Rx is disabled before switching antenna */
2294 2298 tmp = RT2661_READ(sc, RT2661_TXRX_CSR0);
2295 2299 RT2661_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX);
2296 2300
2297 2301 rt2661_bbp_write(sc, 4, bbp4);
2298 2302 rt2661_bbp_write(sc, 77, bbp77);
2299 2303
2300 2304 /* restore Rx filter */
2301 2305 RT2661_WRITE(sc, RT2661_TXRX_CSR0, tmp);
2302 2306 }
2303 2307
2304 2308 static void
2305 2309 rt2661_rf_write(struct rt2661_softc *sc, uint8_t reg, uint32_t val)
2306 2310 {
2307 2311 uint32_t tmp;
2308 2312 int ntries;
2309 2313
2310 2314 for (ntries = 0; ntries < 100; ntries++) {
2311 2315 if (!(RT2661_READ(sc, RT2661_PHY_CSR4) & RT2661_RF_BUSY))
2312 2316 break;
2313 2317 DELAY(1);
2314 2318 }
2315 2319 if (ntries == 100) {
2316 2320 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_rf_write(): "
2317 2321 "could not write to RF\n");
2318 2322 return;
2319 2323 }
2320 2324
2321 2325 tmp = RT2661_RF_BUSY | RT2661_RF_21BIT | (val & 0x1fffff) << 2 |
2322 2326 (reg & 3);
2323 2327 RT2661_WRITE(sc, RT2661_PHY_CSR4, tmp);
2324 2328
2325 2329 /* remember last written value in sc */
2326 2330 sc->rf_regs[reg] = val;
2327 2331
2328 2332 RWD_DEBUG(RT2661_DBG_FW, "rwd: rt2661_rf_write(): "
2329 2333 "RF R[%u] <- 0x%05x\n", reg & 3, val & 0x1fffff);
2330 2334 }
2331 2335
2332 2336 static void
2333 2337 rt2661_set_chan(struct rt2661_softc *sc, struct ieee80211_channel *c)
2334 2338 {
2335 2339 struct ieee80211com *ic = &sc->sc_ic;
2336 2340 const struct rfprog *rfprog;
2337 2341 uint8_t bbp3, bbp94 = RT2661_BBPR94_DEFAULT;
2338 2342 int8_t power;
2339 2343 uint_t i, chan;
2340 2344
2341 2345 chan = ieee80211_chan2ieee(ic, c);
2342 2346 if (chan == 0 || chan == IEEE80211_CHAN_ANY)
2343 2347 return;
2344 2348
2345 2349 /* select the appropriate RF settings based on what EEPROM says */
2346 2350 rfprog = (sc->rfprog == 0) ? rt2661_rf5225_1 : rt2661_rf5225_2;
2347 2351
2348 2352 /* find the settings for this channel (we know it exists) */
2349 2353 i = 0;
2350 2354 while (rfprog[i].chan != chan)
2351 2355 i++;
2352 2356
2353 2357 power = sc->txpow[i];
2354 2358 if (power < 0) {
2355 2359 bbp94 += power;
2356 2360 power = 0;
2357 2361 } else if (power > 31) {
2358 2362 bbp94 += power - 31;
2359 2363 power = 31;
2360 2364 }
2361 2365
2362 2366 /*
2363 2367 * If we are switching from the 2GHz band to the 5GHz band or
2364 2368 * vice-versa, BBP registers need to be reprogrammed.
2365 2369 */
2366 2370 if (ic->ic_flags != sc->sc_curchan->ich_flags) {
2367 2371 rt2661_select_band(sc, c);
2368 2372 rt2661_select_antenna(sc);
2369 2373 }
2370 2374 sc->sc_curchan = c;
2371 2375
2372 2376 rt2661_rf_write(sc, RT2661_RF1, rfprog[i].r1);
2373 2377 rt2661_rf_write(sc, RT2661_RF2, rfprog[i].r2);
2374 2378 rt2661_rf_write(sc, RT2661_RF3, rfprog[i].r3 | power << 7);
2375 2379 rt2661_rf_write(sc, RT2661_RF4, rfprog[i].r4 | sc->rffreq << 10);
2376 2380
2377 2381 DELAY(200);
2378 2382
2379 2383 rt2661_rf_write(sc, RT2661_RF1, rfprog[i].r1);
2380 2384 rt2661_rf_write(sc, RT2661_RF2, rfprog[i].r2);
2381 2385 rt2661_rf_write(sc, RT2661_RF3, rfprog[i].r3 | power << 7 | 1);
2382 2386 rt2661_rf_write(sc, RT2661_RF4, rfprog[i].r4 | sc->rffreq << 10);
2383 2387
2384 2388 DELAY(200);
2385 2389
2386 2390 rt2661_rf_write(sc, RT2661_RF1, rfprog[i].r1);
2387 2391 rt2661_rf_write(sc, RT2661_RF2, rfprog[i].r2);
2388 2392 rt2661_rf_write(sc, RT2661_RF3, rfprog[i].r3 | power << 7);
2389 2393 rt2661_rf_write(sc, RT2661_RF4, rfprog[i].r4 | sc->rffreq << 10);
2390 2394
2391 2395 /* enable smart mode for MIMO-capable RFs */
2392 2396 bbp3 = rt2661_bbp_read(sc, 3);
2393 2397
2394 2398 bbp3 &= ~RT2661_SMART_MODE;
2395 2399 if (sc->rf_rev == RT2661_RF_5325 || sc->rf_rev == RT2661_RF_2529)
2396 2400 bbp3 |= RT2661_SMART_MODE;
2397 2401
2398 2402 rt2661_bbp_write(sc, 3, bbp3);
2399 2403
2400 2404 if (bbp94 != RT2661_BBPR94_DEFAULT)
2401 2405 rt2661_bbp_write(sc, 94, bbp94);
2402 2406
2403 2407 /* 5GHz radio needs a 1ms delay here */
2404 2408 if (IEEE80211_IS_CHAN_5GHZ(c))
2405 2409 DELAY(1000);
2406 2410 }
2407 2411
2408 2412 static int
2409 2413 rt2661_init(struct rt2661_softc *sc)
2410 2414 {
2411 2415 #define N(a) (sizeof (a) / sizeof ((a)[0]))
2412 2416
2413 2417 struct ieee80211com *ic = &sc->sc_ic;
2414 2418 uint32_t tmp, sta[3], *fptr;
2415 2419 int i, err, off, ntries;
2416 2420
2417 2421 RT2661_GLOCK(sc);
2418 2422
2419 2423 rt2661_stop_locked(sc);
2420 2424
2421 2425 if (!RT2661_IS_FWLOADED(sc)) {
2422 2426 err = rt2661_load_microcode(sc, ucode, usize);
2423 2427 if (err != RT2661_SUCCESS) {
2424 2428 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2425 2429 "could not load 8051 microcode\n");
2426 2430 return (DDI_FAILURE);
2427 2431 }
2428 2432 sc->sc_flags |= RT2661_F_FWLOADED;
2429 2433 }
2430 2434
2431 2435 /* initialize Tx rings */
2432 2436 RT2661_WRITE(sc, RT2661_AC1_BASE_CSR, sc->txq[1].paddr);
2433 2437 RT2661_WRITE(sc, RT2661_AC0_BASE_CSR, sc->txq[0].paddr);
2434 2438 RT2661_WRITE(sc, RT2661_AC2_BASE_CSR, sc->txq[2].paddr);
2435 2439 RT2661_WRITE(sc, RT2661_AC3_BASE_CSR, sc->txq[3].paddr);
2436 2440
2437 2441 /* initialize Mgt ring */
2438 2442 RT2661_WRITE(sc, RT2661_MGT_BASE_CSR, sc->mgtq.paddr);
2439 2443
2440 2444 /* initialize Rx ring */
2441 2445 RT2661_WRITE(sc, RT2661_RX_BASE_CSR, sc->rxq.paddr);
2442 2446
2443 2447 /* initialize Tx rings sizes */
2444 2448 RT2661_WRITE(sc, RT2661_TX_RING_CSR0,
2445 2449 RT2661_TX_RING_COUNT << 24 |
2446 2450 RT2661_TX_RING_COUNT << 16 |
2447 2451 RT2661_TX_RING_COUNT << 8 |
2448 2452 RT2661_TX_RING_COUNT);
2449 2453
2450 2454 RT2661_WRITE(sc, RT2661_TX_RING_CSR1,
2451 2455 RT2661_TX_DESC_WSIZE << 16 |
2452 2456 RT2661_TX_RING_COUNT << 8 |
2453 2457 RT2661_MGT_RING_COUNT);
2454 2458
2455 2459 /* initialize Rx rings */
2456 2460 RT2661_WRITE(sc, RT2661_RX_RING_CSR,
2457 2461 RT2661_RX_DESC_BACK << 16 |
2458 2462 RT2661_RX_DESC_WSIZE << 8 |
2459 2463 RT2661_RX_RING_COUNT);
2460 2464
2461 2465 /* XXX: some magic here */
2462 2466 RT2661_WRITE(sc, RT2661_TX_DMA_DST_CSR, 0xaa);
2463 2467
2464 2468 /* load base addresses of all 5 Tx rings (4 data + 1 mgt) */
2465 2469 RT2661_WRITE(sc, RT2661_LOAD_TX_RING_CSR, 0x1f);
2466 2470
2467 2471 /* load base address of Rx ring */
2468 2472 RT2661_WRITE(sc, RT2661_RX_CNTL_CSR, 2);
2469 2473
2470 2474 /* initialize MAC registers to default values */
2471 2475 for (i = 0; i < N(rt2661_def_mac); i++)
2472 2476 RT2661_WRITE(sc, rt2661_def_mac[i].reg, rt2661_def_mac[i].val);
2473 2477
2474 2478 rt2661_set_macaddr(sc, ic->ic_macaddr);
2475 2479
2476 2480 /* set host ready */
2477 2481 RT2661_WRITE(sc, RT2661_MAC_CSR1, 3);
2478 2482 RT2661_WRITE(sc, RT2661_MAC_CSR1, 0);
2479 2483
2480 2484 /* wait for BBP/RF to wakeup */
2481 2485 for (ntries = 0; ntries < 1000; ntries++) {
2482 2486 if (RT2661_READ(sc, RT2661_MAC_CSR12) & 8)
2483 2487 break;
2484 2488 DELAY(1000);
2485 2489 }
2486 2490 if (ntries == 1000) {
2487 2491 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2488 2492 "timeout waiting for BBP/RF to wakeup\n");
2489 2493 rt2661_stop_locked(sc);
2490 2494 RT2661_GUNLOCK(sc);
2491 2495 return (DDI_FAILURE);
2492 2496 }
2493 2497
2494 2498 if (rt2661_bbp_init(sc) != RT2661_SUCCESS) {
2495 2499 rt2661_stop_locked(sc);
2496 2500 RT2661_GUNLOCK(sc);
2497 2501 return (DDI_FAILURE);
2498 2502 }
2499 2503
2500 2504 /* select default channel */
2501 2505 sc->sc_curchan = ic->ic_bss->in_chan = ic->ic_curchan;
2502 2506 rt2661_select_band(sc, sc->sc_curchan);
2503 2507 rt2661_select_antenna(sc);
2504 2508 rt2661_set_chan(sc, sc->sc_curchan);
2505 2509
2506 2510 /* update Rx filter */
2507 2511 tmp = RT2661_READ(sc, RT2661_TXRX_CSR0) & 0xffff;
2508 2512
2509 2513 tmp |= RT2661_DROP_PHY_ERROR | RT2661_DROP_CRC_ERROR;
2510 2514 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
2511 2515 tmp |= RT2661_DROP_CTL | RT2661_DROP_VER_ERROR |
2512 2516 RT2661_DROP_ACKCTS;
2513 2517 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
2514 2518 tmp |= RT2661_DROP_TODS;
2515 2519 if (!(sc->sc_rcr & RT2661_RCR_PROMISC))
2516 2520 tmp |= RT2661_DROP_NOT_TO_ME;
2517 2521 }
2518 2522
2519 2523 RT2661_WRITE(sc, RT2661_TXRX_CSR0, tmp);
2520 2524
2521 2525 /* clear STA registers */
2522 2526 off = RT2661_STA_CSR0;
2523 2527 fptr = sta;
2524 2528 for (i = 0; i < N(sta); i++) {
2525 2529 *fptr = RT2661_MEM_READ1(sc, off++);
2526 2530 }
2527 2531
2528 2532 /* initialize ASIC */
2529 2533 RT2661_WRITE(sc, RT2661_MAC_CSR1, 4);
2530 2534
2531 2535 /* clear any pending interrupt */
2532 2536 RT2661_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff);
2533 2537
2534 2538 /* enable interrupts */
2535 2539 RT2661_WRITE(sc, RT2661_INT_MASK_CSR, 0x0000ff10);
2536 2540 RT2661_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0);
2537 2541
2538 2542 /* kick Rx */
2539 2543 RT2661_WRITE(sc, RT2661_RX_CNTL_CSR, 1);
2540 2544 RT2661_GUNLOCK(sc);
2541 2545
2542 2546 #undef N
2543 2547 return (DDI_SUCCESS);
2544 2548 }
2545 2549
2546 2550 static void
2547 2551 rt2661_stop(struct rt2661_softc *sc)
2548 2552 {
2549 2553 if (!RT2661_IS_FASTREBOOT(sc))
2550 2554 RT2661_GLOCK(sc);
2551 2555 rt2661_stop_locked(sc);
2552 2556 if (!RT2661_IS_FASTREBOOT(sc))
2553 2557 RT2661_GUNLOCK(sc);
2554 2558 }
2555 2559
2556 2560 static int
2557 2561 rt2661_m_start(void *arg)
2558 2562 {
2559 2563 struct rt2661_softc *sc = (struct rt2661_softc *)arg;
2560 2564 struct ieee80211com *ic = &sc->sc_ic;
2561 2565 int err;
2562 2566
2563 2567 err = rt2661_init(sc);
2564 2568 if (err != DDI_SUCCESS) {
2565 2569 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_m_start():"
2566 2570 "Hardware initialization failed\n");
2567 2571 goto fail1;
2568 2572 }
2569 2573
2570 2574 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
2571 2575
2572 2576 RT2661_GLOCK(sc);
2573 2577 sc->sc_flags |= RT2661_F_RUNNING;
2574 2578 RT2661_GUNLOCK(sc);
2575 2579
2576 2580 return (DDI_SUCCESS);
2577 2581 fail1:
2578 2582 rt2661_stop(sc);
2579 2583 return (err);
2580 2584 }
2581 2585
2582 2586 static void
2583 2587 rt2661_m_stop(void *arg)
2584 2588 {
2585 2589 struct rt2661_softc *sc = (struct rt2661_softc *)arg;
2586 2590
2587 2591 (void) rt2661_stop(sc);
2588 2592
2589 2593 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
2590 2594
2591 2595 RT2661_GLOCK(sc);
2592 2596 sc->sc_flags &= ~RT2661_F_RUNNING;
2593 2597 RT2661_GUNLOCK(sc);
2594 2598 }
2595 2599
2596 2600 static void
2597 2601 rt2661_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
2598 2602 {
2599 2603 struct rt2661_softc *sc = (struct rt2661_softc *)arg;
2600 2604 struct ieee80211com *ic = &sc->sc_ic;
2601 2605 int err;
2602 2606
2603 2607 err = ieee80211_ioctl(ic, wq, mp);
2604 2608 RT2661_GLOCK(sc);
2605 2609 if (err == ENETRESET) {
2606 2610 if (ic->ic_des_esslen) {
2607 2611 if (RT2661_IS_RUNNING(sc)) {
2608 2612 RT2661_GUNLOCK(sc);
2609 2613 (void) rt2661_init(sc);
2610 2614 (void) ieee80211_new_state(ic,
2611 2615 IEEE80211_S_SCAN, -1);
2612 2616 RT2661_GLOCK(sc);
2613 2617 }
2614 2618 }
2615 2619 }
2616 2620 RT2661_GUNLOCK(sc);
2617 2621 }
2618 2622
2619 2623 /*
2620 2624 * Call back function for get/set proporty
2621 2625 */
2622 2626 static int
2623 2627 rt2661_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
2624 2628 uint_t wldp_length, void *wldp_buf)
2625 2629 {
2626 2630 struct rt2661_softc *sc = (struct rt2661_softc *)arg;
2627 2631 int err = 0;
2628 2632
2629 2633 err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num,
2630 2634 wldp_length, wldp_buf);
2631 2635
2632 2636 return (err);
2633 2637 }
2634 2638
2635 2639 static void
2636 2640 rt2661_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
2637 2641 mac_prop_info_handle_t mph)
2638 2642 {
2639 2643 struct rt2661_softc *sc = (struct rt2661_softc *)arg;
2640 2644
2641 2645 ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, mph);
2642 2646 }
2643 2647
2644 2648 static int
2645 2649 rt2661_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
2646 2650 uint_t wldp_length, const void *wldp_buf)
2647 2651 {
2648 2652 struct rt2661_softc *sc = (struct rt2661_softc *)arg;
2649 2653 ieee80211com_t *ic = &sc->sc_ic;
2650 2654 int err;
2651 2655
2652 2656 err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length,
2653 2657 wldp_buf);
2654 2658 RT2661_GLOCK(sc);
2655 2659 if (err == ENETRESET) {
2656 2660 if (ic->ic_des_esslen) {
2657 2661 if (RT2661_IS_RUNNING(sc)) {
2658 2662 RT2661_GUNLOCK(sc);
2659 2663 (void) rt2661_init(sc);
2660 2664 (void) ieee80211_new_state(ic,
2661 2665 IEEE80211_S_SCAN, -1);
2662 2666 RT2661_GLOCK(sc);
2663 2667 }
2664 2668 }
2665 2669 err = 0;
2666 2670 }
2667 2671 RT2661_GUNLOCK(sc);
2668 2672 return (err);
2669 2673 }
2670 2674
2671 2675 static mblk_t *
2672 2676 rt2661_m_tx(void *arg, mblk_t *mp)
2673 2677 {
2674 2678 struct rt2661_softc *sc = (struct rt2661_softc *)arg;
2675 2679 struct ieee80211com *ic = &sc->sc_ic;
2676 2680 mblk_t *next;
2677 2681
2678 2682 if (RT2661_IS_SUSPEND(sc)) {
2679 2683 freemsgchain(mp);
2680 2684 return (NULL);
2681 2685 }
2682 2686
2683 2687 /*
2684 2688 * No data frames go out unless we're associated; this
2685 2689 * should not happen as the 802.11 layer does not enable
2686 2690 * the xmit queue until we enter the RUN state.
2687 2691 */
2688 2692 if (ic->ic_state != IEEE80211_S_RUN) {
2689 2693 RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_data(): "
2690 2694 "discard, state %u\n", ic->ic_state);
2691 2695 freemsgchain(mp);
2692 2696 return (NULL);
2693 2697 }
2694 2698
2695 2699 while (mp != NULL) {
2696 2700 next = mp->b_next;
2697 2701 mp->b_next = NULL;
2698 2702 if (rt2661_send(ic, mp) !=
2699 2703 DDI_SUCCESS) {
2700 2704 mp->b_next = next;
2701 2705 break;
2702 2706 }
2703 2707 mp = next;
2704 2708 }
2705 2709 return (mp);
2706 2710 }
2707 2711
2708 2712 /*ARGSUSED*/
2709 2713 static int
2710 2714 rt2661_m_unicst(void *arg, const uint8_t *macaddr)
2711 2715 {
2712 2716 return (ENOTSUP);
2713 2717 }
2714 2718
2715 2719 /*ARGSUSED*/
2716 2720 static int
2717 2721 rt2661_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
2718 2722 {
2719 2723 return (ENOTSUP);
2720 2724 }
2721 2725
2722 2726 /*ARGSUSED*/
2723 2727 static int
2724 2728 rt2661_m_promisc(void *arg, boolean_t on)
2725 2729 {
2726 2730 struct rt2661_softc *sc = (struct rt2661_softc *)arg;
2727 2731
2728 2732 if (on) {
2729 2733 sc->sc_rcr |= RT2661_RCR_PROMISC;
2730 2734 sc->sc_rcr |= RT2661_RCR_MULTI;
2731 2735 } else {
2732 2736 sc->sc_rcr &= ~RT2661_RCR_PROMISC;
2733 2737 sc->sc_rcr &= ~RT2661_RCR_MULTI;
2734 2738 }
2735 2739
2736 2740 rt2661_update_promisc(sc);
2737 2741 return (0);
2738 2742 }
2739 2743
2740 2744 static int
2741 2745 rt2661_m_stat(void *arg, uint_t stat, uint64_t *val)
2742 2746 {
2743 2747 struct rt2661_softc *sc = (struct rt2661_softc *)arg;
2744 2748 struct ieee80211com *ic = &sc->sc_ic;
2745 2749 struct ieee80211_node *ni = ic->ic_bss;
2746 2750 struct ieee80211_rateset *rs = &ni->in_rates;
2747 2751
2748 2752 RT2661_GLOCK(sc);
2749 2753 switch (stat) {
2750 2754 case MAC_STAT_IFSPEED:
2751 2755 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
2752 2756 (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL)
2753 2757 : ic->ic_fixed_rate) / 2 * 1000000;
2754 2758 break;
2755 2759 case MAC_STAT_NOXMTBUF:
2756 2760 *val = sc->sc_tx_nobuf;
2757 2761 break;
2758 2762 case MAC_STAT_NORCVBUF:
2759 2763 *val = sc->sc_rx_nobuf;
2760 2764 break;
2761 2765 case MAC_STAT_IERRORS:
2762 2766 *val = sc->sc_rx_err;
2763 2767 break;
2764 2768 case MAC_STAT_RBYTES:
2765 2769 *val = ic->ic_stats.is_rx_bytes;
2766 2770 break;
2767 2771 case MAC_STAT_IPACKETS:
2768 2772 *val = ic->ic_stats.is_rx_frags;
2769 2773 break;
2770 2774 case MAC_STAT_OBYTES:
2771 2775 *val = ic->ic_stats.is_tx_bytes;
2772 2776 break;
2773 2777 case MAC_STAT_OPACKETS:
2774 2778 *val = ic->ic_stats.is_tx_frags;
2775 2779 break;
2776 2780 case MAC_STAT_OERRORS:
2777 2781 case WIFI_STAT_TX_FAILED:
2778 2782 *val = sc->sc_tx_err;
2779 2783 break;
2780 2784 case WIFI_STAT_TX_RETRANS:
2781 2785 *val = sc->sc_tx_retries;
2782 2786 break;
2783 2787 case WIFI_STAT_FCS_ERRORS:
2784 2788 case WIFI_STAT_WEP_ERRORS:
2785 2789 case WIFI_STAT_TX_FRAGS:
2786 2790 case WIFI_STAT_MCAST_TX:
2787 2791 case WIFI_STAT_RTS_SUCCESS:
2788 2792 case WIFI_STAT_RTS_FAILURE:
2789 2793 case WIFI_STAT_ACK_FAILURE:
2790 2794 case WIFI_STAT_RX_FRAGS:
2791 2795 case WIFI_STAT_MCAST_RX:
2792 2796 case WIFI_STAT_RX_DUPS:
2793 2797 RT2661_GUNLOCK(sc);
2794 2798 return (ieee80211_stat(ic, stat, val));
2795 2799 default:
2796 2800 RT2661_GUNLOCK(sc);
2797 2801 return (ENOTSUP);
2798 2802 }
2799 2803 RT2661_GUNLOCK(sc);
2800 2804
2801 2805 return (0);
2802 2806 }
2803 2807
2804 2808 static int
2805 2809 rt2661_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
2806 2810 {
2807 2811 struct rt2661_softc *sc;
2808 2812 struct ieee80211com *ic;
2809 2813
2810 2814 int i, ac, err, ntries, instance;
2811 2815 int intr_type, intr_count, intr_actual;
2812 2816 char strbuf[32];
2813 2817 uint8_t cachelsz;
2814 2818 uint16_t command, vendor_id, device_id;
2815 2819 uint32_t val;
2816 2820
2817 2821 wifi_data_t wd = { 0 };
2818 2822 mac_register_t *macp;
2819 2823
2820 2824 switch (cmd) {
2821 2825 case DDI_ATTACH:
2822 2826 break;
2823 2827 case DDI_RESUME:
2824 2828 sc = ddi_get_soft_state(rt2661_soft_state_p,
2825 2829 ddi_get_instance(devinfo));
2826 2830 ASSERT(sc != NULL);
2827 2831 RT2661_GLOCK(sc);
2828 2832 sc->sc_flags &= ~RT2661_F_SUSPEND;
2829 2833 RT2661_GUNLOCK(sc);
2830 2834 if (RT2661_IS_RUNNING(sc))
2831 2835 (void) rt2661_init(sc);
2832 2836 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2833 2837 "resume now\n");
2834 2838 return (DDI_SUCCESS);
2835 2839 default:
2836 2840 return (DDI_FAILURE);
2837 2841 }
2838 2842
2839 2843 instance = ddi_get_instance(devinfo);
2840 2844
2841 2845 err = ddi_soft_state_zalloc(rt2661_soft_state_p, instance);
2842 2846 if (err != DDI_SUCCESS) {
2843 2847 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2844 2848 "unable to alloc soft_state_p\n");
2845 2849 return (err);
2846 2850 }
2847 2851
2848 2852 sc = ddi_get_soft_state(rt2661_soft_state_p, instance);
2849 2853 ic = (struct ieee80211com *)&sc->sc_ic;
2850 2854 sc->sc_dev = devinfo;
2851 2855
2852 2856 /* PCI configuration */
2853 2857 err = ddi_regs_map_setup(devinfo, 0, &sc->sc_cfg_base, 0, 0,
2854 2858 &rt2661_csr_accattr, &sc->sc_cfg_handle);
2855 2859 if (err != DDI_SUCCESS) {
2856 2860 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2857 2861 "ddi_regs_map_setup() failed");
2858 2862 goto fail1;
2859 2863 }
2860 2864
2861 2865 cachelsz = ddi_get8(sc->sc_cfg_handle,
2862 2866 (uint8_t *)(sc->sc_cfg_base + PCI_CONF_CACHE_LINESZ));
2863 2867 if (cachelsz == 0)
2864 2868 cachelsz = 0x10;
2865 2869 sc->sc_cachelsz = cachelsz << 2;
2866 2870 sc->sc_dmabuf_size = roundup(IEEE80211_MAX_LEN, sc->sc_cachelsz);
2867 2871
2868 2872 vendor_id = ddi_get16(sc->sc_cfg_handle,
2869 2873 (uint16_t *)((uintptr_t)(sc->sc_cfg_base) + PCI_CONF_VENID));
2870 2874 device_id = ddi_get16(sc->sc_cfg_handle,
2871 2875 (uint16_t *)((uintptr_t)(sc->sc_cfg_base) + PCI_CONF_DEVID));
2872 2876 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2873 2877 "vendor 0x%x, device id 0x%x, cache size %d\n",
2874 2878 vendor_id, device_id, cachelsz);
2875 2879
2876 2880 /*
2877 2881 * Enable response to memory space accesses,
2878 2882 * and enabe bus master.
2879 2883 */
2880 2884 command = PCI_COMM_MAE | PCI_COMM_ME;
2881 2885 ddi_put16(sc->sc_cfg_handle,
2882 2886 (uint16_t *)((uintptr_t)(sc->sc_cfg_base) + PCI_CONF_COMM),
2883 2887 command);
2884 2888 ddi_put8(sc->sc_cfg_handle,
2885 2889 (uint8_t *)(sc->sc_cfg_base + PCI_CONF_LATENCY_TIMER), 0xa8);
2886 2890 ddi_put8(sc->sc_cfg_handle,
2887 2891 (uint8_t *)(sc->sc_cfg_base + PCI_CONF_ILINE), 0x10);
2888 2892
2889 2893 /* pci i/o space */
2890 2894 err = ddi_regs_map_setup(devinfo, 1,
2891 2895 &sc->sc_io_base, 0, 0, &rt2661_csr_accattr, &sc->sc_io_handle);
2892 2896 if (err != DDI_SUCCESS) {
2893 2897 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2894 2898 "ddi_regs_map_setup() failed");
2895 2899 goto fail2;
2896 2900 }
2897 2901 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2898 2902 "PCI configuration is done successfully\n");
2899 2903
2900 2904 err = ddi_intr_get_supported_types(devinfo, &intr_type);
2901 2905 if ((err != DDI_SUCCESS) || (!(intr_type & DDI_INTR_TYPE_FIXED))) {
2902 2906 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2903 2907 "fixed type interrupt is not supported\n");
2904 2908 goto fail3;
2905 2909 }
2906 2910
2907 2911 err = ddi_intr_get_nintrs(devinfo, DDI_INTR_TYPE_FIXED, &intr_count);
2908 2912 if ((err != DDI_SUCCESS) || (intr_count != 1)) {
2909 2913 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2910 2914 "no fixed interrupts\n");
2911 2915 goto fail3;
2912 2916 }
2913 2917
2914 2918 sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP);
2915 2919
2916 2920 err = ddi_intr_alloc(devinfo, sc->sc_intr_htable,
2917 2921 DDI_INTR_TYPE_FIXED, 0, intr_count, &intr_actual, 0);
2918 2922 if ((err != DDI_SUCCESS) || (intr_actual != 1)) {
2919 2923 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2920 2924 "ddi_intr_alloc() failed 0x%x\n", err);
2921 2925 goto faili4;
2922 2926 }
2923 2927
2924 2928 err = ddi_intr_get_pri(sc->sc_intr_htable[0], &sc->sc_intr_pri);
2925 2929 if (err != DDI_SUCCESS) {
2926 2930 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2927 2931 "ddi_intr_get_pri() failed 0x%x\n", err);
2928 2932 goto faili5;
2929 2933 }
2930 2934
2931 2935 sc->amrr.amrr_min_success_threshold = 1;
2932 2936 sc->amrr.amrr_max_success_threshold = 15;
2933 2937
2934 2938 /* wait for NIC to initialize */
2935 2939 for (ntries = 0; ntries < 1000; ntries++) {
2936 2940 if ((val = RT2661_READ(sc, RT2661_MAC_CSR0)) != 0)
2937 2941 break;
2938 2942 DELAY(1000);
2939 2943 }
2940 2944 if (ntries == 1000) {
2941 2945 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2942 2946 "timeout waiting for NIC to initialize\n");
2943 2947 goto faili5;
2944 2948 }
2945 2949
2946 2950 /* retrieve RF rev. no and various other things from EEPROM */
2947 2951 rt2661_read_eeprom(sc);
2948 2952
2949 2953 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2950 2954 "MAC/BBP RT%X, RF %s\n"
2951 2955 "MAC address is: %x:%x:%x:%x:%x:%x\n", val,
2952 2956 rt2661_get_rf(sc->rf_rev),
2953 2957 ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2],
2954 2958 ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5]);
2955 2959
2956 2960 /*
2957 2961 * Load 8051 microcode into NIC.
2958 2962 */
2959 2963 switch (device_id) {
2960 2964 case 0x0301:
2961 2965 ucode = rt2561s_ucode;
2962 2966 usize = sizeof (rt2561s_ucode);
2963 2967 break;
2964 2968 case 0x0302:
2965 2969 ucode = rt2561_ucode;
2966 2970 usize = sizeof (rt2561_ucode);
2967 2971 break;
2968 2972 case 0x0401:
2969 2973 ucode = rt2661_ucode;
2970 2974 usize = sizeof (rt2661_ucode);
2971 2975 break;
2972 2976 }
2973 2977
2974 2978 err = rt2661_load_microcode(sc, ucode, usize);
2975 2979 if (err != RT2661_SUCCESS) {
2976 2980 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
2977 2981 "could not load 8051 microcode\n");
2978 2982 goto faili5;
2979 2983 }
2980 2984
2981 2985 sc->sc_flags = 0;
2982 2986 sc->sc_flags |= RT2661_F_FWLOADED;
2983 2987
2984 2988 /*
2985 2989 * Allocate Tx and Rx rings.
2986 2990 */
2987 2991 for (ac = 0; ac < 4; ac++) {
2988 2992 err = rt2661_alloc_tx_ring(sc, &sc->txq[ac],
2989 2993 RT2661_TX_RING_COUNT);
2990 2994 if (err != RT2661_SUCCESS) {
2991 2995 RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_attach(): "
2992 2996 "could not allocate Tx ring %d\n", ac);
2993 2997 goto fail4;
2994 2998 }
2995 2999 }
2996 3000
2997 3001 err = rt2661_alloc_tx_ring(sc, &sc->mgtq, RT2661_MGT_RING_COUNT);
2998 3002 if (err != RT2661_SUCCESS) {
2999 3003 RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_attach(): "
3000 3004 "could not allocate Mgt ring\n");
3001 3005 goto fail5;
3002 3006 }
3003 3007
3004 3008 err = rt2661_alloc_rx_ring(sc, &sc->rxq, RT2661_RX_RING_COUNT);
3005 3009 if (err != RT2661_SUCCESS) {
3006 3010 RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_attach(): "
3007 3011 "could not allocate Rx ring\n");
3008 3012 goto fail6;
3009 3013 }
3010 3014
3011 3015 mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL);
3012 3016 mutex_init(&sc->sc_txlock, NULL, MUTEX_DRIVER, NULL);
3013 3017 mutex_init(&sc->sc_rxlock, NULL, MUTEX_DRIVER, NULL);
3014 3018
3015 3019 ic->ic_phytype = IEEE80211_T_OFDM;
3016 3020 ic->ic_opmode = IEEE80211_M_STA;
3017 3021 ic->ic_state = IEEE80211_S_INIT;
3018 3022
3019 3023 /* set device capabilities */
3020 3024 ic->ic_caps =
3021 3025 IEEE80211_C_TXPMGT |
3022 3026 IEEE80211_C_SHPREAMBLE |
3023 3027 IEEE80211_C_SHSLOT;
3024 3028
3025 3029 /* WPA/WPA2 support */
3026 3030 ic->ic_caps |= IEEE80211_C_WPA;
3027 3031
3028 3032 /* set supported .11b and .11g rates */
3029 3033 ic->ic_sup_rates[IEEE80211_MODE_11B] = rt2661_rateset_11b;
3030 3034 ic->ic_sup_rates[IEEE80211_MODE_11G] = rt2661_rateset_11g;
3031 3035
3032 3036 /* set supported .11b and .11g channels (1 through 14) */
3033 3037 for (i = 1; i <= 14; i++) {
3034 3038 ic->ic_sup_channels[i].ich_freq =
3035 3039 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
3036 3040 ic->ic_sup_channels[i].ich_flags =
3037 3041 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
3038 3042 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
3039 3043 }
3040 3044
3041 3045 ic->ic_maxrssi = 63;
3042 3046 ic->ic_xmit = rt2661_mgmt_send;
3043 3047
3044 3048 ieee80211_attach(ic);
3045 3049
3046 3050 /* register WPA door */
3047 3051 ieee80211_register_door(ic, ddi_driver_name(devinfo),
3048 3052 ddi_get_instance(devinfo));
3049 3053
3050 3054 ic->ic_node_alloc = rt2661_node_alloc;
3051 3055 ic->ic_node_free = rt2661_node_free;
3052 3056 ic->ic_set_shortslot = rt2661_updateslot;
3053 3057
3054 3058 /* override state transition machine */
3055 3059 sc->sc_newstate = ic->ic_newstate;
3056 3060 ic->ic_newstate = rt2661_newstate;
3057 3061 ieee80211_media_init(ic);
3058 3062 ic->ic_def_txkey = 0;
3059 3063
3060 3064 err = ddi_intr_add_softint(devinfo, &sc->sc_softintr_hdl,
3061 3065 DDI_INTR_SOFTPRI_MAX, rt2661_softintr, (caddr_t)sc);
3062 3066 if (err != DDI_SUCCESS) {
3063 3067 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
3064 3068 "ddi_add_softintr() failed");
3065 3069 goto fail7;
3066 3070 }
3067 3071
3068 3072 err = ddi_intr_add_handler(sc->sc_intr_htable[0], rt2661_intr,
3069 3073 (caddr_t)sc, NULL);
3070 3074 if (err != DDI_SUCCESS) {
3071 3075 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
3072 3076 "ddi_intr_addr_handle() failed\n");
3073 3077 goto fail8;
3074 3078 }
3075 3079
3076 3080 err = ddi_intr_enable(sc->sc_intr_htable[0]);
3077 3081 if (err != DDI_SUCCESS) {
3078 3082 RWD_DEBUG(RT2661_DBG_MSG, "rwd; rt2661_attach(): "
3079 3083 "ddi_intr_enable() failed\n");
3080 3084 goto fail9;
3081 3085 }
3082 3086
3083 3087 /*
3084 3088 * Provide initial settings for the WiFi plugin; whenever this
3085 3089 * information changes, we need to call mac_plugindata_update()
3086 3090 */
3087 3091 wd.wd_opmode = ic->ic_opmode;
3088 3092 wd.wd_secalloc = WIFI_SEC_NONE;
3089 3093 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
3090 3094
3091 3095 if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
3092 3096 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
3093 3097 "MAC version mismatch\n");
3094 3098 goto fail10;
3095 3099 }
3096 3100
3097 3101 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
3098 3102 macp->m_driver = sc;
3099 3103 macp->m_dip = devinfo;
3100 3104 macp->m_src_addr = ic->ic_macaddr;
3101 3105 macp->m_callbacks = &rt2661_m_callbacks;
3102 3106 macp->m_min_sdu = 0;
3103 3107 macp->m_max_sdu = IEEE80211_MTU;
3104 3108 macp->m_pdata = &wd;
3105 3109 macp->m_pdata_size = sizeof (wd);
3106 3110
3107 3111 err = mac_register(macp, &ic->ic_mach);
3108 3112 mac_free(macp);
3109 3113 if (err != 0) {
3110 3114 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
3111 3115 "mac_register err %x\n", err);
3112 3116 goto fail10;
3113 3117 }
3114 3118
3115 3119 /*
3116 3120 * Create minor node of type DDI_NT_NET_WIFI
3117 3121 */
3118 3122 (void) snprintf(strbuf, sizeof (strbuf), "%s%d",
3119 3123 "rwd", instance);
3120 3124 err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR,
3121 3125 instance + 1, DDI_NT_NET_WIFI, 0);
3122 3126
3123 3127 /*
3124 3128 * Notify link is down now
3125 3129 */
3126 3130 mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
3127 3131
3128 3132 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
3129 3133 "attach successfully\n");
3130 3134 return (DDI_SUCCESS);
3131 3135
3132 3136 fail10:
3133 3137 (void) ddi_intr_disable(sc->sc_intr_htable[0]);
3134 3138 fail9:
3135 3139 (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
3136 3140 fail8:
3137 3141 (void) ddi_intr_remove_softint(sc->sc_softintr_hdl);
3138 3142 sc->sc_softintr_hdl = NULL;
3139 3143 fail7:
3140 3144 mutex_destroy(&sc->sc_genlock);
3141 3145 mutex_destroy(&sc->sc_txlock);
3142 3146 mutex_destroy(&sc->sc_rxlock);
3143 3147 fail6:
3144 3148 rt2661_free_rx_ring(sc, &sc->rxq);
3145 3149 fail5:
3146 3150 rt2661_free_tx_ring(sc, &sc->mgtq);
3147 3151 fail4:
3148 3152 while (--ac >= 0)
3149 3153 rt2661_free_tx_ring(sc, &sc->txq[ac]);
3150 3154 faili5:
3151 3155 (void) ddi_intr_free(sc->sc_intr_htable[0]);
3152 3156 faili4:
3153 3157 kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
3154 3158 fail3:
3155 3159 ddi_regs_map_free(&sc->sc_io_handle);
3156 3160 fail2:
3157 3161 ddi_regs_map_free(&sc->sc_cfg_handle);
3158 3162 fail1:
3159 3163 return (DDI_FAILURE);
3160 3164 }
3161 3165
3162 3166 static int
3163 3167 rt2661_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
3164 3168 {
3165 3169
3166 3170 struct rt2661_softc *sc;
3167 3171
3168 3172 sc = ddi_get_soft_state(rt2661_soft_state_p, ddi_get_instance(devinfo));
3169 3173
3170 3174 switch (cmd) {
3171 3175 case DDI_DETACH:
3172 3176 break;
3173 3177 case DDI_SUSPEND:
3174 3178 if (RT2661_IS_RUNNING(sc))
3175 3179 rt2661_stop(sc);
3176 3180 RT2661_GLOCK(sc);
3177 3181 sc->sc_flags |= RT2661_F_SUSPEND;
3178 3182 sc->sc_flags &= ~RT2661_F_FWLOADED;
3179 3183 RT2661_GUNLOCK(sc);
3180 3184 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_detach(): "
3181 3185 "suspend now\n");
3182 3186 return (DDI_SUCCESS);
3183 3187 default:
3184 3188 return (DDI_FAILURE);
3185 3189 }
3186 3190
3187 3191 if (mac_disable(sc->sc_ic.ic_mach) != 0)
3188 3192 return (DDI_FAILURE);
3189 3193
3190 3194 /*
3191 3195 * Unregister from the MAC layer subsystem
3192 3196 */
3193 3197 (void) mac_unregister(sc->sc_ic.ic_mach);
3194 3198
3195 3199 (void) ddi_intr_remove_softint(sc->sc_softintr_hdl);
3196 3200 sc->sc_softintr_hdl = NULL;
3197 3201 (void) ddi_intr_disable(sc->sc_intr_htable[0]);
3198 3202 (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
3199 3203 (void) ddi_intr_free(sc->sc_intr_htable[0]);
3200 3204 kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
3201 3205
3202 3206 /*
3203 3207 * detach ieee80211 layer
3204 3208 */
3205 3209 ieee80211_detach(&sc->sc_ic);
3206 3210
3207 3211 mutex_destroy(&sc->sc_genlock);
3208 3212 mutex_destroy(&sc->sc_txlock);
3209 3213 mutex_destroy(&sc->sc_rxlock);
3210 3214
3211 3215 rt2661_free_tx_ring(sc, &sc->txq[0]);
3212 3216 rt2661_free_tx_ring(sc, &sc->txq[1]);
3213 3217 rt2661_free_tx_ring(sc, &sc->txq[2]);
3214 3218 rt2661_free_tx_ring(sc, &sc->txq[3]);
3215 3219 rt2661_free_tx_ring(sc, &sc->mgtq);
3216 3220 rt2661_free_rx_ring(sc, &sc->rxq);
3217 3221
3218 3222 ddi_regs_map_free(&sc->sc_io_handle);
3219 3223 ddi_regs_map_free(&sc->sc_cfg_handle);
3220 3224
3221 3225 ddi_remove_minor_node(devinfo, NULL);
3222 3226 ddi_soft_state_free(rt2661_soft_state_p, ddi_get_instance(devinfo));
3223 3227
3224 3228 RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_detach(): "
3225 3229 "detach successfully\n");
3226 3230 return (DDI_SUCCESS);
3227 3231 }
3228 3232
3229 3233 static int
3230 3234 rt2661_quiesce(dev_info_t *dip)
3231 3235 {
3232 3236 struct rt2661_softc *sc;
3233 3237
3234 3238 sc = ddi_get_soft_state(rt2661_soft_state_p, ddi_get_instance(dip));
3235 3239 if (sc == NULL)
3236 3240 return (DDI_FAILURE);
3237 3241
3238 3242 #ifdef DEBUG
3239 3243 rt2661_dbg_flags = 0;
3240 3244 #endif
3241 3245
3242 3246 /*
3243 3247 * No more blocking is allowed while we are in quiesce(9E) entry point
3244 3248 */
3245 3249 sc->sc_flags |= RT2661_F_QUIESCE;
3246 3250
3247 3251 /*
3248 3252 * Disable all interrupts
3249 3253 */
3250 3254 rt2661_stop(sc);
3251 3255 return (DDI_SUCCESS);
3252 3256 }
3253 3257
3254 3258 int
3255 3259 _info(struct modinfo *modinfop)
3256 3260 {
3257 3261 return (mod_info(&modlinkage, modinfop));
3258 3262 }
3259 3263
3260 3264 int
3261 3265 _init(void)
3262 3266 {
3263 3267 int status;
3264 3268
3265 3269 status = ddi_soft_state_init(&rt2661_soft_state_p,
3266 3270 sizeof (struct rt2661_softc), 1);
3267 3271 if (status != 0)
3268 3272 return (status);
3269 3273
3270 3274 mac_init_ops(&rwd_dev_ops, "rwd");
3271 3275 status = mod_install(&modlinkage);
3272 3276 if (status != 0) {
3273 3277 mac_fini_ops(&rwd_dev_ops);
3274 3278 ddi_soft_state_fini(&rt2661_soft_state_p);
3275 3279 }
3276 3280 return (status);
3277 3281 }
3278 3282
3279 3283 int
3280 3284 _fini(void)
3281 3285 {
3282 3286 int status;
3283 3287
3284 3288 status = mod_remove(&modlinkage);
3285 3289 if (status == 0) {
3286 3290 mac_fini_ops(&rwd_dev_ops);
3287 3291 ddi_soft_state_fini(&rt2661_soft_state_p);
3288 3292 }
3289 3293 return (status);
3290 3294 }
↓ open down ↓ |
3200 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX