Staging: winbond: mac80211 - unify config_interface and bss_info_changed
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / winbond / wbusb.c
blob745279c528a24143a7c0a6b312cd45e6f37b432b
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 int wbsoft_add_interface(struct ieee80211_hw *dev,
55 struct ieee80211_if_init_conf *conf)
57 printk("wbsoft_add interface called\n");
58 return 0;
61 static void wbsoft_remove_interface(struct ieee80211_hw *dev,
62 struct ieee80211_if_init_conf *conf)
64 printk("wbsoft_remove interface called\n");
67 static void wbsoft_stop(struct ieee80211_hw *hw)
69 printk(KERN_INFO "%s called\n", __func__);
72 static int wbsoft_get_stats(struct ieee80211_hw *hw,
73 struct ieee80211_low_level_stats *stats)
75 printk(KERN_INFO "%s called\n", __func__);
76 return 0;
79 static int wbsoft_get_tx_stats(struct ieee80211_hw *hw,
80 struct ieee80211_tx_queue_stats *stats)
82 printk(KERN_INFO "%s called\n", __func__);
83 return 0;
86 static void wbsoft_configure_filter(struct ieee80211_hw *dev,
87 unsigned int changed_flags,
88 unsigned int *total_flags,
89 int mc_count, struct dev_mc_list *mclist)
91 unsigned int new_flags;
93 new_flags = 0;
95 if (*total_flags & FIF_PROMISC_IN_BSS)
96 new_flags |= FIF_PROMISC_IN_BSS;
97 else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32))
98 new_flags |= FIF_ALLMULTI;
100 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
102 *total_flags = new_flags;
105 static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
107 struct wbsoft_priv *priv = dev->priv;
109 MLMESendFrame(priv, skb->data, skb->len, FRAME_TYPE_802_11_MANAGEMENT);
111 return NETDEV_TX_OK;
114 static int wbsoft_start(struct ieee80211_hw *dev)
116 struct wbsoft_priv *priv = dev->priv;
118 priv->enabled = true;
120 return 0;
123 static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
125 struct wb35_reg *reg = &pHwData->reg;
127 if (pHwData->SurpriseRemove)
128 return;
130 if (radio_off) //disable Baseband receive off
132 pHwData->CurrentRadioSw = 1; // off
133 reg->M24_MacControl &= 0xffffffbf;
134 } else {
135 pHwData->CurrentRadioSw = 0; // on
136 reg->M24_MacControl |= 0x00000040;
138 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
141 static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
143 u32 tmp;
145 if (pHwData->SurpriseRemove)
146 return;
148 pHwData->BeaconPeriod = beacon_period;
149 tmp = pHwData->BeaconPeriod << 16;
150 tmp |= pHwData->ProbeDelay;
151 Wb35Reg_Write(pHwData, 0x0848, tmp);
154 static void
155 hal_set_current_channel_ex(struct hw_data *pHwData, ChanInfo channel)
157 struct wb35_reg *reg = &pHwData->reg;
159 if (pHwData->SurpriseRemove)
160 return;
162 printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo);
164 RFSynthesizer_SwitchingChannel(pHwData, channel); // Switch channel
165 pHwData->Channel = channel.ChanNo;
166 pHwData->band = channel.band;
167 #ifdef _PE_STATE_DUMP_
168 printk("Set channel is %d, band =%d\n", pHwData->Channel,
169 pHwData->band);
170 #endif
171 reg->M28_MacControl &= ~0xff; // Clean channel information field
172 reg->M28_MacControl |= channel.ChanNo;
173 Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
174 (s8 *) & channel, sizeof(ChanInfo));
177 static void hal_set_current_channel(struct hw_data *pHwData, ChanInfo channel)
179 hal_set_current_channel_ex(pHwData, channel);
182 static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
184 struct wb35_reg *reg = &pHwData->reg;
186 if (pHwData->SurpriseRemove)
187 return;
189 reg->M00_MacControl &= ~0x02000000; //The HW value
191 if (enable)
192 reg->M00_MacControl |= 0x02000000; //The HW value
194 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
197 //for wep key error detection, we need to accept broadcast packets to be received temporary.
198 static void hal_set_accept_promiscuous(struct hw_data *pHwData, u8 enable)
200 struct wb35_reg *reg = &pHwData->reg;
202 if (pHwData->SurpriseRemove)
203 return;
204 if (enable) {
205 reg->M00_MacControl |= 0x00400000;
206 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
207 } else {
208 reg->M00_MacControl &= ~0x00400000;
209 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
213 static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
215 struct wb35_reg *reg = &pHwData->reg;
217 if (pHwData->SurpriseRemove)
218 return;
220 reg->M00_MacControl &= ~0x01000000; //The HW value
221 if (enable)
222 reg->M00_MacControl |= 0x01000000; //The HW value
223 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
226 static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
228 struct wb35_reg *reg = &pHwData->reg;
230 if (pHwData->SurpriseRemove)
231 return;
233 // 20040108 debug
234 if (!enable) //Due to SME and MLME are not suitable for 35
235 return;
237 reg->M00_MacControl &= ~0x04000000; //The HW value
238 if (enable)
239 reg->M00_MacControl |= 0x04000000; //The HW value
241 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
244 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
246 struct wbsoft_priv *priv = dev->priv;
247 struct ieee80211_conf *conf = &dev->conf;
248 ChanInfo ch;
250 printk("wbsoft_config called\n");
252 /* Should use channel_num, or something, as that is already pre-translated */
253 ch.band = 1;
254 ch.ChanNo = 1;
256 hal_set_current_channel(&priv->sHwData, ch);
257 hal_set_beacon_period(&priv->sHwData, conf->beacon_int);
258 hal_set_accept_broadcast(&priv->sHwData, 1);
259 hal_set_accept_promiscuous(&priv->sHwData, 1);
260 hal_set_accept_multicast(&priv->sHwData, 1);
261 hal_set_accept_beacon(&priv->sHwData, 1);
262 hal_set_radio_mode(&priv->sHwData, 0);
264 return 0;
267 static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
269 printk("wbsoft_get_tsf called\n");
270 return 0;
273 static const struct ieee80211_ops wbsoft_ops = {
274 .tx = wbsoft_tx,
275 .start = wbsoft_start,
276 .stop = wbsoft_stop,
277 .add_interface = wbsoft_add_interface,
278 .remove_interface = wbsoft_remove_interface,
279 .config = wbsoft_config,
280 .configure_filter = wbsoft_configure_filter,
281 .get_stats = wbsoft_get_stats,
282 .get_tx_stats = wbsoft_get_tx_stats,
283 .get_tsf = wbsoft_get_tsf,
286 static void
287 hal_set_ethernet_address(struct hw_data *pHwData, u8 * current_address)
289 u32 ltmp[2];
291 if (pHwData->SurpriseRemove)
292 return;
294 memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
296 ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
297 ltmp[1] =
298 cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
300 Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
303 static void
304 hal_get_permanent_address(struct hw_data *pHwData, u8 * pethernet_address)
306 if (pHwData->SurpriseRemove)
307 return;
309 memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
312 static void hal_stop(struct hw_data *pHwData)
314 struct wb35_reg *reg = &pHwData->reg;
316 pHwData->Wb35Rx.rx_halt = 1;
317 Wb35Rx_stop(pHwData);
319 pHwData->Wb35Tx.tx_halt = 1;
320 Wb35Tx_stop(pHwData);
322 reg->D00_DmaControl &= ~0xc0000000; //Tx Off, Rx Off
323 Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
326 static unsigned char hal_idle(struct hw_data *pHwData)
328 struct wb35_reg *reg = &pHwData->reg;
329 struct wb_usb *pWbUsb = &pHwData->WbUsb;
331 if (!pHwData->SurpriseRemove
332 && (pWbUsb->DetectCount || reg->EP0vm_state != VM_STOP))
333 return false;
335 return true;
338 u8 hal_get_antenna_number(struct hw_data *pHwData)
340 struct wb35_reg *reg = &pHwData->reg;
342 if ((reg->BB2C & BIT(11)) == 0)
343 return 0;
344 else
345 return 1;
348 /* 0 : radio on; 1: radio off */
349 static u8 hal_get_hw_radio_off(struct hw_data * pHwData)
351 struct wb35_reg *reg = &pHwData->reg;
353 if (pHwData->SurpriseRemove)
354 return 1;
356 //read the bit16 of register U1B0
357 Wb35Reg_Read(pHwData, 0x3b0, &reg->U1B0);
358 if ((reg->U1B0 & 0x00010000)) {
359 pHwData->CurrentRadioHw = 1;
360 return 1;
361 } else {
362 pHwData->CurrentRadioHw = 0;
363 return 0;
367 static u8 LED_GRAY[20] = {
368 0, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2
371 static u8 LED_GRAY2[30] = {
372 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
373 0, 15, 14, 13, 12, 11, 10, 9, 8
376 static void hal_led_control(unsigned long data)
378 struct wbsoft_priv *adapter = (struct wbsoft_priv *)data;
379 struct hw_data *pHwData = &adapter->sHwData;
380 struct wb35_reg *reg = &pHwData->reg;
381 u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
382 u32 TimeInterval = 500, ltmp, ltmp2;
383 ltmp = 0;
385 if (pHwData->SurpriseRemove)
386 return;
388 if (pHwData->LED_control) {
389 ltmp2 = pHwData->LED_control & 0xff;
390 if (ltmp2 == 5) // 5 is WPS mode
392 TimeInterval = 100;
393 ltmp2 = (pHwData->LED_control >> 8) & 0xff;
394 switch (ltmp2) {
395 case 1: // [0.2 On][0.1 Off]...
396 pHwData->LED_Blinking %= 3;
397 ltmp = 0x1010; // Led 1 & 0 Green and Red
398 if (pHwData->LED_Blinking == 2) // Turn off
399 ltmp = 0;
400 break;
401 case 2: // [0.1 On][0.1 Off]...
402 pHwData->LED_Blinking %= 2;
403 ltmp = 0x0010; // Led 0 red color
404 if (pHwData->LED_Blinking) // Turn off
405 ltmp = 0;
406 break;
407 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]...
408 pHwData->LED_Blinking %= 15;
409 ltmp = 0x0010; // Led 0 red color
410 if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) // Turn off 0.6 sec
411 ltmp = 0;
412 break;
413 case 4: // [300 On][ off ]
414 ltmp = 0x1000; // Led 1 Green color
415 if (pHwData->LED_Blinking >= 3000)
416 ltmp = 0; // led maybe on after 300sec * 32bit counter overlap.
417 break;
419 pHwData->LED_Blinking++;
421 reg->U1BC_LEDConfigure = ltmp;
422 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
431 if (reg->U1BC_LEDConfigure & 0x1010) {
432 reg->U1BC_LEDConfigure &= ~0x1010;
433 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
435 } else {
436 switch (LEDSet) {
437 case 4: // [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing
438 if (!pHwData->LED_LinkOn) // Blink only if not Link On
440 // Blinking if scanning is on progress
441 if (pHwData->LED_Scanning) {
442 if (pHwData->LED_Blinking == 0) {
443 reg->U1BC_LEDConfigure |= 0x10;
444 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 On
445 pHwData->LED_Blinking = 1;
446 TimeInterval = 300;
447 } else {
448 reg->U1BC_LEDConfigure &= ~0x10;
449 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
450 pHwData->LED_Blinking = 0;
451 TimeInterval = 300;
453 } else {
454 //Turn Off LED_0
455 if (reg->U1BC_LEDConfigure & 0x10) {
456 reg->U1BC_LEDConfigure &= ~0x10;
457 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
460 } else {
461 // Turn On LED_0
462 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
463 reg->U1BC_LEDConfigure |= 0x10;
464 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
467 break;
469 case 6: // [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing
470 if (!pHwData->LED_LinkOn) // Blink only if not Link On
472 // Blinking if scanning is on progress
473 if (pHwData->LED_Scanning) {
474 if (pHwData->LED_Blinking == 0) {
475 reg->U1BC_LEDConfigure &= ~0xf;
476 reg->U1BC_LEDConfigure |= 0x10;
477 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 On
478 pHwData->LED_Blinking = 1;
479 TimeInterval = 300;
480 } else {
481 reg->U1BC_LEDConfigure &= ~0x1f;
482 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
483 pHwData->LED_Blinking = 0;
484 TimeInterval = 300;
486 } else {
487 // 20060901 Gray blinking if in disconnect state and not scanning
488 ltmp = reg->U1BC_LEDConfigure;
489 reg->U1BC_LEDConfigure &= ~0x1f;
490 if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
491 reg->U1BC_LEDConfigure |= 0x10;
492 reg->U1BC_LEDConfigure |=
493 LED_GRAY2[(pHwData->LED_Blinking % 30)];
495 pHwData->LED_Blinking++;
496 if (reg->U1BC_LEDConfigure != ltmp)
497 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
498 TimeInterval = 100;
500 } else {
501 // Turn On LED_0
502 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
503 reg->U1BC_LEDConfigure |= 0x10;
504 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off
507 break;
509 case 5: // [101] Only 1 Led be placed on PCB and use LED_1 for showing
510 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 |=
516 0x1000;
517 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On
518 pHwData->LED_Blinking = 1;
519 TimeInterval = 300;
520 } else {
521 reg->U1BC_LEDConfigure &=
522 ~0x1000;
523 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 Off
524 pHwData->LED_Blinking = 0;
525 TimeInterval = 300;
527 } else {
528 //Turn Off LED_1
529 if (reg->U1BC_LEDConfigure & 0x1000) {
530 reg->U1BC_LEDConfigure &=
531 ~0x1000;
532 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 Off
535 } else {
536 // Is transmitting/receiving ??
537 if ((adapter->RxByteCount !=
538 pHwData->RxByteCountLast)
539 || (adapter->TxByteCount !=
540 pHwData->TxByteCountLast)) {
541 if ((reg->U1BC_LEDConfigure & 0x3000) !=
542 0x3000) {
543 reg->U1BC_LEDConfigure |=
544 0x3000;
545 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On
547 // Update variable
548 pHwData->RxByteCountLast =
549 adapter->RxByteCount;
550 pHwData->TxByteCountLast =
551 adapter->TxByteCount;
552 TimeInterval = 200;
553 } else {
554 // Turn On LED_1 and blinking if transmitting/receiving
555 if ((reg->U1BC_LEDConfigure & 0x3000) !=
556 0x1000) {
557 reg->U1BC_LEDConfigure &=
558 ~0x3000;
559 reg->U1BC_LEDConfigure |=
560 0x1000;
561 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On
565 break;
567 default: // Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active
568 if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
569 reg->U1BC_LEDConfigure |= 0x3000; // LED_1 is always on and event enable
570 Wb35Reg_Write(pHwData, 0x03bc,
571 reg->U1BC_LEDConfigure);
574 if (pHwData->LED_Blinking) {
575 // Gray blinking
576 reg->U1BC_LEDConfigure &= ~0x0f;
577 reg->U1BC_LEDConfigure |= 0x10;
578 reg->U1BC_LEDConfigure |=
579 LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
580 Wb35Reg_Write(pHwData, 0x03bc,
581 reg->U1BC_LEDConfigure);
583 pHwData->LED_Blinking += 2;
584 if (pHwData->LED_Blinking < 40)
585 TimeInterval = 100;
586 else {
587 pHwData->LED_Blinking = 0; // Stop blinking
588 reg->U1BC_LEDConfigure &= ~0x0f;
589 Wb35Reg_Write(pHwData, 0x03bc,
590 reg->U1BC_LEDConfigure);
592 break;
595 if (pHwData->LED_LinkOn) {
596 if (!(reg->U1BC_LEDConfigure & 0x10)) // Check the LED_0
598 //Try to turn ON LED_0 after gray blinking
599 reg->U1BC_LEDConfigure |= 0x10;
600 pHwData->LED_Blinking = 1; //Start blinking
601 TimeInterval = 50;
603 } else {
604 if (reg->U1BC_LEDConfigure & 0x10) // Check the LED_0
606 reg->U1BC_LEDConfigure &= ~0x10;
607 Wb35Reg_Write(pHwData, 0x03bc,
608 reg->U1BC_LEDConfigure);
611 break;
614 //20060828.1 Active send null packet to avoid AP disconnect
615 if (pHwData->LED_LinkOn) {
616 pHwData->NullPacketCount += TimeInterval;
617 if (pHwData->NullPacketCount >=
618 DEFAULT_NULL_PACKET_COUNT) {
619 pHwData->NullPacketCount = 0;
624 pHwData->time_count += TimeInterval;
625 Wb35Tx_CurrentTime(adapter, pHwData->time_count); // 20060928 add
626 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
627 add_timer(&pHwData->LEDTimer);
630 static int hal_init_hardware(struct ieee80211_hw *hw)
632 struct wbsoft_priv *priv = hw->priv;
633 struct hw_data *pHwData = &priv->sHwData;
634 u16 SoftwareSet;
636 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
637 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
639 if (!Wb35Reg_initial(pHwData))
640 goto error_reg_destroy;
642 if (!Wb35Tx_initial(pHwData))
643 goto error_tx_destroy;
645 if (!Wb35Rx_initial(pHwData))
646 goto error_rx_destroy;
648 init_timer(&pHwData->LEDTimer);
649 pHwData->LEDTimer.function = hal_led_control;
650 pHwData->LEDTimer.data = (unsigned long)priv;
651 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
652 add_timer(&pHwData->LEDTimer);
654 SoftwareSet = hal_software_set(pHwData);
656 #ifdef Vendor2
657 // Try to make sure the EEPROM contain
658 SoftwareSet >>= 8;
659 if (SoftwareSet != 0x82)
660 return false;
661 #endif
663 Wb35Rx_start(hw);
664 Wb35Tx_EP2VM_start(priv);
666 return 0;
668 error_rx_destroy:
669 Wb35Rx_destroy(pHwData);
670 error_tx_destroy:
671 Wb35Tx_destroy(pHwData);
672 error_reg_destroy:
673 Wb35Reg_destroy(pHwData);
675 pHwData->SurpriseRemove = 1;
676 return -EINVAL;
679 static int wb35_hw_init(struct ieee80211_hw *hw)
681 struct wbsoft_priv *priv = hw->priv;
682 struct hw_data *pHwData = &priv->sHwData;
683 u8 EEPROM_region;
684 u8 HwRadioOff;
685 u8 *pMacAddr2;
686 u8 *pMacAddr;
687 int err;
689 pHwData->phy_type = RF_DECIDE_BY_INF;
691 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
692 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
694 priv->sLocalPara.region_INF = REGION_AUTO;
695 priv->sLocalPara.TxRateMode = RATE_AUTO;
696 priv->sLocalPara.bMacOperationMode = MODE_802_11_BG;
697 priv->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
698 priv->sLocalPara.bPreambleMode = AUTO_MODE;
699 priv->sLocalPara.bWepKeyError = false;
700 priv->sLocalPara.bToSelfPacketReceived = false;
701 priv->sLocalPara.WepKeyDetectTimerCount = 2 * 100; /* 2 seconds */
703 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
705 err = hal_init_hardware(hw);
706 if (err)
707 goto error;
709 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
710 if (EEPROM_region != REGION_AUTO)
711 priv->sLocalPara.region = EEPROM_region;
712 else {
713 if (priv->sLocalPara.region_INF != REGION_AUTO)
714 priv->sLocalPara.region = priv->sLocalPara.region_INF;
715 else
716 priv->sLocalPara.region = REGION_USA; /* default setting */
719 // Get Software setting flag from hal
720 priv->sLocalPara.boAntennaDiversity = false;
721 if (hal_software_set(pHwData) & 0x00000001)
722 priv->sLocalPara.boAntennaDiversity = true;
724 Mds_initial(priv);
727 * If no user-defined address in the registry, use the addresss
728 * "burned" on the NIC instead.
730 pMacAddr = priv->sLocalPara.ThisMacAddress;
731 pMacAddr2 = priv->sLocalPara.PermanentAddress;
733 /* Reading ethernet address from EEPROM */
734 hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
735 if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
736 memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
737 else {
738 /* Set the user define MAC address */
739 hal_set_ethernet_address(pHwData,
740 priv->sLocalPara.ThisMacAddress);
743 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
744 #ifdef _PE_STATE_DUMP_
745 printk("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo);
746 #endif
747 hal_get_hw_radio_off(pHwData);
749 /* Waiting for HAL setting OK */
750 while (!hal_idle(pHwData))
751 msleep(10);
753 MTO_Init(priv);
755 HwRadioOff = hal_get_hw_radio_off(pHwData);
756 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
758 hal_set_radio_mode(pHwData,
759 (unsigned char)(priv->sLocalPara.RadioOffStatus.
760 boSwRadioOff
761 || priv->sLocalPara.RadioOffStatus.
762 boHwRadioOff));
764 /* Notify hal that the driver is ready now. */
765 hal_driver_init_OK(pHwData) = 1;
767 error:
768 return err;
771 static int wb35_probe(struct usb_interface *intf,
772 const struct usb_device_id *id_table)
774 struct usb_device *udev = interface_to_usbdev(intf);
775 struct usb_endpoint_descriptor *endpoint;
776 struct usb_host_interface *interface;
777 struct ieee80211_hw *dev;
778 struct wbsoft_priv *priv;
779 struct wb_usb *pWbUsb;
780 int nr, err;
781 u32 ltmp;
783 usb_get_dev(udev);
785 /* Check the device if it already be opened */
786 nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
787 0x01,
788 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
789 0x0, 0x400, &ltmp, 4, HZ * 100);
790 if (nr < 0) {
791 err = nr;
792 goto error;
795 /* Is already initialized? */
796 ltmp = cpu_to_le32(ltmp);
797 if (ltmp) {
798 err = -EBUSY;
799 goto error;
802 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
803 if (!dev) {
804 err = -ENOMEM;
805 goto error;
808 priv = dev->priv;
810 spin_lock_init(&priv->SpinLock);
812 pWbUsb = &priv->sHwData.WbUsb;
813 pWbUsb->udev = udev;
815 interface = intf->cur_altsetting;
816 endpoint = &interface->endpoint[0].desc;
818 if (endpoint[2].wMaxPacketSize == 512) {
819 printk("[w35und] Working on USB 2.0\n");
820 pWbUsb->IsUsb20 = 1;
823 err = wb35_hw_init(dev);
824 if (err)
825 goto error_free_hw;
827 SET_IEEE80211_DEV(dev, &udev->dev);
829 struct hw_data *pHwData = &priv->sHwData;
830 unsigned char dev_addr[MAX_ADDR_LEN];
831 hal_get_permanent_address(pHwData, dev_addr);
832 SET_IEEE80211_PERM_ADDR(dev, dev_addr);
835 dev->extra_tx_headroom = 12; /* FIXME */
836 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
837 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
839 dev->channel_change_time = 1000;
840 dev->max_signal = 100;
841 dev->queues = 1;
843 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
845 err = ieee80211_register_hw(dev);
846 if (err)
847 goto error_free_hw;
849 usb_set_intfdata(intf, dev);
851 return 0;
853 error_free_hw:
854 ieee80211_free_hw(dev);
855 error:
856 usb_put_dev(udev);
857 return err;
860 static void hal_halt(struct hw_data *pHwData)
862 del_timer_sync(&pHwData->LEDTimer);
863 /* XXX: Wait for Timer DPC exit. */
864 msleep(100);
865 Wb35Rx_destroy(pHwData);
866 Wb35Tx_destroy(pHwData);
867 Wb35Reg_destroy(pHwData);
870 static void wb35_hw_halt(struct wbsoft_priv *adapter)
872 Mds_Destroy(adapter);
874 /* Turn off Rx and Tx hardware ability */
875 hal_stop(&adapter->sHwData);
876 #ifdef _PE_USB_INI_DUMP_
877 printk("[w35und] Hal_stop O.K.\n");
878 #endif
879 /* Waiting Irp completed */
880 msleep(100);
882 hal_halt(&adapter->sHwData);
885 static void wb35_disconnect(struct usb_interface *intf)
887 struct ieee80211_hw *hw = usb_get_intfdata(intf);
888 struct wbsoft_priv *priv = hw->priv;
890 wb35_hw_halt(priv);
892 ieee80211_stop_queues(hw);
893 ieee80211_unregister_hw(hw);
894 ieee80211_free_hw(hw);
896 usb_set_intfdata(intf, NULL);
897 usb_put_dev(interface_to_usbdev(intf));
900 static struct usb_driver wb35_driver = {
901 .name = "w35und",
902 .id_table = wb35_table,
903 .probe = wb35_probe,
904 .disconnect = wb35_disconnect,
907 static int __init wb35_init(void)
909 return usb_register(&wb35_driver);
912 static void __exit wb35_exit(void)
914 usb_deregister(&wb35_driver);
917 module_init(wb35_init);
918 module_exit(wb35_exit);