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