1
2
3
4
5
6
7
8
9
10
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[] = {
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}
83
84static void wbsoft_stop(struct ieee80211_hw *hw)
85{
86}
87
88static int wbsoft_get_stats(struct ieee80211_hw *hw,
89 struct ieee80211_low_level_stats *stats)
90{
91 return 0;
92}
93
94static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw,
95 struct netdev_hw_addr_list *mc_list)
96{
97 return netdev_hw_addr_list_count(mc_list);
98}
99
100static void wbsoft_configure_filter(struct ieee80211_hw *dev,
101 unsigned int changed_flags,
102 unsigned int *total_flags,
103 u64 multicast)
104{
105 unsigned int new_flags;
106
107 new_flags = 0;
108
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;
113
114 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
115
116 *total_flags = new_flags;
117}
118
119static void wbsoft_tx(struct ieee80211_hw *dev,
120 struct ieee80211_tx_control *control,
121 struct sk_buff *skb)
122{
123 struct wbsoft_priv *priv = dev->priv;
124
125 if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
126 priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
127 kfree_skb(skb);
128 return;
129 }
130
131 priv->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
132
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++;
137
138
139
140
141
142
143 Mds_Tx(priv);
144}
145
146static int wbsoft_start(struct ieee80211_hw *dev)
147{
148 struct wbsoft_priv *priv = dev->priv;
149
150 priv->enabled = true;
151
152 return 0;
153}
154
155static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
156{
157 struct wb35_reg *reg = &pHwData->reg;
158
159 if (pHwData->SurpriseRemove)
160 return;
161
162 if (radio_off) {
163 pHwData->CurrentRadioSw = 1;
164 reg->M24_MacControl &= 0xffffffbf;
165 } else {
166 pHwData->CurrentRadioSw = 0;
167 reg->M24_MacControl |= 0x00000040;
168 }
169 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
170}
171
172static void hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
173{
174 struct wb35_reg *reg = &pHwData->reg;
175
176 if (pHwData->SurpriseRemove)
177 return;
178
179 RFSynthesizer_SwitchingChannel(pHwData, channel);
180 pHwData->Channel = channel.ChanNo;
181 pHwData->band = channel.band;
182 reg->M28_MacControl &= ~0xff;
183 reg->M28_MacControl |= channel.ChanNo;
184 Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
185 (s8 *) &channel,
186 sizeof(struct chan_info));
187}
188
189static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
190{
191 hal_set_current_channel_ex(pHwData, channel);
192}
193
194static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
195{
196 struct wb35_reg *reg = &pHwData->reg;
197
198 if (pHwData->SurpriseRemove)
199 return;
200
201 reg->M00_MacControl &= ~0x02000000;
202
203 if (enable)
204 reg->M00_MacControl |= 0x02000000;
205
206 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
207}
208
209
210static void hal_set_accept_promiscuous(struct hw_data *pHwData, u8 enable)
211{
212 struct wb35_reg *reg = &pHwData->reg;
213
214 if (pHwData->SurpriseRemove)
215 return;
216
217 if (enable) {
218 reg->M00_MacControl |= 0x00400000;
219 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
220 } else {
221 reg->M00_MacControl &= ~0x00400000;
222 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
223 }
224}
225
226static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
227{
228 struct wb35_reg *reg = &pHwData->reg;
229
230 if (pHwData->SurpriseRemove)
231 return;
232
233 reg->M00_MacControl &= ~0x01000000;
234 if (enable)
235 reg->M00_MacControl |= 0x01000000;
236 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
237}
238
239static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
240{
241 struct wb35_reg *reg = &pHwData->reg;
242
243 if (pHwData->SurpriseRemove)
244 return;
245
246 if (!enable)
247 return;
248
249 reg->M00_MacControl &= ~0x04000000;
250 if (enable)
251 reg->M00_MacControl |= 0x04000000;
252
253 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
254}
255
256static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
257{
258 struct wbsoft_priv *priv = dev->priv;
259 struct chan_info ch;
260
261
262 ch.band = 1;
263 ch.ChanNo = 1;
264
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);
271
272 return 0;
273}
274
275static u64 wbsoft_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
276{
277 return 0;
278}
279
280static const struct ieee80211_ops wbsoft_ops = {
281 .tx = wbsoft_tx,
282 .start = wbsoft_start,
283 .stop = wbsoft_stop,
284 .add_interface = wbsoft_add_interface,
285 .remove_interface = wbsoft_remove_interface,
286 .config = wbsoft_config,
287 .prepare_multicast = wbsoft_prepare_multicast,
288 .configure_filter = wbsoft_configure_filter,
289 .get_stats = wbsoft_get_stats,
290 .get_tsf = wbsoft_get_tsf,
291};
292
293static void hal_set_ethernet_address(struct hw_data *pHwData, u8 *current_address)
294{
295 u32 ltmp[2];
296
297 if (pHwData->SurpriseRemove)
298 return;
299
300 memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
301
302 ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
303 ltmp[1] = cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
304
305 Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
306}
307
308static void hal_get_permanent_address(struct hw_data *pHwData, u8 *pethernet_address)
309{
310 if (pHwData->SurpriseRemove)
311 return;
312
313 memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
314}
315
316static void hal_stop(struct hw_data *pHwData)
317{
318 struct wb35_reg *reg = &pHwData->reg;
319
320 pHwData->Wb35Rx.rx_halt = 1;
321 Wb35Rx_stop(pHwData);
322
323 pHwData->Wb35Tx.tx_halt = 1;
324 Wb35Tx_stop(pHwData);
325
326 reg->D00_DmaControl &= ~0xc0000000;
327 Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
328}
329
330static unsigned char hal_idle(struct hw_data *pHwData)
331{
332 struct wb35_reg *reg = &pHwData->reg;
333
334 if (!pHwData->SurpriseRemove && reg->EP0vm_state != VM_STOP)
335 return false;
336
337 return true;
338}
339
340u8 hal_get_antenna_number(struct hw_data *pHwData)
341{
342 struct wb35_reg *reg = &pHwData->reg;
343
344 if ((reg->BB2C & BIT(11)) == 0)
345 return 0;
346 else
347 return 1;
348}
349
350
351static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
352{
353 struct wb35_reg *reg = &pHwData->reg;
354
355 if (pHwData->SurpriseRemove)
356 return 1;
357
358
359 Wb35Reg_Read(pHwData, 0x3b0, ®->U1B0);
360 if ((reg->U1B0 & 0x00010000)) {
361 pHwData->CurrentRadioHw = 1;
362 return 1;
363 } else {
364 pHwData->CurrentRadioHw = 0;
365 return 0;
366 }
367}
368
369static 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
371};
372
373static 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
376};
377
378static void hal_led_control(unsigned long data)
379{
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;
385 ltmp = 0;
386
387 if (pHwData->SurpriseRemove)
388 return;
389
390 if (pHwData->LED_control) {
391 ltmp2 = pHwData->LED_control & 0xff;
392 if (ltmp2 == 5) {
393 TimeInterval = 100;
394 ltmp2 = (pHwData->LED_control >> 8) & 0xff;
395 switch (ltmp2) {
396 case 1:
397 pHwData->LED_Blinking %= 3;
398 ltmp = 0x1010;
399 if (pHwData->LED_Blinking == 2)
400 ltmp = 0;
401 break;
402 case 2:
403 pHwData->LED_Blinking %= 2;
404 ltmp = 0x0010;
405 if (pHwData->LED_Blinking)
406 ltmp = 0;
407 break;
408 case 3:
409 pHwData->LED_Blinking %= 15;
410 ltmp = 0x0010;
411 if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2))
412 ltmp = 0;
413 break;
414 case 4:
415 ltmp = 0x1000;
416 if (pHwData->LED_Blinking >= 3000)
417 ltmp = 0;
418 break;
419 }
420 pHwData->LED_Blinking++;
421
422 reg->U1BC_LEDConfigure = ltmp;
423 if (LEDSet != 7) {
424 reg->U1BC_LEDConfigure |= (ltmp & 0xff) << 8;
425 reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
426 }
427 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
428 }
429 } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) {
430 if (reg->U1BC_LEDConfigure & 0x1010) {
431 reg->U1BC_LEDConfigure &= ~0x1010;
432 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
433 }
434 } else {
435 switch (LEDSet) {
436 case 4:
437 if (!pHwData->LED_LinkOn) {
438
439 if (pHwData->LED_Scanning) {
440 if (pHwData->LED_Blinking == 0) {
441 reg->U1BC_LEDConfigure |= 0x10;
442 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
443 pHwData->LED_Blinking = 1;
444 TimeInterval = 300;
445 } else {
446 reg->U1BC_LEDConfigure &= ~0x10;
447 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
448 pHwData->LED_Blinking = 0;
449 TimeInterval = 300;
450 }
451 } else {
452
453 if (reg->U1BC_LEDConfigure & 0x10) {
454 reg->U1BC_LEDConfigure &= ~0x10;
455 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
456 }
457 }
458 } else {
459
460 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
461 reg->U1BC_LEDConfigure |= 0x10;
462 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
463 }
464 }
465 break;
466 case 6:
467 if (!pHwData->LED_LinkOn) {
468
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);
474 pHwData->LED_Blinking = 1;
475 TimeInterval = 300;
476 } else {
477 reg->U1BC_LEDConfigure &= ~0x1f;
478 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
479 pHwData->LED_Blinking = 0;
480 TimeInterval = 300;
481 }
482 } else {
483
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)];
490 }
491 pHwData->LED_Blinking++;
492 if (reg->U1BC_LEDConfigure != ltmp)
493 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
494 TimeInterval = 100;
495 }
496 } else {
497
498 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
499 reg->U1BC_LEDConfigure |= 0x10;
500 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
501 }
502 }
503 break;
504 case 5:
505 if (!pHwData->LED_LinkOn) {
506
507 if (pHwData->LED_Scanning) {
508 if (pHwData->LED_Blinking == 0) {
509 reg->U1BC_LEDConfigure |= 0x1000;
510 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
511 pHwData->LED_Blinking = 1;
512 TimeInterval = 300;
513 } else {
514 reg->U1BC_LEDConfigure &= ~0x1000;
515 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
516 pHwData->LED_Blinking = 0;
517 TimeInterval = 300;
518 }
519 } else {
520
521 if (reg->U1BC_LEDConfigure & 0x1000) {
522 reg->U1BC_LEDConfigure &= ~0x1000;
523 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
524 }
525 }
526 } else {
527
528 if ((adapter->RxByteCount !=
529 pHwData->RxByteCountLast)
530 || (adapter->TxByteCount !=
531 pHwData->TxByteCountLast)) {
532 if ((reg->U1BC_LEDConfigure & 0x3000) !=
533 0x3000) {
534 reg->U1BC_LEDConfigure |= 0x3000;
535 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
536 }
537
538 pHwData->RxByteCountLast =
539 adapter->RxByteCount;
540 pHwData->TxByteCountLast =
541 adapter->TxByteCount;
542 TimeInterval = 200;
543 } else {
544
545 if ((reg->U1BC_LEDConfigure & 0x3000) !=
546 0x1000) {
547 reg->U1BC_LEDConfigure &=
548 ~0x3000;
549 reg->U1BC_LEDConfigure |=
550 0x1000;
551 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
552 }
553 }
554 }
555 break;
556 default:
557 if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
558 reg->U1BC_LEDConfigure |= 0x3000;
559 Wb35Reg_Write(pHwData, 0x03bc,
560 reg->U1BC_LEDConfigure);
561 }
562
563 if (pHwData->LED_Blinking) {
564
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);
571
572 pHwData->LED_Blinking += 2;
573 if (pHwData->LED_Blinking < 40)
574 TimeInterval = 100;
575 else {
576 pHwData->LED_Blinking = 0;
577 reg->U1BC_LEDConfigure &= ~0x0f;
578 Wb35Reg_Write(pHwData, 0x03bc,
579 reg->U1BC_LEDConfigure);
580 }
581 break;
582 }
583
584 if (pHwData->LED_LinkOn) {
585 if (!(reg->U1BC_LEDConfigure & 0x10)) {
586
587 reg->U1BC_LEDConfigure |= 0x10;
588 pHwData->LED_Blinking = 1;
589 TimeInterval = 50;
590 }
591 } else {
592 if (reg->U1BC_LEDConfigure & 0x10) {
593 reg->U1BC_LEDConfigure &= ~0x10;
594 Wb35Reg_Write(pHwData, 0x03bc,
595 reg->U1BC_LEDConfigure);
596 }
597 }
598 break;
599 }
600 }
601
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);
606}
607
608static int hal_init_hardware(struct ieee80211_hw *hw)
609{
610 struct wbsoft_priv *priv = hw->priv;
611 struct hw_data *pHwData = &priv->sHwData;
612 u16 SoftwareSet;
613
614 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
615 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
616
617 if (!Wb35Reg_initial(pHwData))
618 goto error_reg_destroy;
619
620 if (!Wb35Tx_initial(pHwData))
621 goto error_tx_destroy;
622
623 if (!Wb35Rx_initial(pHwData))
624 goto error_rx_destroy;
625
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);
631
632 SoftwareSet = hal_software_set(pHwData);
633
634 Wb35Rx_start(hw);
635 Wb35Tx_EP2VM_start(priv);
636
637 return 0;
638
639error_rx_destroy:
640 Wb35Rx_destroy(pHwData);
641error_tx_destroy:
642 Wb35Tx_destroy(pHwData);
643error_reg_destroy:
644 Wb35Reg_destroy(pHwData);
645
646 pHwData->SurpriseRemove = 1;
647 return -EINVAL;
648}
649
650static int wb35_hw_init(struct ieee80211_hw *hw)
651{
652 struct wbsoft_priv *priv = hw->priv;
653 struct hw_data *pHwData = &priv->sHwData;
654 u8 EEPROM_region;
655 u8 HwRadioOff;
656 u8 *pMacAddr2;
657 u8 *pMacAddr;
658 int err;
659
660 pHwData->phy_type = RF_DECIDE_BY_INF;
661
662 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
663 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
664
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;
673
674 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
675
676 err = hal_init_hardware(hw);
677 if (err)
678 goto error;
679
680 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
681 if (EEPROM_region != REGION_AUTO)
682 priv->sLocalPara.region = EEPROM_region;
683 else {
684 if (priv->sLocalPara.region_INF != REGION_AUTO)
685 priv->sLocalPara.region = priv->sLocalPara.region_INF;
686 else
687 priv->sLocalPara.region = REGION_USA;
688 }
689
690 Mds_initial(priv);
691
692
693
694
695
696 pMacAddr = priv->sLocalPara.ThisMacAddress;
697 pMacAddr2 = priv->sLocalPara.PermanentAddress;
698
699
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);
703 else {
704
705 hal_set_ethernet_address(pHwData,
706 priv->sLocalPara.ThisMacAddress);
707 }
708
709 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
710 hal_get_hw_radio_off(pHwData);
711
712
713 while (!hal_idle(pHwData))
714 msleep(10);
715
716 MTO_Init(priv);
717
718 HwRadioOff = hal_get_hw_radio_off(pHwData);
719 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
720
721 hal_set_radio_mode(pHwData,
722 (unsigned char)(priv->sLocalPara.RadioOffStatus.
723 boSwRadioOff
724 || priv->sLocalPara.RadioOffStatus.
725 boHwRadioOff));
726
727
728 hal_driver_init_OK(pHwData) = 1;
729
730error:
731 return err;
732}
733
734static int wb35_probe(struct usb_interface *intf,
735 const struct usb_device_id *id_table)
736{
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;
742 int err;
743 u32 ltmp;
744
745 usb_get_dev(udev);
746
747
748 err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
749 0x01,
750 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
751 0x0, 0x400, <mp, 4, HZ * 100);
752 if (err < 0)
753 goto error;
754
755
756 ltmp = cpu_to_le32(ltmp);
757 if (ltmp) {
758 err = -EBUSY;
759 goto error;
760 }
761
762 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
763 if (!dev) {
764 err = -ENOMEM;
765 goto error;
766 }
767
768 priv = dev->priv;
769
770 priv->sHwData.udev = udev;
771
772 interface = intf->cur_altsetting;
773 endpoint = &interface->endpoint[0].desc;
774
775 err = wb35_hw_init(dev);
776 if (err)
777 goto error_free_hw;
778
779 SET_IEEE80211_DEV(dev, &udev->dev);
780 {
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);
785 }
786
787 dev->extra_tx_headroom = 12;
788 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
789 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
790
791 dev->channel_change_time = 1000;
792 dev->max_signal = 100;
793 dev->queues = 1;
794
795 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
796
797 err = ieee80211_register_hw(dev);
798 if (err)
799 goto error_free_hw;
800
801 usb_set_intfdata(intf, dev);
802
803 return 0;
804
805error_free_hw:
806 ieee80211_free_hw(dev);
807error:
808 usb_put_dev(udev);
809 return err;
810}
811
812static void hal_halt(struct hw_data *pHwData)
813{
814 del_timer_sync(&pHwData->LEDTimer);
815
816 msleep(100);
817 Wb35Rx_destroy(pHwData);
818 Wb35Tx_destroy(pHwData);
819 Wb35Reg_destroy(pHwData);
820}
821
822static void wb35_hw_halt(struct wbsoft_priv *adapter)
823{
824
825 hal_stop(&adapter->sHwData);
826
827 msleep(100);
828
829 hal_halt(&adapter->sHwData);
830}
831
832static void wb35_disconnect(struct usb_interface *intf)
833{
834 struct ieee80211_hw *hw = usb_get_intfdata(intf);
835 struct wbsoft_priv *priv = hw->priv;
836
837 wb35_hw_halt(priv);
838
839 ieee80211_stop_queues(hw);
840 ieee80211_unregister_hw(hw);
841 ieee80211_free_hw(hw);
842
843 usb_set_intfdata(intf, NULL);
844 usb_put_dev(interface_to_usbdev(intf));
845}
846
847static struct usb_driver wb35_driver = {
848 .name = "w35und",
849 .id_table = wb35_table,
850 .probe = wb35_probe,
851 .disconnect = wb35_disconnect,
852};
853
854module_usb_driver(wb35_driver);
855