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