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>
19 #include "wb35reg_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) },
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
)
59 if (pHwData
->SurpriseRemove
)
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
);
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__
);
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
,
107 unsigned int new_flags
;
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
++;
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.
146 static int wbsoft_start(struct ieee80211_hw
*dev
)
148 struct wbsoft_priv
*priv
= dev
->priv
;
150 priv
->enabled
= true;
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
)
162 if (radio_off
) { /* disable Baseband receive off */
163 pHwData
->CurrentRadioSw
= 1; /* off */
164 reg
->M24_MacControl
&= 0xffffffbf;
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
)
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
,
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
)
204 reg
->M00_MacControl
&= ~0x02000000; /* The HW value */
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
)
221 reg
->M00_MacControl
|= 0x00400000;
222 Wb35Reg_Write(pHwData
, 0x0800, reg
->M00_MacControl
);
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
)
236 reg
->M00_MacControl
&= ~0x01000000; /* The HW value */
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
)
249 if (!enable
) /* Due to SME and MLME are not suitable for 35 */
252 reg
->M00_MacControl
&= ~0x04000000; /* The HW value */
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
;
264 printk("wbsoft_config called\n");
266 /* Should use channel_num, or something, as that is already pre-translated */
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);
280 static u64
wbsoft_get_tsf(struct ieee80211_hw
*dev
)
282 printk("wbsoft_get_tsf called\n");
286 static const struct ieee80211_ops wbsoft_ops
= {
288 .start
= wbsoft_start
,
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
)
303 if (pHwData
->SurpriseRemove
)
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
)
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
)
346 u8
hal_get_antenna_number(struct hw_data
*pHwData
)
348 struct wb35_reg
*reg
= &pHwData
->reg
;
350 if ((reg
->BB2C
& BIT(11)) == 0)
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
)
364 /* read the bit16 of register U1B0 */
365 Wb35Reg_Read(pHwData
, 0x3b0, ®
->U1B0
);
366 if ((reg
->U1B0
& 0x00010000)) {
367 pHwData
->CurrentRadioHw
= 1;
370 pHwData
->CurrentRadioHw
= 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
;
393 if (pHwData
->SurpriseRemove
)
396 if (pHwData
->LED_control
) {
397 ltmp2
= pHwData
->LED_control
& 0xff;
398 if (ltmp2
== 5) { /* 5 is WPS mode */
400 ltmp2
= (pHwData
->LED_control
>> 8) & 0xff;
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 */
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 */
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 */
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. */
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
);
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;
452 reg
->U1BC_LEDConfigure
&= ~0x10;
453 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 Off */
454 pHwData
->LED_Blinking
= 0;
459 if (reg
->U1BC_LEDConfigure
& 0x10) {
460 reg
->U1BC_LEDConfigure
&= ~0x10;
461 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 Off */
466 if ((reg
->U1BC_LEDConfigure
& 0x10) == 0) {
467 reg
->U1BC_LEDConfigure
|= 0x10;
468 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 Off */
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;
483 reg
->U1BC_LEDConfigure
&= ~0x1f;
484 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 Off */
485 pHwData
->LED_Blinking
= 0;
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 */
504 if ((reg
->U1BC_LEDConfigure
& 0x10) == 0) {
505 reg
->U1BC_LEDConfigure
|= 0x10;
506 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 Off */
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;
520 reg
->U1BC_LEDConfigure
&= ~0x1000;
521 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_1 Off */
522 pHwData
->LED_Blinking
= 0;
527 if (reg
->U1BC_LEDConfigure
& 0x1000) {
528 reg
->U1BC_LEDConfigure
&= ~0x1000;
529 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_1 Off */
533 /* Is transmitting/receiving ?? */
534 if ((adapter
->RxByteCount
!=
535 pHwData
->RxByteCountLast
)
536 || (adapter
->TxByteCount
!=
537 pHwData
->TxByteCountLast
)) {
538 if ((reg
->U1BC_LEDConfigure
& 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
;
550 /* Turn On LED_1 and blinking if transmitting/receiving */
551 if ((reg
->U1BC_LEDConfigure
& 0x3000) !=
553 reg
->U1BC_LEDConfigure
&=
555 reg
->U1BC_LEDConfigure
|=
557 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_1 On */
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
) {
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)
582 pHwData
->LED_Blinking
= 0; /* Stop blinking */
583 reg
->U1BC_LEDConfigure
&= ~0x0f;
584 Wb35Reg_Write(pHwData
, 0x03bc,
585 reg
->U1BC_LEDConfigure
);
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 */
598 if (reg
->U1BC_LEDConfigure
& 0x10) { /* Check the LED_0 */
599 reg
->U1BC_LEDConfigure
&= ~0x10;
600 Wb35Reg_Write(pHwData
, 0x03bc,
601 reg
->U1BC_LEDConfigure
);
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
;
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
);
641 Wb35Tx_EP2VM_start(priv
);
646 Wb35Rx_destroy(pHwData
);
648 Wb35Tx_destroy(pHwData
);
650 Wb35Reg_destroy(pHwData
);
652 pHwData
->SurpriseRemove
= 1;
656 static int wb35_hw_init(struct ieee80211_hw
*hw
)
658 struct wbsoft_priv
*priv
= hw
->priv
;
659 struct hw_data
*pHwData
= &priv
->sHwData
;
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
);
686 EEPROM_region
= hal_get_region_from_EEPROM(pHwData
);
687 if (EEPROM_region
!= REGION_AUTO
)
688 priv
->sLocalPara
.region
= EEPROM_region
;
690 if (priv
->sLocalPara
.region_INF
!= REGION_AUTO
)
691 priv
->sLocalPara
.region
= priv
->sLocalPara
.region_INF
;
693 priv
->sLocalPara
.region
= REGION_USA
; /* default setting */
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
);
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
))
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
.
731 || priv
->sLocalPara
.RadioOffStatus
.
734 /* Notify hal that the driver is ready now. */
735 hal_driver_init_OK(pHwData
) = 1;
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
;
754 /* Check the device if it already be opened */
755 nr
= usb_control_msg(udev
, usb_rcvctrlpipe(udev
, 0),
757 USB_TYPE_VENDOR
| USB_RECIP_DEVICE
| USB_DIR_IN
,
758 0x0, 0x400, <mp
, 4, HZ
* 100);
764 /* Is already initialized? */
765 ltmp
= cpu_to_le32(ltmp
);
771 dev
= ieee80211_alloc_hw(sizeof(*priv
), &wbsoft_ops
);
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
);
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;
807 dev
->wiphy
->bands
[IEEE80211_BAND_2GHZ
] = &wbsoft_band_2GHz
;
809 err
= ieee80211_register_hw(dev
);
813 usb_set_intfdata(intf
, dev
);
818 ieee80211_free_hw(dev
);
824 static void hal_halt(struct hw_data
*pHwData
)
826 del_timer_sync(&pHwData
->LEDTimer
);
827 /* XXX: Wait for Timer DPC exit. */
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 */
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
;
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
= {
862 .id_table
= wb35_table
,
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
);