Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/atu/atu.c
+++ new/usr/src/uts/common/io/atu/atu.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) 2003, 2004
8 8 * Daan Vreeken <Danovitsch@Vitsch.net>. All rights reserved.
9 9 *
10 10 * Redistribution and use in source and binary forms, with or without
11 11 * modification, are permitted provided that the following conditions
12 12 * are met:
13 13 * 1. Redistributions of source code must retain the above copyright
14 14 * notice, this list of conditions and the following disclaimer.
15 15 * 2. Redistributions in binary form must reproduce the above copyright
16 16 * notice, this list of conditions and the following disclaimer in the
17 17 * documentation and/or other materials provided with the distribution.
18 18 * 3. All advertising materials mentioning features or use of this software
19 19 * must display the following acknowledgement:
20 20 * This product includes software developed by Daan Vreeken.
21 21 * 4. Neither the name of the author nor the names of any co-contributors
22 22 * may be used to endorse or promote products derived from this software
23 23 * without specific prior written permission.
24 24 *
25 25 * THIS SOFTWARE IS PROVIDED BY Daan Vreeken AND CONTRIBUTORS ``AS IS'' AND
26 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 28 * ARE DISCLAIMED. IN NO EVENT SHALL Daan Vreeken OR THE VOICES IN HIS HEAD
29 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35 35 * THE POSSIBILITY OF SUCH DAMAGE.
36 36 */
37 37
38 38 /*
39 39 * Atmel AT76c503 / AT76c503a / AT76c505 / AT76c505a USB WLAN driver
40 40 *
41 41 * Originally written by Daan Vreeken <Danovitsch @ Vitsch . net>
42 42 * http://vitsch.net/bsd/atuwi
43 43 *
44 44 * Contributed to by :
45 45 * Chris Whitehouse, Alistair Phillips, Peter Pilka, Martijn van Buul,
46 46 * Suihong Liang, Arjan van Leeuwen, Stuart Walsh
47 47 *
48 48 * Ported to OpenBSD by Theo de Raadt and David Gwynne.
49 49 */
50 50
51 51 #include <sys/strsubr.h>
52 52 #include <sys/strsun.h>
53 53 #include <sys/mac_provider.h>
54 54 #include <sys/mac_wifi.h>
55 55 #include <sys/net80211.h>
56 56 #define USBDRV_MAJOR_VER 2
57 57 #define USBDRV_MINOR_VER 0
58 58 #include <sys/usb/usba.h>
59 59 #include <sys/usb/usba/usba_types.h>
60 60
61 61 #include "fw/atmel_rfmd.hex"
62 62 #include "fw/atmel_rfmd2958.hex"
63 63 #include "fw/atmel_rfmd2958-smc.hex"
64 64 #include "fw/atmel_intersil.hex"
65 65 #include "fw/atmel_at76c505_rfmd.hex"
66 66 #include "fw/atmel_at76c503_rfmd_acc.hex"
67 67 #include "fw/atmel_at76c503_i3863.hex"
68 68 #include "atu.h"
69 69
70 70 static void *atu_soft_state_p;
71 71 static mac_callbacks_t atu_m_callbacks;
72 72 static const struct ieee80211_rateset atu_rateset = {4, {2, 4, 11, 22}};
73 73
74 74 static int
75 75 atu_usb_request(struct atu_softc *sc, uint8_t type,
76 76 uint8_t request, uint16_t value, uint16_t index, uint16_t length,
77 77 uint8_t *data)
78 78 {
79 79 usb_ctrl_setup_t req;
80 80 usb_cb_flags_t cf;
81 81 usb_cr_t cr;
82 82 mblk_t *mp = NULL;
83 83 int uret = USB_SUCCESS;
84 84
85 85 bzero(&req, sizeof (req));
86 86 req.bmRequestType = type;
87 87 req.bRequest = request;
88 88 req.wValue = value;
89 89 req.wIndex = index;
90 90 req.wLength = length;
91 91 req.attrs = USB_ATTRS_NONE;
92 92
93 93 if (type & USB_DEV_REQ_DEV_TO_HOST) {
94 94 req.attrs = USB_ATTRS_AUTOCLEARING;
95 95 uret = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph,
96 96 &req, &mp, &cr, &cf, 0);
97 97 if (mp == NULL)
98 98 return (EIO);
99 99
100 100 if (uret == USB_SUCCESS)
101 101 bcopy(mp->b_rptr, data, length);
102 102 } else {
103 103 if ((mp = allocb(length, BPRI_HI)) == NULL)
104 104 return (ENOMEM);
105 105
106 106 bcopy(data, mp->b_wptr, length);
107 107 mp->b_wptr += length;
108 108 uret = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph,
109 109 &req, &mp, &cr, &cf, 0);
110 110 }
111 111
112 112 if (mp)
113 113 freemsg(mp);
114 114
115 115 return (uret == USB_SUCCESS ? 0 : EIO);
116 116 }
117 117
118 118 static int
119 119 atu_get_mib(struct atu_softc *sc, uint8_t type, uint8_t size,
120 120 uint8_t index, uint8_t *buf)
121 121 {
122 122 return atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x033,
123 123 type << 8, index, size, buf);
124 124 }
125 125
126 126 static int
127 127 atu_get_cmd_status(struct atu_softc *sc, uint8_t cmd, uint8_t *status)
128 128 {
129 129 /*
130 130 * all other drivers (including Windoze) request 40 bytes of status
131 131 * and get a short-xfer of just 6 bytes. we can save 34 bytes of
132 132 * buffer if we just request those 6 bytes in the first place :)
133 133 */
134 134 return atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x22, cmd,
135 135 0x0000, 6, status);
136 136 }
137 137
138 138 static uint8_t
139 139 atu_get_dfu_state(struct atu_softc *sc)
140 140 {
141 141 uint8_t state;
142 142
143 143 if (atu_usb_request(sc, DFU_GETSTATE, 0, 0, 1, &state))
144 144 return (DFUState_DFUError);
145 145 return (state);
146 146 }
147 147
148 148 static int
149 149 atu_get_opmode(struct atu_softc *sc, uint8_t *mode)
150 150 {
151 151 return atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x33, 0x0001,
152 152 0x0000, 1, mode);
153 153 }
154 154
155 155 static int
156 156 atu_get_config(struct atu_softc *sc)
157 157 {
158 158 struct ieee80211com *ic = &sc->sc_ic;
159 159 struct atu_rfmd_conf rfmd_conf;
160 160 struct atu_intersil_conf intersil_conf;
161 161 int err;
162 162
163 163 switch (sc->sc_radio) {
164 164 case RadioRFMD:
165 165 case RadioRFMD2958:
166 166 case RadioRFMD2958_SMC:
167 167 case AT76C503_RFMD_ACC:
168 168 case AT76C505_RFMD:
169 169 err = atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x33, 0x0a02,
170 170 0x0000, sizeof (rfmd_conf), (uint8_t *)&rfmd_conf);
171 171 if (err) {
172 172 cmn_err(CE_WARN, "%s: get RFMD config failed\n",
173 173 sc->sc_name);
174 174 return (err);
175 175 }
176 176 bcopy(rfmd_conf.MACAddr, ic->ic_macaddr, IEEE80211_ADDR_LEN);
177 177 break;
178 178
179 179 case RadioIntersil:
180 180 case AT76C503_i3863:
181 181 err = atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x33, 0x0902,
182 182 0x0000, sizeof (intersil_conf), (uint8_t *)&intersil_conf);
183 183 if (err) {
184 184 cmn_err(CE_WARN, "%s: get Intersil config failed\n",
185 185 sc->sc_name);
186 186 return (err);
187 187 }
188 188 bcopy(intersil_conf.MACAddr, ic->ic_macaddr,
189 189 IEEE80211_ADDR_LEN);
190 190 break;
191 191 }
192 192
193 193 return (0);
194 194 }
195 195
196 196 static int
197 197 atu_wait_completion(struct atu_softc *sc, uint8_t cmd, uint8_t *status)
198 198 {
199 199 uint8_t statusreq[6];
200 200 int idle_count = 0, err;
201 201
202 202 while ((err = atu_get_cmd_status(sc, cmd, statusreq)) == 0) {
203 203
204 204 if ((statusreq[5] != STATUS_IN_PROGRESS) &&
205 205 (statusreq[5] != STATUS_IDLE)) {
206 206 if (status != NULL)
207 207 *status = statusreq[5];
208 208 return (0);
209 209 } else if (idle_count++ > 60) {
210 210 cmn_err(CE_WARN, "%s: command (0x%02x) timeout\n",
211 211 sc->sc_name, cmd);
212 212 return (ETIME);
213 213 }
214 214
215 215 drv_usecwait(10 * 1000);
216 216 }
217 217
218 218 return (err);
219 219 }
220 220
221 221 static int
222 222 atu_send_command(struct atu_softc *sc, uint8_t *command, int size)
223 223 {
224 224 return atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e, 0x0000,
225 225 0x0000, size, command);
226 226 }
227 227
228 228 static int
229 229 atu_send_mib(struct atu_softc *sc, uint8_t type, uint8_t size,
230 230 uint8_t index, void *data)
231 231 {
232 232 struct atu_cmd_set_mib request;
233 233 int err;
234 234
235 235 bzero(&request, sizeof (request));
236 236 request.AtCmd = CMD_SET_MIB;
237 237 request.AtSize = size + 4;
238 238 request.MIBType = type;
239 239 request.MIBSize = size;
240 240 request.MIBIndex = index;
241 241 request.MIBReserved = 0;
242 242
243 243 /*
244 244 * For 1 and 2 byte requests we assume a direct value,
245 245 * everything bigger than 2 bytes we assume a pointer to the data
246 246 */
247 247 switch (size) {
248 248 case 0:
249 249 break;
250 250 case 1:
251 251 request.data[0] = (long)data & 0x000000ff;
252 252 break;
253 253 case 2:
254 254 request.data[0] = (long)data & 0x000000ff;
255 255 request.data[1] = (long)data >> 8;
256 256 break;
257 257 default:
258 258 bcopy(data, request.data, size);
259 259 break;
260 260 }
261 261
262 262 err = atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e, 0x0000,
263 263 0x0000, size+8, (uint8_t *)&request);
264 264 if (err)
265 265 return (err);
266 266
267 267 return (atu_wait_completion(sc, CMD_SET_MIB, NULL));
268 268 }
269 269
270 270 static int
271 271 atu_switch_radio(struct atu_softc *sc, boolean_t on)
272 272 {
273 273 struct atu_cmd radio;
274 274 boolean_t ostate;
275 275 int err;
276 276
277 277 /* Intersil doesn't seem to support radio switch */
278 278 if (sc->sc_radio == RadioIntersil)
279 279 return (0);
280 280
281 281 ostate = ATU_RADIO_ON(sc) ? B_TRUE : B_FALSE;
282 282 if (on != ostate) {
283 283 bzero(&radio, sizeof (radio));
284 284 radio.Cmd = on ? CMD_RADIO_ON : CMD_RADIO_OFF;
285 285
286 286 err = atu_send_command(sc, (uint8_t *)&radio,
287 287 sizeof (radio));
288 288 if (err)
289 289 return (err);
290 290
291 291 err = atu_wait_completion(sc, radio.Cmd, NULL);
292 292 if (err)
293 293 return (err);
294 294
295 295 if (on)
296 296 sc->sc_flags |= ATU_FLAG_RADIO_ON;
297 297 else
298 298 sc->sc_flags &= ~ATU_FLAG_RADIO_ON;
299 299 }
300 300
301 301 return (0);
302 302 }
303 303
304 304 static int
305 305 atu_config(struct atu_softc *sc)
306 306 {
307 307 struct ieee80211com *ic = &sc->sc_ic;
308 308 struct ieee80211_key *k;
309 309 struct atu_cmd_card_config cmd;
310 310 uint8_t rates[4] = {0x82, 0x84, 0x8B, 0x96};
311 311 int err, i;
312 312
313 313 err = atu_send_mib(sc, MIB_MAC_ADDR_STA, ic->ic_macaddr);
314 314 if (err) {
315 315 cmn_err(CE_WARN, "%s: setting MAC address failed\n",
316 316 sc->sc_name);
317 317 return (err);
318 318 }
319 319
320 320 bzero(&cmd, sizeof (cmd));
321 321 cmd.Cmd = CMD_STARTUP;
322 322 cmd.Reserved = 0;
323 323 cmd.Size = sizeof (cmd) - 4;
324 324 cmd.Channel = ATU_DEF_CHAN;
325 325 cmd.ShortRetryLimit = 7;
326 326 cmd.RTS_Threshold = 2347;
327 327 cmd.FragThreshold = 2346;
328 328 cmd.PromiscuousMode = 1;
329 329 cmd.AutoRateFallback = 1;
330 330 bcopy(rates, cmd.BasicRateSet, 4);
331 331
332 332 if (ic->ic_flags & IEEE80211_F_PRIVACY) {
333 333 k = ic->ic_nw_keys + ic->ic_def_txkey;
334 334 switch (k->wk_keylen) {
335 335 case 5:
336 336 cmd.EncryptionType = ATU_ENC_WEP40;
337 337 break;
338 338 case 13:
339 339 cmd.EncryptionType = ATU_ENC_WEP104;
340 340 break;
341 341 default:
342 342 cmn_err(CE_WARN, "%s: key invalid (%d bytes)\n",
343 343 sc->sc_name, k->wk_keylen);
344 344 goto nowep;
345 345 }
346 346 cmd.PrivacyInvoked = 1;
347 347 cmd.ExcludeUnencrypted = 1;
348 348 cmd.WEP_DefaultKeyID = ic->ic_def_txkey;
349 349 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
350 350 k = ic->ic_nw_keys + i;
351 351 if (k->wk_keylen == 0)
352 352 continue;
353 353 bcopy(k->wk_key, cmd.WEP_DefaultKey + i, k->wk_keylen);
354 354 }
355 355 } else {
356 356 nowep:
357 357 cmd.EncryptionType = ATU_ENC_NONE;
358 358 }
359 359
360 360 bcopy(ic->ic_des_essid, cmd.SSID, ic->ic_des_esslen);
361 361 cmd.SSID_Len = ic->ic_des_esslen;
362 362 cmd.BeaconPeriod = 100;
363 363
364 364 err = atu_send_command(sc, (uint8_t *)&cmd, sizeof (cmd));
365 365 if (err)
366 366 return (err);
367 367 err = atu_wait_completion(sc, CMD_STARTUP, NULL);
368 368 if (err)
369 369 return (err);
370 370
371 371 err = atu_switch_radio(sc, B_TRUE);
372 372 if (err)
373 373 return (err);
374 374
375 375 err = atu_send_mib(sc, MIB_MAC_MGMT_POWER_MODE,
376 376 (void *)ATU_POWER_ACTIVE);
377 377 if (err)
378 378 return (err);
379 379
380 380 return (0);
381 381 }
382 382
383 383 static int
384 384 atu_start_scan(struct atu_softc *sc)
385 385 {
386 386 struct ieee80211com *ic = &sc->sc_ic;
387 387 struct atu_cmd_do_scan scan;
388 388 int err;
389 389
390 390 if (!ATU_RUNNING(sc))
391 391 return (EIO);
392 392
393 393 bzero(&scan, sizeof (scan));
394 394 scan.Cmd = CMD_START_SCAN;
395 395 scan.Reserved = 0;
396 396 scan.Size = sizeof (scan) - 4;
397 397 (void) memset(scan.BSSID, 0xff, sizeof (scan.BSSID));
398 398 bcopy(ic->ic_des_essid, scan.SSID, ic->ic_des_esslen);
399 399 scan.SSID_Len = ic->ic_des_esslen;
400 400 scan.ScanType = ATU_SCAN_ACTIVE;
401 401 scan.Channel = ieee80211_chan2ieee(ic, ic->ic_curchan);
402 402 scan.ProbeDelay = 0;
403 403 scan.MinChannelTime = 20;
404 404 scan.MaxChannelTime = 40;
405 405 scan.InternationalScan = 0;
406 406
407 407 err = atu_send_command(sc, (uint8_t *)&scan, sizeof (scan));
408 408 if (err) {
409 409 cmn_err(CE_WARN, "%s: SCAN command failed\n",
410 410 sc->sc_name);
411 411 return (err);
412 412 }
413 413
414 414 err = atu_wait_completion(sc, CMD_START_SCAN, NULL);
415 415 if (err) {
416 416 cmn_err(CE_WARN, "%s: SCAN completion failed\n",
417 417 sc->sc_name);
418 418 return (err);
419 419 }
420 420
421 421 return (0);
422 422 }
423 423
424 424 static int
425 425 atu_join(struct atu_softc *sc, struct ieee80211_node *node)
426 426 {
427 427 struct atu_cmd_join join;
428 428 uint8_t status;
429 429 int err;
430 430
431 431 bzero(&join, sizeof (join));
432 432 join.Cmd = CMD_JOIN;
433 433 join.Reserved = 0x00;
434 434 join.Size = sizeof (join) - 4;
435 435 bcopy(node->in_bssid, join.bssid, IEEE80211_ADDR_LEN);
436 436 bcopy(node->in_essid, join.essid, node->in_esslen);
437 437 join.essid_size = node->in_esslen;
438 438
439 439 if (node->in_capinfo & IEEE80211_CAPINFO_IBSS)
440 440 join.bss_type = ATU_MODE_IBSS;
441 441 else
442 442 join.bss_type = ATU_MODE_STA;
443 443
444 444 join.channel = ieee80211_chan2ieee(&sc->sc_ic, node->in_chan);
445 445 join.timeout = ATU_JOIN_TIMEOUT;
446 446 join.reserved = 0x00;
447 447
448 448 err = atu_send_command(sc, (uint8_t *)&join, sizeof (join));
449 449 if (err) {
450 450 cmn_err(CE_WARN, "%s: JOIN command failed\n",
451 451 sc->sc_name);
452 452 return (err);
453 453 }
454 454 err = atu_wait_completion(sc, CMD_JOIN, &status);
455 455 if (err)
456 456 return (err);
457 457
458 458 if (status != STATUS_COMPLETE) {
459 459 cmn_err(CE_WARN, "%s: incorrect JOIN state (0x%02x)\n",
460 460 sc->sc_name, status);
461 461 return (EIO);
462 462 }
463 463
464 464 return (0);
465 465 }
466 466
467 467 static int
468 468 atu_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
469 469 {
470 470 struct atu_softc *sc = (struct atu_softc *)ic;
471 471 enum ieee80211_state ostate = ic->ic_state;
472 472 int err = 0;
473 473
474 474 ATU_LOCK(sc);
475 475
476 476 if (sc->sc_scan_timer != 0) {
477 477 ATU_UNLOCK(sc);
478 478 (void) untimeout(sc->sc_scan_timer);
479 479 ATU_LOCK(sc);
480 480 sc->sc_scan_timer = 0;
481 481 }
482 482 ostate = ic->ic_state;
483 483
484 484 switch (nstate) {
485 485 case IEEE80211_S_SCAN:
486 486 switch (ostate) {
487 487 case IEEE80211_S_SCAN:
488 488 case IEEE80211_S_AUTH:
489 489 case IEEE80211_S_ASSOC:
490 490 case IEEE80211_S_RUN:
491 491 ATU_UNLOCK(sc);
492 492 sc->sc_newstate(ic, nstate, arg);
493 493 ATU_LOCK(sc);
494 494 if ((err = atu_start_scan(sc)) != 0) {
495 495 ATU_UNLOCK(sc);
496 496 ieee80211_cancel_scan(ic);
497 497 return (err);
498 498 }
499 499 sc->sc_scan_timer = timeout(
500 500 (void (*) (void*))ieee80211_next_scan,
501 501 (void *)&sc->sc_ic, 0);
502 502
503 503 ATU_UNLOCK(sc);
504 504 return (err);
505 505 default:
506 506 break;
507 507 }
508 508 break;
509 509
510 510 case IEEE80211_S_AUTH:
511 511 switch (ostate) {
512 512 case IEEE80211_S_INIT:
513 513 case IEEE80211_S_SCAN:
514 514 err = atu_join(sc, ic->ic_bss);
515 515 if (err) {
516 516 ATU_UNLOCK(sc);
517 517 return (err);
518 518 }
519 519 break;
520 520 default:
521 521 break;
522 522 }
523 523 default:
524 524 break;
525 525 }
526 526
527 527 ATU_UNLOCK(sc);
528 528 err = sc->sc_newstate(ic, nstate, arg);
529 529
530 530 return (err);
531 531 }
532 532
533 533 static int
534 534 atu_open_pipes(struct atu_softc *sc)
535 535 {
536 536 usb_ep_data_t *ep;
537 537 usb_pipe_policy_t policy = {0};
538 538 int uret;
539 539
540 540 ep = usb_lookup_ep_data(sc->sc_dip, sc->sc_udev, 0, 0, 0,
541 541 USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
542 542 policy.pp_max_async_reqs = ATU_TX_LIST_CNT;
543 543
544 544 uret = usb_pipe_open(sc->sc_dip, &ep->ep_descr, &policy,
545 545 USB_FLAGS_SLEEP, &sc->sc_tx_pipe);
546 546 if (uret != USB_SUCCESS)
547 547 goto fail;
548 548
549 549 ep = usb_lookup_ep_data(sc->sc_dip, sc->sc_udev, 0, 0, 0,
550 550 USB_EP_ATTR_BULK, USB_EP_DIR_IN);
551 551 policy.pp_max_async_reqs = ATU_RX_LIST_CNT + 32;
552 552
553 553 uret = usb_pipe_open(sc->sc_dip, &ep->ep_descr, &policy,
554 554 USB_FLAGS_SLEEP, &sc->sc_rx_pipe);
555 555 if (uret != USB_SUCCESS)
556 556 goto fail;
557 557
558 558 return (0);
559 559 fail:
560 560 if (sc->sc_rx_pipe != NULL) {
561 561 usb_pipe_close(sc->sc_dip, sc->sc_rx_pipe,
562 562 USB_FLAGS_SLEEP, NULL, 0);
563 563 sc->sc_rx_pipe = NULL;
564 564 }
565 565
566 566 if (sc->sc_tx_pipe != NULL) {
567 567 usb_pipe_close(sc->sc_dip, sc->sc_tx_pipe,
568 568 USB_FLAGS_SLEEP, NULL, 0);
569 569 sc->sc_tx_pipe = NULL;
570 570 }
571 571
572 572 return (EIO);
573 573 }
574 574
575 575 static void
576 576 atu_close_pipes(struct atu_softc *sc)
577 577 {
578 578 usb_flags_t flags = USB_FLAGS_SLEEP;
579 579
580 580 if (sc->sc_rx_pipe != NULL) {
581 581 usb_pipe_reset(sc->sc_dip, sc->sc_rx_pipe, flags, NULL, 0);
582 582 usb_pipe_close(sc->sc_dip, sc->sc_rx_pipe, flags, NULL, 0);
583 583 sc->sc_rx_pipe = NULL;
584 584 }
585 585
586 586 if (sc->sc_tx_pipe != NULL) {
587 587 usb_pipe_reset(sc->sc_dip, sc->sc_tx_pipe, flags, NULL, 0);
588 588 usb_pipe_close(sc->sc_dip, sc->sc_tx_pipe, flags, NULL, 0);
589 589 sc->sc_tx_pipe = NULL;
590 590 }
591 591 }
592 592
593 593 static int atu_rx_trigger(struct atu_softc *sc);
594 594
595 595 /*ARGSUSED*/
596 596 static void
597 597 atu_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
598 598 {
599 599 struct atu_softc *sc = (struct atu_softc *)req->bulk_client_private;
600 600 struct ieee80211com *ic = &sc->sc_ic;
601 601 struct ieee80211_node *ni;
602 602 struct atu_rx_hdr *h;
603 603 struct ieee80211_frame *wh;
604 604 mblk_t *mp = req->bulk_data;
605 605 int len, pktlen;
606 606
607 607 req->bulk_data = NULL;
608 608 if (req->bulk_completion_reason != USB_CR_OK) {
609 609 sc->sc_rx_err++;
610 610 goto fail;
611 611 }
612 612
613 613 len = msgdsize(mp);
614 614 if (len < ATU_RX_HDRLEN + ATU_MIN_FRAMELEN) {
615 615 cmn_err(CE_CONT, "%s: fragment (%d bytes)\n",
616 616 sc->sc_name, len);
617 617 sc->sc_rx_err++;
618 618 goto fail;
619 619 }
620 620
621 621 h = (struct atu_rx_hdr *)mp->b_rptr;
622 622 pktlen = h->length - 4;
623 623 if (pktlen + ATU_RX_HDRLEN + 4 != len) {
624 624 cmn_err(CE_CONT, "%s: jumbo (%d bytes -> %d bytes)\n",
625 625 sc->sc_name, len, pktlen);
626 626 sc->sc_rx_err++;
627 627 goto fail;
628 628 }
629 629
630 630 mp->b_rptr += ATU_RX_HDRLEN;
631 631 mp->b_wptr = mp->b_rptr + pktlen;
632 632 wh = (struct ieee80211_frame *)mp->b_rptr;
633 633
634 634 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
635 635 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
636 636
637 637 ni = ieee80211_find_rxnode(ic, wh);
638 638 (void) ieee80211_input(ic, mp, ni, h->rssi, h->rx_time);
639 639 ieee80211_free_node(ni);
640 640 done:
641 641 usb_free_bulk_req(req);
642 642
643 643 mutex_enter(&sc->sc_rxlock);
644 644 sc->rx_queued--;
645 645 mutex_exit(&sc->sc_rxlock);
646 646
647 647 if (ATU_RUNNING(sc))
648 648 (void) atu_rx_trigger(sc);
649 649 return;
650 650 fail:
651 651 freemsg(mp);
652 652 goto done;
653 653 }
654 654
655 655 /*ARGSUSED*/
656 656 static void
657 657 atu_txeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
658 658 {
659 659 struct atu_softc *sc = (struct atu_softc *)req->bulk_client_private;
660 660 struct ieee80211com *ic = &sc->sc_ic;
661 661
662 662 if (req->bulk_completion_reason != USB_CR_OK)
663 663 ic->ic_stats.is_tx_failed++;
664 664 usb_free_bulk_req(req);
665 665
666 666 mutex_enter(&sc->sc_txlock);
667 667 sc->tx_queued--;
668 668
669 669 if (sc->sc_need_sched) {
670 670 sc->sc_need_sched = 0;
671 671 mac_tx_update(ic->ic_mach);
672 672 }
673 673
674 674 mutex_exit(&sc->sc_txlock);
675 675 }
676 676
677 677 static int
678 678 atu_rx_trigger(struct atu_softc *sc)
679 679 {
680 680 usb_bulk_req_t *req;
681 681 int uret;
682 682
683 683 req = usb_alloc_bulk_req(sc->sc_dip, ATU_RX_BUFSZ, USB_FLAGS_SLEEP);
684 684 if (req == NULL)
685 685 return (ENOMEM);
686 686
687 687 req->bulk_len = ATU_RX_BUFSZ;
688 688 req->bulk_client_private = (usb_opaque_t)sc;
689 689 req->bulk_timeout = 0;
690 690 req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING;
691 691 req->bulk_cb = atu_rxeof;
692 692 req->bulk_exc_cb = atu_rxeof;
693 693 req->bulk_completion_reason = 0;
694 694 req->bulk_cb_flags = 0;
695 695
696 696 uret = usb_pipe_bulk_xfer(sc->sc_rx_pipe, req, 0);
697 697 if (uret != USB_SUCCESS) {
698 698 usb_free_bulk_req(req);
699 699 return (EIO);
700 700 }
701 701
702 702 mutex_enter(&sc->sc_rxlock);
703 703 sc->rx_queued++;
704 704 mutex_exit(&sc->sc_rxlock);
705 705
706 706 return (0);
707 707 }
708 708
709 709 static int
710 710 atu_tx_trigger(struct atu_softc *sc, mblk_t *mp)
711 711 {
712 712 usb_bulk_req_t *req;
713 713 int uret;
714 714
715 715 req = usb_alloc_bulk_req(sc->sc_dip, 0, USB_FLAGS_SLEEP);
716 716 if (req == NULL)
717 717 return (EIO);
718 718
719 719 req->bulk_len = msgdsize(mp);
720 720 req->bulk_data = mp;
721 721 req->bulk_client_private = (usb_opaque_t)sc;
722 722 req->bulk_timeout = 10;
723 723 req->bulk_attributes = USB_ATTRS_AUTOCLEARING;
724 724 req->bulk_cb = atu_txeof;
725 725 req->bulk_exc_cb = atu_txeof;
726 726 req->bulk_completion_reason = 0;
727 727 req->bulk_cb_flags = 0;
728 728
729 729 uret = usb_pipe_bulk_xfer(sc->sc_tx_pipe, req, 0);
730 730 if (uret != USB_SUCCESS) {
731 731 req->bulk_data = NULL;
732 732 usb_free_bulk_req(req);
733 733 return (EIO);
734 734 }
735 735
736 736 mutex_enter(&sc->sc_txlock);
737 737 sc->tx_queued++;
738 738 mutex_exit(&sc->sc_txlock);
739 739
740 740 return (0);
741 741 }
742 742
743 743 static int
744 744 atu_init_rx_queue(struct atu_softc *sc)
745 745 {
746 746 int err, i;
747 747
748 748 mutex_enter(&sc->sc_rxlock);
749 749 sc->rx_queued = 0;
750 750 mutex_exit(&sc->sc_rxlock);
751 751
752 752 for (i = 0; i < ATU_RX_LIST_CNT; i++) {
753 753 err = atu_rx_trigger(sc);
754 754 if (err)
755 755 return (err);
756 756 }
757 757
758 758 return (0);
759 759 }
760 760
761 761 static void
762 762 atu_init_tx_queue(struct atu_softc *sc)
763 763 {
764 764 mutex_enter(&sc->sc_txlock);
765 765 sc->tx_queued = 0;
766 766 mutex_exit(&sc->sc_txlock);
767 767 }
768 768
769 769 static int
770 770 atu_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
771 771 {
772 772 struct atu_softc *sc = (struct atu_softc *)ic;
773 773 struct ieee80211_node *ni = NULL;
774 774 struct atu_tx_hdr *desc;
775 775 struct ieee80211_frame *wh;
776 776 mblk_t *m;
777 777 int pktlen = msgdsize(mp), err = 0;
778 778
779 779 mutex_enter(&sc->sc_txlock);
780 780 if (sc->tx_queued > ATU_TX_LIST_CNT) {
781 781 sc->sc_tx_nobuf++;
782 782 mutex_exit(&sc->sc_txlock);
783 783 err = ENOMEM;
784 784 goto fail;
785 785 }
786 786 mutex_exit(&sc->sc_txlock);
787 787
788 788 m = allocb(ATU_TX_BUFSZ, BPRI_MED);
789 789 if (m == NULL) {
790 790 sc->sc_tx_nobuf++;
791 791 err = ENOMEM;
792 792 goto fail;
793 793 }
794 794 /* reserve tx header space */
795 795 m->b_rptr += ATU_TX_HDRLEN;
796 796 m->b_wptr += ATU_TX_HDRLEN;
797 797
798 798 /* copy and (implicitly) free old data */
799 799 mcopymsg(mp, m->b_wptr);
800 800 m->b_wptr += pktlen;
801 801 wh = (struct ieee80211_frame *)m->b_rptr;
802 802
803 803 ni = ieee80211_find_txnode(ic, wh->i_addr1);
804 804 if (ni == NULL) {
805 805 ic->ic_stats.is_tx_failed++;
806 806 freemsg(m);
807 807 err = ENXIO;
808 808 goto fail;
809 809 }
810 810
811 811 if (type == IEEE80211_FC0_TYPE_DATA)
812 812 (void) ieee80211_encap(ic, m, ni);
813 813
814 814 /* full WEP in device, prune WEP fields (IV, KID) */
815 815 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
816 816 (void) memmove(m->b_rptr + IEEE80211_WEP_IVLEN
817 817 + IEEE80211_WEP_KIDLEN, m->b_rptr,
818 818 sizeof (struct ieee80211_frame));
819 819 m->b_rptr += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
820 820 }
821 821 pktlen = msgdsize(m);
822 822 m->b_rptr -= ATU_TX_HDRLEN;
823 823
824 824 /* setup tx header */
825 825 desc = (struct atu_tx_hdr *)m->b_rptr;
826 826 bzero(desc, ATU_TX_HDRLEN);
827 827 desc->length = (uint16_t)pktlen;
828 828 desc->tx_rate = ATU_DEF_TX_RATE;
829 829
830 830 err = atu_tx_trigger(sc, m);
831 831 if (!err) {
832 832 ic->ic_stats.is_tx_frags++;
833 833 ic->ic_stats.is_tx_bytes += pktlen;
834 834 } else {
835 835 ic->ic_stats.is_tx_failed++;
836 836 freemsg(m);
837 837 }
838 838 fail:
839 839 if (ni != NULL)
840 840 ieee80211_free_node(ni);
841 841
842 842 return (err);
843 843 }
844 844
845 845 static int
846 846 atu_stop(struct atu_softc *sc)
847 847 {
848 848 sc->sc_flags &= ~ATU_FLAG_RUNNING;
849 849 atu_close_pipes(sc);
850 850
851 851 return (atu_switch_radio(sc, B_FALSE));
852 852 }
853 853
854 854 static int
855 855 atu_init(struct atu_softc *sc)
856 856 {
857 857 int err;
858 858
859 859 err = atu_stop(sc);
860 860 if (err)
861 861 return (err);
862 862
863 863 err = atu_open_pipes(sc);
864 864 if (err)
865 865 goto fail;
866 866
867 867 err = atu_config(sc);
868 868 if (err) {
869 869 cmn_err(CE_WARN, "%s: startup config failed\n",
870 870 sc->sc_name);
871 871 goto fail;
872 872 }
873 873
874 874 atu_init_tx_queue(sc);
875 875
876 876 err = atu_init_rx_queue(sc);
877 877 if (err) {
878 878 cmn_err(CE_WARN, "%s: rx queue init failed\n", sc->sc_name);
879 879 goto fail;
880 880 }
881 881
882 882 sc->sc_flags |= ATU_FLAG_RUNNING;
883 883
884 884 return (0);
885 885 fail:
886 886 (void) atu_stop(sc);
887 887 return (err);
888 888 }
889 889
890 890 static void
891 891 atu_watchdog(void *arg)
892 892 {
893 893 struct atu_softc *sc = arg;
894 894 struct ieee80211com *ic = &sc->sc_ic;
895 895
896 896 ieee80211_stop_watchdog(ic);
897 897
898 898 ATU_LOCK(sc);
899 899 if (!ATU_RUNNING(sc)) {
900 900 ATU_UNLOCK(sc);
901 901 return;
902 902 }
903 903
904 904 ATU_UNLOCK(sc);
905 905 switch (ic->ic_state) {
906 906 case IEEE80211_S_AUTH:
907 907 case IEEE80211_S_ASSOC:
908 908 if (ic->ic_bss->in_fails > 0)
909 909 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
910 910 else
911 911 ieee80211_watchdog(ic);
912 912 break;
913 913 }
914 914 }
915 915
916 916 static int
917 917 atu_dfu_stage1(void *arg)
918 918 {
919 919 struct atu_softc *sc = arg;
920 920 uint8_t state, *ptr = NULL, status[6];
921 921 int block_size, bytes_left = 0, block = 0, err, i, count = 0;
922 922
923 923 /*
924 924 * Uploading firmware is done with the DFU (Device Firmware Upgrade)
925 925 * interface. See "Universal Serial Bus - Device Class Specification
926 926 * for Device Firmware Upgrade" pdf for details of the protocol.
927 927 * Maybe this could be moved to a separate 'firmware driver' once more
928 928 * device drivers need it... For now we'll just do it here.
929 929 *
930 930 * Just for your information, the Atmel's DFU descriptor looks like
931 931 * this:
932 932 *
933 933 * 07 size
934 934 * 21 type
935 935 * 01 capabilities : only firmware download, *need* reset
936 936 * after download
937 937 * 13 05 detach timeout : max 1299ms between DFU_DETACH and
938 938 * reset
939 939 * 00 04 max bytes of firmware per transaction : 1024
940 940 */
941 941 for (i = 0; i < sizeof (atu_fw_table) / sizeof (atu_fw_table[0]); i++)
942 942 if (sc->sc_radio == atu_fw_table[i].atur_type) {
943 943 ptr = atu_fw_table[i].atur_int;
944 944 bytes_left = atu_fw_table[i].atur_int_size;
945 945 }
946 946
947 947 state = atu_get_dfu_state(sc);
948 948 while (block >= 0 && state > 0) {
949 949 switch (state) {
950 950 case DFUState_DnLoadSync:
951 951 /* get DFU status */
952 952 err = atu_usb_request(sc, DFU_GETSTATUS, 0, 0, 6,
953 953 status);
954 954 if (err) {
955 955 cmn_err(CE_WARN, "%s: DFU get status failed\n",
956 956 sc->sc_name);
957 957 return (err);
958 958 }
959 959 /* success means state => DnLoadIdle */
960 960 state = DFUState_DnLoadIdle;
961 961 continue;
962 962
963 963 case DFUState_DFUIdle:
964 964 case DFUState_DnLoadIdle:
965 965 if (bytes_left >= DFU_MaxBlockSize)
966 966 block_size = DFU_MaxBlockSize;
967 967 else
968 968 block_size = bytes_left;
969 969
970 970 err = atu_usb_request(sc, DFU_DNLOAD, block++, 0,
971 971 block_size, ptr);
972 972 if (err) {
973 973 cmn_err(CE_WARN, "%s: DFU download failed\n",
974 974 sc->sc_name);
975 975 return (err);
976 976 }
977 977
978 978 ptr += block_size;
979 979 bytes_left -= block_size;
980 980 if (block_size == 0)
981 981 block = -1;
982 982 break;
983 983
984 984 case DFUState_DFUError:
985 985 cmn_err(CE_WARN, "%s: DFU state error\n", sc->sc_name);
986 986 return (EIO);
987 987
988 988 default:
989 989 drv_usecwait(10*1000);
990 990 if (++count > 100) {
991 991 cmn_err(CE_WARN, "%s: DFU timeout\n",
992 992 sc->sc_name);
993 993 return (ETIME);
994 994 }
995 995 break;
996 996 }
997 997
998 998 state = atu_get_dfu_state(sc);
999 999 }
1000 1000 if (state != DFUState_ManifestSync)
1001 1001 cmn_err(CE_WARN, "%s: DFU state (%d) != ManifestSync\n",
1002 1002 sc->sc_name, state);
1003 1003
1004 1004 err = atu_usb_request(sc, DFU_GETSTATUS, 0, 0, 6, status);
1005 1005 if (err) {
1006 1006 cmn_err(CE_WARN, "%s: DFU get status failed\n",
1007 1007 sc->sc_name);
1008 1008 return (err);
1009 1009 }
1010 1010
1011 1011 err = atu_usb_request(sc, DFU_REMAP, 0, 0, 0, NULL);
1012 1012 if (err && !(sc->sc_quirk & ATU_QUIRK_NO_REMAP)) {
1013 1013 cmn_err(CE_WARN, "%s: DFU remap failed\n", sc->sc_name);
1014 1014 return (err);
1015 1015 }
1016 1016
1017 1017 /*
1018 1018 * after a lot of trying and measuring I found out the device needs
1019 1019 * about 56 miliseconds after sending the remap command before
1020 1020 * it's ready to communicate again. So we'll wait just a little bit
1021 1021 * longer than that to be sure...
1022 1022 */
1023 1023 drv_usecwait((56+100)*1000);
1024 1024
1025 1025 return (0);
1026 1026 }
1027 1027
1028 1028 static int
1029 1029 atu_dfu_stage2(void *arg)
1030 1030 {
1031 1031 struct atu_softc *sc = arg;
1032 1032 uint8_t *ptr = NULL;
1033 1033 int block_size, bytes_left = 0, block = 0, err, i;
1034 1034
1035 1035 for (i = 0; i < sizeof (atu_fw_table) / sizeof (atu_fw_table[0]); i++)
1036 1036 if (sc->sc_radio == atu_fw_table[i].atur_type) {
1037 1037 ptr = atu_fw_table[i].atur_ext;
1038 1038 bytes_left = atu_fw_table[i].atur_ext_size;
1039 1039 }
1040 1040
1041 1041 while (bytes_left) {
1042 1042 if (bytes_left > 1024)
1043 1043 block_size = 1024;
1044 1044 else
1045 1045 block_size = bytes_left;
1046 1046
1047 1047 err = atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e,
1048 1048 0x0802, block, block_size, ptr);
1049 1049 if (err) {
1050 1050 cmn_err(CE_WARN, "%s: stage2 firmware load failed\n",
1051 1051 sc->sc_name);
1052 1052 return (err);
1053 1053 }
1054 1054
1055 1055 ptr += block_size;
1056 1056 block++;
1057 1057 bytes_left -= block_size;
1058 1058 }
1059 1059
1060 1060 err = atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e, 0x0802,
1061 1061 block, 0, NULL);
1062 1062 if (err) {
1063 1063 cmn_err(CE_WARN, "%s: zero-length block load failed\n",
1064 1064 sc->sc_name);
1065 1065 return (err);
1066 1066 }
1067 1067
1068 1068 /*
1069 1069 * The SMC2662w V.4 seems to require some time to do its thing with
1070 1070 * the stage2 firmware... 20 ms isn't enough, but 21 ms works 100
1071 1071 * times out of 100 tries. We'll wait a bit longer just to be sure
1072 1072 */
1073 1073 if (sc->sc_quirk & ATU_QUIRK_FW_DELAY)
1074 1074 drv_usecwait((21 + 100) * 1000);
1075 1075
1076 1076 return (0);
1077 1077 }
1078 1078
1079 1079 static int
1080 1080 atu_load_microcode(struct atu_softc *sc, boolean_t attach)
1081 1081 {
1082 1082 usb_dev_reset_lvl_t reset;
1083 1083 uint8_t mode, chan;
1084 1084 int err;
1085 1085
1086 1086 reset = attach ? USB_RESET_LVL_REATTACH : USB_RESET_LVL_DEFAULT;
1087 1087
1088 1088 err = atu_get_opmode(sc, &mode);
1089 1089 if (!err) {
1090 1090 if (mode == ATU_DEV_READY)
1091 1091 return (0);
1092 1092 /*
1093 1093 * Opmode of SMC2662 V.4 does not change after stage2
1094 1094 * firmware download. If succeeded reading the channel
1095 1095 * number, stage2 firmware is already running.
1096 1096 */
1097 1097 if (sc->sc_radio != RadioIntersil &&
1098 1098 atu_get_mib(sc, MIB_PHY_CHANNEL, &chan) == 0)
1099 1099 return (0);
1100 1100
1101 1101 if (mode == ATU_DEV_STAGE2)
1102 1102 stage2:
1103 1103 return (atu_dfu_stage2(sc));
1104 1104 }
1105 1105
1106 1106 err = atu_dfu_stage1(sc);
1107 1107 if (err)
1108 1108 return (err);
1109 1109
1110 1110 if (usb_reset_device(sc->sc_dip, reset) != USB_SUCCESS)
1111 1111 return (EIO);
1112 1112
1113 1113 if (attach)
1114 1114 return (EAGAIN);
1115 1115 else
1116 1116 goto stage2;
1117 1117 }
1118 1118
1119 1119 static int
1120 1120 atu_disconnect(dev_info_t *dip)
1121 1121 {
1122 1122 struct atu_softc *sc;
1123 1123 struct ieee80211com *ic;
1124 1124
1125 1125 sc = ddi_get_soft_state(atu_soft_state_p, ddi_get_instance(dip));
1126 1126 ic = &sc->sc_ic;
1127 1127
1128 1128 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1129 1129 ieee80211_stop_watchdog(ic);
1130 1130
1131 1131 ATU_LOCK(sc);
1132 1132 if (sc->sc_scan_timer != 0) {
1133 1133 ATU_UNLOCK(sc);
1134 1134 (void) untimeout(sc->sc_scan_timer);
1135 1135 ATU_LOCK(sc);
1136 1136 sc->sc_scan_timer = 0;
1137 1137 }
1138 1138
1139 1139 sc->sc_flags &= ~(ATU_FLAG_RUNNING | ATU_FLAG_RADIO_ON);
1140 1140 atu_close_pipes(sc);
1141 1141
1142 1142 ATU_UNLOCK(sc);
1143 1143 return (0);
1144 1144 }
1145 1145
1146 1146 static int
1147 1147 atu_reconnect(dev_info_t *dip)
1148 1148 {
1149 1149 struct atu_softc *sc;
1150 1150 int err;
1151 1151
1152 1152 sc = ddi_get_soft_state(atu_soft_state_p, ddi_get_instance(dip));
1153 1153 if (usb_check_same_device(sc->sc_dip, NULL, USB_LOG_L2, -1,
1154 1154 USB_CHK_BASIC, NULL) != USB_SUCCESS)
1155 1155 return (DDI_FAILURE);
1156 1156
1157 1157 ATU_LOCK(sc);
1158 1158 err = atu_load_microcode(sc, B_FALSE);
1159 1159 if (!err)
1160 1160 err = atu_init(sc);
1161 1161
1162 1162 ATU_UNLOCK(sc);
1163 1163 return (err ? DDI_FAILURE : DDI_SUCCESS);
1164 1164 }
1165 1165
1166 1166 static int
1167 1167 atu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1168 1168 {
1169 1169 struct atu_softc *sc;
1170 1170 struct ieee80211com *ic;
1171 1171 mac_register_t *macp;
1172 1172 wifi_data_t wd = {0};
1173 1173 int instance, i, err;
1174 1174
1175 1175 switch (cmd) {
1176 1176 case DDI_ATTACH:
1177 1177 break;
1178 1178 case DDI_RESUME:
1179 1179 sc = ddi_get_soft_state(atu_soft_state_p,
1180 1180 ddi_get_instance(dip));
1181 1181 if (usb_check_same_device(sc->sc_dip, NULL, USB_LOG_L2, -1,
1182 1182 USB_CHK_BASIC, NULL) != USB_SUCCESS)
1183 1183 return (DDI_SUCCESS);
1184 1184
1185 1185 if (atu_load_microcode(sc, B_FALSE) == 0)
1186 1186 (void) atu_init(sc);
1187 1187
1188 1188 return (DDI_SUCCESS);
1189 1189 default:
1190 1190 return (DDI_FAILURE);
1191 1191 }
1192 1192
1193 1193 instance = ddi_get_instance(dip);
1194 1194 if (ddi_soft_state_zalloc(atu_soft_state_p, instance) != DDI_SUCCESS)
1195 1195 return (DDI_FAILURE);
1196 1196
1197 1197 sc = ddi_get_soft_state(atu_soft_state_p, instance);
1198 1198 ic = &sc->sc_ic;
1199 1199 sc->sc_dip = dip;
1200 1200
1201 1201 (void) snprintf(sc->sc_name, sizeof (sc->sc_name), "%s%d",
1202 1202 "atu", instance);
1203 1203
1204 1204 err = usb_client_attach(dip, USBDRV_VERSION, 0);
1205 1205 if (err != USB_SUCCESS)
1206 1206 goto fail1;
1207 1207
1208 1208 err = usb_get_dev_data(dip, &sc->sc_udev, USB_PARSE_LVL_ALL, 0);
1209 1209 if (err != USB_SUCCESS) {
1210 1210 sc->sc_udev = NULL;
1211 1211 goto fail2;
1212 1212 }
1213 1213
1214 1214 for (i = 0; i < sizeof (atu_dev_table)/sizeof (atu_dev_table[0]); i++) {
1215 1215 struct atu_dev_type *t = &atu_dev_table[i];
1216 1216 if (sc->sc_udev->dev_descr->idVendor == t->atu_vid &&
1217 1217 sc->sc_udev->dev_descr->idProduct == t->atu_pid) {
1218 1218 sc->sc_radio = t->atu_radio;
1219 1219 sc->sc_quirk = t->atu_quirk;
1220 1220 }
1221 1221 }
1222 1222
1223 1223 err = atu_load_microcode(sc, B_TRUE);
1224 1224 if (err == EAGAIN) {
1225 1225 sc->sc_flags |= ATU_FLAG_REATTACH; /* reattaching */
1226 1226 return (DDI_SUCCESS);
1227 1227 } else if (err) {
1228 1228 goto fail2;
1229 1229 }
1230 1230 sc->sc_flags &= ~ATU_FLAG_REATTACH;
1231 1231
1232 1232 /* read device config & MAC address */
1233 1233 err = atu_get_config(sc);
1234 1234 if (err) {
1235 1235 cmn_err(CE_WARN, "%s: read device config failed\n",
1236 1236 sc->sc_name);
1237 1237 goto fail2;
1238 1238 }
1239 1239
1240 1240 mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL);
1241 1241 mutex_init(&sc->sc_txlock, NULL, MUTEX_DRIVER, NULL);
1242 1242 mutex_init(&sc->sc_rxlock, NULL, MUTEX_DRIVER, NULL);
1243 1243
1244 1244 ic->ic_phytype = IEEE80211_T_DS;
1245 1245 ic->ic_opmode = IEEE80211_M_STA;
1246 1246 ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_WEP;
1247 1247 ic->ic_sup_rates[IEEE80211_MODE_11B] = atu_rateset;
1248 1248 ic->ic_maxrssi = atu_fw_table[sc->sc_radio].max_rssi;
1249 1249 ic->ic_state = IEEE80211_S_INIT;
1250 1250 for (i = 1; i <= 14; i++) {
1251 1251 ic->ic_sup_channels[i].ich_freq =
1252 1252 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
1253 1253 ic->ic_sup_channels[i].ich_flags =
1254 1254 IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ |
1255 1255 IEEE80211_CHAN_PASSIVE;
1256 1256 }
1257 1257 ic->ic_xmit = atu_send;
1258 1258 ieee80211_attach(ic);
1259 1259
1260 1260 sc->sc_newstate = ic->ic_newstate;
1261 1261 ic->ic_newstate = atu_newstate;
1262 1262 ic->ic_watchdog = atu_watchdog;
1263 1263 ieee80211_media_init(ic);
1264 1264
1265 1265 ic->ic_def_txkey = 0;
1266 1266 wd.wd_opmode = ic->ic_opmode;
1267 1267 wd.wd_secalloc = WIFI_SEC_NONE;
1268 1268 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
1269 1269
1270 1270 macp = mac_alloc(MAC_VERSION);
1271 1271 if (macp == NULL)
1272 1272 goto fail3;
1273 1273
1274 1274 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
1275 1275 macp->m_driver = sc;
1276 1276 macp->m_dip = dip;
1277 1277 macp->m_src_addr = ic->ic_macaddr;
1278 1278 macp->m_callbacks = &atu_m_callbacks;
1279 1279 macp->m_min_sdu = 0;
1280 1280 macp->m_max_sdu = IEEE80211_MTU;
1281 1281 macp->m_pdata = &wd;
1282 1282 macp->m_pdata_size = sizeof (wd);
1283 1283
1284 1284 err = mac_register(macp, &ic->ic_mach);
1285 1285 mac_free(macp);
1286 1286 if (err)
1287 1287 goto fail3;
1288 1288
1289 1289 err = usb_register_hotplug_cbs(sc->sc_dip, atu_disconnect,
1290 1290 atu_reconnect);
1291 1291 if (err != USB_SUCCESS)
1292 1292 goto fail4;
1293 1293
1294 1294 err = ddi_create_minor_node(dip, sc->sc_name, S_IFCHR,
1295 1295 instance + 1, DDI_NT_NET_WIFI, 0);
1296 1296 if (err != DDI_SUCCESS)
1297 1297 cmn_err(CE_WARN, "%s: minor node creation failed\n",
1298 1298 sc->sc_name);
1299 1299
1300 1300 mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
1301 1301 return (DDI_SUCCESS);
1302 1302
1303 1303 fail4:
1304 1304 (void) mac_unregister(ic->ic_mach);
1305 1305 fail3:
1306 1306 mutex_destroy(&sc->sc_genlock);
1307 1307 mutex_destroy(&sc->sc_rxlock);
1308 1308 mutex_destroy(&sc->sc_txlock);
1309 1309 fail2:
1310 1310 usb_client_detach(sc->sc_dip, sc->sc_udev);
1311 1311 fail1:
1312 1312 ddi_soft_state_free(atu_soft_state_p, instance);
1313 1313
1314 1314 return (DDI_FAILURE);
1315 1315 }
1316 1316
1317 1317 static int
1318 1318 atu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1319 1319 {
1320 1320 struct atu_softc *sc;
1321 1321 int err;
1322 1322
1323 1323 sc = ddi_get_soft_state(atu_soft_state_p, ddi_get_instance(dip));
1324 1324
1325 1325 switch (cmd) {
1326 1326 case DDI_DETACH:
1327 1327 break;
1328 1328 case DDI_SUSPEND:
1329 1329 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
1330 1330 ieee80211_stop_watchdog(&sc->sc_ic);
1331 1331
1332 1332 ATU_LOCK(sc);
1333 1333 if (sc->sc_scan_timer != 0) {
1334 1334 ATU_UNLOCK(sc);
1335 1335 (void) untimeout(sc->sc_scan_timer);
1336 1336 ATU_LOCK(sc);
1337 1337 sc->sc_scan_timer = 0;
1338 1338 }
1339 1339 (void) atu_stop(sc);
1340 1340
1341 1341 ATU_UNLOCK(sc);
1342 1342 return (DDI_SUCCESS);
1343 1343 default:
1344 1344 return (DDI_FAILURE);
1345 1345 }
1346 1346
1347 1347 if (!ATU_REATTACH(sc)) {
1348 1348 err = mac_disable(sc->sc_ic.ic_mach);
1349 1349 if (err)
1350 1350 return (DDI_FAILURE);
1351 1351
1352 1352 (void) atu_stop(sc);
1353 1353
1354 1354 usb_unregister_hotplug_cbs(dip);
1355 1355 (void) mac_unregister(sc->sc_ic.ic_mach);
1356 1356 ieee80211_detach(&sc->sc_ic);
1357 1357
1358 1358 mutex_destroy(&sc->sc_genlock);
1359 1359 mutex_destroy(&sc->sc_txlock);
1360 1360 mutex_destroy(&sc->sc_rxlock);
1361 1361
1362 1362 ddi_remove_minor_node(dip, NULL);
1363 1363 }
1364 1364
1365 1365 usb_client_detach(dip, sc->sc_udev);
1366 1366 ddi_soft_state_free(atu_soft_state_p, ddi_get_instance(dip));
1367 1367
1368 1368 return (DDI_SUCCESS);
1369 1369 }
1370 1370
1371 1371 DDI_DEFINE_STREAM_OPS(atu_dev_ops, nulldev, nulldev, atu_attach,
↓ open down ↓ |
1371 lines elided |
↑ open up ↑ |
1372 1372 atu_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed);
1373 1373
1374 1374 static struct modldrv atu_modldrv = {
1375 1375 &mod_driverops,
1376 1376 "atu driver v1.1",
1377 1377 &atu_dev_ops
1378 1378 };
1379 1379
1380 1380 static struct modlinkage modlinkage = {
1381 1381 MODREV_1,
1382 - (void *)&atu_modldrv,
1383 - NULL
1382 + { (void *)&atu_modldrv, NULL }
1384 1383 };
1385 1384
1386 1385 int
1387 1386 _info(struct modinfo *modinfop)
1388 1387 {
1389 1388 return (mod_info(&modlinkage, modinfop));
1390 1389 }
1391 1390
1392 1391 int
1393 1392 _init(void)
1394 1393 {
1395 1394 int status;
1396 1395
1397 1396 status = ddi_soft_state_init(&atu_soft_state_p,
1398 1397 sizeof (struct atu_softc), 1);
1399 1398 if (status != 0)
1400 1399 return (status);
1401 1400
1402 1401 mac_init_ops(&atu_dev_ops, "atu");
1403 1402 status = mod_install(&modlinkage);
1404 1403 if (status != 0) {
1405 1404 mac_fini_ops(&atu_dev_ops);
1406 1405 ddi_soft_state_fini(&atu_soft_state_p);
1407 1406 }
1408 1407 return (status);
1409 1408 }
1410 1409
1411 1410 int
1412 1411 _fini(void)
1413 1412 {
1414 1413 int status;
1415 1414
1416 1415 status = mod_remove(&modlinkage);
1417 1416 if (status == 0) {
1418 1417 mac_fini_ops(&atu_dev_ops);
1419 1418 ddi_soft_state_fini(&atu_soft_state_p);
1420 1419 }
1421 1420 return (status);
1422 1421 }
1423 1422
1424 1423 static int
1425 1424 atu_m_start(void *arg)
1426 1425 {
1427 1426 struct atu_softc *sc = (struct atu_softc *)arg;
1428 1427 int err;
1429 1428
1430 1429 ATU_LOCK(sc);
1431 1430 err = atu_init(sc);
1432 1431
1433 1432 ATU_UNLOCK(sc);
1434 1433 return (err);
1435 1434 }
1436 1435
1437 1436 static void
1438 1437 atu_m_stop(void *arg)
1439 1438 {
1440 1439 struct atu_softc *sc = (struct atu_softc *)arg;
1441 1440 struct ieee80211com *ic = &sc->sc_ic;
1442 1441
1443 1442 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1444 1443 ieee80211_stop_watchdog(ic);
1445 1444
1446 1445 ATU_LOCK(sc);
1447 1446 if (sc->sc_scan_timer != 0) {
1448 1447 ATU_UNLOCK(sc);
1449 1448 (void) untimeout(sc->sc_scan_timer);
1450 1449 ATU_LOCK(sc);
1451 1450 sc->sc_scan_timer = 0;
1452 1451 }
1453 1452 (void) atu_stop(sc);
1454 1453
1455 1454 ATU_UNLOCK(sc);
1456 1455 }
1457 1456
1458 1457 /*ARGSUSED*/
1459 1458 static int
1460 1459 atu_m_unicst(void *arg, const uint8_t *macaddr)
1461 1460 {
1462 1461 return (ENOTSUP);
1463 1462 }
1464 1463
1465 1464 /*ARGSUSED*/
1466 1465 static int
1467 1466 atu_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
1468 1467 {
1469 1468 return (ENOTSUP);
1470 1469 }
1471 1470
1472 1471 /*ARGSUSED*/
1473 1472 static int
1474 1473 atu_m_promisc(void *arg, boolean_t on)
1475 1474 {
1476 1475 return (0);
1477 1476 }
1478 1477
1479 1478 static int
1480 1479 atu_m_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t len,
1481 1480 const void *buf)
1482 1481 {
1483 1482 struct atu_softc *sc = (struct atu_softc *)arg;
1484 1483 struct ieee80211com *ic = &sc->sc_ic;
1485 1484 int err;
1486 1485
1487 1486 err = ieee80211_setprop(ic, name, id, len, buf);
1488 1487 if (err != ENETRESET)
1489 1488 return (err);
1490 1489 if (ic->ic_des_esslen == 0)
1491 1490 return (0);
1492 1491
1493 1492 ATU_LOCK(sc);
1494 1493 if (ATU_RUNNING(sc)) {
1495 1494 if (sc->sc_scan_timer != 0) {
1496 1495 ATU_UNLOCK(sc);
1497 1496 (void) untimeout(sc->sc_scan_timer);
1498 1497 ATU_LOCK(sc);
1499 1498 sc->sc_scan_timer = 0;
1500 1499 }
1501 1500 err = atu_init(sc);
1502 1501
1503 1502 ATU_UNLOCK(sc);
1504 1503 if (err)
1505 1504 return (err);
1506 1505 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
1507 1506 ATU_LOCK(sc);
1508 1507 }
1509 1508
1510 1509 ATU_UNLOCK(sc);
1511 1510 return (0);
1512 1511 }
1513 1512
1514 1513 static int
1515 1514 atu_m_getprop(void *arg, const char *name, mac_prop_id_t id,
1516 1515 uint_t length, void *buf)
1517 1516 {
1518 1517 struct atu_softc *sc = (struct atu_softc *)arg;
1519 1518 struct ieee80211com *ic = &sc->sc_ic;
1520 1519
1521 1520 return (ieee80211_getprop(ic, name, id, length, buf));
1522 1521 }
1523 1522
1524 1523 static void
1525 1524 atu_m_propinfo(void *arg, const char *name, mac_prop_id_t id,
1526 1525 mac_prop_info_handle_t mph)
1527 1526 {
1528 1527 struct atu_softc *sc = (struct atu_softc *)arg;
1529 1528 struct ieee80211com *ic = &sc->sc_ic;
1530 1529
1531 1530 ieee80211_propinfo(ic, name, id, mph);
1532 1531 }
1533 1532
1534 1533 static void
1535 1534 atu_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
1536 1535 {
1537 1536 struct atu_softc *sc = (struct atu_softc *)arg;
1538 1537 struct ieee80211com *ic = &sc->sc_ic;
1539 1538 int err;
1540 1539
1541 1540 err = ieee80211_ioctl(ic, wq, mp);
1542 1541 if (err != ENETRESET || ic->ic_des_esslen == 0)
1543 1542 return;
1544 1543
1545 1544 ATU_LOCK(sc);
1546 1545 if (ATU_RUNNING(sc)) {
1547 1546 if (sc->sc_scan_timer != 0) {
1548 1547 ATU_UNLOCK(sc);
1549 1548 (void) untimeout(sc->sc_scan_timer);
1550 1549 ATU_LOCK(sc);
1551 1550 sc->sc_scan_timer = 0;
1552 1551 }
1553 1552 err = atu_init(sc);
1554 1553
1555 1554 ATU_UNLOCK(sc);
1556 1555 if (err)
1557 1556 return;
1558 1557 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
1559 1558 ATU_LOCK(sc);
1560 1559 }
1561 1560
1562 1561 ATU_UNLOCK(sc);
1563 1562 }
1564 1563
1565 1564 static mblk_t *
1566 1565 atu_m_tx(void *arg, mblk_t *mp)
1567 1566 {
1568 1567 struct atu_softc *sc = (struct atu_softc *)arg;
1569 1568 struct ieee80211com *ic = &sc->sc_ic;
1570 1569 mblk_t *next;
1571 1570
1572 1571 if (ic->ic_state != IEEE80211_S_RUN) {
1573 1572 freemsgchain(mp);
1574 1573 return (NULL);
1575 1574 }
1576 1575
1577 1576 while (mp != NULL) {
1578 1577 next = mp->b_next;
1579 1578 mp->b_next = NULL;
1580 1579 if (atu_send(ic, mp, IEEE80211_FC0_TYPE_DATA) == ENOMEM) {
1581 1580 mutex_enter(&sc->sc_txlock);
1582 1581 sc->sc_need_sched = 1;
1583 1582 mutex_exit(&sc->sc_txlock);
1584 1583
1585 1584 mp->b_next = next;
1586 1585 return (mp);
1587 1586 }
1588 1587 mp = next;
1589 1588 }
1590 1589
1591 1590 return (mp);
1592 1591 }
1593 1592
1594 1593 static int
1595 1594 atu_m_stat(void *arg, uint_t stat, uint64_t *val)
1596 1595 {
1597 1596 struct atu_softc *sc = (struct atu_softc *)arg;
1598 1597 ieee80211com_t *ic = &sc->sc_ic;
1599 1598 ieee80211_node_t *in;
1600 1599
1601 1600 ATU_LOCK(sc);
1602 1601 switch (stat) {
1603 1602 case MAC_STAT_IFSPEED:
1604 1603 in = ic->ic_bss;
1605 1604 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
1606 1605 IEEE80211_RATE(in->in_txrate) :
1607 1606 ic->ic_fixed_rate) / 2 * 1000000;
1608 1607 break;
1609 1608 case MAC_STAT_NOXMTBUF:
1610 1609 *val = sc->sc_tx_nobuf;
1611 1610 break;
1612 1611 case MAC_STAT_NORCVBUF:
1613 1612 *val = sc->sc_rx_nobuf;
1614 1613 break;
1615 1614 case MAC_STAT_IERRORS:
1616 1615 *val = sc->sc_rx_err;
1617 1616 break;
1618 1617 case MAC_STAT_RBYTES:
1619 1618 *val = ic->ic_stats.is_rx_bytes;
1620 1619 break;
1621 1620 case MAC_STAT_IPACKETS:
1622 1621 *val = ic->ic_stats.is_rx_frags;
1623 1622 break;
1624 1623 case MAC_STAT_OBYTES:
1625 1624 *val = ic->ic_stats.is_tx_bytes;
1626 1625 break;
1627 1626 case MAC_STAT_OPACKETS:
1628 1627 *val = ic->ic_stats.is_tx_frags;
1629 1628 break;
1630 1629 case MAC_STAT_OERRORS:
1631 1630 *val = ic->ic_stats.is_tx_failed;
1632 1631 break;
1633 1632 case WIFI_STAT_TX_FRAGS:
1634 1633 case WIFI_STAT_MCAST_TX:
1635 1634 case WIFI_STAT_TX_FAILED:
1636 1635 case WIFI_STAT_TX_RETRANS:
1637 1636 case WIFI_STAT_TX_RERETRANS:
1638 1637 case WIFI_STAT_RTS_SUCCESS:
1639 1638 case WIFI_STAT_RTS_FAILURE:
1640 1639 case WIFI_STAT_ACK_FAILURE:
1641 1640 case WIFI_STAT_RX_FRAGS:
1642 1641 case WIFI_STAT_MCAST_RX:
1643 1642 case WIFI_STAT_FCS_ERRORS:
1644 1643 case WIFI_STAT_WEP_ERRORS:
1645 1644 case WIFI_STAT_RX_DUPS:
1646 1645 ATU_UNLOCK(sc);
1647 1646 return (ieee80211_stat(ic, stat, val));
1648 1647 default:
1649 1648 ATU_UNLOCK(sc);
1650 1649 return (ENOTSUP);
1651 1650 }
1652 1651
1653 1652 ATU_UNLOCK(sc);
1654 1653 return (0);
1655 1654 }
1656 1655
1657 1656 static mac_callbacks_t atu_m_callbacks = {
1658 1657 MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
1659 1658 atu_m_stat,
1660 1659 atu_m_start,
1661 1660 atu_m_stop,
1662 1661 atu_m_promisc,
1663 1662 atu_m_multicst,
1664 1663 atu_m_unicst,
1665 1664 atu_m_tx,
1666 1665 NULL,
1667 1666 atu_m_ioctl,
1668 1667 NULL,
1669 1668 NULL,
1670 1669 NULL,
1671 1670 atu_m_setprop,
1672 1671 atu_m_getprop,
1673 1672 atu_m_propinfo
1674 1673 };
↓ open down ↓ |
281 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX