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