]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/staging/winbond/wbusb.c
Staging: w35und: Merge wbhal_f.h to wbhal_s.h
[mirror_ubuntu-artful-kernel.git] / drivers / staging / winbond / wbusb.c
CommitLineData
66101de1 1/*
a2531293 2 * Copyright 2008 Pavel Machek <pavel@ucw.cz>
66101de1
PM
3 *
4 * Distribute under GPLv2.
7c49a0ac
PE
5 *
6 * The original driver was written by:
7 * Jeff Lee <YY_Lee@issc.com.tw>
8 *
9 * and was adapted to the 2.6 kernel by:
10 * Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar>
66101de1 11 */
66101de1 12#include <net/mac80211.h>
80aba536
PE
13#include <linux/usb.h>
14
cc180710 15#include "core.h"
912b209f 16#include "mds_f.h"
9ce922fd 17#include "mlmetxrx_f.h"
64328c87 18#include "mto.h"
72ca8819
PE
19#include "wbhal_s.h"
20#include "wb35reg_f.h"
21#include "wb35tx_f.h"
22#include "wb35rx_f.h"
9ce922fd 23#include "wblinux_f.h"
66101de1 24
7b9a79bf 25MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
66101de1
PM
26MODULE_LICENSE("GPL");
27MODULE_VERSION("0.1");
28
a457732b 29static const struct usb_device_id wb35_table[] __devinitconst = {
a32b9810
PE
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) },
68ab0c96 37 { 0, }
66101de1
PM
38};
39
dd38da46 40MODULE_DEVICE_TABLE(usb, wb35_table);
66101de1 41
68ab0c96 42static struct ieee80211_rate wbsoft_rates[] = {
66101de1
PM
43 { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
44};
45
68ab0c96 46static struct ieee80211_channel wbsoft_channels[] = {
a32b9810 47 { .center_freq = 2412 },
66101de1
PM
48};
49
a36e0894
PE
50static 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),
55};
56
4074e77c
PE
57static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
58{
59 u32 tmp;
60
61 if (pHwData->SurpriseRemove)
62 return;
63
64 pHwData->BeaconPeriod = beacon_period;
65 tmp = pHwData->BeaconPeriod << 16;
66 tmp |= pHwData->ProbeDelay;
67 Wb35Reg_Write(pHwData, 0x0848, tmp);
68}
69
66101de1 70static int wbsoft_add_interface(struct ieee80211_hw *dev,
a71b676f 71 struct ieee80211_vif *vif)
66101de1 72{
4074e77c
PE
73 struct wbsoft_priv *priv = dev->priv;
74
a71b676f 75 hal_set_beacon_period(&priv->sHwData, vif->bss_conf.beacon_int);
4074e77c 76
66101de1
PM
77 return 0;
78}
79
80static void wbsoft_remove_interface(struct ieee80211_hw *dev,
a71b676f 81 struct ieee80211_vif *vif)
66101de1
PM
82{
83 printk("wbsoft_remove interface called\n");
84}
85
68ab0c96 86static void wbsoft_stop(struct ieee80211_hw *hw)
66101de1 87{
68ab0c96
GKH
88 printk(KERN_INFO "%s called\n", __func__);
89}
90
91static int wbsoft_get_stats(struct ieee80211_hw *hw,
92 struct ieee80211_low_level_stats *stats)
93{
94 printk(KERN_INFO "%s called\n", __func__);
95 return 0;
96}
97
22bedad3
JP
98static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw,
99 struct netdev_hw_addr_list *mc_list)
6d7fd647 100{
22bedad3 101 return netdev_hw_addr_list_count(mc_list);
6d7fd647
JM
102}
103
66101de1 104static void wbsoft_configure_filter(struct ieee80211_hw *dev,
a32b9810
PE
105 unsigned int changed_flags,
106 unsigned int *total_flags,
6d7fd647 107 u64 multicast)
66101de1 108{
6ab32127 109 unsigned int new_flags;
66101de1
PM
110
111 new_flags = 0;
112
6ab32127 113 if (*total_flags & FIF_PROMISC_IN_BSS)
66101de1 114 new_flags |= FIF_PROMISC_IN_BSS;
6d7fd647 115 else if ((*total_flags & FIF_ALLMULTI) || (multicast > 32))
66101de1 116 new_flags |= FIF_ALLMULTI;
66101de1
PM
117
118 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
119
120 *total_flags = new_flags;
121}
122
68ab0c96 123static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
66101de1 124{
cc180710
PE
125 struct wbsoft_priv *priv = dev->priv;
126
11c9a55d
PE
127 if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
128 priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
129 return NETDEV_TX_BUSY;
130 }
131
132 priv->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
133
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++;
138
139 /*
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.
142 */
143
144 Mds_Tx(priv);
145
146 return NETDEV_TX_OK;
66101de1
PM
147}
148
66101de1
PM
149static int wbsoft_start(struct ieee80211_hw *dev)
150{
c930e0c0
PE
151 struct wbsoft_priv *priv = dev->priv;
152
153 priv->enabled = true;
154
66101de1
PM
155 return 0;
156}
157
22a82bcd
PE
158static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
159{
160 struct wb35_reg *reg = &pHwData->reg;
161
162 if (pHwData->SurpriseRemove)
163 return;
164
e5851c20
LL
165 if (radio_off) { /* disable Baseband receive off */
166 pHwData->CurrentRadioSw = 1; /* off */
22a82bcd
PE
167 reg->M24_MacControl &= 0xffffffbf;
168 } else {
e5851c20 169 pHwData->CurrentRadioSw = 0; /* on */
22a82bcd
PE
170 reg->M24_MacControl |= 0x00000040;
171 }
172 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
173}
174
e5851c20 175static void hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
22a82bcd
PE
176{
177 struct wb35_reg *reg = &pHwData->reg;
178
179 if (pHwData->SurpriseRemove)
180 return;
181
182 printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo);
183
e5851c20 184 RFSynthesizer_SwitchingChannel(pHwData, channel); /* Switch channel */
22a82bcd
PE
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
e5851c20 191 reg->M28_MacControl &= ~0xff; /* Clean channel information field */
22a82bcd
PE
192 reg->M28_MacControl |= channel.ChanNo;
193 Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
e5851c20
LL
194 (s8 *) &channel,
195 sizeof(struct chan_info));
22a82bcd
PE
196}
197
440a233d 198static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
22a82bcd
PE
199{
200 hal_set_current_channel_ex(pHwData, channel);
201}
202
203static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
204{
205 struct wb35_reg *reg = &pHwData->reg;
206
207 if (pHwData->SurpriseRemove)
208 return;
209
e5851c20 210 reg->M00_MacControl &= ~0x02000000; /* The HW value */
22a82bcd
PE
211
212 if (enable)
e5851c20 213 reg->M00_MacControl |= 0x02000000; /* The HW value */
22a82bcd
PE
214
215 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
216}
217
e5851c20 218/* For wep key error detection, we need to accept broadcast packets to be received temporary. */
22a82bcd
PE
219static void hal_set_accept_promiscuous(struct hw_data *pHwData, u8 enable)
220{
221 struct wb35_reg *reg = &pHwData->reg;
222
223 if (pHwData->SurpriseRemove)
224 return;
e5851c20 225
22a82bcd
PE
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);
232 }
233}
234
235static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
236{
237 struct wb35_reg *reg = &pHwData->reg;
238
239 if (pHwData->SurpriseRemove)
240 return;
241
e5851c20 242 reg->M00_MacControl &= ~0x01000000; /* The HW value */
22a82bcd 243 if (enable)
e5851c20 244 reg->M00_MacControl |= 0x01000000; /* The HW value */
22a82bcd
PE
245 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
246}
247
248static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
249{
250 struct wb35_reg *reg = &pHwData->reg;
251
252 if (pHwData->SurpriseRemove)
253 return;
254
e5851c20 255 if (!enable) /* Due to SME and MLME are not suitable for 35 */
22a82bcd
PE
256 return;
257
e5851c20 258 reg->M00_MacControl &= ~0x04000000; /* The HW value */
22a82bcd 259 if (enable)
e5851c20 260 reg->M00_MacControl |= 0x04000000; /* The HW value */
22a82bcd
PE
261
262 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
263}
264
f02466fc 265static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
66101de1 266{
cc180710 267 struct wbsoft_priv *priv = dev->priv;
440a233d 268 struct chan_info ch;
f02466fc 269
66101de1
PM
270 printk("wbsoft_config called\n");
271
bdbb8839 272 /* Should use channel_num, or something, as that is already pre-translated */
66101de1 273 ch.band = 1;
bdbb8839 274 ch.ChanNo = 1;
66101de1 275
1e8a2b60 276 hal_set_current_channel(&priv->sHwData, ch);
1e8a2b60 277 hal_set_accept_broadcast(&priv->sHwData, 1);
a32b9810
PE
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);
66101de1
PM
282
283 return 0;
284}
285
66101de1
PM
286static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
287{
288 printk("wbsoft_get_tsf called\n");
289 return 0;
290}
291
292static const struct ieee80211_ops wbsoft_ops = {
293 .tx = wbsoft_tx,
bdbb8839 294 .start = wbsoft_start,
68ab0c96 295 .stop = wbsoft_stop,
66101de1
PM
296 .add_interface = wbsoft_add_interface,
297 .remove_interface = wbsoft_remove_interface,
298 .config = wbsoft_config,
6d7fd647 299 .prepare_multicast = wbsoft_prepare_multicast,
66101de1 300 .configure_filter = wbsoft_configure_filter,
68ab0c96 301 .get_stats = wbsoft_get_stats,
66101de1 302 .get_tsf = wbsoft_get_tsf,
66101de1
PM
303};
304
e5851c20 305static void hal_set_ethernet_address(struct hw_data *pHwData, u8 *current_address)
22a82bcd
PE
306{
307 u32 ltmp[2];
308
309 if (pHwData->SurpriseRemove)
310 return;
311
312 memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
313
314 ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
e5851c20 315 ltmp[1] = cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
22a82bcd
PE
316
317 Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
318}
319
e5851c20 320static void hal_get_permanent_address(struct hw_data *pHwData, u8 *pethernet_address)
22a82bcd
PE
321{
322 if (pHwData->SurpriseRemove)
323 return;
324
325 memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
326}
327
328static void hal_stop(struct hw_data *pHwData)
329{
330 struct wb35_reg *reg = &pHwData->reg;
331
332 pHwData->Wb35Rx.rx_halt = 1;
333 Wb35Rx_stop(pHwData);
334
335 pHwData->Wb35Tx.tx_halt = 1;
336 Wb35Tx_stop(pHwData);
337
e5851c20 338 reg->D00_DmaControl &= ~0xc0000000; /* Tx Off, Rx Off */
22a82bcd
PE
339 Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
340}
341
342static unsigned char hal_idle(struct hw_data *pHwData)
343{
344 struct wb35_reg *reg = &pHwData->reg;
345 struct wb_usb *pWbUsb = &pHwData->WbUsb;
346
347 if (!pHwData->SurpriseRemove
348 && (pWbUsb->DetectCount || reg->EP0vm_state != VM_STOP))
349 return false;
350
351 return true;
352}
353
354u8 hal_get_antenna_number(struct hw_data *pHwData)
355{
356 struct wb35_reg *reg = &pHwData->reg;
357
358 if ((reg->BB2C & BIT(11)) == 0)
359 return 0;
360 else
361 return 1;
362}
363
364/* 0 : radio on; 1: radio off */
e5851c20 365static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
22a82bcd
PE
366{
367 struct wb35_reg *reg = &pHwData->reg;
368
369 if (pHwData->SurpriseRemove)
370 return 1;
371
e5851c20 372 /* read the bit16 of register U1B0 */
22a82bcd
PE
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;
380 }
381}
382
833d0cd3
PE
383static 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
385};
386
387static 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
390};
391
80767e6e
PE
392static void hal_led_control(unsigned long data)
393{
a32b9810
PE
394 struct wbsoft_priv *adapter = (struct wbsoft_priv *)data;
395 struct hw_data *pHwData = &adapter->sHwData;
80767e6e 396 struct wb35_reg *reg = &pHwData->reg;
a32b9810 397 u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
a32b9810
PE
398 u32 TimeInterval = 500, ltmp, ltmp2;
399 ltmp = 0;
80767e6e 400
a32b9810
PE
401 if (pHwData->SurpriseRemove)
402 return;
80767e6e 403
a32b9810 404 if (pHwData->LED_control) {
80767e6e 405 ltmp2 = pHwData->LED_control & 0xff;
e5851c20 406 if (ltmp2 == 5) { /* 5 is WPS mode */
80767e6e 407 TimeInterval = 100;
a32b9810
PE
408 ltmp2 = (pHwData->LED_control >> 8) & 0xff;
409 switch (ltmp2) {
e5851c20 410 case 1: /* [0.2 On][0.1 Off]... */
a32b9810 411 pHwData->LED_Blinking %= 3;
e5851c20
LL
412 ltmp = 0x1010; /* Led 1 & 0 Green and Red */
413 if (pHwData->LED_Blinking == 2) /* Turn off */
a32b9810
PE
414 ltmp = 0;
415 break;
e5851c20 416 case 2: /* [0.1 On][0.1 Off]... */
a32b9810 417 pHwData->LED_Blinking %= 2;
e5851c20
LL
418 ltmp = 0x0010; /* Led 0 red color */
419 if (pHwData->LED_Blinking) /* Turn off */
a32b9810
PE
420 ltmp = 0;
421 break;
e5851c20 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]... */
a32b9810 423 pHwData->LED_Blinking %= 15;
e5851c20
LL
424 ltmp = 0x0010; /* Led 0 red color */
425 if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) /* Turn off 0.6 sec */
a32b9810
PE
426 ltmp = 0;
427 break;
e5851c20
LL
428 case 4: /* [300 On][ off ] */
429 ltmp = 0x1000; /* Led 1 Green color */
a32b9810 430 if (pHwData->LED_Blinking >= 3000)
e5851c20 431 ltmp = 0; /* led maybe on after 300sec * 32bit counter overlap. */
a32b9810 432 break;
80767e6e
PE
433 }
434 pHwData->LED_Blinking++;
435
436 reg->U1BC_LEDConfigure = ltmp;
e5851c20
LL
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 */
a32b9810 439 reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
80767e6e 440 }
a32b9810 441 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
80767e6e 442 }
e5851c20 443 } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) { /* If radio off */
a32b9810 444 if (reg->U1BC_LEDConfigure & 0x1010) {
80767e6e 445 reg->U1BC_LEDConfigure &= ~0x1010;
a32b9810 446 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
80767e6e 447 }
a32b9810
PE
448 } else {
449 switch (LEDSet) {
e5851c20
LL
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 */
a32b9810
PE
453 if (pHwData->LED_Scanning) {
454 if (pHwData->LED_Blinking == 0) {
455 reg->U1BC_LEDConfigure |= 0x10;
e5851c20 456 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
a32b9810
PE
457 pHwData->LED_Blinking = 1;
458 TimeInterval = 300;
459 } else {
460 reg->U1BC_LEDConfigure &= ~0x10;
e5851c20 461 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
a32b9810
PE
462 pHwData->LED_Blinking = 0;
463 TimeInterval = 300;
80767e6e 464 }
a32b9810 465 } else {
e5851c20 466 /* Turn Off LED_0 */
a32b9810
PE
467 if (reg->U1BC_LEDConfigure & 0x10) {
468 reg->U1BC_LEDConfigure &= ~0x10;
e5851c20 469 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
80767e6e
PE
470 }
471 }
a32b9810 472 } else {
e5851c20 473 /* Turn On LED_0 */
a32b9810
PE
474 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
475 reg->U1BC_LEDConfigure |= 0x10;
e5851c20 476 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
80767e6e 477 }
a32b9810
PE
478 }
479 break;
e5851c20
LL
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 */
a32b9810
PE
483 if (pHwData->LED_Scanning) {
484 if (pHwData->LED_Blinking == 0) {
485 reg->U1BC_LEDConfigure &= ~0xf;
486 reg->U1BC_LEDConfigure |= 0x10;
e5851c20 487 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
a32b9810
PE
488 pHwData->LED_Blinking = 1;
489 TimeInterval = 300;
490 } else {
80767e6e 491 reg->U1BC_LEDConfigure &= ~0x1f;
e5851c20 492 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
a32b9810
PE
493 pHwData->LED_Blinking = 0;
494 TimeInterval = 300;
80767e6e 495 }
a32b9810 496 } else {
e5851c20 497 /* Gray blinking if in disconnect state and not scanning */
a32b9810
PE
498 ltmp = reg->U1BC_LEDConfigure;
499 reg->U1BC_LEDConfigure &= ~0x1f;
833d0cd3 500 if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
80767e6e 501 reg->U1BC_LEDConfigure |= 0x10;
a32b9810 502 reg->U1BC_LEDConfigure |=
833d0cd3 503 LED_GRAY2[(pHwData->LED_Blinking % 30)];
80767e6e 504 }
a32b9810
PE
505 pHwData->LED_Blinking++;
506 if (reg->U1BC_LEDConfigure != ltmp)
e5851c20 507 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
a32b9810 508 TimeInterval = 100;
80767e6e 509 }
a32b9810 510 } else {
e5851c20 511 /* Turn On LED_0 */
a32b9810
PE
512 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
513 reg->U1BC_LEDConfigure |= 0x10;
e5851c20 514 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
a32b9810
PE
515 }
516 }
517 break;
e5851c20
LL
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 */
a32b9810
PE
521 if (pHwData->LED_Scanning) {
522 if (pHwData->LED_Blinking == 0) {
e5851c20
LL
523 reg->U1BC_LEDConfigure |= 0x1000;
524 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
a32b9810
PE
525 pHwData->LED_Blinking = 1;
526 TimeInterval = 300;
527 } else {
e5851c20
LL
528 reg->U1BC_LEDConfigure &= ~0x1000;
529 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
a32b9810
PE
530 pHwData->LED_Blinking = 0;
531 TimeInterval = 300;
80767e6e 532 }
a32b9810 533 } else {
e5851c20 534 /* Turn Off LED_1 */
a32b9810 535 if (reg->U1BC_LEDConfigure & 0x1000) {
e5851c20
LL
536 reg->U1BC_LEDConfigure &= ~0x1000;
537 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
80767e6e
PE
538 }
539 }
a32b9810 540 } else {
e5851c20 541 /* Is transmitting/receiving ?? */
a32b9810
PE
542 if ((adapter->RxByteCount !=
543 pHwData->RxByteCountLast)
544 || (adapter->TxByteCount !=
545 pHwData->TxByteCountLast)) {
546 if ((reg->U1BC_LEDConfigure & 0x3000) !=
547 0x3000) {
e5851c20
LL
548 reg->U1BC_LEDConfigure |= 0x3000;
549 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
80767e6e 550 }
e5851c20 551 /* Update variable */
a32b9810
PE
552 pHwData->RxByteCountLast =
553 adapter->RxByteCount;
554 pHwData->TxByteCountLast =
555 adapter->TxByteCount;
556 TimeInterval = 200;
557 } else {
e5851c20 558 /* Turn On LED_1 and blinking if transmitting/receiving */
a32b9810
PE
559 if ((reg->U1BC_LEDConfigure & 0x3000) !=
560 0x1000) {
561 reg->U1BC_LEDConfigure &=
562 ~0x3000;
563 reg->U1BC_LEDConfigure |=
564 0x1000;
e5851c20 565 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
80767e6e
PE
566 }
567 }
a32b9810
PE
568 }
569 break;
e5851c20 570 default: /* Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active */
a32b9810 571 if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
e5851c20 572 reg->U1BC_LEDConfigure |= 0x3000; /* LED_1 is always on and event enable */
a32b9810
PE
573 Wb35Reg_Write(pHwData, 0x03bc,
574 reg->U1BC_LEDConfigure);
575 }
80767e6e 576
a32b9810 577 if (pHwData->LED_Blinking) {
e5851c20 578 /* Gray blinking */
a32b9810
PE
579 reg->U1BC_LEDConfigure &= ~0x0f;
580 reg->U1BC_LEDConfigure |= 0x10;
581 reg->U1BC_LEDConfigure |=
833d0cd3 582 LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
a32b9810
PE
583 Wb35Reg_Write(pHwData, 0x03bc,
584 reg->U1BC_LEDConfigure);
585
586 pHwData->LED_Blinking += 2;
587 if (pHwData->LED_Blinking < 40)
588 TimeInterval = 100;
589 else {
e5851c20 590 pHwData->LED_Blinking = 0; /* Stop blinking */
80767e6e 591 reg->U1BC_LEDConfigure &= ~0x0f;
a32b9810
PE
592 Wb35Reg_Write(pHwData, 0x03bc,
593 reg->U1BC_LEDConfigure);
80767e6e 594 }
a32b9810
PE
595 break;
596 }
80767e6e 597
a32b9810 598 if (pHwData->LED_LinkOn) {
e5851c20
LL
599 if (!(reg->U1BC_LEDConfigure & 0x10)) { /* Check the LED_0 */
600 /* Try to turn ON LED_0 after gray blinking */
a32b9810 601 reg->U1BC_LEDConfigure |= 0x10;
e5851c20 602 pHwData->LED_Blinking = 1; /* Start blinking */
a32b9810 603 TimeInterval = 50;
80767e6e 604 }
a32b9810 605 } else {
e5851c20 606 if (reg->U1BC_LEDConfigure & 0x10) { /* Check the LED_0 */
a32b9810
PE
607 reg->U1BC_LEDConfigure &= ~0x10;
608 Wb35Reg_Write(pHwData, 0x03bc,
609 reg->U1BC_LEDConfigure);
80767e6e 610 }
a32b9810
PE
611 }
612 break;
80767e6e
PE
613 }
614
e5851c20 615 /* Active send null packet to avoid AP disconnect */
a32b9810 616 if (pHwData->LED_LinkOn) {
80767e6e 617 pHwData->NullPacketCount += TimeInterval;
a32b9810
PE
618 if (pHwData->NullPacketCount >=
619 DEFAULT_NULL_PACKET_COUNT) {
80767e6e
PE
620 pHwData->NullPacketCount = 0;
621 }
622 }
623 }
624
625 pHwData->time_count += TimeInterval;
e5851c20 626 Wb35Tx_CurrentTime(adapter, pHwData->time_count);
80767e6e
PE
627 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
628 add_timer(&pHwData->LEDTimer);
629}
630
cfe31f81 631static int hal_init_hardware(struct ieee80211_hw *hw)
80767e6e
PE
632{
633 struct wbsoft_priv *priv = hw->priv;
a32b9810 634 struct hw_data *pHwData = &priv->sHwData;
80767e6e
PE
635 u16 SoftwareSet;
636
bdbb8839
PE
637 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
638 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
80767e6e 639
00e2e05d 640 if (!Wb35Reg_initial(pHwData))
a39ee671 641 goto error_reg_destroy;
00e2e05d 642
00e2e05d 643 if (!Wb35Tx_initial(pHwData))
a39ee671 644 goto error_tx_destroy;
00e2e05d 645
00e2e05d 646 if (!Wb35Rx_initial(pHwData))
a39ee671 647 goto error_rx_destroy;
00e2e05d 648
00e2e05d
PE
649 init_timer(&pHwData->LEDTimer);
650 pHwData->LEDTimer.function = hal_led_control;
a32b9810 651 pHwData->LEDTimer.data = (unsigned long)priv;
00e2e05d
PE
652 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
653 add_timer(&pHwData->LEDTimer);
654
a32b9810 655 SoftwareSet = hal_software_set(pHwData);
00e2e05d 656
a32b9810 657#ifdef Vendor2
e5851c20 658 /* Try to make sure the EEPROM contain */
00e2e05d 659 SoftwareSet >>= 8;
a32b9810 660 if (SoftwareSet != 0x82)
00e2e05d 661 return false;
a32b9810 662#endif
00e2e05d
PE
663
664 Wb35Rx_start(hw);
665 Wb35Tx_EP2VM_start(priv);
666
667 return 0;
80767e6e 668
a39ee671
PE
669error_rx_destroy:
670 Wb35Rx_destroy(pHwData);
671error_tx_destroy:
672 Wb35Tx_destroy(pHwData);
673error_reg_destroy:
674 Wb35Reg_destroy(pHwData);
675
80767e6e 676 pHwData->SurpriseRemove = 1;
cfe31f81 677 return -EINVAL;
80767e6e
PE
678}
679
26598511 680static int wb35_hw_init(struct ieee80211_hw *hw)
912b209f
PE
681{
682 struct wbsoft_priv *priv = hw->priv;
a32b9810
PE
683 struct hw_data *pHwData = &priv->sHwData;
684 u8 EEPROM_region;
685 u8 HwRadioOff;
686 u8 *pMacAddr2;
687 u8 *pMacAddr;
26598511 688 int err;
912b209f 689
9ca748ce 690 pHwData->phy_type = RF_DECIDE_BY_INF;
912b209f 691
a32b9810
PE
692 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
693 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
694
695 priv->sLocalPara.region_INF = REGION_AUTO;
696 priv->sLocalPara.TxRateMode = RATE_AUTO;
697 priv->sLocalPara.bMacOperationMode = MODE_802_11_BG;
698 priv->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
699 priv->sLocalPara.bPreambleMode = AUTO_MODE;
700 priv->sLocalPara.bWepKeyError = false;
701 priv->sLocalPara.bToSelfPacketReceived = false;
702 priv->sLocalPara.WepKeyDetectTimerCount = 2 * 100; /* 2 seconds */
703
704 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
912b209f 705
cfe31f81
PE
706 err = hal_init_hardware(hw);
707 if (err)
912b209f
PE
708 goto error;
709
a32b9810 710 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
912b209f
PE
711 if (EEPROM_region != REGION_AUTO)
712 priv->sLocalPara.region = EEPROM_region;
713 else {
714 if (priv->sLocalPara.region_INF != REGION_AUTO)
715 priv->sLocalPara.region = priv->sLocalPara.region_INF;
716 else
a32b9810 717 priv->sLocalPara.region = REGION_USA; /* default setting */
912b209f
PE
718 }
719
912b209f
PE
720 Mds_initial(priv);
721
bdbb8839 722 /*
f69b0d64 723 * If no user-defined address in the registry, use the address
bdbb8839
PE
724 * "burned" on the NIC instead.
725 */
912b209f
PE
726 pMacAddr = priv->sLocalPara.ThisMacAddress;
727 pMacAddr2 = priv->sLocalPara.PermanentAddress;
bdbb8839
PE
728
729 /* Reading ethernet address from EEPROM */
a32b9810 730 hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
912b209f
PE
731 if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
732 memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
733 else {
bdbb8839 734 /* Set the user define MAC address */
a32b9810
PE
735 hal_set_ethernet_address(pHwData,
736 priv->sLocalPara.ThisMacAddress);
912b209f
PE
737 }
738
912b209f
PE
739 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
740#ifdef _PE_STATE_DUMP_
0c59dbaa 741 printk("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo);
912b209f 742#endif
a32b9810 743 hal_get_hw_radio_off(pHwData);
912b209f 744
bdbb8839 745 /* Waiting for HAL setting OK */
912b209f
PE
746 while (!hal_idle(pHwData))
747 msleep(10);
748
749 MTO_Init(priv);
750
a32b9810 751 HwRadioOff = hal_get_hw_radio_off(pHwData);
912b209f
PE
752 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
753
a32b9810
PE
754 hal_set_radio_mode(pHwData,
755 (unsigned char)(priv->sLocalPara.RadioOffStatus.
756 boSwRadioOff
757 || priv->sLocalPara.RadioOffStatus.
758 boHwRadioOff));
912b209f 759
bdbb8839
PE
760 /* Notify hal that the driver is ready now. */
761 hal_driver_init_OK(pHwData) = 1;
912b209f
PE
762
763error:
26598511 764 return err;
912b209f
PE
765}
766
a32b9810
PE
767static int wb35_probe(struct usb_interface *intf,
768 const struct usb_device_id *id_table)
66101de1 769{
66101de1 770 struct usb_device *udev = interface_to_usbdev(intf);
a32b9810
PE
771 struct usb_endpoint_descriptor *endpoint;
772 struct usb_host_interface *interface;
1523ddc4 773 struct ieee80211_hw *dev;
a32b9810
PE
774 struct wbsoft_priv *priv;
775 struct wb_usb *pWbUsb;
acfa5110 776 int nr, err;
a32b9810 777 u32 ltmp;
66101de1
PM
778
779 usb_get_dev(udev);
780
bdbb8839 781 /* Check the device if it already be opened */
a32b9810
PE
782 nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
783 0x01,
784 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
785 0x0, 0x400, &ltmp, 4, HZ * 100);
acfa5110
PE
786 if (nr < 0) {
787 err = nr;
dc7e04fe 788 goto error;
acfa5110 789 }
66101de1 790
bdbb8839 791 /* Is already initialized? */
dc7e04fe 792 ltmp = cpu_to_le32(ltmp);
bdbb8839 793 if (ltmp) {
1523ddc4 794 err = -EBUSY;
dc7e04fe 795 goto error;
1523ddc4 796 }
66101de1 797
1e8a2b60 798 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
acfa5110
PE
799 if (!dev) {
800 err = -ENOMEM;
1523ddc4 801 goto error;
acfa5110 802 }
66101de1 803
1e8a2b60 804 priv = dev->priv;
1e8a2b60
PE
805
806 pWbUsb = &priv->sHwData.WbUsb;
dc7e04fe 807 pWbUsb->udev = udev;
66101de1 808
a32b9810
PE
809 interface = intf->cur_altsetting;
810 endpoint = &interface->endpoint[0].desc;
66101de1 811
dc7e04fe
PE
812 if (endpoint[2].wMaxPacketSize == 512) {
813 printk("[w35und] Working on USB 2.0\n");
814 pWbUsb->IsUsb20 = 1;
815 }
66101de1 816
26598511
PE
817 err = wb35_hw_init(dev);
818 if (err)
1e8a2b60 819 goto error_free_hw;
66101de1 820
1523ddc4
PE
821 SET_IEEE80211_DEV(dev, &udev->dev);
822 {
a32b9810
PE
823 struct hw_data *pHwData = &priv->sHwData;
824 unsigned char dev_addr[MAX_ADDR_LEN];
1523ddc4
PE
825 hal_get_permanent_address(pHwData, dev_addr);
826 SET_IEEE80211_PERM_ADDR(dev, dev_addr);
827 }
66101de1 828
1523ddc4 829 dev->extra_tx_headroom = 12; /* FIXME */
05e361ca
PM
830 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
831 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
66101de1 832
1523ddc4 833 dev->channel_change_time = 1000;
05e361ca 834 dev->max_signal = 100;
1523ddc4 835 dev->queues = 1;
dc7e04fe 836
a36e0894 837 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
66101de1 838
1523ddc4
PE
839 err = ieee80211_register_hw(dev);
840 if (err)
841 goto error_free_hw;
66101de1 842
82fbb01c 843 usb_set_intfdata(intf, dev);
66101de1 844
dc7e04fe 845 return 0;
1523ddc4
PE
846
847error_free_hw:
848 ieee80211_free_hw(dev);
dc7e04fe 849error:
4af12e55 850 usb_put_dev(udev);
1523ddc4 851 return err;
66101de1
PM
852}
853
f592a859
PE
854static void hal_halt(struct hw_data *pHwData)
855{
856 del_timer_sync(&pHwData->LEDTimer);
857 /* XXX: Wait for Timer DPC exit. */
858 msleep(100);
859 Wb35Rx_destroy(pHwData);
860 Wb35Tx_destroy(pHwData);
861 Wb35Reg_destroy(pHwData);
862}
863
912b209f
PE
864static void wb35_hw_halt(struct wbsoft_priv *adapter)
865{
a32b9810 866 Mds_Destroy(adapter);
912b209f 867
bdbb8839 868 /* Turn off Rx and Tx hardware ability */
a32b9810 869 hal_stop(&adapter->sHwData);
912b209f 870#ifdef _PE_USB_INI_DUMP_
0c59dbaa 871 printk("[w35und] Hal_stop O.K.\n");
912b209f 872#endif
bdbb8839
PE
873 /* Waiting Irp completed */
874 msleep(100);
912b209f 875
f592a859 876 hal_halt(&adapter->sHwData);
912b209f
PE
877}
878
302bae85 879static void wb35_disconnect(struct usb_interface *intf)
66101de1 880{
82fbb01c
PE
881 struct ieee80211_hw *hw = usb_get_intfdata(intf);
882 struct wbsoft_priv *priv = hw->priv;
66101de1 883
912b209f 884 wb35_hw_halt(priv);
66101de1 885
82fbb01c
PE
886 ieee80211_stop_queues(hw);
887 ieee80211_unregister_hw(hw);
888 ieee80211_free_hw(hw);
889
4af12e55
PE
890 usb_set_intfdata(intf, NULL);
891 usb_put_dev(interface_to_usbdev(intf));
66101de1
PM
892}
893
dd38da46
PE
894static struct usb_driver wb35_driver = {
895 .name = "w35und",
896 .id_table = wb35_table,
897 .probe = wb35_probe,
898 .disconnect = wb35_disconnect,
899};
900
901static int __init wb35_init(void)
902{
903 return usb_register(&wb35_driver);
904}
905
906static void __exit wb35_exit(void)
907{
908 usb_deregister(&wb35_driver);
909}
66101de1 910
dd38da46
PE
911module_init(wb35_init);
912module_exit(wb35_exit);