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>
14 #include <linux/module.h>
20 #include "wb35reg_f.h"
24 MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
25 MODULE_LICENSE("GPL");
26 MODULE_VERSION("0.1");
28 static const struct usb_device_id wb35_table
[] = {
29 { USB_DEVICE(0x0416, 0x0035) },
30 { USB_DEVICE(0x18E8, 0x6201) },
31 { USB_DEVICE(0x18E8, 0x6206) },
32 { USB_DEVICE(0x18E8, 0x6217) },
33 { USB_DEVICE(0x18E8, 0x6230) },
34 { USB_DEVICE(0x18E8, 0x6233) },
35 { USB_DEVICE(0x1131, 0x2035) },
39 MODULE_DEVICE_TABLE(usb
, wb35_table
);
41 static struct ieee80211_rate wbsoft_rates
[] = {
42 { .bitrate
= 10, .flags
= IEEE80211_RATE_SHORT_PREAMBLE
},
45 static struct ieee80211_channel wbsoft_channels
[] = {
46 { .center_freq
= 2412 },
49 static 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
),
56 static void hal_set_beacon_period(struct hw_data
*pHwData
, u16 beacon_period
)
60 if (pHwData
->SurpriseRemove
)
63 pHwData
->BeaconPeriod
= beacon_period
;
64 tmp
= pHwData
->BeaconPeriod
<< 16;
65 tmp
|= pHwData
->ProbeDelay
;
66 Wb35Reg_Write(pHwData
, 0x0848, tmp
);
69 static int wbsoft_add_interface(struct ieee80211_hw
*dev
,
70 struct ieee80211_vif
*vif
)
72 struct wbsoft_priv
*priv
= dev
->priv
;
74 hal_set_beacon_period(&priv
->sHwData
, vif
->bss_conf
.beacon_int
);
79 static void wbsoft_remove_interface(struct ieee80211_hw
*dev
,
80 struct ieee80211_vif
*vif
)
84 static void wbsoft_stop(struct ieee80211_hw
*hw
)
88 static int wbsoft_get_stats(struct ieee80211_hw
*hw
,
89 struct ieee80211_low_level_stats
*stats
)
94 static u64
wbsoft_prepare_multicast(struct ieee80211_hw
*hw
,
95 struct netdev_hw_addr_list
*mc_list
)
97 return netdev_hw_addr_list_count(mc_list
);
100 static void wbsoft_configure_filter(struct ieee80211_hw
*dev
,
101 unsigned int changed_flags
,
102 unsigned int *total_flags
,
105 unsigned int new_flags
;
109 if (*total_flags
& FIF_PROMISC_IN_BSS
)
110 new_flags
|= FIF_PROMISC_IN_BSS
;
111 else if ((*total_flags
& FIF_ALLMULTI
) || (multicast
> 32))
112 new_flags
|= FIF_ALLMULTI
;
114 dev
->flags
&= ~IEEE80211_HW_RX_INCLUDES_FCS
;
116 *total_flags
= new_flags
;
119 static void wbsoft_tx(struct ieee80211_hw
*dev
,
120 struct ieee80211_tx_control
*control
,
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 RFSynthesizer_SwitchingChannel(pHwData
, channel
); /* Switch channel */
180 pHwData
->Channel
= channel
.ChanNo
;
181 pHwData
->band
= channel
.band
;
182 reg
->M28_MacControl
&= ~0xff; /* Clean channel information field */
183 reg
->M28_MacControl
|= channel
.ChanNo
;
184 Wb35Reg_WriteWithCallbackValue(pHwData
, 0x0828, reg
->M28_MacControl
,
186 sizeof(struct chan_info
));
189 static void hal_set_current_channel(struct hw_data
*pHwData
, struct chan_info channel
)
191 hal_set_current_channel_ex(pHwData
, channel
);
194 static void hal_set_accept_broadcast(struct hw_data
*pHwData
, u8 enable
)
196 struct wb35_reg
*reg
= &pHwData
->reg
;
198 if (pHwData
->SurpriseRemove
)
201 reg
->M00_MacControl
&= ~0x02000000; /* The HW value */
204 reg
->M00_MacControl
|= 0x02000000; /* The HW value */
206 Wb35Reg_Write(pHwData
, 0x0800, reg
->M00_MacControl
);
209 /* For wep key error detection, we need to accept broadcast packets to be received temporary. */
210 static void hal_set_accept_promiscuous(struct hw_data
*pHwData
, u8 enable
)
212 struct wb35_reg
*reg
= &pHwData
->reg
;
214 if (pHwData
->SurpriseRemove
)
218 reg
->M00_MacControl
|= 0x00400000;
219 Wb35Reg_Write(pHwData
, 0x0800, reg
->M00_MacControl
);
221 reg
->M00_MacControl
&= ~0x00400000;
222 Wb35Reg_Write(pHwData
, 0x0800, reg
->M00_MacControl
);
226 static void hal_set_accept_multicast(struct hw_data
*pHwData
, u8 enable
)
228 struct wb35_reg
*reg
= &pHwData
->reg
;
230 if (pHwData
->SurpriseRemove
)
233 reg
->M00_MacControl
&= ~0x01000000; /* The HW value */
235 reg
->M00_MacControl
|= 0x01000000; /* The HW value */
236 Wb35Reg_Write(pHwData
, 0x0800, reg
->M00_MacControl
);
239 static void hal_set_accept_beacon(struct hw_data
*pHwData
, u8 enable
)
241 struct wb35_reg
*reg
= &pHwData
->reg
;
243 if (pHwData
->SurpriseRemove
)
246 if (!enable
) /* Due to SME and MLME are not suitable for 35 */
249 reg
->M00_MacControl
&= ~0x04000000; /* The HW value */
251 reg
->M00_MacControl
|= 0x04000000; /* The HW value */
253 Wb35Reg_Write(pHwData
, 0x0800, reg
->M00_MacControl
);
256 static int wbsoft_config(struct ieee80211_hw
*dev
, u32 changed
)
258 struct wbsoft_priv
*priv
= dev
->priv
;
261 /* Should use channel_num, or something, as that is already pre-translated */
265 hal_set_current_channel(&priv
->sHwData
, ch
);
266 hal_set_accept_broadcast(&priv
->sHwData
, 1);
267 hal_set_accept_promiscuous(&priv
->sHwData
, 1);
268 hal_set_accept_multicast(&priv
->sHwData
, 1);
269 hal_set_accept_beacon(&priv
->sHwData
, 1);
270 hal_set_radio_mode(&priv
->sHwData
, 0);
275 static u64
wbsoft_get_tsf(struct ieee80211_hw
*dev
, struct ieee80211_vif
*vif
)
280 static const struct ieee80211_ops wbsoft_ops
= {
282 .start
= wbsoft_start
,
284 .add_interface
= wbsoft_add_interface
,
285 .remove_interface
= wbsoft_remove_interface
,
286 .config
= wbsoft_config
,
287 .prepare_multicast
= wbsoft_prepare_multicast
,
288 .configure_filter
= wbsoft_configure_filter
,
289 .get_stats
= wbsoft_get_stats
,
290 .get_tsf
= wbsoft_get_tsf
,
293 static void hal_set_ethernet_address(struct hw_data
*pHwData
, u8
*current_address
)
297 if (pHwData
->SurpriseRemove
)
300 memcpy(pHwData
->CurrentMacAddress
, current_address
, ETH_ALEN
);
302 ltmp
[0] = cpu_to_le32(*(u32
*) pHwData
->CurrentMacAddress
);
303 ltmp
[1] = cpu_to_le32(*(u32
*) (pHwData
->CurrentMacAddress
+ 4)) & 0xffff;
305 Wb35Reg_BurstWrite(pHwData
, 0x03e8, ltmp
, 2, AUTO_INCREMENT
);
308 static void hal_get_permanent_address(struct hw_data
*pHwData
, u8
*pethernet_address
)
310 if (pHwData
->SurpriseRemove
)
313 memcpy(pethernet_address
, pHwData
->PermanentMacAddress
, 6);
316 static void hal_stop(struct hw_data
*pHwData
)
318 struct wb35_reg
*reg
= &pHwData
->reg
;
320 pHwData
->Wb35Rx
.rx_halt
= 1;
321 Wb35Rx_stop(pHwData
);
323 pHwData
->Wb35Tx
.tx_halt
= 1;
324 Wb35Tx_stop(pHwData
);
326 reg
->D00_DmaControl
&= ~0xc0000000; /* Tx Off, Rx Off */
327 Wb35Reg_Write(pHwData
, 0x0400, reg
->D00_DmaControl
);
330 static unsigned char hal_idle(struct hw_data
*pHwData
)
332 struct wb35_reg
*reg
= &pHwData
->reg
;
334 if (!pHwData
->SurpriseRemove
&& reg
->EP0vm_state
!= VM_STOP
)
340 u8
hal_get_antenna_number(struct hw_data
*pHwData
)
342 struct wb35_reg
*reg
= &pHwData
->reg
;
344 if ((reg
->BB2C
& BIT(11)) == 0)
350 /* 0 : radio on; 1: radio off */
351 static u8
hal_get_hw_radio_off(struct hw_data
*pHwData
)
353 struct wb35_reg
*reg
= &pHwData
->reg
;
355 if (pHwData
->SurpriseRemove
)
358 /* read the bit16 of register U1B0 */
359 Wb35Reg_Read(pHwData
, 0x3b0, ®
->U1B0
);
360 if ((reg
->U1B0
& 0x00010000)) {
361 pHwData
->CurrentRadioHw
= 1;
364 pHwData
->CurrentRadioHw
= 0;
369 static u8 LED_GRAY
[20] = {
370 0, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2
373 static u8 LED_GRAY2
[30] = {
374 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
375 0, 15, 14, 13, 12, 11, 10, 9, 8
378 static void hal_led_control(unsigned long data
)
380 struct wbsoft_priv
*adapter
= (struct wbsoft_priv
*)data
;
381 struct hw_data
*pHwData
= &adapter
->sHwData
;
382 struct wb35_reg
*reg
= &pHwData
->reg
;
383 u32 LEDSet
= (pHwData
->SoftwareSet
& HAL_LED_SET_MASK
) >> HAL_LED_SET_SHIFT
;
384 u32 TimeInterval
= 500, ltmp
, ltmp2
;
387 if (pHwData
->SurpriseRemove
)
390 if (pHwData
->LED_control
) {
391 ltmp2
= pHwData
->LED_control
& 0xff;
392 if (ltmp2
== 5) { /* 5 is WPS mode */
394 ltmp2
= (pHwData
->LED_control
>> 8) & 0xff;
396 case 1: /* [0.2 On][0.1 Off]... */
397 pHwData
->LED_Blinking
%= 3;
398 ltmp
= 0x1010; /* Led 1 & 0 Green and Red */
399 if (pHwData
->LED_Blinking
== 2) /* Turn off */
402 case 2: /* [0.1 On][0.1 Off]... */
403 pHwData
->LED_Blinking
%= 2;
404 ltmp
= 0x0010; /* Led 0 red color */
405 if (pHwData
->LED_Blinking
) /* Turn off */
408 case 3: /* [0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.5 Off]... */
409 pHwData
->LED_Blinking
%= 15;
410 ltmp
= 0x0010; /* Led 0 red color */
411 if ((pHwData
->LED_Blinking
>= 9) || (pHwData
->LED_Blinking
% 2)) /* Turn off 0.6 sec */
414 case 4: /* [300 On][ off ] */
415 ltmp
= 0x1000; /* Led 1 Green color */
416 if (pHwData
->LED_Blinking
>= 3000)
417 ltmp
= 0; /* led maybe on after 300sec * 32bit counter overlap. */
420 pHwData
->LED_Blinking
++;
422 reg
->U1BC_LEDConfigure
= ltmp
;
423 if (LEDSet
!= 7) { /* Only 111 mode has 2 LEDs on PCB. */
424 reg
->U1BC_LEDConfigure
|= (ltmp
& 0xff) << 8; /* Copy LED result to each LED control register */
425 reg
->U1BC_LEDConfigure
|= (ltmp
& 0xff00) >> 8;
427 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
);
429 } else if (pHwData
->CurrentRadioSw
|| pHwData
->CurrentRadioHw
) { /* If radio off */
430 if (reg
->U1BC_LEDConfigure
& 0x1010) {
431 reg
->U1BC_LEDConfigure
&= ~0x1010;
432 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
);
436 case 4: /* [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
437 if (!pHwData
->LED_LinkOn
) { /* Blink only if not Link On */
438 /* Blinking if scanning is on progress */
439 if (pHwData
->LED_Scanning
) {
440 if (pHwData
->LED_Blinking
== 0) {
441 reg
->U1BC_LEDConfigure
|= 0x10;
442 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 On */
443 pHwData
->LED_Blinking
= 1;
446 reg
->U1BC_LEDConfigure
&= ~0x10;
447 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 Off */
448 pHwData
->LED_Blinking
= 0;
453 if (reg
->U1BC_LEDConfigure
& 0x10) {
454 reg
->U1BC_LEDConfigure
&= ~0x10;
455 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 Off */
460 if ((reg
->U1BC_LEDConfigure
& 0x10) == 0) {
461 reg
->U1BC_LEDConfigure
|= 0x10;
462 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 Off */
466 case 6: /* [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
467 if (!pHwData
->LED_LinkOn
) { /* Blink only if not Link On */
468 /* Blinking if scanning is on progress */
469 if (pHwData
->LED_Scanning
) {
470 if (pHwData
->LED_Blinking
== 0) {
471 reg
->U1BC_LEDConfigure
&= ~0xf;
472 reg
->U1BC_LEDConfigure
|= 0x10;
473 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 On */
474 pHwData
->LED_Blinking
= 1;
477 reg
->U1BC_LEDConfigure
&= ~0x1f;
478 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 Off */
479 pHwData
->LED_Blinking
= 0;
483 /* Gray blinking if in disconnect state and not scanning */
484 ltmp
= reg
->U1BC_LEDConfigure
;
485 reg
->U1BC_LEDConfigure
&= ~0x1f;
486 if (LED_GRAY2
[(pHwData
->LED_Blinking
% 30)]) {
487 reg
->U1BC_LEDConfigure
|= 0x10;
488 reg
->U1BC_LEDConfigure
|=
489 LED_GRAY2
[(pHwData
->LED_Blinking
% 30)];
491 pHwData
->LED_Blinking
++;
492 if (reg
->U1BC_LEDConfigure
!= ltmp
)
493 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 Off */
498 if ((reg
->U1BC_LEDConfigure
& 0x10) == 0) {
499 reg
->U1BC_LEDConfigure
|= 0x10;
500 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_0 Off */
504 case 5: /* [101] Only 1 Led be placed on PCB and use LED_1 for showing */
505 if (!pHwData
->LED_LinkOn
) { /* Blink only if not Link On */
506 /* Blinking if scanning is on progress */
507 if (pHwData
->LED_Scanning
) {
508 if (pHwData
->LED_Blinking
== 0) {
509 reg
->U1BC_LEDConfigure
|= 0x1000;
510 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_1 On */
511 pHwData
->LED_Blinking
= 1;
514 reg
->U1BC_LEDConfigure
&= ~0x1000;
515 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_1 Off */
516 pHwData
->LED_Blinking
= 0;
521 if (reg
->U1BC_LEDConfigure
& 0x1000) {
522 reg
->U1BC_LEDConfigure
&= ~0x1000;
523 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_1 Off */
527 /* Is transmitting/receiving ?? */
528 if ((adapter
->RxByteCount
!=
529 pHwData
->RxByteCountLast
)
530 || (adapter
->TxByteCount
!=
531 pHwData
->TxByteCountLast
)) {
532 if ((reg
->U1BC_LEDConfigure
& 0x3000) !=
534 reg
->U1BC_LEDConfigure
|= 0x3000;
535 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_1 On */
537 /* Update variable */
538 pHwData
->RxByteCountLast
=
539 adapter
->RxByteCount
;
540 pHwData
->TxByteCountLast
=
541 adapter
->TxByteCount
;
544 /* Turn On LED_1 and blinking if transmitting/receiving */
545 if ((reg
->U1BC_LEDConfigure
& 0x3000) !=
547 reg
->U1BC_LEDConfigure
&=
549 reg
->U1BC_LEDConfigure
|=
551 Wb35Reg_Write(pHwData
, 0x03bc, reg
->U1BC_LEDConfigure
); /* LED_1 On */
556 default: /* Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active */
557 if ((reg
->U1BC_LEDConfigure
& 0x3000) != 0x3000) {
558 reg
->U1BC_LEDConfigure
|= 0x3000; /* LED_1 is always on and event enable */
559 Wb35Reg_Write(pHwData
, 0x03bc,
560 reg
->U1BC_LEDConfigure
);
563 if (pHwData
->LED_Blinking
) {
565 reg
->U1BC_LEDConfigure
&= ~0x0f;
566 reg
->U1BC_LEDConfigure
|= 0x10;
567 reg
->U1BC_LEDConfigure
|=
568 LED_GRAY
[(pHwData
->LED_Blinking
- 1) % 20];
569 Wb35Reg_Write(pHwData
, 0x03bc,
570 reg
->U1BC_LEDConfigure
);
572 pHwData
->LED_Blinking
+= 2;
573 if (pHwData
->LED_Blinking
< 40)
576 pHwData
->LED_Blinking
= 0; /* Stop blinking */
577 reg
->U1BC_LEDConfigure
&= ~0x0f;
578 Wb35Reg_Write(pHwData
, 0x03bc,
579 reg
->U1BC_LEDConfigure
);
584 if (pHwData
->LED_LinkOn
) {
585 if (!(reg
->U1BC_LEDConfigure
& 0x10)) { /* Check the LED_0 */
586 /* Try to turn ON LED_0 after gray blinking */
587 reg
->U1BC_LEDConfigure
|= 0x10;
588 pHwData
->LED_Blinking
= 1; /* Start blinking */
592 if (reg
->U1BC_LEDConfigure
& 0x10) { /* Check the LED_0 */
593 reg
->U1BC_LEDConfigure
&= ~0x10;
594 Wb35Reg_Write(pHwData
, 0x03bc,
595 reg
->U1BC_LEDConfigure
);
602 pHwData
->time_count
+= TimeInterval
;
603 Wb35Tx_CurrentTime(adapter
, pHwData
->time_count
);
604 pHwData
->LEDTimer
.expires
= jiffies
+ msecs_to_jiffies(TimeInterval
);
605 add_timer(&pHwData
->LEDTimer
);
608 static int hal_init_hardware(struct ieee80211_hw
*hw
)
610 struct wbsoft_priv
*priv
= hw
->priv
;
611 struct hw_data
*pHwData
= &priv
->sHwData
;
614 pHwData
->MaxReceiveLifeTime
= DEFAULT_MSDU_LIFE_TIME
;
615 pHwData
->FragmentThreshold
= DEFAULT_FRAGMENT_THRESHOLD
;
617 if (!Wb35Reg_initial(pHwData
))
618 goto error_reg_destroy
;
620 if (!Wb35Tx_initial(pHwData
))
621 goto error_tx_destroy
;
623 if (!Wb35Rx_initial(pHwData
))
624 goto error_rx_destroy
;
626 init_timer(&pHwData
->LEDTimer
);
627 pHwData
->LEDTimer
.function
= hal_led_control
;
628 pHwData
->LEDTimer
.data
= (unsigned long)priv
;
629 pHwData
->LEDTimer
.expires
= jiffies
+ msecs_to_jiffies(1000);
630 add_timer(&pHwData
->LEDTimer
);
632 SoftwareSet
= hal_software_set(pHwData
);
635 Wb35Tx_EP2VM_start(priv
);
640 Wb35Rx_destroy(pHwData
);
642 Wb35Tx_destroy(pHwData
);
644 Wb35Reg_destroy(pHwData
);
646 pHwData
->SurpriseRemove
= 1;
650 static int wb35_hw_init(struct ieee80211_hw
*hw
)
652 struct wbsoft_priv
*priv
= hw
->priv
;
653 struct hw_data
*pHwData
= &priv
->sHwData
;
660 pHwData
->phy_type
= RF_DECIDE_BY_INF
;
662 priv
->Mds
.TxRTSThreshold
= DEFAULT_RTSThreshold
;
663 priv
->Mds
.TxFragmentThreshold
= DEFAULT_FRAGMENT_THRESHOLD
;
665 priv
->sLocalPara
.region_INF
= REGION_AUTO
;
666 priv
->sLocalPara
.TxRateMode
= RATE_AUTO
;
667 priv
->sLocalPara
.bMacOperationMode
= MODE_802_11_BG
;
668 priv
->sLocalPara
.MTUsize
= MAX_ETHERNET_PACKET_SIZE
;
669 priv
->sLocalPara
.bPreambleMode
= AUTO_MODE
;
670 priv
->sLocalPara
.bWepKeyError
= false;
671 priv
->sLocalPara
.bToSelfPacketReceived
= false;
672 priv
->sLocalPara
.WepKeyDetectTimerCount
= 2 * 100; /* 2 seconds */
674 priv
->sLocalPara
.RadioOffStatus
.boSwRadioOff
= false;
676 err
= hal_init_hardware(hw
);
680 EEPROM_region
= hal_get_region_from_EEPROM(pHwData
);
681 if (EEPROM_region
!= REGION_AUTO
)
682 priv
->sLocalPara
.region
= EEPROM_region
;
684 if (priv
->sLocalPara
.region_INF
!= REGION_AUTO
)
685 priv
->sLocalPara
.region
= priv
->sLocalPara
.region_INF
;
687 priv
->sLocalPara
.region
= REGION_USA
; /* default setting */
693 * If no user-defined address in the registry, use the address
694 * "burned" on the NIC instead.
696 pMacAddr
= priv
->sLocalPara
.ThisMacAddress
;
697 pMacAddr2
= priv
->sLocalPara
.PermanentAddress
;
699 /* Reading ethernet address from EEPROM */
700 hal_get_permanent_address(pHwData
, priv
->sLocalPara
.PermanentAddress
);
701 if (memcmp(pMacAddr
, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH
) == 0)
702 memcpy(pMacAddr
, pMacAddr2
, MAC_ADDR_LENGTH
);
704 /* Set the user define MAC address */
705 hal_set_ethernet_address(pHwData
,
706 priv
->sLocalPara
.ThisMacAddress
);
709 priv
->sLocalPara
.bAntennaNo
= hal_get_antenna_number(pHwData
);
710 hal_get_hw_radio_off(pHwData
);
712 /* Waiting for HAL setting OK */
713 while (!hal_idle(pHwData
))
718 HwRadioOff
= hal_get_hw_radio_off(pHwData
);
719 priv
->sLocalPara
.RadioOffStatus
.boHwRadioOff
= !!HwRadioOff
;
721 hal_set_radio_mode(pHwData
,
722 (unsigned char)(priv
->sLocalPara
.RadioOffStatus
.
724 || priv
->sLocalPara
.RadioOffStatus
.
727 /* Notify hal that the driver is ready now. */
728 hal_driver_init_OK(pHwData
) = 1;
734 static int wb35_probe(struct usb_interface
*intf
,
735 const struct usb_device_id
*id_table
)
737 struct usb_device
*udev
= interface_to_usbdev(intf
);
738 struct usb_endpoint_descriptor
*endpoint
;
739 struct usb_host_interface
*interface
;
740 struct ieee80211_hw
*dev
;
741 struct wbsoft_priv
*priv
;
747 /* Check the device if it already be opened */
748 err
= usb_control_msg(udev
, usb_rcvctrlpipe(udev
, 0),
750 USB_TYPE_VENDOR
| USB_RECIP_DEVICE
| USB_DIR_IN
,
751 0x0, 0x400, <mp
, 4, HZ
* 100);
755 /* Is already initialized? */
756 ltmp
= cpu_to_le32(ltmp
);
762 dev
= ieee80211_alloc_hw(sizeof(*priv
), &wbsoft_ops
);
770 priv
->sHwData
.udev
= udev
;
772 interface
= intf
->cur_altsetting
;
773 endpoint
= &interface
->endpoint
[0].desc
;
775 err
= wb35_hw_init(dev
);
779 SET_IEEE80211_DEV(dev
, &udev
->dev
);
781 struct hw_data
*pHwData
= &priv
->sHwData
;
782 unsigned char dev_addr
[MAX_ADDR_LEN
];
783 hal_get_permanent_address(pHwData
, dev_addr
);
784 SET_IEEE80211_PERM_ADDR(dev
, dev_addr
);
787 dev
->extra_tx_headroom
= 12; /* FIXME */
788 dev
->flags
= IEEE80211_HW_SIGNAL_UNSPEC
;
789 dev
->wiphy
->interface_modes
= BIT(NL80211_IFTYPE_STATION
);
791 dev
->channel_change_time
= 1000;
792 dev
->max_signal
= 100;
795 dev
->wiphy
->bands
[IEEE80211_BAND_2GHZ
] = &wbsoft_band_2GHz
;
797 err
= ieee80211_register_hw(dev
);
801 usb_set_intfdata(intf
, dev
);
806 ieee80211_free_hw(dev
);
812 static void hal_halt(struct hw_data
*pHwData
)
814 del_timer_sync(&pHwData
->LEDTimer
);
815 /* XXX: Wait for Timer DPC exit. */
817 Wb35Rx_destroy(pHwData
);
818 Wb35Tx_destroy(pHwData
);
819 Wb35Reg_destroy(pHwData
);
822 static void wb35_hw_halt(struct wbsoft_priv
*adapter
)
824 /* Turn off Rx and Tx hardware ability */
825 hal_stop(&adapter
->sHwData
);
826 /* Waiting Irp completed */
829 hal_halt(&adapter
->sHwData
);
832 static void wb35_disconnect(struct usb_interface
*intf
)
834 struct ieee80211_hw
*hw
= usb_get_intfdata(intf
);
835 struct wbsoft_priv
*priv
= hw
->priv
;
839 ieee80211_stop_queues(hw
);
840 ieee80211_unregister_hw(hw
);
841 ieee80211_free_hw(hw
);
843 usb_set_intfdata(intf
, NULL
);
844 usb_put_dev(interface_to_usbdev(intf
));
847 static struct usb_driver wb35_driver
= {
849 .id_table
= wb35_table
,
851 .disconnect
= wb35_disconnect
,
854 module_usb_driver(wb35_driver
);