On Tue, Nov 06, 2007 at 02:33:53AM -0800, akpm@linux-foundation.org wrote:
[mmotm.git] / drivers / staging / winbond / wbusb.c
blob067082a7d759f2149029b1735c0f55a779fe861f
1 /*
2 * Copyright 2008 Pavel Machek <pavel@suse.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 "mlmetxrx_f.h"
18 #include "mto.h"
19 #include "wbhal_f.h"
20 #include "wblinux_f.h"
22 MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
23 MODULE_LICENSE("GPL");
24 MODULE_VERSION("0.1");
26 static struct usb_device_id wb35_table[] __devinitdata = {
27 { USB_DEVICE(0x0416, 0x0035) },
28 { USB_DEVICE(0x18E8, 0x6201) },
29 { USB_DEVICE(0x18E8, 0x6206) },
30 { USB_DEVICE(0x18E8, 0x6217) },
31 { USB_DEVICE(0x18E8, 0x6230) },
32 { USB_DEVICE(0x18E8, 0x6233) },
33 { USB_DEVICE(0x1131, 0x2035) },
34 { 0, }
37 MODULE_DEVICE_TABLE(usb, wb35_table);
39 static struct ieee80211_rate wbsoft_rates[] = {
40 { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
43 static struct ieee80211_channel wbsoft_channels[] = {
44 { .center_freq = 2412 },
47 static struct ieee80211_supported_band wbsoft_band_2GHz = {
48 .channels = wbsoft_channels,
49 .n_channels = ARRAY_SIZE(wbsoft_channels),
50 .bitrates = wbsoft_rates,
51 .n_bitrates = ARRAY_SIZE(wbsoft_rates),
54 static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
56 u32 tmp;
58 if (pHwData->SurpriseRemove)
59 return;
61 pHwData->BeaconPeriod = beacon_period;
62 tmp = pHwData->BeaconPeriod << 16;
63 tmp |= pHwData->ProbeDelay;
64 Wb35Reg_Write(pHwData, 0x0848, tmp);
67 static int wbsoft_add_interface(struct ieee80211_hw *dev,
68 struct ieee80211_if_init_conf *conf)
70 struct wbsoft_priv *priv = dev->priv;
72 hal_set_beacon_period(&priv->sHwData, conf->vif->bss_conf.beacon_int);
74 return 0;
77 static void wbsoft_remove_interface(struct ieee80211_hw *dev,
78 struct ieee80211_if_init_conf *conf)
80 printk("wbsoft_remove interface called\n");
83 static void wbsoft_stop(struct ieee80211_hw *hw)
85 printk(KERN_INFO "%s called\n", __func__);
88 static int wbsoft_get_stats(struct ieee80211_hw *hw,
89 struct ieee80211_low_level_stats *stats)
91 printk(KERN_INFO "%s called\n", __func__);
92 return 0;
95 static int wbsoft_get_tx_stats(struct ieee80211_hw *hw,
96 struct ieee80211_tx_queue_stats *stats)
98 printk(KERN_INFO "%s called\n", __func__);
99 return 0;
102 static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
103 struct dev_addr_list *mc_list)
105 return mc_count;
108 static void wbsoft_configure_filter(struct ieee80211_hw *dev,
109 unsigned int changed_flags,
110 unsigned int *total_flags,
111 u64 multicast)
113 unsigned int new_flags;
115 new_flags = 0;
117 if (*total_flags & FIF_PROMISC_IN_BSS)
118 new_flags |= FIF_PROMISC_IN_BSS;
119 else if ((*total_flags & FIF_ALLMULTI) || (multicast > 32))
120 new_flags |= FIF_ALLMULTI;
122 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
124 *total_flags = new_flags;
127 static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
129 struct wbsoft_priv *priv = dev->priv;
131 MLMESendFrame(priv, skb->data, skb->len, FRAME_TYPE_802_11_MANAGEMENT);
133 return NETDEV_TX_OK;
136 static int wbsoft_start(struct ieee80211_hw *dev)
138 struct wbsoft_priv *priv = dev->priv;
140 priv->enabled = true;
142 return 0;
145 static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
147 struct wb35_reg *reg = &pHwData->reg;
149 if (pHwData->SurpriseRemove)
150 return;
152 if (radio_off) //disable Baseband receive off
154 pHwData->CurrentRadioSw = 1; // off
155 reg->M24_MacControl &= 0xffffffbf;
156 } else {
157 pHwData->CurrentRadioSw = 0; // on
158 reg->M24_MacControl |= 0x00000040;
160 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
163 static void
164 hal_set_current_channel_ex(struct hw_data *pHwData, ChanInfo channel)
166 struct wb35_reg *reg = &pHwData->reg;
168 if (pHwData->SurpriseRemove)
169 return;
171 printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo);
173 RFSynthesizer_SwitchingChannel(pHwData, channel); // Switch channel
174 pHwData->Channel = channel.ChanNo;
175 pHwData->band = channel.band;
176 #ifdef _PE_STATE_DUMP_
177 printk("Set channel is %d, band =%d\n", pHwData->Channel,
178 pHwData->band);
179 #endif
180 reg->M28_MacControl &= ~0xff; // Clean channel information field
181 reg->M28_MacControl |= channel.ChanNo;
182 Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
183 (s8 *) & channel, sizeof(ChanInfo));
186 static void hal_set_current_channel(struct hw_data *pHwData, ChanInfo channel)
188 hal_set_current_channel_ex(pHwData, channel);
191 static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
193 struct wb35_reg *reg = &pHwData->reg;
195 if (pHwData->SurpriseRemove)
196 return;
198 reg->M00_MacControl &= ~0x02000000; //The HW value
200 if (enable)
201 reg->M00_MacControl |= 0x02000000; //The HW value
203 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
206 //for wep key error detection, we need to accept broadcast packets to be received temporary.
207 static void hal_set_accept_promiscuous(struct hw_data *pHwData, u8 enable)
209 struct wb35_reg *reg = &pHwData->reg;
211 if (pHwData->SurpriseRemove)
212 return;
213 if (enable) {
214 reg->M00_MacControl |= 0x00400000;
215 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
216 } else {
217 reg->M00_MacControl &= ~0x00400000;
218 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
222 static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
224 struct wb35_reg *reg = &pHwData->reg;
226 if (pHwData->SurpriseRemove)
227 return;
229 reg->M00_MacControl &= ~0x01000000; //The HW value
230 if (enable)
231 reg->M00_MacControl |= 0x01000000; //The HW value
232 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
235 static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
237 struct wb35_reg *reg = &pHwData->reg;
239 if (pHwData->SurpriseRemove)
240 return;
242 // 20040108 debug
243 if (!enable) //Due to SME and MLME are not suitable for 35
244 return;
246 reg->M00_MacControl &= ~0x04000000; //The HW value
247 if (enable)
248 reg->M00_MacControl |= 0x04000000; //The HW value
250 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
253 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
255 struct wbsoft_priv *priv = dev->priv;
256 ChanInfo ch;
258 printk("wbsoft_config called\n");
260 /* Should use channel_num, or something, as that is already pre-translated */
261 ch.band = 1;
262 ch.ChanNo = 1;
264 hal_set_current_channel(&priv->sHwData, ch);
265 hal_set_accept_broadcast(&priv->sHwData, 1);
266 hal_set_accept_promiscuous(&priv->sHwData, 1);
267 hal_set_accept_multicast(&priv->sHwData, 1);
268 hal_set_accept_beacon(&priv->sHwData, 1);
269 hal_set_radio_mode(&priv->sHwData, 0);
271 return 0;
274 static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
276 printk("wbsoft_get_tsf called\n");
277 return 0;
280 static 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_tx_stats = wbsoft_get_tx_stats,
291 .get_tsf = wbsoft_get_tsf,
294 static void
295 hal_set_ethernet_address(struct hw_data *pHwData, u8 * current_address)
297 u32 ltmp[2];
299 if (pHwData->SurpriseRemove)
300 return;
302 memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
304 ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
305 ltmp[1] =
306 cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
308 Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
311 static void
312 hal_get_permanent_address(struct hw_data *pHwData, u8 * pethernet_address)
314 if (pHwData->SurpriseRemove)
315 return;
317 memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
320 static void hal_stop(struct hw_data *pHwData)
322 struct wb35_reg *reg = &pHwData->reg;
324 pHwData->Wb35Rx.rx_halt = 1;
325 Wb35Rx_stop(pHwData);
327 pHwData->Wb35Tx.tx_halt = 1;
328 Wb35Tx_stop(pHwData);
330 reg->D00_DmaControl &= ~0xc0000000; //Tx Off, Rx Off
331 Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
334 static unsigned char hal_idle(struct hw_data *pHwData)
336 struct wb35_reg *reg = &pHwData->reg;
337 struct wb_usb *pWbUsb = &pHwData->WbUsb;
339 if (!pHwData->SurpriseRemove
340 && (pWbUsb->DetectCount || 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
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;
427 pHwData->LED_Blinking++;
429 reg->U1BC_LEDConfigure = ltmp;
430 if (LEDSet != 7) // Only 111 mode has 2 LEDs on PCB.
432 reg->U1BC_LEDConfigure |= (ltmp & 0xff) << 8; // Copy LED result to each LED control register
433 reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
435 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
437 } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) // If radio off
439 if (reg->U1BC_LEDConfigure & 0x1010) {
440 reg->U1BC_LEDConfigure &= ~0x1010;
441 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
443 } else {
444 switch (LEDSet) {
445 case 4: // [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing
446 if (!pHwData->LED_LinkOn) // Blink only if not Link On
448 // Blinking if scanning is on progress
449 if (pHwData->LED_Scanning) {
450 if (pHwData->LED_Blinking == 0) {
451 reg->U1BC_LEDConfigure |= 0x10;
452 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 On
453 pHwData->LED_Blinking = 1;
454 TimeInterval = 300;
455 } else {
456 reg->U1BC_LEDConfigure &= ~0x10;
457 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
458 pHwData->LED_Blinking = 0;
459 TimeInterval = 300;
461 } else {
462 //Turn Off LED_0
463 if (reg->U1BC_LEDConfigure & 0x10) {
464 reg->U1BC_LEDConfigure &= ~0x10;
465 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
468 } else {
469 // Turn On LED_0
470 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
471 reg->U1BC_LEDConfigure |= 0x10;
472 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
475 break;
477 case 6: // [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing
478 if (!pHwData->LED_LinkOn) // Blink only if not Link On
480 // Blinking if scanning is on progress
481 if (pHwData->LED_Scanning) {
482 if (pHwData->LED_Blinking == 0) {
483 reg->U1BC_LEDConfigure &= ~0xf;
484 reg->U1BC_LEDConfigure |= 0x10;
485 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 On
486 pHwData->LED_Blinking = 1;
487 TimeInterval = 300;
488 } else {
489 reg->U1BC_LEDConfigure &= ~0x1f;
490 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
491 pHwData->LED_Blinking = 0;
492 TimeInterval = 300;
494 } else {
495 // 20060901 Gray blinking if in disconnect state and not scanning
496 ltmp = reg->U1BC_LEDConfigure;
497 reg->U1BC_LEDConfigure &= ~0x1f;
498 if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
499 reg->U1BC_LEDConfigure |= 0x10;
500 reg->U1BC_LEDConfigure |=
501 LED_GRAY2[(pHwData->LED_Blinking % 30)];
503 pHwData->LED_Blinking++;
504 if (reg->U1BC_LEDConfigure != ltmp)
505 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
506 TimeInterval = 100;
508 } else {
509 // Turn On LED_0
510 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
511 reg->U1BC_LEDConfigure |= 0x10;
512 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
515 break;
517 case 5: // [101] Only 1 Led be placed on PCB and use LED_1 for showing
518 if (!pHwData->LED_LinkOn) // Blink only if not Link On
520 // Blinking if scanning is on progress
521 if (pHwData->LED_Scanning) {
522 if (pHwData->LED_Blinking == 0) {
523 reg->U1BC_LEDConfigure |=
524 0x1000;
525 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On
526 pHwData->LED_Blinking = 1;
527 TimeInterval = 300;
528 } else {
529 reg->U1BC_LEDConfigure &=
530 ~0x1000;
531 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 Off
532 pHwData->LED_Blinking = 0;
533 TimeInterval = 300;
535 } else {
536 //Turn Off LED_1
537 if (reg->U1BC_LEDConfigure & 0x1000) {
538 reg->U1BC_LEDConfigure &=
539 ~0x1000;
540 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 Off
543 } else {
544 // Is transmitting/receiving ??
545 if ((adapter->RxByteCount !=
546 pHwData->RxByteCountLast)
547 || (adapter->TxByteCount !=
548 pHwData->TxByteCountLast)) {
549 if ((reg->U1BC_LEDConfigure & 0x3000) !=
550 0x3000) {
551 reg->U1BC_LEDConfigure |=
552 0x3000;
553 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On
555 // Update variable
556 pHwData->RxByteCountLast =
557 adapter->RxByteCount;
558 pHwData->TxByteCountLast =
559 adapter->TxByteCount;
560 TimeInterval = 200;
561 } else {
562 // Turn On LED_1 and blinking if transmitting/receiving
563 if ((reg->U1BC_LEDConfigure & 0x3000) !=
564 0x1000) {
565 reg->U1BC_LEDConfigure &=
566 ~0x3000;
567 reg->U1BC_LEDConfigure |=
568 0x1000;
569 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On
573 break;
575 default: // Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active
576 if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
577 reg->U1BC_LEDConfigure |= 0x3000; // LED_1 is always on and event enable
578 Wb35Reg_Write(pHwData, 0x03bc,
579 reg->U1BC_LEDConfigure);
582 if (pHwData->LED_Blinking) {
583 // Gray blinking
584 reg->U1BC_LEDConfigure &= ~0x0f;
585 reg->U1BC_LEDConfigure |= 0x10;
586 reg->U1BC_LEDConfigure |=
587 LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
588 Wb35Reg_Write(pHwData, 0x03bc,
589 reg->U1BC_LEDConfigure);
591 pHwData->LED_Blinking += 2;
592 if (pHwData->LED_Blinking < 40)
593 TimeInterval = 100;
594 else {
595 pHwData->LED_Blinking = 0; // Stop blinking
596 reg->U1BC_LEDConfigure &= ~0x0f;
597 Wb35Reg_Write(pHwData, 0x03bc,
598 reg->U1BC_LEDConfigure);
600 break;
603 if (pHwData->LED_LinkOn) {
604 if (!(reg->U1BC_LEDConfigure & 0x10)) // Check the LED_0
606 //Try to turn ON LED_0 after gray blinking
607 reg->U1BC_LEDConfigure |= 0x10;
608 pHwData->LED_Blinking = 1; //Start blinking
609 TimeInterval = 50;
611 } else {
612 if (reg->U1BC_LEDConfigure & 0x10) // Check the LED_0
614 reg->U1BC_LEDConfigure &= ~0x10;
615 Wb35Reg_Write(pHwData, 0x03bc,
616 reg->U1BC_LEDConfigure);
619 break;
622 //20060828.1 Active send null packet to avoid AP disconnect
623 if (pHwData->LED_LinkOn) {
624 pHwData->NullPacketCount += TimeInterval;
625 if (pHwData->NullPacketCount >=
626 DEFAULT_NULL_PACKET_COUNT) {
627 pHwData->NullPacketCount = 0;
632 pHwData->time_count += TimeInterval;
633 Wb35Tx_CurrentTime(adapter, pHwData->time_count); // 20060928 add
634 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
635 add_timer(&pHwData->LEDTimer);
638 static int hal_init_hardware(struct ieee80211_hw *hw)
640 struct wbsoft_priv *priv = hw->priv;
641 struct hw_data *pHwData = &priv->sHwData;
642 u16 SoftwareSet;
644 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
645 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
647 if (!Wb35Reg_initial(pHwData))
648 goto error_reg_destroy;
650 if (!Wb35Tx_initial(pHwData))
651 goto error_tx_destroy;
653 if (!Wb35Rx_initial(pHwData))
654 goto error_rx_destroy;
656 init_timer(&pHwData->LEDTimer);
657 pHwData->LEDTimer.function = hal_led_control;
658 pHwData->LEDTimer.data = (unsigned long)priv;
659 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
660 add_timer(&pHwData->LEDTimer);
662 SoftwareSet = hal_software_set(pHwData);
664 #ifdef Vendor2
665 // Try to make sure the EEPROM contain
666 SoftwareSet >>= 8;
667 if (SoftwareSet != 0x82)
668 return false;
669 #endif
671 Wb35Rx_start(hw);
672 Wb35Tx_EP2VM_start(priv);
674 return 0;
676 error_rx_destroy:
677 Wb35Rx_destroy(pHwData);
678 error_tx_destroy:
679 Wb35Tx_destroy(pHwData);
680 error_reg_destroy:
681 Wb35Reg_destroy(pHwData);
683 pHwData->SurpriseRemove = 1;
684 return -EINVAL;
687 static int wb35_hw_init(struct ieee80211_hw *hw)
689 struct wbsoft_priv *priv = hw->priv;
690 struct hw_data *pHwData = &priv->sHwData;
691 u8 EEPROM_region;
692 u8 HwRadioOff;
693 u8 *pMacAddr2;
694 u8 *pMacAddr;
695 int err;
697 pHwData->phy_type = RF_DECIDE_BY_INF;
699 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
700 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
702 priv->sLocalPara.region_INF = REGION_AUTO;
703 priv->sLocalPara.TxRateMode = RATE_AUTO;
704 priv->sLocalPara.bMacOperationMode = MODE_802_11_BG;
705 priv->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
706 priv->sLocalPara.bPreambleMode = AUTO_MODE;
707 priv->sLocalPara.bWepKeyError = false;
708 priv->sLocalPara.bToSelfPacketReceived = false;
709 priv->sLocalPara.WepKeyDetectTimerCount = 2 * 100; /* 2 seconds */
711 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
713 err = hal_init_hardware(hw);
714 if (err)
715 goto error;
717 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
718 if (EEPROM_region != REGION_AUTO)
719 priv->sLocalPara.region = EEPROM_region;
720 else {
721 if (priv->sLocalPara.region_INF != REGION_AUTO)
722 priv->sLocalPara.region = priv->sLocalPara.region_INF;
723 else
724 priv->sLocalPara.region = REGION_USA; /* default setting */
727 Mds_initial(priv);
730 * If no user-defined address in the registry, use the addresss
731 * "burned" on the NIC instead.
733 pMacAddr = priv->sLocalPara.ThisMacAddress;
734 pMacAddr2 = priv->sLocalPara.PermanentAddress;
736 /* Reading ethernet address from EEPROM */
737 hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
738 if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
739 memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
740 else {
741 /* Set the user define MAC address */
742 hal_set_ethernet_address(pHwData,
743 priv->sLocalPara.ThisMacAddress);
746 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
747 #ifdef _PE_STATE_DUMP_
748 printk("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo);
749 #endif
750 hal_get_hw_radio_off(pHwData);
752 /* Waiting for HAL setting OK */
753 while (!hal_idle(pHwData))
754 msleep(10);
756 MTO_Init(priv);
758 HwRadioOff = hal_get_hw_radio_off(pHwData);
759 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
761 hal_set_radio_mode(pHwData,
762 (unsigned char)(priv->sLocalPara.RadioOffStatus.
763 boSwRadioOff
764 || priv->sLocalPara.RadioOffStatus.
765 boHwRadioOff));
767 /* Notify hal that the driver is ready now. */
768 hal_driver_init_OK(pHwData) = 1;
770 error:
771 return err;
774 static int wb35_probe(struct usb_interface *intf,
775 const struct usb_device_id *id_table)
777 struct usb_device *udev = interface_to_usbdev(intf);
778 struct usb_endpoint_descriptor *endpoint;
779 struct usb_host_interface *interface;
780 struct ieee80211_hw *dev;
781 struct wbsoft_priv *priv;
782 struct wb_usb *pWbUsb;
783 int nr, err;
784 u32 ltmp;
786 usb_get_dev(udev);
788 /* Check the device if it already be opened */
789 nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
790 0x01,
791 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
792 0x0, 0x400, &ltmp, 4, HZ * 100);
793 if (nr < 0) {
794 err = nr;
795 goto error;
798 /* Is already initialized? */
799 ltmp = cpu_to_le32(ltmp);
800 if (ltmp) {
801 err = -EBUSY;
802 goto error;
805 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
806 if (!dev) {
807 err = -ENOMEM;
808 goto error;
811 priv = dev->priv;
813 spin_lock_init(&priv->SpinLock);
815 pWbUsb = &priv->sHwData.WbUsb;
816 pWbUsb->udev = udev;
818 interface = intf->cur_altsetting;
819 endpoint = &interface->endpoint[0].desc;
821 if (endpoint[2].wMaxPacketSize == 512) {
822 printk("[w35und] Working on USB 2.0\n");
823 pWbUsb->IsUsb20 = 1;
826 err = wb35_hw_init(dev);
827 if (err)
828 goto error_free_hw;
830 SET_IEEE80211_DEV(dev, &udev->dev);
832 struct hw_data *pHwData = &priv->sHwData;
833 unsigned char dev_addr[MAX_ADDR_LEN];
834 hal_get_permanent_address(pHwData, dev_addr);
835 SET_IEEE80211_PERM_ADDR(dev, dev_addr);
838 dev->extra_tx_headroom = 12; /* FIXME */
839 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
840 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
842 dev->channel_change_time = 1000;
843 dev->max_signal = 100;
844 dev->queues = 1;
846 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
848 err = ieee80211_register_hw(dev);
849 if (err)
850 goto error_free_hw;
852 usb_set_intfdata(intf, dev);
854 return 0;
856 error_free_hw:
857 ieee80211_free_hw(dev);
858 error:
859 usb_put_dev(udev);
860 return err;
863 static void hal_halt(struct hw_data *pHwData)
865 del_timer_sync(&pHwData->LEDTimer);
866 /* XXX: Wait for Timer DPC exit. */
867 msleep(100);
868 Wb35Rx_destroy(pHwData);
869 Wb35Tx_destroy(pHwData);
870 Wb35Reg_destroy(pHwData);
873 static void wb35_hw_halt(struct wbsoft_priv *adapter)
875 Mds_Destroy(adapter);
877 /* Turn off Rx and Tx hardware ability */
878 hal_stop(&adapter->sHwData);
879 #ifdef _PE_USB_INI_DUMP_
880 printk("[w35und] Hal_stop O.K.\n");
881 #endif
882 /* Waiting Irp completed */
883 msleep(100);
885 hal_halt(&adapter->sHwData);
888 static void wb35_disconnect(struct usb_interface *intf)
890 struct ieee80211_hw *hw = usb_get_intfdata(intf);
891 struct wbsoft_priv *priv = hw->priv;
893 wb35_hw_halt(priv);
895 ieee80211_stop_queues(hw);
896 ieee80211_unregister_hw(hw);
897 ieee80211_free_hw(hw);
899 usb_set_intfdata(intf, NULL);
900 usb_put_dev(interface_to_usbdev(intf));
903 static struct usb_driver wb35_driver = {
904 .name = "w35und",
905 .id_table = wb35_table,
906 .probe = wb35_probe,
907 .disconnect = wb35_disconnect,
910 static int __init wb35_init(void)
912 return usb_register(&wb35_driver);
915 static void __exit wb35_exit(void)
917 usb_deregister(&wb35_driver);
920 module_init(wb35_init);
921 module_exit(wb35_exit);