7127  remove -Wno-missing-braces from Makefile.uts

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

1383 };
1384 
1385 int
1386 _info(struct modinfo *modinfop)
1387 {
1388         return (mod_info(&modlinkage, modinfop));
1389 }
1390 
1391 int
1392 _init(void)
1393 {
1394         int status;
1395 
1396         status = ddi_soft_state_init(&atu_soft_state_p,
1397             sizeof (struct atu_softc), 1);
1398         if (status != 0)
1399                 return (status);
1400 
1401         mac_init_ops(&atu_dev_ops, "atu");
1402         status = mod_install(&modlinkage);
1403         if (status != 0) {
1404                 mac_fini_ops(&atu_dev_ops);
1405                 ddi_soft_state_fini(&atu_soft_state_p);
1406         }
1407         return (status);
1408 }
1409 
1410 int
1411 _fini(void)
1412 {
1413         int status;
1414 
1415         status = mod_remove(&modlinkage);
1416         if (status == 0) {
1417                 mac_fini_ops(&atu_dev_ops);
1418                 ddi_soft_state_fini(&atu_soft_state_p);
1419         }
1420         return (status);
1421 }
1422 
1423 static int
1424 atu_m_start(void *arg)
1425 {
1426         struct atu_softc *sc = (struct atu_softc *)arg;
1427         int err;
1428 
1429         ATU_LOCK(sc);
1430         err = atu_init(sc);
1431 
1432         ATU_UNLOCK(sc);
1433         return (err);
1434 }
1435 
1436 static void
1437 atu_m_stop(void *arg)
1438 {
1439         struct atu_softc *sc = (struct atu_softc *)arg;
1440         struct ieee80211com *ic = &sc->sc_ic;
1441 
1442         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1443         ieee80211_stop_watchdog(ic);
1444 
1445         ATU_LOCK(sc);
1446         if (sc->sc_scan_timer != 0) {
1447                 ATU_UNLOCK(sc);
1448                 (void) untimeout(sc->sc_scan_timer);
1449                 ATU_LOCK(sc);
1450                 sc->sc_scan_timer = 0;
1451         }
1452         (void) atu_stop(sc);
1453 
1454         ATU_UNLOCK(sc);
1455 }
1456 
1457 /*ARGSUSED*/
1458 static int
1459 atu_m_unicst(void *arg, const uint8_t *macaddr)
1460 {
1461         return (ENOTSUP);
1462 }
1463 
1464 /*ARGSUSED*/
1465 static int
1466 atu_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
1467 {
1468         return (ENOTSUP);
1469 }
1470 
1471 /*ARGSUSED*/
1472 static int
1473 atu_m_promisc(void *arg, boolean_t on)
1474 {
1475         return (0);
1476 }
1477 
1478 static int
1479 atu_m_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t len,
1480     const void *buf)
1481 {
1482         struct atu_softc *sc = (struct atu_softc *)arg;
1483         struct ieee80211com *ic = &sc->sc_ic;
1484         int err;
1485 
1486         err = ieee80211_setprop(ic, name, id, len, buf);
1487         if (err != ENETRESET)
1488                 return (err);
1489         if (ic->ic_des_esslen == 0)
1490                 return (0);
1491 
1492         ATU_LOCK(sc);
1493         if (ATU_RUNNING(sc)) {
1494                 if (sc->sc_scan_timer != 0) {
1495                         ATU_UNLOCK(sc);
1496                         (void) untimeout(sc->sc_scan_timer);
1497                         ATU_LOCK(sc);
1498                         sc->sc_scan_timer = 0;
1499                 }
1500                 err = atu_init(sc);
1501 
1502                 ATU_UNLOCK(sc);
1503                 if (err)
1504                         return (err);
1505                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
1506                 ATU_LOCK(sc);
1507         }
1508 
1509         ATU_UNLOCK(sc);
1510         return (0);
1511 }
1512 
1513 static int
1514 atu_m_getprop(void *arg, const char *name, mac_prop_id_t id,
1515     uint_t length, void *buf)
1516 {
1517         struct atu_softc *sc = (struct atu_softc *)arg;
1518         struct ieee80211com *ic = &sc->sc_ic;
1519 
1520         return (ieee80211_getprop(ic, name, id, length, buf));
1521 }
1522 
1523 static void
1524 atu_m_propinfo(void *arg, const char *name, mac_prop_id_t id,
1525     mac_prop_info_handle_t mph)
1526 {
1527         struct atu_softc *sc = (struct atu_softc *)arg;
1528         struct ieee80211com *ic = &sc->sc_ic;
1529 
1530         ieee80211_propinfo(ic, name, id, mph);
1531 }
1532 
1533 static void
1534 atu_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
1535 {
1536         struct atu_softc *sc = (struct atu_softc *)arg;
1537         struct ieee80211com *ic = &sc->sc_ic;
1538         int err;
1539 
1540         err = ieee80211_ioctl(ic, wq, mp);
1541         if (err != ENETRESET || ic->ic_des_esslen == 0)
1542                 return;
1543 
1544         ATU_LOCK(sc);
1545         if (ATU_RUNNING(sc)) {
1546                 if (sc->sc_scan_timer != 0) {
1547                         ATU_UNLOCK(sc);
1548                         (void) untimeout(sc->sc_scan_timer);
1549                         ATU_LOCK(sc);
1550                         sc->sc_scan_timer = 0;
1551                 }
1552                 err = atu_init(sc);
1553 
1554                 ATU_UNLOCK(sc);
1555                 if (err)
1556                         return;
1557                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
1558                 ATU_LOCK(sc);
1559         }
1560 
1561         ATU_UNLOCK(sc);
1562 }
1563 
1564 static mblk_t *
1565 atu_m_tx(void *arg, mblk_t *mp)
1566 {
1567         struct atu_softc *sc = (struct atu_softc *)arg;
1568         struct ieee80211com *ic = &sc->sc_ic;
1569         mblk_t *next;
1570 
1571         if (ic->ic_state != IEEE80211_S_RUN) {
1572                 freemsgchain(mp);
1573                 return (NULL);
1574         }
1575 
1576         while (mp != NULL) {
1577                 next = mp->b_next;
1578                 mp->b_next = NULL;
1579                 if (atu_send(ic, mp, IEEE80211_FC0_TYPE_DATA) == ENOMEM) {
1580                         mutex_enter(&sc->sc_txlock);
1581                         sc->sc_need_sched = 1;
1582                         mutex_exit(&sc->sc_txlock);
1583 
1584                         mp->b_next = next;
1585                         return (mp);
1586                 }
1587                 mp = next;
1588         }
1589 
1590         return (mp);
1591 }
1592 
1593 static int
1594 atu_m_stat(void *arg, uint_t stat, uint64_t *val)
1595 {
1596         struct atu_softc        *sc  = (struct atu_softc *)arg;
1597         ieee80211com_t          *ic = &sc->sc_ic;
1598         ieee80211_node_t        *in;
1599 
1600         ATU_LOCK(sc);
1601         switch (stat) {
1602         case MAC_STAT_IFSPEED:
1603                 in = ic->ic_bss;
1604                 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
1605                     IEEE80211_RATE(in->in_txrate) :
1606                     ic->ic_fixed_rate) / 2 * 1000000;
1607                 break;
1608         case MAC_STAT_NOXMTBUF:
1609                 *val = sc->sc_tx_nobuf;
1610                 break;
1611         case MAC_STAT_NORCVBUF:
1612                 *val = sc->sc_rx_nobuf;
1613                 break;
1614         case MAC_STAT_IERRORS:
1615                 *val = sc->sc_rx_err;
1616                 break;
1617         case MAC_STAT_RBYTES:
1618                 *val = ic->ic_stats.is_rx_bytes;
1619                 break;
1620         case MAC_STAT_IPACKETS:
1621                 *val = ic->ic_stats.is_rx_frags;
1622                 break;
1623         case MAC_STAT_OBYTES:
1624                 *val = ic->ic_stats.is_tx_bytes;
1625                 break;
1626         case MAC_STAT_OPACKETS:
1627                 *val = ic->ic_stats.is_tx_frags;
1628                 break;
1629         case MAC_STAT_OERRORS:
1630                 *val = ic->ic_stats.is_tx_failed;
1631                 break;
1632         case WIFI_STAT_TX_FRAGS:
1633         case WIFI_STAT_MCAST_TX:
1634         case WIFI_STAT_TX_FAILED:
1635         case WIFI_STAT_TX_RETRANS:
1636         case WIFI_STAT_TX_RERETRANS:
1637         case WIFI_STAT_RTS_SUCCESS:
1638         case WIFI_STAT_RTS_FAILURE:
1639         case WIFI_STAT_ACK_FAILURE:
1640         case WIFI_STAT_RX_FRAGS:
1641         case WIFI_STAT_MCAST_RX:
1642         case WIFI_STAT_FCS_ERRORS:
1643         case WIFI_STAT_WEP_ERRORS:
1644         case WIFI_STAT_RX_DUPS:
1645                 ATU_UNLOCK(sc);
1646                 return (ieee80211_stat(ic, stat, val));
1647         default:
1648                 ATU_UNLOCK(sc);
1649                 return (ENOTSUP);
1650         }
1651 
1652         ATU_UNLOCK(sc);
1653         return (0);
1654 }
1655 
1656 static mac_callbacks_t atu_m_callbacks = {
1657         MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
1658         atu_m_stat,
1659         atu_m_start,
1660         atu_m_stop,
1661         atu_m_promisc,
1662         atu_m_multicst,
1663         atu_m_unicst,
1664         atu_m_tx,
1665         NULL,
1666         atu_m_ioctl,
1667         NULL,
1668         NULL,
1669         NULL,
1670         atu_m_setprop,
1671         atu_m_getprop,
1672         atu_m_propinfo
1673 };
--- EOF ---