Staging: w35und: Kill struct hwdata ->NullPacketCount
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / winbond / wbusb.c
blobdcb6d5b63d76ccee8c775ff79c39d3c7cbb072f0
1 /*
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>
15 #include "core.h"
16 #include "mds_f.h"
17 #include "mlmetxrx_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 #include "wblinux_f.h"
25 MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
26 MODULE_LICENSE("GPL");
27 MODULE_VERSION("0.1");
29 static const struct usb_device_id wb35_table[] __devinitconst = {
30 { USB_DEVICE(0x0416, 0x0035) },
31 { USB_DEVICE(0x18E8, 0x6201) },
32 { USB_DEVICE(0x18E8, 0x6206) },
33 { USB_DEVICE(0x18E8, 0x6217) },
34 { USB_DEVICE(0x18E8, 0x6230) },
35 { USB_DEVICE(0x18E8, 0x6233) },
36 { USB_DEVICE(0x1131, 0x2035) },
37 { 0, }
40 MODULE_DEVICE_TABLE(usb, wb35_table);
42 static struct ieee80211_rate wbsoft_rates[] = {
43 { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
46 static struct ieee80211_channel wbsoft_channels[] = {
47 { .center_freq = 2412 },
50 static struct ieee80211_supported_band wbsoft_band_2GHz = {
51 .channels = wbsoft_channels,
52 .n_channels = ARRAY_SIZE(wbsoft_channels),
53 .bitrates = wbsoft_rates,
54 .n_bitrates = ARRAY_SIZE(wbsoft_rates),
57 static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
59 u32 tmp;
61 if (pHwData->SurpriseRemove)
62 return;
64 pHwData->BeaconPeriod = beacon_period;
65 tmp = pHwData->BeaconPeriod << 16;
66 tmp |= pHwData->ProbeDelay;
67 Wb35Reg_Write(pHwData, 0x0848, tmp);
70 static int wbsoft_add_interface(struct ieee80211_hw *dev,
71 struct ieee80211_vif *vif)
73 struct wbsoft_priv *priv = dev->priv;
75 hal_set_beacon_period(&priv->sHwData, vif->bss_conf.beacon_int);
77 return 0;
80 static void wbsoft_remove_interface(struct ieee80211_hw *dev,
81 struct ieee80211_vif *vif)
83 printk("wbsoft_remove interface called\n");
86 static void wbsoft_stop(struct ieee80211_hw *hw)
88 printk(KERN_INFO "%s called\n", __func__);
91 static int wbsoft_get_stats(struct ieee80211_hw *hw,
92 struct ieee80211_low_level_stats *stats)
94 printk(KERN_INFO "%s called\n", __func__);
95 return 0;
98 static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw,
99 struct netdev_hw_addr_list *mc_list)
101 return netdev_hw_addr_list_count(mc_list);
104 static void wbsoft_configure_filter(struct ieee80211_hw *dev,
105 unsigned int changed_flags,
106 unsigned int *total_flags,
107 u64 multicast)
109 unsigned int new_flags;
111 new_flags = 0;
113 if (*total_flags & FIF_PROMISC_IN_BSS)
114 new_flags |= FIF_PROMISC_IN_BSS;
115 else if ((*total_flags & FIF_ALLMULTI) || (multicast > 32))
116 new_flags |= FIF_ALLMULTI;
118 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
120 *total_flags = new_flags;
123 static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
125 struct wbsoft_priv *priv = dev->priv;
127 if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
128 priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
129 return NETDEV_TX_BUSY;
132 priv->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
134 priv->sMlmeFrame.pMMPDU = skb->data;
135 priv->sMlmeFrame.DataType = FRAME_TYPE_802_11_MANAGEMENT;
136 priv->sMlmeFrame.len = skb->len;
137 priv->sMlmeFrame.wNumTxMMPDU++;
140 * H/W will enter power save by set the register. S/W don't send null
141 * frame with PWRMgt bit enbled to enter power save now.
144 Mds_Tx(priv);
146 return NETDEV_TX_OK;
149 static int wbsoft_start(struct ieee80211_hw *dev)
151 struct wbsoft_priv *priv = dev->priv;
153 priv->enabled = true;
155 return 0;
158 static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
160 struct wb35_reg *reg = &pHwData->reg;
162 if (pHwData->SurpriseRemove)
163 return;
165 if (radio_off) { /* disable Baseband receive off */
166 pHwData->CurrentRadioSw = 1; /* off */
167 reg->M24_MacControl &= 0xffffffbf;
168 } else {
169 pHwData->CurrentRadioSw = 0; /* on */
170 reg->M24_MacControl |= 0x00000040;
172 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
175 static void hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
177 struct wb35_reg *reg = &pHwData->reg;
179 if (pHwData->SurpriseRemove)
180 return;
182 printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo);
184 RFSynthesizer_SwitchingChannel(pHwData, channel); /* Switch channel */
185 pHwData->Channel = channel.ChanNo;
186 pHwData->band = channel.band;
187 #ifdef _PE_STATE_DUMP_
188 printk("Set channel is %d, band =%d\n", pHwData->Channel,
189 pHwData->band);
190 #endif
191 reg->M28_MacControl &= ~0xff; /* Clean channel information field */
192 reg->M28_MacControl |= channel.ChanNo;
193 Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
194 (s8 *) &channel,
195 sizeof(struct chan_info));
198 static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
200 hal_set_current_channel_ex(pHwData, channel);
203 static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
205 struct wb35_reg *reg = &pHwData->reg;
207 if (pHwData->SurpriseRemove)
208 return;
210 reg->M00_MacControl &= ~0x02000000; /* The HW value */
212 if (enable)
213 reg->M00_MacControl |= 0x02000000; /* The HW value */
215 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
218 /* For wep key error detection, we need to accept broadcast packets to be received temporary. */
219 static void hal_set_accept_promiscuous(struct hw_data *pHwData, u8 enable)
221 struct wb35_reg *reg = &pHwData->reg;
223 if (pHwData->SurpriseRemove)
224 return;
226 if (enable) {
227 reg->M00_MacControl |= 0x00400000;
228 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
229 } else {
230 reg->M00_MacControl &= ~0x00400000;
231 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
235 static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
237 struct wb35_reg *reg = &pHwData->reg;
239 if (pHwData->SurpriseRemove)
240 return;
242 reg->M00_MacControl &= ~0x01000000; /* The HW value */
243 if (enable)
244 reg->M00_MacControl |= 0x01000000; /* The HW value */
245 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
248 static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
250 struct wb35_reg *reg = &pHwData->reg;
252 if (pHwData->SurpriseRemove)
253 return;
255 if (!enable) /* Due to SME and MLME are not suitable for 35 */
256 return;
258 reg->M00_MacControl &= ~0x04000000; /* The HW value */
259 if (enable)
260 reg->M00_MacControl |= 0x04000000; /* The HW value */
262 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
265 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
267 struct wbsoft_priv *priv = dev->priv;
268 struct chan_info ch;
270 printk("wbsoft_config called\n");
272 /* Should use channel_num, or something, as that is already pre-translated */
273 ch.band = 1;
274 ch.ChanNo = 1;
276 hal_set_current_channel(&priv->sHwData, ch);
277 hal_set_accept_broadcast(&priv->sHwData, 1);
278 hal_set_accept_promiscuous(&priv->sHwData, 1);
279 hal_set_accept_multicast(&priv->sHwData, 1);
280 hal_set_accept_beacon(&priv->sHwData, 1);
281 hal_set_radio_mode(&priv->sHwData, 0);
283 return 0;
286 static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
288 printk("wbsoft_get_tsf called\n");
289 return 0;
292 static const struct ieee80211_ops wbsoft_ops = {
293 .tx = wbsoft_tx,
294 .start = wbsoft_start,
295 .stop = wbsoft_stop,
296 .add_interface = wbsoft_add_interface,
297 .remove_interface = wbsoft_remove_interface,
298 .config = wbsoft_config,
299 .prepare_multicast = wbsoft_prepare_multicast,
300 .configure_filter = wbsoft_configure_filter,
301 .get_stats = wbsoft_get_stats,
302 .get_tsf = wbsoft_get_tsf,
305 static void hal_set_ethernet_address(struct hw_data *pHwData, u8 *current_address)
307 u32 ltmp[2];
309 if (pHwData->SurpriseRemove)
310 return;
312 memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
314 ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
315 ltmp[1] = cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
317 Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
320 static void hal_get_permanent_address(struct hw_data *pHwData, u8 *pethernet_address)
322 if (pHwData->SurpriseRemove)
323 return;
325 memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
328 static void hal_stop(struct hw_data *pHwData)
330 struct wb35_reg *reg = &pHwData->reg;
332 pHwData->Wb35Rx.rx_halt = 1;
333 Wb35Rx_stop(pHwData);
335 pHwData->Wb35Tx.tx_halt = 1;
336 Wb35Tx_stop(pHwData);
338 reg->D00_DmaControl &= ~0xc0000000; /* Tx Off, Rx Off */
339 Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
342 static unsigned char hal_idle(struct hw_data *pHwData)
344 struct wb35_reg *reg = &pHwData->reg;
345 struct wb_usb *pWbUsb = &pHwData->WbUsb;
347 if (!pHwData->SurpriseRemove
348 && (pWbUsb->DetectCount || reg->EP0vm_state != VM_STOP))
349 return false;
351 return true;
354 u8 hal_get_antenna_number(struct hw_data *pHwData)
356 struct wb35_reg *reg = &pHwData->reg;
358 if ((reg->BB2C & BIT(11)) == 0)
359 return 0;
360 else
361 return 1;
364 /* 0 : radio on; 1: radio off */
365 static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
367 struct wb35_reg *reg = &pHwData->reg;
369 if (pHwData->SurpriseRemove)
370 return 1;
372 /* read the bit16 of register U1B0 */
373 Wb35Reg_Read(pHwData, 0x3b0, &reg->U1B0);
374 if ((reg->U1B0 & 0x00010000)) {
375 pHwData->CurrentRadioHw = 1;
376 return 1;
377 } else {
378 pHwData->CurrentRadioHw = 0;
379 return 0;
383 static u8 LED_GRAY[20] = {
384 0, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2
387 static u8 LED_GRAY2[30] = {
388 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
389 0, 15, 14, 13, 12, 11, 10, 9, 8
392 static void hal_led_control(unsigned long data)
394 struct wbsoft_priv *adapter = (struct wbsoft_priv *)data;
395 struct hw_data *pHwData = &adapter->sHwData;
396 struct wb35_reg *reg = &pHwData->reg;
397 u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
398 u32 TimeInterval = 500, ltmp, ltmp2;
399 ltmp = 0;
401 if (pHwData->SurpriseRemove)
402 return;
404 if (pHwData->LED_control) {
405 ltmp2 = pHwData->LED_control & 0xff;
406 if (ltmp2 == 5) { /* 5 is WPS mode */
407 TimeInterval = 100;
408 ltmp2 = (pHwData->LED_control >> 8) & 0xff;
409 switch (ltmp2) {
410 case 1: /* [0.2 On][0.1 Off]... */
411 pHwData->LED_Blinking %= 3;
412 ltmp = 0x1010; /* Led 1 & 0 Green and Red */
413 if (pHwData->LED_Blinking == 2) /* Turn off */
414 ltmp = 0;
415 break;
416 case 2: /* [0.1 On][0.1 Off]... */
417 pHwData->LED_Blinking %= 2;
418 ltmp = 0x0010; /* Led 0 red color */
419 if (pHwData->LED_Blinking) /* Turn off */
420 ltmp = 0;
421 break;
422 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]... */
423 pHwData->LED_Blinking %= 15;
424 ltmp = 0x0010; /* Led 0 red color */
425 if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) /* Turn off 0.6 sec */
426 ltmp = 0;
427 break;
428 case 4: /* [300 On][ off ] */
429 ltmp = 0x1000; /* Led 1 Green color */
430 if (pHwData->LED_Blinking >= 3000)
431 ltmp = 0; /* led maybe on after 300sec * 32bit counter overlap. */
432 break;
434 pHwData->LED_Blinking++;
436 reg->U1BC_LEDConfigure = ltmp;
437 if (LEDSet != 7) { /* Only 111 mode has 2 LEDs on PCB. */
438 reg->U1BC_LEDConfigure |= (ltmp & 0xff) << 8; /* Copy LED result to each LED control register */
439 reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
441 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
443 } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) { /* If radio off */
444 if (reg->U1BC_LEDConfigure & 0x1010) {
445 reg->U1BC_LEDConfigure &= ~0x1010;
446 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
448 } else {
449 switch (LEDSet) {
450 case 4: /* [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
451 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
452 /* Blinking if scanning is on progress */
453 if (pHwData->LED_Scanning) {
454 if (pHwData->LED_Blinking == 0) {
455 reg->U1BC_LEDConfigure |= 0x10;
456 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
457 pHwData->LED_Blinking = 1;
458 TimeInterval = 300;
459 } else {
460 reg->U1BC_LEDConfigure &= ~0x10;
461 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
462 pHwData->LED_Blinking = 0;
463 TimeInterval = 300;
465 } else {
466 /* Turn Off LED_0 */
467 if (reg->U1BC_LEDConfigure & 0x10) {
468 reg->U1BC_LEDConfigure &= ~0x10;
469 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
472 } else {
473 /* Turn On LED_0 */
474 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
475 reg->U1BC_LEDConfigure |= 0x10;
476 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
479 break;
480 case 6: /* [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
481 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
482 /* Blinking if scanning is on progress */
483 if (pHwData->LED_Scanning) {
484 if (pHwData->LED_Blinking == 0) {
485 reg->U1BC_LEDConfigure &= ~0xf;
486 reg->U1BC_LEDConfigure |= 0x10;
487 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
488 pHwData->LED_Blinking = 1;
489 TimeInterval = 300;
490 } else {
491 reg->U1BC_LEDConfigure &= ~0x1f;
492 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
493 pHwData->LED_Blinking = 0;
494 TimeInterval = 300;
496 } else {
497 /* Gray blinking if in disconnect state and not scanning */
498 ltmp = reg->U1BC_LEDConfigure;
499 reg->U1BC_LEDConfigure &= ~0x1f;
500 if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
501 reg->U1BC_LEDConfigure |= 0x10;
502 reg->U1BC_LEDConfigure |=
503 LED_GRAY2[(pHwData->LED_Blinking % 30)];
505 pHwData->LED_Blinking++;
506 if (reg->U1BC_LEDConfigure != ltmp)
507 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
508 TimeInterval = 100;
510 } else {
511 /* Turn On LED_0 */
512 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
513 reg->U1BC_LEDConfigure |= 0x10;
514 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
517 break;
518 case 5: /* [101] Only 1 Led be placed on PCB and use LED_1 for showing */
519 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 |= 0x1000;
524 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
525 pHwData->LED_Blinking = 1;
526 TimeInterval = 300;
527 } else {
528 reg->U1BC_LEDConfigure &= ~0x1000;
529 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
530 pHwData->LED_Blinking = 0;
531 TimeInterval = 300;
533 } else {
534 /* Turn Off LED_1 */
535 if (reg->U1BC_LEDConfigure & 0x1000) {
536 reg->U1BC_LEDConfigure &= ~0x1000;
537 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
540 } else {
541 /* Is transmitting/receiving ?? */
542 if ((adapter->RxByteCount !=
543 pHwData->RxByteCountLast)
544 || (adapter->TxByteCount !=
545 pHwData->TxByteCountLast)) {
546 if ((reg->U1BC_LEDConfigure & 0x3000) !=
547 0x3000) {
548 reg->U1BC_LEDConfigure |= 0x3000;
549 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
551 /* Update variable */
552 pHwData->RxByteCountLast =
553 adapter->RxByteCount;
554 pHwData->TxByteCountLast =
555 adapter->TxByteCount;
556 TimeInterval = 200;
557 } else {
558 /* Turn On LED_1 and blinking if transmitting/receiving */
559 if ((reg->U1BC_LEDConfigure & 0x3000) !=
560 0x1000) {
561 reg->U1BC_LEDConfigure &=
562 ~0x3000;
563 reg->U1BC_LEDConfigure |=
564 0x1000;
565 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
569 break;
570 default: /* Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active */
571 if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
572 reg->U1BC_LEDConfigure |= 0x3000; /* LED_1 is always on and event enable */
573 Wb35Reg_Write(pHwData, 0x03bc,
574 reg->U1BC_LEDConfigure);
577 if (pHwData->LED_Blinking) {
578 /* Gray blinking */
579 reg->U1BC_LEDConfigure &= ~0x0f;
580 reg->U1BC_LEDConfigure |= 0x10;
581 reg->U1BC_LEDConfigure |=
582 LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
583 Wb35Reg_Write(pHwData, 0x03bc,
584 reg->U1BC_LEDConfigure);
586 pHwData->LED_Blinking += 2;
587 if (pHwData->LED_Blinking < 40)
588 TimeInterval = 100;
589 else {
590 pHwData->LED_Blinking = 0; /* Stop blinking */
591 reg->U1BC_LEDConfigure &= ~0x0f;
592 Wb35Reg_Write(pHwData, 0x03bc,
593 reg->U1BC_LEDConfigure);
595 break;
598 if (pHwData->LED_LinkOn) {
599 if (!(reg->U1BC_LEDConfigure & 0x10)) { /* Check the LED_0 */
600 /* Try to turn ON LED_0 after gray blinking */
601 reg->U1BC_LEDConfigure |= 0x10;
602 pHwData->LED_Blinking = 1; /* Start blinking */
603 TimeInterval = 50;
605 } else {
606 if (reg->U1BC_LEDConfigure & 0x10) { /* Check the LED_0 */
607 reg->U1BC_LEDConfigure &= ~0x10;
608 Wb35Reg_Write(pHwData, 0x03bc,
609 reg->U1BC_LEDConfigure);
612 break;
616 pHwData->time_count += TimeInterval;
617 Wb35Tx_CurrentTime(adapter, pHwData->time_count);
618 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
619 add_timer(&pHwData->LEDTimer);
622 static int hal_init_hardware(struct ieee80211_hw *hw)
624 struct wbsoft_priv *priv = hw->priv;
625 struct hw_data *pHwData = &priv->sHwData;
626 u16 SoftwareSet;
628 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
629 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
631 if (!Wb35Reg_initial(pHwData))
632 goto error_reg_destroy;
634 if (!Wb35Tx_initial(pHwData))
635 goto error_tx_destroy;
637 if (!Wb35Rx_initial(pHwData))
638 goto error_rx_destroy;
640 init_timer(&pHwData->LEDTimer);
641 pHwData->LEDTimer.function = hal_led_control;
642 pHwData->LEDTimer.data = (unsigned long)priv;
643 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
644 add_timer(&pHwData->LEDTimer);
646 SoftwareSet = hal_software_set(pHwData);
648 #ifdef Vendor2
649 /* Try to make sure the EEPROM contain */
650 SoftwareSet >>= 8;
651 if (SoftwareSet != 0x82)
652 return false;
653 #endif
655 Wb35Rx_start(hw);
656 Wb35Tx_EP2VM_start(priv);
658 return 0;
660 error_rx_destroy:
661 Wb35Rx_destroy(pHwData);
662 error_tx_destroy:
663 Wb35Tx_destroy(pHwData);
664 error_reg_destroy:
665 Wb35Reg_destroy(pHwData);
667 pHwData->SurpriseRemove = 1;
668 return -EINVAL;
671 static int wb35_hw_init(struct ieee80211_hw *hw)
673 struct wbsoft_priv *priv = hw->priv;
674 struct hw_data *pHwData = &priv->sHwData;
675 u8 EEPROM_region;
676 u8 HwRadioOff;
677 u8 *pMacAddr2;
678 u8 *pMacAddr;
679 int err;
681 pHwData->phy_type = RF_DECIDE_BY_INF;
683 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
684 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
686 priv->sLocalPara.region_INF = REGION_AUTO;
687 priv->sLocalPara.TxRateMode = RATE_AUTO;
688 priv->sLocalPara.bMacOperationMode = MODE_802_11_BG;
689 priv->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
690 priv->sLocalPara.bPreambleMode = AUTO_MODE;
691 priv->sLocalPara.bWepKeyError = false;
692 priv->sLocalPara.bToSelfPacketReceived = false;
693 priv->sLocalPara.WepKeyDetectTimerCount = 2 * 100; /* 2 seconds */
695 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
697 err = hal_init_hardware(hw);
698 if (err)
699 goto error;
701 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
702 if (EEPROM_region != REGION_AUTO)
703 priv->sLocalPara.region = EEPROM_region;
704 else {
705 if (priv->sLocalPara.region_INF != REGION_AUTO)
706 priv->sLocalPara.region = priv->sLocalPara.region_INF;
707 else
708 priv->sLocalPara.region = REGION_USA; /* default setting */
711 Mds_initial(priv);
714 * If no user-defined address in the registry, use the address
715 * "burned" on the NIC instead.
717 pMacAddr = priv->sLocalPara.ThisMacAddress;
718 pMacAddr2 = priv->sLocalPara.PermanentAddress;
720 /* Reading ethernet address from EEPROM */
721 hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
722 if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
723 memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
724 else {
725 /* Set the user define MAC address */
726 hal_set_ethernet_address(pHwData,
727 priv->sLocalPara.ThisMacAddress);
730 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
731 #ifdef _PE_STATE_DUMP_
732 printk("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo);
733 #endif
734 hal_get_hw_radio_off(pHwData);
736 /* Waiting for HAL setting OK */
737 while (!hal_idle(pHwData))
738 msleep(10);
740 MTO_Init(priv);
742 HwRadioOff = hal_get_hw_radio_off(pHwData);
743 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
745 hal_set_radio_mode(pHwData,
746 (unsigned char)(priv->sLocalPara.RadioOffStatus.
747 boSwRadioOff
748 || priv->sLocalPara.RadioOffStatus.
749 boHwRadioOff));
751 /* Notify hal that the driver is ready now. */
752 hal_driver_init_OK(pHwData) = 1;
754 error:
755 return err;
758 static int wb35_probe(struct usb_interface *intf,
759 const struct usb_device_id *id_table)
761 struct usb_device *udev = interface_to_usbdev(intf);
762 struct usb_endpoint_descriptor *endpoint;
763 struct usb_host_interface *interface;
764 struct ieee80211_hw *dev;
765 struct wbsoft_priv *priv;
766 struct wb_usb *pWbUsb;
767 int nr, err;
768 u32 ltmp;
770 usb_get_dev(udev);
772 /* Check the device if it already be opened */
773 nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
774 0x01,
775 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
776 0x0, 0x400, &ltmp, 4, HZ * 100);
777 if (nr < 0) {
778 err = nr;
779 goto error;
782 /* Is already initialized? */
783 ltmp = cpu_to_le32(ltmp);
784 if (ltmp) {
785 err = -EBUSY;
786 goto error;
789 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
790 if (!dev) {
791 err = -ENOMEM;
792 goto error;
795 priv = dev->priv;
797 pWbUsb = &priv->sHwData.WbUsb;
798 pWbUsb->udev = udev;
800 interface = intf->cur_altsetting;
801 endpoint = &interface->endpoint[0].desc;
803 if (endpoint[2].wMaxPacketSize == 512) {
804 printk("[w35und] Working on USB 2.0\n");
805 pWbUsb->IsUsb20 = 1;
808 err = wb35_hw_init(dev);
809 if (err)
810 goto error_free_hw;
812 SET_IEEE80211_DEV(dev, &udev->dev);
814 struct hw_data *pHwData = &priv->sHwData;
815 unsigned char dev_addr[MAX_ADDR_LEN];
816 hal_get_permanent_address(pHwData, dev_addr);
817 SET_IEEE80211_PERM_ADDR(dev, dev_addr);
820 dev->extra_tx_headroom = 12; /* FIXME */
821 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
822 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
824 dev->channel_change_time = 1000;
825 dev->max_signal = 100;
826 dev->queues = 1;
828 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
830 err = ieee80211_register_hw(dev);
831 if (err)
832 goto error_free_hw;
834 usb_set_intfdata(intf, dev);
836 return 0;
838 error_free_hw:
839 ieee80211_free_hw(dev);
840 error:
841 usb_put_dev(udev);
842 return err;
845 static void hal_halt(struct hw_data *pHwData)
847 del_timer_sync(&pHwData->LEDTimer);
848 /* XXX: Wait for Timer DPC exit. */
849 msleep(100);
850 Wb35Rx_destroy(pHwData);
851 Wb35Tx_destroy(pHwData);
852 Wb35Reg_destroy(pHwData);
855 static void wb35_hw_halt(struct wbsoft_priv *adapter)
857 /* Turn off Rx and Tx hardware ability */
858 hal_stop(&adapter->sHwData);
859 #ifdef _PE_USB_INI_DUMP_
860 printk("[w35und] Hal_stop O.K.\n");
861 #endif
862 /* Waiting Irp completed */
863 msleep(100);
865 hal_halt(&adapter->sHwData);
868 static void wb35_disconnect(struct usb_interface *intf)
870 struct ieee80211_hw *hw = usb_get_intfdata(intf);
871 struct wbsoft_priv *priv = hw->priv;
873 wb35_hw_halt(priv);
875 ieee80211_stop_queues(hw);
876 ieee80211_unregister_hw(hw);
877 ieee80211_free_hw(hw);
879 usb_set_intfdata(intf, NULL);
880 usb_put_dev(interface_to_usbdev(intf));
883 static struct usb_driver wb35_driver = {
884 .name = "w35und",
885 .id_table = wb35_table,
886 .probe = wb35_probe,
887 .disconnect = wb35_disconnect,
890 static int __init wb35_init(void)
892 return usb_register(&wb35_driver);
895 static void __exit wb35_exit(void)
897 usb_deregister(&wb35_driver);
900 module_init(wb35_init);
901 module_exit(wb35_exit);