Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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