Merge remote-tracking branch 'pm/linux-next'
[linux-2.6/next.git] / drivers / staging / winbond / wbusb.c
blob3724e1e67ec23adfd56d52b0e1cf6a5e0fe9e523
1 /*
2 * Copyright 2008 Pavel Machek <pavel@ucw.cz>
4 * Distribute under GPLv2.
6 * The original driver was written by:
7 * Jeff Lee <YY_Lee@issc.com.tw>
9 * and was adapted to the 2.6 kernel by:
10 * Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar>
12 #include <net/mac80211.h>
13 #include <linux/usb.h>
15 #include "core.h"
16 #include "mds_f.h"
17 #include "mto.h"
18 #include "wbhal.h"
19 #include "wb35reg_f.h"
20 #include "wb35tx_f.h"
21 #include "wb35rx_f.h"
23 MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
24 MODULE_LICENSE("GPL");
25 MODULE_VERSION("0.1");
27 static const struct usb_device_id wb35_table[] __devinitconst = {
28 { USB_DEVICE(0x0416, 0x0035) },
29 { USB_DEVICE(0x18E8, 0x6201) },
30 { USB_DEVICE(0x18E8, 0x6206) },
31 { USB_DEVICE(0x18E8, 0x6217) },
32 { USB_DEVICE(0x18E8, 0x6230) },
33 { USB_DEVICE(0x18E8, 0x6233) },
34 { USB_DEVICE(0x1131, 0x2035) },
35 { 0, }
38 MODULE_DEVICE_TABLE(usb, wb35_table);
40 static struct ieee80211_rate wbsoft_rates[] = {
41 { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
44 static struct ieee80211_channel wbsoft_channels[] = {
45 { .center_freq = 2412 },
48 static struct ieee80211_supported_band wbsoft_band_2GHz = {
49 .channels = wbsoft_channels,
50 .n_channels = ARRAY_SIZE(wbsoft_channels),
51 .bitrates = wbsoft_rates,
52 .n_bitrates = ARRAY_SIZE(wbsoft_rates),
55 static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
57 u32 tmp;
59 if (pHwData->SurpriseRemove)
60 return;
62 pHwData->BeaconPeriod = beacon_period;
63 tmp = pHwData->BeaconPeriod << 16;
64 tmp |= pHwData->ProbeDelay;
65 Wb35Reg_Write(pHwData, 0x0848, tmp);
68 static int wbsoft_add_interface(struct ieee80211_hw *dev,
69 struct ieee80211_vif *vif)
71 struct wbsoft_priv *priv = dev->priv;
73 hal_set_beacon_period(&priv->sHwData, vif->bss_conf.beacon_int);
75 return 0;
78 static void wbsoft_remove_interface(struct ieee80211_hw *dev,
79 struct ieee80211_vif *vif)
81 printk("wbsoft_remove interface called\n");
84 static void wbsoft_stop(struct ieee80211_hw *hw)
86 printk(KERN_INFO "%s called\n", __func__);
89 static int wbsoft_get_stats(struct ieee80211_hw *hw,
90 struct ieee80211_low_level_stats *stats)
92 printk(KERN_INFO "%s called\n", __func__);
93 return 0;
96 static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw,
97 struct netdev_hw_addr_list *mc_list)
99 return netdev_hw_addr_list_count(mc_list);
102 static void wbsoft_configure_filter(struct ieee80211_hw *dev,
103 unsigned int changed_flags,
104 unsigned int *total_flags,
105 u64 multicast)
107 unsigned int new_flags;
109 new_flags = 0;
111 if (*total_flags & FIF_PROMISC_IN_BSS)
112 new_flags |= FIF_PROMISC_IN_BSS;
113 else if ((*total_flags & FIF_ALLMULTI) || (multicast > 32))
114 new_flags |= FIF_ALLMULTI;
116 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
118 *total_flags = new_flags;
121 static void wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
123 struct wbsoft_priv *priv = dev->priv;
125 if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
126 priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
127 kfree_skb(skb);
128 return;
131 priv->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
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++;
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.
143 Mds_Tx(priv);
146 static int wbsoft_start(struct ieee80211_hw *dev)
148 struct wbsoft_priv *priv = dev->priv;
150 priv->enabled = true;
152 return 0;
155 static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
157 struct wb35_reg *reg = &pHwData->reg;
159 if (pHwData->SurpriseRemove)
160 return;
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;
169 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
172 static void hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
174 struct wb35_reg *reg = &pHwData->reg;
176 if (pHwData->SurpriseRemove)
177 return;
179 printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo);
181 RFSynthesizer_SwitchingChannel(pHwData, channel); /* Switch channel */
182 pHwData->Channel = channel.ChanNo;
183 pHwData->band = channel.band;
184 pr_debug("Set channel is %d, band =%d\n", pHwData->Channel, pHwData->band);
185 reg->M28_MacControl &= ~0xff; /* Clean channel information field */
186 reg->M28_MacControl |= channel.ChanNo;
187 Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
188 (s8 *) &channel,
189 sizeof(struct chan_info));
192 static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
194 hal_set_current_channel_ex(pHwData, channel);
197 static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
199 struct wb35_reg *reg = &pHwData->reg;
201 if (pHwData->SurpriseRemove)
202 return;
204 reg->M00_MacControl &= ~0x02000000; /* The HW value */
206 if (enable)
207 reg->M00_MacControl |= 0x02000000; /* The HW value */
209 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
212 /* For wep key error detection, we need to accept broadcast packets to be received temporary. */
213 static void hal_set_accept_promiscuous(struct hw_data *pHwData, u8 enable)
215 struct wb35_reg *reg = &pHwData->reg;
217 if (pHwData->SurpriseRemove)
218 return;
220 if (enable) {
221 reg->M00_MacControl |= 0x00400000;
222 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
223 } else {
224 reg->M00_MacControl &= ~0x00400000;
225 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
229 static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
231 struct wb35_reg *reg = &pHwData->reg;
233 if (pHwData->SurpriseRemove)
234 return;
236 reg->M00_MacControl &= ~0x01000000; /* The HW value */
237 if (enable)
238 reg->M00_MacControl |= 0x01000000; /* The HW value */
239 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
242 static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
244 struct wb35_reg *reg = &pHwData->reg;
246 if (pHwData->SurpriseRemove)
247 return;
249 if (!enable) /* Due to SME and MLME are not suitable for 35 */
250 return;
252 reg->M00_MacControl &= ~0x04000000; /* The HW value */
253 if (enable)
254 reg->M00_MacControl |= 0x04000000; /* The HW value */
256 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
259 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
261 struct wbsoft_priv *priv = dev->priv;
262 struct chan_info ch;
264 printk("wbsoft_config called\n");
266 /* Should use channel_num, or something, as that is already pre-translated */
267 ch.band = 1;
268 ch.ChanNo = 1;
270 hal_set_current_channel(&priv->sHwData, ch);
271 hal_set_accept_broadcast(&priv->sHwData, 1);
272 hal_set_accept_promiscuous(&priv->sHwData, 1);
273 hal_set_accept_multicast(&priv->sHwData, 1);
274 hal_set_accept_beacon(&priv->sHwData, 1);
275 hal_set_radio_mode(&priv->sHwData, 0);
277 return 0;
280 static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
282 printk("wbsoft_get_tsf called\n");
283 return 0;
286 static const struct ieee80211_ops wbsoft_ops = {
287 .tx = wbsoft_tx,
288 .start = wbsoft_start,
289 .stop = wbsoft_stop,
290 .add_interface = wbsoft_add_interface,
291 .remove_interface = wbsoft_remove_interface,
292 .config = wbsoft_config,
293 .prepare_multicast = wbsoft_prepare_multicast,
294 .configure_filter = wbsoft_configure_filter,
295 .get_stats = wbsoft_get_stats,
296 .get_tsf = wbsoft_get_tsf,
299 static void hal_set_ethernet_address(struct hw_data *pHwData, u8 *current_address)
301 u32 ltmp[2];
303 if (pHwData->SurpriseRemove)
304 return;
306 memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
308 ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
309 ltmp[1] = cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
311 Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
314 static void hal_get_permanent_address(struct hw_data *pHwData, u8 *pethernet_address)
316 if (pHwData->SurpriseRemove)
317 return;
319 memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
322 static void hal_stop(struct hw_data *pHwData)
324 struct wb35_reg *reg = &pHwData->reg;
326 pHwData->Wb35Rx.rx_halt = 1;
327 Wb35Rx_stop(pHwData);
329 pHwData->Wb35Tx.tx_halt = 1;
330 Wb35Tx_stop(pHwData);
332 reg->D00_DmaControl &= ~0xc0000000; /* Tx Off, Rx Off */
333 Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
336 static unsigned char hal_idle(struct hw_data *pHwData)
338 struct wb35_reg *reg = &pHwData->reg;
340 if (!pHwData->SurpriseRemove && reg->EP0vm_state != VM_STOP)
341 return false;
343 return true;
346 u8 hal_get_antenna_number(struct hw_data *pHwData)
348 struct wb35_reg *reg = &pHwData->reg;
350 if ((reg->BB2C & BIT(11)) == 0)
351 return 0;
352 else
353 return 1;
356 /* 0 : radio on; 1: radio off */
357 static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
359 struct wb35_reg *reg = &pHwData->reg;
361 if (pHwData->SurpriseRemove)
362 return 1;
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;
375 static 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
379 static 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
384 static void hal_led_control(unsigned long data)
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;
393 if (pHwData->SurpriseRemove)
394 return;
396 if (pHwData->LED_control) {
397 ltmp2 = pHwData->LED_control & 0xff;
398 if (ltmp2 == 5) { /* 5 is WPS mode */
399 TimeInterval = 100;
400 ltmp2 = (pHwData->LED_control >> 8) & 0xff;
401 switch (ltmp2) {
402 case 1: /* [0.2 On][0.1 Off]... */
403 pHwData->LED_Blinking %= 3;
404 ltmp = 0x1010; /* Led 1 & 0 Green and Red */
405 if (pHwData->LED_Blinking == 2) /* Turn off */
406 ltmp = 0;
407 break;
408 case 2: /* [0.1 On][0.1 Off]... */
409 pHwData->LED_Blinking %= 2;
410 ltmp = 0x0010; /* Led 0 red color */
411 if (pHwData->LED_Blinking) /* Turn off */
412 ltmp = 0;
413 break;
414 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]... */
415 pHwData->LED_Blinking %= 15;
416 ltmp = 0x0010; /* Led 0 red color */
417 if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) /* Turn off 0.6 sec */
418 ltmp = 0;
419 break;
420 case 4: /* [300 On][ off ] */
421 ltmp = 0x1000; /* Led 1 Green color */
422 if (pHwData->LED_Blinking >= 3000)
423 ltmp = 0; /* led maybe on after 300sec * 32bit counter overlap. */
424 break;
426 pHwData->LED_Blinking++;
428 reg->U1BC_LEDConfigure = ltmp;
429 if (LEDSet != 7) { /* Only 111 mode has 2 LEDs on PCB. */
430 reg->U1BC_LEDConfigure |= (ltmp & 0xff) << 8; /* Copy LED result to each LED control register */
431 reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
433 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
435 } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) { /* If radio off */
436 if (reg->U1BC_LEDConfigure & 0x1010) {
437 reg->U1BC_LEDConfigure &= ~0x1010;
438 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
440 } else {
441 switch (LEDSet) {
442 case 4: /* [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
443 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
444 /* Blinking if scanning is on progress */
445 if (pHwData->LED_Scanning) {
446 if (pHwData->LED_Blinking == 0) {
447 reg->U1BC_LEDConfigure |= 0x10;
448 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
449 pHwData->LED_Blinking = 1;
450 TimeInterval = 300;
451 } else {
452 reg->U1BC_LEDConfigure &= ~0x10;
453 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
454 pHwData->LED_Blinking = 0;
455 TimeInterval = 300;
457 } else {
458 /* Turn Off LED_0 */
459 if (reg->U1BC_LEDConfigure & 0x10) {
460 reg->U1BC_LEDConfigure &= ~0x10;
461 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
464 } else {
465 /* Turn On LED_0 */
466 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
467 reg->U1BC_LEDConfigure |= 0x10;
468 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
471 break;
472 case 6: /* [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
473 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
474 /* Blinking if scanning is on progress */
475 if (pHwData->LED_Scanning) {
476 if (pHwData->LED_Blinking == 0) {
477 reg->U1BC_LEDConfigure &= ~0xf;
478 reg->U1BC_LEDConfigure |= 0x10;
479 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
480 pHwData->LED_Blinking = 1;
481 TimeInterval = 300;
482 } else {
483 reg->U1BC_LEDConfigure &= ~0x1f;
484 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
485 pHwData->LED_Blinking = 0;
486 TimeInterval = 300;
488 } else {
489 /* Gray blinking if in disconnect state and not scanning */
490 ltmp = reg->U1BC_LEDConfigure;
491 reg->U1BC_LEDConfigure &= ~0x1f;
492 if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
493 reg->U1BC_LEDConfigure |= 0x10;
494 reg->U1BC_LEDConfigure |=
495 LED_GRAY2[(pHwData->LED_Blinking % 30)];
497 pHwData->LED_Blinking++;
498 if (reg->U1BC_LEDConfigure != ltmp)
499 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
500 TimeInterval = 100;
502 } else {
503 /* Turn On LED_0 */
504 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
505 reg->U1BC_LEDConfigure |= 0x10;
506 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
509 break;
510 case 5: /* [101] Only 1 Led be placed on PCB and use LED_1 for showing */
511 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
512 /* Blinking if scanning is on progress */
513 if (pHwData->LED_Scanning) {
514 if (pHwData->LED_Blinking == 0) {
515 reg->U1BC_LEDConfigure |= 0x1000;
516 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
517 pHwData->LED_Blinking = 1;
518 TimeInterval = 300;
519 } else {
520 reg->U1BC_LEDConfigure &= ~0x1000;
521 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
522 pHwData->LED_Blinking = 0;
523 TimeInterval = 300;
525 } else {
526 /* Turn Off LED_1 */
527 if (reg->U1BC_LEDConfigure & 0x1000) {
528 reg->U1BC_LEDConfigure &= ~0x1000;
529 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
532 } else {
533 /* Is transmitting/receiving ?? */
534 if ((adapter->RxByteCount !=
535 pHwData->RxByteCountLast)
536 || (adapter->TxByteCount !=
537 pHwData->TxByteCountLast)) {
538 if ((reg->U1BC_LEDConfigure & 0x3000) !=
539 0x3000) {
540 reg->U1BC_LEDConfigure |= 0x3000;
541 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
543 /* Update variable */
544 pHwData->RxByteCountLast =
545 adapter->RxByteCount;
546 pHwData->TxByteCountLast =
547 adapter->TxByteCount;
548 TimeInterval = 200;
549 } else {
550 /* Turn On LED_1 and blinking if transmitting/receiving */
551 if ((reg->U1BC_LEDConfigure & 0x3000) !=
552 0x1000) {
553 reg->U1BC_LEDConfigure &=
554 ~0x3000;
555 reg->U1BC_LEDConfigure |=
556 0x1000;
557 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
561 break;
562 default: /* Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active */
563 if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
564 reg->U1BC_LEDConfigure |= 0x3000; /* LED_1 is always on and event enable */
565 Wb35Reg_Write(pHwData, 0x03bc,
566 reg->U1BC_LEDConfigure);
569 if (pHwData->LED_Blinking) {
570 /* Gray blinking */
571 reg->U1BC_LEDConfigure &= ~0x0f;
572 reg->U1BC_LEDConfigure |= 0x10;
573 reg->U1BC_LEDConfigure |=
574 LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
575 Wb35Reg_Write(pHwData, 0x03bc,
576 reg->U1BC_LEDConfigure);
578 pHwData->LED_Blinking += 2;
579 if (pHwData->LED_Blinking < 40)
580 TimeInterval = 100;
581 else {
582 pHwData->LED_Blinking = 0; /* Stop blinking */
583 reg->U1BC_LEDConfigure &= ~0x0f;
584 Wb35Reg_Write(pHwData, 0x03bc,
585 reg->U1BC_LEDConfigure);
587 break;
590 if (pHwData->LED_LinkOn) {
591 if (!(reg->U1BC_LEDConfigure & 0x10)) { /* Check the LED_0 */
592 /* Try to turn ON LED_0 after gray blinking */
593 reg->U1BC_LEDConfigure |= 0x10;
594 pHwData->LED_Blinking = 1; /* Start blinking */
595 TimeInterval = 50;
597 } else {
598 if (reg->U1BC_LEDConfigure & 0x10) { /* Check the LED_0 */
599 reg->U1BC_LEDConfigure &= ~0x10;
600 Wb35Reg_Write(pHwData, 0x03bc,
601 reg->U1BC_LEDConfigure);
604 break;
608 pHwData->time_count += TimeInterval;
609 Wb35Tx_CurrentTime(adapter, pHwData->time_count);
610 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
611 add_timer(&pHwData->LEDTimer);
614 static int hal_init_hardware(struct ieee80211_hw *hw)
616 struct wbsoft_priv *priv = hw->priv;
617 struct hw_data *pHwData = &priv->sHwData;
618 u16 SoftwareSet;
620 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
621 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
623 if (!Wb35Reg_initial(pHwData))
624 goto error_reg_destroy;
626 if (!Wb35Tx_initial(pHwData))
627 goto error_tx_destroy;
629 if (!Wb35Rx_initial(pHwData))
630 goto error_rx_destroy;
632 init_timer(&pHwData->LEDTimer);
633 pHwData->LEDTimer.function = hal_led_control;
634 pHwData->LEDTimer.data = (unsigned long)priv;
635 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
636 add_timer(&pHwData->LEDTimer);
638 SoftwareSet = hal_software_set(pHwData);
640 Wb35Rx_start(hw);
641 Wb35Tx_EP2VM_start(priv);
643 return 0;
645 error_rx_destroy:
646 Wb35Rx_destroy(pHwData);
647 error_tx_destroy:
648 Wb35Tx_destroy(pHwData);
649 error_reg_destroy:
650 Wb35Reg_destroy(pHwData);
652 pHwData->SurpriseRemove = 1;
653 return -EINVAL;
656 static int wb35_hw_init(struct ieee80211_hw *hw)
658 struct wbsoft_priv *priv = hw->priv;
659 struct hw_data *pHwData = &priv->sHwData;
660 u8 EEPROM_region;
661 u8 HwRadioOff;
662 u8 *pMacAddr2;
663 u8 *pMacAddr;
664 int err;
666 pHwData->phy_type = RF_DECIDE_BY_INF;
668 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
669 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
671 priv->sLocalPara.region_INF = REGION_AUTO;
672 priv->sLocalPara.TxRateMode = RATE_AUTO;
673 priv->sLocalPara.bMacOperationMode = MODE_802_11_BG;
674 priv->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
675 priv->sLocalPara.bPreambleMode = AUTO_MODE;
676 priv->sLocalPara.bWepKeyError = false;
677 priv->sLocalPara.bToSelfPacketReceived = false;
678 priv->sLocalPara.WepKeyDetectTimerCount = 2 * 100; /* 2 seconds */
680 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
682 err = hal_init_hardware(hw);
683 if (err)
684 goto error;
686 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
687 if (EEPROM_region != REGION_AUTO)
688 priv->sLocalPara.region = EEPROM_region;
689 else {
690 if (priv->sLocalPara.region_INF != REGION_AUTO)
691 priv->sLocalPara.region = priv->sLocalPara.region_INF;
692 else
693 priv->sLocalPara.region = REGION_USA; /* default setting */
696 Mds_initial(priv);
699 * If no user-defined address in the registry, use the address
700 * "burned" on the NIC instead.
702 pMacAddr = priv->sLocalPara.ThisMacAddress;
703 pMacAddr2 = priv->sLocalPara.PermanentAddress;
705 /* Reading ethernet address from EEPROM */
706 hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
707 if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
708 memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
709 else {
710 /* Set the user define MAC address */
711 hal_set_ethernet_address(pHwData,
712 priv->sLocalPara.ThisMacAddress);
715 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
716 pr_debug("Driver init, antenna no = %d\n", priv->sLocalPara.bAntennaNo);
717 hal_get_hw_radio_off(pHwData);
719 /* Waiting for HAL setting OK */
720 while (!hal_idle(pHwData))
721 msleep(10);
723 MTO_Init(priv);
725 HwRadioOff = hal_get_hw_radio_off(pHwData);
726 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
728 hal_set_radio_mode(pHwData,
729 (unsigned char)(priv->sLocalPara.RadioOffStatus.
730 boSwRadioOff
731 || priv->sLocalPara.RadioOffStatus.
732 boHwRadioOff));
734 /* Notify hal that the driver is ready now. */
735 hal_driver_init_OK(pHwData) = 1;
737 error:
738 return err;
741 static int wb35_probe(struct usb_interface *intf,
742 const struct usb_device_id *id_table)
744 struct usb_device *udev = interface_to_usbdev(intf);
745 struct usb_endpoint_descriptor *endpoint;
746 struct usb_host_interface *interface;
747 struct ieee80211_hw *dev;
748 struct wbsoft_priv *priv;
749 int nr, err;
750 u32 ltmp;
752 usb_get_dev(udev);
754 /* Check the device if it already be opened */
755 nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
756 0x01,
757 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
758 0x0, 0x400, &ltmp, 4, HZ * 100);
759 if (nr < 0) {
760 err = nr;
761 goto error;
764 /* Is already initialized? */
765 ltmp = cpu_to_le32(ltmp);
766 if (ltmp) {
767 err = -EBUSY;
768 goto error;
771 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
772 if (!dev) {
773 err = -ENOMEM;
774 goto error;
777 priv = dev->priv;
779 priv->sHwData.udev = udev;
781 interface = intf->cur_altsetting;
782 endpoint = &interface->endpoint[0].desc;
784 if (endpoint[2].wMaxPacketSize == 512)
785 printk("[w35und] Working on USB 2.0\n");
787 err = wb35_hw_init(dev);
788 if (err)
789 goto error_free_hw;
791 SET_IEEE80211_DEV(dev, &udev->dev);
793 struct hw_data *pHwData = &priv->sHwData;
794 unsigned char dev_addr[MAX_ADDR_LEN];
795 hal_get_permanent_address(pHwData, dev_addr);
796 SET_IEEE80211_PERM_ADDR(dev, dev_addr);
799 dev->extra_tx_headroom = 12; /* FIXME */
800 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
801 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
803 dev->channel_change_time = 1000;
804 dev->max_signal = 100;
805 dev->queues = 1;
807 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
809 err = ieee80211_register_hw(dev);
810 if (err)
811 goto error_free_hw;
813 usb_set_intfdata(intf, dev);
815 return 0;
817 error_free_hw:
818 ieee80211_free_hw(dev);
819 error:
820 usb_put_dev(udev);
821 return err;
824 static void hal_halt(struct hw_data *pHwData)
826 del_timer_sync(&pHwData->LEDTimer);
827 /* XXX: Wait for Timer DPC exit. */
828 msleep(100);
829 Wb35Rx_destroy(pHwData);
830 Wb35Tx_destroy(pHwData);
831 Wb35Reg_destroy(pHwData);
834 static void wb35_hw_halt(struct wbsoft_priv *adapter)
836 /* Turn off Rx and Tx hardware ability */
837 hal_stop(&adapter->sHwData);
838 pr_debug("[w35und] Hal_stop O.K.\n");
839 /* Waiting Irp completed */
840 msleep(100);
842 hal_halt(&adapter->sHwData);
845 static void wb35_disconnect(struct usb_interface *intf)
847 struct ieee80211_hw *hw = usb_get_intfdata(intf);
848 struct wbsoft_priv *priv = hw->priv;
850 wb35_hw_halt(priv);
852 ieee80211_stop_queues(hw);
853 ieee80211_unregister_hw(hw);
854 ieee80211_free_hw(hw);
856 usb_set_intfdata(intf, NULL);
857 usb_put_dev(interface_to_usbdev(intf));
860 static struct usb_driver wb35_driver = {
861 .name = "w35und",
862 .id_table = wb35_table,
863 .probe = wb35_probe,
864 .disconnect = wb35_disconnect,
867 static int __init wb35_init(void)
869 return usb_register(&wb35_driver);
872 static void __exit wb35_exit(void)
874 usb_deregister(&wb35_driver);
877 module_init(wb35_init);
878 module_exit(wb35_exit);