blob: f1248fb2e4a0a056c2cc7893031a97d3b5a34c16 [file] [log] [blame]
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001/******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3 * Linux device driver for RTL8190P / RTL8192E
4 *
5 * Based on the r8180 driver, which is:
6 * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * The full GNU General Public License is included in this distribution in the
21 * file called LICENSE.
22 *
23 * Contact Information:
24 * Jerry chuang <wlanfae@realtek.com>
25 */
26
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070027
28#undef LOOP_TEST
29#undef RX_DONT_PASS_UL
30#undef DEBUG_EPROM
31#undef DEBUG_RX_VERBOSE
32#undef DUMMY_RX
33#undef DEBUG_ZERO_RX
34#undef DEBUG_RX_SKB
35#undef DEBUG_TX_FRAG
36#undef DEBUG_RX_FRAG
37#undef DEBUG_TX_FILLDESC
38#undef DEBUG_TX
39#undef DEBUG_IRQ
40#undef DEBUG_RX
41#undef DEBUG_RXALLOC
42#undef DEBUG_REGISTERS
43#undef DEBUG_RING
44#undef DEBUG_IRQ_TASKLET
45#undef DEBUG_TX_ALLOC
46#undef DEBUG_TX_DESC
47
48//#define CONFIG_RTL8192_IO_MAP
Jeff Mahoney3d14b512009-10-08 17:30:40 -040049#include <linux/vmalloc.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090050#include <linux/slab.h>
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070051#include <asm/uaccess.h>
52#include "r8192E_hw.h"
53#include "r8192E.h"
54#include "r8190_rtl8256.h" /* RTL8225 Radio frontend */
55#include "r8180_93cx6.h" /* Card EEPROM */
56#include "r8192E_wx.h"
57#include "r819xE_phy.h" //added by WB 4.30.2008
58#include "r819xE_phyreg.h"
59#include "r819xE_cmdpkt.h"
60#include "r8192E_dm.h"
61//#include "r8192xU_phyreg.h"
62//#include <linux/usb.h>
63// FIXME: check if 2.6.7 is ok
64
Yong Wangbebdf802010-04-23 16:26:42 +080065#ifdef CONFIG_PM
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070066#include "r8192_pm.h"
67#endif
68
69#ifdef ENABLE_DOT11D
david woo65a43782009-12-22 09:40:36 -080070#include "ieee80211/dot11d.h"
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070071#endif
72
73//set here to open your trace code. //WB
74u32 rt_global_debug_component = \
75 // COMP_INIT |
76 // COMP_EPROM |
77 // COMP_PHY |
78 // COMP_RF |
david woo65a43782009-12-22 09:40:36 -080079// COMP_FIRMWARE |
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070080 // COMP_TRACE |
81 // COMP_DOWN |
82 // COMP_SWBW |
83 // COMP_SEC |
84// COMP_QOS |
85// COMP_RATE |
86 // COMP_RECV |
87 // COMP_SEND |
88 // COMP_POWER |
89 // COMP_EVENTS |
90 // COMP_RESET |
91 // COMP_CMDPKT |
92 // COMP_POWER_TRACKING |
93 // COMP_INTR |
94 COMP_ERR ; //always open err flags on
95#ifndef PCI_DEVICE
96#define PCI_DEVICE(vend,dev)\
97 .vendor=(vend),.device=(dev),\
98 .subvendor=PCI_ANY_ID,.subdevice=PCI_ANY_ID
99#endif
Mike McCormack881a9752010-07-26 22:58:03 +0900100static const struct pci_device_id rtl8192_pci_id_tbl[] __devinitdata = {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700101#ifdef RTL8190P
102 /* Realtek */
103 /* Dlink */
104 { PCI_DEVICE(0x10ec, 0x8190) },
105 /* Corega */
106 { PCI_DEVICE(0x07aa, 0x0045) },
107 { PCI_DEVICE(0x07aa, 0x0046) },
108#else
109 /* Realtek */
110 { PCI_DEVICE(0x10ec, 0x8192) },
111
112 /* Corega */
113 { PCI_DEVICE(0x07aa, 0x0044) },
114 { PCI_DEVICE(0x07aa, 0x0047) },
115#endif
116 {}
117};
118
119static char* ifname = "wlan%d";
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700120static int hwwep = 1; //default use hw. set 0 to use software security
121static int channels = 0x3fff;
122
123MODULE_LICENSE("GPL");
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700124MODULE_VERSION("V 1.1");
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700125MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl);
126//MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
127MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards");
128
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700129
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700130module_param(ifname, charp, S_IRUGO|S_IWUSR );
131//module_param(hwseqnum,int, S_IRUGO|S_IWUSR);
132module_param(hwwep,int, S_IRUGO|S_IWUSR);
133module_param(channels,int, S_IRUGO|S_IWUSR);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700134
135MODULE_PARM_DESC(ifname," Net interface name, wlan%d=default");
136//MODULE_PARM_DESC(hwseqnum," Try to use hardware 802.11 header sequence numbers. Zero=default");
137MODULE_PARM_DESC(hwwep," Try to use hardware WEP support. Still broken and not available on all cards");
138MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI");
139
140static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
141 const struct pci_device_id *id);
142static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev);
143
144static struct pci_driver rtl8192_pci_driver = {
145 .name = RTL819xE_MODULE_NAME, /* Driver name */
146 .id_table = rtl8192_pci_id_tbl, /* PCI_ID table */
147 .probe = rtl8192_pci_probe, /* probe fn */
148 .remove = __devexit_p(rtl8192_pci_disconnect), /* remove fn */
Yong Wangbebdf802010-04-23 16:26:42 +0800149#ifdef CONFIG_PM
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700150 .suspend = rtl8192E_suspend, /* PM suspend fn */
151 .resume = rtl8192E_resume, /* PM resume fn */
152#else
153 .suspend = NULL, /* PM suspend fn */
154 .resume = NULL, /* PM resume fn */
155#endif
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700156};
157
Mike McCormack559fba52010-07-26 22:57:52 +0900158static void rtl8192_start_beacon(struct net_device *dev);
159static void rtl8192_stop_beacon(struct net_device *dev);
160static void rtl819x_watchdog_wqcallback(struct work_struct *work);
161static void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
162static void rtl8192_irq_tx_tasklet(struct r8192_priv *priv);
163static void rtl8192_prepare_beacon(struct r8192_priv *priv);
164static irqreturn_t rtl8192_interrupt(int irq, void *netdev);
165static void rtl8192_try_wake_queue(struct net_device *dev, int pri);
Mike McCormack881a9752010-07-26 22:58:03 +0900166static void rtl819xE_tx_cmd(struct net_device *dev, struct sk_buff *skb);
Mike McCormack559fba52010-07-26 22:57:52 +0900167
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700168#ifdef ENABLE_DOT11D
169
170typedef struct _CHANNEL_LIST
171{
172 u8 Channel[32];
173 u8 Len;
174}CHANNEL_LIST, *PCHANNEL_LIST;
175
Mike McCormackab2161a2010-07-26 22:57:24 +0900176static const CHANNEL_LIST ChannelPlan[] = {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700177 {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,149,153,157,161,165},24}, //FCC
178 {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC
179 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //ETSI
180 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Spain. Change to ETSI.
181 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //France. Change to ETSI.
182 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, //MKK //MKK
183 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1
184 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Israel.
185 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, // For 11a , TELEC
186 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22}, //MIC
187 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14} //For Global Domain. 1-11:active scan, 12-14 passive scan. //+YJ, 080626
188};
189
190static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv* priv)
191{
192 int i, max_chan=-1, min_chan=-1;
193 struct ieee80211_device* ieee = priv->ieee80211;
194 switch (channel_plan)
195 {
196 case COUNTRY_CODE_FCC:
197 case COUNTRY_CODE_IC:
198 case COUNTRY_CODE_ETSI:
199 case COUNTRY_CODE_SPAIN:
200 case COUNTRY_CODE_FRANCE:
201 case COUNTRY_CODE_MKK:
202 case COUNTRY_CODE_MKK1:
203 case COUNTRY_CODE_ISRAEL:
204 case COUNTRY_CODE_TELEC:
205 case COUNTRY_CODE_MIC:
206 {
207 Dot11d_Init(ieee);
208 ieee->bGlobalDomain = false;
209 //acturally 8225 & 8256 rf chip only support B,G,24N mode
210 if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256))
211 {
212 min_chan = 1;
213 max_chan = 14;
214 }
215 else
216 {
217 RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __FUNCTION__);
218 }
219 if (ChannelPlan[channel_plan].Len != 0){
220 // Clear old channel map
221 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
222 // Set new channel map
223 for (i=0;i<ChannelPlan[channel_plan].Len;i++)
224 {
225 if (ChannelPlan[channel_plan].Channel[i] < min_chan || ChannelPlan[channel_plan].Channel[i] > max_chan)
226 break;
227 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
228 }
229 }
230 break;
231 }
232 case COUNTRY_CODE_GLOBAL_DOMAIN:
233 {
234 GET_DOT11D_INFO(ieee)->bEnabled = 0; //this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain setting
235 Dot11d_Reset(ieee);
236 ieee->bGlobalDomain = true;
237 break;
238 }
239 default:
240 break;
241 }
242}
243#endif
244
245
246#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 )
247/* 2007/07/25 MH Defien temp tx fw info. */
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -0700248static TX_FWINFO_T Tmp_TxFwInfo;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700249
250
251#define rx_hal_is_cck_rate(_pdrvinfo)\
252 (_pdrvinfo->RxRate == DESC90_RATE1M ||\
253 _pdrvinfo->RxRate == DESC90_RATE2M ||\
254 _pdrvinfo->RxRate == DESC90_RATE5_5M ||\
255 _pdrvinfo->RxRate == DESC90_RATE11M) &&\
256 !_pdrvinfo->RxHT\
257
258
259void CamResetAllEntry(struct net_device *dev)
260{
261 //u8 ucIndex;
262 u32 ulcommand = 0;
263
264#if 1
265 ulcommand |= BIT31|BIT30;
266 write_nic_dword(dev, RWCAM, ulcommand);
267#else
268 for(ucIndex=0;ucIndex<TOTAL_CAM_ENTRY;ucIndex++)
269 CAM_mark_invalid(dev, ucIndex);
270 for(ucIndex=0;ucIndex<TOTAL_CAM_ENTRY;ucIndex++)
271 CAM_empty_entry(dev, ucIndex);
272#endif
273}
274
275
276void write_cam(struct net_device *dev, u8 addr, u32 data)
277{
278 write_nic_dword(dev, WCAMI, data);
279 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff) );
280}
281u32 read_cam(struct net_device *dev, u8 addr)
282{
283 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff) );
284 return read_nic_dword(dev, 0xa8);
285}
286
287////////////////////////////////////////////////////////////
288#ifdef CONFIG_RTL8180_IO_MAP
289
290u8 read_nic_byte(struct net_device *dev, int x)
291{
292 return 0xff&inb(dev->base_addr +x);
293}
294
295u32 read_nic_dword(struct net_device *dev, int x)
296{
297 return inl(dev->base_addr +x);
298}
299
300u16 read_nic_word(struct net_device *dev, int x)
301{
302 return inw(dev->base_addr +x);
303}
304
305void write_nic_byte(struct net_device *dev, int x,u8 y)
306{
307 outb(y&0xff,dev->base_addr +x);
308}
309
310void write_nic_word(struct net_device *dev, int x,u16 y)
311{
312 outw(y,dev->base_addr +x);
313}
314
315void write_nic_dword(struct net_device *dev, int x,u32 y)
316{
317 outl(y,dev->base_addr +x);
318}
319
320#else /* RTL_IO_MAP */
321
322u8 read_nic_byte(struct net_device *dev, int x)
323{
324 return 0xff&readb((u8*)dev->mem_start +x);
325}
326
327u32 read_nic_dword(struct net_device *dev, int x)
328{
329 return readl((u8*)dev->mem_start +x);
330}
331
332u16 read_nic_word(struct net_device *dev, int x)
333{
334 return readw((u8*)dev->mem_start +x);
335}
336
337void write_nic_byte(struct net_device *dev, int x,u8 y)
338{
339 writeb(y,(u8*)dev->mem_start +x);
340 udelay(20);
341}
342
343void write_nic_dword(struct net_device *dev, int x,u32 y)
344{
345 writel(y,(u8*)dev->mem_start +x);
346 udelay(20);
347}
348
349void write_nic_word(struct net_device *dev, int x,u16 y)
350{
351 writew(y,(u8*)dev->mem_start +x);
352 udelay(20);
353}
354
355#endif /* RTL_IO_MAP */
356
david woo65a43782009-12-22 09:40:36 -0800357u8 rtl8192e_ap_sec_type(struct ieee80211_device *ieee)
358{
359 //struct r8192_priv* priv = ieee80211_priv(dev);
360 //struct ieee80211_device *ieee = priv->ieee80211;
361
Mike McCormack4a533362010-07-26 22:57:35 +0900362 static const u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
363 static const u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
david woo65a43782009-12-22 09:40:36 -0800364 int wpa_ie_len= ieee->wpa_ie_len;
365 struct ieee80211_crypt_data* crypt;
366 int encrypt;
367
368 crypt = ieee->crypt[ieee->tx_keyidx];
369
370 encrypt = (ieee->current_network.capability & WLAN_CAPABILITY_PRIVACY) ||\
371 (ieee->host_encrypt && crypt && crypt->ops && \
372 (0 == strcmp(crypt->ops->name,"WEP")));
373
374 /* simply judge */
375 if(encrypt && (wpa_ie_len == 0)) {
376 // wep encryption, no N mode setting */
377 return SEC_ALG_WEP;
378 } else if((wpa_ie_len != 0)) {
379 // parse pairwise key type */
380 if (((ieee->wpa_ie[0] == 0xdd) && (!memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) ||
381 ((ieee->wpa_ie[0] == 0x30) && (!memcmp(&ieee->wpa_ie[10],ccmp_rsn_ie, 4))))
382 return SEC_ALG_CCMP;
383 else
384 return SEC_ALG_TKIP;
385 } else {
386 return SEC_ALG_NONE;
387 }
388}
389
390void
391rtl8192e_SetHwReg(struct net_device *dev,u8 variable,u8* val)
392{
393 struct r8192_priv* priv = ieee80211_priv(dev);
394
395 switch(variable)
396 {
397
398 case HW_VAR_BSSID:
399 write_nic_dword(dev, BSSIDR, ((u32*)(val))[0]);
400 write_nic_word(dev, BSSIDR+2, ((u16*)(val+2))[0]);
401 break;
402
403 case HW_VAR_MEDIA_STATUS:
404 {
405 RT_OP_MODE OpMode = *((RT_OP_MODE *)(val));
406 //LED_CTL_MODE LedAction = LED_CTL_NO_LINK;
407 u8 btMsr = read_nic_byte(dev, MSR);
408
409 btMsr &= 0xfc;
410
411 switch(OpMode)
412 {
413 case RT_OP_MODE_INFRASTRUCTURE:
414 btMsr |= MSR_INFRA;
415 //LedAction = LED_CTL_LINK;
416 break;
417
418 case RT_OP_MODE_IBSS:
419 btMsr |= MSR_ADHOC;
Anand Gadiyar935e99f2010-05-12 13:03:13 +0530420 // led link set separate
david woo65a43782009-12-22 09:40:36 -0800421 break;
422
423 case RT_OP_MODE_AP:
424 btMsr |= MSR_AP;
425 //LedAction = LED_CTL_LINK;
426 break;
427
428 default:
429 btMsr |= MSR_NOLINK;
430 break;
431 }
432
433 write_nic_byte(dev, MSR, btMsr);
434
435 //priv->ieee80211->LedControlHandler(dev, LedAction);
436 }
437 break;
438
439 case HW_VAR_CECHK_BSSID:
440 {
441 u32 RegRCR, Type;
442
443 Type = ((u8*)(val))[0];
444 //priv->ieee80211->GetHwRegHandler(dev, HW_VAR_RCR, (u8*)(&RegRCR));
445 RegRCR = read_nic_dword(dev,RCR);
446 priv->ReceiveConfig = RegRCR;
447
448 if (Type == true)
449 RegRCR |= (RCR_CBSSID);
450 else if (Type == false)
451 RegRCR &= (~RCR_CBSSID);
452
453 //priv->ieee80211->SetHwRegHandler( dev, HW_VAR_RCR, (u8*)(&RegRCR) );
454 write_nic_dword(dev, RCR,RegRCR);
455 priv->ReceiveConfig = RegRCR;
456
457 }
458 break;
459
460 case HW_VAR_SLOT_TIME:
461 {
462 //PSTA_QOS pStaQos = Adapter->MgntInfo.pStaQos;
463 //AC_CODING eACI;
464
465 priv->slot_time = val[0];
466 write_nic_byte(dev, SLOT_TIME, val[0]);
467
468 }
469 break;
470
471 case HW_VAR_ACK_PREAMBLE:
472 {
473 u32 regTmp = 0;
474 priv->short_preamble = (bool)(*(u8*)val );
475 regTmp = priv->basic_rate;
476 if (priv->short_preamble)
477 regTmp |= BRSR_AckShortPmb;
478 write_nic_dword(dev, RRSR, regTmp);
479 }
480 break;
481
482 case HW_VAR_CPU_RST:
483 write_nic_dword(dev, CPU_GEN, ((u32*)(val))[0]);
484 break;
485
486 default:
487 break;
488 }
489
490}
491
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700492
493///////////////////////////////////////////////////////////
494
495//u8 read_phy_cck(struct net_device *dev, u8 adr);
496//u8 read_phy_ofdm(struct net_device *dev, u8 adr);
497/* this might still called in what was the PHY rtl8185/rtl8192 common code
498 * plans are to possibilty turn it again in one common code...
499 */
Mike McCormack559fba52010-07-26 22:57:52 +0900500void force_pci_posting(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700501{
502}
503
504
505//warning message WB
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700506//static struct net_device_stats *rtl8192_stats(struct net_device *dev);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700507//void rtl8192_restart(struct net_device *dev);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700508void rtl8192_restart(struct work_struct *work);
509//void rtl8192_rq_tx_ack(struct work_struct *work);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700510
511void watch_dog_timer_callback(unsigned long data);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700512/****************************************************************************
513 -----------------------------PROCFS STUFF-------------------------
514*****************************************************************************/
515
516static struct proc_dir_entry *rtl8192_proc = NULL;
517
518
519
520static int proc_get_stats_ap(char *page, char **start,
521 off_t offset, int count,
522 int *eof, void *data)
523{
524 struct net_device *dev = data;
525 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
526 struct ieee80211_device *ieee = priv->ieee80211;
527 struct ieee80211_network *target;
528
529 int len = 0;
530
531 list_for_each_entry(target, &ieee->network_list, list) {
532
533 len += snprintf(page + len, count - len,
534 "%s ", target->ssid);
535
536 if(target->wpa_ie_len>0 || target->rsn_ie_len>0){
537 len += snprintf(page + len, count - len,
538 "WPA\n");
539 }
540 else{
541 len += snprintf(page + len, count - len,
542 "non_WPA\n");
543 }
544
545 }
546
547 *eof = 1;
548 return len;
549}
550
551static int proc_get_registers(char *page, char **start,
552 off_t offset, int count,
553 int *eof, void *data)
554{
555 struct net_device *dev = data;
556// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
557
558 int len = 0;
559 int i,n;
560
561 int max=0xff;
562
563 /* This dump the current register page */
564 len += snprintf(page + len, count - len,
565 "\n####################page 0##################\n ");
566
567 for(n=0;n<=max;)
568 {
569 //printk( "\nD: %2x> ", n);
570 len += snprintf(page + len, count - len,
571 "\nD: %2x > ",n);
572
573 for(i=0;i<16 && n<=max;i++,n++)
574 len += snprintf(page + len, count - len,
575 "%2x ",read_nic_byte(dev,n));
576
577 // printk("%2x ",read_nic_byte(dev,n));
578 }
579 len += snprintf(page + len, count - len,"\n");
580 len += snprintf(page + len, count - len,
581 "\n####################page 1##################\n ");
582 for(n=0;n<=max;)
583 {
584 //printk( "\nD: %2x> ", n);
585 len += snprintf(page + len, count - len,
586 "\nD: %2x > ",n);
587
588 for(i=0;i<16 && n<=max;i++,n++)
589 len += snprintf(page + len, count - len,
590 "%2x ",read_nic_byte(dev,0x100|n));
591
592 // printk("%2x ",read_nic_byte(dev,n));
593 }
594
595 len += snprintf(page + len, count - len,
596 "\n####################page 3##################\n ");
597 for(n=0;n<=max;)
598 {
599 //printk( "\nD: %2x> ", n);
600 len += snprintf(page + len, count - len,
601 "\nD: %2x > ",n);
602
603 for(i=0;i<16 && n<=max;i++,n++)
604 len += snprintf(page + len, count - len,
605 "%2x ",read_nic_byte(dev,0x300|n));
606
607 // printk("%2x ",read_nic_byte(dev,n));
608 }
609
610
611 *eof = 1;
612 return len;
613
614}
615
616
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700617
618static int proc_get_stats_tx(char *page, char **start,
619 off_t offset, int count,
620 int *eof, void *data)
621{
622 struct net_device *dev = data;
623 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
624
625 int len = 0;
626
627 len += snprintf(page + len, count - len,
628 "TX VI priority ok int: %lu\n"
629// "TX VI priority error int: %lu\n"
630 "TX VO priority ok int: %lu\n"
631// "TX VO priority error int: %lu\n"
632 "TX BE priority ok int: %lu\n"
633// "TX BE priority error int: %lu\n"
634 "TX BK priority ok int: %lu\n"
635// "TX BK priority error int: %lu\n"
636 "TX MANAGE priority ok int: %lu\n"
637// "TX MANAGE priority error int: %lu\n"
638 "TX BEACON priority ok int: %lu\n"
639 "TX BEACON priority error int: %lu\n"
640 "TX CMDPKT priority ok int: %lu\n"
641// "TX high priority ok int: %lu\n"
642// "TX high priority failed error int: %lu\n"
643// "TX queue resume: %lu\n"
644 "TX queue stopped?: %d\n"
645 "TX fifo overflow: %lu\n"
646// "TX beacon: %lu\n"
647// "TX VI queue: %d\n"
648// "TX VO queue: %d\n"
649// "TX BE queue: %d\n"
650// "TX BK queue: %d\n"
651// "TX HW queue: %d\n"
652// "TX VI dropped: %lu\n"
653// "TX VO dropped: %lu\n"
654// "TX BE dropped: %lu\n"
655// "TX BK dropped: %lu\n"
656 "TX total data packets %lu\n"
657 "TX total data bytes :%lu\n",
658// "TX beacon aborted: %lu\n",
659 priv->stats.txviokint,
660// priv->stats.txvierr,
661 priv->stats.txvookint,
662// priv->stats.txvoerr,
663 priv->stats.txbeokint,
664// priv->stats.txbeerr,
665 priv->stats.txbkokint,
666// priv->stats.txbkerr,
667 priv->stats.txmanageokint,
668// priv->stats.txmanageerr,
669 priv->stats.txbeaconokint,
670 priv->stats.txbeaconerr,
671 priv->stats.txcmdpktokint,
672// priv->stats.txhpokint,
673// priv->stats.txhperr,
674// priv->stats.txresumed,
675 netif_queue_stopped(dev),
676 priv->stats.txoverflow,
677// priv->stats.txbeacon,
678// atomic_read(&(priv->tx_pending[VI_QUEUE])),
679// atomic_read(&(priv->tx_pending[VO_QUEUE])),
680// atomic_read(&(priv->tx_pending[BE_QUEUE])),
681// atomic_read(&(priv->tx_pending[BK_QUEUE])),
682// read_nic_byte(dev, TXFIFOCOUNT),
683// priv->stats.txvidrop,
684// priv->stats.txvodrop,
685 priv->ieee80211->stats.tx_packets,
686 priv->ieee80211->stats.tx_bytes
687
688
689// priv->stats.txbedrop,
690// priv->stats.txbkdrop
691 // priv->stats.txdatapkt
692// priv->stats.txbeaconerr
693 );
694
695 *eof = 1;
696 return len;
697}
698
699
700
701static int proc_get_stats_rx(char *page, char **start,
702 off_t offset, int count,
703 int *eof, void *data)
704{
705 struct net_device *dev = data;
706 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
707
708 int len = 0;
709
710 len += snprintf(page + len, count - len,
711 "RX packets: %lu\n"
712 "RX desc err: %lu\n"
713 "RX rx overflow error: %lu\n"
714 "RX invalid urb error: %lu\n",
715 priv->stats.rxint,
716 priv->stats.rxrdu,
717 priv->stats.rxoverflow,
718 priv->stats.rxurberr);
719
720 *eof = 1;
721 return len;
722}
723
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -0700724static void rtl8192_proc_module_init(void)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700725{
726 RT_TRACE(COMP_INIT, "Initializing proc filesystem");
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700727 rtl8192_proc=create_proc_entry(RTL819xE_MODULE_NAME, S_IFDIR, init_net.proc_net);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700728}
729
730
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -0700731static void rtl8192_proc_module_remove(void)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700732{
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700733 remove_proc_entry(RTL819xE_MODULE_NAME, init_net.proc_net);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700734}
735
736
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -0700737static void rtl8192_proc_remove_one(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700738{
739 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
740
741 printk("dev name=======> %s\n",dev->name);
742
743 if (priv->dir_dev) {
744 // remove_proc_entry("stats-hw", priv->dir_dev);
745 remove_proc_entry("stats-tx", priv->dir_dev);
746 remove_proc_entry("stats-rx", priv->dir_dev);
747 // remove_proc_entry("stats-ieee", priv->dir_dev);
748 remove_proc_entry("stats-ap", priv->dir_dev);
749 remove_proc_entry("registers", priv->dir_dev);
750 // remove_proc_entry("cck-registers",priv->dir_dev);
751 // remove_proc_entry("ofdm-registers",priv->dir_dev);
752 //remove_proc_entry(dev->name, rtl8192_proc);
753 remove_proc_entry("wlan0", rtl8192_proc);
754 priv->dir_dev = NULL;
755 }
756}
757
758
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -0700759static void rtl8192_proc_init_one(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700760{
761 struct proc_dir_entry *e;
762 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
763 priv->dir_dev = create_proc_entry(dev->name,
764 S_IFDIR | S_IRUGO | S_IXUGO,
765 rtl8192_proc);
766 if (!priv->dir_dev) {
767 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
768 dev->name);
769 return;
770 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700771 e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
772 priv->dir_dev, proc_get_stats_rx, dev);
773
774 if (!e) {
775 RT_TRACE(COMP_ERR,"Unable to initialize "
776 "/proc/net/rtl8192/%s/stats-rx\n",
777 dev->name);
778 }
779
780
781 e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
782 priv->dir_dev, proc_get_stats_tx, dev);
783
784 if (!e) {
785 RT_TRACE(COMP_ERR, "Unable to initialize "
786 "/proc/net/rtl8192/%s/stats-tx\n",
787 dev->name);
788 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700789
790 e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO,
791 priv->dir_dev, proc_get_stats_ap, dev);
792
793 if (!e) {
794 RT_TRACE(COMP_ERR, "Unable to initialize "
795 "/proc/net/rtl8192/%s/stats-ap\n",
796 dev->name);
797 }
798
799 e = create_proc_read_entry("registers", S_IFREG | S_IRUGO,
800 priv->dir_dev, proc_get_registers, dev);
801 if (!e) {
802 RT_TRACE(COMP_ERR, "Unable to initialize "
803 "/proc/net/rtl8192/%s/registers\n",
804 dev->name);
805 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700806}
807/****************************************************************************
808 -----------------------------MISC STUFF-------------------------
809*****************************************************************************/
810
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700811short check_nic_enough_desc(struct net_device *dev, int prio)
812{
813 struct r8192_priv *priv = ieee80211_priv(dev);
814 struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
815
816 /* for now we reserve two free descriptor as a safety boundary
817 * between the tail and the head
818 */
819 if (ring->entries - skb_queue_len(&ring->queue) >= 2) {
820 return 1;
821 } else {
822 return 0;
823 }
824}
825
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -0700826static void tx_timeout(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700827{
828 struct r8192_priv *priv = ieee80211_priv(dev);
829 //rtl8192_commit(dev);
830
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700831 schedule_work(&priv->reset_wq);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700832 printk("TXTIMEOUT");
833}
834
835
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700836/****************************************************************************
837 ------------------------------HW STUFF---------------------------
838*****************************************************************************/
839
840
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -0700841static void rtl8192_irq_enable(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700842{
843 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
844 priv->irq_enabled = 1;
845 write_nic_dword(dev,INTA_MASK, priv->irq_mask);
846}
847
848
david woo65a43782009-12-22 09:40:36 -0800849void rtl8192_irq_disable(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700850{
851 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
852
853 write_nic_dword(dev,INTA_MASK,0);
854 force_pci_posting(dev);
855 priv->irq_enabled = 0;
856}
857
858
david woo65a43782009-12-22 09:40:36 -0800859#if 0
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -0700860static void rtl8192_set_mode(struct net_device *dev,int mode)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700861{
862 u8 ecmd;
863 ecmd=read_nic_byte(dev, EPROM_CMD);
864 ecmd=ecmd &~ EPROM_CMD_OPERATING_MODE_MASK;
865 ecmd=ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
866 ecmd=ecmd &~ (1<<EPROM_CS_SHIFT);
867 ecmd=ecmd &~ (1<<EPROM_CK_SHIFT);
868 write_nic_byte(dev, EPROM_CMD, ecmd);
869}
david woo65a43782009-12-22 09:40:36 -0800870#endif
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700871
872void rtl8192_update_msr(struct net_device *dev)
873{
874 struct r8192_priv *priv = ieee80211_priv(dev);
875 u8 msr;
876
877 msr = read_nic_byte(dev, MSR);
878 msr &= ~ MSR_LINK_MASK;
879
880 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
881 * msr must be updated if the state is ASSOCIATING.
882 * this is intentional and make sense for ad-hoc and
883 * master (see the create BSS/IBSS func)
884 */
885 if (priv->ieee80211->state == IEEE80211_LINKED){
886
887 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
888 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
889 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
890 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
891 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
892 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
893
894 }else
895 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
896
897 write_nic_byte(dev, MSR, msr);
898}
899
900void rtl8192_set_chan(struct net_device *dev,short ch)
901{
902 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
903 RT_TRACE(COMP_RF, "=====>%s()====ch:%d\n", __FUNCTION__, ch);
904 priv->chan=ch;
905#if 0
906 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC ||
907 priv->ieee80211->iw_mode == IW_MODE_MASTER){
908
909 priv->ieee80211->link_state = WLAN_LINK_ASSOCIATED;
910 priv->ieee80211->master_chan = ch;
911 rtl8192_update_beacon_ch(dev);
912 }
913#endif
914
915 /* this hack should avoid frame TX during channel setting*/
916
917
918 // tx = read_nic_dword(dev,TX_CONF);
919 // tx &= ~TX_LOOPBACK_MASK;
920
921#ifndef LOOP_TEST
922 //TODO
923 // write_nic_dword(dev,TX_CONF, tx |( TX_LOOPBACK_MAC<<TX_LOOPBACK_SHIFT));
924
925 //need to implement rf set channel here WB
926
927 if (priv->rf_set_chan)
928 priv->rf_set_chan(dev,priv->chan);
929 // mdelay(10);
930 // write_nic_dword(dev,TX_CONF,tx | (TX_LOOPBACK_NONE<<TX_LOOPBACK_SHIFT));
931#endif
932}
933
934void rtl8192_rx_enable(struct net_device *dev)
935{
936 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
937 write_nic_dword(dev, RDQDA,priv->rx_ring_dma);
938}
939
940/* the TX_DESC_BASE setting is according to the following queue index
941 * BK_QUEUE ===> 0
942 * BE_QUEUE ===> 1
943 * VI_QUEUE ===> 2
944 * VO_QUEUE ===> 3
945 * HCCA_QUEUE ===> 4
946 * TXCMD_QUEUE ===> 5
947 * MGNT_QUEUE ===> 6
948 * HIGH_QUEUE ===> 7
949 * BEACON_QUEUE ===> 8
950 * */
Mike McCormack881a9752010-07-26 22:58:03 +0900951static const u32 TX_DESC_BASE[] = {BKQDA, BEQDA, VIQDA, VOQDA, HCCAQDA, CQDA, MQDA, HQDA, BQDA};
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700952void rtl8192_tx_enable(struct net_device *dev)
953{
954 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
955 u32 i;
956 for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
957 write_nic_dword(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma);
958
959 ieee80211_reset_queue(priv->ieee80211);
960}
961
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700962
963static void rtl8192_free_rx_ring(struct net_device *dev)
964{
965 struct r8192_priv *priv = ieee80211_priv(dev);
966 int i;
967
968 for (i = 0; i < priv->rxringcount; i++) {
969 struct sk_buff *skb = priv->rx_buf[i];
970 if (!skb)
971 continue;
972
973 pci_unmap_single(priv->pdev,
974 *((dma_addr_t *)skb->cb),
975 priv->rxbuffersize, PCI_DMA_FROMDEVICE);
976 kfree_skb(skb);
977 }
978
979 pci_free_consistent(priv->pdev, sizeof(*priv->rx_ring) * priv->rxringcount,
980 priv->rx_ring, priv->rx_ring_dma);
981 priv->rx_ring = NULL;
982}
983
984static void rtl8192_free_tx_ring(struct net_device *dev, unsigned int prio)
985{
986 struct r8192_priv *priv = ieee80211_priv(dev);
987 struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
988
989 while (skb_queue_len(&ring->queue)) {
990 tx_desc_819x_pci *entry = &ring->desc[ring->idx];
991 struct sk_buff *skb = __skb_dequeue(&ring->queue);
992
993 pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr),
994 skb->len, PCI_DMA_TODEVICE);
995 kfree_skb(skb);
996 ring->idx = (ring->idx + 1) % ring->entries;
997 }
998
999 pci_free_consistent(priv->pdev, sizeof(*ring->desc)*ring->entries,
1000 ring->desc, ring->dma);
1001 ring->desc = NULL;
1002}
1003
david woo65a43782009-12-22 09:40:36 -08001004#if 0
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001005static void rtl8192_beacon_disable(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001006{
1007 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1008 u32 reg;
1009
1010 reg = read_nic_dword(priv->ieee80211->dev,INTA_MASK);
1011
1012 /* disable Beacon realted interrupt signal */
1013 reg &= ~(IMR_BcnInt | IMR_BcnInt | IMR_TBDOK | IMR_TBDER);
1014 write_nic_dword(priv->ieee80211->dev, INTA_MASK, reg);
1015}
david woo65a43782009-12-22 09:40:36 -08001016#endif
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001017
david woo65a43782009-12-22 09:40:36 -08001018void PHY_SetRtl8192eRfOff(struct net_device* dev )
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001019{
david woo65a43782009-12-22 09:40:36 -08001020 //struct r8192_priv *priv = ieee80211_priv(dev);
1021
1022 //disable RF-Chip A/B
1023 rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
1024 //analog to digital off, for power save
1025 rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0);
1026 //digital to analog off, for power save
1027 rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0);
1028 //rx antenna off
1029 rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);
1030 //rx antenna off
1031 rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);
1032 //analog to digital part2 off, for power save
1033 rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);
1034 rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0);
1035 // Analog parameter!!Change bias and Lbus control.
1036 write_nic_byte(dev, ANAPAR_FOR_8192PciE, 0x07);
1037
1038}
1039
1040void rtl8192_halt_adapter(struct net_device *dev, bool reset)
1041{
1042 //u8 cmd;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001043 struct r8192_priv *priv = ieee80211_priv(dev);
david woo65a43782009-12-22 09:40:36 -08001044 int i;
1045 u8 OpMode;
1046 u8 u1bTmp;
1047 u32 ulRegRead;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001048
david woo65a43782009-12-22 09:40:36 -08001049 OpMode = RT_OP_MODE_NO_LINK;
1050 priv->ieee80211->SetHwRegHandler(dev, HW_VAR_MEDIA_STATUS, &OpMode);
1051
1052#if 1
1053 if(!priv->ieee80211->bSupportRemoteWakeUp)
1054 {
1055 u1bTmp = 0x0; // disable tx/rx. In 8185 we write 0x10 (Reset bit), but here we make reference to WMAC and wirte 0x0. 2006.11.21 Emily
1056 //priv->ieee80211->SetHwRegHandler(dev, HW_VAR_COMMAND, &u1bTmp ); // Using HW_VAR_COMMAND instead of writing CMDR directly. Rewrited by Annie, 2006-04-07.
1057 write_nic_byte(dev, CMDR, u1bTmp);
1058 }
1059#else
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001060 cmd=read_nic_byte(dev,CMDR);
david woo65a43782009-12-22 09:40:36 -08001061 write_nic_byte(dev, CMDR, cmd &~ (CR_TE|CR_RE));
1062#endif
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001063
david woo65a43782009-12-22 09:40:36 -08001064 mdelay(20);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001065
david woo65a43782009-12-22 09:40:36 -08001066 if(!reset)
1067 {
1068 //PlatformStallExecution(150000);
1069 mdelay(150);
1070
1071#ifdef RTL8192E
1072 priv->bHwRfOffAction = 2;
1073#endif
1074
1075 //
1076 // Call MgntActSet_RF_State instead to prevent RF config race condition.
1077 // By Bruce, 2008-01-17.
1078 //
1079 if(!priv->ieee80211->bSupportRemoteWakeUp)
1080 {
1081 //MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_INIT);
1082 //MgntActSet_RF_State(Adapter, eRfOff, Adapter->MgntInfo.RfOffReason);
1083 //if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
1084
1085 PHY_SetRtl8192eRfOff(dev);
1086
1087 // 2006.11.30. System reset bit
1088 //priv->ieee80211->GetHwRegHandler(dev, HW_VAR_CPU_RST, (u32*)(&ulRegRead) );
1089 ulRegRead = read_nic_dword(dev,CPU_GEN);
1090 ulRegRead|=CPU_GEN_SYSTEM_RESET;
1091 //priv->ieee80211->SetHwRegHandler(dev, HW_VAR_CPU_RST, &ulRegRead);
1092 write_nic_dword(dev,CPU_GEN, ulRegRead);
1093 }
1094 else
1095 {
1096 //2008.06.03 for WOL
1097 write_nic_dword(dev, WFCRC0, 0xffffffff);
1098 write_nic_dword(dev, WFCRC1, 0xffffffff);
1099 write_nic_dword(dev, WFCRC2, 0xffffffff);
1100
1101 //Write PMR register
1102 write_nic_byte(dev, PMR, 0x5);
1103 //Disable tx, enanble rx
1104 write_nic_byte(dev, MacBlkCtrl, 0xa);
1105 }
1106 }
1107
1108 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
1109 skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
1110 }
1111 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
1112 skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
1113 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001114
1115 skb_queue_purge(&priv->skb_queue);
1116 return;
1117}
1118
david woo65a43782009-12-22 09:40:36 -08001119#if 0
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001120static void rtl8192_reset(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001121{
1122 rtl8192_irq_disable(dev);
1123 printk("This is RTL819xP Reset procedure\n");
1124}
david woo65a43782009-12-22 09:40:36 -08001125#endif
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001126
Mike McCormack881a9752010-07-26 22:58:03 +09001127static const u16 rtl_rate[] = {10,20,55,110,60,90,120,180,240,360,480,540};
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001128inline u16 rtl8192_rate2rate(short rate)
1129{
1130 if (rate >11) return 0;
1131 return rtl_rate[rate];
1132}
1133
1134
1135
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001136
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001137static void rtl8192_data_hard_stop(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001138{
1139 //FIXME !!
1140 #if 0
1141 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1142 priv->dma_poll_mask |= (1<<TX_DMA_STOP_LOWPRIORITY_SHIFT);
1143 rtl8192_set_mode(dev,EPROM_CMD_CONFIG);
1144 write_nic_byte(dev,TX_DMA_POLLING,priv->dma_poll_mask);
1145 rtl8192_set_mode(dev,EPROM_CMD_NORMAL);
1146 #endif
1147}
1148
1149
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001150static void rtl8192_data_hard_resume(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001151{
1152 // FIXME !!
1153 #if 0
1154 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1155 priv->dma_poll_mask &= ~(1<<TX_DMA_STOP_LOWPRIORITY_SHIFT);
1156 rtl8192_set_mode(dev,EPROM_CMD_CONFIG);
1157 write_nic_byte(dev,TX_DMA_POLLING,priv->dma_poll_mask);
1158 rtl8192_set_mode(dev,EPROM_CMD_NORMAL);
1159 #endif
1160}
1161
1162/* this function TX data frames when the ieee80211 stack requires this.
1163 * It checks also if we need to stop the ieee tx queue, eventually do it
1164 */
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001165static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001166{
1167 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1168 int ret;
1169 //unsigned long flags;
1170 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1171 u8 queue_index = tcb_desc->queue_index;
1172 /* shall not be referred by command packet */
1173 assert(queue_index != TXCMD_QUEUE);
1174
david woo65a43782009-12-22 09:40:36 -08001175 if((priv->bHwRadioOff == true)||(!priv->up))
1176 {
1177 kfree_skb(skb);
1178 return;
1179 }
1180
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001181 //spin_lock_irqsave(&priv->tx_lock,flags);
1182
1183 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
1184#if 0
1185 tcb_desc->RATRIndex = 7;
1186 tcb_desc->bTxDisableRateFallBack = 1;
1187 tcb_desc->bTxUseDriverAssingedRate = 1;
1188 tcb_desc->bTxEnableFwCalcDur = 1;
1189#endif
1190 skb_push(skb, priv->ieee80211->tx_headroom);
1191 ret = rtl8192_tx(dev, skb);
1192 if(ret != 0) {
1193 kfree_skb(skb);
1194 };
1195
1196//
1197 if(queue_index!=MGNT_QUEUE) {
1198 priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom);
1199 priv->ieee80211->stats.tx_packets++;
1200 }
1201
1202 //spin_unlock_irqrestore(&priv->tx_lock,flags);
1203
1204// return ret;
1205 return;
1206}
1207
1208/* This is a rough attempt to TX a frame
1209 * This is called by the ieee 80211 stack to TX management frames.
1210 * If the ring is full packet are dropped (for data frame the queue
1211 * is stopped before this can happen).
1212 */
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001213static int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001214{
1215 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1216
1217
1218 int ret;
1219 //unsigned long flags;
1220 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1221 u8 queue_index = tcb_desc->queue_index;
1222
david woo65a43782009-12-22 09:40:36 -08001223 if(queue_index != TXCMD_QUEUE){
1224 if((priv->bHwRadioOff == true)||(!priv->up))
1225 {
1226 kfree_skb(skb);
1227 return 0;
1228 }
1229 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001230
1231 //spin_lock_irqsave(&priv->tx_lock,flags);
1232
1233 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
1234 if(queue_index == TXCMD_QUEUE) {
1235 // skb_push(skb, USB_HWDESC_HEADER_LEN);
1236 rtl819xE_tx_cmd(dev, skb);
1237 ret = 0;
1238 //spin_unlock_irqrestore(&priv->tx_lock,flags);
1239 return ret;
1240 } else {
1241 // RT_TRACE(COMP_SEND, "To send management packet\n");
1242 tcb_desc->RATRIndex = 7;
1243 tcb_desc->bTxDisableRateFallBack = 1;
1244 tcb_desc->bTxUseDriverAssingedRate = 1;
1245 tcb_desc->bTxEnableFwCalcDur = 1;
1246 skb_push(skb, priv->ieee80211->tx_headroom);
1247 ret = rtl8192_tx(dev, skb);
1248 if(ret != 0) {
1249 kfree_skb(skb);
1250 };
1251 }
1252
1253// priv->ieee80211->stats.tx_bytes+=skb->len;
1254// priv->ieee80211->stats.tx_packets++;
1255
1256 //spin_unlock_irqrestore(&priv->tx_lock,flags);
1257
1258 return ret;
1259
1260}
1261
1262
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001263static void rtl8192_tx_isr(struct net_device *dev, int prio)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001264{
1265 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1266
1267 struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
1268
1269 while (skb_queue_len(&ring->queue)) {
1270 tx_desc_819x_pci *entry = &ring->desc[ring->idx];
1271 struct sk_buff *skb;
1272
André Goddard Rosabbc9a992009-11-14 13:09:06 -02001273 /* beacon packet will only use the first descriptor defaultly,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001274 * and the OWN may not be cleared by the hardware
1275 * */
1276 if(prio != BEACON_QUEUE) {
1277 if(entry->OWN)
1278 return;
1279 ring->idx = (ring->idx + 1) % ring->entries;
1280 }
1281
1282 skb = __skb_dequeue(&ring->queue);
1283 pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr),
1284 skb->len, PCI_DMA_TODEVICE);
1285
1286 kfree_skb(skb);
1287 }
1288 if (prio == MGNT_QUEUE){
1289 if (priv->ieee80211->ack_tx_to_ieee){
1290 if (rtl8192_is_tx_queue_empty(dev)){
1291 priv->ieee80211->ack_tx_to_ieee = 0;
1292 ieee80211_ps_tx_ack(priv->ieee80211, 1);
1293 }
1294 }
1295 }
1296
1297 if(prio != BEACON_QUEUE) {
1298 /* try to deal with the pending packets */
1299 tasklet_schedule(&priv->irq_tx_tasklet);
1300 }
1301
1302}
1303
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001304static void rtl8192_stop_beacon(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001305{
1306 //rtl8192_beacon_disable(dev);
1307}
1308
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001309static void rtl8192_config_rate(struct net_device* dev, u16* rate_config)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001310{
1311 struct r8192_priv *priv = ieee80211_priv(dev);
1312 struct ieee80211_network *net;
1313 u8 i=0, basic_rate = 0;
1314 net = & priv->ieee80211->current_network;
1315
1316 for (i=0; i<net->rates_len; i++)
1317 {
1318 basic_rate = net->rates[i]&0x7f;
1319 switch(basic_rate)
1320 {
1321 case MGN_1M: *rate_config |= RRSR_1M; break;
1322 case MGN_2M: *rate_config |= RRSR_2M; break;
1323 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1324 case MGN_11M: *rate_config |= RRSR_11M; break;
1325 case MGN_6M: *rate_config |= RRSR_6M; break;
1326 case MGN_9M: *rate_config |= RRSR_9M; break;
1327 case MGN_12M: *rate_config |= RRSR_12M; break;
1328 case MGN_18M: *rate_config |= RRSR_18M; break;
1329 case MGN_24M: *rate_config |= RRSR_24M; break;
1330 case MGN_36M: *rate_config |= RRSR_36M; break;
1331 case MGN_48M: *rate_config |= RRSR_48M; break;
1332 case MGN_54M: *rate_config |= RRSR_54M; break;
1333 }
1334 }
1335 for (i=0; i<net->rates_ex_len; i++)
1336 {
1337 basic_rate = net->rates_ex[i]&0x7f;
1338 switch(basic_rate)
1339 {
1340 case MGN_1M: *rate_config |= RRSR_1M; break;
1341 case MGN_2M: *rate_config |= RRSR_2M; break;
1342 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1343 case MGN_11M: *rate_config |= RRSR_11M; break;
1344 case MGN_6M: *rate_config |= RRSR_6M; break;
1345 case MGN_9M: *rate_config |= RRSR_9M; break;
1346 case MGN_12M: *rate_config |= RRSR_12M; break;
1347 case MGN_18M: *rate_config |= RRSR_18M; break;
1348 case MGN_24M: *rate_config |= RRSR_24M; break;
1349 case MGN_36M: *rate_config |= RRSR_36M; break;
1350 case MGN_48M: *rate_config |= RRSR_48M; break;
1351 case MGN_54M: *rate_config |= RRSR_54M; break;
1352 }
1353 }
1354}
1355
1356
1357#define SHORT_SLOT_TIME 9
1358#define NON_SHORT_SLOT_TIME 20
1359
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001360static void rtl8192_update_cap(struct net_device* dev, u16 cap)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001361{
1362 u32 tmp = 0;
1363 struct r8192_priv *priv = ieee80211_priv(dev);
1364 struct ieee80211_network *net = &priv->ieee80211->current_network;
1365 priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
1366 tmp = priv->basic_rate;
1367 if (priv->short_preamble)
1368 tmp |= BRSR_AckShortPmb;
1369 write_nic_dword(dev, RRSR, tmp);
1370
1371 if (net->mode & (IEEE_G|IEEE_N_24G))
1372 {
1373 u8 slot_time = 0;
1374 if ((cap & WLAN_CAPABILITY_SHORT_SLOT)&&(!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime))
1375 {//short slot time
1376 slot_time = SHORT_SLOT_TIME;
1377 }
1378 else //long slot time
1379 slot_time = NON_SHORT_SLOT_TIME;
1380 priv->slot_time = slot_time;
1381 write_nic_byte(dev, SLOT_TIME, slot_time);
1382 }
1383
1384}
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001385
1386static void rtl8192_net_update(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001387{
1388
1389 struct r8192_priv *priv = ieee80211_priv(dev);
1390 struct ieee80211_network *net;
1391 u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
1392 u16 rate_config = 0;
1393 net = &priv->ieee80211->current_network;
1394 //update Basic rate: RR, BRSR
1395 rtl8192_config_rate(dev, &rate_config);
1396 // 2007.01.16, by Emily
1397 // Select RRSR (in Legacy-OFDM and CCK)
1398 // For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M, and 1M from the Basic rate.
1399 // We do not use other rates.
1400 priv->basic_rate = rate_config &= 0x15f;
1401 //BSSID
1402 write_nic_dword(dev,BSSIDR,((u32*)net->bssid)[0]);
1403 write_nic_word(dev,BSSIDR+4,((u16*)net->bssid)[2]);
1404#if 0
1405 //MSR
1406 rtl8192_update_msr(dev);
1407#endif
1408
1409
1410// rtl8192_update_cap(dev, net->capability);
1411 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
1412 {
1413 write_nic_word(dev, ATIMWND, 2);
1414 write_nic_word(dev, BCN_DMATIME, 256);
1415 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
1416 // write_nic_word(dev, BcnIntTime, 100);
1417 //BIT15 of BCN_DRV_EARLY_INT will indicate whether software beacon or hw beacon is applied.
1418 write_nic_word(dev, BCN_DRV_EARLY_INT, 10);
1419 write_nic_byte(dev, BCN_ERR_THRESH, 100);
1420
1421 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
1422 // TODO: BcnIFS may required to be changed on ASIC
1423 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
1424
1425 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
1426 }
1427
1428
1429}
1430
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001431void rtl819xE_tx_cmd(struct net_device *dev, struct sk_buff *skb)
1432{
1433 struct r8192_priv *priv = ieee80211_priv(dev);
1434 struct rtl8192_tx_ring *ring;
1435 tx_desc_819x_pci *entry;
1436 unsigned int idx;
1437 dma_addr_t mapping;
1438 cb_desc *tcb_desc;
1439 unsigned long flags;
1440
1441 ring = &priv->tx_ring[TXCMD_QUEUE];
1442 mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
1443
1444 spin_lock_irqsave(&priv->irq_th_lock,flags);
1445 idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
1446 entry = &ring->desc[idx];
1447
1448 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1449 memset(entry,0,12);
1450 entry->LINIP = tcb_desc->bLastIniPkt;
1451 entry->FirstSeg = 1;//first segment
1452 entry->LastSeg = 1; //last segment
1453 if(tcb_desc->bCmdOrInit == DESC_PACKET_TYPE_INIT) {
1454 entry->CmdInit = DESC_PACKET_TYPE_INIT;
1455 } else {
1456 entry->CmdInit = DESC_PACKET_TYPE_NORMAL;
1457 entry->Offset = sizeof(TX_FWINFO_8190PCI) + 8;
1458 entry->PktSize = (u16)(tcb_desc->pkt_size + entry->Offset);
1459 entry->QueueSelect = QSLT_CMD;
1460 entry->TxFWInfoSize = 0x08;
1461 entry->RATid = (u8)DESC_PACKET_TYPE_INIT;
1462 }
1463 entry->TxBufferSize = skb->len;
1464 entry->TxBuffAddr = cpu_to_le32(mapping);
1465 entry->OWN = 1;
1466
1467#ifdef JOHN_DUMP_TXDESC
1468 { int i;
1469 tx_desc_819x_pci *entry1 = &ring->desc[0];
1470 unsigned int *ptr= (unsigned int *)entry1;
1471 printk("<Tx descriptor>:\n");
1472 for (i = 0; i < 8; i++)
1473 printk("%8x ", ptr[i]);
1474 printk("\n");
1475 }
1476#endif
1477 __skb_queue_tail(&ring->queue, skb);
1478 spin_unlock_irqrestore(&priv->irq_th_lock,flags);
1479
1480 write_nic_byte(dev, TPPoll, TPPoll_CQ);
1481
1482 return;
1483}
1484
1485/*
1486 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1487 * in TxFwInfo data structure
1488 * 2006.10.30 by Emily
1489 *
1490 * \param QUEUEID Software Queue
1491*/
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001492static u8 MapHwQueueToFirmwareQueue(u8 QueueID)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001493{
1494 u8 QueueSelect = 0x0; //defualt set to
1495
1496 switch(QueueID) {
1497 case BE_QUEUE:
1498 QueueSelect = QSLT_BE; //or QSelect = pTcb->priority;
1499 break;
1500
1501 case BK_QUEUE:
1502 QueueSelect = QSLT_BK; //or QSelect = pTcb->priority;
1503 break;
1504
1505 case VO_QUEUE:
1506 QueueSelect = QSLT_VO; //or QSelect = pTcb->priority;
1507 break;
1508
1509 case VI_QUEUE:
1510 QueueSelect = QSLT_VI; //or QSelect = pTcb->priority;
1511 break;
1512 case MGNT_QUEUE:
1513 QueueSelect = QSLT_MGNT;
1514 break;
1515
1516 case BEACON_QUEUE:
1517 QueueSelect = QSLT_BEACON;
1518 break;
1519
1520 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
1521 // TODO: Remove Assertions
1522//#if (RTL819X_FPGA_VER & RTL819X_FPGA_GUANGAN_070502)
1523 case TXCMD_QUEUE:
1524 QueueSelect = QSLT_CMD;
1525 break;
1526//#endif
1527 case HIGH_QUEUE:
1528 //QueueSelect = QSLT_HIGH;
1529 //break;
1530
1531 default:
1532 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
1533 break;
1534 }
1535 return QueueSelect;
1536}
1537
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001538static u8 MRateToHwRate8190Pci(u8 rate)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001539{
1540 u8 ret = DESC90_RATE1M;
1541
1542 switch(rate) {
1543 case MGN_1M: ret = DESC90_RATE1M; break;
1544 case MGN_2M: ret = DESC90_RATE2M; break;
1545 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1546 case MGN_11M: ret = DESC90_RATE11M; break;
1547 case MGN_6M: ret = DESC90_RATE6M; break;
1548 case MGN_9M: ret = DESC90_RATE9M; break;
1549 case MGN_12M: ret = DESC90_RATE12M; break;
1550 case MGN_18M: ret = DESC90_RATE18M; break;
1551 case MGN_24M: ret = DESC90_RATE24M; break;
1552 case MGN_36M: ret = DESC90_RATE36M; break;
1553 case MGN_48M: ret = DESC90_RATE48M; break;
1554 case MGN_54M: ret = DESC90_RATE54M; break;
1555
1556 // HT rate since here
1557 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1558 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1559 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1560 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1561 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1562 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1563 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1564 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1565 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1566 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1567 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1568 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1569 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1570 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1571 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1572 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1573 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
1574
1575 default: break;
1576 }
1577 return ret;
1578}
1579
1580
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001581static u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001582{
1583 u8 tmp_Short;
1584
1585 tmp_Short = (TxHT==1)?((tcb_desc->bUseShortGI)?1:0):((tcb_desc->bUseShortPreamble)?1:0);
1586
1587 if(TxHT==1 && TxRate != DESC90_RATEMCS15)
1588 tmp_Short = 0;
1589
1590 return tmp_Short;
1591}
1592
1593/*
1594 * The tx procedure is just as following,
1595 * skb->cb will contain all the following information,
1596 * priority, morefrag, rate, &dev.
1597 * */
1598short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
1599{
1600 struct r8192_priv *priv = ieee80211_priv(dev);
1601 struct rtl8192_tx_ring *ring;
1602 unsigned long flags;
1603 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1604 tx_desc_819x_pci *pdesc = NULL;
1605 TX_FWINFO_8190PCI *pTxFwInfo = NULL;
1606 dma_addr_t mapping;
1607 bool multi_addr=false,broad_addr=false,uni_addr=false;
1608 u8* pda_addr = NULL;
1609 int idx;
1610
david woo65a43782009-12-22 09:40:36 -08001611 if(priv->bdisable_nic){
1612 RT_TRACE(COMP_ERR,"%s: ERR!! Nic is disabled! Can't tx packet len=%d qidx=%d!!!\n", __FUNCTION__, skb->len, tcb_desc->queue_index);
1613 return skb->len;
1614 }
1615
1616#ifdef ENABLE_LPS
1617 priv->ieee80211->bAwakePktSent = true;
1618#endif
1619
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001620 mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
1621 /* collect the tx packets statitcs */
1622 pda_addr = ((u8*)skb->data) + sizeof(TX_FWINFO_8190PCI);
1623 if(is_multicast_ether_addr(pda_addr))
1624 multi_addr = true;
1625 else if(is_broadcast_ether_addr(pda_addr))
1626 broad_addr = true;
1627 else
1628 uni_addr = true;
1629
1630 if(uni_addr)
1631 priv->stats.txbytesunicast += (u8)(skb->len) - sizeof(TX_FWINFO_8190PCI);
1632 else if(multi_addr)
1633 priv->stats.txbytesmulticast +=(u8)(skb->len) - sizeof(TX_FWINFO_8190PCI);
1634 else
1635 priv->stats.txbytesbroadcast += (u8)(skb->len) - sizeof(TX_FWINFO_8190PCI);
1636
1637 /* fill tx firmware */
1638 pTxFwInfo = (PTX_FWINFO_8190PCI)skb->data;
1639 memset(pTxFwInfo,0,sizeof(TX_FWINFO_8190PCI));
1640 pTxFwInfo->TxHT = (tcb_desc->data_rate&0x80)?1:0;
1641 pTxFwInfo->TxRate = MRateToHwRate8190Pci((u8)tcb_desc->data_rate);
1642 pTxFwInfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1643 pTxFwInfo->Short = QueryIsShort(pTxFwInfo->TxHT, pTxFwInfo->TxRate, tcb_desc);
1644
1645 /* Aggregation related */
1646 if(tcb_desc->bAMPDUEnable) {
1647 pTxFwInfo->AllowAggregation = 1;
1648 pTxFwInfo->RxMF = tcb_desc->ampdu_factor;
1649 pTxFwInfo->RxAMD = tcb_desc->ampdu_density;
1650 } else {
1651 pTxFwInfo->AllowAggregation = 0;
1652 pTxFwInfo->RxMF = 0;
1653 pTxFwInfo->RxAMD = 0;
1654 }
1655
1656 //
1657 // Protection mode related
1658 //
1659 pTxFwInfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0;
1660 pTxFwInfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0;
1661 pTxFwInfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0;
1662 pTxFwInfo->RtsHT= (tcb_desc->rts_rate&0x80)?1:0;
1663 pTxFwInfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
1664 pTxFwInfo->RtsBandwidth = 0;
1665 pTxFwInfo->RtsSubcarrier = tcb_desc->RTSSC;
1666 pTxFwInfo->RtsShort = (pTxFwInfo->RtsHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):(tcb_desc->bRTSUseShortGI?1:0);
1667 //
1668 // Set Bandwidth and sub-channel settings.
1669 //
1670 if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
1671 {
1672 if(tcb_desc->bPacketBW)
1673 {
1674 pTxFwInfo->TxBandwidth = 1;
1675#ifdef RTL8190P
1676 pTxFwInfo->TxSubCarrier = 3;
1677#else
1678 pTxFwInfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode, cosa 04012008
1679#endif
1680 }
1681 else
1682 {
1683 pTxFwInfo->TxBandwidth = 0;
1684 pTxFwInfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1685 }
1686 } else {
1687 pTxFwInfo->TxBandwidth = 0;
1688 pTxFwInfo->TxSubCarrier = 0;
1689 }
1690
1691 if (0)
1692 {
1693 /* 2007/07/25 MH Copy current TX FW info.*/
1694 memcpy((void*)(&Tmp_TxFwInfo), (void*)(pTxFwInfo), sizeof(TX_FWINFO_8190PCI));
1695 printk("&&&&&&&&&&&&&&&&&&&&&&====>print out fwinf\n");
1696 printk("===>enable fwcacl:%d\n", Tmp_TxFwInfo.EnableCPUDur);
1697 printk("===>RTS STBC:%d\n", Tmp_TxFwInfo.RtsSTBC);
1698 printk("===>RTS Subcarrier:%d\n", Tmp_TxFwInfo.RtsSubcarrier);
1699 printk("===>Allow Aggregation:%d\n", Tmp_TxFwInfo.AllowAggregation);
1700 printk("===>TX HT bit:%d\n", Tmp_TxFwInfo.TxHT);
1701 printk("===>Tx rate:%d\n", Tmp_TxFwInfo.TxRate);
1702 printk("===>Received AMPDU Density:%d\n", Tmp_TxFwInfo.RxAMD);
1703 printk("===>Received MPDU Factor:%d\n", Tmp_TxFwInfo.RxMF);
1704 printk("===>TxBandwidth:%d\n", Tmp_TxFwInfo.TxBandwidth);
1705 printk("===>TxSubCarrier:%d\n", Tmp_TxFwInfo.TxSubCarrier);
1706
1707 printk("<=====**********************out of print\n");
1708
1709 }
1710 spin_lock_irqsave(&priv->irq_th_lock,flags);
1711 ring = &priv->tx_ring[tcb_desc->queue_index];
1712 if (tcb_desc->queue_index != BEACON_QUEUE) {
1713 idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
1714 } else {
1715 idx = 0;
1716 }
1717
1718 pdesc = &ring->desc[idx];
1719 if((pdesc->OWN == 1) && (tcb_desc->queue_index != BEACON_QUEUE)) {
1720 RT_TRACE(COMP_ERR,"No more TX desc@%d, ring->idx = %d,idx = %d,%x", \
1721 tcb_desc->queue_index,ring->idx, idx,skb->len);
david woo65a43782009-12-22 09:40:36 -08001722 spin_unlock_irqrestore(&priv->irq_th_lock,flags);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001723 return skb->len;
1724 }
1725
1726 /* fill tx descriptor */
1727 memset((u8*)pdesc,0,12);
1728 /*DWORD 0*/
1729 pdesc->LINIP = 0;
1730 pdesc->CmdInit = 1;
1731 pdesc->Offset = sizeof(TX_FWINFO_8190PCI) + 8; //We must add 8!! Emily
1732 pdesc->PktSize = (u16)skb->len-sizeof(TX_FWINFO_8190PCI);
1733
1734 /*DWORD 1*/
1735 pdesc->SecCAMID= 0;
1736 pdesc->RATid = tcb_desc->RATRIndex;
1737
1738
1739 pdesc->NoEnc = 1;
1740 pdesc->SecType = 0x0;
1741 if (tcb_desc->bHwSec) {
1742 static u8 tmp =0;
1743 if (!tmp) {
1744 printk("==>================hw sec\n");
1745 tmp = 1;
1746 }
1747 switch (priv->ieee80211->pairwise_key_type) {
1748 case KEY_TYPE_WEP40:
1749 case KEY_TYPE_WEP104:
1750 pdesc->SecType = 0x1;
1751 pdesc->NoEnc = 0;
1752 break;
1753 case KEY_TYPE_TKIP:
1754 pdesc->SecType = 0x2;
1755 pdesc->NoEnc = 0;
1756 break;
1757 case KEY_TYPE_CCMP:
1758 pdesc->SecType = 0x3;
1759 pdesc->NoEnc = 0;
1760 break;
1761 case KEY_TYPE_NA:
1762 pdesc->SecType = 0x0;
1763 pdesc->NoEnc = 1;
1764 break;
1765 }
1766 }
1767
1768 //
1769 // Set Packet ID
1770 //
1771 pdesc->PktId = 0x0;
1772
1773 pdesc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1774 pdesc->TxFWInfoSize = sizeof(TX_FWINFO_8190PCI);
1775
1776 pdesc->DISFB = tcb_desc->bTxDisableRateFallBack;
1777 pdesc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1778
1779 pdesc->FirstSeg =1;
1780 pdesc->LastSeg = 1;
1781 pdesc->TxBufferSize = skb->len;
1782
1783 pdesc->TxBuffAddr = cpu_to_le32(mapping);
1784 __skb_queue_tail(&ring->queue, skb);
1785 pdesc->OWN = 1;
1786 spin_unlock_irqrestore(&priv->irq_th_lock,flags);
1787 dev->trans_start = jiffies;
1788 write_nic_word(dev,TPPoll,0x01<<tcb_desc->queue_index);
1789 return 0;
1790}
1791
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001792static short rtl8192_alloc_rx_desc_ring(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001793{
1794 struct r8192_priv *priv = ieee80211_priv(dev);
1795 rx_desc_819x_pci *entry = NULL;
1796 int i;
1797
1798 priv->rx_ring = pci_alloc_consistent(priv->pdev,
1799 sizeof(*priv->rx_ring) * priv->rxringcount, &priv->rx_ring_dma);
1800
1801 if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) {
1802 RT_TRACE(COMP_ERR,"Cannot allocate RX ring\n");
1803 return -ENOMEM;
1804 }
1805
1806 memset(priv->rx_ring, 0, sizeof(*priv->rx_ring) * priv->rxringcount);
1807 priv->rx_idx = 0;
1808
1809 for (i = 0; i < priv->rxringcount; i++) {
1810 struct sk_buff *skb = dev_alloc_skb(priv->rxbuffersize);
1811 dma_addr_t *mapping;
1812 entry = &priv->rx_ring[i];
1813 if (!skb)
1814 return 0;
1815 priv->rx_buf[i] = skb;
1816 mapping = (dma_addr_t *)skb->cb;
Jeff Mahoney1c7ec2e2010-01-11 10:54:27 -05001817 *mapping = pci_map_single(priv->pdev, skb_tail_pointer(skb),
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001818 priv->rxbuffersize, PCI_DMA_FROMDEVICE);
1819
1820 entry->BufferAddress = cpu_to_le32(*mapping);
1821
1822 entry->Length = priv->rxbuffersize;
1823 entry->OWN = 1;
1824 }
1825
1826 entry->EOR = 1;
1827 return 0;
1828}
1829
1830static int rtl8192_alloc_tx_desc_ring(struct net_device *dev,
1831 unsigned int prio, unsigned int entries)
1832{
1833 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1834 tx_desc_819x_pci *ring;
1835 dma_addr_t dma;
1836 int i;
1837
1838 ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
1839 if (!ring || (unsigned long)ring & 0xFF) {
1840 RT_TRACE(COMP_ERR, "Cannot allocate TX ring (prio = %d)\n", prio);
1841 return -ENOMEM;
1842 }
1843
1844 memset(ring, 0, sizeof(*ring)*entries);
1845 priv->tx_ring[prio].desc = ring;
1846 priv->tx_ring[prio].dma = dma;
1847 priv->tx_ring[prio].idx = 0;
1848 priv->tx_ring[prio].entries = entries;
1849 skb_queue_head_init(&priv->tx_ring[prio].queue);
1850
1851 for (i = 0; i < entries; i++)
1852 ring[i].NextDescAddress =
1853 cpu_to_le32((u32)dma + ((i + 1) % entries) * sizeof(*ring));
1854
1855 return 0;
1856}
1857
1858
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001859static short rtl8192_pci_initdescring(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001860{
1861 u32 ret;
1862 int i;
1863 struct r8192_priv *priv = ieee80211_priv(dev);
1864
1865 ret = rtl8192_alloc_rx_desc_ring(dev);
1866 if (ret) {
1867 return ret;
1868 }
1869
1870
1871 /* general process for other queue */
1872 for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
Joe Perchesd6d42df2010-03-24 22:17:02 -07001873 ret = rtl8192_alloc_tx_desc_ring(dev, i, priv->txringcount);
1874 if (ret)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001875 goto err_free_rings;
1876 }
1877
1878#if 0
1879 /* specific process for hardware beacon process */
Joe Perchesd6d42df2010-03-24 22:17:02 -07001880 ret = rtl8192_alloc_tx_desc_ring(dev, MAX_TX_QUEUE_COUNT - 1, 2);
1881 if (ret)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001882 goto err_free_rings;
1883#endif
1884
1885 return 0;
1886
1887err_free_rings:
1888 rtl8192_free_rx_ring(dev);
1889 for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
1890 if (priv->tx_ring[i].desc)
1891 rtl8192_free_tx_ring(dev, i);
1892 return 1;
1893}
1894
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001895static void rtl8192_pci_resetdescring(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001896{
1897 struct r8192_priv *priv = ieee80211_priv(dev);
1898 int i;
1899
1900 /* force the rx_idx to the first one */
1901 if(priv->rx_ring) {
1902 rx_desc_819x_pci *entry = NULL;
1903 for (i = 0; i < priv->rxringcount; i++) {
1904 entry = &priv->rx_ring[i];
1905 entry->OWN = 1;
1906 }
1907 priv->rx_idx = 0;
1908 }
1909
1910 /* after reset, release previous pending packet, and force the
1911 * tx idx to the first one */
1912 for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
1913 if (priv->tx_ring[i].desc) {
1914 struct rtl8192_tx_ring *ring = &priv->tx_ring[i];
1915
1916 while (skb_queue_len(&ring->queue)) {
1917 tx_desc_819x_pci *entry = &ring->desc[ring->idx];
1918 struct sk_buff *skb = __skb_dequeue(&ring->queue);
1919
1920 pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr),
1921 skb->len, PCI_DMA_TODEVICE);
1922 kfree_skb(skb);
1923 ring->idx = (ring->idx + 1) % ring->entries;
1924 }
1925 ring->idx = 0;
1926 }
1927 }
1928}
1929
1930#if 1
1931extern void rtl8192_update_ratr_table(struct net_device* dev);
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001932static void rtl8192_link_change(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001933{
1934// int i;
1935
1936 struct r8192_priv *priv = ieee80211_priv(dev);
1937 struct ieee80211_device* ieee = priv->ieee80211;
1938 //write_nic_word(dev, BCN_INTR_ITV, net->beacon_interval);
1939 if (ieee->state == IEEE80211_LINKED)
1940 {
1941 rtl8192_net_update(dev);
1942 rtl8192_update_ratr_table(dev);
1943#if 1
1944 //add this as in pure N mode, wep encryption will use software way, but there is no chance to set this as wep will not set group key in wext. WB.2008.07.08
1945 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
1946 EnableHWSecurityConfig8192(dev);
1947#endif
1948 }
1949 else
1950 {
1951 write_nic_byte(dev, 0x173, 0);
1952 }
1953 /*update timing params*/
1954 //rtl8192_set_chan(dev, priv->chan);
1955 //MSR
1956 rtl8192_update_msr(dev);
1957
1958 // 2007/10/16 MH MAC Will update TSF according to all received beacon, so we have
1959 // // To set CBSSID bit when link with any AP or STA.
1960 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
1961 {
1962 u32 reg = 0;
1963 reg = read_nic_dword(dev, RCR);
1964 if (priv->ieee80211->state == IEEE80211_LINKED)
1965 priv->ReceiveConfig = reg |= RCR_CBSSID;
1966 else
1967 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
1968 write_nic_dword(dev, RCR, reg);
1969 }
1970}
1971#endif
1972
1973
1974static struct ieee80211_qos_parameters def_qos_parameters = {
1975 {3,3,3,3},/* cw_min */
1976 {7,7,7,7},/* cw_max */
1977 {2,2,2,2},/* aifs */
1978 {0,0,0,0},/* flags */
1979 {0,0,0,0} /* tx_op_limit */
1980};
1981
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001982static void rtl8192_update_beacon(struct work_struct * work)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001983{
1984 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
1985 struct net_device *dev = priv->ieee80211->dev;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001986 struct ieee80211_device* ieee = priv->ieee80211;
1987 struct ieee80211_network* net = &ieee->current_network;
1988
1989 if (ieee->pHTInfo->bCurrentHTSupport)
1990 HTUpdateSelfAndPeerSetting(ieee, net);
1991 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
1992 rtl8192_update_cap(dev, net->capability);
1993}
1994/*
1995* background support to run QoS activate functionality
1996*/
Mike McCormack881a9752010-07-26 22:58:03 +09001997static const int WDCAPARA_ADD[] = {EDCAPARA_BE,EDCAPARA_BK,EDCAPARA_VI,EDCAPARA_VO};
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07001998static void rtl8192_qos_activate(struct work_struct * work)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001999{
2000 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
2001 struct net_device *dev = priv->ieee80211->dev;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002002 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2003 u8 mode = priv->ieee80211->current_network.mode;
2004// u32 size = sizeof(struct ieee80211_qos_parameters);
2005 u8 u1bAIFS;
2006 u32 u4bAcParam;
2007 int i;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002008
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002009 mutex_lock(&priv->mutex);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002010 if(priv->ieee80211->state != IEEE80211_LINKED)
2011 goto success;
2012 RT_TRACE(COMP_QOS,"qos active process with associate response received\n");
2013 /* It better set slot time at first */
2014 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2015 /* update the ac parameter to related registers */
2016 for(i = 0; i < QOS_QUEUE_NUM; i++) {
2017 //Mode G/A: slotTimeTimer = 9; Mode B: 20
2018 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime;
2019 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
2020 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2021 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2022 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
david woo65a43782009-12-22 09:40:36 -08002023 //printk("===>u4bAcParam:%x, ", u4bAcParam);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002024 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
2025 //write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
2026 }
2027
2028success:
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002029 mutex_unlock(&priv->mutex);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002030}
2031
2032static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
2033 int active_network,
2034 struct ieee80211_network *network)
2035{
2036 int ret = 0;
2037 u32 size = sizeof(struct ieee80211_qos_parameters);
2038
2039 if(priv->ieee80211->state !=IEEE80211_LINKED)
2040 return ret;
2041
2042 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2043 return ret;
2044
2045 if (network->flags & NETWORK_HAS_QOS_MASK) {
2046 if (active_network &&
2047 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
2048 network->qos_data.active = network->qos_data.supported;
2049
2050 if ((network->qos_data.active == 1) && (active_network == 1) &&
2051 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2052 (network->qos_data.old_param_count !=
2053 network->qos_data.param_count)) {
2054 network->qos_data.old_param_count =
2055 network->qos_data.param_count;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002056 queue_work(priv->priv_wq, &priv->qos_activate);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002057 RT_TRACE (COMP_QOS, "QoS parameters change call "
2058 "qos_activate\n");
2059 }
2060 } else {
2061 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2062 &def_qos_parameters, size);
2063
2064 if ((network->qos_data.active == 1) && (active_network == 1)) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002065 queue_work(priv->priv_wq, &priv->qos_activate);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002066 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2067 }
2068 network->qos_data.active = 0;
2069 network->qos_data.supported = 0;
2070 }
2071
2072 return 0;
2073}
2074
2075/* handle manage frame frame beacon and probe response */
2076static int rtl8192_handle_beacon(struct net_device * dev,
2077 struct ieee80211_beacon * beacon,
2078 struct ieee80211_network * network)
2079{
2080 struct r8192_priv *priv = ieee80211_priv(dev);
2081
2082 rtl8192_qos_handle_probe_response(priv,1,network);
2083
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002084 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002085 return 0;
2086
2087}
2088
2089/*
2090* handling the beaconing responses. if we get different QoS setting
2091* off the network from the associated setting, adjust the QoS
2092* setting
2093*/
2094static int rtl8192_qos_association_resp(struct r8192_priv *priv,
2095 struct ieee80211_network *network)
2096{
2097 int ret = 0;
2098 unsigned long flags;
2099 u32 size = sizeof(struct ieee80211_qos_parameters);
2100 int set_qos_param = 0;
2101
2102 if ((priv == NULL) || (network == NULL))
2103 return ret;
2104
2105 if(priv->ieee80211->state !=IEEE80211_LINKED)
2106 return ret;
2107
2108 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2109 return ret;
2110
2111 spin_lock_irqsave(&priv->ieee80211->lock, flags);
2112 if(network->flags & NETWORK_HAS_QOS_PARAMETERS) {
2113 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2114 &network->qos_data.parameters,\
2115 sizeof(struct ieee80211_qos_parameters));
2116 priv->ieee80211->current_network.qos_data.active = 1;
2117#if 0
2118 if((priv->ieee80211->current_network.qos_data.param_count != \
2119 network->qos_data.param_count))
2120#endif
2121 {
2122 set_qos_param = 1;
2123 /* update qos parameter for current network */
2124 priv->ieee80211->current_network.qos_data.old_param_count = \
2125 priv->ieee80211->current_network.qos_data.param_count;
2126 priv->ieee80211->current_network.qos_data.param_count = \
2127 network->qos_data.param_count;
2128 }
2129 } else {
2130 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2131 &def_qos_parameters, size);
2132 priv->ieee80211->current_network.qos_data.active = 0;
2133 priv->ieee80211->current_network.qos_data.supported = 0;
2134 set_qos_param = 1;
2135 }
2136
2137 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
2138
2139 RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n",__FUNCTION__,network->flags ,priv->ieee80211->current_network.qos_data.active);
2140 if (set_qos_param == 1)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002141 queue_work(priv->priv_wq, &priv->qos_activate);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002142
2143 return ret;
2144}
2145
2146
2147static int rtl8192_handle_assoc_response(struct net_device *dev,
2148 struct ieee80211_assoc_response_frame *resp,
2149 struct ieee80211_network *network)
2150{
2151 struct r8192_priv *priv = ieee80211_priv(dev);
2152 rtl8192_qos_association_resp(priv, network);
2153 return 0;
2154}
2155
2156
2157//updateRATRTabel for MCS only. Basic rate is not implement.
2158void rtl8192_update_ratr_table(struct net_device* dev)
2159 // POCTET_STRING posLegacyRate,
2160 // u8* pMcsRate)
2161 // PRT_WLAN_STA pEntry)
2162{
2163 struct r8192_priv* priv = ieee80211_priv(dev);
2164 struct ieee80211_device* ieee = priv->ieee80211;
2165 u8* pMcsRate = ieee->dot11HTOperationalRateSet;
2166 //struct ieee80211_network *net = &ieee->current_network;
2167 u32 ratr_value = 0;
2168 u8 rate_index = 0;
2169
2170 rtl8192_config_rate(dev, (u16*)(&ratr_value));
2171 ratr_value |= (*(u16*)(pMcsRate)) << 12;
2172// switch (net->mode)
2173 switch (ieee->mode)
2174 {
2175 case IEEE_A:
2176 ratr_value &= 0x00000FF0;
2177 break;
2178 case IEEE_B:
2179 ratr_value &= 0x0000000F;
2180 break;
2181 case IEEE_G:
2182 ratr_value &= 0x00000FF7;
2183 break;
2184 case IEEE_N_24G:
2185 case IEEE_N_5G:
2186 if (ieee->pHTInfo->PeerMimoPs == 0) //MIMO_PS_STATIC
2187 ratr_value &= 0x0007F007;
2188 else{
2189 if (priv->rf_type == RF_1T2R)
2190 ratr_value &= 0x000FF007;
2191 else
2192 ratr_value &= 0x0F81F007;
2193 }
2194 break;
2195 default:
2196 break;
2197 }
2198 ratr_value &= 0x0FFFFFFF;
2199 if(ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz){
2200 ratr_value |= 0x80000000;
2201 }else if(!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz){
2202 ratr_value |= 0x80000000;
2203 }
2204 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2205 write_nic_byte(dev, UFWP, 1);
2206}
2207
david woo65a43782009-12-22 09:40:36 -08002208#if 0
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002209static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
2210static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
david woo65a43782009-12-22 09:40:36 -08002211#endif
2212
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07002213static bool GetNmodeSupportBySecCfg8190Pci(struct net_device*dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002214{
2215#if 1
david woo65a43782009-12-22 09:40:36 -08002216
2217 struct r8192_priv *priv = ieee80211_priv(dev);
2218 struct ieee80211_device *ieee = priv->ieee80211;
2219 if (ieee->rtllib_ap_sec_type &&
2220 (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))) {
2221 return false;
2222 } else {
2223 return true;
2224 }
2225#else
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002226 struct r8192_priv* priv = ieee80211_priv(dev);
2227 struct ieee80211_device* ieee = priv->ieee80211;
2228 int wpa_ie_len= ieee->wpa_ie_len;
2229 struct ieee80211_crypt_data* crypt;
2230 int encrypt;
2231
2232 crypt = ieee->crypt[ieee->tx_keyidx];
2233 encrypt = (ieee->current_network.capability & WLAN_CAPABILITY_PRIVACY) || (ieee->host_encrypt && crypt && crypt->ops && (0 == strcmp(crypt->ops->name,"WEP")));
2234
2235 /* simply judge */
2236 if(encrypt && (wpa_ie_len == 0)) {
2237 /* wep encryption, no N mode setting */
2238 return false;
2239// } else if((wpa_ie_len != 0)&&(memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) {
2240 } else if((wpa_ie_len != 0)) {
2241 /* parse pairwise key type */
2242 //if((pairwisekey = WEP40)||(pairwisekey = WEP104)||(pairwisekey = TKIP))
2243 if (((ieee->wpa_ie[0] == 0xdd) && (!memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) || ((ieee->wpa_ie[0] == 0x30) && (!memcmp(&ieee->wpa_ie[10],ccmp_rsn_ie, 4))))
2244 return true;
2245 else
2246 return false;
2247 } else {
2248 //RT_TRACE(COMP_ERR,"In %s The GroupEncAlgorithm is [4]\n",__FUNCTION__ );
2249 return true;
2250 }
2251
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002252 return true;
2253#endif
2254}
2255
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07002256static void rtl8192_refresh_supportrate(struct r8192_priv* priv)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002257{
2258 struct ieee80211_device* ieee = priv->ieee80211;
2259 //we donot consider set support rate for ABG mode, only HT MCS rate is set here.
2260 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
2261 {
2262 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
2263 //RT_DEBUG_DATA(COMP_INIT, ieee->RegHTSuppRateSet, 16);
2264 //RT_DEBUG_DATA(COMP_INIT, ieee->Regdot11HTOperationalRateSet, 16);
2265 }
2266 else
2267 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2268 return;
2269}
2270
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07002271static u8 rtl8192_getSupportedWireleeMode(struct net_device*dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002272{
2273 struct r8192_priv *priv = ieee80211_priv(dev);
2274 u8 ret = 0;
2275 switch(priv->rf_chip)
2276 {
2277 case RF_8225:
2278 case RF_8256:
2279 case RF_PSEUDO_11N:
2280 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2281 break;
2282 case RF_8258:
2283 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2284 break;
2285 default:
2286 ret = WIRELESS_MODE_B;
2287 break;
2288 }
2289 return ret;
2290}
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07002291
2292static void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002293{
2294 struct r8192_priv *priv = ieee80211_priv(dev);
2295 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2296
2297#if 1
2298 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode)==0))
2299 {
2300 if(bSupportMode & WIRELESS_MODE_N_24G)
2301 {
2302 wireless_mode = WIRELESS_MODE_N_24G;
2303 }
2304 else if(bSupportMode & WIRELESS_MODE_N_5G)
2305 {
2306 wireless_mode = WIRELESS_MODE_N_5G;
2307 }
2308 else if((bSupportMode & WIRELESS_MODE_A))
2309 {
2310 wireless_mode = WIRELESS_MODE_A;
2311 }
2312 else if((bSupportMode & WIRELESS_MODE_G))
2313 {
2314 wireless_mode = WIRELESS_MODE_G;
2315 }
2316 else if((bSupportMode & WIRELESS_MODE_B))
2317 {
2318 wireless_mode = WIRELESS_MODE_B;
2319 }
2320 else{
2321 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __FUNCTION__,bSupportMode);
2322 wireless_mode = WIRELESS_MODE_B;
2323 }
2324 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002325#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we should wait for FPGA
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002326 ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
2327#endif
2328 priv->ieee80211->mode = wireless_mode;
2329
2330 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2331 priv->ieee80211->pHTInfo->bEnableHT = 1;
2332 else
2333 priv->ieee80211->pHTInfo->bEnableHT = 0;
2334 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2335 rtl8192_refresh_supportrate(priv);
2336#endif
2337
2338}
2339//init priv variables here
2340
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07002341static bool GetHalfNmodeSupportByAPs819xPci(struct net_device* dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002342{
2343 bool Reval;
2344 struct r8192_priv* priv = ieee80211_priv(dev);
2345 struct ieee80211_device* ieee = priv->ieee80211;
2346
2347 if(ieee->bHalfWirelessN24GMode == true)
2348 Reval = true;
2349 else
2350 Reval = false;
2351
2352 return Reval;
2353}
2354
2355short rtl8192_is_tx_queue_empty(struct net_device *dev)
2356{
2357 int i=0;
2358 struct r8192_priv *priv = ieee80211_priv(dev);
2359 for (i=0; i<=MGNT_QUEUE; i++)
2360 {
2361 if ((i== TXCMD_QUEUE) || (i == HCCA_QUEUE) )
2362 continue;
2363 if (skb_queue_len(&(&priv->tx_ring[i])->queue) > 0){
2364 printk("===>tx queue is not empty:%d, %d\n", i, skb_queue_len(&(&priv->tx_ring[i])->queue));
2365 return 0;
2366 }
2367 }
2368 return 1;
2369}
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07002370static void rtl8192_hw_sleep_down(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002371{
david woo65a43782009-12-22 09:40:36 -08002372 struct r8192_priv *priv = ieee80211_priv(dev);
2373 unsigned long flags = 0;
2374
2375 spin_lock_irqsave(&priv->rf_ps_lock,flags);
2376 if (priv->RFChangeInProgress) {
2377 spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
2378 RT_TRACE(COMP_RF, "rtl8192_hw_sleep_down(): RF Change in progress! \n");
2379 printk("rtl8192_hw_sleep_down(): RF Change in progress!\n");
2380 return;
2381 }
2382 spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
2383 //RT_TRACE(COMP_PS, "%s()============>come to sleep down\n", __FUNCTION__);
2384
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002385 MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS);
2386}
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07002387static void rtl8192_hw_sleep_wq (struct work_struct *work)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002388{
2389// struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq);
2390// struct ieee80211_device * ieee = (struct ieee80211_device*)
2391// container_of(work, struct ieee80211_device, watch_dog_wq);
2392 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
2393 struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_sleep_wq);
2394 struct net_device *dev = ieee->dev;
david woo65a43782009-12-22 09:40:36 -08002395
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002396 rtl8192_hw_sleep_down(dev);
2397}
david woo65a43782009-12-22 09:40:36 -08002398
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07002399static void rtl8192_hw_wakeup(struct net_device* dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002400{
david woo65a43782009-12-22 09:40:36 -08002401 struct r8192_priv *priv = ieee80211_priv(dev);
2402 unsigned long flags = 0;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002403
david woo65a43782009-12-22 09:40:36 -08002404 spin_lock_irqsave(&priv->rf_ps_lock,flags);
2405 if (priv->RFChangeInProgress) {
2406 spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
2407 RT_TRACE(COMP_RF, "rtl8192_hw_wakeup(): RF Change in progress! \n");
2408 printk("rtl8192_hw_wakeup(): RF Change in progress! schedule wake up task again\n");
2409 queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->hw_wakeup_wq,MSECS(10));//PowerSave is not supported if kernel version is below 2.6.20
2410 return;
2411 }
2412 spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
2413
2414 //RT_TRACE(COMP_PS, "%s()============>come to wake up\n", __FUNCTION__);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002415 MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002416}
david woo65a43782009-12-22 09:40:36 -08002417
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002418void rtl8192_hw_wakeup_wq (struct work_struct *work)
2419{
2420// struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq);
2421// struct ieee80211_device * ieee = (struct ieee80211_device*)
2422// container_of(work, struct ieee80211_device, watch_dog_wq);
2423 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
2424 struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_wakeup_wq);
2425 struct net_device *dev = ieee->dev;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002426 rtl8192_hw_wakeup(dev);
2427
2428}
2429
2430#define MIN_SLEEP_TIME 50
2431#define MAX_SLEEP_TIME 10000
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07002432static void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002433{
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002434 struct r8192_priv *priv = ieee80211_priv(dev);
2435
2436 u32 rb = jiffies;
2437 unsigned long flags;
2438
2439 spin_lock_irqsave(&priv->ps_lock,flags);
2440
david woo65a43782009-12-22 09:40:36 -08002441 // Writing HW register with 0 equals to disable
2442 // the timer, that is not really what we want
2443 //
2444 tl -= MSECS(8+16+7);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002445
david woo65a43782009-12-22 09:40:36 -08002446 // If the interval in witch we are requested to sleep is too
2447 // short then give up and remain awake
2448 // when we sleep after send null frame, the timer will be too short to sleep.
2449 //
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002450 if(((tl>=rb)&& (tl-rb) <= MSECS(MIN_SLEEP_TIME))
david woo65a43782009-12-22 09:40:36 -08002451 ||((rb>tl)&& (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002452 spin_unlock_irqrestore(&priv->ps_lock,flags);
david woo65a43782009-12-22 09:40:36 -08002453 printk("too short to sleep::%x, %x, %lx\n",tl, rb, MSECS(MIN_SLEEP_TIME));
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002454 return;
2455 }
2456
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002457 if(((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME)))||
david woo65a43782009-12-22 09:40:36 -08002458 ((tl < rb) && (tl>MSECS(69)) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))||
2459 ((tl<rb)&&(tl<MSECS(69))&&((tl+0xffffffff-rb)>MSECS(MAX_SLEEP_TIME)))) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002460 printk("========>too long to sleep:%x, %x, %lx\n", tl, rb, MSECS(MAX_SLEEP_TIME));
2461 spin_unlock_irqrestore(&priv->ps_lock,flags);
2462 return;
2463 }
david woo65a43782009-12-22 09:40:36 -08002464 {
2465 u32 tmp = (tl>rb)?(tl-rb):(rb-tl);
2466 queue_delayed_work(priv->ieee80211->wq,
2467 &priv->ieee80211->hw_wakeup_wq,tmp);
2468 //PowerSave not supported when kernel version less 2.6.20
2469 }
2470 queue_delayed_work(priv->ieee80211->wq,
2471 (void *)&priv->ieee80211->hw_sleep_wq,0);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002472 spin_unlock_irqrestore(&priv->ps_lock,flags);
david woo65a43782009-12-22 09:40:36 -08002473
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002474}
2475static void rtl8192_init_priv_variable(struct net_device* dev)
2476{
2477 struct r8192_priv *priv = ieee80211_priv(dev);
2478 u8 i;
david woo65a43782009-12-22 09:40:36 -08002479 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
2480
2481 // Default Halt the NIC if RF is OFF.
2482 pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC;
2483 pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_CLK_REQ;
2484 pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM;
2485 pPSC->RegRfPsLevel |= RT_RF_LPS_LEVEL_ASPM;
2486 pPSC->bLeisurePs = true;
2487 pPSC->RegMaxLPSAwakeIntvl = 5;
2488 priv->bHwRadioOff = false;
2489
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002490 priv->being_init_adapter = false;
2491 priv->txbuffsize = 1600;//1024;
2492 priv->txfwbuffersize = 4096;
2493 priv->txringcount = 64;//32;
2494 //priv->txbeaconcount = priv->txringcount;
2495 priv->txbeaconcount = 2;
2496 priv->rxbuffersize = 9100;//2048;//1024;
2497 priv->rxringcount = MAX_RX_COUNT;//64;
2498 priv->irq_enabled=0;
2499 priv->card_8192 = NIC_8192E;
2500 priv->rx_skb_complete = 1;
2501 priv->chan = 1; //set to channel 1
2502 priv->RegWirelessMode = WIRELESS_MODE_AUTO;
2503 priv->RegChannelPlan = 0xf;
2504 priv->nrxAMPDU_size = 0;
2505 priv->nrxAMPDU_aggr_num = 0;
2506 priv->last_rxdesc_tsf_high = 0;
2507 priv->last_rxdesc_tsf_low = 0;
2508 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2509 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2510 priv->ieee80211->ieee_up=0;
2511 priv->retry_rts = DEFAULT_RETRY_RTS;
2512 priv->retry_data = DEFAULT_RETRY_DATA;
2513 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2514 priv->ieee80211->rate = 110; //11 mbps
2515 priv->ieee80211->short_slot = 1;
2516 priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0;
2517 priv->bcck_in_ch14 = false;
2518 priv->bfsync_processing = false;
2519 priv->CCKPresentAttentuation = 0;
2520 priv->rfa_txpowertrackingindex = 0;
2521 priv->rfc_txpowertrackingindex = 0;
2522 priv->CckPwEnl = 6;
2523 priv->ScanDelay = 50;//for Scan TODO
2524 //added by amy for silent reset
2525 priv->ResetProgress = RESET_TYPE_NORESET;
2526 priv->bForcedSilentReset = 0;
2527 priv->bDisableNormalResetCheck = false;
2528 priv->force_reset = false;
2529 //added by amy for power save
2530 priv->RegRfOff = 0;
2531 priv->ieee80211->RfOffReason = 0;
2532 priv->RFChangeInProgress = false;
2533 priv->bHwRfOffAction = 0;
2534 priv->SetRFPowerStateInProgress = false;
2535 priv->ieee80211->PowerSaveControl.bInactivePs = true;
2536 priv->ieee80211->PowerSaveControl.bIPSModeBackup = false;
2537 //just for debug
2538 priv->txpower_checkcnt = 0;
2539 priv->thermal_readback_index =0;
2540 priv->txpower_tracking_callback_cnt = 0;
2541 priv->ccktxpower_adjustcnt_ch14 = 0;
2542 priv->ccktxpower_adjustcnt_not_ch14 = 0;
2543
2544 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2545 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2546 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2547 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2548 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE;/* |
2549 IEEE_SOFTMAC_BEACONS;*///added by amy 080604 //| //IEEE_SOFTMAC_SINGLE_QUEUE;
2550
2551 priv->ieee80211->active_scan = 1;
2552 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2553 priv->ieee80211->host_encrypt = 1;
2554 priv->ieee80211->host_decrypt = 1;
2555 //priv->ieee80211->start_send_beacons = NULL;//rtl819xusb_beacon_tx;//-by amy 080604
2556 //priv->ieee80211->stop_send_beacons = NULL;//rtl8192_beacon_stop;//-by amy 080604
2557 priv->ieee80211->start_send_beacons = rtl8192_start_beacon;//+by david 081107
2558 priv->ieee80211->stop_send_beacons = rtl8192_stop_beacon;//+by david 081107
2559 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2560 priv->ieee80211->set_chan = rtl8192_set_chan;
2561 priv->ieee80211->link_change = rtl8192_link_change;
2562 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2563 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2564 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2565 priv->ieee80211->init_wmmparam_flag = 0;
2566 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2567 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2568 priv->ieee80211->tx_headroom = sizeof(TX_FWINFO_8190PCI);
2569 priv->ieee80211->qos_support = 1;
2570 priv->ieee80211->dot11PowerSaveMode = 0;
2571 //added by WB
2572// priv->ieee80211->SwChnlByTimerHandler = rtl8192_phy_SwChnl;
2573 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2574 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2575 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2576
2577 priv->ieee80211->sta_wake_up = rtl8192_hw_wakeup;
2578// priv->ieee80211->ps_request_tx_ack = rtl8192_rq_tx_ack;
2579 priv->ieee80211->enter_sleep_state = rtl8192_hw_to_sleep;
2580 priv->ieee80211->ps_is_queue_empty = rtl8192_is_tx_queue_empty;
2581 //added by david
2582 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8190Pci;
2583 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2584 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xPci;
2585
2586 //added by amy
2587 priv->ieee80211->InitialGainHandler = InitialGain819xPci;
2588
david woo65a43782009-12-22 09:40:36 -08002589#ifdef ENABLE_IPS
2590 priv->ieee80211->ieee80211_ips_leave_wq = ieee80211_ips_leave_wq;
2591 priv->ieee80211->ieee80211_ips_leave = ieee80211_ips_leave;
2592#endif
2593#ifdef ENABLE_LPS
2594 priv->ieee80211->LeisurePSLeave = LeisurePSLeave;
2595#endif//ENABL
2596
2597 priv->ieee80211->SetHwRegHandler = rtl8192e_SetHwReg;
2598 priv->ieee80211->rtllib_ap_sec_type = rtl8192e_ap_sec_type;
2599
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002600 priv->card_type = USB;
2601 {
2602 priv->ShortRetryLimit = 0x30;
2603 priv->LongRetryLimit = 0x30;
2604 }
2605 priv->EarlyRxThreshold = 7;
2606 priv->enable_gpio0 = 0;
2607
2608 priv->TransmitConfig = 0;
2609
2610 priv->ReceiveConfig = RCR_ADD3 |
2611 RCR_AMF | RCR_ADF | //accept management/data
2612 RCR_AICV | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2613 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
2614 RCR_AAP | ((u32)7<<RCR_MXDMA_OFFSET) |
2615 ((u32)7 << RCR_FIFO_OFFSET) | RCR_ONLYERLPKT;
2616
2617 priv->irq_mask = (u32)(IMR_ROK | IMR_VODOK | IMR_VIDOK | IMR_BEDOK | IMR_BKDOK |\
2618 IMR_HCCADOK | IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK |\
2619 IMR_BDOK | IMR_RXCMDOK | IMR_TIMEOUT0 | IMR_RDU | IMR_RXFOVW |\
2620 IMR_TXFOVW | IMR_BcnInt | IMR_TBDOK | IMR_TBDER);
2621
2622 priv->AcmControl = 0;
2623 priv->pFirmware = (rt_firmware*)vmalloc(sizeof(rt_firmware));
2624 if (priv->pFirmware)
2625 memset(priv->pFirmware, 0, sizeof(rt_firmware));
2626
2627 /* rx related queue */
2628 skb_queue_head_init(&priv->rx_queue);
2629 skb_queue_head_init(&priv->skb_queue);
2630
2631 /* Tx related queue */
2632 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
2633 skb_queue_head_init(&priv->ieee80211->skb_waitQ [i]);
2634 }
2635 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
2636 skb_queue_head_init(&priv->ieee80211->skb_aggQ [i]);
2637 }
2638 priv->rf_set_chan = rtl8192_phy_SwChnl;
2639}
2640
2641//init lock here
2642static void rtl8192_init_priv_lock(struct r8192_priv* priv)
2643{
2644 spin_lock_init(&priv->tx_lock);
2645 spin_lock_init(&priv->irq_lock);//added by thomas
2646 spin_lock_init(&priv->irq_th_lock);
2647 spin_lock_init(&priv->rf_ps_lock);
2648 spin_lock_init(&priv->ps_lock);
2649 //spin_lock_init(&priv->rf_lock);
2650 sema_init(&priv->wx_sem,1);
2651 sema_init(&priv->rf_sem,1);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002652 mutex_init(&priv->mutex);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002653}
2654
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002655//init tasklet and wait_queue here. only 2.6 above kernel is considered
2656#define DRV_NAME "wlan0"
2657static void rtl8192_init_priv_task(struct net_device* dev)
2658{
2659 struct r8192_priv *priv = ieee80211_priv(dev);
2660
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002661#ifdef PF_SYNCTHREAD
2662 priv->priv_wq = create_workqueue(DRV_NAME,0);
2663#else
2664 priv->priv_wq = create_workqueue(DRV_NAME);
2665#endif
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002666
david woo65a43782009-12-22 09:40:36 -08002667#ifdef ENABLE_IPS
2668 INIT_WORK(&priv->ieee80211->ips_leave_wq, (void*)IPSLeave_wq);
2669#endif
2670
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002671// INIT_WORK(&priv->reset_wq, (void(*)(void*)) rtl8192_restart);
2672 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2673// INIT_DELAYED_WORK(&priv->watch_dog_wq, hal_dm_watchdog);
2674 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2675 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
2676 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2677 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2678 //INIT_WORK(&priv->SwChnlWorkItem, rtl8192_SwChnl_WorkItem);
2679 //INIT_WORK(&priv->SetBWModeWorkItem, rtl8192_SetBWModeWorkItem);
2680 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
2681 INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq,(void*) rtl8192_hw_wakeup_wq);
2682 INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq,(void*) rtl8192_hw_sleep_wq);
2683
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002684 tasklet_init(&priv->irq_rx_tasklet,
2685 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2686 (unsigned long)priv);
2687 tasklet_init(&priv->irq_tx_tasklet,
2688 (void(*)(unsigned long))rtl8192_irq_tx_tasklet,
2689 (unsigned long)priv);
2690 tasklet_init(&priv->irq_prepare_beacon_tasklet,
2691 (void(*)(unsigned long))rtl8192_prepare_beacon,
2692 (unsigned long)priv);
2693}
2694
2695static void rtl8192_get_eeprom_size(struct net_device* dev)
2696{
2697 u16 curCR = 0;
2698 struct r8192_priv *priv = ieee80211_priv(dev);
2699 RT_TRACE(COMP_INIT, "===========>%s()\n", __FUNCTION__);
2700 curCR = read_nic_dword(dev, EPROM_CMD);
2701 RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD, curCR);
2702 //whether need I consider BIT5?
2703 priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EPROM_93c56 : EPROM_93c46;
2704 RT_TRACE(COMP_INIT, "<===========%s(), epromtype:%d\n", __FUNCTION__, priv->epromtype);
2705}
2706
2707//used to swap endian. as ntohl & htonl are not neccessary to swap endian, so use this instead.
2708static inline u16 endian_swap(u16* data)
2709{
2710 u16 tmp = *data;
2711 *data = (tmp >> 8) | (tmp << 8);
2712 return *data;
2713}
2714
2715/*
2716 * Note: Adapter->EEPROMAddressSize should be set before this function call.
2717 * EEPROM address size can be got through GetEEPROMSize8185()
2718*/
2719static void rtl8192_read_eeprom_info(struct net_device* dev)
2720{
2721 struct r8192_priv *priv = ieee80211_priv(dev);
2722
2723 u8 tempval;
2724#ifdef RTL8192E
2725 u8 ICVer8192, ICVer8256;
2726#endif
2727 u16 i,usValue, IC_Version;
2728 u16 EEPROMId;
2729#ifdef RTL8190P
2730 u8 offset;//, tmpAFR;
2731 u8 EepromTxPower[100];
2732#endif
2733 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x01};
2734 RT_TRACE(COMP_INIT, "====> rtl8192_read_eeprom_info\n");
2735
2736
2737 // TODO: I don't know if we need to apply EF function to EEPROM read function
2738
2739 //2 Read EEPROM ID to make sure autoload is success
2740 EEPROMId = eprom_read(dev, 0);
2741 if( EEPROMId != RTL8190_EEPROM_ID )
2742 {
2743 RT_TRACE(COMP_ERR, "EEPROM ID is invalid:%x, %x\n", EEPROMId, RTL8190_EEPROM_ID);
2744 priv->AutoloadFailFlag=true;
2745 }
2746 else
2747 {
2748 priv->AutoloadFailFlag=false;
2749 }
2750
2751 //
2752 // Assign Chip Version ID
2753 //
2754 // Read IC Version && Channel Plan
2755 if(!priv->AutoloadFailFlag)
2756 {
2757 // VID, PID
2758 priv->eeprom_vid = eprom_read(dev, (EEPROM_VID >> 1));
2759 priv->eeprom_did = eprom_read(dev, (EEPROM_DID >> 1));
2760
2761 usValue = eprom_read(dev, (u16)(EEPROM_Customer_ID>>1)) >> 8 ;
2762 priv->eeprom_CustomerID = (u8)( usValue & 0xff);
2763 usValue = eprom_read(dev, (EEPROM_ICVersion_ChannelPlan>>1));
2764 priv->eeprom_ChannelPlan = usValue&0xff;
2765 IC_Version = ((usValue&0xff00)>>8);
2766
2767#ifdef RTL8190P
2768 priv->card_8192_version = (VERSION_8190)(IC_Version);
2769#else
2770 #ifdef RTL8192E
2771 ICVer8192 = (IC_Version&0xf); //bit0~3; 1:A cut, 2:B cut, 3:C cut...
2772 ICVer8256 = ((IC_Version&0xf0)>>4);//bit4~6, bit7 reserved for other RF chip; 1:A cut, 2:B cut, 3:C cut...
2773 RT_TRACE(COMP_INIT, "\nICVer8192 = 0x%x\n", ICVer8192);
2774 RT_TRACE(COMP_INIT, "\nICVer8256 = 0x%x\n", ICVer8256);
2775 if(ICVer8192 == 0x2) //B-cut
2776 {
2777 if(ICVer8256 == 0x5) //E-cut
2778 priv->card_8192_version= VERSION_8190_BE;
2779 }
2780 #endif
2781#endif
2782 switch(priv->card_8192_version)
2783 {
2784 case VERSION_8190_BD:
2785 case VERSION_8190_BE:
2786 break;
2787 default:
2788 priv->card_8192_version = VERSION_8190_BD;
2789 break;
2790 }
2791 RT_TRACE(COMP_INIT, "\nIC Version = 0x%x\n", priv->card_8192_version);
2792 }
2793 else
2794 {
2795 priv->card_8192_version = VERSION_8190_BD;
2796 priv->eeprom_vid = 0;
2797 priv->eeprom_did = 0;
2798 priv->eeprom_CustomerID = 0;
2799 priv->eeprom_ChannelPlan = 0;
2800 RT_TRACE(COMP_INIT, "\nIC Version = 0x%x\n", 0xff);
2801 }
2802
2803 RT_TRACE(COMP_INIT, "EEPROM VID = 0x%4x\n", priv->eeprom_vid);
2804 RT_TRACE(COMP_INIT, "EEPROM DID = 0x%4x\n", priv->eeprom_did);
2805 RT_TRACE(COMP_INIT,"EEPROM Customer ID: 0x%2x\n", priv->eeprom_CustomerID);
2806
2807 //2 Read Permanent MAC address
2808 if(!priv->AutoloadFailFlag)
2809 {
2810 for(i = 0; i < 6; i += 2)
2811 {
2812 usValue = eprom_read(dev, (u16) ((EEPROM_NODE_ADDRESS_BYTE_0+i)>>1));
2813 *(u16*)(&dev->dev_addr[i]) = usValue;
2814 }
2815 } else {
2816 // when auto load failed, the last address byte set to be a random one.
2817 // added by david woo.2007/11/7
2818 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002819 }
2820
H Hartley Sweeten820793c2009-12-28 19:28:11 -05002821 RT_TRACE(COMP_INIT, "Permanent Address = %pM\n", dev->dev_addr);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002822
2823 //2 TX Power Check EEPROM Fail or not
2824 if(priv->card_8192_version > VERSION_8190_BD) {
2825 priv->bTXPowerDataReadFromEEPORM = true;
2826 } else {
2827 priv->bTXPowerDataReadFromEEPORM = false;
2828 }
2829
André Goddard Rosabbc9a992009-11-14 13:09:06 -02002830 // 2007/11/15 MH 8190PCI Default=2T4R, 8192PCIE default=1T2R
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07002831 priv->rf_type = RTL819X_DEFAULT_RF_TYPE;
2832
2833 if(priv->card_8192_version > VERSION_8190_BD)
2834 {
2835 // Read RF-indication and Tx Power gain index diff of legacy to HT OFDM rate.
2836 if(!priv->AutoloadFailFlag)
2837 {
2838 tempval = (eprom_read(dev, (EEPROM_RFInd_PowerDiff>>1))) & 0xff;
2839 priv->EEPROMLegacyHTTxPowerDiff = tempval & 0xf; // bit[3:0]
2840
2841 if (tempval&0x80) //RF-indication, bit[7]
2842 priv->rf_type = RF_1T2R;
2843 else
2844 priv->rf_type = RF_2T4R;
2845 }
2846 else
2847 {
2848 priv->EEPROMLegacyHTTxPowerDiff = EEPROM_Default_LegacyHTTxPowerDiff;
2849 }
2850 RT_TRACE(COMP_INIT, "EEPROMLegacyHTTxPowerDiff = %d\n",
2851 priv->EEPROMLegacyHTTxPowerDiff);
2852
2853 // Read ThermalMeter from EEPROM
2854 if(!priv->AutoloadFailFlag)
2855 {
2856 priv->EEPROMThermalMeter = (u8)(((eprom_read(dev, (EEPROM_ThermalMeter>>1))) & 0xff00)>>8);
2857 }
2858 else
2859 {
2860 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2861 }
2862 RT_TRACE(COMP_INIT, "ThermalMeter = %d\n", priv->EEPROMThermalMeter);
2863 //vivi, for tx power track
2864 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2865
2866 if(priv->epromtype == EPROM_93c46)
2867 {
2868 // Read antenna tx power offset of B/C/D to A and CrystalCap from EEPROM
2869 if(!priv->AutoloadFailFlag)
2870 {
2871 usValue = eprom_read(dev, (EEPROM_TxPwDiff_CrystalCap>>1));
2872 priv->EEPROMAntPwDiff = (usValue&0x0fff);
2873 priv->EEPROMCrystalCap = (u8)((usValue&0xf000)>>12);
2874 }
2875 else
2876 {
2877 priv->EEPROMAntPwDiff = EEPROM_Default_AntTxPowerDiff;
2878 priv->EEPROMCrystalCap = EEPROM_Default_TxPwDiff_CrystalCap;
2879 }
2880 RT_TRACE(COMP_INIT, "EEPROMAntPwDiff = %d\n", priv->EEPROMAntPwDiff);
2881 RT_TRACE(COMP_INIT, "EEPROMCrystalCap = %d\n", priv->EEPROMCrystalCap);
2882
2883 //
2884 // Get per-channel Tx Power Level
2885 //
2886 for(i=0; i<14; i+=2)
2887 {
2888 if(!priv->AutoloadFailFlag)
2889 {
2890 usValue = eprom_read(dev, (u16) ((EEPROM_TxPwIndex_CCK+i)>>1) );
2891 }
2892 else
2893 {
2894 usValue = EEPROM_Default_TxPower;
2895 }
2896 *((u16*)(&priv->EEPROMTxPowerLevelCCK[i])) = usValue;
2897 RT_TRACE(COMP_INIT,"CCK Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK[i]);
2898 RT_TRACE(COMP_INIT, "CCK Tx Power Level, Index %d = 0x%02x\n", i+1, priv->EEPROMTxPowerLevelCCK[i+1]);
2899 }
2900 for(i=0; i<14; i+=2)
2901 {
2902 if(!priv->AutoloadFailFlag)
2903 {
2904 usValue = eprom_read(dev, (u16) ((EEPROM_TxPwIndex_OFDM_24G+i)>>1) );
2905 }
2906 else
2907 {
2908 usValue = EEPROM_Default_TxPower;
2909 }
2910 *((u16*)(&priv->EEPROMTxPowerLevelOFDM24G[i])) = usValue;
2911 RT_TRACE(COMP_INIT, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelOFDM24G[i]);
2912 RT_TRACE(COMP_INIT, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i+1, priv->EEPROMTxPowerLevelOFDM24G[i+1]);
2913 }
2914 }
2915 else if(priv->epromtype== EPROM_93c56)
2916 {
2917 #ifdef RTL8190P
2918 // Read CrystalCap from EEPROM
2919 if(!priv->AutoloadFailFlag)
2920 {
2921 priv->EEPROMAntPwDiff = EEPROM_Default_AntTxPowerDiff;
2922 priv->EEPROMCrystalCap = (u8)(((eprom_read(dev, (EEPROM_C56_CrystalCap>>1))) & 0xf000)>>12);
2923 }
2924 else
2925 {
2926 priv->EEPROMAntPwDiff = EEPROM_Default_AntTxPowerDiff;
2927 priv->EEPROMCrystalCap = EEPROM_Default_TxPwDiff_CrystalCap;
2928 }
2929 RT_TRACE(COMP_INIT,"EEPROMAntPwDiff = %d\n", priv->EEPROMAntPwDiff);
2930 RT_TRACE(COMP_INIT, "EEPROMCrystalCap = %d\n", priv->EEPROMCrystalCap);
2931
2932 // Get Tx Power Level by Channel
2933 if(!priv->AutoloadFailFlag)
2934 {
2935 // Read Tx power of Channel 1 ~ 14 from EEPROM.
2936 for(i = 0; i < 12; i+=2)
2937 {
2938 if (i <6)
2939 offset = EEPROM_C56_RfA_CCK_Chnl1_TxPwIndex + i;
2940 else
2941 offset = EEPROM_C56_RfC_CCK_Chnl1_TxPwIndex + i - 6;
2942 usValue = eprom_read(dev, (offset>>1));
2943 *((u16*)(&EepromTxPower[i])) = usValue;
2944 }
2945
2946 for(i = 0; i < 12; i++)
2947 {
2948 if (i <= 2)
2949 priv->EEPROMRfACCKChnl1TxPwLevel[i] = EepromTxPower[i];
2950 else if ((i >=3 )&&(i <= 5))
2951 priv->EEPROMRfAOfdmChnlTxPwLevel[i-3] = EepromTxPower[i];
2952 else if ((i >=6 )&&(i <= 8))
2953 priv->EEPROMRfCCCKChnl1TxPwLevel[i-6] = EepromTxPower[i];
2954 else
2955 priv->EEPROMRfCOfdmChnlTxPwLevel[i-9] = EepromTxPower[i];
2956 }
2957 }
2958 else
2959 {
2960 priv->EEPROMRfACCKChnl1TxPwLevel[0] = EEPROM_Default_TxPowerLevel;
2961 priv->EEPROMRfACCKChnl1TxPwLevel[1] = EEPROM_Default_TxPowerLevel;
2962 priv->EEPROMRfACCKChnl1TxPwLevel[2] = EEPROM_Default_TxPowerLevel;
2963
2964 priv->EEPROMRfAOfdmChnlTxPwLevel[0] = EEPROM_Default_TxPowerLevel;
2965 priv->EEPROMRfAOfdmChnlTxPwLevel[1] = EEPROM_Default_TxPowerLevel;
2966 priv->EEPROMRfAOfdmChnlTxPwLevel[2] = EEPROM_Default_TxPowerLevel;
2967
2968 priv->EEPROMRfCCCKChnl1TxPwLevel[0] = EEPROM_Default_TxPowerLevel;
2969 priv->EEPROMRfCCCKChnl1TxPwLevel[1] = EEPROM_Default_TxPowerLevel;
2970 priv->EEPROMRfCCCKChnl1TxPwLevel[2] = EEPROM_Default_TxPowerLevel;
2971
2972 priv->EEPROMRfCOfdmChnlTxPwLevel[0] = EEPROM_Default_TxPowerLevel;
2973 priv->EEPROMRfCOfdmChnlTxPwLevel[1] = EEPROM_Default_TxPowerLevel;
2974 priv->EEPROMRfCOfdmChnlTxPwLevel[2] = EEPROM_Default_TxPowerLevel;
2975 }
2976 RT_TRACE(COMP_INIT, "priv->EEPROMRfACCKChnl1TxPwLevel[0] = 0x%x\n", priv->EEPROMRfACCKChnl1TxPwLevel[0]);
2977 RT_TRACE(COMP_INIT, "priv->EEPROMRfACCKChnl1TxPwLevel[1] = 0x%x\n", priv->EEPROMRfACCKChnl1TxPwLevel[1]);
2978 RT_TRACE(COMP_INIT, "priv->EEPROMRfACCKChnl1TxPwLevel[2] = 0x%x\n", priv->EEPROMRfACCKChnl1TxPwLevel[2]);
2979 RT_TRACE(COMP_INIT, "priv->EEPROMRfAOfdmChnlTxPwLevel[0] = 0x%x\n", priv->EEPROMRfAOfdmChnlTxPwLevel[0]);
2980 RT_TRACE(COMP_INIT, "priv->EEPROMRfAOfdmChnlTxPwLevel[1] = 0x%x\n", priv->EEPROMRfAOfdmChnlTxPwLevel[1]);
2981 RT_TRACE(COMP_INIT, "priv->EEPROMRfAOfdmChnlTxPwLevel[2] = 0x%x\n", priv->EEPROMRfAOfdmChnlTxPwLevel[2]);
2982 RT_TRACE(COMP_INIT, "priv->EEPROMRfCCCKChnl1TxPwLevel[0] = 0x%x\n", priv->EEPROMRfCCCKChnl1TxPwLevel[0]);
2983 RT_TRACE(COMP_INIT, "priv->EEPROMRfCCCKChnl1TxPwLevel[1] = 0x%x\n", priv->EEPROMRfCCCKChnl1TxPwLevel[1]);
2984 RT_TRACE(COMP_INIT, "priv->EEPROMRfCCCKChnl1TxPwLevel[2] = 0x%x\n", priv->EEPROMRfCCCKChnl1TxPwLevel[2]);
2985 RT_TRACE(COMP_INIT, "priv->EEPROMRfCOfdmChnlTxPwLevel[0] = 0x%x\n", priv->EEPROMRfCOfdmChnlTxPwLevel[0]);
2986 RT_TRACE(COMP_INIT, "priv->EEPROMRfCOfdmChnlTxPwLevel[1] = 0x%x\n", priv->EEPROMRfCOfdmChnlTxPwLevel[1]);
2987 RT_TRACE(COMP_INIT, "priv->EEPROMRfCOfdmChnlTxPwLevel[2] = 0x%x\n", priv->EEPROMRfCOfdmChnlTxPwLevel[2]);
2988#endif
2989
2990 }
2991 //
2992 // Update HAL variables.
2993 //
2994 if(priv->epromtype == EPROM_93c46)
2995 {
2996 for(i=0; i<14; i++)
2997 {
2998 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK[i];
2999 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[i];
3000 }
3001 priv->LegacyHTTxPowerDiff = priv->EEPROMLegacyHTTxPowerDiff;
3002 // Antenna B gain offset to antenna A, bit0~3
3003 priv->AntennaTxPwDiff[0] = (priv->EEPROMAntPwDiff & 0xf);
3004 // Antenna C gain offset to antenna A, bit4~7
3005 priv->AntennaTxPwDiff[1] = ((priv->EEPROMAntPwDiff & 0xf0)>>4);
3006 // Antenna D gain offset to antenna A, bit8~11
3007 priv->AntennaTxPwDiff[2] = ((priv->EEPROMAntPwDiff & 0xf00)>>8);
3008 // CrystalCap, bit12~15
3009 priv->CrystalCap = priv->EEPROMCrystalCap;
3010 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
3011 priv->ThermalMeter[0] = (priv->EEPROMThermalMeter & 0xf);
3012 priv->ThermalMeter[1] = ((priv->EEPROMThermalMeter & 0xf0)>>4);
3013 }
3014 else if(priv->epromtype == EPROM_93c56)
3015 {
3016 //char cck_pwr_diff_a=0, cck_pwr_diff_c=0;
3017
3018 //cck_pwr_diff_a = pHalData->EEPROMRfACCKChnl7TxPwLevel - pHalData->EEPROMRfAOfdmChnlTxPwLevel[1];
3019 //cck_pwr_diff_c = pHalData->EEPROMRfCCCKChnl7TxPwLevel - pHalData->EEPROMRfCOfdmChnlTxPwLevel[1];
3020 for(i=0; i<3; i++) // channel 1~3 use the same Tx Power Level.
3021 {
3022 priv->TxPowerLevelCCK_A[i] = priv->EEPROMRfACCKChnl1TxPwLevel[0];
3023 priv->TxPowerLevelOFDM24G_A[i] = priv->EEPROMRfAOfdmChnlTxPwLevel[0];
3024 priv->TxPowerLevelCCK_C[i] = priv->EEPROMRfCCCKChnl1TxPwLevel[0];
3025 priv->TxPowerLevelOFDM24G_C[i] = priv->EEPROMRfCOfdmChnlTxPwLevel[0];
3026 }
3027 for(i=3; i<9; i++) // channel 4~9 use the same Tx Power Level
3028 {
3029 priv->TxPowerLevelCCK_A[i] = priv->EEPROMRfACCKChnl1TxPwLevel[1];
3030 priv->TxPowerLevelOFDM24G_A[i] = priv->EEPROMRfAOfdmChnlTxPwLevel[1];
3031 priv->TxPowerLevelCCK_C[i] = priv->EEPROMRfCCCKChnl1TxPwLevel[1];
3032 priv->TxPowerLevelOFDM24G_C[i] = priv->EEPROMRfCOfdmChnlTxPwLevel[1];
3033 }
3034 for(i=9; i<14; i++) // channel 10~14 use the same Tx Power Level
3035 {
3036 priv->TxPowerLevelCCK_A[i] = priv->EEPROMRfACCKChnl1TxPwLevel[2];
3037 priv->TxPowerLevelOFDM24G_A[i] = priv->EEPROMRfAOfdmChnlTxPwLevel[2];
3038 priv->TxPowerLevelCCK_C[i] = priv->EEPROMRfCCCKChnl1TxPwLevel[2];
3039 priv->TxPowerLevelOFDM24G_C[i] = priv->EEPROMRfCOfdmChnlTxPwLevel[2];
3040 }
3041 for(i=0; i<14; i++)
3042 RT_TRACE(COMP_INIT, "priv->TxPowerLevelCCK_A[%d] = 0x%x\n", i, priv->TxPowerLevelCCK_A[i]);
3043 for(i=0; i<14; i++)
3044 RT_TRACE(COMP_INIT,"priv->TxPowerLevelOFDM24G_A[%d] = 0x%x\n", i, priv->TxPowerLevelOFDM24G_A[i]);
3045 for(i=0; i<14; i++)
3046 RT_TRACE(COMP_INIT, "priv->TxPowerLevelCCK_C[%d] = 0x%x\n", i, priv->TxPowerLevelCCK_C[i]);
3047 for(i=0; i<14; i++)
3048 RT_TRACE(COMP_INIT, "priv->TxPowerLevelOFDM24G_C[%d] = 0x%x\n", i, priv->TxPowerLevelOFDM24G_C[i]);
3049 priv->LegacyHTTxPowerDiff = priv->EEPROMLegacyHTTxPowerDiff;
3050 priv->AntennaTxPwDiff[0] = 0;
3051 priv->AntennaTxPwDiff[1] = 0;
3052 priv->AntennaTxPwDiff[2] = 0;
3053 priv->CrystalCap = priv->EEPROMCrystalCap;
3054 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
3055 priv->ThermalMeter[0] = (priv->EEPROMThermalMeter & 0xf);
3056 priv->ThermalMeter[1] = ((priv->EEPROMThermalMeter & 0xf0)>>4);
3057 }
3058 }
3059
3060 if(priv->rf_type == RF_1T2R)
3061 {
3062 RT_TRACE(COMP_INIT, "\n1T2R config\n");
3063 }
3064 else if (priv->rf_type == RF_2T4R)
3065 {
3066 RT_TRACE(COMP_INIT, "\n2T4R config\n");
3067 }
3068
3069 // 2008/01/16 MH We can only know RF type in the function. So we have to init
3070 // DIG RATR table again.
3071 init_rate_adaptive(dev);
3072
3073 //1 Make a copy for following variables and we can change them if we want
3074
3075 priv->rf_chip= RF_8256;
3076
3077 if(priv->RegChannelPlan == 0xf)
3078 {
3079 priv->ChannelPlan = priv->eeprom_ChannelPlan;
3080 }
3081 else
3082 {
3083 priv->ChannelPlan = priv->RegChannelPlan;
3084 }
3085
3086 //
3087 // Used PID and DID to Set CustomerID
3088 //
3089 if( priv->eeprom_vid == 0x1186 && priv->eeprom_did == 0x3304 )
3090 {
3091 priv->CustomerID = RT_CID_DLINK;
3092 }
3093
3094 switch(priv->eeprom_CustomerID)
3095 {
3096 case EEPROM_CID_DEFAULT:
3097 priv->CustomerID = RT_CID_DEFAULT;
3098 break;
3099 case EEPROM_CID_CAMEO:
3100 priv->CustomerID = RT_CID_819x_CAMEO;
3101 break;
3102 case EEPROM_CID_RUNTOP:
3103 priv->CustomerID = RT_CID_819x_RUNTOP;
3104 break;
3105 case EEPROM_CID_NetCore:
3106 priv->CustomerID = RT_CID_819x_Netcore;
3107 break;
3108 case EEPROM_CID_TOSHIBA: // Merge by Jacken, 2008/01/31
3109 priv->CustomerID = RT_CID_TOSHIBA;
3110 if(priv->eeprom_ChannelPlan&0x80)
3111 priv->ChannelPlan = priv->eeprom_ChannelPlan&0x7f;
3112 else
3113 priv->ChannelPlan = 0x0;
3114 RT_TRACE(COMP_INIT, "Toshiba ChannelPlan = 0x%x\n",
3115 priv->ChannelPlan);
3116 break;
3117 case EEPROM_CID_Nettronix:
3118 priv->ScanDelay = 100; //cosa add for scan
3119 priv->CustomerID = RT_CID_Nettronix;
3120 break;
3121 case EEPROM_CID_Pronet:
3122 priv->CustomerID = RT_CID_PRONET;
3123 break;
3124 case EEPROM_CID_DLINK:
3125 priv->CustomerID = RT_CID_DLINK;
3126 break;
3127
3128 case EEPROM_CID_WHQL:
3129 //Adapter->bInHctTest = TRUE;//do not supported
3130
3131 //priv->bSupportTurboMode = FALSE;
3132 //priv->bAutoTurboBy8186 = FALSE;
3133
3134 //pMgntInfo->PowerSaveControl.bInactivePs = FALSE;
3135 //pMgntInfo->PowerSaveControl.bIPSModeBackup = FALSE;
3136 //pMgntInfo->PowerSaveControl.bLeisurePs = FALSE;
3137
3138 break;
3139 default:
3140 // value from RegCustomerID
3141 break;
3142 }
3143
3144 //Avoid the channel plan array overflow, by Bruce, 2007-08-27.
3145 if(priv->ChannelPlan > CHANNEL_PLAN_LEN - 1)
3146 priv->ChannelPlan = 0; //FCC
3147
3148 switch(priv->CustomerID)
3149 {
3150 case RT_CID_DEFAULT:
3151 #ifdef RTL8190P
3152 priv->LedStrategy = HW_LED;
3153 #else
3154 #ifdef RTL8192E
3155 priv->LedStrategy = SW_LED_MODE1;
3156 #endif
3157 #endif
3158 break;
3159
3160 case RT_CID_819x_CAMEO:
3161 priv->LedStrategy = SW_LED_MODE2;
3162 break;
3163
3164 case RT_CID_819x_RUNTOP:
3165 priv->LedStrategy = SW_LED_MODE3;
3166 break;
3167
3168 case RT_CID_819x_Netcore:
3169 priv->LedStrategy = SW_LED_MODE4;
3170 break;
3171
3172 case RT_CID_Nettronix:
3173 priv->LedStrategy = SW_LED_MODE5;
3174 break;
3175
3176 case RT_CID_PRONET:
3177 priv->LedStrategy = SW_LED_MODE6;
3178 break;
3179
3180 case RT_CID_TOSHIBA: //Modify by Jacken 2008/01/31
3181 // Do nothing.
3182 //break;
3183
3184 default:
3185 #ifdef RTL8190P
3186 priv->LedStrategy = HW_LED;
3187 #else
3188 #ifdef RTL8192E
3189 priv->LedStrategy = SW_LED_MODE1;
3190 #endif
3191 #endif
3192 break;
3193 }
david woo65a43782009-12-22 09:40:36 -08003194
3195
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003196 if( priv->eeprom_vid == 0x1186 && priv->eeprom_did == 0x3304)
david woo65a43782009-12-22 09:40:36 -08003197 priv->ieee80211->bSupportRemoteWakeUp = true;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003198 else
david woo65a43782009-12-22 09:40:36 -08003199 priv->ieee80211->bSupportRemoteWakeUp = false;
3200
3201
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003202 RT_TRACE(COMP_INIT, "RegChannelPlan(%d)\n", priv->RegChannelPlan);
3203 RT_TRACE(COMP_INIT, "ChannelPlan = %d \n", priv->ChannelPlan);
3204 RT_TRACE(COMP_INIT, "LedStrategy = %d \n", priv->LedStrategy);
3205 RT_TRACE(COMP_TRACE, "<==== ReadAdapterInfo\n");
3206
3207 return ;
3208}
3209
3210
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07003211static short rtl8192_get_channel_map(struct net_device * dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003212{
3213 struct r8192_priv *priv = ieee80211_priv(dev);
3214#ifdef ENABLE_DOT11D
3215 if(priv->ChannelPlan> COUNTRY_CODE_GLOBAL_DOMAIN){
3216 printk("rtl8180_init:Error channel plan! Set to default.\n");
3217 priv->ChannelPlan= 0;
3218 }
3219 RT_TRACE(COMP_INIT, "Channel plan is %d\n",priv->ChannelPlan);
3220
3221 rtl819x_set_channel_map(priv->ChannelPlan, priv);
3222#else
3223 int ch,i;
3224 //Set Default Channel Plan
3225 if(!channels){
3226 DMESG("No channels, aborting");
3227 return -1;
3228 }
3229 ch=channels;
3230 priv->ChannelPlan= 0;//hikaru
3231 // set channels 1..14 allowed in given locale
3232 for (i=1; i<=14; i++) {
3233 (priv->ieee80211->channel_map)[i] = (u8)(ch & 0x01);
3234 ch >>= 1;
3235 }
3236#endif
3237 return 0;
3238}
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07003239
3240static short rtl8192_init(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003241{
3242 struct r8192_priv *priv = ieee80211_priv(dev);
3243 memset(&(priv->stats),0,sizeof(struct Stats));
3244 rtl8192_init_priv_variable(dev);
3245 rtl8192_init_priv_lock(priv);
3246 rtl8192_init_priv_task(dev);
3247 rtl8192_get_eeprom_size(dev);
3248 rtl8192_read_eeprom_info(dev);
3249 rtl8192_get_channel_map(dev);
3250 init_hal_dm(dev);
3251 init_timer(&priv->watch_dog_timer);
3252 priv->watch_dog_timer.data = (unsigned long)dev;
3253 priv->watch_dog_timer.function = watch_dog_timer_callback;
3254#if defined(IRQF_SHARED)
3255 if(request_irq(dev->irq, (void*)rtl8192_interrupt, IRQF_SHARED, dev->name, dev)){
3256#else
3257 if(request_irq(dev->irq, (void *)rtl8192_interrupt, SA_SHIRQ, dev->name, dev)){
3258#endif
3259 printk("Error allocating IRQ %d",dev->irq);
3260 return -1;
3261 }else{
3262 priv->irq=dev->irq;
3263 printk("IRQ %d",dev->irq);
3264 }
3265 if(rtl8192_pci_initdescring(dev)!=0){
3266 printk("Endopoints initialization failed");
3267 return -1;
3268 }
3269
3270 //rtl8192_rx_enable(dev);
3271 //rtl8192_adapter_start(dev);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003272 return 0;
3273}
3274
3275/******************************************************************************
3276 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
3277 * not to do all the hw config as its name says
3278 * input: net_device dev
3279 * output: none
3280 * return: none
3281 * notice: This part need to modified according to the rate set we filtered
3282 * ****************************************************************************/
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07003283static void rtl8192_hwconfig(struct net_device* dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003284{
3285 u32 regRATR = 0, regRRSR = 0;
3286 u8 regBwOpMode = 0, regTmp = 0;
3287 struct r8192_priv *priv = ieee80211_priv(dev);
3288
3289// Set RRSR, RATR, and BW_OPMODE registers
3290 //
3291 switch(priv->ieee80211->mode)
3292 {
3293 case WIRELESS_MODE_B:
3294 regBwOpMode = BW_OPMODE_20MHZ;
3295 regRATR = RATE_ALL_CCK;
3296 regRRSR = RATE_ALL_CCK;
3297 break;
3298 case WIRELESS_MODE_A:
3299 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
3300 regRATR = RATE_ALL_OFDM_AG;
3301 regRRSR = RATE_ALL_OFDM_AG;
3302 break;
3303 case WIRELESS_MODE_G:
3304 regBwOpMode = BW_OPMODE_20MHZ;
3305 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3306 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3307 break;
3308 case WIRELESS_MODE_AUTO:
3309 case WIRELESS_MODE_N_24G:
3310 // It support CCK rate by default.
3311 // CCK rate will be filtered out only when associated AP does not support it.
3312 regBwOpMode = BW_OPMODE_20MHZ;
3313 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
3314 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3315 break;
3316 case WIRELESS_MODE_N_5G:
3317 regBwOpMode = BW_OPMODE_5G;
3318 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
3319 regRRSR = RATE_ALL_OFDM_AG;
3320 break;
3321 }
3322
3323 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
3324 {
3325 u32 ratr_value = 0;
3326 ratr_value = regRATR;
3327 if (priv->rf_type == RF_1T2R)
3328 {
3329 ratr_value &= ~(RATE_ALL_OFDM_2SS);
3330 }
3331 write_nic_dword(dev, RATR0, ratr_value);
3332 write_nic_byte(dev, UFWP, 1);
3333 }
3334 regTmp = read_nic_byte(dev, 0x313);
3335 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
3336 write_nic_dword(dev, RRSR, regRRSR);
3337
3338 //
3339 // Set Retry Limit here
3340 //
3341 write_nic_word(dev, RETRY_LIMIT,
3342 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT | \
3343 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
3344 // Set Contention Window here
3345
3346 // Set Tx AGC
3347
3348 // Set Tx Antenna including Feedback control
3349
3350 // Set Auto Rate fallback control
3351
3352
3353}
3354
3355
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07003356static RT_STATUS rtl8192_adapter_start(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003357{
3358 struct r8192_priv *priv = ieee80211_priv(dev);
3359// struct ieee80211_device *ieee = priv->ieee80211;
3360 u32 ulRegRead;
3361 RT_STATUS rtStatus = RT_STATUS_SUCCESS;
3362// static char szMACPHYRegFile[] = RTL819X_PHY_MACPHY_REG;
3363// static char szMACPHYRegPGFile[] = RTL819X_PHY_MACPHY_REG_PG;
3364 //u8 eRFPath;
3365 u8 tmpvalue;
3366#ifdef RTL8192E
3367 u8 ICVersion,SwitchingRegulatorOutput;
3368#endif
3369 bool bfirmwareok = true;
3370#ifdef RTL8190P
3371 u8 ucRegRead;
3372#endif
3373 u32 tmpRegA, tmpRegC, TempCCk;
3374 int i =0;
3375// u32 dwRegRead = 0;
3376
3377 RT_TRACE(COMP_INIT, "====>%s()\n", __FUNCTION__);
3378 priv->being_init_adapter = true;
3379 rtl8192_pci_resetdescring(dev);
3380 // 2007/11/02 MH Before initalizing RF. We can not use FW to do RF-R/W.
3381 priv->Rf_Mode = RF_OP_By_SW_3wire;
3382#ifdef RTL8192E
3383 //dPLL on
3384 if(priv->ResetProgress == RESET_TYPE_NORESET)
3385 {
3386 write_nic_byte(dev, ANAPAR, 0x37);
3387 // Accordign to designer's explain, LBUS active will never > 10ms. We delay 10ms
3388 // Joseph increae the time to prevent firmware download fail
3389 mdelay(500);
3390 }
3391#endif
3392 //PlatformSleepUs(10000);
3393 // For any kind of InitializeAdapter process, we shall use system now!!
3394 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
3395
3396 // Set to eRfoff in order not to count receive count.
3397 if(priv->RegRfOff == TRUE)
3398 priv->ieee80211->eRFPowerState = eRfOff;
3399
3400 //
3401 //3 //Config CPUReset Register
3402 //3//
3403 //3 Firmware Reset Or Not
3404 ulRegRead = read_nic_dword(dev, CPU_GEN);
3405 if(priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
3406 { //called from MPInitialized. do nothing
3407 ulRegRead |= CPU_GEN_SYSTEM_RESET;
3408 }else if(priv->pFirmware->firmware_status == FW_STATUS_5_READY)
3409 ulRegRead |= CPU_GEN_FIRMWARE_RESET; // Called from MPReset
3410 else
3411 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __FUNCTION__, priv->pFirmware->firmware_status);
3412
3413#ifdef RTL8190P
3414 //2008.06.03, for WOL 90 hw bug
3415 ulRegRead &= (~(CPU_GEN_GPIO_UART));
3416#endif
3417
3418 write_nic_dword(dev, CPU_GEN, ulRegRead);
3419 //mdelay(100);
3420
3421#ifdef RTL8192E
3422
3423 //3//
3424 //3 //Fix the issue of E-cut high temperature issue
3425 //3//
3426 // TODO: E cut only
3427 ICVersion = read_nic_byte(dev, IC_VERRSION);
3428 if(ICVersion >= 0x4) //E-cut only
3429 {
3430 // HW SD suggest that we should not wirte this register too often, so driver
3431 // should readback this register. This register will be modified only when
3432 // power on reset
3433 SwitchingRegulatorOutput = read_nic_byte(dev, SWREGULATOR);
3434 if(SwitchingRegulatorOutput != 0xb8)
3435 {
3436 write_nic_byte(dev, SWREGULATOR, 0xa8);
3437 mdelay(1);
3438 write_nic_byte(dev, SWREGULATOR, 0xb8);
3439 }
3440 }
3441#endif
3442
3443
3444 //3//
3445 //3// Initialize BB before MAC
3446 //3//
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003447 RT_TRACE(COMP_INIT, "BB Config Start!\n");
3448 rtStatus = rtl8192_BBConfig(dev);
3449 if(rtStatus != RT_STATUS_SUCCESS)
3450 {
3451 RT_TRACE(COMP_ERR, "BB Config failed\n");
3452 return rtStatus;
3453 }
3454 RT_TRACE(COMP_INIT,"BB Config Finished!\n");
3455
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003456 //3//Set Loopback mode or Normal mode
3457 //3//
3458 //2006.12.13 by emily. Note!We should not merge these two CPU_GEN register writings
3459 // because setting of System_Reset bit reset MAC to default transmission mode.
3460 //Loopback mode or not
3461 priv->LoopbackMode = RTL819X_NO_LOOPBACK;
3462 //priv->LoopbackMode = RTL819X_MAC_LOOPBACK;
3463 if(priv->ResetProgress == RESET_TYPE_NORESET)
3464 {
3465 ulRegRead = read_nic_dword(dev, CPU_GEN);
3466 if(priv->LoopbackMode == RTL819X_NO_LOOPBACK)
3467 {
3468 ulRegRead = ((ulRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
3469 }
3470 else if (priv->LoopbackMode == RTL819X_MAC_LOOPBACK )
3471 {
3472 ulRegRead |= CPU_CCK_LOOPBACK;
3473 }
3474 else
3475 {
3476 RT_TRACE(COMP_ERR,"Serious error: wrong loopback mode setting\n");
3477 }
3478
3479 //2008.06.03, for WOL
3480 //ulRegRead &= (~(CPU_GEN_GPIO_UART));
3481 write_nic_dword(dev, CPU_GEN, ulRegRead);
3482
3483 // 2006.11.29. After reset cpu, we sholud wait for a second, otherwise, it may fail to write registers. Emily
3484 udelay(500);
3485 }
3486 //3Set Hardware(Do nothing now)
3487 rtl8192_hwconfig(dev);
3488 //2=======================================================
3489 // Common Setting for all of the FPGA platform. (part 1)
3490 //2=======================================================
3491 // If there is changes, please make sure it applies to all of the FPGA version
3492 //3 Turn on Tx/Rx
3493 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
3494
3495 //2Set Tx dma burst
3496#ifdef RTL8190P
3497 write_nic_byte(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) | \
3498 (MXDMA2_NoLimit<<MXDMA2_TX_SHIFT) | \
3499 (1<<MULRW_SHIFT)));
3500#else
3501 #ifdef RTL8192E
3502 write_nic_byte(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) |\
3503 (MXDMA2_NoLimit<<MXDMA2_TX_SHIFT) ));
3504 #endif
3505#endif
3506 //set IDR0 here
3507 write_nic_dword(dev, MAC0, ((u32*)dev->dev_addr)[0]);
3508 write_nic_word(dev, MAC4, ((u16*)(dev->dev_addr + 4))[0]);
3509 //set RCR
3510 write_nic_dword(dev, RCR, priv->ReceiveConfig);
3511
3512 //3 Initialize Number of Reserved Pages in Firmware Queue
3513 #ifdef TO_DO_LIST
3514 if(priv->bInHctTest)
3515 {
3516 PlatformEFIOWrite4Byte(Adapter, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM << RSVD_FW_QUEUE_PAGE_BK_SHIFT |\
3517 NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM << RSVD_FW_QUEUE_PAGE_BE_SHIFT | \
3518 NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM << RSVD_FW_QUEUE_PAGE_VI_SHIFT | \
3519 NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
3520 PlatformEFIOWrite4Byte(Adapter, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
3521 PlatformEFIOWrite4Byte(Adapter, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW| \
3522 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT|\
3523 NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM<<RSVD_FW_QUEUE_PAGE_PUB_SHIFT);
3524 }
3525 else
3526 #endif
3527 {
3528 write_nic_dword(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << RSVD_FW_QUEUE_PAGE_BK_SHIFT |\
3529 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT | \
3530 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT | \
3531 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
3532 write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
3533 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW| \
3534 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT|\
3535 NUM_OF_PAGE_IN_FW_QUEUE_PUB<<RSVD_FW_QUEUE_PAGE_PUB_SHIFT);
3536 }
3537
3538 rtl8192_tx_enable(dev);
3539 rtl8192_rx_enable(dev);
3540 //3Set Response Rate Setting Register
3541 // CCK rate is supported by default.
3542 // CCK rate will be filtered out only when associated AP does not support it.
3543 ulRegRead = (0xFFF00000 & read_nic_dword(dev, RRSR)) | RATE_ALL_OFDM_AG | RATE_ALL_CCK;
3544 write_nic_dword(dev, RRSR, ulRegRead);
3545 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
3546
3547 //2Set AckTimeout
3548 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
3549 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
3550
3551 //rtl8192_actset_wirelessmode(dev,priv->RegWirelessMode);
3552 if(priv->ResetProgress == RESET_TYPE_NORESET)
3553 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
3554 //-----------------------------------------------------------------------------
3555 // Set up security related. 070106, by rcnjko:
3556 // 1. Clear all H/W keys.
3557 // 2. Enable H/W encryption/decryption.
3558 //-----------------------------------------------------------------------------
3559 CamResetAllEntry(dev);
3560 {
3561 u8 SECR_value = 0x0;
3562 SECR_value |= SCR_TxEncEnable;
3563 SECR_value |= SCR_RxDecEnable;
3564 SECR_value |= SCR_NoSKMC;
3565 write_nic_byte(dev, SECR, SECR_value);
3566 }
3567 //3Beacon related
3568 write_nic_word(dev, ATIMWND, 2);
3569 write_nic_word(dev, BCN_INTERVAL, 100);
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07003570 for (i=0; i<QOS_QUEUE_NUM; i++)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003571 write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003572 //
3573 // Switching regulator controller: This is set temporarily.
3574 // It's not sure if this can be removed in the future.
3575 // PJ advised to leave it by default.
3576 //
3577 write_nic_byte(dev, 0xbe, 0xc0);
3578
3579 //2=======================================================
3580 // Set PHY related configuration defined in MAC register bank
3581 //2=======================================================
3582 rtl8192_phy_configmac(dev);
3583
3584 if (priv->card_8192_version > (u8) VERSION_8190_BD) {
3585 rtl8192_phy_getTxPower(dev);
3586 rtl8192_phy_setTxPower(dev, priv->chan);
3587 }
3588
3589 //if D or C cut
3590 tmpvalue = read_nic_byte(dev, IC_VERRSION);
3591 priv->IC_Cut = tmpvalue;
3592 RT_TRACE(COMP_INIT, "priv->IC_Cut = 0x%x\n", priv->IC_Cut);
3593 if(priv->IC_Cut >= IC_VersionCut_D)
3594 {
3595 //pHalData->bDcut = TRUE;
3596 if(priv->IC_Cut == IC_VersionCut_D)
3597 RT_TRACE(COMP_INIT, "D-cut\n");
3598 if(priv->IC_Cut == IC_VersionCut_E)
3599 {
3600 RT_TRACE(COMP_INIT, "E-cut\n");
3601 // HW SD suggest that we should not wirte this register too often, so driver
3602 // should readback this register. This register will be modified only when
3603 // power on reset
3604 }
3605 }
3606 else
3607 {
3608 //pHalData->bDcut = FALSE;
3609 RT_TRACE(COMP_INIT, "Before C-cut\n");
3610 }
3611
3612#if 1
3613 //Firmware download
3614 RT_TRACE(COMP_INIT, "Load Firmware!\n");
3615 bfirmwareok = init_firmware(dev);
3616 if(bfirmwareok != true) {
3617 rtStatus = RT_STATUS_FAILURE;
3618 return rtStatus;
3619 }
3620 RT_TRACE(COMP_INIT, "Load Firmware finished!\n");
3621#endif
3622 //RF config
3623 if(priv->ResetProgress == RESET_TYPE_NORESET)
3624 {
3625 RT_TRACE(COMP_INIT, "RF Config Started!\n");
3626 rtStatus = rtl8192_phy_RFConfig(dev);
3627 if(rtStatus != RT_STATUS_SUCCESS)
3628 {
3629 RT_TRACE(COMP_ERR, "RF Config failed\n");
3630 return rtStatus;
3631 }
3632 RT_TRACE(COMP_INIT, "RF Config Finished!\n");
3633 }
3634 rtl8192_phy_updateInitGain(dev);
3635
3636 /*---- Set CCK and OFDM Block "ON"----*/
3637 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3638 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3639
3640#ifdef RTL8192E
3641 //Enable Led
3642 write_nic_byte(dev, 0x87, 0x0);
3643#endif
3644#ifdef RTL8190P
3645 //2008.06.03, for WOL
3646 ucRegRead = read_nic_byte(dev, GPE);
3647 ucRegRead |= BIT0;
3648 write_nic_byte(dev, GPE, ucRegRead);
3649
3650 ucRegRead = read_nic_byte(dev, GPO);
3651 ucRegRead &= ~BIT0;
3652 write_nic_byte(dev, GPO, ucRegRead);
3653#endif
3654
3655 //2=======================================================
3656 // RF Power Save
3657 //2=======================================================
3658#ifdef ENABLE_IPS
3659
3660{
3661 if(priv->RegRfOff == TRUE)
3662 { // User disable RF via registry.
3663 RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RegRfOff ----------\n",__FUNCTION__);
3664 MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_SW);
3665#if 0//cosa, ask SD3 willis and he doesn't know what is this for
3666 // Those action will be discard in MgntActSet_RF_State because off the same state
3667 for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
3668 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3669#endif
3670 }
3671 else if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_PS)
3672 { // H/W or S/W RF OFF before sleep.
3673 RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RfOffReason(%d) ----------\n", __FUNCTION__,priv->ieee80211->RfOffReason);
3674 MgntActSet_RF_State(dev, eRfOff, priv->ieee80211->RfOffReason);
3675 }
3676 else if(priv->ieee80211->RfOffReason >= RF_CHANGE_BY_IPS)
3677 { // H/W or S/W RF OFF before sleep.
3678 RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RfOffReason(%d) ----------\n", __FUNCTION__,priv->ieee80211->RfOffReason);
3679 MgntActSet_RF_State(dev, eRfOff, priv->ieee80211->RfOffReason);
3680 }
3681 else
3682 {
3683 RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): RF-ON \n",__FUNCTION__);
3684 priv->ieee80211->eRFPowerState = eRfOn;
3685 priv->ieee80211->RfOffReason = 0;
3686 //DrvIFIndicateCurrentPhyStatus(Adapter);
3687 // LED control
3688 //Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_POWER_ON);
3689
3690 //
3691 // If inactive power mode is enabled, disable rf while in disconnected state.
3692 // But we should still tell upper layer we are in rf on state.
3693 // 2007.07.16, by shien chang.
3694 //
3695 //if(!Adapter->bInHctTest)
3696 //IPSEnter(Adapter);
3697
3698 }
3699}
3700#endif
3701 if(1){
3702#ifdef RTL8192E
3703 // We can force firmware to do RF-R/W
3704 if(priv->ieee80211->FwRWRF)
3705 priv->Rf_Mode = RF_OP_By_FW;
3706 else
3707 priv->Rf_Mode = RF_OP_By_SW_3wire;
3708#else
3709 priv->Rf_Mode = RF_OP_By_SW_3wire;
3710#endif
3711 }
3712#ifdef RTL8190P
3713 if(priv->ResetProgress == RESET_TYPE_NORESET)
3714 {
3715 dm_initialize_txpower_tracking(dev);
3716
3717 tmpRegA= rtl8192_QueryBBReg(dev,rOFDM0_XATxIQImbalance,bMaskDWord);
3718 tmpRegC= rtl8192_QueryBBReg(dev,rOFDM0_XCTxIQImbalance,bMaskDWord);
3719
3720 if(priv->rf_type == RF_2T4R){
3721 for(i = 0; i<TxBBGainTableLength; i++)
3722 {
3723 if(tmpRegA == priv->txbbgain_table[i].txbbgain_value)
3724 {
3725 priv->rfa_txpowertrackingindex= (u8)i;
3726 priv->rfa_txpowertrackingindex_real= (u8)i;
3727 priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
3728 break;
3729 }
3730 }
3731 }
3732 for(i = 0; i<TxBBGainTableLength; i++)
3733 {
3734 if(tmpRegC == priv->txbbgain_table[i].txbbgain_value)
3735 {
3736 priv->rfc_txpowertrackingindex= (u8)i;
3737 priv->rfc_txpowertrackingindex_real= (u8)i;
3738 priv->rfc_txpowertracking_default = priv->rfc_txpowertrackingindex;
3739 break;
3740 }
3741 }
3742 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3743
3744 for(i=0 ; i<CCKTxBBGainTableLength ; i++)
3745 {
3746 if(TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0])
3747 {
3748 priv->CCKPresentAttentuation_20Mdefault =(u8) i;
3749 break;
3750 }
3751 }
3752 priv->CCKPresentAttentuation_40Mdefault = 0;
3753 priv->CCKPresentAttentuation_difference = 0;
3754 priv->CCKPresentAttentuation = priv->CCKPresentAttentuation_20Mdefault;
3755 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_initial = %d\n", priv->rfa_txpowertrackingindex);
3756 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real__initial = %d\n", priv->rfa_txpowertrackingindex_real);
3757 RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_initial = %d\n", priv->rfc_txpowertrackingindex);
3758 RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real_initial = %d\n", priv->rfc_txpowertrackingindex_real);
3759 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference_initial = %d\n", priv->CCKPresentAttentuation_difference);
3760 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_initial = %d\n", priv->CCKPresentAttentuation);
3761 }
3762#else
3763 #ifdef RTL8192E
3764 if(priv->ResetProgress == RESET_TYPE_NORESET)
3765 {
3766 dm_initialize_txpower_tracking(dev);
3767
3768 if(priv->IC_Cut >= IC_VersionCut_D)
3769 {
3770 tmpRegA= rtl8192_QueryBBReg(dev,rOFDM0_XATxIQImbalance,bMaskDWord);
3771 tmpRegC= rtl8192_QueryBBReg(dev,rOFDM0_XCTxIQImbalance,bMaskDWord);
3772 for(i = 0; i<TxBBGainTableLength; i++)
3773 {
3774 if(tmpRegA == priv->txbbgain_table[i].txbbgain_value)
3775 {
3776 priv->rfa_txpowertrackingindex= (u8)i;
3777 priv->rfa_txpowertrackingindex_real= (u8)i;
3778 priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
3779 break;
3780 }
3781 }
3782
3783 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3784
3785 for(i=0 ; i<CCKTxBBGainTableLength ; i++)
3786 {
3787 if(TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0])
3788 {
3789 priv->CCKPresentAttentuation_20Mdefault =(u8) i;
3790 break;
3791 }
3792 }
3793 priv->CCKPresentAttentuation_40Mdefault = 0;
3794 priv->CCKPresentAttentuation_difference = 0;
3795 priv->CCKPresentAttentuation = priv->CCKPresentAttentuation_20Mdefault;
3796 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_initial = %d\n", priv->rfa_txpowertrackingindex);
3797 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real__initial = %d\n", priv->rfa_txpowertrackingindex_real);
3798 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference_initial = %d\n", priv->CCKPresentAttentuation_difference);
3799 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_initial = %d\n", priv->CCKPresentAttentuation);
3800 priv->btxpower_tracking = FALSE;//TEMPLY DISABLE
3801 }
3802 }
3803 #endif
3804#endif
3805 rtl8192_irq_enable(dev);
3806 priv->being_init_adapter = false;
3807 return rtStatus;
3808
3809}
3810
Mike McCormack559fba52010-07-26 22:57:52 +09003811static void rtl8192_prepare_beacon(struct r8192_priv *priv)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003812{
3813 struct sk_buff *skb;
3814 //unsigned long flags;
3815 cb_desc *tcb_desc;
3816
3817 skb = ieee80211_get_beacon(priv->ieee80211);
3818 tcb_desc = (cb_desc *)(skb->cb + 8);
3819 //printk("===========> %s\n", __FUNCTION__);
3820 //spin_lock_irqsave(&priv->tx_lock,flags);
3821 /* prepare misc info for the beacon xmit */
3822 tcb_desc->queue_index = BEACON_QUEUE;
André Goddard Rosabbc9a992009-11-14 13:09:06 -02003823 /* IBSS does not support HT yet, use 1M defaultly */
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003824 tcb_desc->data_rate = 2;
3825 tcb_desc->RATRIndex = 7;
3826 tcb_desc->bTxDisableRateFallBack = 1;
3827 tcb_desc->bTxUseDriverAssingedRate = 1;
3828
3829 skb_push(skb, priv->ieee80211->tx_headroom);
3830 if(skb){
3831 rtl8192_tx(priv->ieee80211->dev,skb);
3832 }
3833 //spin_unlock_irqrestore (&priv->tx_lock, flags);
3834}
3835
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003836
3837/* this configures registers for beacon tx and enables it via
3838 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3839 * be used to stop beacon transmission
3840 */
Mike McCormack559fba52010-07-26 22:57:52 +09003841static void rtl8192_start_beacon(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003842{
3843 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3844 struct ieee80211_network *net = &priv->ieee80211->current_network;
3845 u16 BcnTimeCfg = 0;
3846 u16 BcnCW = 6;
3847 u16 BcnIFS = 0xf;
3848
3849 DMESG("Enabling beacon TX");
3850 //rtl8192_prepare_beacon(dev);
3851 rtl8192_irq_disable(dev);
3852 //rtl8192_beacon_tx_enable(dev);
3853
3854 /* ATIM window */
3855 write_nic_word(dev, ATIMWND, 2);
3856
3857 /* Beacon interval (in unit of TU) */
3858 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
3859
3860 /*
3861 * DrvErlyInt (in unit of TU).
3862 * (Time to send interrupt to notify driver to c
3863 * hange beacon content)
3864 * */
3865 write_nic_word(dev, BCN_DRV_EARLY_INT, 10);
3866
3867 /*
3868 * BcnDMATIM(in unit of us).
3869 * Indicates the time before TBTT to perform beacon queue DMA
3870 * */
3871 write_nic_word(dev, BCN_DMATIME, 256);
3872
3873 /*
3874 * Force beacon frame transmission even after receiving
3875 * beacon frame from other ad hoc STA
3876 * */
3877 write_nic_byte(dev, BCN_ERR_THRESH, 100);
3878
3879 /* Set CW and IFS */
3880 BcnTimeCfg |= BcnCW<<BCN_TCFG_CW_SHIFT;
3881 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
3882 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
3883
3884
3885 /* enable the interrupt for ad-hoc process */
3886 rtl8192_irq_enable(dev);
3887}
3888/***************************************************************************
3889 -------------------------------NET STUFF---------------------------
3890***************************************************************************/
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003891
3892
3893
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07003894static bool HalTxCheckStuck8190Pci(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003895{
3896 u16 RegTxCounter = read_nic_word(dev, 0x128);
3897 struct r8192_priv *priv = ieee80211_priv(dev);
3898 bool bStuck = FALSE;
3899 RT_TRACE(COMP_RESET,"%s():RegTxCounter is %d,TxCounter is %d\n",__FUNCTION__,RegTxCounter,priv->TxCounter);
3900 if(priv->TxCounter==RegTxCounter)
3901 bStuck = TRUE;
3902
3903 priv->TxCounter = RegTxCounter;
3904
3905 return bStuck;
3906}
3907
3908/*
3909* <Assumption: RT_TX_SPINLOCK is acquired.>
3910* First added: 2006.11.19 by emily
3911*/
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07003912static RESET_TYPE
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003913TxCheckStuck(struct net_device *dev)
3914{
3915 struct r8192_priv *priv = ieee80211_priv(dev);
3916 u8 QueueID;
3917 ptx_ring head=NULL,tail=NULL,txring = NULL;
3918 u8 ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
3919 bool bCheckFwTxCnt = false;
3920 //unsigned long flags;
3921
3922 //
3923 // Decide Stuch threshold according to current power save mode
3924 //
3925 //printk("++++++++++++>%s()\n",__FUNCTION__);
3926 switch (priv->ieee80211->dot11PowerSaveMode)
3927 {
3928 // The threshold value may required to be adjusted .
3929 case eActive: // Active/Continuous access.
3930 ResetThreshold = NIC_SEND_HANG_THRESHOLD_NORMAL;
3931 break;
3932 case eMaxPs: // Max power save mode.
3933 ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
3934 break;
3935 case eFastPs: // Fast power save mode.
3936 ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
3937 break;
3938 }
3939
3940 //
3941 // Check whether specific tcb has been queued for a specific time
3942 //
3943 for(QueueID = 0; QueueID < MAX_TX_QUEUE; QueueID++)
3944 {
3945
3946
3947 if(QueueID == TXCMD_QUEUE)
3948 continue;
3949
3950 switch(QueueID) {
3951 case MGNT_QUEUE:
3952 tail=priv->txmapringtail;
3953 head=priv->txmapringhead;
3954 break;
3955
3956 case BK_QUEUE:
3957 tail=priv->txbkpringtail;
3958 head=priv->txbkpringhead;
3959 break;
3960
3961 case BE_QUEUE:
3962 tail=priv->txbepringtail;
3963 head=priv->txbepringhead;
3964 break;
3965
3966 case VI_QUEUE:
3967 tail=priv->txvipringtail;
3968 head=priv->txvipringhead;
3969 break;
3970
3971 case VO_QUEUE:
3972 tail=priv->txvopringtail;
3973 head=priv->txvopringhead;
3974 break;
3975
3976 default:
3977 tail=head=NULL;
3978 break;
3979 }
3980
3981 if(tail == head)
3982 continue;
3983 else
3984 {
3985 txring = head;
3986 if(txring == NULL)
3987 {
3988 RT_TRACE(COMP_ERR,"%s():txring is NULL , BUG!\n",__FUNCTION__);
3989 continue;
3990 }
3991 txring->nStuckCount++;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07003992 bCheckFwTxCnt = TRUE;
3993 }
3994 }
3995#if 1
3996 if(bCheckFwTxCnt)
3997 {
3998 if(HalTxCheckStuck8190Pci(dev))
3999 {
4000 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
4001 return RESET_TYPE_SILENT;
4002 }
4003 }
4004#endif
4005 return RESET_TYPE_NORESET;
4006}
4007
4008
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07004009static bool HalRxCheckStuck8190Pci(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004010{
4011 struct r8192_priv *priv = ieee80211_priv(dev);
4012 u16 RegRxCounter = read_nic_word(dev, 0x130);
4013 bool bStuck = FALSE;
4014 static u8 rx_chk_cnt = 0;
4015 RT_TRACE(COMP_RESET,"%s(): RegRxCounter is %d,RxCounter is %d\n",__FUNCTION__,RegRxCounter,priv->RxCounter);
4016 // If rssi is small, we should check rx for long time because of bad rx.
4017 // or maybe it will continuous silent reset every 2 seconds.
4018 rx_chk_cnt++;
4019 if(priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5))
4020 {
4021 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
4022 }
4023 else if(priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
4024 ((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_40M) ||
4025 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_20M)) )
4026
4027 {
4028 if(rx_chk_cnt < 2)
4029 {
4030 return bStuck;
4031 }
4032 else
4033 {
4034 rx_chk_cnt = 0;
4035 }
4036 }
4037 else if(((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_40M) ||
4038 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_20M)) &&
4039 priv->undecorated_smoothed_pwdb >= VeryLowRSSI)
4040 {
4041 if(rx_chk_cnt < 4)
4042 {
4043 //DbgPrint("RSSI < %d && RSSI >= %d, no check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
4044 return bStuck;
4045 }
4046 else
4047 {
4048 rx_chk_cnt = 0;
4049 //DbgPrint("RSSI < %d && RSSI >= %d, check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
4050 }
4051 }
4052 else
4053 {
4054 if(rx_chk_cnt < 8)
4055 {
4056 //DbgPrint("RSSI <= %d, no check this time \n", VeryLowRSSI);
4057 return bStuck;
4058 }
4059 else
4060 {
4061 rx_chk_cnt = 0;
4062 //DbgPrint("RSSI <= %d, check this time \n", VeryLowRSSI);
4063 }
4064 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004065 if(priv->RxCounter==RegRxCounter)
4066 bStuck = TRUE;
4067
4068 priv->RxCounter = RegRxCounter;
4069
4070 return bStuck;
4071}
4072
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07004073static RESET_TYPE RxCheckStuck(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004074{
4075
4076 if(HalRxCheckStuck8190Pci(dev))
4077 {
4078 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
4079 return RESET_TYPE_SILENT;
4080 }
4081
4082 return RESET_TYPE_NORESET;
4083}
4084
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07004085static RESET_TYPE
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004086rtl819x_ifcheck_resetornot(struct net_device *dev)
4087{
4088 struct r8192_priv *priv = ieee80211_priv(dev);
4089 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
4090 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
4091 RT_RF_POWER_STATE rfState;
4092
4093 rfState = priv->ieee80211->eRFPowerState;
4094
4095 TxResetType = TxCheckStuck(dev);
4096#if 1
4097 if( rfState != eRfOff &&
4098 /*ADAPTER_TEST_STATUS_FLAG(Adapter, ADAPTER_STATUS_FW_DOWNLOAD_FAILURE)) &&*/
4099 (priv->ieee80211->iw_mode != IW_MODE_ADHOC))
4100 {
4101 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
4102 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
4103 // if driver is in firmware download failure status, driver should initialize RF in the following
4104 // silent reset procedure Emily, 2008.01.21
4105
4106 // Driver should not check RX stuck in IBSS mode because it is required to
4107 // set Check BSSID in order to send beacon, however, if check BSSID is
4108 // set, STA cannot hear any packet a all. Emily, 2008.04.12
4109 RxResetType = RxCheckStuck(dev);
4110 }
4111#endif
4112
4113 RT_TRACE(COMP_RESET,"%s(): TxResetType is %d, RxResetType is %d\n",__FUNCTION__,TxResetType,RxResetType);
4114 if(TxResetType==RESET_TYPE_NORMAL || RxResetType==RESET_TYPE_NORMAL)
4115 return RESET_TYPE_NORMAL;
4116 else if(TxResetType==RESET_TYPE_SILENT || RxResetType==RESET_TYPE_SILENT)
4117 return RESET_TYPE_SILENT;
4118 else
4119 return RESET_TYPE_NORESET;
4120
4121}
4122
4123
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07004124static void CamRestoreAllEntry(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004125{
4126 u8 EntryId = 0;
4127 struct r8192_priv *priv = ieee80211_priv(dev);
Mike McCormack881a9752010-07-26 22:58:03 +09004128 const u8* MacAddr = priv->ieee80211->current_network.bssid;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004129
Mike McCormack881a9752010-07-26 22:58:03 +09004130 static const u8 CAM_CONST_ADDR[4][6] = {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004131 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
4132 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
4133 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
4134 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
Mike McCormack881a9752010-07-26 22:58:03 +09004135 static const u8 CAM_CONST_BROAD[] =
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004136 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4137
4138 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
4139
4140
4141 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40)||
4142 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104))
4143 {
4144
4145 for(EntryId=0; EntryId<4; EntryId++)
4146 {
4147 {
4148 MacAddr = CAM_CONST_ADDR[EntryId];
4149 setKey(dev,
4150 EntryId ,
4151 EntryId,
4152 priv->ieee80211->pairwise_key_type,
4153 MacAddr,
4154 0,
4155 NULL);
4156 }
4157 }
4158
4159 }
4160 else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP)
4161 {
4162
4163 {
4164 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
4165 setKey(dev,
4166 4,
4167 0,
4168 priv->ieee80211->pairwise_key_type,
4169 (u8*)dev->dev_addr,
4170 0,
4171 NULL);
4172 else
4173 setKey(dev,
4174 4,
4175 0,
4176 priv->ieee80211->pairwise_key_type,
4177 MacAddr,
4178 0,
4179 NULL);
4180 }
4181 }
4182 else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP)
4183 {
4184
4185 {
4186 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
4187 setKey(dev,
4188 4,
4189 0,
4190 priv->ieee80211->pairwise_key_type,
4191 (u8*)dev->dev_addr,
4192 0,
4193 NULL);
4194 else
4195 setKey(dev,
4196 4,
4197 0,
4198 priv->ieee80211->pairwise_key_type,
4199 MacAddr,
4200 0,
4201 NULL);
4202 }
4203 }
4204
4205
4206
4207 if(priv->ieee80211->group_key_type == KEY_TYPE_TKIP)
4208 {
4209 MacAddr = CAM_CONST_BROAD;
4210 for(EntryId=1 ; EntryId<4 ; EntryId++)
4211 {
4212 {
4213 setKey(dev,
4214 EntryId,
4215 EntryId,
4216 priv->ieee80211->group_key_type,
4217 MacAddr,
4218 0,
4219 NULL);
4220 }
4221 }
4222 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
4223 setKey(dev,
4224 0,
4225 0,
4226 priv->ieee80211->group_key_type,
4227 CAM_CONST_ADDR[0],
4228 0,
4229 NULL);
4230 }
4231 else if(priv->ieee80211->group_key_type == KEY_TYPE_CCMP)
4232 {
4233 MacAddr = CAM_CONST_BROAD;
4234 for(EntryId=1; EntryId<4 ; EntryId++)
4235 {
4236 {
4237 setKey(dev,
4238 EntryId ,
4239 EntryId,
4240 priv->ieee80211->group_key_type,
4241 MacAddr,
4242 0,
4243 NULL);
4244 }
4245 }
4246
4247 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
4248 setKey(dev,
4249 0 ,
4250 0,
4251 priv->ieee80211->group_key_type,
4252 CAM_CONST_ADDR[0],
4253 0,
4254 NULL);
4255 }
4256}
4257
4258void rtl8192_cancel_deferred_work(struct r8192_priv* priv);
4259int _rtl8192_up(struct net_device *dev);
4260
4261/*
4262 * This function is used to fix Tx/Rx stop bug temporarily.
4263 * This function will do "system reset" to NIC when Tx or Rx is stuck.
4264 * The method checking Tx/Rx stuck of this function is supported by FW,
4265 * which reports Tx and Rx counter to register 0x128 and 0x130.
4266 * */
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07004267static void rtl819x_ifsilentreset(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004268{
4269 struct r8192_priv *priv = ieee80211_priv(dev);
4270 u8 reset_times = 0;
4271 int reset_status = 0;
4272 struct ieee80211_device *ieee = priv->ieee80211;
4273
4274
david woo65a43782009-12-22 09:40:36 -08004275 return;
4276
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004277 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
4278 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
4279
4280 if(priv->ResetProgress==RESET_TYPE_NORESET)
4281 {
4282RESET_START:
david woo65a43782009-12-22 09:40:36 -08004283#ifdef ENABLE_LPS
4284 //LZM for PS-Poll AID issue. 090429
4285 if(priv->ieee80211->state == IEEE80211_LINKED)
4286 LeisurePSLeave(dev);
4287#endif
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004288
4289 RT_TRACE(COMP_RESET,"=========>Reset progress!! \n");
4290
4291 // Set the variable for reset.
4292 priv->ResetProgress = RESET_TYPE_SILENT;
4293// rtl8192_close(dev);
4294#if 1
4295 down(&priv->wx_sem);
4296 if(priv->up == 0)
4297 {
4298 RT_TRACE(COMP_ERR,"%s():the driver is not up! return\n",__FUNCTION__);
4299 up(&priv->wx_sem);
4300 return ;
4301 }
4302 priv->up = 0;
4303 RT_TRACE(COMP_RESET,"%s():======>start to down the driver\n",__FUNCTION__);
4304 if(!netif_queue_stopped(dev))
4305 netif_stop_queue(dev);
4306
4307 dm_backup_dynamic_mechanism_state(dev);
4308
4309 rtl8192_irq_disable(dev);
4310 rtl8192_cancel_deferred_work(priv);
4311 deinit_hal_dm(dev);
4312 del_timer_sync(&priv->watch_dog_timer);
4313 ieee->sync_scan_hurryup = 1;
4314 if(ieee->state == IEEE80211_LINKED)
4315 {
4316 down(&ieee->wx_sem);
4317 printk("ieee->state is IEEE80211_LINKED\n");
4318 ieee80211_stop_send_beacons(priv->ieee80211);
4319 del_timer_sync(&ieee->associate_timer);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004320 cancel_delayed_work(&ieee->associate_retry_wq);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004321 ieee80211_stop_scan(ieee);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004322 up(&ieee->wx_sem);
4323 }
4324 else{
4325 printk("ieee->state is NOT LINKED\n");
david woo65a43782009-12-22 09:40:36 -08004326 ieee80211_softmac_stop_protocol(priv->ieee80211,true);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004327 }
david woo65a43782009-12-22 09:40:36 -08004328 rtl8192_halt_adapter(dev, true);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004329 up(&priv->wx_sem);
4330 RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__);
4331 RT_TRACE(COMP_RESET,"%s():===========>start to up the driver\n",__FUNCTION__);
4332 reset_status = _rtl8192_up(dev);
4333
4334 RT_TRACE(COMP_RESET,"%s():<===========up process is finished\n",__FUNCTION__);
4335 if(reset_status == -1)
4336 {
4337 if(reset_times < 3)
4338 {
4339 reset_times++;
4340 goto RESET_START;
4341 }
4342 else
4343 {
4344 RT_TRACE(COMP_ERR," ERR!!! %s(): Reset Failed!!\n",__FUNCTION__);
4345 }
4346 }
4347#endif
4348 ieee->is_silent_reset = 1;
4349#if 1
4350 EnableHWSecurityConfig8192(dev);
4351#if 1
4352 if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA)
4353 {
4354 ieee->set_chan(ieee->dev, ieee->current_network.channel);
4355
4356#if 1
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004357 queue_work(ieee->wq, &ieee->associate_complete_wq);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004358#endif
4359
4360 }
4361 else if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC)
4362 {
4363 ieee->set_chan(ieee->dev, ieee->current_network.channel);
4364 ieee->link_change(ieee->dev);
4365
4366 // notify_wx_assoc_event(ieee);
4367
4368 ieee80211_start_send_beacons(ieee);
4369
4370 if (ieee->data_hard_resume)
4371 ieee->data_hard_resume(ieee->dev);
4372 netif_carrier_on(ieee->dev);
4373 }
4374#endif
4375
4376 CamRestoreAllEntry(dev);
4377
4378 // Restore the previous setting for all dynamic mechanism
4379 dm_restore_dynamic_mechanism_state(dev);
4380
4381 priv->ResetProgress = RESET_TYPE_NORESET;
4382 priv->reset_count++;
4383
4384 priv->bForcedSilentReset =false;
4385 priv->bResetInProgress = false;
4386
4387 // For test --> force write UFWP.
4388 write_nic_byte(dev, UFWP, 1);
4389 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
4390#endif
4391 }
4392}
4393
4394#ifdef ENABLE_IPS
4395void InactivePsWorkItemCallback(struct net_device *dev)
4396{
4397 struct r8192_priv *priv = ieee80211_priv(dev);
4398 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
4399 //u8 index = 0;
4400
4401 RT_TRACE(COMP_POWER, "InactivePsWorkItemCallback() ---------> \n");
4402 //
4403 // This flag "bSwRfProcessing", indicates the status of IPS procedure, should be set if the IPS workitem
4404 // is really scheduled.
4405 // The old code, sets this flag before scheduling the IPS workitem and however, at the same time the
4406 // previous IPS workitem did not end yet, fails to schedule the current workitem. Thus, bSwRfProcessing
4407 // blocks the IPS procedure of switching RF.
4408 // By Bruce, 2007-12-25.
4409 //
4410 pPSC->bSwRfProcessing = TRUE;
4411
4412 RT_TRACE(COMP_RF, "InactivePsWorkItemCallback(): Set RF to %s.\n", \
4413 pPSC->eInactivePowerState == eRfOff?"OFF":"ON");
4414
4415
4416 MgntActSet_RF_State(dev, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS);
4417
4418 //
4419 // To solve CAM values miss in RF OFF, rewrite CAM values after RF ON. By Bruce, 2007-09-20.
4420 //
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004421 pPSC->bSwRfProcessing = FALSE;
4422 RT_TRACE(COMP_POWER, "InactivePsWorkItemCallback() <--------- \n");
4423}
4424
david woo65a43782009-12-22 09:40:36 -08004425#ifdef ENABLE_LPS
4426//
4427// Change current and default preamble mode.
4428// 2005.01.06, by rcnjko.
4429//
4430bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev, u8 rtPsMode)
4431{
4432 struct r8192_priv *priv = ieee80211_priv(dev);
4433 //PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
4434 //u8 RpwmVal, FwPwrMode;
4435
4436 // Currently, we do not change power save mode on IBSS mode.
4437 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
4438 {
4439 return false;
4440 }
4441
4442 //
4443 // <RJ_NOTE> If we make HW to fill up the PwrMgt bit for us,
4444 // some AP will not response to our mgnt frames with PwrMgt bit set,
4445 // e.g. cannot associate the AP.
4446 // So I commented out it. 2005.02.16, by rcnjko.
4447 //
4448// // Change device's power save mode.
4449// Adapter->HalFunc.SetPSModeHandler( Adapter, rtPsMode );
4450
4451 // Update power save mode configured.
4452 //RT_TRACE(COMP_LPS,"%s(): set ieee->ps = %x\n",__FUNCTION__,rtPsMode);
4453 if(!priv->ps_force) {
4454 priv->ieee80211->ps = rtPsMode;
4455 }
4456
4457 // Awake immediately
4458 if(priv->ieee80211->sta_sleep != 0 && rtPsMode == IEEE80211_PS_DISABLED)
4459 {
4460 unsigned long flags;
4461
4462 //PlatformSetTimer(Adapter, &(pMgntInfo->AwakeTimer), 0);
4463 // Notify the AP we awke.
4464 rtl8192_hw_wakeup(dev);
4465 priv->ieee80211->sta_sleep = 0;
4466
4467 spin_lock_irqsave(&(priv->ieee80211->mgmt_tx_lock), flags);
4468 printk("LPS leave: notify AP we are awaked ++++++++++ SendNullFunctionData\n");
4469 ieee80211_sta_ps_send_null_frame(priv->ieee80211, 0);
4470 spin_unlock_irqrestore(&(priv->ieee80211->mgmt_tx_lock), flags);
4471 }
4472
4473 return true;
4474}
4475
4476//================================================================================
4477// Leisure Power Save in linked state.
4478//================================================================================
4479
4480//
4481// Description:
4482// Enter the leisure power save mode.
4483//
4484void LeisurePSEnter(struct net_device *dev)
4485{
4486 struct r8192_priv *priv = ieee80211_priv(dev);
4487 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
4488
4489 //RT_TRACE(COMP_PS, "LeisurePSEnter()...\n");
4490 //RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdleCount is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n",
4491 // pPSC->bLeisurePs, priv->ieee80211->ps,pPSC->LpsIdleCount,RT_CHECK_FOR_HANG_PERIOD);
4492
4493 if(!((priv->ieee80211->iw_mode == IW_MODE_INFRA) &&
4494 (priv->ieee80211->state == IEEE80211_LINKED)) ||
4495 (priv->ieee80211->iw_mode == IW_MODE_ADHOC) ||
4496 (priv->ieee80211->iw_mode == IW_MODE_MASTER))
4497 return;
4498
4499 if (pPSC->bLeisurePs)
4500 {
4501 // Idle for a while if we connect to AP a while ago.
4502 if(pPSC->LpsIdleCount >= RT_CHECK_FOR_HANG_PERIOD) // 4 Sec
4503 {
4504
4505 if(priv->ieee80211->ps == IEEE80211_PS_DISABLED)
4506 {
4507
4508 //RT_TRACE(COMP_LPS, "LeisurePSEnter(): Enter 802.11 power save mode...\n");
4509 MgntActSet_802_11_PowerSaveMode(dev, IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST);
4510
4511 }
4512 }
4513 else
4514 pPSC->LpsIdleCount++;
4515 }
4516}
4517
4518
4519//
4520// Description:
4521// Leave the leisure power save mode.
4522//
4523void LeisurePSLeave(struct net_device *dev)
4524{
4525 struct r8192_priv *priv = ieee80211_priv(dev);
4526 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
4527
4528
4529 //RT_TRACE(COMP_PS, "LeisurePSLeave()...\n");
4530 //RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d\n",
4531 // pPSC->bLeisurePs, priv->ieee80211->ps);
4532
4533 if (pPSC->bLeisurePs)
4534 {
4535 if(priv->ieee80211->ps != IEEE80211_PS_DISABLED)
4536 {
4537 // move to lps_wakecomplete()
4538 //RT_TRACE(COMP_LPS, "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n");
4539 MgntActSet_802_11_PowerSaveMode(dev, IEEE80211_PS_DISABLED);
4540
4541 }
4542 }
4543}
4544#endif
4545
4546
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004547//
4548// Description:
4549// Enter the inactive power save mode. RF will be off
4550// 2007.08.17, by shien chang.
4551//
4552void
4553IPSEnter(struct net_device *dev)
4554{
4555 struct r8192_priv *priv = ieee80211_priv(dev);
4556 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
4557 RT_RF_POWER_STATE rtState;
4558
4559 if (pPSC->bInactivePs)
4560 {
4561 rtState = priv->ieee80211->eRFPowerState;
4562 //
4563 // Added by Bruce, 2007-12-25.
4564 // Do not enter IPS in the following conditions:
4565 // (1) RF is already OFF or Sleep
4566 // (2) bSwRfProcessing (indicates the IPS is still under going)
4567 // (3) Connectted (only disconnected can trigger IPS)
4568 // (4) IBSS (send Beacon)
4569 // (5) AP mode (send Beacon)
4570 //
4571 if (rtState == eRfOn && !pPSC->bSwRfProcessing
4572 && (priv->ieee80211->state != IEEE80211_LINKED) )
4573 {
4574 RT_TRACE(COMP_RF,"IPSEnter(): Turn off RF.\n");
david woo65a43782009-12-22 09:40:36 -08004575 //printk("IPSEnter(): Turn off RF.\n");
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004576 pPSC->eInactivePowerState = eRfOff;
4577// queue_work(priv->priv_wq,&(pPSC->InactivePsWorkItem));
4578 InactivePsWorkItemCallback(dev);
4579 }
4580 }
4581}
4582
4583//
4584// Description:
4585// Leave the inactive power save mode, RF will be on.
4586// 2007.08.17, by shien chang.
4587//
4588void
4589IPSLeave(struct net_device *dev)
4590{
4591 struct r8192_priv *priv = ieee80211_priv(dev);
4592 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
4593 RT_RF_POWER_STATE rtState;
4594
4595 if (pPSC->bInactivePs)
4596 {
4597 rtState = priv->ieee80211->eRFPowerState;
4598 if (rtState != eRfOn && !pPSC->bSwRfProcessing && priv->ieee80211->RfOffReason <= RF_CHANGE_BY_IPS)
4599 {
4600 RT_TRACE(COMP_POWER, "IPSLeave(): Turn on RF.\n");
david woo65a43782009-12-22 09:40:36 -08004601 //printk("IPSLeave(): Turn on RF.\n");
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004602 pPSC->eInactivePowerState = eRfOn;
4603// queue_work(priv->priv_wq,&(pPSC->InactivePsWorkItem));
4604 InactivePsWorkItemCallback(dev);
4605 }
4606 }
4607}
david woo65a43782009-12-22 09:40:36 -08004608
4609void IPSLeave_wq(void *data)
4610{
4611 struct ieee80211_device *ieee = container_of(data,struct ieee80211_device,ips_leave_wq);
4612 struct net_device *dev = ieee->dev;
4613
4614 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4615 down(&priv->ieee80211->ips_sem);
4616 IPSLeave(dev);
4617 up(&priv->ieee80211->ips_sem);
4618}
4619
4620void ieee80211_ips_leave_wq(struct net_device *dev)
4621{
4622 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4623 RT_RF_POWER_STATE rtState;
4624 rtState = priv->ieee80211->eRFPowerState;
4625
4626 if(priv->ieee80211->PowerSaveControl.bInactivePs){
4627 if(rtState == eRfOff){
4628 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
4629 {
4630 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
4631 return;
4632 }
4633 else{
4634 printk("=========>%s(): IPSLeave\n",__FUNCTION__);
4635 queue_work(priv->ieee80211->wq,&priv->ieee80211->ips_leave_wq);
4636 }
4637 }
4638 }
4639}
4640//added by amy 090331 end
4641void ieee80211_ips_leave(struct net_device *dev)
4642{
4643 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4644 down(&priv->ieee80211->ips_sem);
4645 IPSLeave(dev);
4646 up(&priv->ieee80211->ips_sem);
4647}
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004648#endif
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004649
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07004650static void rtl819x_update_rxcounts(
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004651 struct r8192_priv *priv,
4652 u32* TotalRxBcnNum,
4653 u32* TotalRxDataNum
4654)
4655{
4656 u16 SlotIndex;
4657 u8 i;
4658
4659 *TotalRxBcnNum = 0;
4660 *TotalRxDataNum = 0;
4661
4662 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
4663 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
4664 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
4665 for( i=0; i<priv->ieee80211->LinkDetectInfo.SlotNum; i++ ){
4666 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
4667 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
4668 }
4669}
4670
4671
Mike McCormack559fba52010-07-26 22:57:52 +09004672static void rtl819x_watchdog_wqcallback(struct work_struct *work)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004673{
4674 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
4675 struct r8192_priv *priv = container_of(dwork,struct r8192_priv,watch_dog_wq);
4676 struct net_device *dev = priv->ieee80211->dev;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004677 struct ieee80211_device* ieee = priv->ieee80211;
4678 RESET_TYPE ResetType = RESET_TYPE_NORESET;
4679 static u8 check_reset_cnt=0;
4680 unsigned long flags;
4681 bool bBusyTraffic = false;
4682 static u8 last_time = 0;
david woo65a43782009-12-22 09:40:36 -08004683 bool bEnterPS = false;
4684
4685 if((!priv->up) || (priv->bHwRadioOff == true))
4686 return;
4687
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004688 if(!priv->up)
4689 return;
4690 hal_dm_watchdog(dev);
4691#ifdef ENABLE_IPS
4692// printk("watch_dog ENABLE_IPS\n");
4693 if(ieee->actscanning == false){
david woo65a43782009-12-22 09:40:36 -08004694 //printk("%d,%d,%d,%d\n", ieee->eRFPowerState, ieee->is_set_key, ieee->proto_stoppping, ieee->wx_set_enc);
4695 if((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == IEEE80211_NOLINK) &&\
4696 (ieee->eRFPowerState == eRfOn)&&!ieee->is_set_key &&\
4697 (!ieee->proto_stoppping) && !ieee->wx_set_enc){
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004698 if(ieee->PowerSaveControl.ReturnPoint == IPS_CALLBACK_NONE){
david woo65a43782009-12-22 09:40:36 -08004699 //printk("====================>haha:IPSEnter()\n");
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004700 IPSEnter(dev);
4701 //ieee80211_stop_scan(priv->ieee80211);
4702 }
4703 }
4704 }
4705#endif
4706 {//to get busy traffic condition
4707 if(ieee->state == IEEE80211_LINKED)
4708 {
david woo65a43782009-12-22 09:40:36 -08004709 if( ieee->LinkDetectInfo.NumRxOkInPeriod> 100 ||
4710 ieee->LinkDetectInfo.NumTxOkInPeriod> 100 ) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004711 bBusyTraffic = true;
4712 }
4713
david woo65a43782009-12-22 09:40:36 -08004714#ifdef ENABLE_LPS
4715 //added by amy for Leisure PS
4716 if( ((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod + ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
4717 (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
4718 {
4719 //printk("ieee->LinkDetectInfo.NumRxUnicastOkInPeriod is %d,ieee->LinkDetectInfo.NumTxOkInPeriod is %d\n",
4720 // ieee->LinkDetectInfo.NumRxUnicastOkInPeriod,ieee->LinkDetectInfo.NumTxOkInPeriod);
4721 bEnterPS= false;
4722 }
4723 else
4724 {
4725 bEnterPS= true;
4726 }
4727
4728 //printk("***bEnterPS = %d\n", bEnterPS);
4729 // LeisurePS only work in infra mode.
4730 if(bEnterPS)
4731 {
4732 LeisurePSEnter(dev);
4733 }
4734 else
4735 {
4736 LeisurePSLeave(dev);
4737 }
4738#endif
4739
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004740 }
david woo65a43782009-12-22 09:40:36 -08004741 else
4742 {
4743#ifdef ENABLE_LPS
4744 //RT_TRACE(COMP_LPS,"====>no link LPS leave\n");
4745 LeisurePSLeave(dev);
4746#endif
4747 }
4748
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004749 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
4750 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
david woo65a43782009-12-22 09:40:36 -08004751 ieee->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004752 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
4753 }
4754
4755
4756 //added by amy for AP roaming
4757 if (1)
4758 {
4759 if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA)
4760 {
4761 u32 TotalRxBcnNum = 0;
4762 u32 TotalRxDataNum = 0;
4763
4764 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
4765 if((TotalRxBcnNum+TotalRxDataNum) == 0)
4766 {
4767 if( ieee->eRFPowerState == eRfOff)
4768 RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__);
4769 printk("===>%s(): AP is power off,connect another one\n",__FUNCTION__);
david woo65a43782009-12-22 09:40:36 -08004770 // Dot11d_Reset(dev);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004771 ieee->state = IEEE80211_ASSOCIATING;
4772 notify_wx_assoc_event(priv->ieee80211);
david woo65a43782009-12-22 09:40:36 -08004773 RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004774 ieee->is_roaming = true;
4775 ieee->is_set_key = false;
david woo65a43782009-12-22 09:40:36 -08004776 ieee->link_change(dev);
4777 queue_work(ieee->wq, &ieee->associate_procedure_wq);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004778 }
4779 }
4780 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
4781 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
4782
4783 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004784 //check if reset the driver
4785 spin_lock_irqsave(&priv->tx_lock,flags);
4786 if(check_reset_cnt++ >= 3 && !ieee->is_roaming && (last_time != 1))
4787 {
4788 ResetType = rtl819x_ifcheck_resetornot(dev);
4789 check_reset_cnt = 3;
4790 //DbgPrint("Start to check silent reset\n");
4791 }
4792 spin_unlock_irqrestore(&priv->tx_lock,flags);
4793 if(!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_NORMAL)
4794 {
4795 priv->ResetProgress = RESET_TYPE_NORMAL;
4796 RT_TRACE(COMP_RESET,"%s(): NOMAL RESET\n",__FUNCTION__);
4797 return;
4798 }
4799 /* disable silent reset temply 2008.9.11*/
4800#if 1
4801 if( ((priv->force_reset) || (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT))) // This is control by OID set in Pomelo
4802 {
4803 last_time = 1;
4804 rtl819x_ifsilentreset(dev);
4805 }
4806 else
4807 last_time = 0;
4808#endif
4809 priv->force_reset = false;
4810 priv->bForcedSilentReset = false;
4811 priv->bResetInProgress = false;
4812 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
4813
4814}
4815
4816void watch_dog_timer_callback(unsigned long data)
4817{
4818 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004819 queue_delayed_work(priv->priv_wq,&priv->watch_dog_wq,0);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004820 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
4821
4822}
4823int _rtl8192_up(struct net_device *dev)
4824{
4825 struct r8192_priv *priv = ieee80211_priv(dev);
4826 //int i;
4827 RT_STATUS init_status = RT_STATUS_SUCCESS;
4828 priv->up=1;
4829 priv->ieee80211->ieee_up=1;
david woo65a43782009-12-22 09:40:36 -08004830 priv->bdisable_nic = false; //YJ,add,091111
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004831 RT_TRACE(COMP_INIT, "Bringing up iface");
4832
4833 init_status = rtl8192_adapter_start(dev);
4834 if(init_status != RT_STATUS_SUCCESS)
4835 {
4836 RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
4837 return -1;
4838 }
4839 RT_TRACE(COMP_INIT, "start adapter finished\n");
4840#ifdef RTL8192E
4841 if(priv->ieee80211->eRFPowerState!=eRfOn)
4842 MgntActSet_RF_State(dev, eRfOn, priv->ieee80211->RfOffReason);
4843#endif
4844 if(priv->ieee80211->state != IEEE80211_LINKED)
4845 ieee80211_softmac_start_protocol(priv->ieee80211);
4846 ieee80211_reset_queue(priv->ieee80211);
4847 watch_dog_timer_callback((unsigned long) dev);
4848 if(!netif_queue_stopped(dev))
4849 netif_start_queue(dev);
4850 else
4851 netif_wake_queue(dev);
4852
4853 return 0;
4854}
4855
4856
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07004857static int rtl8192_open(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004858{
4859 struct r8192_priv *priv = ieee80211_priv(dev);
4860 int ret;
4861
4862 down(&priv->wx_sem);
4863 ret = rtl8192_up(dev);
4864 up(&priv->wx_sem);
4865 return ret;
4866
4867}
4868
4869
4870int rtl8192_up(struct net_device *dev)
4871{
4872 struct r8192_priv *priv = ieee80211_priv(dev);
4873
4874 if (priv->up == 1) return -1;
4875
4876 return _rtl8192_up(dev);
4877}
4878
4879
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07004880static int rtl8192_close(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004881{
4882 struct r8192_priv *priv = ieee80211_priv(dev);
4883 int ret;
4884
4885 down(&priv->wx_sem);
4886
4887 ret = rtl8192_down(dev);
4888
4889 up(&priv->wx_sem);
4890
4891 return ret;
4892
4893}
4894
4895int rtl8192_down(struct net_device *dev)
4896{
4897 struct r8192_priv *priv = ieee80211_priv(dev);
4898// int i;
4899#if 0
4900 u8 ucRegRead;
4901 u32 ulRegRead;
4902#endif
4903 if (priv->up == 0) return -1;
4904
david woo65a43782009-12-22 09:40:36 -08004905#ifdef ENABLE_LPS
4906 //LZM for PS-Poll AID issue. 090429
4907 if(priv->ieee80211->state == IEEE80211_LINKED)
4908 LeisurePSLeave(dev);
4909#endif
4910
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004911 priv->up=0;
4912 priv->ieee80211->ieee_up = 0;
4913 RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
4914/* FIXME */
4915 if (!netif_queue_stopped(dev))
4916 netif_stop_queue(dev);
4917
4918 rtl8192_irq_disable(dev);
4919#if 0
4920 if(!priv->ieee80211->bSupportRemoteWakeUp) {
4921 MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_INIT);
4922 // 2006.11.30. System reset bit
4923 ulRegRead = read_nic_dword(dev, CPU_GEN);
4924 ulRegRead|=CPU_GEN_SYSTEM_RESET;
4925 write_nic_dword(dev, CPU_GEN, ulRegRead);
4926 } else {
4927 //2008.06.03 for WOL
4928 write_nic_dword(dev, WFCRC0, 0xffffffff);
4929 write_nic_dword(dev, WFCRC1, 0xffffffff);
4930 write_nic_dword(dev, WFCRC2, 0xffffffff);
4931#ifdef RTL8190P
4932 //GPIO 0 = TRUE
4933 ucRegRead = read_nic_byte(dev, GPO);
4934 ucRegRead |= BIT0;
4935 write_nic_byte(dev, GPO, ucRegRead);
4936#endif
4937 //Write PMR register
4938 write_nic_byte(dev, PMR, 0x5);
4939 //Disable tx, enanble rx
4940 write_nic_byte(dev, MacBlkCtrl, 0xa);
4941 }
4942#endif
4943// flush_scheduled_work();
4944 rtl8192_cancel_deferred_work(priv);
4945 deinit_hal_dm(dev);
4946 del_timer_sync(&priv->watch_dog_timer);
4947
david woo65a43782009-12-22 09:40:36 -08004948 ieee80211_softmac_stop_protocol(priv->ieee80211,true);
4949
4950 rtl8192_halt_adapter(dev,false);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004951 memset(&priv->ieee80211->current_network, 0 , offsetof(struct ieee80211_network, list));
4952
4953 RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
4954
4955 return 0;
4956}
4957
4958
4959void rtl8192_commit(struct net_device *dev)
4960{
4961 struct r8192_priv *priv = ieee80211_priv(dev);
4962
4963 if (priv->up == 0) return ;
4964
4965
david woo65a43782009-12-22 09:40:36 -08004966 ieee80211_softmac_stop_protocol(priv->ieee80211,true);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004967
4968 rtl8192_irq_disable(dev);
david woo65a43782009-12-22 09:40:36 -08004969 rtl8192_halt_adapter(dev,true);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004970 _rtl8192_up(dev);
4971}
4972
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004973void rtl8192_restart(struct work_struct *work)
4974{
4975 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
4976 struct net_device *dev = priv->ieee80211->dev;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07004977
4978 down(&priv->wx_sem);
4979
4980 rtl8192_commit(dev);
4981
4982 up(&priv->wx_sem);
4983}
4984
4985static void r8192_set_multicast(struct net_device *dev)
4986{
4987 struct r8192_priv *priv = ieee80211_priv(dev);
4988 short promisc;
4989
4990 //down(&priv->wx_sem);
4991
4992 /* FIXME FIXME */
4993
4994 promisc = (dev->flags & IFF_PROMISC) ? 1:0;
4995
4996 if (promisc != priv->promisc) {
4997 ;
4998 // rtl8192_commit(dev);
4999 }
5000
5001 priv->promisc = promisc;
5002
5003 //schedule_work(&priv->reset_wq);
5004 //up(&priv->wx_sem);
5005}
5006
5007
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07005008static int r8192_set_mac_adr(struct net_device *dev, void *mac)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005009{
5010 struct r8192_priv *priv = ieee80211_priv(dev);
5011 struct sockaddr *addr = mac;
5012
5013 down(&priv->wx_sem);
5014
5015 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
5016
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005017 schedule_work(&priv->reset_wq);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005018 up(&priv->wx_sem);
5019
5020 return 0;
5021}
5022
5023/* based on ipw2200 driver */
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07005024static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005025{
5026 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5027 struct iwreq *wrq = (struct iwreq *)rq;
5028 int ret=-1;
5029 struct ieee80211_device *ieee = priv->ieee80211;
5030 u32 key[4];
5031 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
5032 struct iw_point *p = &wrq->u.data;
5033 struct ieee_param *ipw = NULL;//(struct ieee_param *)wrq->u.data.pointer;
5034
5035 down(&priv->wx_sem);
5036
5037
5038 if (p->length < sizeof(struct ieee_param) || !p->pointer){
5039 ret = -EINVAL;
5040 goto out;
5041 }
5042
Julia Lawall32414872010-05-11 20:26:57 +02005043 ipw = kmalloc(p->length, GFP_KERNEL);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005044 if (ipw == NULL){
5045 ret = -ENOMEM;
5046 goto out;
5047 }
5048 if (copy_from_user(ipw, p->pointer, p->length)) {
5049 kfree(ipw);
5050 ret = -EFAULT;
5051 goto out;
5052 }
5053
5054 switch (cmd) {
5055 case RTL_IOCTL_WPA_SUPPLICANT:
5056 //parse here for HW security
5057 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION)
5058 {
5059 if (ipw->u.crypt.set_tx)
5060 {
5061 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
5062 ieee->pairwise_key_type = KEY_TYPE_CCMP;
5063 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
5064 ieee->pairwise_key_type = KEY_TYPE_TKIP;
5065 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
5066 {
5067 if (ipw->u.crypt.key_len == 13)
5068 ieee->pairwise_key_type = KEY_TYPE_WEP104;
5069 else if (ipw->u.crypt.key_len == 5)
5070 ieee->pairwise_key_type = KEY_TYPE_WEP40;
5071 }
5072 else
5073 ieee->pairwise_key_type = KEY_TYPE_NA;
5074
5075 if (ieee->pairwise_key_type)
5076 {
5077 memcpy((u8*)key, ipw->u.crypt.key, 16);
5078 EnableHWSecurityConfig8192(dev);
5079 //we fill both index entry and 4th entry for pairwise key as in IPW interface, adhoc will only get here, so we need index entry for its default key serching!
5080 //added by WB.
5081 setKey(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
5082 if (ieee->auth_mode != 2) //LEAP WEP will never set this.
5083 setKey(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
5084 }
5085 if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
5086 write_nic_byte(dev, 0x173, 1); //fix aes bug
5087 }
5088
5089 }
5090 else //if (ipw->u.crypt.idx) //group key use idx > 0
5091 {
5092 memcpy((u8*)key, ipw->u.crypt.key, 16);
5093 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
5094 ieee->group_key_type= KEY_TYPE_CCMP;
5095 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
5096 ieee->group_key_type = KEY_TYPE_TKIP;
5097 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
5098 {
5099 if (ipw->u.crypt.key_len == 13)
5100 ieee->group_key_type = KEY_TYPE_WEP104;
5101 else if (ipw->u.crypt.key_len == 5)
5102 ieee->group_key_type = KEY_TYPE_WEP40;
5103 }
5104 else
5105 ieee->group_key_type = KEY_TYPE_NA;
5106
5107 if (ieee->group_key_type)
5108 {
5109 setKey( dev,
5110 ipw->u.crypt.idx,
5111 ipw->u.crypt.idx, //KeyIndex
5112 ieee->group_key_type, //KeyType
5113 broadcast_addr, //MacAddr
5114 0, //DefaultKey
5115 key); //KeyContent
5116 }
5117 }
5118 }
5119#ifdef JOHN_DEBUG
5120 //john's test 0711
5121 {
5122 int i;
5123 printk("@@ wrq->u pointer = ");
5124 for(i=0;i<wrq->u.data.length;i++){
5125 if(i%10==0) printk("\n");
5126 printk( "%8x|", ((u32*)wrq->u.data.pointer)[i] );
5127 }
5128 printk("\n");
5129 }
5130#endif /*JOHN_DEBUG*/
5131 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
5132 break;
5133
5134 default:
5135 ret = -EOPNOTSUPP;
5136 break;
5137 }
5138
5139 kfree(ipw);
5140out:
5141 up(&priv->wx_sem);
5142
5143 return ret;
5144}
5145
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07005146static u8 HwRateToMRate90(bool bIsHT, u8 rate)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005147{
5148 u8 ret_rate = 0x02;
5149
5150 if(!bIsHT) {
5151 switch(rate) {
5152 case DESC90_RATE1M: ret_rate = MGN_1M; break;
5153 case DESC90_RATE2M: ret_rate = MGN_2M; break;
5154 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
5155 case DESC90_RATE11M: ret_rate = MGN_11M; break;
5156 case DESC90_RATE6M: ret_rate = MGN_6M; break;
5157 case DESC90_RATE9M: ret_rate = MGN_9M; break;
5158 case DESC90_RATE12M: ret_rate = MGN_12M; break;
5159 case DESC90_RATE18M: ret_rate = MGN_18M; break;
5160 case DESC90_RATE24M: ret_rate = MGN_24M; break;
5161 case DESC90_RATE36M: ret_rate = MGN_36M; break;
5162 case DESC90_RATE48M: ret_rate = MGN_48M; break;
5163 case DESC90_RATE54M: ret_rate = MGN_54M; break;
5164
5165 default:
5166 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
5167 break;
5168 }
5169
5170 } else {
5171 switch(rate) {
5172 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
5173 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
5174 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
5175 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
5176 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
5177 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
5178 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
5179 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
5180 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
5181 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
5182 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
5183 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
5184 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
5185 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
5186 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
5187 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
5188 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
5189
5190 default:
5191 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n",rate, bIsHT);
5192 break;
5193 }
5194 }
5195
5196 return ret_rate;
5197}
5198
5199/**
5200 * Function: UpdateRxPktTimeStamp
5201 * Overview: Recored down the TSF time stamp when receiving a packet
5202 *
5203 * Input:
5204 * PADAPTER Adapter
5205 * PRT_RFD pRfd,
5206 *
5207 * Output:
5208 * PRT_RFD pRfd
5209 * (pRfd->Status.TimeStampHigh is updated)
5210 * (pRfd->Status.TimeStampLow is updated)
5211 * Return:
5212 * None
5213 */
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07005214static void UpdateRxPktTimeStamp8190 (struct net_device *dev, struct ieee80211_rx_stats *stats)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005215{
5216 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5217
5218 if(stats->bIsAMPDU && !stats->bFirstMPDU) {
5219 stats->mac_time[0] = priv->LastRxDescTSFLow;
5220 stats->mac_time[1] = priv->LastRxDescTSFHigh;
5221 } else {
5222 priv->LastRxDescTSFLow = stats->mac_time[0];
5223 priv->LastRxDescTSFHigh = stats->mac_time[1];
5224 }
5225}
5226
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07005227static long rtl819x_translate_todbm(u8 signal_strength_index)// 0-100 index.
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005228{
5229 long signal_power; // in dBm.
5230
5231 // Translate to dBm (x=0.5y-95).
5232 signal_power = (long)((signal_strength_index + 1) >> 1);
5233 signal_power -= 95;
5234
5235 return signal_power;
5236}
5237
5238//
5239// Description:
5240// Update Rx signal related information in the packet reeived
5241// to RxStats. User application can query RxStats to realize
5242// current Rx signal status.
5243//
5244// Assumption:
5245// In normal operation, user only care about the information of the BSS
5246// and we shall invoke this function if the packet received is from the BSS.
5247//
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07005248static void
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005249rtl819x_update_rxsignalstatistics8190pci(
5250 struct r8192_priv * priv,
5251 struct ieee80211_rx_stats * pprevious_stats
5252 )
5253{
5254 int weighting = 0;
5255
5256 //2 <ToDo> Update Rx Statistics (such as signal strength and signal quality).
5257
5258 // Initila state
5259 if(priv->stats.recv_signal_power == 0)
5260 priv->stats.recv_signal_power = pprevious_stats->RecvSignalPower;
5261
5262 // To avoid the past result restricting the statistics sensitivity, weight the current power (5/6) to speed up the
5263 // reaction of smoothed Signal Power.
5264 if(pprevious_stats->RecvSignalPower > priv->stats.recv_signal_power)
5265 weighting = 5;
5266 else if(pprevious_stats->RecvSignalPower < priv->stats.recv_signal_power)
5267 weighting = (-5);
5268 //
5269 // We need more correct power of received packets and the "SignalStrength" of RxStats have been beautified or translated,
5270 // so we record the correct power in Dbm here. By Bruce, 2008-03-07.
5271 //
5272 priv->stats.recv_signal_power = (priv->stats.recv_signal_power * 5 + pprevious_stats->RecvSignalPower + weighting) / 6;
5273}
5274
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07005275static void
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005276rtl8190_process_cck_rxpathsel(
5277 struct r8192_priv * priv,
5278 struct ieee80211_rx_stats * pprevious_stats
5279 )
5280{
5281#ifdef RTL8190P //Only 90P 2T4R need to check
5282 char last_cck_adc_pwdb[4]={0,0,0,0};
5283 u8 i;
5284//cosa add for Rx path selection
5285 if(priv->rf_type == RF_2T4R && DM_RxPathSelTable.Enable)
5286 {
5287 if(pprevious_stats->bIsCCK &&
5288 (pprevious_stats->bPacketToSelf ||pprevious_stats->bPacketBeacon))
5289 {
5290 /* record the cck adc_pwdb to the sliding window. */
5291 if(priv->stats.cck_adc_pwdb.TotalNum++ >= PHY_RSSI_SLID_WIN_MAX)
5292 {
5293 priv->stats.cck_adc_pwdb.TotalNum = PHY_RSSI_SLID_WIN_MAX;
5294 for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
5295 {
5296 last_cck_adc_pwdb[i] = priv->stats.cck_adc_pwdb.elements[i][priv->stats.cck_adc_pwdb.index];
5297 priv->stats.cck_adc_pwdb.TotalVal[i] -= last_cck_adc_pwdb[i];
5298 }
5299 }
5300 for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
5301 {
5302 priv->stats.cck_adc_pwdb.TotalVal[i] += pprevious_stats->cck_adc_pwdb[i];
5303 priv->stats.cck_adc_pwdb.elements[i][priv->stats.cck_adc_pwdb.index] = pprevious_stats->cck_adc_pwdb[i];
5304 }
5305 priv->stats.cck_adc_pwdb.index++;
5306 if(priv->stats.cck_adc_pwdb.index >= PHY_RSSI_SLID_WIN_MAX)
5307 priv->stats.cck_adc_pwdb.index = 0;
5308
5309 for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
5310 {
5311 DM_RxPathSelTable.cck_pwdb_sta[i] = priv->stats.cck_adc_pwdb.TotalVal[i]/priv->stats.cck_adc_pwdb.TotalNum;
5312 }
5313
5314 for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
5315 {
5316 if(pprevious_stats->cck_adc_pwdb[i] > (char)priv->undecorated_smoothed_cck_adc_pwdb[i])
5317 {
5318 priv->undecorated_smoothed_cck_adc_pwdb[i] =
5319 ( (priv->undecorated_smoothed_cck_adc_pwdb[i]*(Rx_Smooth_Factor-1)) +
5320 (pprevious_stats->cck_adc_pwdb[i])) /(Rx_Smooth_Factor);
5321 priv->undecorated_smoothed_cck_adc_pwdb[i] = priv->undecorated_smoothed_cck_adc_pwdb[i] + 1;
5322 }
5323 else
5324 {
5325 priv->undecorated_smoothed_cck_adc_pwdb[i] =
5326 ( (priv->undecorated_smoothed_cck_adc_pwdb[i]*(Rx_Smooth_Factor-1)) +
5327 (pprevious_stats->cck_adc_pwdb[i])) /(Rx_Smooth_Factor);
5328 }
5329 }
5330 }
5331 }
5332#endif
5333}
5334
5335
5336/* 2008/01/22 MH We can not delcare RSSI/EVM total value of sliding window to
5337 be a local static. Otherwise, it may increase when we return from S3/S4. The
5338 value will be kept in memory or disk. We must delcare the value in adapter
5339 and it will be reinitialized when return from S3/S4. */
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07005340static void rtl8192_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct ieee80211_rx_stats * pprevious_stats, struct ieee80211_rx_stats * pcurrent_stats)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005341{
5342 bool bcheck = false;
5343 u8 rfpath;
5344 u32 nspatial_stream, tmp_val;
5345 //u8 i;
5346 static u32 slide_rssi_index=0, slide_rssi_statistics=0;
5347 static u32 slide_evm_index=0, slide_evm_statistics=0;
5348 static u32 last_rssi=0, last_evm=0;
5349 //cosa add for rx path selection
5350// static long slide_cck_adc_pwdb_index=0, slide_cck_adc_pwdb_statistics=0;
5351// static char last_cck_adc_pwdb[4]={0,0,0,0};
5352 //cosa add for beacon rssi smoothing
5353 static u32 slide_beacon_adc_pwdb_index=0, slide_beacon_adc_pwdb_statistics=0;
5354 static u32 last_beacon_adc_pwdb=0;
5355
5356 struct ieee80211_hdr_3addr *hdr;
5357 u16 sc ;
5358 unsigned int frag,seq;
5359 hdr = (struct ieee80211_hdr_3addr *)buffer;
5360 sc = le16_to_cpu(hdr->seq_ctl);
5361 frag = WLAN_GET_SEQ_FRAG(sc);
5362 seq = WLAN_GET_SEQ_SEQ(sc);
5363 //cosa add 04292008 to record the sequence number
5364 pcurrent_stats->Seq_Num = seq;
5365 //
5366 // Check whether we should take the previous packet into accounting
5367 //
5368 if(!pprevious_stats->bIsAMPDU)
5369 {
5370 // if previous packet is not aggregated packet
5371 bcheck = true;
5372 }else
5373 {
5374//remve for that we don't use AMPDU to calculate PWDB,because the reported PWDB of some AP is fault.
5375#if 0
5376 // if previous packet is aggregated packet, and current packet
5377 // (1) is not AMPDU
5378 // (2) is the first packet of one AMPDU
5379 // that means the previous packet is the last one aggregated packet
5380 if( !pcurrent_stats->bIsAMPDU || pcurrent_stats->bFirstMPDU)
5381 bcheck = true;
5382#endif
5383 }
5384
5385 if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX)
5386 {
5387 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
5388 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
5389 priv->stats.slide_rssi_total -= last_rssi;
5390 }
5391 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
5392
5393 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
5394 if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
5395 slide_rssi_index = 0;
5396
5397 // <1> Showed on UI for user, in dbm
5398 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
5399 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
5400 pcurrent_stats->rssi = priv->stats.signal_strength;
5401 //
5402 // If the previous packet does not match the criteria, neglect it
5403 //
5404 if(!pprevious_stats->bPacketMatchBSSID)
5405 {
5406 if(!pprevious_stats->bToSelfBA)
5407 return;
5408 }
5409
5410 if(!bcheck)
5411 return;
5412
5413 rtl8190_process_cck_rxpathsel(priv,pprevious_stats);
5414
5415 //
5416 // Check RSSI
5417 //
5418 priv->stats.num_process_phyinfo++;
5419#if 0
5420 /* record the general signal strength to the sliding window. */
5421 if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX)
5422 {
5423 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
5424 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
5425 priv->stats.slide_rssi_total -= last_rssi;
5426 }
5427 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
5428
5429 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
5430 if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
5431 slide_rssi_index = 0;
5432
5433 // <1> Showed on UI for user, in dbm
5434 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
5435 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
5436
5437#endif
5438 // <2> Showed on UI for engineering
5439 // hardware does not provide rssi information for each rf path in CCK
5440 if(!pprevious_stats->bIsCCK && pprevious_stats->bPacketToSelf)
5441 {
5442 for (rfpath = RF90_PATH_A; rfpath < RF90_PATH_C; rfpath++)
5443 {
5444 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
5445 continue;
5446 RT_TRACE(COMP_DBG,"Jacken -> pPreviousstats->RxMIMOSignalStrength[rfpath] = %d \n" ,pprevious_stats->RxMIMOSignalStrength[rfpath] );
5447 //Fixed by Jacken 2008-03-20
5448 if(priv->stats.rx_rssi_percentage[rfpath] == 0)
5449 {
5450 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
5451 //DbgPrint("MIMO RSSI initialize \n");
5452 }
5453 if(pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath])
5454 {
5455 priv->stats.rx_rssi_percentage[rfpath] =
5456 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
5457 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
5458 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
5459 }
5460 else
5461 {
5462 priv->stats.rx_rssi_percentage[rfpath] =
5463 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
5464 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
5465 }
5466 RT_TRACE(COMP_DBG,"Jacken -> priv->RxStats.RxRSSIPercentage[rfPath] = %d \n" ,priv->stats.rx_rssi_percentage[rfpath] );
5467 }
5468 }
5469
5470
5471 //
5472 // Check PWDB.
5473 //
5474 //cosa add for beacon rssi smoothing by average.
5475 if(pprevious_stats->bPacketBeacon)
5476 {
5477 /* record the beacon pwdb to the sliding window. */
5478 if(slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX)
5479 {
5480 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
5481 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
5482 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
5483 //DbgPrint("slide_beacon_adc_pwdb_index = %d, last_beacon_adc_pwdb = %d, Adapter->RxStats.Slide_Beacon_Total = %d\n",
5484 // slide_beacon_adc_pwdb_index, last_beacon_adc_pwdb, Adapter->RxStats.Slide_Beacon_Total);
5485 }
5486 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
5487 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
5488 //DbgPrint("slide_beacon_adc_pwdb_index = %d, pPreviousRfd->Status.RxPWDBAll = %d\n", slide_beacon_adc_pwdb_index, pPreviousRfd->Status.RxPWDBAll);
5489 slide_beacon_adc_pwdb_index++;
5490 if(slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
5491 slide_beacon_adc_pwdb_index = 0;
5492 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
5493 if(pprevious_stats->RxPWDBAll >= 3)
5494 pprevious_stats->RxPWDBAll -= 3;
5495 }
5496
5497 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
5498 pprevious_stats->bIsCCK? "CCK": "OFDM",
5499 pprevious_stats->RxPWDBAll);
5500
5501 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
5502 {
5503 if(priv->undecorated_smoothed_pwdb < 0) // initialize
5504 {
5505 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
5506 //DbgPrint("First pwdb initialize \n");
5507 }
5508#if 1
5509 if(pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb)
5510 {
5511 priv->undecorated_smoothed_pwdb =
5512 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
5513 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
5514 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
5515 }
5516 else
5517 {
5518 priv->undecorated_smoothed_pwdb =
5519 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
5520 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
5521 }
5522#else
5523 //Fixed by Jacken 2008-03-20
5524 if(pPreviousRfd->Status.RxPWDBAll > (u32)pHalData->UndecoratedSmoothedPWDB)
5525 {
5526 pHalData->UndecoratedSmoothedPWDB =
5527 ( ((pHalData->UndecoratedSmoothedPWDB)* 5) + (pPreviousRfd->Status.RxPWDBAll)) / 6;
5528 pHalData->UndecoratedSmoothedPWDB = pHalData->UndecoratedSmoothedPWDB + 1;
5529 }
5530 else
5531 {
5532 pHalData->UndecoratedSmoothedPWDB =
5533 ( ((pHalData->UndecoratedSmoothedPWDB)* 5) + (pPreviousRfd->Status.RxPWDBAll)) / 6;
5534 }
5535#endif
5536 rtl819x_update_rxsignalstatistics8190pci(priv,pprevious_stats);
5537 }
5538
5539 //
5540 // Check EVM
5541 //
5542 /* record the general EVM to the sliding window. */
5543 if(pprevious_stats->SignalQuality == 0)
5544 {
5545 }
5546 else
5547 {
5548 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA){
5549 if(slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX){
5550 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
5551 last_evm = priv->stats.slide_evm[slide_evm_index];
5552 priv->stats.slide_evm_total -= last_evm;
5553 }
5554
5555 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
5556
5557 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
5558 if(slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
5559 slide_evm_index = 0;
5560
5561 // <1> Showed on UI for user, in percentage.
5562 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
5563 priv->stats.signal_quality = tmp_val;
5564 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
5565 priv->stats.last_signal_strength_inpercent = tmp_val;
5566 }
5567
5568 // <2> Showed on UI for engineering
5569 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
5570 {
5571 for(nspatial_stream = 0; nspatial_stream<2 ; nspatial_stream++) // 2 spatial stream
5572 {
5573 if(pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1)
5574 {
5575 if(priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
5576 {
5577 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
5578 }
5579 priv->stats.rx_evm_percentage[nspatial_stream] =
5580 ( (priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
5581 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
5582 }
5583 }
5584 }
5585 }
5586
5587}
5588
5589/*-----------------------------------------------------------------------------
5590 * Function: rtl819x_query_rxpwrpercentage()
5591 *
5592 * Overview:
5593 *
5594 * Input: char antpower
5595 *
5596 * Output: NONE
5597 *
5598 * Return: 0-100 percentage
5599 *
5600 * Revised History:
5601 * When Who Remark
5602 * 05/26/2008 amy Create Version 0 porting from windows code.
5603 *
5604 *---------------------------------------------------------------------------*/
5605static u8 rtl819x_query_rxpwrpercentage(
5606 char antpower
5607 )
5608{
5609 if ((antpower <= -100) || (antpower >= 20))
5610 {
5611 return 0;
5612 }
5613 else if (antpower >= 0)
5614 {
5615 return 100;
5616 }
5617 else
5618 {
5619 return (100+antpower);
5620 }
5621
5622} /* QueryRxPwrPercentage */
5623
5624static u8
5625rtl819x_evm_dbtopercentage(
5626 char value
5627 )
5628{
5629 char ret_val;
5630
5631 ret_val = value;
5632
5633 if(ret_val >= 0)
5634 ret_val = 0;
5635 if(ret_val <= -33)
5636 ret_val = -33;
5637 ret_val = 0 - ret_val;
5638 ret_val*=3;
5639 if(ret_val == 99)
5640 ret_val = 100;
5641 return(ret_val);
5642}
5643
5644//
5645// Description:
5646// We want good-looking for signal strength/quality
5647// 2007/7/19 01:09, by cosa.
5648//
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07005649static long rtl819x_signal_scale_mapping(long currsig)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005650{
5651 long retsig;
5652
5653 // Step 1. Scale mapping.
5654 if(currsig >= 61 && currsig <= 100)
5655 {
5656 retsig = 90 + ((currsig - 60) / 4);
5657 }
5658 else if(currsig >= 41 && currsig <= 60)
5659 {
5660 retsig = 78 + ((currsig - 40) / 2);
5661 }
5662 else if(currsig >= 31 && currsig <= 40)
5663 {
5664 retsig = 66 + (currsig - 30);
5665 }
5666 else if(currsig >= 21 && currsig <= 30)
5667 {
5668 retsig = 54 + (currsig - 20);
5669 }
5670 else if(currsig >= 5 && currsig <= 20)
5671 {
5672 retsig = 42 + (((currsig - 5) * 2) / 3);
5673 }
5674 else if(currsig == 4)
5675 {
5676 retsig = 36;
5677 }
5678 else if(currsig == 3)
5679 {
5680 retsig = 27;
5681 }
5682 else if(currsig == 2)
5683 {
5684 retsig = 18;
5685 }
5686 else if(currsig == 1)
5687 {
5688 retsig = 9;
5689 }
5690 else
5691 {
5692 retsig = currsig;
5693 }
5694
5695 return retsig;
5696}
5697
5698static void rtl8192_query_rxphystatus(
5699 struct r8192_priv * priv,
5700 struct ieee80211_rx_stats * pstats,
5701 prx_desc_819x_pci pdesc,
5702 prx_fwinfo_819x_pci pdrvinfo,
5703 struct ieee80211_rx_stats * precord_stats,
5704 bool bpacket_match_bssid,
5705 bool bpacket_toself,
5706 bool bPacketBeacon,
5707 bool bToSelfBA
5708 )
5709{
5710 //PRT_RFD_STATUS pRtRfdStatus = &(pRfd->Status);
5711 phy_sts_ofdm_819xpci_t* pofdm_buf;
5712 phy_sts_cck_819xpci_t * pcck_buf;
5713 phy_ofdm_rx_status_rxsc_sgien_exintfflag* prxsc;
5714 u8 *prxpkt;
5715 u8 i,max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
5716 char rx_pwr[4], rx_pwr_all=0;
5717 //long rx_avg_pwr = 0;
5718 char rx_snrX, rx_evmX;
5719 u8 evm, pwdb_all;
5720 u32 RSSI, total_rssi=0;//, total_evm=0;
5721// long signal_strength_index = 0;
5722 u8 is_cck_rate=0;
5723 u8 rf_rx_num = 0;
5724
5725 /* 2007/07/04 MH For OFDM RSSI. For high power or not. */
5726 static u8 check_reg824 = 0;
5727 static u32 reg824_bit9 = 0;
5728
5729 priv->stats.numqry_phystatus++;
5730
5731 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
5732
5733 // Record it for next packet processing
5734 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
5735 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
5736 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
5737 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;//RX_HAL_IS_CCK_RATE(pDrvInfo);
5738 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
5739 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
5740 /*2007.08.30 requested by SD3 Jerry */
5741 if(check_reg824 == 0)
5742 {
5743 reg824_bit9 = rtl8192_QueryBBReg(priv->ieee80211->dev, rFPGA0_XA_HSSIParameter2, 0x200);
5744 check_reg824 = 1;
5745 }
5746
5747
5748 prxpkt = (u8*)pdrvinfo;
5749
5750 /* Move pointer to the 16th bytes. Phy status start address. */
5751 prxpkt += sizeof(rx_fwinfo_819x_pci);
5752
5753 /* Initial the cck and ofdm buffer pointer */
5754 pcck_buf = (phy_sts_cck_819xpci_t *)prxpkt;
5755 pofdm_buf = (phy_sts_ofdm_819xpci_t *)prxpkt;
5756
5757 pstats->RxMIMOSignalQuality[0] = -1;
5758 pstats->RxMIMOSignalQuality[1] = -1;
5759 precord_stats->RxMIMOSignalQuality[0] = -1;
5760 precord_stats->RxMIMOSignalQuality[1] = -1;
5761
5762 if(is_cck_rate)
5763 {
5764 //
5765 // (1)Hardware does not provide RSSI for CCK
5766 //
5767
5768 //
5769 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
5770 //
5771 u8 report;//, cck_agc_rpt;
5772#ifdef RTL8190P
5773 u8 tmp_pwdb;
5774 char cck_adc_pwdb[4];
5775#endif
5776 priv->stats.numqry_phystatusCCK++;
5777
5778#ifdef RTL8190P //Only 90P 2T4R need to check
5779 if(priv->rf_type == RF_2T4R && DM_RxPathSelTable.Enable && bpacket_match_bssid)
5780 {
5781 for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
5782 {
5783 tmp_pwdb = pcck_buf->adc_pwdb_X[i];
5784 cck_adc_pwdb[i] = (char)tmp_pwdb;
5785 cck_adc_pwdb[i] /= 2;
5786 pstats->cck_adc_pwdb[i] = precord_stats->cck_adc_pwdb[i] = cck_adc_pwdb[i];
5787 //DbgPrint("RF-%d tmp_pwdb = 0x%x, cck_adc_pwdb = %d", i, tmp_pwdb, cck_adc_pwdb[i]);
5788 }
5789 }
5790#endif
5791
5792 if(!reg824_bit9)
5793 {
5794 report = pcck_buf->cck_agc_rpt & 0xc0;
5795 report = report>>6;
5796 switch(report)
5797 {
5798 //Fixed by Jacken from Bryant 2008-03-20
5799 //Original value is -38 , -26 , -14 , -2
5800 //Fixed value is -35 , -23 , -11 , 6
5801 case 0x3:
5802 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
5803 break;
5804 case 0x2:
5805 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
5806 break;
5807 case 0x1:
5808 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
5809 break;
5810 case 0x0:
5811 rx_pwr_all = 8 - (pcck_buf->cck_agc_rpt & 0x3e);
5812 break;
5813 }
5814 }
5815 else
5816 {
5817 report = pcck_buf->cck_agc_rpt & 0x60;
5818 report = report>>5;
5819 switch(report)
5820 {
5821 case 0x3:
5822 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
5823 break;
5824 case 0x2:
5825 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
5826 break;
5827 case 0x1:
5828 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
5829 break;
5830 case 0x0:
5831 rx_pwr_all = -8 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
5832 break;
5833 }
5834 }
5835
5836 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
5837 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
5838 pstats->RecvSignalPower = rx_pwr_all;
5839
5840 //
5841 // (3) Get Signal Quality (EVM)
5842 //
5843 if(bpacket_match_bssid)
5844 {
5845 u8 sq;
5846
5847 if(pstats->RxPWDBAll > 40)
5848 {
5849 sq = 100;
5850 }else
5851 {
5852 sq = pcck_buf->sq_rpt;
5853
5854 if(pcck_buf->sq_rpt > 64)
5855 sq = 0;
5856 else if (pcck_buf->sq_rpt < 20)
5857 sq = 100;
5858 else
5859 sq = ((64-sq) * 100) / 44;
5860 }
5861 pstats->SignalQuality = precord_stats->SignalQuality = sq;
5862 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
5863 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
5864 }
5865 }
5866 else
5867 {
5868 priv->stats.numqry_phystatusHT++;
5869 //
5870 // (1)Get RSSI for HT rate
5871 //
5872 for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
5873 {
5874 // 2008/01/30 MH we will judge RF RX path now.
5875 if (priv->brfpath_rxenable[i])
5876 rf_rx_num++;
5877 //else
5878 //continue;
5879
5880 //Fixed by Jacken from Bryant 2008-03-20
5881 //Original value is 106
5882#ifdef RTL8190P //Modify by Jacken 2008/03/31
5883 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
5884#else
5885 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 110;
5886#endif
5887
5888 //Get Rx snr value in DB
5889 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
5890 rx_snrX = (char)(tmp_rxsnr);
5891 rx_snrX /= 2;
5892 priv->stats.rxSNRdB[i] = (long)rx_snrX;
5893
5894 /* Translate DBM to percentage. */
5895 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
5896 if (priv->brfpath_rxenable[i])
5897 total_rssi += RSSI;
5898
5899 /* Record Signal Strength for next packet */
5900 if(bpacket_match_bssid)
5901 {
5902 pstats->RxMIMOSignalStrength[i] =(u8) RSSI;
5903 precord_stats->RxMIMOSignalStrength[i] =(u8) RSSI;
5904 }
5905 }
5906
5907
5908 //
5909 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
5910 //
5911 //Fixed by Jacken from Bryant 2008-03-20
5912 //Original value is 106
5913 rx_pwr_all = (((pofdm_buf->pwdb_all ) >> 1 )& 0x7f) -106;
5914 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
5915
5916 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
5917 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
5918 pstats->RecvSignalPower = rx_pwr_all;
5919 //
5920 // (3)EVM of HT rate
5921 //
5922 if(pdrvinfo->RxHT && pdrvinfo->RxRate>=DESC90_RATEMCS8 &&
5923 pdrvinfo->RxRate<=DESC90_RATEMCS15)
5924 max_spatial_stream = 2; //both spatial stream make sense
5925 else
5926 max_spatial_stream = 1; //only spatial stream 1 makes sense
5927
5928 for(i=0; i<max_spatial_stream; i++)
5929 {
5930 tmp_rxevm = pofdm_buf->rxevm_X[i];
5931 rx_evmX = (char)(tmp_rxevm);
5932
5933 // Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment
5934 // fill most significant bit to "zero" when doing shifting operation which may change a negative
5935 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
5936 rx_evmX /= 2; //dbm
5937
5938 evm = rtl819x_evm_dbtopercentage(rx_evmX);
5939#if 0
5940 EVM = SignalScaleMapping(EVM);//make it good looking, from 0~100
5941#endif
5942 if(bpacket_match_bssid)
5943 {
5944 if(i==0) // Fill value in RFD, Get the first spatial stream only
5945 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
5946 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
5947 }
5948 }
5949
5950
5951 /* record rx statistics for debug */
5952 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
5953 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
5954 if(pdrvinfo->BW) //40M channel
5955 priv->stats.received_bwtype[1+prxsc->rxsc]++;
5956 else //20M channel
5957 priv->stats.received_bwtype[0]++;
5958 }
5959
5960 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
5961 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
5962 if(is_cck_rate)
5963 {
5964 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));//PWDB_ALL;
5965
5966 }
5967 else
5968 {
5969 //pRfd->Status.SignalStrength = pRecordRfd->Status.SignalStrength = (u1Byte)(SignalScaleMapping(total_rssi/=RF90_PATH_MAX));//(u1Byte)(total_rssi/=RF90_PATH_MAX);
5970 // We can judge RX path number now.
5971 if (rf_rx_num != 0)
5972 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi/=rf_rx_num)));
5973 }
5974} /* QueryRxPhyStatus8190Pci */
5975
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07005976static void
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005977rtl8192_record_rxdesc_forlateruse(
5978 struct ieee80211_rx_stats * psrc_stats,
5979 struct ieee80211_rx_stats * ptarget_stats
5980)
5981{
5982 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
5983 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
5984 //ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
5985}
5986
5987
5988
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07005989static void TranslateRxSignalStuff819xpci(struct net_device *dev,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07005990 struct sk_buff *skb,
5991 struct ieee80211_rx_stats * pstats,
5992 prx_desc_819x_pci pdesc,
5993 prx_fwinfo_819x_pci pdrvinfo)
5994{
5995 // TODO: We must only check packet for current MAC address. Not finish
5996 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5997 bool bpacket_match_bssid, bpacket_toself;
5998 bool bPacketBeacon=false, bToSelfBA=false;
5999 static struct ieee80211_rx_stats previous_stats;
6000 struct ieee80211_hdr_3addr *hdr;
6001 u16 fc,type;
6002
6003 // Get Signal Quality for only RX data queue (but not command queue)
6004
6005 u8* tmp_buf;
6006 u8 *praddr;
6007
6008 /* Get MAC frame start address. */
6009 tmp_buf = skb->data;
6010
6011 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
6012 fc = le16_to_cpu(hdr->frame_ctl);
6013 type = WLAN_FC_GET_TYPE(fc);
6014 praddr = hdr->addr1;
6015
6016 /* Check if the received packet is acceptabe. */
6017 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
6018 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
6019 && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV));
6020 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
6021#if 1//cosa
6022 if(WLAN_FC_GET_FRAMETYPE(fc)== IEEE80211_STYPE_BEACON)
6023 {
6024 bPacketBeacon = true;
6025 //DbgPrint("Beacon 2, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
6026 }
6027 if(WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK)
6028 {
6029 if((eqMacAddr(praddr,dev->dev_addr)))
6030 bToSelfBA = true;
6031 //DbgPrint("BlockAck, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
6032 }
6033
6034#endif
6035 if(bpacket_match_bssid)
6036 {
6037 priv->stats.numpacket_matchbssid++;
6038 }
6039 if(bpacket_toself){
6040 priv->stats.numpacket_toself++;
6041 }
6042 //
6043 // Process PHY information for previous packet (RSSI/PWDB/EVM)
6044 //
6045 // Because phy information is contained in the last packet of AMPDU only, so driver
6046 // should process phy information of previous packet
6047 rtl8192_process_phyinfo(priv, tmp_buf,&previous_stats, pstats);
6048 rtl8192_query_rxphystatus(priv, pstats, pdesc, pdrvinfo, &previous_stats, bpacket_match_bssid,
6049 bpacket_toself ,bPacketBeacon, bToSelfBA);
6050 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
6051
6052}
6053
6054
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07006055static void rtl8192_tx_resume(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006056{
6057 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
6058 struct ieee80211_device *ieee = priv->ieee80211;
6059 struct sk_buff *skb;
6060 int queue_index;
6061
6062 for(queue_index = BK_QUEUE; queue_index < TXCMD_QUEUE;queue_index++) {
6063 while((!skb_queue_empty(&ieee->skb_waitQ[queue_index]))&&
6064 (priv->ieee80211->check_nic_enough_desc(dev,queue_index) > 0)) {
6065 /* 1. dequeue the packet from the wait queue */
6066 skb = skb_dequeue(&ieee->skb_waitQ[queue_index]);
6067 /* 2. tx the packet directly */
6068 ieee->softmac_data_hard_start_xmit(skb,dev,0/* rate useless now*/);
6069 #if 0
6070 if(queue_index!=MGNT_QUEUE) {
6071 ieee->stats.tx_packets++;
6072 ieee->stats.tx_bytes += skb->len;
6073 }
6074 #endif
6075 }
6076 }
6077}
6078
Mike McCormack559fba52010-07-26 22:57:52 +09006079static void rtl8192_irq_tx_tasklet(struct r8192_priv *priv)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006080{
6081 rtl8192_tx_resume(priv->ieee80211->dev);
6082}
6083
6084/**
6085* Function: UpdateReceivedRateHistogramStatistics
6086* Overview: Recored down the received data rate
6087*
6088* Input:
6089* PADAPTER Adapter
6090* PRT_RFD pRfd,
6091*
6092* Output:
6093* PRT_TCB Adapter
6094* (Adapter->RxStats.ReceivedRateHistogram[] is updated)
6095* Return:
6096* None
6097*/
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07006098static void UpdateReceivedRateHistogramStatistics8190(
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006099 struct net_device *dev,
6100 struct ieee80211_rx_stats* pstats
6101 )
6102{
6103 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
6104 u32 rcvType=1; //0: Total, 1:OK, 2:CRC, 3:ICV
6105 u32 rateIndex;
6106 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
6107
6108 /* 2007/03/09 MH We will not update rate of packet from rx cmd queue. */
6109 #if 0
6110 if (pRfd->queue_id == CMPK_RX_QUEUE_ID)
6111 return;
6112 #endif
6113 if(pstats->bCRC)
6114 rcvType = 2;
6115 else if(pstats->bICV)
6116 rcvType = 3;
6117
6118 if(pstats->bShortPreamble)
6119 preamble_guardinterval = 1;// short
6120 else
6121 preamble_guardinterval = 0;// long
6122
6123 switch(pstats->rate)
6124 {
6125 //
6126 // CCK rate
6127 //
6128 case MGN_1M: rateIndex = 0; break;
6129 case MGN_2M: rateIndex = 1; break;
6130 case MGN_5_5M: rateIndex = 2; break;
6131 case MGN_11M: rateIndex = 3; break;
6132 //
6133 // Legacy OFDM rate
6134 //
6135 case MGN_6M: rateIndex = 4; break;
6136 case MGN_9M: rateIndex = 5; break;
6137 case MGN_12M: rateIndex = 6; break;
6138 case MGN_18M: rateIndex = 7; break;
6139 case MGN_24M: rateIndex = 8; break;
6140 case MGN_36M: rateIndex = 9; break;
6141 case MGN_48M: rateIndex = 10; break;
6142 case MGN_54M: rateIndex = 11; break;
6143 //
6144 // 11n High throughput rate
6145 //
6146 case MGN_MCS0: rateIndex = 12; break;
6147 case MGN_MCS1: rateIndex = 13; break;
6148 case MGN_MCS2: rateIndex = 14; break;
6149 case MGN_MCS3: rateIndex = 15; break;
6150 case MGN_MCS4: rateIndex = 16; break;
6151 case MGN_MCS5: rateIndex = 17; break;
6152 case MGN_MCS6: rateIndex = 18; break;
6153 case MGN_MCS7: rateIndex = 19; break;
6154 case MGN_MCS8: rateIndex = 20; break;
6155 case MGN_MCS9: rateIndex = 21; break;
6156 case MGN_MCS10: rateIndex = 22; break;
6157 case MGN_MCS11: rateIndex = 23; break;
6158 case MGN_MCS12: rateIndex = 24; break;
6159 case MGN_MCS13: rateIndex = 25; break;
6160 case MGN_MCS14: rateIndex = 26; break;
6161 case MGN_MCS15: rateIndex = 27; break;
6162 default: rateIndex = 28; break;
6163 }
6164 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
6165 priv->stats.received_rate_histogram[0][rateIndex]++; //total
6166 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
6167}
6168
Greg Kroah-Hartman5e1ad182009-08-10 16:34:22 -07006169static void rtl8192_rx(struct net_device *dev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006170{
6171 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
6172 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
6173 bool unicast_packet = false;
6174 struct ieee80211_rx_stats stats = {
6175 .signal = 0,
6176 .noise = -98,
6177 .rate = 0,
6178 .freq = IEEE80211_24GHZ_BAND,
6179 };
6180 unsigned int count = priv->rxringcount;
6181
6182 stats.nic_type = NIC_8192E;
6183
6184 while (count--) {
6185 rx_desc_819x_pci *pdesc = &priv->rx_ring[priv->rx_idx];//rx descriptor
6186 struct sk_buff *skb = priv->rx_buf[priv->rx_idx];//rx pkt
6187
6188 if (pdesc->OWN){
6189 /* wait data to be filled by hardware */
6190 return;
6191 } else {
6192 stats.bICV = pdesc->ICV;
6193 stats.bCRC = pdesc->CRC32;
6194 stats.bHwError = pdesc->CRC32 | pdesc->ICV;
6195
6196 stats.Length = pdesc->Length;
6197 if(stats.Length < 24)
6198 stats.bHwError |= 1;
6199
6200 if(stats.bHwError) {
6201 stats.bShift = false;
6202
6203 if(pdesc->CRC32) {
6204 if (pdesc->Length <500)
6205 priv->stats.rxcrcerrmin++;
6206 else if (pdesc->Length >1000)
6207 priv->stats.rxcrcerrmax++;
6208 else
6209 priv->stats.rxcrcerrmid++;
6210 }
6211 goto done;
6212 } else {
6213 prx_fwinfo_819x_pci pDrvInfo = NULL;
6214 struct sk_buff *new_skb = dev_alloc_skb(priv->rxbuffersize);
6215
6216 if (unlikely(!new_skb)) {
6217 goto done;
6218 }
6219
6220 stats.RxDrvInfoSize = pdesc->RxDrvInfoSize;
6221 stats.RxBufShift = ((pdesc->Shift)&0x03);
6222 stats.Decrypted = !pdesc->SWDec;
6223
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006224 pci_dma_sync_single_for_cpu(priv->pdev,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006225 *((dma_addr_t *)skb->cb),
6226 priv->rxbuffersize,
6227 PCI_DMA_FROMDEVICE);
6228 skb_put(skb, pdesc->Length);
6229 pDrvInfo = (rx_fwinfo_819x_pci *)(skb->data + stats.RxBufShift);
6230 skb_reserve(skb, stats.RxDrvInfoSize + stats.RxBufShift);
6231
6232 stats.rate = HwRateToMRate90((bool)pDrvInfo->RxHT, (u8)pDrvInfo->RxRate);
6233 stats.bShortPreamble = pDrvInfo->SPLCP;
6234
6235 /* it is debug only. It should be disabled in released driver.
6236 * 2007.1.11 by Emily
6237 * */
6238 UpdateReceivedRateHistogramStatistics8190(dev, &stats);
6239
6240 stats.bIsAMPDU = (pDrvInfo->PartAggr==1);
6241 stats.bFirstMPDU = (pDrvInfo->PartAggr==1) && (pDrvInfo->FirstAGGR==1);
6242
6243 stats.TimeStampLow = pDrvInfo->TSFL;
6244 stats.TimeStampHigh = read_nic_dword(dev, TSFR+4);
6245
6246 UpdateRxPktTimeStamp8190(dev, &stats);
6247
6248 //
6249 // Get Total offset of MPDU Frame Body
6250 //
6251 if((stats.RxBufShift + stats.RxDrvInfoSize) > 0)
6252 stats.bShift = 1;
6253
6254 stats.RxIs40MHzPacket = pDrvInfo->BW;
6255
6256 /* ???? */
6257 TranslateRxSignalStuff819xpci(dev,skb, &stats, pdesc, pDrvInfo);
6258
6259 /* Rx A-MPDU */
6260 if(pDrvInfo->FirstAGGR==1 || pDrvInfo->PartAggr == 1)
6261 RT_TRACE(COMP_RXDESC, "pDrvInfo->FirstAGGR = %d, pDrvInfo->PartAggr = %d\n",
6262 pDrvInfo->FirstAGGR, pDrvInfo->PartAggr);
6263 skb_trim(skb, skb->len - 4/*sCrcLng*/);
6264 /* rx packets statistics */
6265 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
6266 unicast_packet = false;
6267
6268 if(is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
6269 //TODO
6270 }else if(is_multicast_ether_addr(ieee80211_hdr->addr1)){
6271 //TODO
6272 }else {
6273 /* unicast packet */
6274 unicast_packet = true;
6275 }
6276
6277 stats.packetlength = stats.Length-4;
6278 stats.fraglength = stats.packetlength;
6279 stats.fragoffset = 0;
6280 stats.ntotalfrag = 1;
6281
George Kadianakisfb5fe272009-12-17 01:18:08 +02006282 if(!ieee80211_rtl_rx(priv->ieee80211, skb, &stats)){
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006283 dev_kfree_skb_any(skb);
6284 } else {
6285 priv->stats.rxok++;
6286 if(unicast_packet) {
6287 priv->stats.rxbytesunicast += skb->len;
6288 }
6289 }
6290
6291 skb = new_skb;
6292 priv->rx_buf[priv->rx_idx] = skb;
Jeff Mahoney1c7ec2e2010-01-11 10:54:27 -05006293 *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006294 }
6295
6296 }
6297done:
6298 pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb));
6299 pdesc->OWN = 1;
6300 pdesc->Length = priv->rxbuffersize;
6301 if (priv->rx_idx == priv->rxringcount-1)
6302 pdesc->EOR = 1;
6303 priv->rx_idx = (priv->rx_idx + 1) % priv->rxringcount;
6304 }
6305
6306}
6307
Mike McCormack559fba52010-07-26 22:57:52 +09006308static void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006309{
6310 rtl8192_rx(priv->ieee80211->dev);
6311 /* unmask RDU */
6312 write_nic_dword(priv->ieee80211->dev, INTA_MASK,read_nic_dword(priv->ieee80211->dev, INTA_MASK) | IMR_RDU);
6313}
6314
6315static const struct net_device_ops rtl8192_netdev_ops = {
6316 .ndo_open = rtl8192_open,
6317 .ndo_stop = rtl8192_close,
6318/* .ndo_get_stats = rtl8192_stats, */
6319 .ndo_tx_timeout = tx_timeout,
6320 .ndo_do_ioctl = rtl8192_ioctl,
6321 .ndo_set_multicast_list = r8192_set_multicast,
6322 .ndo_set_mac_address = r8192_set_mac_adr,
George Kadianakisfb5fe272009-12-17 01:18:08 +02006323 .ndo_start_xmit = ieee80211_rtl_xmit,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006324};
6325
6326/****************************************************************************
6327 ---------------------------- PCI_STUFF---------------------------
6328*****************************************************************************/
6329
6330static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
6331 const struct pci_device_id *id)
6332{
6333 unsigned long ioaddr = 0;
6334 struct net_device *dev = NULL;
6335 struct r8192_priv *priv= NULL;
6336 u8 unit = 0;
6337
6338#ifdef CONFIG_RTL8192_IO_MAP
6339 unsigned long pio_start, pio_len, pio_flags;
6340#else
6341 unsigned long pmem_start, pmem_len, pmem_flags;
6342#endif //end #ifdef RTL_IO_MAP
6343
6344 RT_TRACE(COMP_INIT,"Configuring chip resources");
6345
6346 if( pci_enable_device (pdev) ){
6347 RT_TRACE(COMP_ERR,"Failed to enable PCI device");
6348 return -EIO;
6349 }
6350
6351 pci_set_master(pdev);
6352 //pci_set_wmi(pdev);
6353 pci_set_dma_mask(pdev, 0xffffff00ULL);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006354 pci_set_consistent_dma_mask(pdev,0xffffff00ULL);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006355 dev = alloc_ieee80211(sizeof(struct r8192_priv));
6356 if (!dev)
6357 return -ENOMEM;
6358
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006359 pci_set_drvdata(pdev, dev);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006360 SET_NETDEV_DEV(dev, &pdev->dev);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006361 priv = ieee80211_priv(dev);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006362 priv->ieee80211 = netdev_priv(dev);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006363 priv->pdev=pdev;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006364 if((pdev->subsystem_vendor == PCI_VENDOR_ID_DLINK)&&(pdev->subsystem_device == 0x3304)){
6365 priv->ieee80211->bSupportRemoteWakeUp = 1;
6366 } else
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006367 {
6368 priv->ieee80211->bSupportRemoteWakeUp = 0;
6369 }
6370
6371#ifdef CONFIG_RTL8192_IO_MAP
6372
6373 pio_start = (unsigned long)pci_resource_start (pdev, 0);
6374 pio_len = (unsigned long)pci_resource_len (pdev, 0);
6375 pio_flags = (unsigned long)pci_resource_flags (pdev, 0);
6376
6377 if (!(pio_flags & IORESOURCE_IO)) {
6378 RT_TRACE(COMP_ERR,"region #0 not a PIO resource, aborting");
6379 goto fail;
6380 }
6381
6382 //DMESG("IO space @ 0x%08lx", pio_start );
6383 if( ! request_region( pio_start, pio_len, RTL819xE_MODULE_NAME ) ){
6384 RT_TRACE(COMP_ERR,"request_region failed!");
6385 goto fail;
6386 }
6387
6388 ioaddr = pio_start;
6389 dev->base_addr = ioaddr; // device I/O address
6390
6391#else
6392
6393 pmem_start = pci_resource_start(pdev, 1);
6394 pmem_len = pci_resource_len(pdev, 1);
6395 pmem_flags = pci_resource_flags (pdev, 1);
6396
6397 if (!(pmem_flags & IORESOURCE_MEM)) {
6398 RT_TRACE(COMP_ERR,"region #1 not a MMIO resource, aborting");
6399 goto fail;
6400 }
6401
6402 //DMESG("Memory mapped space @ 0x%08lx ", pmem_start);
6403 if( ! request_mem_region(pmem_start, pmem_len, RTL819xE_MODULE_NAME)) {
6404 RT_TRACE(COMP_ERR,"request_mem_region failed!");
6405 goto fail;
6406 }
6407
6408
6409 ioaddr = (unsigned long)ioremap_nocache( pmem_start, pmem_len);
6410 if( ioaddr == (unsigned long)NULL ){
6411 RT_TRACE(COMP_ERR,"ioremap failed!");
6412 // release_mem_region( pmem_start, pmem_len );
6413 goto fail1;
6414 }
6415
6416 dev->mem_start = ioaddr; // shared mem start
6417 dev->mem_end = ioaddr + pci_resource_len(pdev, 0); // shared mem end
6418
6419#endif //end #ifdef RTL_IO_MAP
6420
6421 /* We disable the RETRY_TIMEOUT register (0x41) to keep
6422 * PCI Tx retries from interfering with C3 CPU state */
6423 pci_write_config_byte(pdev, 0x41, 0x00);
6424
6425
6426 pci_read_config_byte(pdev, 0x05, &unit);
6427 pci_write_config_byte(pdev, 0x05, unit & (~0x04));
6428
6429 dev->irq = pdev->irq;
6430 priv->irq = 0;
6431
6432 dev->netdev_ops = &rtl8192_netdev_ops;
6433#if 0
6434 dev->open = rtl8192_open;
6435 dev->stop = rtl8192_close;
6436 //dev->hard_start_xmit = rtl8192_8023_hard_start_xmit;
6437 dev->tx_timeout = tx_timeout;
6438 //dev->wireless_handlers = &r8192_wx_handlers_def;
6439 dev->do_ioctl = rtl8192_ioctl;
6440 dev->set_multicast_list = r8192_set_multicast;
6441 dev->set_mac_address = r8192_set_mac_adr;
6442#endif
6443
6444 //DMESG("Oops: i'm coming\n");
6445#if WIRELESS_EXT >= 12
6446#if WIRELESS_EXT < 17
6447 dev->get_wireless_stats = r8192_get_wireless_stats;
6448#endif
6449 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
6450#endif
6451 //dev->get_wireless_stats = r8192_get_wireless_stats;
6452 dev->type=ARPHRD_ETHER;
6453
6454 dev->watchdog_timeo = HZ*3; //modified by john, 0805
6455
6456 if (dev_alloc_name(dev, ifname) < 0){
6457 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
6458 ifname = "wlan%d";
6459 dev_alloc_name(dev, ifname);
6460 }
6461
6462 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
6463 if(rtl8192_init(dev)!=0){
6464 RT_TRACE(COMP_ERR, "Initialization failed");
6465 goto fail;
6466 }
6467
6468 netif_carrier_off(dev);
6469 netif_stop_queue(dev);
6470
6471 register_netdev(dev);
6472 RT_TRACE(COMP_INIT, "dev name=======> %s\n",dev->name);
6473 rtl8192_proc_init_one(dev);
6474
6475
6476 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006477 return 0;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006478
6479fail1:
6480
6481#ifdef CONFIG_RTL8180_IO_MAP
6482
6483 if( dev->base_addr != 0 ){
6484
6485 release_region(dev->base_addr,
6486 pci_resource_len(pdev, 0) );
6487 }
6488#else
6489 if( dev->mem_start != (unsigned long)NULL ){
6490 iounmap( (void *)dev->mem_start );
6491 release_mem_region( pci_resource_start(pdev, 1),
6492 pci_resource_len(pdev, 1) );
6493 }
6494#endif //end #ifdef RTL_IO_MAP
6495
6496fail:
6497 if(dev){
6498
6499 if (priv->irq) {
6500 free_irq(dev->irq, dev);
6501 dev->irq=0;
6502 }
6503 free_ieee80211(dev);
6504 }
6505
6506 pci_disable_device(pdev);
6507
6508 DMESG("wlan driver load failed\n");
6509 pci_set_drvdata(pdev, NULL);
6510 return -ENODEV;
6511
6512}
6513
6514/* detach all the work and timer structure declared or inititialized
6515 * in r8192_init function.
6516 * */
6517void rtl8192_cancel_deferred_work(struct r8192_priv* priv)
6518{
6519 /* call cancel_work_sync instead of cancel_delayed_work if and only if Linux_version_code
6520 * is or is newer than 2.6.20 and work structure is defined to be struct work_struct.
6521 * Otherwise call cancel_delayed_work is enough.
Adam Buchbinder39cfb972009-12-18 15:43:51 -05006522 * FIXME (2.6.20 should 2.6.22, work_struct should not cancel)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006523 * */
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006524 cancel_delayed_work(&priv->watch_dog_wq);
6525 cancel_delayed_work(&priv->update_beacon_wq);
6526 cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq);
6527 cancel_delayed_work(&priv->ieee80211->hw_sleep_wq);
6528#ifdef RTL8192E
6529 cancel_delayed_work(&priv->gpio_change_rf_wq);
6530#endif
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006531 cancel_work_sync(&priv->reset_wq);
6532 cancel_work_sync(&priv->qos_activate);
6533 //cancel_work_sync(&priv->SetBWModeWorkItem);
6534 //cancel_work_sync(&priv->SwChnlWorkItem);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006535
6536}
6537
6538
6539static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev)
6540{
6541 struct net_device *dev = pci_get_drvdata(pdev);
6542 struct r8192_priv *priv ;
6543
6544 if(dev){
6545
6546 unregister_netdev(dev);
6547
6548 priv=ieee80211_priv(dev);
6549
6550 rtl8192_proc_remove_one(dev);
6551
6552 rtl8192_down(dev);
6553 if (priv->pFirmware)
6554 {
6555 vfree(priv->pFirmware);
6556 priv->pFirmware = NULL;
6557 }
6558 // priv->rf_close(dev);
6559 // rtl8192_usb_deleteendpoints(dev);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006560 destroy_workqueue(priv->priv_wq);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006561 /* redundant with rtl8192_down */
6562 // rtl8192_irq_disable(dev);
6563 // rtl8192_reset(dev);
6564 // mdelay(10);
6565 {
6566 u32 i;
6567 /* free tx/rx rings */
6568 rtl8192_free_rx_ring(dev);
6569 for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
6570 rtl8192_free_tx_ring(dev, i);
6571 }
6572 }
6573 if(priv->irq){
6574
6575 printk("Freeing irq %d\n",dev->irq);
6576 free_irq(dev->irq, dev);
6577 priv->irq=0;
6578
6579 }
6580
6581
6582
6583 // free_beacon_desc_ring(dev,priv->txbeaconcount);
6584
6585#ifdef CONFIG_RTL8180_IO_MAP
6586
6587 if( dev->base_addr != 0 ){
6588
6589 release_region(dev->base_addr,
6590 pci_resource_len(pdev, 0) );
6591 }
6592#else
6593 if( dev->mem_start != (unsigned long)NULL ){
6594 iounmap( (void *)dev->mem_start );
6595 release_mem_region( pci_resource_start(pdev, 1),
6596 pci_resource_len(pdev, 1) );
6597 }
6598#endif /*end #ifdef RTL_IO_MAP*/
6599 free_ieee80211(dev);
6600
6601 }
6602
6603 pci_disable_device(pdev);
6604 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
6605}
6606
George Kadianakisfb5fe272009-12-17 01:18:08 +02006607extern int ieee80211_rtl_init(void);
6608extern void ieee80211_rtl_exit(void);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006609
6610static int __init rtl8192_pci_module_init(void)
6611{
6612 int retval;
6613
George Kadianakisfb5fe272009-12-17 01:18:08 +02006614 retval = ieee80211_rtl_init();
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006615 if (retval)
6616 return retval;
6617
6618 printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n");
6619 printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n");
6620 RT_TRACE(COMP_INIT, "Initializing module");
6621 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
6622 rtl8192_proc_module_init();
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006623 if(0!=pci_register_driver(&rtl8192_pci_driver))
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006624 {
6625 DMESG("No device found");
6626 /*pci_unregister_driver (&rtl8192_pci_driver);*/
6627 return -ENODEV;
6628 }
6629 return 0;
6630}
6631
6632
6633static void __exit rtl8192_pci_module_exit(void)
6634{
6635 pci_unregister_driver(&rtl8192_pci_driver);
6636
6637 RT_TRACE(COMP_DOWN, "Exiting");
6638 rtl8192_proc_module_remove();
George Kadianakisfb5fe272009-12-17 01:18:08 +02006639 ieee80211_rtl_exit();
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006640}
6641
6642//warning message WB
Mike McCormack559fba52010-07-26 22:57:52 +09006643static irqreturn_t rtl8192_interrupt(int irq, void *netdev)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006644{
6645 struct net_device *dev = (struct net_device *) netdev;
6646 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
6647 unsigned long flags;
6648 u32 inta;
6649 /* We should return IRQ_NONE, but for now let me keep this */
6650 if(priv->irq_enabled == 0){
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006651 return IRQ_HANDLED;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006652 }
6653
6654 spin_lock_irqsave(&priv->irq_th_lock,flags);
6655
6656 //ISR: 4bytes
6657
6658 inta = read_nic_dword(dev, ISR);// & priv->IntrMask;
6659 write_nic_dword(dev,ISR,inta); // reset int situation
6660
6661 priv->stats.shints++;
6662 //DMESG("Enter interrupt, ISR value = 0x%08x", inta);
6663 if(!inta){
6664 spin_unlock_irqrestore(&priv->irq_th_lock,flags);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006665 return IRQ_HANDLED;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006666 /*
6667 most probably we can safely return IRQ_NONE,
6668 but for now is better to avoid problems
6669 */
6670 }
6671
6672 if(inta == 0xffff){
6673 /* HW disappared */
6674 spin_unlock_irqrestore(&priv->irq_th_lock,flags);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006675 return IRQ_HANDLED;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006676 }
6677
6678 priv->stats.ints++;
6679#ifdef DEBUG_IRQ
6680 DMESG("NIC irq %x",inta);
6681#endif
6682 //priv->irqpending = inta;
6683
6684
6685 if(!netif_running(dev)) {
6686 spin_unlock_irqrestore(&priv->irq_th_lock,flags);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006687 return IRQ_HANDLED;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006688 }
6689
6690 if(inta & IMR_TIMEOUT0){
6691 // write_nic_dword(dev, TimerInt, 0);
6692 //DMESG("=================>waking up");
6693 // rtl8180_hw_wakeup(dev);
6694 }
6695
6696 if(inta & IMR_TBDOK){
6697 RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
6698 rtl8192_tx_isr(dev, BEACON_QUEUE);
6699 priv->stats.txbeaconokint++;
6700 }
6701
6702 if(inta & IMR_TBDER){
6703 RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
6704 rtl8192_tx_isr(dev, BEACON_QUEUE);
6705 priv->stats.txbeaconerr++;
6706 }
6707
6708 if(inta & IMR_MGNTDOK ) {
6709 RT_TRACE(COMP_INTR, "Manage ok interrupt!\n");
6710 priv->stats.txmanageokint++;
6711 rtl8192_tx_isr(dev,MGNT_QUEUE);
6712
6713 }
6714
6715 if(inta & IMR_COMDOK)
6716 {
6717 priv->stats.txcmdpktokint++;
6718 rtl8192_tx_isr(dev,TXCMD_QUEUE);
6719 }
6720
6721 if(inta & IMR_ROK){
6722#ifdef DEBUG_RX
6723 DMESG("Frame arrived !");
6724#endif
6725 priv->stats.rxint++;
6726 tasklet_schedule(&priv->irq_rx_tasklet);
6727 }
6728
6729 if(inta & IMR_BcnInt) {
6730 RT_TRACE(COMP_INTR, "prepare beacon for interrupt!\n");
6731 tasklet_schedule(&priv->irq_prepare_beacon_tasklet);
6732 }
6733
6734 if(inta & IMR_RDU){
6735 RT_TRACE(COMP_INTR, "rx descriptor unavailable!\n");
6736 priv->stats.rxrdu++;
6737 /* reset int situation */
6738 write_nic_dword(dev,INTA_MASK,read_nic_dword(dev, INTA_MASK) & ~IMR_RDU);
6739 tasklet_schedule(&priv->irq_rx_tasklet);
6740 }
6741
6742 if(inta & IMR_RXFOVW){
6743 RT_TRACE(COMP_INTR, "rx overflow !\n");
6744 priv->stats.rxoverflow++;
6745 tasklet_schedule(&priv->irq_rx_tasklet);
6746 }
6747
6748 if(inta & IMR_TXFOVW) priv->stats.txoverflow++;
6749
6750 if(inta & IMR_BKDOK){
6751 RT_TRACE(COMP_INTR, "BK Tx OK interrupt!\n");
6752 priv->stats.txbkokint++;
6753 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
6754 rtl8192_tx_isr(dev,BK_QUEUE);
6755 rtl8192_try_wake_queue(dev, BK_QUEUE);
6756 }
6757
6758 if(inta & IMR_BEDOK){
6759 RT_TRACE(COMP_INTR, "BE TX OK interrupt!\n");
6760 priv->stats.txbeokint++;
6761 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
6762 rtl8192_tx_isr(dev,BE_QUEUE);
6763 rtl8192_try_wake_queue(dev, BE_QUEUE);
6764 }
6765
6766 if(inta & IMR_VIDOK){
6767 RT_TRACE(COMP_INTR, "VI TX OK interrupt!\n");
6768 priv->stats.txviokint++;
6769 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
6770 rtl8192_tx_isr(dev,VI_QUEUE);
6771 rtl8192_try_wake_queue(dev, VI_QUEUE);
6772 }
6773
6774 if(inta & IMR_VODOK){
6775 priv->stats.txvookint++;
6776 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
6777 rtl8192_tx_isr(dev,VO_QUEUE);
6778 rtl8192_try_wake_queue(dev, VO_QUEUE);
6779 }
6780
6781 force_pci_posting(dev);
6782 spin_unlock_irqrestore(&priv->irq_th_lock,flags);
6783
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006784 return IRQ_HANDLED;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006785}
6786
Mike McCormack559fba52010-07-26 22:57:52 +09006787static void rtl8192_try_wake_queue(struct net_device *dev, int pri)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006788{
6789#if 0
6790 unsigned long flags;
6791 short enough_desc;
6792 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
6793
6794 spin_lock_irqsave(&priv->tx_lock,flags);
6795 enough_desc = check_nic_enough_desc(dev,pri);
6796 spin_unlock_irqrestore(&priv->tx_lock,flags);
6797
6798 if(enough_desc)
George Kadianakisfb5fe272009-12-17 01:18:08 +02006799 ieee80211_rtl_wake_queue(priv->ieee80211);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006800#endif
6801}
6802
6803
6804void EnableHWSecurityConfig8192(struct net_device *dev)
6805{
6806 u8 SECR_value = 0x0;
6807 // struct ieee80211_device* ieee1 = container_of(&dev, struct ieee80211_device, dev);
6808 //printk("==>ieee1:%p, dev:%p\n", ieee1, dev);
6809 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
6810 struct ieee80211_device* ieee = priv->ieee80211;
6811 //printk("==>ieee:%p, dev:%p\n", ieee, dev);
6812 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
6813#if 1
6814 if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->ieee80211->auth_mode != 2))
6815 {
6816 SECR_value |= SCR_RxUseDK;
6817 SECR_value |= SCR_TxUseDK;
6818 }
6819 else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP)))
6820 {
6821 SECR_value |= SCR_RxUseDK;
6822 SECR_value |= SCR_TxUseDK;
6823 }
6824
6825#endif
6826
6827 //add HWSec active enable here.
6828//default using hwsec. when peer AP is in N mode only and pairwise_key_type is none_aes(which HT_IOT_ACT_PURE_N_MODE indicates it), use software security. when peer AP is in b,g,n mode mixed and pairwise_key_type is none_aes, use g mode hw security. WB on 2008.7.4
6829 ieee->hwsec_active = 1;
6830
6831 if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep)//!ieee->hwsec_support) //add hwsec_support flag to totol control hw_sec on/off
6832 {
6833 ieee->hwsec_active = 0;
6834 SECR_value &= ~SCR_RxDecEnable;
6835 }
6836
6837 RT_TRACE(COMP_SEC,"%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __FUNCTION__, \
6838 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
6839 {
6840 write_nic_byte(dev, SECR, SECR_value);//SECR_value | SCR_UseDK );
6841 }
6842
6843}
6844#define TOTAL_CAM_ENTRY 32
6845//#define CAM_CONTENT_COUNT 8
6846void setKey( struct net_device *dev,
6847 u8 EntryNo,
6848 u8 KeyIndex,
6849 u16 KeyType,
Mike McCormack881a9752010-07-26 22:58:03 +09006850 const u8 *MacAddr,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006851 u8 DefaultKey,
6852 u32 *KeyContent )
6853{
6854 u32 TargetCommand = 0;
6855 u32 TargetContent = 0;
6856 u16 usConfig = 0;
6857 u8 i;
6858#ifdef ENABLE_IPS
6859 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
6860 RT_RF_POWER_STATE rtState;
6861 rtState = priv->ieee80211->eRFPowerState;
6862 if(priv->ieee80211->PowerSaveControl.bInactivePs){
6863 if(rtState == eRfOff){
6864 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
6865 {
6866 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
david woo65a43782009-12-22 09:40:36 -08006867 //up(&priv->wx_sem);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006868 return ;
6869 }
6870 else{
david woo65a43782009-12-22 09:40:36 -08006871 down(&priv->ieee80211->ips_sem);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006872 IPSLeave(dev);
david woo65a43782009-12-22 09:40:36 -08006873 up(&priv->ieee80211->ips_sem);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006874 }
6875 }
6876 }
6877 priv->ieee80211->is_set_key = true;
6878#endif
6879 if (EntryNo >= TOTAL_CAM_ENTRY)
6880 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
6881
Joe Perches0ee9f672009-12-06 11:34:52 -08006882 RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", dev,EntryNo, KeyIndex, KeyType, MacAddr);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006883
6884 if (DefaultKey)
6885 usConfig |= BIT15 | (KeyType<<2);
6886 else
6887 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
6888// usConfig |= BIT15 | (KeyType<<2) | (DefaultKey<<5) | KeyIndex;
6889
6890
6891 for(i=0 ; i<CAM_CONTENT_COUNT; i++){
6892 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
6893 TargetCommand |= BIT31|BIT16;
6894
6895 if(i==0){//MAC|Config
6896 TargetContent = (u32)(*(MacAddr+0)) << 16|
6897 (u32)(*(MacAddr+1)) << 24|
6898 (u32)usConfig;
6899
6900 write_nic_dword(dev, WCAMI, TargetContent);
6901 write_nic_dword(dev, RWCAM, TargetCommand);
6902 // printk("setkey cam =%8x\n", read_cam(dev, i+6*EntryNo));
6903 }
6904 else if(i==1){//MAC
6905 TargetContent = (u32)(*(MacAddr+2)) |
6906 (u32)(*(MacAddr+3)) << 8|
6907 (u32)(*(MacAddr+4)) << 16|
6908 (u32)(*(MacAddr+5)) << 24;
6909 write_nic_dword(dev, WCAMI, TargetContent);
6910 write_nic_dword(dev, RWCAM, TargetCommand);
6911 }
6912 else { //Key Material
6913 if(KeyContent != NULL)
6914 {
6915 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)) );
6916 write_nic_dword(dev, RWCAM, TargetCommand);
6917 }
6918 }
6919 }
6920 RT_TRACE(COMP_SEC,"=========>after set key, usconfig:%x\n", usConfig);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07006921}
6922// This function seems not ready! WB
6923void CamPrintDbgReg(struct net_device* dev)
6924{
6925 unsigned long rvalue;
6926 unsigned char ucValue;
6927 write_nic_dword(dev, DCAM, 0x80000000);
6928 msleep(40);
6929 rvalue = read_nic_dword(dev, DCAM); //delay_ms(40);
6930 RT_TRACE(COMP_SEC, " TX CAM=%8lX ",rvalue);
6931 if((rvalue & 0x40000000) != 0x4000000)
6932 RT_TRACE(COMP_SEC, "-->TX Key Not Found ");
6933 msleep(20);
6934 write_nic_dword(dev, DCAM, 0x00000000); //delay_ms(40);
6935 rvalue = read_nic_dword(dev, DCAM); //delay_ms(40);
6936 RT_TRACE(COMP_SEC, "RX CAM=%8lX ",rvalue);
6937 if((rvalue & 0x40000000) != 0x4000000)
6938 RT_TRACE(COMP_SEC, "-->CAM Key Not Found ");
6939 ucValue = read_nic_byte(dev, SECR);
6940 RT_TRACE(COMP_SEC, "WPA_Config=%x \n",ucValue);
6941}
6942
david woo65a43782009-12-22 09:40:36 -08006943bool NicIFEnableNIC(struct net_device* dev)
6944{
6945 RT_STATUS init_status = RT_STATUS_SUCCESS;
6946 struct r8192_priv* priv = ieee80211_priv(dev);
6947 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
6948
6949 //YJ,add,091109
6950 if (priv->up == 0){
6951 RT_TRACE(COMP_ERR, "ERR!!! %s(): Driver is already down!\n",__FUNCTION__);
6952 priv->bdisable_nic = false; //YJ,add,091111
6953 return false;
6954 }
6955 // <1> Reset memory: descriptor, buffer,..
6956 //NicIFResetMemory(Adapter);
6957
6958 // <2> Enable Adapter
6959 //printk("===========>%s()\n",__FUNCTION__);
6960 //priv->bfirst_init = true;
6961 init_status = rtl8192_adapter_start(dev);
6962 if (init_status != RT_STATUS_SUCCESS) {
6963 RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
6964 priv->bdisable_nic = false; //YJ,add,091111
6965 return -1;
6966 }
6967 //printk("start adapter finished\n");
6968 RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
6969 //priv->bfirst_init = false;
6970
6971 // <3> Enable Interrupt
6972 rtl8192_irq_enable(dev);
6973 priv->bdisable_nic = false;
6974 //RT_TRACE(COMP_PS,"<===========%s()\n",__FUNCTION__);
6975 return (init_status == RT_STATUS_SUCCESS) ? true:false;
6976}
6977bool NicIFDisableNIC(struct net_device* dev)
6978{
6979 bool status = true;
6980 struct r8192_priv* priv = ieee80211_priv(dev);
6981 u8 tmp_state = 0;
6982 // <1> Disable Interrupt
6983 //RT_TRACE(COMP_PS, "=========>%s()\n",__FUNCTION__);
6984 priv->bdisable_nic = true; //YJ,move,091109
6985 tmp_state = priv->ieee80211->state;
6986
6987 ieee80211_softmac_stop_protocol(priv->ieee80211, false);
6988
6989 priv->ieee80211->state = tmp_state;
6990 rtl8192_cancel_deferred_work(priv);
6991 rtl8192_irq_disable(dev);
6992 // <2> Stop all timer
6993
6994 // <3> Disable Adapter
6995 rtl8192_halt_adapter(dev, false);
6996// priv->bdisable_nic = true;
6997 //RT_TRACE(COMP_PS, "<=========%s()\n",__FUNCTION__);
6998
6999 return status;
7000}
7001
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07007002
7003/***************************************************************************
7004 ------------------- module init / exit stubs ----------------
7005****************************************************************************/
7006module_init(rtl8192_pci_module_init);
7007module_exit(rtl8192_pci_module_exit);