linux/drivers/staging/winbond/wbusb.c
<<
>>
Prefs
   1/*
   2 * Copyright 2008 Pavel Machek <pavel@ucw.cz>
   3 *
   4 * Distribute under GPLv2.
   5 *
   6 * The original driver was written by:
   7 *     Jeff Lee <YY_Lee@issc.com.tw>
   8 *
   9 * and was adapted to the 2.6 kernel by:
  10 *     Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar>
  11 */
  12#include <net/mac80211.h>
  13#include <linux/usb.h>
  14#include <linux/module.h>
  15
  16#include "core.h"
  17#include "mds_f.h"
  18#include "mto.h"
  19#include "wbhal.h"
  20#include "wb35reg_f.h"
  21#include "wb35tx_f.h"
  22#include "wb35rx_f.h"
  23
  24MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
  25MODULE_LICENSE("GPL");
  26MODULE_VERSION("0.1");
  27
  28static const struct usb_device_id wb35_table[] = {
  29        { USB_DEVICE(0x0416, 0x0035) },
  30        { USB_DEVICE(0x18E8, 0x6201) },
  31        { USB_DEVICE(0x18E8, 0x6206) },
  32        { USB_DEVICE(0x18E8, 0x6217) },
  33        { USB_DEVICE(0x18E8, 0x6230) },
  34        { USB_DEVICE(0x18E8, 0x6233) },
  35        { USB_DEVICE(0x1131, 0x2035) },
  36        { 0, }
  37};
  38
  39MODULE_DEVICE_TABLE(usb, wb35_table);
  40
  41static struct ieee80211_rate wbsoft_rates[] = {
  42        { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
  43};
  44
  45static struct ieee80211_channel wbsoft_channels[] = {
  46        { .center_freq = 2412 },
  47};
  48
  49static struct ieee80211_supported_band wbsoft_band_2GHz = {
  50        .channels       = wbsoft_channels,
  51        .n_channels     = ARRAY_SIZE(wbsoft_channels),
  52        .bitrates       = wbsoft_rates,
  53        .n_bitrates     = ARRAY_SIZE(wbsoft_rates),
  54};
  55
  56static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
  57{
  58        u32 tmp;
  59
  60        if (pHwData->SurpriseRemove)
  61                return;
  62
  63        pHwData->BeaconPeriod = beacon_period;
  64        tmp = pHwData->BeaconPeriod << 16;
  65        tmp |= pHwData->ProbeDelay;
  66        Wb35Reg_Write(pHwData, 0x0848, tmp);
  67}
  68
  69static int wbsoft_add_interface(struct ieee80211_hw *dev,
  70                                struct ieee80211_vif *vif)
  71{
  72        struct wbsoft_priv *priv = dev->priv;
  73
  74        hal_set_beacon_period(&priv->sHwData, vif->bss_conf.beacon_int);
  75
  76        return 0;
  77}
  78
  79static void wbsoft_remove_interface(struct ieee80211_hw *dev,
  80                                    struct ieee80211_vif *vif)
  81{
  82}
  83
  84static void wbsoft_stop(struct ieee80211_hw *hw)
  85{
  86}
  87
  88static int wbsoft_get_stats(struct ieee80211_hw *hw,
  89                            struct ieee80211_low_level_stats *stats)
  90{
  91        return 0;
  92}
  93
  94static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw,
  95                                    struct netdev_hw_addr_list *mc_list)
  96{
  97        return netdev_hw_addr_list_count(mc_list);
  98}
  99
 100static void wbsoft_configure_filter(struct ieee80211_hw *dev,
 101                                    unsigned int changed_flags,
 102                                    unsigned int *total_flags,
 103                                    u64 multicast)
 104{
 105        unsigned int new_flags;
 106
 107        new_flags = 0;
 108
 109        if (*total_flags & FIF_PROMISC_IN_BSS)
 110                new_flags |= FIF_PROMISC_IN_BSS;
 111        else if ((*total_flags & FIF_ALLMULTI) || (multicast > 32))
 112                new_flags |= FIF_ALLMULTI;
 113
 114        dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
 115
 116        *total_flags = new_flags;
 117}
 118
 119static void wbsoft_tx(struct ieee80211_hw *dev,
 120                      struct ieee80211_tx_control *control,
 121                      struct sk_buff *skb)
 122{
 123        struct wbsoft_priv *priv = dev->priv;
 124
 125        if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
 126                priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
 127                kfree_skb(skb);
 128                return;
 129        }
 130
 131        priv->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
 132
 133        priv->sMlmeFrame.pMMPDU         = skb->data;
 134        priv->sMlmeFrame.DataType       = FRAME_TYPE_802_11_MANAGEMENT;
 135        priv->sMlmeFrame.len            = skb->len;
 136        priv->sMlmeFrame.wNumTxMMPDU++;
 137
 138        /*
 139         * H/W will enter power save by set the register. S/W don't send null
 140         * frame with PWRMgt bit enbled to enter power save now.
 141         */
 142
 143        Mds_Tx(priv);
 144}
 145
 146static int wbsoft_start(struct ieee80211_hw *dev)
 147{
 148        struct wbsoft_priv *priv = dev->priv;
 149
 150        priv->enabled = true;
 151
 152        return 0;
 153}
 154
 155static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
 156{
 157        struct wb35_reg *reg = &pHwData->reg;
 158
 159        if (pHwData->SurpriseRemove)
 160                return;
 161
 162        if (radio_off) {        /* disable Baseband receive off */
 163                pHwData->CurrentRadioSw = 1;    /* off */
 164                reg->M24_MacControl &= 0xffffffbf;
 165        } else {
 166                pHwData->CurrentRadioSw = 0;    /* on */
 167                reg->M24_MacControl |= 0x00000040;
 168        }
 169        Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
 170}
 171
 172static void hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
 173{
 174        struct wb35_reg *reg = &pHwData->reg;
 175
 176        if (pHwData->SurpriseRemove)
 177                return;
 178
 179        RFSynthesizer_SwitchingChannel(pHwData, channel); /* Switch channel */
 180        pHwData->Channel = channel.ChanNo;
 181        pHwData->band = channel.band;
 182        reg->M28_MacControl &= ~0xff;   /* Clean channel information field */
 183        reg->M28_MacControl |= channel.ChanNo;
 184        Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
 185                                       (s8 *) &channel,
 186                                       sizeof(struct chan_info));
 187}
 188
 189static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
 190{
 191        hal_set_current_channel_ex(pHwData, channel);
 192}
 193
 194static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
 195{
 196        struct wb35_reg *reg = &pHwData->reg;
 197
 198        if (pHwData->SurpriseRemove)
 199                return;
 200
 201        reg->M00_MacControl &= ~0x02000000;     /* The HW value */
 202
 203        if (enable)
 204                reg->M00_MacControl |= 0x02000000;      /* The HW value */
 205
 206        Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
 207}
 208
 209/* For wep key error detection, we need to accept broadcast packets to be received temporary. */
 210static void hal_set_accept_promiscuous(struct hw_data *pHwData, u8 enable)
 211{
 212        struct wb35_reg *reg = &pHwData->reg;
 213
 214        if (pHwData->SurpriseRemove)
 215                return;
 216
 217        if (enable) {
 218                reg->M00_MacControl |= 0x00400000;
 219                Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
 220        } else {
 221                reg->M00_MacControl &= ~0x00400000;
 222                Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
 223        }
 224}
 225
 226static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
 227{
 228        struct wb35_reg *reg = &pHwData->reg;
 229
 230        if (pHwData->SurpriseRemove)
 231                return;
 232
 233        reg->M00_MacControl &= ~0x01000000;     /* The HW value */
 234        if (enable)
 235                reg->M00_MacControl |= 0x01000000;      /* The HW value */
 236        Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
 237}
 238
 239static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
 240{
 241        struct wb35_reg *reg = &pHwData->reg;
 242
 243        if (pHwData->SurpriseRemove)
 244                return;
 245
 246        if (!enable)    /* Due to SME and MLME are not suitable for 35 */
 247                return;
 248
 249        reg->M00_MacControl &= ~0x04000000;     /* The HW value */
 250        if (enable)
 251                reg->M00_MacControl |= 0x04000000;      /* The HW value */
 252
 253        Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
 254}
 255
 256static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
 257{
 258        struct wbsoft_priv *priv = dev->priv;
 259        struct chan_info ch;
 260
 261        /* Should use channel_num, or something, as that is already pre-translated */
 262        ch.band = 1;
 263        ch.ChanNo = 1;
 264
 265        hal_set_current_channel(&priv->sHwData, ch);
 266        hal_set_accept_broadcast(&priv->sHwData, 1);
 267        hal_set_accept_promiscuous(&priv->sHwData, 1);
 268        hal_set_accept_multicast(&priv->sHwData, 1);
 269        hal_set_accept_beacon(&priv->sHwData, 1);
 270        hal_set_radio_mode(&priv->sHwData, 0);
 271
 272        return 0;
 273}
 274
 275static u64 wbsoft_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
 276{
 277        return 0;
 278}
 279
 280static const struct ieee80211_ops wbsoft_ops = {
 281        .tx                     = wbsoft_tx,
 282        .start                  = wbsoft_start,
 283        .stop                   = wbsoft_stop,
 284        .add_interface          = wbsoft_add_interface,
 285        .remove_interface       = wbsoft_remove_interface,
 286        .config                 = wbsoft_config,
 287        .prepare_multicast      = wbsoft_prepare_multicast,
 288        .configure_filter       = wbsoft_configure_filter,
 289        .get_stats              = wbsoft_get_stats,
 290        .get_tsf                = wbsoft_get_tsf,
 291};
 292
 293static void hal_set_ethernet_address(struct hw_data *pHwData, u8 *current_address)
 294{
 295        u32 ltmp[2];
 296
 297        if (pHwData->SurpriseRemove)
 298                return;
 299
 300        memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
 301
 302        ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
 303        ltmp[1] = cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
 304
 305        Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
 306}
 307
 308static void hal_get_permanent_address(struct hw_data *pHwData, u8 *pethernet_address)
 309{
 310        if (pHwData->SurpriseRemove)
 311                return;
 312
 313        memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
 314}
 315
 316static void hal_stop(struct hw_data *pHwData)
 317{
 318        struct wb35_reg *reg = &pHwData->reg;
 319
 320        pHwData->Wb35Rx.rx_halt = 1;
 321        Wb35Rx_stop(pHwData);
 322
 323        pHwData->Wb35Tx.tx_halt = 1;
 324        Wb35Tx_stop(pHwData);
 325
 326        reg->D00_DmaControl &= ~0xc0000000;     /* Tx Off, Rx Off */
 327        Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
 328}
 329
 330static unsigned char hal_idle(struct hw_data *pHwData)
 331{
 332        struct wb35_reg *reg = &pHwData->reg;
 333
 334        if (!pHwData->SurpriseRemove && reg->EP0vm_state != VM_STOP)
 335                return false;
 336
 337        return true;
 338}
 339
 340u8 hal_get_antenna_number(struct hw_data *pHwData)
 341{
 342        struct wb35_reg *reg = &pHwData->reg;
 343
 344        if ((reg->BB2C & BIT(11)) == 0)
 345                return 0;
 346        else
 347                return 1;
 348}
 349
 350/* 0 : radio on; 1: radio off */
 351static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
 352{
 353        struct wb35_reg *reg = &pHwData->reg;
 354
 355        if (pHwData->SurpriseRemove)
 356                return 1;
 357
 358        /* read the bit16 of register U1B0 */
 359        Wb35Reg_Read(pHwData, 0x3b0, &reg->U1B0);
 360        if ((reg->U1B0 & 0x00010000)) {
 361                pHwData->CurrentRadioHw = 1;
 362                return 1;
 363        } else {
 364                pHwData->CurrentRadioHw = 0;
 365                return 0;
 366        }
 367}
 368
 369static u8 LED_GRAY[20] = {
 370        0, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2
 371};
 372
 373static u8 LED_GRAY2[30] = {
 374        7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 375        0, 15, 14, 13, 12, 11, 10, 9, 8
 376};
 377
 378static void hal_led_control(unsigned long data)
 379{
 380        struct wbsoft_priv *adapter = (struct wbsoft_priv *)data;
 381        struct hw_data *pHwData = &adapter->sHwData;
 382        struct wb35_reg *reg = &pHwData->reg;
 383        u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
 384        u32 TimeInterval = 500, ltmp, ltmp2;
 385        ltmp = 0;
 386
 387        if (pHwData->SurpriseRemove)
 388                return;
 389
 390        if (pHwData->LED_control) {
 391                ltmp2 = pHwData->LED_control & 0xff;
 392                if (ltmp2 == 5) { /* 5 is WPS mode */
 393                        TimeInterval = 100;
 394                        ltmp2 = (pHwData->LED_control >> 8) & 0xff;
 395                        switch (ltmp2) {
 396                        case 1: /* [0.2 On][0.1 Off]... */
 397                                pHwData->LED_Blinking %= 3;
 398                                ltmp = 0x1010;  /* Led 1 & 0 Green and Red */
 399                                if (pHwData->LED_Blinking == 2) /* Turn off */
 400                                        ltmp = 0;
 401                                break;
 402                        case 2: /* [0.1 On][0.1 Off]... */
 403                                pHwData->LED_Blinking %= 2;
 404                                ltmp = 0x0010;  /* Led 0 red color */
 405                                if (pHwData->LED_Blinking) /* Turn off */
 406                                        ltmp = 0;
 407                                break;
 408                        case 3: /* [0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.5 Off]... */
 409                                pHwData->LED_Blinking %= 15;
 410                                ltmp = 0x0010;  /* Led 0 red color */
 411                                if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) /* Turn off 0.6 sec */
 412                                        ltmp = 0;
 413                                break;
 414                        case 4: /* [300 On][ off ] */
 415                                ltmp = 0x1000;  /* Led 1 Green color */
 416                                if (pHwData->LED_Blinking >= 3000)
 417                                        ltmp = 0; /* led maybe on after 300sec * 32bit counter overlap. */
 418                                break;
 419                        }
 420                        pHwData->LED_Blinking++;
 421
 422                        reg->U1BC_LEDConfigure = ltmp;
 423                        if (LEDSet != 7) { /* Only 111 mode has 2 LEDs on PCB. */
 424                                reg->U1BC_LEDConfigure |= (ltmp & 0xff) << 8; /* Copy LED result to each LED control register */
 425                                reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
 426                        }
 427                        Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
 428                }
 429        } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) { /* If radio off */
 430                if (reg->U1BC_LEDConfigure & 0x1010) {
 431                        reg->U1BC_LEDConfigure &= ~0x1010;
 432                        Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
 433                }
 434        } else {
 435                switch (LEDSet) {
 436                case 4: /* [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
 437                        if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
 438                                /* Blinking if scanning is on progress */
 439                                if (pHwData->LED_Scanning) {
 440                                        if (pHwData->LED_Blinking == 0) {
 441                                                reg->U1BC_LEDConfigure |= 0x10;
 442                                                Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
 443                                                pHwData->LED_Blinking = 1;
 444                                                TimeInterval = 300;
 445                                        } else {
 446                                                reg->U1BC_LEDConfigure &= ~0x10;
 447                                                Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
 448                                                pHwData->LED_Blinking = 0;
 449                                                TimeInterval = 300;
 450                                        }
 451                                } else {
 452                                        /* Turn Off LED_0 */
 453                                        if (reg->U1BC_LEDConfigure & 0x10) {
 454                                                reg->U1BC_LEDConfigure &= ~0x10;
 455                                                Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
 456                                        }
 457                                }
 458                        } else {
 459                                /* Turn On LED_0 */
 460                                if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
 461                                        reg->U1BC_LEDConfigure |= 0x10;
 462                                        Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
 463                                }
 464                        }
 465                        break;
 466                case 6: /* [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
 467                        if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
 468                                /* Blinking if scanning is on progress */
 469                                if (pHwData->LED_Scanning) {
 470                                        if (pHwData->LED_Blinking == 0) {
 471                                                reg->U1BC_LEDConfigure &= ~0xf;
 472                                                reg->U1BC_LEDConfigure |= 0x10;
 473                                                Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
 474                                                pHwData->LED_Blinking = 1;
 475                                                TimeInterval = 300;
 476                                        } else {
 477                                                reg->U1BC_LEDConfigure &= ~0x1f;
 478                                                Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
 479                                                pHwData->LED_Blinking = 0;
 480                                                TimeInterval = 300;
 481                                        }
 482                                } else {
 483                                        /* Gray blinking if in disconnect state and not scanning */
 484                                        ltmp = reg->U1BC_LEDConfigure;
 485                                        reg->U1BC_LEDConfigure &= ~0x1f;
 486                                        if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
 487                                                reg->U1BC_LEDConfigure |= 0x10;
 488                                                reg->U1BC_LEDConfigure |=
 489                                                    LED_GRAY2[(pHwData->LED_Blinking % 30)];
 490                                        }
 491                                        pHwData->LED_Blinking++;
 492                                        if (reg->U1BC_LEDConfigure != ltmp)
 493                                                Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
 494                                        TimeInterval = 100;
 495                                }
 496                        } else {
 497                                /* Turn On LED_0 */
 498                                if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
 499                                        reg->U1BC_LEDConfigure |= 0x10;
 500                                        Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
 501                                }
 502                        }
 503                        break;
 504                case 5: /* [101] Only 1 Led be placed on PCB and use LED_1 for showing */
 505                        if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
 506                                /* Blinking if scanning is on progress */
 507                                if (pHwData->LED_Scanning) {
 508                                        if (pHwData->LED_Blinking == 0) {
 509                                                reg->U1BC_LEDConfigure |= 0x1000;
 510                                                Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
 511                                                pHwData->LED_Blinking = 1;
 512                                                TimeInterval = 300;
 513                                        } else {
 514                                                reg->U1BC_LEDConfigure &= ~0x1000;
 515                                                Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
 516                                                pHwData->LED_Blinking = 0;
 517                                                TimeInterval = 300;
 518                                        }
 519                                } else {
 520                                        /* Turn Off LED_1 */
 521                                        if (reg->U1BC_LEDConfigure & 0x1000) {
 522                                                reg->U1BC_LEDConfigure &= ~0x1000;
 523                                                Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
 524                                        }
 525                                }
 526                        } else {
 527                                /* Is transmitting/receiving ?? */
 528                                if ((adapter->RxByteCount !=
 529                                     pHwData->RxByteCountLast)
 530                                    || (adapter->TxByteCount !=
 531                                        pHwData->TxByteCountLast)) {
 532                                        if ((reg->U1BC_LEDConfigure & 0x3000) !=
 533                                            0x3000) {
 534                                                reg->U1BC_LEDConfigure |= 0x3000;
 535                                                Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
 536                                        }
 537                                        /* Update variable */
 538                                        pHwData->RxByteCountLast =
 539                                            adapter->RxByteCount;
 540                                        pHwData->TxByteCountLast =
 541                                            adapter->TxByteCount;
 542                                        TimeInterval = 200;
 543                                } else {
 544                                        /* Turn On LED_1 and blinking if transmitting/receiving */
 545                                        if ((reg->U1BC_LEDConfigure & 0x3000) !=
 546                                            0x1000) {
 547                                                reg->U1BC_LEDConfigure &=
 548                                                    ~0x3000;
 549                                                reg->U1BC_LEDConfigure |=
 550                                                    0x1000;
 551                                                Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
 552                                        }
 553                                }
 554                        }
 555                        break;
 556                default: /* Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active */
 557                        if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
 558                                reg->U1BC_LEDConfigure |= 0x3000;       /* LED_1 is always on and event enable */
 559                                Wb35Reg_Write(pHwData, 0x03bc,
 560                                              reg->U1BC_LEDConfigure);
 561                        }
 562
 563                        if (pHwData->LED_Blinking) {
 564                                /* Gray blinking */
 565                                reg->U1BC_LEDConfigure &= ~0x0f;
 566                                reg->U1BC_LEDConfigure |= 0x10;
 567                                reg->U1BC_LEDConfigure |=
 568                                    LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
 569                                Wb35Reg_Write(pHwData, 0x03bc,
 570                                              reg->U1BC_LEDConfigure);
 571
 572                                pHwData->LED_Blinking += 2;
 573                                if (pHwData->LED_Blinking < 40)
 574                                        TimeInterval = 100;
 575                                else {
 576                                        pHwData->LED_Blinking = 0; /* Stop blinking */
 577                                        reg->U1BC_LEDConfigure &= ~0x0f;
 578                                        Wb35Reg_Write(pHwData, 0x03bc,
 579                                                      reg->U1BC_LEDConfigure);
 580                                }
 581                                break;
 582                        }
 583
 584                        if (pHwData->LED_LinkOn) {
 585                                if (!(reg->U1BC_LEDConfigure & 0x10)) { /* Check the LED_0 */
 586                                        /* Try to turn ON LED_0 after gray blinking */
 587                                        reg->U1BC_LEDConfigure |= 0x10;
 588                                        pHwData->LED_Blinking = 1; /* Start blinking */
 589                                        TimeInterval = 50;
 590                                }
 591                        } else {
 592                                if (reg->U1BC_LEDConfigure & 0x10) { /* Check the LED_0 */
 593                                        reg->U1BC_LEDConfigure &= ~0x10;
 594                                        Wb35Reg_Write(pHwData, 0x03bc,
 595                                                      reg->U1BC_LEDConfigure);
 596                                }
 597                        }
 598                        break;
 599                }
 600        }
 601
 602        pHwData->time_count += TimeInterval;
 603        Wb35Tx_CurrentTime(adapter, pHwData->time_count);
 604        pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
 605        add_timer(&pHwData->LEDTimer);
 606}
 607
 608static int hal_init_hardware(struct ieee80211_hw *hw)
 609{
 610        struct wbsoft_priv *priv = hw->priv;
 611        struct hw_data *pHwData = &priv->sHwData;
 612        u16 SoftwareSet;
 613
 614        pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
 615        pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
 616
 617        if (!Wb35Reg_initial(pHwData))
 618                goto error_reg_destroy;
 619
 620        if (!Wb35Tx_initial(pHwData))
 621                goto error_tx_destroy;
 622
 623        if (!Wb35Rx_initial(pHwData))
 624                goto error_rx_destroy;
 625
 626        init_timer(&pHwData->LEDTimer);
 627        pHwData->LEDTimer.function = hal_led_control;
 628        pHwData->LEDTimer.data = (unsigned long)priv;
 629        pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
 630        add_timer(&pHwData->LEDTimer);
 631
 632        SoftwareSet = hal_software_set(pHwData);
 633
 634        Wb35Rx_start(hw);
 635        Wb35Tx_EP2VM_start(priv);
 636
 637        return 0;
 638
 639error_rx_destroy:
 640        Wb35Rx_destroy(pHwData);
 641error_tx_destroy:
 642        Wb35Tx_destroy(pHwData);
 643error_reg_destroy:
 644        Wb35Reg_destroy(pHwData);
 645
 646        pHwData->SurpriseRemove = 1;
 647        return -EINVAL;
 648}
 649
 650static int wb35_hw_init(struct ieee80211_hw *hw)
 651{
 652        struct wbsoft_priv *priv = hw->priv;
 653        struct hw_data *pHwData = &priv->sHwData;
 654        u8 EEPROM_region;
 655        u8 HwRadioOff;
 656        u8 *pMacAddr2;
 657        u8 *pMacAddr;
 658        int err;
 659
 660        pHwData->phy_type = RF_DECIDE_BY_INF;
 661
 662        priv->Mds.TxRTSThreshold                = DEFAULT_RTSThreshold;
 663        priv->Mds.TxFragmentThreshold           = DEFAULT_FRAGMENT_THRESHOLD;
 664
 665        priv->sLocalPara.region_INF             = REGION_AUTO;
 666        priv->sLocalPara.TxRateMode             = RATE_AUTO;
 667        priv->sLocalPara.bMacOperationMode      = MODE_802_11_BG;
 668        priv->sLocalPara.MTUsize                = MAX_ETHERNET_PACKET_SIZE;
 669        priv->sLocalPara.bPreambleMode          = AUTO_MODE;
 670        priv->sLocalPara.bWepKeyError           = false;
 671        priv->sLocalPara.bToSelfPacketReceived  = false;
 672        priv->sLocalPara.WepKeyDetectTimerCount = 2 * 100; /* 2 seconds */
 673
 674        priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
 675
 676        err = hal_init_hardware(hw);
 677        if (err)
 678                goto error;
 679
 680        EEPROM_region = hal_get_region_from_EEPROM(pHwData);
 681        if (EEPROM_region != REGION_AUTO)
 682                priv->sLocalPara.region = EEPROM_region;
 683        else {
 684                if (priv->sLocalPara.region_INF != REGION_AUTO)
 685                        priv->sLocalPara.region = priv->sLocalPara.region_INF;
 686                else
 687                        priv->sLocalPara.region = REGION_USA;   /* default setting */
 688        }
 689
 690        Mds_initial(priv);
 691
 692        /*
 693         * If no user-defined address in the registry, use the address
 694         * "burned" on the NIC instead.
 695         */
 696        pMacAddr = priv->sLocalPara.ThisMacAddress;
 697        pMacAddr2 = priv->sLocalPara.PermanentAddress;
 698
 699        /* Reading ethernet address from EEPROM */
 700        hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
 701        if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
 702                memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
 703        else {
 704                /* Set the user define MAC address */
 705                hal_set_ethernet_address(pHwData,
 706                                         priv->sLocalPara.ThisMacAddress);
 707        }
 708
 709        priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
 710        hal_get_hw_radio_off(pHwData);
 711
 712        /* Waiting for HAL setting OK */
 713        while (!hal_idle(pHwData))
 714                msleep(10);
 715
 716        MTO_Init(priv);
 717
 718        HwRadioOff = hal_get_hw_radio_off(pHwData);
 719        priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
 720
 721        hal_set_radio_mode(pHwData,
 722                           (unsigned char)(priv->sLocalPara.RadioOffStatus.
 723                                           boSwRadioOff
 724                                           || priv->sLocalPara.RadioOffStatus.
 725                                           boHwRadioOff));
 726
 727        /* Notify hal that the driver is ready now. */
 728        hal_driver_init_OK(pHwData) = 1;
 729
 730error:
 731        return err;
 732}
 733
 734static int wb35_probe(struct usb_interface *intf,
 735                      const struct usb_device_id *id_table)
 736{
 737        struct usb_device *udev = interface_to_usbdev(intf);
 738        struct usb_endpoint_descriptor *endpoint;
 739        struct usb_host_interface *interface;
 740        struct ieee80211_hw *dev;
 741        struct wbsoft_priv *priv;
 742        int err;
 743        u32 ltmp;
 744
 745        usb_get_dev(udev);
 746
 747        /* Check the device if it already be opened */
 748        err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 749                             0x01,
 750                             USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 751                             0x0, 0x400, &ltmp, 4, HZ * 100);
 752        if (err < 0)
 753                goto error;
 754
 755        /* Is already initialized? */
 756        ltmp = cpu_to_le32(ltmp);
 757        if (ltmp) {
 758                err = -EBUSY;
 759                goto error;
 760        }
 761
 762        dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
 763        if (!dev) {
 764                err = -ENOMEM;
 765                goto error;
 766        }
 767
 768        priv = dev->priv;
 769
 770        priv->sHwData.udev = udev;
 771
 772        interface = intf->cur_altsetting;
 773        endpoint = &interface->endpoint[0].desc;
 774
 775        err = wb35_hw_init(dev);
 776        if (err)
 777                goto error_free_hw;
 778
 779        SET_IEEE80211_DEV(dev, &udev->dev);
 780        {
 781                struct hw_data *pHwData = &priv->sHwData;
 782                unsigned char dev_addr[MAX_ADDR_LEN];
 783                hal_get_permanent_address(pHwData, dev_addr);
 784                SET_IEEE80211_PERM_ADDR(dev, dev_addr);
 785        }
 786
 787        dev->extra_tx_headroom = 12;    /* FIXME */
 788        dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
 789        dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
 790
 791        dev->channel_change_time = 1000;
 792        dev->max_signal = 100;
 793        dev->queues = 1;
 794
 795        dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
 796
 797        err = ieee80211_register_hw(dev);
 798        if (err)
 799                goto error_free_hw;
 800
 801        usb_set_intfdata(intf, dev);
 802
 803        return 0;
 804
 805error_free_hw:
 806        ieee80211_free_hw(dev);
 807error:
 808        usb_put_dev(udev);
 809        return err;
 810}
 811
 812static void hal_halt(struct hw_data *pHwData)
 813{
 814        del_timer_sync(&pHwData->LEDTimer);
 815        /* XXX: Wait for Timer DPC exit. */
 816        msleep(100);
 817        Wb35Rx_destroy(pHwData);
 818        Wb35Tx_destroy(pHwData);
 819        Wb35Reg_destroy(pHwData);
 820}
 821
 822static void wb35_hw_halt(struct wbsoft_priv *adapter)
 823{
 824        /* Turn off Rx and Tx hardware ability */
 825        hal_stop(&adapter->sHwData);
 826        /* Waiting Irp completed */
 827        msleep(100);
 828
 829        hal_halt(&adapter->sHwData);
 830}
 831
 832static void wb35_disconnect(struct usb_interface *intf)
 833{
 834        struct ieee80211_hw *hw = usb_get_intfdata(intf);
 835        struct wbsoft_priv *priv = hw->priv;
 836
 837        wb35_hw_halt(priv);
 838
 839        ieee80211_stop_queues(hw);
 840        ieee80211_unregister_hw(hw);
 841        ieee80211_free_hw(hw);
 842
 843        usb_set_intfdata(intf, NULL);
 844        usb_put_dev(interface_to_usbdev(intf));
 845}
 846
 847static struct usb_driver wb35_driver = {
 848        .name           = "w35und",
 849        .id_table       = wb35_table,
 850        .probe          = wb35_probe,
 851        .disconnect     = wb35_disconnect,
 852};
 853
 854module_usb_driver(wb35_driver);
 855