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