blob: 7aa464224d101c1754687bb2a99a1a68efa458e5 [file] [log] [blame]
Jerry Chuang8fc85982009-11-03 07:17:11 -02001/******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3 * Linux device driver for RTL8192U
4 *
5 * Based on the r8187 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
27#ifndef CONFIG_FORCE_HARD_FLOAT
28double __floatsidf (int i) { return i; }
29unsigned int __fixunsdfsi (double d) { return d; }
30double __adddf3(double a, double b) { return a+b; }
31double __addsf3(float a, float b) { return a+b; }
32double __subdf3(double a, double b) { return a-b; }
33double __extendsfdf2(float a) {return a;}
34#endif
35
36#undef LOOP_TEST
37#undef DUMP_RX
38#undef DUMP_TX
39#undef DEBUG_TX_DESC2
40#undef RX_DONT_PASS_UL
41#undef DEBUG_EPROM
42#undef DEBUG_RX_VERBOSE
43#undef DUMMY_RX
44#undef DEBUG_ZERO_RX
45#undef DEBUG_RX_SKB
46#undef DEBUG_TX_FRAG
47#undef DEBUG_RX_FRAG
48#undef DEBUG_TX_FILLDESC
49#undef DEBUG_TX
50#undef DEBUG_IRQ
51#undef DEBUG_RX
52#undef DEBUG_RXALLOC
53#undef DEBUG_REGISTERS
54#undef DEBUG_RING
55#undef DEBUG_IRQ_TASKLET
56#undef DEBUG_TX_ALLOC
57#undef DEBUG_TX_DESC
58
59#define CONFIG_RTL8192_IO_MAP
60
61#include <asm/uaccess.h>
62#include "r8192U_hw.h"
63#include "r8192U.h"
64#include "r8190_rtl8256.h" /* RTL8225 Radio frontend */
65#include "r8180_93cx6.h" /* Card EEPROM */
66#include "r8192U_wx.h"
67#include "r819xU_phy.h" //added by WB 4.30.2008
68#include "r819xU_phyreg.h"
69#include "r819xU_cmdpkt.h"
70#include "r8192U_dm.h"
71//#include "r8192xU_phyreg.h"
72#include <linux/usb.h>
73// FIXME: check if 2.6.7 is ok
74#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7))
75#define usb_kill_urb usb_unlink_urb
76#endif
77
78#ifdef CONFIG_RTL8192_PM
79#include "r8192_pm.h"
80#endif
81
82#ifdef ENABLE_DOT11D
83#include "dot11d.h"
84#endif
85//set here to open your trace code. //WB
86u32 rt_global_debug_component = \
87 // COMP_INIT |
88// COMP_DBG |
89 // COMP_EPROM |
90// COMP_PHY |
91 // COMP_RF |
92// COMP_FIRMWARE |
93// COMP_CH |
94 // COMP_POWER_TRACKING |
95// COMP_RATE |
96 // COMP_TXAGC |
97 // COMP_TRACE |
98 COMP_DOWN |
99 // COMP_RECV |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200100 // COMP_SWBW |
Jerry Chuang8fc85982009-11-03 07:17:11 -0200101 COMP_SEC |
102 // COMP_RESET |
103 // COMP_SEND |
104 // COMP_EVENTS |
105 COMP_ERR ; //always open err flags on
106
107#define TOTAL_CAM_ENTRY 32
108#define CAM_CONTENT_COUNT 8
109
110static struct usb_device_id rtl8192_usb_id_tbl[] = {
111 /* Realtek */
112 {USB_DEVICE(0x0bda, 0x8192)},
113 {USB_DEVICE(0x0bda, 0x8709)},
114 /* Corega */
115 {USB_DEVICE(0x07aa, 0x0043)},
116 /* Belkin */
117 {USB_DEVICE(0x050d, 0x805E)},
118 /* Sitecom */
119 {USB_DEVICE(0x0df6, 0x0031)},
120 /* EnGenius */
121 {USB_DEVICE(0x1740, 0x9201)},
122 /* Dlink */
123 {USB_DEVICE(0x2001, 0x3301)},
124 /* Zinwell */
125 {USB_DEVICE(0x5a57, 0x0290)},
126 {}
127};
128
129MODULE_LICENSE("GPL");
130#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
131MODULE_VERSION("V 1.1");
132#endif
133MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl);
134MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards");
135
136static char* ifname = "wlan%d";
137#if 0
138static int hwseqnum = 0;
139static int hwwep = 0;
140#endif
141static int hwwep = 1; //default use hw. set 0 to use software security
142static int channels = 0x3fff;
143
144
145
146#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
147module_param(ifname, charp, S_IRUGO|S_IWUSR );
148//module_param(hwseqnum,int, S_IRUGO|S_IWUSR);
149module_param(hwwep,int, S_IRUGO|S_IWUSR);
150module_param(channels,int, S_IRUGO|S_IWUSR);
151#else
152MODULE_PARM(ifname, "s");
153//MODULE_PARM(hwseqnum,"i");
154MODULE_PARM(hwwep,"i");
155MODULE_PARM(channels,"i");
156#endif
157
158MODULE_PARM_DESC(ifname," Net interface name, wlan%d=default");
159//MODULE_PARM_DESC(hwseqnum," Try to use hardware 802.11 header sequence numbers. Zero=default");
160MODULE_PARM_DESC(hwwep," Try to use hardware security support. ");
161MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI");
162
163#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
164static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
165 const struct usb_device_id *id);
166static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf);
167#else
168static void *__devinit rtl8192_usb_probe(struct usb_device *udev,unsigned int ifnum,
169 const struct usb_device_id *id);
170static void __devexit rtl8192_usb_disconnect(struct usb_device *udev, void *ptr);
171#endif
172
173
174static struct usb_driver rtl8192_usb_driver = {
175#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
176 .owner = THIS_MODULE,
177#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200178 .name = RTL819xU_MODULE_NAME, /* Driver name */
179 .id_table = rtl8192_usb_id_tbl, /* PCI_ID table */
180 .probe = rtl8192_usb_probe, /* probe fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200181 .disconnect = rtl8192_usb_disconnect, /* remove fn */
182#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)
183#ifdef CONFIG_RTL8192_PM
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200184 .suspend = rtl8192_suspend, /* PM suspend fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200185 .resume = rtl8192_resume, /* PM resume fn */
186#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200187 .suspend = NULL, /* PM suspend fn */
188 .resume = NULL, /* PM resume fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200189#endif
190#endif
191};
192
193#ifdef ENABLE_DOT11D
194
195typedef struct _CHANNEL_LIST
196{
197 u8 Channel[32];
198 u8 Len;
199}CHANNEL_LIST, *PCHANNEL_LIST;
200
201static CHANNEL_LIST ChannelPlan[] = {
202 {{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
203 {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC
204 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //ETSI
205 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Spain. Change to ETSI.
206 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //France. Change to ETSI.
207 {{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
208 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1
209 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Israel.
210 {{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
211 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22}, //MIC
212 {{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
213};
214
215static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv* priv)
216{
217 int i, max_chan=-1, min_chan=-1;
218 struct ieee80211_device* ieee = priv->ieee80211;
219 switch (channel_plan)
220 {
221 case COUNTRY_CODE_FCC:
222 case COUNTRY_CODE_IC:
223 case COUNTRY_CODE_ETSI:
224 case COUNTRY_CODE_SPAIN:
225 case COUNTRY_CODE_FRANCE:
226 case COUNTRY_CODE_MKK:
227 case COUNTRY_CODE_MKK1:
228 case COUNTRY_CODE_ISRAEL:
229 case COUNTRY_CODE_TELEC:
230 case COUNTRY_CODE_MIC:
231 {
232 Dot11d_Init(ieee);
233 ieee->bGlobalDomain = false;
234 //acturally 8225 & 8256 rf chip only support B,G,24N mode
235 if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256))
236 {
237 min_chan = 1;
238 max_chan = 14;
239 }
240 else
241 {
242 RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __FUNCTION__);
243 }
244 if (ChannelPlan[channel_plan].Len != 0){
245 // Clear old channel map
246 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
247 // Set new channel map
248 for (i=0;i<ChannelPlan[channel_plan].Len;i++)
249 {
250 if (ChannelPlan[channel_plan].Channel[i] < min_chan || ChannelPlan[channel_plan].Channel[i] > max_chan)
251 break;
252 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
253 }
254 }
255 break;
256 }
257 case COUNTRY_CODE_GLOBAL_DOMAIN:
258 {
259 GET_DOT11D_INFO(ieee)->bEnabled = 0;//this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain settings.
260 Dot11d_Reset(ieee);
261 ieee->bGlobalDomain = true;
262 break;
263 }
264 default:
265 break;
266 }
267 return;
268}
269#endif
270
271#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 )
272
273#define rx_hal_is_cck_rate(_pdrvinfo)\
274 (_pdrvinfo->RxRate == DESC90_RATE1M ||\
275 _pdrvinfo->RxRate == DESC90_RATE2M ||\
276 _pdrvinfo->RxRate == DESC90_RATE5_5M ||\
277 _pdrvinfo->RxRate == DESC90_RATE11M) &&\
278 !_pdrvinfo->RxHT\
279
280
281void CamResetAllEntry(struct net_device *dev)
282{
283#if 1
284 u32 ulcommand = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200285 //2004/02/11 In static WEP, OID_ADD_KEY or OID_ADD_WEP are set before STA associate to AP.
286 // However, ResetKey is called on OID_802_11_INFRASTRUCTURE_MODE and MlmeAssociateRequest
287 // In this condition, Cam can not be reset because upper layer will not set this static key again.
288 //if(Adapter->EncAlgorithm == WEP_Encryption)
289 // return;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200290//debug
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200291 //DbgPrint("========================================\n");
292 //DbgPrint(" Call ResetAllEntry \n");
293 //DbgPrint("========================================\n\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200294 ulcommand |= BIT31|BIT30;
295 write_nic_dword(dev, RWCAM, ulcommand);
296#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200297 for(ucIndex=0;ucIndex<TOTAL_CAM_ENTRY;ucIndex++)
298 CAM_mark_invalid(dev, ucIndex);
299 for(ucIndex=0;ucIndex<TOTAL_CAM_ENTRY;ucIndex++)
300 CAM_empty_entry(dev, ucIndex);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200301#endif
302
303}
304
305
306void write_cam(struct net_device *dev, u8 addr, u32 data)
307{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200308 write_nic_dword(dev, WCAMI, data);
309 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff) );
Jerry Chuang8fc85982009-11-03 07:17:11 -0200310}
311
312u32 read_cam(struct net_device *dev, u8 addr)
313{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200314 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff) );
315 return read_nic_dword(dev, 0xa8);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200316}
317
318void write_nic_byte_E(struct net_device *dev, int indx, u8 data)
319{
320 int status;
321 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
322 struct usb_device *udev = priv->udev;
323
324 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
325 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
326 indx|0xfe00, 0, &data, 1, HZ / 2);
327
328 if (status < 0)
329 {
330 printk("write_nic_byte_E TimeOut! status:%d\n", status);
331 }
332}
333
334u8 read_nic_byte_E(struct net_device *dev, int indx)
335{
336 int status;
337 u8 data;
338 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
339 struct usb_device *udev = priv->udev;
340
341 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
342 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
343 indx|0xfe00, 0, &data, 1, HZ / 2);
344
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200345 if (status < 0)
346 {
347 printk("read_nic_byte_E TimeOut! status:%d\n", status);
348 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200349
350 return data;
351}
352//as 92U has extend page from 4 to 16, so modify functions below.
353void write_nic_byte(struct net_device *dev, int indx, u8 data)
354{
355 int status;
356
357 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
358 struct usb_device *udev = priv->udev;
359
360 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
361 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
362 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
363
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200364 if (status < 0)
365 {
366 printk("write_nic_byte TimeOut! status:%d\n", status);
367 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200368
369
370}
371
372
373void write_nic_word(struct net_device *dev, int indx, u16 data)
374{
375
376 int status;
377
378 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
379 struct usb_device *udev = priv->udev;
380
381 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
382 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
383 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2);
384
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200385 if (status < 0)
386 {
387 printk("write_nic_word TimeOut! status:%d\n", status);
388 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200389
390}
391
392
393void write_nic_dword(struct net_device *dev, int indx, u32 data)
394{
395
396 int status;
397
398 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
399 struct usb_device *udev = priv->udev;
400
401 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
402 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
403 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2);
404
405
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200406 if (status < 0)
407 {
408 printk("write_nic_dword TimeOut! status:%d\n", status);
409 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200410
411}
412
413
414
415u8 read_nic_byte(struct net_device *dev, int indx)
416{
417 u8 data;
418 int status;
419 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
420 struct usb_device *udev = priv->udev;
421
422 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
423 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
424 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
425
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200426 if (status < 0)
427 {
428 printk("read_nic_byte TimeOut! status:%d\n", status);
429 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200430
431 return data;
432}
433
434
435
436u16 read_nic_word(struct net_device *dev, int indx)
437{
438 u16 data;
439 int status;
440 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
441 struct usb_device *udev = priv->udev;
442
443 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
444 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
445 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2);
446
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200447 if (status < 0)
448 {
449 printk("read_nic_word TimeOut! status:%d\n", status);
450 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200451
452
453 return data;
454}
455
456u16 read_nic_word_E(struct net_device *dev, int indx)
457{
458 u16 data;
459 int status;
460 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
461 struct usb_device *udev = priv->udev;
462
463 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
464 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
465 indx|0xfe00, 0, &data, 2, HZ / 2);
466
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200467 if (status < 0)
468 {
469 printk("read_nic_word TimeOut! status:%d\n", status);
470 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200471
472
473 return data;
474}
475
476u32 read_nic_dword(struct net_device *dev, int indx)
477{
478 u32 data;
479 int status;
480// int result;
481
482 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
483 struct usb_device *udev = priv->udev;
484
485 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
486 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
487 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2);
488// if(0 != result) {
489// printk(KERN_WARNING "read size of data = %d\, date = %d\n", result, data);
490// }
491
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200492 if (status < 0)
493 {
494 printk("read_nic_dword TimeOut! status:%d\n", status);
495 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200496
497
498
499 return data;
500}
501
502
503//u8 read_phy_cck(struct net_device *dev, u8 adr);
504//u8 read_phy_ofdm(struct net_device *dev, u8 adr);
505/* this might still called in what was the PHY rtl8185/rtl8192 common code
506 * plans are to possibilty turn it again in one common code...
507 */
508inline void force_pci_posting(struct net_device *dev)
509{
510}
511
512
513static struct net_device_stats *rtl8192_stats(struct net_device *dev);
514void rtl8192_commit(struct net_device *dev);
515//void rtl8192_restart(struct net_device *dev);
516#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
517void rtl8192_restart(struct work_struct *work);
518//void rtl8192_rq_tx_ack(struct work_struct *work);
519#else
520 void rtl8192_restart(struct net_device *dev);
521// //void rtl8192_rq_tx_ack(struct net_device *dev);
522 #endif
523
524void watch_dog_timer_callback(unsigned long data);
525
526/****************************************************************************
527 -----------------------------PROCFS STUFF-------------------------
528*****************************************************************************/
529
530static struct proc_dir_entry *rtl8192_proc = NULL;
531
532
533
534static int proc_get_stats_ap(char *page, char **start,
535 off_t offset, int count,
536 int *eof, void *data)
537{
538 struct net_device *dev = data;
539 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
540 struct ieee80211_device *ieee = priv->ieee80211;
541 struct ieee80211_network *target;
542
543 int len = 0;
544
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200545 list_for_each_entry(target, &ieee->network_list, list) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200546
547 len += snprintf(page + len, count - len,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200548 "%s ", target->ssid);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200549
550 if(target->wpa_ie_len>0 || target->rsn_ie_len>0){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200551 len += snprintf(page + len, count - len,
552 "WPA\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200553 }
554 else{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200555 len += snprintf(page + len, count - len,
556 "non_WPA\n");
557 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200558
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200559 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200560
561 *eof = 1;
562 return len;
563}
564
565static int proc_get_registers(char *page, char **start,
566 off_t offset, int count,
567 int *eof, void *data)
568{
569 struct net_device *dev = data;
570// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
571
572 int len = 0;
573 int i,n;
574
575 int max=0xff;
576
577 /* This dump the current register page */
578len += snprintf(page + len, count - len,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200579 "\n####################page 0##################\n ");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200580
581 for(n=0;n<=max;)
582 {
583 //printk( "\nD: %2x> ", n);
584 len += snprintf(page + len, count - len,
585 "\nD: %2x > ",n);
586
587 for(i=0;i<16 && n<=max;i++,n++)
588 len += snprintf(page + len, count - len,
589 "%2x ",read_nic_byte(dev,0x000|n));
590
591 // printk("%2x ",read_nic_byte(dev,n));
592 }
593#if 1
594len += snprintf(page + len, count - len,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200595 "\n####################page 1##################\n ");
596 for(n=0;n<=max;)
597 {
598 //printk( "\nD: %2x> ", n);
599 len += snprintf(page + len, count - len,
600 "\nD: %2x > ",n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200601
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200602 for(i=0;i<16 && n<=max;i++,n++)
603 len += snprintf(page + len, count - len,
604 "%2x ",read_nic_byte(dev,0x100|n));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200605
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200606 // printk("%2x ",read_nic_byte(dev,n));
607 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200608len += snprintf(page + len, count - len,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200609 "\n####################page 3##################\n ");
610 for(n=0;n<=max;)
611 {
612 //printk( "\nD: %2x> ", n);
613 len += snprintf(page + len, count - len,
614 "\nD: %2x > ",n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200615
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200616 for(i=0;i<16 && n<=max;i++,n++)
617 len += snprintf(page + len, count - len,
618 "%2x ",read_nic_byte(dev,0x300|n));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200619
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200620 // printk("%2x ",read_nic_byte(dev,n));
621 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200622
623#endif
624
625 len += snprintf(page + len, count - len,"\n");
626 *eof = 1;
627 return len;
628
629}
630
631
632#if 0
633static int proc_get_cck_reg(char *page, char **start,
634 off_t offset, int count,
635 int *eof, void *data)
636{
637 struct net_device *dev = data;
638// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
639
640 int len = 0;
641 int i,n;
642
643 int max = 0x5F;
644
645 /* This dump the current register page */
646 for(n=0;n<=max;)
647 {
648 //printk( "\nD: %2x> ", n);
649 len += snprintf(page + len, count - len,
650 "\nD: %2x > ",n);
651
652 for(i=0;i<16 && n<=max;i++,n++)
653 len += snprintf(page + len, count - len,
654 "%2x ",read_phy_cck(dev,n));
655
656 // printk("%2x ",read_nic_byte(dev,n));
657 }
658 len += snprintf(page + len, count - len,"\n");
659
660
661 *eof = 1;
662 return len;
663}
664
665#endif
666
667#if 0
668static int proc_get_ofdm_reg(char *page, char **start,
669 off_t offset, int count,
670 int *eof, void *data)
671{
672 struct net_device *dev = data;
673// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
674
675 int len = 0;
676 int i,n;
677
678 //int max=0xff;
679 int max = 0x40;
680
681 /* This dump the current register page */
682 for(n=0;n<=max;)
683 {
684 //printk( "\nD: %2x> ", n);
685 len += snprintf(page + len, count - len,
686 "\nD: %2x > ",n);
687
688 for(i=0;i<16 && n<=max;i++,n++)
689 len += snprintf(page + len, count - len,
690 "%2x ",read_phy_ofdm(dev,n));
691
692 // printk("%2x ",read_nic_byte(dev,n));
693 }
694 len += snprintf(page + len, count - len,"\n");
695
696
697
698 *eof = 1;
699 return len;
700}
701
702#endif
703
704#if 0
705static int proc_get_stats_hw(char *page, char **start,
706 off_t offset, int count,
707 int *eof, void *data)
708{
709 struct net_device *dev = data;
710 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
711
712 int len = 0;
713
714 len += snprintf(page + len, count - len,
715 "NIC int: %lu\n"
716 "Total int: %lu\n",
717 priv->stats.ints,
718 priv->stats.shints);
719
720 *eof = 1;
721 return len;
722}
723#endif
724
725static int proc_get_stats_tx(char *page, char **start,
726 off_t offset, int count,
727 int *eof, void *data)
728{
729 struct net_device *dev = data;
730 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
731
732 int len = 0;
733
734 len += snprintf(page + len, count - len,
735 "TX VI priority ok int: %lu\n"
736 "TX VI priority error int: %lu\n"
737 "TX VO priority ok int: %lu\n"
738 "TX VO priority error int: %lu\n"
739 "TX BE priority ok int: %lu\n"
740 "TX BE priority error int: %lu\n"
741 "TX BK priority ok int: %lu\n"
742 "TX BK priority error int: %lu\n"
743 "TX MANAGE priority ok int: %lu\n"
744 "TX MANAGE priority error int: %lu\n"
745 "TX BEACON priority ok int: %lu\n"
746 "TX BEACON priority error int: %lu\n"
747// "TX high priority ok int: %lu\n"
748// "TX high priority failed error int: %lu\n"
749 "TX queue resume: %lu\n"
750 "TX queue stopped?: %d\n"
751 "TX fifo overflow: %lu\n"
752// "TX beacon: %lu\n"
753 "TX VI queue: %d\n"
754 "TX VO queue: %d\n"
755 "TX BE queue: %d\n"
756 "TX BK queue: %d\n"
757// "TX HW queue: %d\n"
758 "TX VI dropped: %lu\n"
759 "TX VO dropped: %lu\n"
760 "TX BE dropped: %lu\n"
761 "TX BK dropped: %lu\n"
762 "TX total data packets %lu\n",
763// "TX beacon aborted: %lu\n",
764 priv->stats.txviokint,
765 priv->stats.txvierr,
766 priv->stats.txvookint,
767 priv->stats.txvoerr,
768 priv->stats.txbeokint,
769 priv->stats.txbeerr,
770 priv->stats.txbkokint,
771 priv->stats.txbkerr,
772 priv->stats.txmanageokint,
773 priv->stats.txmanageerr,
774 priv->stats.txbeaconokint,
775 priv->stats.txbeaconerr,
776// priv->stats.txhpokint,
777// priv->stats.txhperr,
778 priv->stats.txresumed,
779 netif_queue_stopped(dev),
780 priv->stats.txoverflow,
781// priv->stats.txbeacon,
782 atomic_read(&(priv->tx_pending[VI_PRIORITY])),
783 atomic_read(&(priv->tx_pending[VO_PRIORITY])),
784 atomic_read(&(priv->tx_pending[BE_PRIORITY])),
785 atomic_read(&(priv->tx_pending[BK_PRIORITY])),
786// read_nic_byte(dev, TXFIFOCOUNT),
787 priv->stats.txvidrop,
788 priv->stats.txvodrop,
789 priv->stats.txbedrop,
790 priv->stats.txbkdrop,
791 priv->stats.txdatapkt
792// priv->stats.txbeaconerr
793 );
794
795 *eof = 1;
796 return len;
797}
798
799
800
801static int proc_get_stats_rx(char *page, char **start,
802 off_t offset, int count,
803 int *eof, void *data)
804{
805 struct net_device *dev = data;
806 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
807
808 int len = 0;
809
810 len += snprintf(page + len, count - len,
811 "RX packets: %lu\n"
812 "RX urb status error: %lu\n"
813 "RX invalid urb error: %lu\n",
814 priv->stats.rxoktotal,
815 priv->stats.rxstaterr,
816 priv->stats.rxurberr);
817
818 *eof = 1;
819 return len;
820}
821#if 0
822#if WIRELESS_EXT >= 12 && WIRELESS_EXT < 17
823
824static struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
825{
826 struct r8192_priv *priv = ieee80211_priv(dev);
827
828 return &priv->wstats;
829}
830#endif
831#endif
832void rtl8192_proc_module_init(void)
833{
834 RT_TRACE(COMP_INIT, "Initializing proc filesystem");
835#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
836 rtl8192_proc=create_proc_entry(RTL819xU_MODULE_NAME, S_IFDIR, proc_net);
837#else
838 rtl8192_proc=create_proc_entry(RTL819xU_MODULE_NAME, S_IFDIR, init_net.proc_net);
839#endif
840}
841
842
843void rtl8192_proc_module_remove(void)
844{
845#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
846 remove_proc_entry(RTL819xU_MODULE_NAME, proc_net);
847#else
848 remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net);
849#endif
850}
851
852
853void rtl8192_proc_remove_one(struct net_device *dev)
854{
855 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
856
857
858 if (priv->dir_dev) {
859 // remove_proc_entry("stats-hw", priv->dir_dev);
860 remove_proc_entry("stats-tx", priv->dir_dev);
861 remove_proc_entry("stats-rx", priv->dir_dev);
862 // remove_proc_entry("stats-ieee", priv->dir_dev);
863 remove_proc_entry("stats-ap", priv->dir_dev);
864 remove_proc_entry("registers", priv->dir_dev);
865 // remove_proc_entry("cck-registers",priv->dir_dev);
866 // remove_proc_entry("ofdm-registers",priv->dir_dev);
867 //remove_proc_entry(dev->name, rtl8192_proc);
868 remove_proc_entry("wlan0", rtl8192_proc);
869 priv->dir_dev = NULL;
870 }
871}
872
873
874void rtl8192_proc_init_one(struct net_device *dev)
875{
876 struct proc_dir_entry *e;
877 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
878 priv->dir_dev = create_proc_entry(dev->name,
879 S_IFDIR | S_IRUGO | S_IXUGO,
880 rtl8192_proc);
881 if (!priv->dir_dev) {
882 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
883 dev->name);
884 return;
885 }
886 #if 0
887 e = create_proc_read_entry("stats-hw", S_IFREG | S_IRUGO,
888 priv->dir_dev, proc_get_stats_hw, dev);
889
890 if (!e) {
891 DMESGE("Unable to initialize "
892 "/proc/net/rtl8192/%s/stats-hw\n",
893 dev->name);
894 }
895 #endif
896 e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
897 priv->dir_dev, proc_get_stats_rx, dev);
898
899 if (!e) {
900 RT_TRACE(COMP_ERR,"Unable to initialize "
901 "/proc/net/rtl8192/%s/stats-rx\n",
902 dev->name);
903 }
904
905
906 e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
907 priv->dir_dev, proc_get_stats_tx, dev);
908
909 if (!e) {
910 RT_TRACE(COMP_ERR, "Unable to initialize "
911 "/proc/net/rtl8192/%s/stats-tx\n",
912 dev->name);
913 }
914 #if 0
915 e = create_proc_read_entry("stats-ieee", S_IFREG | S_IRUGO,
916 priv->dir_dev, proc_get_stats_ieee, dev);
917
918 if (!e) {
919 DMESGE("Unable to initialize "
920 "/proc/net/rtl8192/%s/stats-ieee\n",
921 dev->name);
922 }
923
924 #endif
925
926 e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO,
927 priv->dir_dev, proc_get_stats_ap, dev);
928
929 if (!e) {
930 RT_TRACE(COMP_ERR, "Unable to initialize "
931 "/proc/net/rtl8192/%s/stats-ap\n",
932 dev->name);
933 }
934
935 e = create_proc_read_entry("registers", S_IFREG | S_IRUGO,
936 priv->dir_dev, proc_get_registers, dev);
937 if (!e) {
938 RT_TRACE(COMP_ERR, "Unable to initialize "
939 "/proc/net/rtl8192/%s/registers\n",
940 dev->name);
941 }
942#if 0
943 e = create_proc_read_entry("cck-registers", S_IFREG | S_IRUGO,
944 priv->dir_dev, proc_get_cck_reg, dev);
945 if (!e) {
946 RT_TRACE(COMP_ERR, "Unable to initialize "
947 "/proc/net/rtl8192/%s/cck-registers\n",
948 dev->name);
949 }
950
951 e = create_proc_read_entry("ofdm-registers", S_IFREG | S_IRUGO,
952 priv->dir_dev, proc_get_ofdm_reg, dev);
953 if (!e) {
954 RT_TRACE(COMP_ERR, "Unable to initialize "
955 "/proc/net/rtl8192/%s/ofdm-registers\n",
956 dev->name);
957 }
958#endif
959}
960/****************************************************************************
961 -----------------------------MISC STUFF-------------------------
962*****************************************************************************/
963
964/* this is only for debugging */
965void print_buffer(u32 *buffer, int len)
966{
967 int i;
968 u8 *buf =(u8*)buffer;
969
970 printk("ASCII BUFFER DUMP (len: %x):\n",len);
971
972 for(i=0;i<len;i++)
973 printk("%c",buf[i]);
974
975 printk("\nBINARY BUFFER DUMP (len: %x):\n",len);
976
977 for(i=0;i<len;i++)
978 printk("%x",buf[i]);
979
980 printk("\n");
981}
982
983//short check_nic_enough_desc(struct net_device *dev, priority_t priority)
984short check_nic_enough_desc(struct net_device *dev,int queue_index)
985{
986 struct r8192_priv *priv = ieee80211_priv(dev);
987 int used = atomic_read(&priv->tx_pending[queue_index]);
988
989 return (used < MAX_TX_URB);
990}
991
992void tx_timeout(struct net_device *dev)
993{
994 struct r8192_priv *priv = ieee80211_priv(dev);
995 //rtl8192_commit(dev);
996
997#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
998 schedule_work(&priv->reset_wq);
999#else
1000 schedule_task(&priv->reset_wq);
1001#endif
1002 //DMESG("TXTIMEOUT");
1003}
1004
1005
1006/* this is only for debug */
1007void dump_eprom(struct net_device *dev)
1008{
1009 int i;
1010 for(i=0; i<63; i++)
1011 RT_TRACE(COMP_EPROM, "EEPROM addr %x : %x", i, eprom_read(dev,i));
1012}
1013
1014/* this is only for debug */
1015void rtl8192_dump_reg(struct net_device *dev)
1016{
1017 int i;
1018 int n;
1019 int max=0x1ff;
1020
1021 RT_TRACE(COMP_PHY, "Dumping NIC register map");
1022
1023 for(n=0;n<=max;)
1024 {
1025 printk( "\nD: %2x> ", n);
1026 for(i=0;i<16 && n<=max;i++,n++)
1027 printk("%2x ",read_nic_byte(dev,n));
1028 }
1029 printk("\n");
1030}
1031
1032/****************************************************************************
1033 ------------------------------HW STUFF---------------------------
1034*****************************************************************************/
1035
1036#if 0
1037void rtl8192_irq_enable(struct net_device *dev)
1038{
1039 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1040 //priv->irq_enabled = 1;
1041/*
1042 write_nic_word(dev,INTA_MASK,INTA_RXOK | INTA_RXDESCERR | INTA_RXOVERFLOW |\
1043 INTA_TXOVERFLOW | INTA_HIPRIORITYDESCERR | INTA_HIPRIORITYDESCOK |\
1044 INTA_NORMPRIORITYDESCERR | INTA_NORMPRIORITYDESCOK |\
1045 INTA_LOWPRIORITYDESCERR | INTA_LOWPRIORITYDESCOK | INTA_TIMEOUT);
1046*/
1047 write_nic_word(dev,INTA_MASK, priv->irq_mask);
1048}
1049
1050
1051void rtl8192_irq_disable(struct net_device *dev)
1052{
1053// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1054
1055 write_nic_word(dev,INTA_MASK,0);
1056 force_pci_posting(dev);
1057// priv->irq_enabled = 0;
1058}
1059#endif
1060
1061void rtl8192_set_mode(struct net_device *dev,int mode)
1062{
1063 u8 ecmd;
1064 ecmd=read_nic_byte(dev, EPROM_CMD);
1065 ecmd=ecmd &~ EPROM_CMD_OPERATING_MODE_MASK;
1066 ecmd=ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
1067 ecmd=ecmd &~ (1<<EPROM_CS_SHIFT);
1068 ecmd=ecmd &~ (1<<EPROM_CK_SHIFT);
1069 write_nic_byte(dev, EPROM_CMD, ecmd);
1070}
1071
1072
1073void rtl8192_update_msr(struct net_device *dev)
1074{
1075 struct r8192_priv *priv = ieee80211_priv(dev);
1076 u8 msr;
1077
1078 msr = read_nic_byte(dev, MSR);
1079 msr &= ~ MSR_LINK_MASK;
1080
1081 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
1082 * msr must be updated if the state is ASSOCIATING.
1083 * this is intentional and make sense for ad-hoc and
1084 * master (see the create BSS/IBSS func)
1085 */
1086 if (priv->ieee80211->state == IEEE80211_LINKED){
1087
1088 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
1089 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
1090 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
1091 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
1092 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
1093 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
1094
1095 }else
1096 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
1097
1098 write_nic_byte(dev, MSR, msr);
1099}
1100
1101void rtl8192_set_chan(struct net_device *dev,short ch)
1102{
1103 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1104// u32 tx;
1105 RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __FUNCTION__, ch);
1106 priv->chan=ch;
1107 #if 0
1108 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC ||
1109 priv->ieee80211->iw_mode == IW_MODE_MASTER){
1110
1111 priv->ieee80211->link_state = WLAN_LINK_ASSOCIATED;
1112 priv->ieee80211->master_chan = ch;
1113 rtl8192_update_beacon_ch(dev);
1114 }
1115 #endif
1116
1117 /* this hack should avoid frame TX during channel setting*/
1118
1119
1120// tx = read_nic_dword(dev,TX_CONF);
1121// tx &= ~TX_LOOPBACK_MASK;
1122
1123#ifndef LOOP_TEST
1124// write_nic_dword(dev,TX_CONF, tx |( TX_LOOPBACK_MAC<<TX_LOOPBACK_SHIFT));
1125
1126 //need to implement rf set channel here WB
1127
1128 if (priv->rf_set_chan)
1129 priv->rf_set_chan(dev,priv->chan);
1130 mdelay(10);
1131// write_nic_dword(dev,TX_CONF,tx | (TX_LOOPBACK_NONE<<TX_LOOPBACK_SHIFT));
1132#endif
1133}
1134
1135#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
1136static void rtl8192_rx_isr(struct urb *urb, struct pt_regs *regs);
1137#else
1138static void rtl8192_rx_isr(struct urb *urb);
1139#endif
1140//static void rtl8192_rx_isr(struct urb *rx_urb);
1141
1142u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
1143{
1144
1145#ifdef USB_RX_AGGREGATION_SUPPORT
1146 if (pstats->bisrxaggrsubframe)
1147 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
1148 + pstats->RxBufShift + 8);
1149 else
1150#endif
1151 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
1152 + pstats->RxBufShift);
1153
1154}
1155static int rtl8192_rx_initiate(struct net_device*dev)
1156{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001157 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1158 struct urb *entry;
1159 struct sk_buff *skb;
1160 struct rtl8192_rx_info *info;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001161
1162 /* nomal packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001163 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB) {
1164 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
1165 if (!skb)
1166 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001167#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001168 entry = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001169#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001170 entry = usb_alloc_urb(0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001171#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001172 if (!entry) {
1173 kfree_skb(skb);
1174 break;
1175 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001176// printk("nomal packet IN request!\n");
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001177 usb_fill_bulk_urb(entry, priv->udev,
1178 usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb),
1179 RX_URB_SIZE, rtl8192_rx_isr, skb);
1180 info = (struct rtl8192_rx_info *) skb->cb;
1181 info->urb = entry;
1182 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001183 info->out_pipe = 3; //denote rx normal packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001184 skb_queue_tail(&priv->rx_queue, skb);
1185 usb_submit_urb(entry, GFP_KERNEL);
1186 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001187
1188 /* command packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001189 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001190// printk("command packet IN request!\n");
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001191 skb = __dev_alloc_skb(RX_URB_SIZE ,GFP_KERNEL);
1192 if (!skb)
1193 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001194#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001195 entry = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001196#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001197 entry = usb_alloc_urb(0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001198#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001199 if (!entry) {
1200 kfree_skb(skb);
1201 break;
1202 }
1203 usb_fill_bulk_urb(entry, priv->udev,
1204 usb_rcvbulkpipe(priv->udev, 9), skb_tail_pointer(skb),
1205 RX_URB_SIZE, rtl8192_rx_isr, skb);
1206 info = (struct rtl8192_rx_info *) skb->cb;
1207 info->urb = entry;
1208 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001209 info->out_pipe = 9; //denote rx cmd packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001210 skb_queue_tail(&priv->rx_queue, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001211 usb_submit_urb(entry, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001212 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001213
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001214 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001215}
1216
1217void rtl8192_set_rxconf(struct net_device *dev)
1218{
1219 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1220 u32 rxconf;
1221
1222 rxconf=read_nic_dword(dev,RCR);
1223 rxconf = rxconf &~ MAC_FILTER_MASK;
1224 rxconf = rxconf | RCR_AMF;
1225 rxconf = rxconf | RCR_ADF;
1226 rxconf = rxconf | RCR_AB;
1227 rxconf = rxconf | RCR_AM;
1228 //rxconf = rxconf | RCR_ACF;
1229
1230 if (dev->flags & IFF_PROMISC) {DMESG ("NIC in promisc mode");}
1231
1232 if(priv->ieee80211->iw_mode == IW_MODE_MONITOR || \
1233 dev->flags & IFF_PROMISC){
1234 rxconf = rxconf | RCR_AAP;
1235 } /*else if(priv->ieee80211->iw_mode == IW_MODE_MASTER){
1236 rxconf = rxconf | (1<<ACCEPT_ALLMAC_FRAME_SHIFT);
1237 rxconf = rxconf | (1<<RX_CHECK_BSSID_SHIFT);
1238 }*/else{
1239 rxconf = rxconf | RCR_APM;
1240 rxconf = rxconf | RCR_CBSSID;
1241 }
1242
1243
1244 if(priv->ieee80211->iw_mode == IW_MODE_MONITOR){
1245 rxconf = rxconf | RCR_AICV;
1246 rxconf = rxconf | RCR_APWRMGT;
1247 }
1248
1249 if( priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
1250 rxconf = rxconf | RCR_ACRC32;
1251
1252
1253 rxconf = rxconf &~ RX_FIFO_THRESHOLD_MASK;
1254 rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE<<RX_FIFO_THRESHOLD_SHIFT);
1255 rxconf = rxconf &~ MAX_RX_DMA_MASK;
1256 rxconf = rxconf | ((u32)7<<RCR_MXDMA_OFFSET);
1257
1258// rxconf = rxconf | (1<<RX_AUTORESETPHY_SHIFT);
1259 rxconf = rxconf | RCR_ONLYERLPKT;
1260
1261// rxconf = rxconf &~ RCR_CS_MASK;
1262// rxconf = rxconf | (1<<RCR_CS_SHIFT);
1263
1264 write_nic_dword(dev, RCR, rxconf);
1265
1266 #ifdef DEBUG_RX
1267 DMESG("rxconf: %x %x",rxconf ,read_nic_dword(dev,RCR));
1268 #endif
1269}
1270//wait to be removed
1271void rtl8192_rx_enable(struct net_device *dev)
1272{
1273 //u8 cmd;
1274
1275 //struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1276
1277 rtl8192_rx_initiate(dev);
1278
1279// rtl8192_set_rxconf(dev);
1280#if 0
1281 if(NIC_8187 == priv->card_8187) {
1282 cmd=read_nic_byte(dev,CMD);
1283 write_nic_byte(dev,CMD,cmd | (1<<CMD_RX_ENABLE_SHIFT));
1284 }
1285 else {
1286 //write_nic_dword(dev, RX_CONF, priv->ReceiveConfig);
1287 }
1288#endif
1289}
1290
1291
1292void rtl8192_tx_enable(struct net_device *dev)
1293{
1294#if 0
1295 u8 cmd;
1296 u8 byte;
1297 u32 txconf;
1298 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1299 //test loopback
1300 // priv->TransmitConfig |= (TX_LOOPBACK_BASEBAND<<TX_LOOPBACK_SHIFT);
1301 if(NIC_8187B == priv->card_8187){
1302 write_nic_dword(dev, TX_CONF, priv->TransmitConfig);
1303 byte = read_nic_byte(dev, MSR);
1304 byte |= MSR_LINK_ENEDCA;
1305 write_nic_byte(dev, MSR, byte);
1306 } else {
1307 byte = read_nic_byte(dev,CW_CONF);
1308 byte &= ~(1<<CW_CONF_PERPACKET_CW_SHIFT);
1309 byte &= ~(1<<CW_CONF_PERPACKET_RETRY_SHIFT);
1310 write_nic_byte(dev, CW_CONF, byte);
1311
1312 byte = read_nic_byte(dev, TX_AGC_CTL);
1313 byte &= ~(1<<TX_AGC_CTL_PERPACKET_GAIN_SHIFT);
1314 byte &= ~(1<<TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT);
1315 byte &= ~(1<<TX_AGC_CTL_FEEDBACK_ANT);
1316 write_nic_byte(dev, TX_AGC_CTL, byte);
1317
1318 txconf= read_nic_dword(dev,TX_CONF);
1319
1320
1321 txconf = txconf &~ TX_LOOPBACK_MASK;
1322
1323#ifndef LOOP_TEST
1324 txconf = txconf | (TX_LOOPBACK_NONE<<TX_LOOPBACK_SHIFT);
1325#else
1326 txconf = txconf | (TX_LOOPBACK_BASEBAND<<TX_LOOPBACK_SHIFT);
1327#endif
1328 txconf = txconf &~ TCR_SRL_MASK;
1329 txconf = txconf &~ TCR_LRL_MASK;
1330
1331 txconf = txconf | (priv->retry_data<<TX_LRLRETRY_SHIFT); // long
1332 txconf = txconf | (priv->retry_rts<<TX_SRLRETRY_SHIFT); // short
1333
1334 txconf = txconf &~ (1<<TX_NOCRC_SHIFT);
1335
1336 txconf = txconf &~ TCR_MXDMA_MASK;
1337 txconf = txconf | (TCR_MXDMA_2048<<TCR_MXDMA_SHIFT);
1338
1339 txconf = txconf | TCR_DISReqQsize;
1340 txconf = txconf | TCR_DISCW;
1341 txconf = txconf &~ TCR_SWPLCPLEN;
1342
1343 txconf=txconf | (1<<TX_NOICV_SHIFT);
1344
1345 write_nic_dword(dev,TX_CONF,txconf);
1346
1347#ifdef DEBUG_TX
1348 DMESG("txconf: %x %x",txconf,read_nic_dword(dev,TX_CONF));
1349#endif
1350
1351 cmd=read_nic_byte(dev,CMD);
1352 write_nic_byte(dev,CMD,cmd | (1<<CMD_TX_ENABLE_SHIFT));
1353 }
1354#endif
1355}
1356
1357#if 0
1358void rtl8192_beacon_tx_enable(struct net_device *dev)
1359{
1360 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1361 priv->dma_poll_mask &=~(1<<TX_DMA_STOP_BEACON_SHIFT);
1362 rtl8192_set_mode(dev,EPROM_CMD_CONFIG);
1363 write_nic_byte(dev,TX_DMA_POLLING,priv->dma_poll_mask);
1364 rtl8192_set_mode(dev,EPROM_CMD_NORMAL);
1365}
1366
1367
1368void rtl8192_
1369_disable(struct net_device *dev)
1370{
1371 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1372 priv->dma_poll_mask |= (1<<TX_DMA_STOP_BEACON_SHIFT);
1373 rtl8192_set_mode(dev,EPROM_CMD_CONFIG);
1374 write_nic_byte(dev,TX_DMA_POLLING,priv->dma_poll_mask);
1375 rtl8192_set_mode(dev,EPROM_CMD_NORMAL);
1376}
1377
1378#endif
1379
1380
1381void rtl8192_rtx_disable(struct net_device *dev)
1382{
1383 u8 cmd;
1384 struct r8192_priv *priv = ieee80211_priv(dev);
1385 struct sk_buff *skb;
1386 struct rtl8192_rx_info *info;
1387
1388 cmd=read_nic_byte(dev,CMDR);
1389 write_nic_byte(dev, CMDR, cmd &~ \
1390 (CR_TE|CR_RE));
1391 force_pci_posting(dev);
1392 mdelay(10);
1393
1394 while ((skb = __skb_dequeue(&priv->rx_queue))) {
1395 info = (struct rtl8192_rx_info *) skb->cb;
1396 if (!info->urb)
1397 continue;
1398
1399 usb_kill_urb(info->urb);
1400 kfree_skb(skb);
1401 }
1402
1403 if (skb_queue_len(&priv->skb_queue)) {
1404 printk(KERN_WARNING "skb_queue not empty\n");
1405 }
1406
1407 skb_queue_purge(&priv->skb_queue);
1408 return;
1409}
1410
1411
1412int alloc_tx_beacon_desc_ring(struct net_device *dev, int count)
1413{
1414 #if 0
1415 int i;
1416 u32 *tmp;
1417 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1418
1419 priv->txbeaconring = (u32*)pci_alloc_consistent(priv->pdev,
1420 sizeof(u32)*8*count,
1421 &priv->txbeaconringdma);
1422 if (!priv->txbeaconring) return -1;
1423 for (tmp=priv->txbeaconring,i=0;i<count;i++){
1424 *tmp = *tmp &~ (1<<31); // descriptor empty, owned by the drv
1425 /*
1426 *(tmp+2) = (u32)dma_tmp;
1427 *(tmp+3) = bufsize;
1428 */
1429 if(i+1<count)
1430 *(tmp+4) = (u32)priv->txbeaconringdma+((i+1)*8*4);
1431 else
1432 *(tmp+4) = (u32)priv->txbeaconringdma;
1433
1434 tmp=tmp+8;
1435 }
1436 #endif
1437 return 0;
1438}
1439
1440#if 0
1441void rtl8192_reset(struct net_device *dev)
1442{
1443
1444 //struct r8192_priv *priv = ieee80211_priv(dev);
1445 //u8 cr;
1446
1447
1448 /* make sure the analog power is on before
1449 * reset, otherwise reset may fail
1450 */
1451#if 0
1452 if(NIC_8187 == priv->card_8187) {
1453 rtl8192_set_anaparam(dev, RTL8225_ANAPARAM_ON);
1454 rtl8185_set_anaparam2(dev, RTL8225_ANAPARAM2_ON);
1455 rtl8192_irq_disable(dev);
1456 mdelay(200);
1457 write_nic_byte_E(dev,0x18,0x10);
1458 write_nic_byte_E(dev,0x18,0x11);
1459 write_nic_byte_E(dev,0x18,0x00);
1460 mdelay(200);
1461 }
1462#endif
1463 printk("=====>reset?\n");
1464#if 0
1465 cr=read_nic_byte(dev,CMD);
1466 cr = cr & 2;
1467 cr = cr | (1<<CMD_RST_SHIFT);
1468 write_nic_byte(dev,CMD,cr);
1469
1470 force_pci_posting(dev);
1471
1472 mdelay(200);
1473
1474 if(read_nic_byte(dev,CMD) & (1<<CMD_RST_SHIFT))
1475 RT_TRACE(COMP_ERR, "Card reset timeout!\n");
1476 else
1477 RT_TRACE(COMP_DOWN, "Card successfully reset\n");
1478#endif
1479#if 0
1480 if(NIC_8187 == priv->card_8187) {
1481
1482 printk("This is RTL8187 Reset procedure\n");
1483 rtl8192_set_mode(dev,EPROM_CMD_LOAD);
1484 force_pci_posting(dev);
1485 mdelay(200);
1486
1487 /* after the eeprom load cycle, make sure we have
1488 * correct anaparams
1489 */
1490 rtl8192_set_anaparam(dev, RTL8225_ANAPARAM_ON);
1491 rtl8185_set_anaparam2(dev, RTL8225_ANAPARAM2_ON);
1492 }
1493 else
1494#endif
1495 printk("This is RTL8187B Reset procedure\n");
1496
1497}
1498#endif
1499inline u16 ieeerate2rtlrate(int rate)
1500{
1501 switch(rate){
1502 case 10:
1503 return 0;
1504 case 20:
1505 return 1;
1506 case 55:
1507 return 2;
1508 case 110:
1509 return 3;
1510 case 60:
1511 return 4;
1512 case 90:
1513 return 5;
1514 case 120:
1515 return 6;
1516 case 180:
1517 return 7;
1518 case 240:
1519 return 8;
1520 case 360:
1521 return 9;
1522 case 480:
1523 return 10;
1524 case 540:
1525 return 11;
1526 default:
1527 return 3;
1528
1529 }
1530}
1531static u16 rtl_rate[] = {10,20,55,110,60,90,120,180,240,360,480,540};
1532inline u16 rtl8192_rate2rate(short rate)
1533{
1534 if (rate >11) return 0;
1535 return rtl_rate[rate];
1536}
1537
1538
1539/* The protype of rx_isr has changed since one verion of Linux Kernel */
1540#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
1541static void rtl8192_rx_isr(struct urb *urb, struct pt_regs *regs)
1542#else
1543static void rtl8192_rx_isr(struct urb *urb)
1544#endif
1545{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001546 struct sk_buff *skb = (struct sk_buff *) urb->context;
1547 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
1548 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001549 struct r8192_priv *priv = ieee80211_priv(dev);
1550 int out_pipe = info->out_pipe;
1551 int err;
1552 if(!priv->up)
1553 return;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001554 if (unlikely(urb->status)) {
1555 info->urb = NULL;
1556 priv->stats.rxstaterr++;
1557 priv->ieee80211->stats.rx_errors++;
1558 usb_free_urb(urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001559 // printk("%s():rx status err\n",__FUNCTION__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001560 return;
1561 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001562#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001563 skb_unlink(skb, &priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001564#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001565 __skb_unlink(skb,&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001566#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001567 skb_put(skb, urb->actual_length);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001568
1569 skb_queue_tail(&priv->skb_queue, skb);
1570 tasklet_schedule(&priv->irq_rx_tasklet);
1571
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001572 skb = dev_alloc_skb(RX_URB_SIZE);
1573 if (unlikely(!skb)) {
1574 usb_free_urb(urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001575 printk("%s():can,t alloc skb\n",__FUNCTION__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001576 /* TODO check rx queue length and refill *somewhere* */
1577 return;
1578 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001579
1580 usb_fill_bulk_urb(urb, priv->udev,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001581 usb_rcvbulkpipe(priv->udev, out_pipe), skb_tail_pointer(skb),
Jerry Chuang8fc85982009-11-03 07:17:11 -02001582 RX_URB_SIZE, rtl8192_rx_isr, skb);
1583
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001584 info = (struct rtl8192_rx_info *) skb->cb;
1585 info->urb = urb;
1586 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001587 info->out_pipe = out_pipe;
1588
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001589 urb->transfer_buffer = skb_tail_pointer(skb);
1590 urb->context = skb;
1591 skb_queue_tail(&priv->rx_queue, skb);
1592 err = usb_submit_urb(urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001593 if(err && err != EPERM)
1594 printk("can not submit rxurb, err is %x,URB status is %x\n",err,urb->status);
1595}
1596
1597u32
1598rtl819xusb_rx_command_packet(
1599 struct net_device *dev,
1600 struct ieee80211_rx_stats *pstats
1601 )
1602{
1603 u32 status;
1604
1605 //RT_TRACE(COMP_RECV, DBG_TRACE, ("---> RxCommandPacketHandle819xUsb()\n"));
1606
1607 status = cmpk_message_handle_rx(dev, pstats);
1608 if (status)
1609 {
1610 DMESG("rxcommandpackethandle819xusb: It is a command packet\n");
1611 }
1612 else
1613 {
1614 //RT_TRACE(COMP_RECV, DBG_TRACE, ("RxCommandPacketHandle819xUsb: It is not a command packet\n"));
1615 }
1616
1617 //RT_TRACE(COMP_RECV, DBG_TRACE, ("<--- RxCommandPacketHandle819xUsb()\n"));
1618 return status;
1619}
1620
1621#if 0
1622void rtl8192_tx_queues_stop(struct net_device *dev)
1623{
1624 //struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1625 u8 dma_poll_mask = (1<<TX_DMA_STOP_LOWPRIORITY_SHIFT);
1626 dma_poll_mask |= (1<<TX_DMA_STOP_HIPRIORITY_SHIFT);
1627 dma_poll_mask |= (1<<TX_DMA_STOP_NORMPRIORITY_SHIFT);
1628 dma_poll_mask |= (1<<TX_DMA_STOP_BEACON_SHIFT);
1629
1630 rtl8192_set_mode(dev,EPROM_CMD_CONFIG);
1631 write_nic_byte(dev,TX_DMA_POLLING,dma_poll_mask);
1632 rtl8192_set_mode(dev,EPROM_CMD_NORMAL);
1633}
1634#endif
1635
1636void rtl8192_data_hard_stop(struct net_device *dev)
1637{
1638 //FIXME !!
1639 #if 0
1640 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1641 priv->dma_poll_mask |= (1<<TX_DMA_STOP_LOWPRIORITY_SHIFT);
1642 rtl8192_set_mode(dev,EPROM_CMD_CONFIG);
1643 write_nic_byte(dev,TX_DMA_POLLING,priv->dma_poll_mask);
1644 rtl8192_set_mode(dev,EPROM_CMD_NORMAL);
1645 #endif
1646}
1647
1648
1649void rtl8192_data_hard_resume(struct net_device *dev)
1650{
1651 // FIXME !!
1652 #if 0
1653 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1654 priv->dma_poll_mask &= ~(1<<TX_DMA_STOP_LOWPRIORITY_SHIFT);
1655 rtl8192_set_mode(dev,EPROM_CMD_CONFIG);
1656 write_nic_byte(dev,TX_DMA_POLLING,priv->dma_poll_mask);
1657 rtl8192_set_mode(dev,EPROM_CMD_NORMAL);
1658 #endif
1659}
1660
1661/* this function TX data frames when the ieee80211 stack requires this.
1662 * It checks also if we need to stop the ieee tx queue, eventually do it
1663 */
1664void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
1665{
1666 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1667 int ret;
1668 unsigned long flags;
1669 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1670 u8 queue_index = tcb_desc->queue_index;
1671
1672 /* shall not be referred by command packet */
1673 assert(queue_index != TXCMD_QUEUE);
1674
1675 spin_lock_irqsave(&priv->tx_lock,flags);
1676
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001677 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001678// tcb_desc->RATRIndex = 7;
1679// tcb_desc->bTxDisableRateFallBack = 1;
1680// tcb_desc->bTxUseDriverAssingedRate = 1;
1681 tcb_desc->bTxEnableFwCalcDur = 1;
1682 skb_push(skb, priv->ieee80211->tx_headroom);
1683 ret = rtl8192_tx(dev, skb);
1684
1685 //priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom);
1686 //priv->ieee80211->stats.tx_packets++;
1687
1688 spin_unlock_irqrestore(&priv->tx_lock,flags);
1689
1690// return ret;
1691 return;
1692}
1693
1694/* This is a rough attempt to TX a frame
1695 * This is called by the ieee 80211 stack to TX management frames.
1696 * If the ring is full packet are dropped (for data frame the queue
1697 * is stopped before this can happen).
1698 */
1699int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
1700{
1701 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1702 int ret;
1703 unsigned long flags;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001704 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1705 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001706
1707
1708 spin_lock_irqsave(&priv->tx_lock,flags);
1709
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001710 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001711 if(queue_index == TXCMD_QUEUE) {
1712 skb_push(skb, USB_HWDESC_HEADER_LEN);
1713 rtl819xU_tx_cmd(dev, skb);
1714 ret = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001715 spin_unlock_irqrestore(&priv->tx_lock,flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001716 return ret;
1717 } else {
1718 skb_push(skb, priv->ieee80211->tx_headroom);
1719 ret = rtl8192_tx(dev, skb);
1720 }
1721
1722 spin_unlock_irqrestore(&priv->tx_lock,flags);
1723
1724 return ret;
1725}
1726
1727
1728void rtl8192_try_wake_queue(struct net_device *dev, int pri);
1729
1730#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1731u16 DrvAggr_PaddingAdd(struct net_device *dev, struct sk_buff *skb)
1732{
1733 u16 PaddingNum = 256 - ((skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES) % 256);
1734 return (PaddingNum&0xff);
1735}
1736
1737u8 MRateToHwRate8190Pci(u8 rate);
1738u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc);
1739u8 MapHwQueueToFirmwareQueue(u8 QueueID);
1740struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv_agg_txb *pSendList)
1741{
1742#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1743 struct ieee80211_device *ieee = netdev_priv(dev);
1744#else
1745 struct ieee80211_device *ieee = (struct ieee80211_device *)dev->priv;
1746#endif
1747 struct r8192_priv *priv = ieee80211_priv(dev);
1748 cb_desc *tcb_desc = NULL;
1749 u8 i;
1750 u32 TotalLength;
1751 struct sk_buff *skb;
1752 struct sk_buff *agg_skb;
1753 tx_desc_819x_usb_aggr_subframe *tx_agg_desc = NULL;
1754 tx_fwinfo_819x_usb *tx_fwinfo = NULL;
1755
1756 //
1757 // Local variable initialization.
1758 //
1759 /* first skb initialization */
1760 skb = pSendList->tx_agg_frames[0];
1761 TotalLength = skb->len;
1762
1763 /* Get the total aggregation length including the padding space and
1764 * sub frame header.
1765 */
1766 for(i = 1; i < pSendList->nr_drv_agg_frames; i++) {
1767 TotalLength += DrvAggr_PaddingAdd(dev, skb);
1768 skb = pSendList->tx_agg_frames[i];
1769 TotalLength += (skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1770 }
1771
1772 /* allocate skb to contain the aggregated packets */
1773 agg_skb = dev_alloc_skb(TotalLength + ieee->tx_headroom);
1774 memset(agg_skb->data, 0, agg_skb->len);
1775 skb_reserve(agg_skb, ieee->tx_headroom);
1776
1777// RT_DEBUG_DATA(COMP_SEND, skb->cb, sizeof(skb->cb));
1778 /* reserve info for first subframe Tx descriptor to be set in the tx function */
1779 skb = pSendList->tx_agg_frames[0];
1780 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1781 tcb_desc->drv_agg_enable = 1;
1782 tcb_desc->pkt_size = skb->len;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001783 tcb_desc->DrvAggrNum = pSendList->nr_drv_agg_frames;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001784 printk("DrvAggNum = %d\n", tcb_desc->DrvAggrNum);
1785// RT_DEBUG_DATA(COMP_SEND, skb->cb, sizeof(skb->cb));
1786// printk("========>skb->data ======> \n");
1787// RT_DEBUG_DATA(COMP_SEND, skb->data, skb->len);
1788 memcpy(agg_skb->cb, skb->cb, sizeof(skb->cb));
1789 memcpy(skb_put(agg_skb,skb->len),skb->data,skb->len);
1790
1791 for(i = 1; i < pSendList->nr_drv_agg_frames; i++) {
1792 /* push the next sub frame to be 256 byte aline */
1793 skb_put(agg_skb,DrvAggr_PaddingAdd(dev,skb));
1794
1795 /* Subframe drv Tx descriptor and firmware info setting */
1796 skb = pSendList->tx_agg_frames[i];
1797 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1798 tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)agg_skb->tail;
1799 tx_fwinfo = (tx_fwinfo_819x_usb *)(agg_skb->tail + sizeof(tx_desc_819x_usb_aggr_subframe));
1800
1801 memset(tx_fwinfo,0,sizeof(tx_fwinfo_819x_usb));
1802 /* DWORD 0 */
1803 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0;
1804 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1805 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1806 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
1807 if(tcb_desc->bAMPDUEnable) {//AMPDU enabled
1808 tx_fwinfo->AllowAggregation = 1;
1809 /* DWORD 1 */
1810 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1811 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1812 } else {
1813 tx_fwinfo->AllowAggregation = 0;
1814 /* DWORD 1 */
1815 tx_fwinfo->RxMF = 0;
1816 tx_fwinfo->RxAMD = 0;
1817 }
1818
1819 /* Protection mode related */
1820 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0;
1821 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0;
1822 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0;
1823 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80)?1:0;
1824 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
1825 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT==0)?(tcb_desc->RTSSC):0;
1826 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT==1)?((tcb_desc->bRTSBW)?1:0):0;
1827 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):\
1828 (tcb_desc->bRTSUseShortGI?1:0);
1829
1830 /* Set Bandwidth and sub-channel settings. */
1831 if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
1832 {
1833 if(tcb_desc->bPacketBW) {
1834 tx_fwinfo->TxBandwidth = 1;
1835 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1836 } else {
1837 tx_fwinfo->TxBandwidth = 0;
1838 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1839 }
1840 } else {
1841 tx_fwinfo->TxBandwidth = 0;
1842 tx_fwinfo->TxSubCarrier = 0;
1843 }
1844
1845 /* Fill Tx descriptor */
1846 memset(tx_agg_desc, 0, sizeof(tx_desc_819x_usb_aggr_subframe));
1847 /* DWORD 0 */
1848 //tx_agg_desc->LINIP = 0;
1849 //tx_agg_desc->CmdInit = 1;
1850 tx_agg_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
1851 /* already raw data, need not to substract header length */
1852 tx_agg_desc->PktSize = skb->len & 0xffff;
1853
1854 /*DWORD 1*/
1855 tx_agg_desc->SecCAMID= 0;
1856 tx_agg_desc->RATid = tcb_desc->RATRIndex;
1857#if 0
1858 /* Fill security related */
1859 if( pTcb->bEncrypt && !Adapter->MgntInfo.SecurityInfo.SWTxEncryptFlag)
1860 {
1861 EncAlg = SecGetEncryptionOverhead(
1862 Adapter,
1863 &EncryptionMPDUHeadOverhead,
1864 &EncryptionMPDUTailOverhead,
1865 NULL,
1866 NULL,
1867 FALSE,
1868 FALSE);
1869 //2004/07/22, kcwu, EncryptionMPDUHeadOverhead has been added in previous code
1870 //MPDUOverhead = EncryptionMPDUHeadOverhead + EncryptionMPDUTailOverhead;
1871 MPDUOverhead = EncryptionMPDUTailOverhead;
1872 tx_agg_desc->NoEnc = 0;
1873 RT_TRACE(COMP_SEC, DBG_LOUD, ("******We in the loop SecCAMID is %d SecDescAssign is %d The Sec is %d********\n",tx_agg_desc->SecCAMID,tx_agg_desc->SecDescAssign,EncAlg));
1874 //CamDumpAll(Adapter);
1875 }
1876 else
1877#endif
1878 {
1879 //MPDUOverhead = 0;
1880 tx_agg_desc->NoEnc = 1;
1881 }
1882#if 0
1883 switch(EncAlg){
1884 case NO_Encryption:
1885 tx_agg_desc->SecType = 0x0;
1886 break;
1887 case WEP40_Encryption:
1888 case WEP104_Encryption:
1889 tx_agg_desc->SecType = 0x1;
1890 break;
1891 case TKIP_Encryption:
1892 tx_agg_desc->SecType = 0x2;
1893 break;
1894 case AESCCMP_Encryption:
1895 tx_agg_desc->SecType = 0x3;
1896 break;
1897 default:
1898 tx_agg_desc->SecType = 0x0;
1899 break;
1900 }
1901#else
1902 tx_agg_desc->SecType = 0x0;
1903#endif
1904
1905 if (tcb_desc->bHwSec) {
1906 switch (priv->ieee80211->pairwise_key_type)
1907 {
1908 case KEY_TYPE_WEP40:
1909 case KEY_TYPE_WEP104:
1910 tx_agg_desc->SecType = 0x1;
1911 tx_agg_desc->NoEnc = 0;
1912 break;
1913 case KEY_TYPE_TKIP:
1914 tx_agg_desc->SecType = 0x2;
1915 tx_agg_desc->NoEnc = 0;
1916 break;
1917 case KEY_TYPE_CCMP:
1918 tx_agg_desc->SecType = 0x3;
1919 tx_agg_desc->NoEnc = 0;
1920 break;
1921 case KEY_TYPE_NA:
1922 tx_agg_desc->SecType = 0x0;
1923 tx_agg_desc->NoEnc = 1;
1924 break;
1925 }
1926 }
1927
1928 tx_agg_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1929 tx_agg_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1930
1931 tx_agg_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1932 tx_agg_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1933
1934 tx_agg_desc->OWN = 1;
1935
1936 //DWORD 2
1937 /* According windows driver, it seems that there no need to fill this field */
1938 //tx_agg_desc->TxBufferSize= (u32)(skb->len - USB_HWDESC_HEADER_LEN);
1939
1940 /* to fill next packet */
1941 skb_put(agg_skb,TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1942 memcpy(skb_put(agg_skb,skb->len),skb->data,skb->len);
1943 }
1944
1945 for(i = 0; i < pSendList->nr_drv_agg_frames; i++) {
1946 dev_kfree_skb_any(pSendList->tx_agg_frames[i]);
1947 }
1948
1949 return agg_skb;
1950}
1951
1952/* NOTE:
1953 This function return a list of PTCB which is proper to be aggregate with the input TCB.
1954 If no proper TCB is found to do aggregation, SendList will only contain the input TCB.
1955*/
1956u8 DrvAggr_GetAggregatibleList(struct net_device *dev, struct sk_buff *skb,
1957 struct ieee80211_drv_agg_txb *pSendList)
1958{
1959#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1960 struct ieee80211_device *ieee = netdev_priv(dev);
1961#else
1962 struct ieee80211_device *ieee = (struct ieee80211_device *)dev->priv;
1963#endif
1964 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1965 u16 nMaxAggrNum = pHTInfo->UsbTxAggrNum;
1966 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1967 u8 QueueID = tcb_desc->queue_index;
1968
1969 do {
1970 pSendList->tx_agg_frames[pSendList->nr_drv_agg_frames++] = skb;
1971 if(pSendList->nr_drv_agg_frames >= nMaxAggrNum) {
1972 break;
1973 }
1974
1975 } while((skb = skb_dequeue(&ieee->skb_drv_aggQ[QueueID])));
1976
1977 RT_TRACE(COMP_AMSDU, "DrvAggr_GetAggregatibleList, nAggrTcbNum = %d \n", pSendList->nr_drv_agg_frames);
1978 return pSendList->nr_drv_agg_frames;
1979}
1980#endif
1981
1982#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
1983static void rtl8192_tx_isr(struct urb *tx_urb, struct pt_regs *reg)
1984#else
1985static void rtl8192_tx_isr(struct urb *tx_urb)
1986#endif
1987{
1988 struct sk_buff *skb = (struct sk_buff*)tx_urb->context;
1989 struct net_device *dev = NULL;
1990 struct r8192_priv *priv = NULL;
1991 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1992 u8 queue_index = tcb_desc->queue_index;
1993// bool bToSend0Byte;
1994// u16 BufLen = skb->len;
1995
1996 memcpy(&dev,(struct net_device*)(skb->cb),sizeof(struct net_device*));
1997 priv = ieee80211_priv(dev);
1998
1999 if(tcb_desc->queue_index != TXCMD_QUEUE) {
2000 if(tx_urb->status == 0) {
2001 dev->trans_start = jiffies;
2002 // As act as station mode, destion shall be unicast address.
2003 //priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom);
2004 //priv->ieee80211->stats.tx_packets++;
2005 priv->stats.txoktotal++;
2006 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
2007 priv->stats.txbytesunicast += (skb->len - priv->ieee80211->tx_headroom);
2008 } else {
2009 priv->ieee80211->stats.tx_errors++;
2010 //priv->stats.txmanageerr++;
2011 /* TODO */
2012 }
2013 }
2014
2015 /* free skb and tx_urb */
2016 if(skb != NULL) {
2017 dev_kfree_skb_any(skb);
2018 usb_free_urb(tx_urb);
2019 atomic_dec(&priv->tx_pending[queue_index]);
2020 }
2021
2022#if 0 //we need to send zero byte packet just after 512 byte(64 byte)packet is transmitted, or we will halt. It will greatly reduced available page in FW, and ruin our throughput. WB 2008.08.27
2023 if(BufLen > 0 && ((BufLen % 512 == 0)||(BufLen % 64 == 0))) {
2024 bToSend0Byte = true;
2025 }
2026
2027 bToSend0Byte = false;
2028 //
2029 // Note that, we at most handle 1 MPDU to send here, either
2030 // fragment or MPDU in wait queue.
2031 //
2032 if(!bToSend0Byte)
2033#endif
2034 {
2035 //
2036 // Handle HW Beacon:
2037 // We had transfer our beacon frame to host controler at this moment.
2038 //
2039#if 0
2040 if(tcb_desc->tx_queue == BEACON_QUEUE)
2041 {
2042 priv->bSendingBeacon = FALSE;
2043 }
2044#endif
2045 //
2046 // Caution:
2047 // Handling the wait queue of command packets.
2048 // For Tx command packets, we must not do TCB fragment because it is not handled right now.
2049 // We must cut the packets to match the size of TX_CMD_PKT before we send it.
2050 //
2051
2052 /* Handle MPDU in wait queue. */
2053 if(queue_index != BEACON_QUEUE) {
2054 /* Don't send data frame during scanning.*/
2055 if((skb_queue_len(&priv->ieee80211->skb_waitQ[queue_index]) != 0)&&\
2056 (!(priv->ieee80211->queue_stop))) {
2057 if(NULL != (skb = skb_dequeue(&(priv->ieee80211->skb_waitQ[queue_index]))))
2058 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
2059
2060 return; //modified by david to avoid further processing AMSDU
2061 }
2062#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2063 else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index])!= 0)&&\
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002064 (!(priv->ieee80211->queue_stop))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002065 // Tx Driver Aggregation process
2066 /* The driver will aggregation the packets according to the following stets
2067 * 1. check whether there's tx irq available, for it's a completion return
2068 * function, it should contain enough tx irq;
2069 * 2. check pakcet type;
2070 * 3. intialize sendlist, check whether the to-be send packet no greater than 1
2071 * 4. aggregation the packets, and fill firmware info and tx desc to it, etc.
2072 * 5. check whehter the packet could be sent, otherwise just insert to wait head
2073 * */
2074 skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]);
2075 if(!check_nic_enough_desc(dev, queue_index)) {
2076 skb_queue_head(&(priv->ieee80211->skb_drv_aggQ[queue_index]), skb);
2077 return;
2078 }
2079
2080 {
2081 /*TODO*/
2082 /*
2083 u8* pHeader = skb->data;
2084
2085 if(IsMgntQosData(pHeader) ||
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002086 IsMgntQData_Ack(pHeader) ||
Jerry Chuang8fc85982009-11-03 07:17:11 -02002087 IsMgntQData_Poll(pHeader) ||
2088 IsMgntQData_Poll_Ack(pHeader)
2089 )
2090 */
2091 {
2092 struct ieee80211_drv_agg_txb SendList;
2093
2094 memset(&SendList, 0, sizeof(struct ieee80211_drv_agg_txb));
2095 if(DrvAggr_GetAggregatibleList(dev, skb, &SendList) > 1) {
2096 skb = DrvAggr_Aggregation(dev, &SendList);
2097
2098#if 0
2099 printk("=============>to send aggregated packet!\n");
2100 RT_DEBUG_DATA(COMP_SEND, skb->cb, sizeof(skb->cb));
2101 printk("\n=================skb->len = %d\n", skb->len);
2102 RT_DEBUG_DATA(COMP_SEND, skb->data, skb->len);
2103#endif
2104 }
2105 }
2106 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
2107 }
2108 }
2109#endif
2110 }
2111 }
2112
2113#if 0
2114 else
2115 {
2116 RT_TRACE( COMP_SEND,"HalUsbOutComplete(%d): bToSend0Byte.\n", PipeIndex);
2117
2118 //
2119 // In this case, we don't return skb now.
2120 // It will be returned when the 0-byte request completed.
2121 //
2122
2123 //
2124 // Bulk out an 0-byte padding transfer.
2125 //
2126 HalUsbOut0Byte(pAdapter, PipeIndex, skb);
2127 }
2128
2129#endif
2130}
2131
2132void rtl8192_beacon_stop(struct net_device *dev)
2133{
2134 u8 msr, msrm, msr2;
2135 struct r8192_priv *priv = ieee80211_priv(dev);
2136
2137 msr = read_nic_byte(dev, MSR);
2138 msrm = msr & MSR_LINK_MASK;
2139 msr2 = msr & ~MSR_LINK_MASK;
2140
2141 if(NIC_8192U == priv->card_8192) {
2142 usb_kill_urb(priv->rx_urb[MAX_RX_URB]);
2143 }
2144 if ((msrm == (MSR_LINK_ADHOC<<MSR_LINK_SHIFT) ||
2145 (msrm == (MSR_LINK_MASTER<<MSR_LINK_SHIFT)))){
2146 write_nic_byte(dev, MSR, msr2 | MSR_LINK_NONE);
2147 write_nic_byte(dev, MSR, msr);
2148 }
2149}
2150
2151void rtl8192_config_rate(struct net_device* dev, u16* rate_config)
2152{
2153 struct r8192_priv *priv = ieee80211_priv(dev);
2154 struct ieee80211_network *net;
2155 u8 i=0, basic_rate = 0;
2156 net = & priv->ieee80211->current_network;
2157
2158 for (i=0; i<net->rates_len; i++)
2159 {
2160 basic_rate = net->rates[i]&0x7f;
2161 switch(basic_rate)
2162 {
2163 case MGN_1M: *rate_config |= RRSR_1M; break;
2164 case MGN_2M: *rate_config |= RRSR_2M; break;
2165 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
2166 case MGN_11M: *rate_config |= RRSR_11M; break;
2167 case MGN_6M: *rate_config |= RRSR_6M; break;
2168 case MGN_9M: *rate_config |= RRSR_9M; break;
2169 case MGN_12M: *rate_config |= RRSR_12M; break;
2170 case MGN_18M: *rate_config |= RRSR_18M; break;
2171 case MGN_24M: *rate_config |= RRSR_24M; break;
2172 case MGN_36M: *rate_config |= RRSR_36M; break;
2173 case MGN_48M: *rate_config |= RRSR_48M; break;
2174 case MGN_54M: *rate_config |= RRSR_54M; break;
2175 }
2176 }
2177 for (i=0; i<net->rates_ex_len; i++)
2178 {
2179 basic_rate = net->rates_ex[i]&0x7f;
2180 switch(basic_rate)
2181 {
2182 case MGN_1M: *rate_config |= RRSR_1M; break;
2183 case MGN_2M: *rate_config |= RRSR_2M; break;
2184 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
2185 case MGN_11M: *rate_config |= RRSR_11M; break;
2186 case MGN_6M: *rate_config |= RRSR_6M; break;
2187 case MGN_9M: *rate_config |= RRSR_9M; break;
2188 case MGN_12M: *rate_config |= RRSR_12M; break;
2189 case MGN_18M: *rate_config |= RRSR_18M; break;
2190 case MGN_24M: *rate_config |= RRSR_24M; break;
2191 case MGN_36M: *rate_config |= RRSR_36M; break;
2192 case MGN_48M: *rate_config |= RRSR_48M; break;
2193 case MGN_54M: *rate_config |= RRSR_54M; break;
2194 }
2195 }
2196}
2197
2198
2199#define SHORT_SLOT_TIME 9
2200#define NON_SHORT_SLOT_TIME 20
2201
2202void rtl8192_update_cap(struct net_device* dev, u16 cap)
2203{
2204 u32 tmp = 0;
2205 struct r8192_priv *priv = ieee80211_priv(dev);
2206 struct ieee80211_network *net = &priv->ieee80211->current_network;
2207 priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
2208 tmp = priv->basic_rate;
2209 if (priv->short_preamble)
2210 tmp |= BRSR_AckShortPmb;
2211 write_nic_dword(dev, RRSR, tmp);
2212
2213 if (net->mode & (IEEE_G|IEEE_N_24G))
2214 {
2215 u8 slot_time = 0;
2216 if ((cap & WLAN_CAPABILITY_SHORT_SLOT)&&(!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime))
2217 {//short slot time
2218 slot_time = SHORT_SLOT_TIME;
2219 }
2220 else //long slot time
2221 slot_time = NON_SHORT_SLOT_TIME;
2222 priv->slot_time = slot_time;
2223 write_nic_byte(dev, SLOT_TIME, slot_time);
2224 }
2225
2226}
2227void rtl8192_net_update(struct net_device *dev)
2228{
2229
2230 struct r8192_priv *priv = ieee80211_priv(dev);
2231 struct ieee80211_network *net;
2232 u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
2233 u16 rate_config = 0;
2234 net = & priv->ieee80211->current_network;
2235
2236 rtl8192_config_rate(dev, &rate_config);
2237 priv->basic_rate = rate_config &= 0x15f;
2238
2239 write_nic_dword(dev,BSSIDR,((u32*)net->bssid)[0]);
2240 write_nic_word(dev,BSSIDR+4,((u16*)net->bssid)[2]);
2241 //for(i=0;i<ETH_ALEN;i++)
2242 // write_nic_byte(dev,BSSID+i,net->bssid[i]);
2243
2244 rtl8192_update_msr(dev);
2245// rtl8192_update_cap(dev, net->capability);
2246 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
2247 {
2248 write_nic_word(dev, ATIMWND, 2);
2249 write_nic_word(dev, BCN_DMATIME, 1023);
2250 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
2251// write_nic_word(dev, BcnIntTime, 100);
2252 write_nic_word(dev, BCN_DRV_EARLY_INT, 1);
2253 write_nic_byte(dev, BCN_ERR_THRESH, 100);
2254 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
2255 // TODO: BcnIFS may required to be changed on ASIC
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002256 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002257
2258 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
2259 }
2260
2261
2262
2263}
2264
2265//temporary hw beacon is not used any more.
2266//open it when necessary
2267#if 1
2268void rtl819xusb_beacon_tx(struct net_device *dev,u16 tx_rate)
2269{
2270
2271#if 0
2272 struct r8192_priv *priv = ieee80211_priv(dev);
2273 struct sk_buff *skb;
2274 int i = 0;
2275 //u8 cr;
2276
2277 rtl8192_net_update(dev);
2278
2279 skb = ieee80211_get_beacon(priv->ieee80211);
2280 if(!skb){
2281 DMESG("not enought memory for allocating beacon");
2282 return;
2283 }
2284
2285
2286 write_nic_byte(dev, BQREQ, read_nic_byte(dev, BQREQ) | (1<<7));
2287
2288 i=0;
2289 //while(!read_nic_byte(dev,BQREQ & (1<<7)))
2290 while( (read_nic_byte(dev, BQREQ) & (1<<7)) == 0 )
2291 {
2292 msleep_interruptible_rtl(HZ/2);
2293 if(i++ > 10){
2294 DMESGW("get stuck to wait HW beacon to be ready");
2295 return ;
2296 }
2297 }
2298 skb->cb[0] = NORM_PRIORITY;
2299 skb->cb[1] = 0; //morefragment = 0
2300 skb->cb[2] = ieeerate2rtlrate(tx_rate);
2301
2302 rtl8192_tx(dev,skb);
2303
2304#endif
2305}
2306#endif
2307inline u8 rtl8192_IsWirelessBMode(u16 rate)
2308{
2309 if( ((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220) )
2310 return 1;
2311 else return 0;
2312}
2313
2314u16 N_DBPSOfRate(u16 DataRate);
2315
2316u16 ComputeTxTime(
2317 u16 FrameLength,
2318 u16 DataRate,
2319 u8 bManagementFrame,
2320 u8 bShortPreamble
2321)
2322{
2323 u16 FrameTime;
2324 u16 N_DBPS;
2325 u16 Ceiling;
2326
2327 if( rtl8192_IsWirelessBMode(DataRate) )
2328 {
2329 if( bManagementFrame || !bShortPreamble || DataRate == 10 )
2330 { // long preamble
2331 FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
2332 }
2333 else
2334 { // Short preamble
2335 FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
2336 }
2337 if( ( FrameLength*8 % (DataRate/10) ) != 0 ) //Get the Ceilling
2338 FrameTime ++;
2339 } else { //802.11g DSSS-OFDM PLCP length field calculation.
2340 N_DBPS = N_DBPSOfRate(DataRate);
2341 Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
2342 + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
2343 FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
2344 }
2345 return FrameTime;
2346}
2347
2348u16 N_DBPSOfRate(u16 DataRate)
2349{
2350 u16 N_DBPS = 24;
2351
2352 switch(DataRate)
2353 {
2354 case 60:
2355 N_DBPS = 24;
2356 break;
2357
2358 case 90:
2359 N_DBPS = 36;
2360 break;
2361
2362 case 120:
2363 N_DBPS = 48;
2364 break;
2365
2366 case 180:
2367 N_DBPS = 72;
2368 break;
2369
2370 case 240:
2371 N_DBPS = 96;
2372 break;
2373
2374 case 360:
2375 N_DBPS = 144;
2376 break;
2377
2378 case 480:
2379 N_DBPS = 192;
2380 break;
2381
2382 case 540:
2383 N_DBPS = 216;
2384 break;
2385
2386 default:
2387 break;
2388 }
2389
2390 return N_DBPS;
2391}
2392
2393void rtl819xU_cmd_isr(struct urb *tx_cmd_urb, struct pt_regs *regs)
2394{
2395#if 0
2396 struct net_device *dev = (struct net_device*)tx_cmd_urb->context;
2397 struct r8192_priv *priv = ieee80211_priv(dev);
2398 int last_init_packet = 0;
2399 u8 *ptr_cmd_buf;
2400 u16 cmd_buf_len;
2401
2402 if(tx_cmd_urb->status != 0) {
2403 priv->pFirmware.firmware_seg_index = 0; //only begin transter, should it can be set to 1
2404 }
2405
2406 /* Free the urb and the corresponding buf for common Tx cmd packet, or
2407 * last segment of each firmware img.
2408 */
2409 if((priv->pFirmware.firmware_seg_index == 0) ||(priv->pFirmware.firmware_seg_index == priv->pFirmware.firmware_seg_maxnum)) {
2410 priv->pFirmware.firmware_seg_index = 0;//only begin transter, should it can be set to 1
2411 } else {
2412 /* prepare for last transfer */
2413 /* update some infomation for */
2414 /* last segment of the firmware img need indicate to device */
2415 priv->pFirmware.firmware_seg_index++;
2416 if(priv->pFirmware.firmware_seg_index == priv->pFirmware.firmware_seg_maxnum) {
2417 last_init_packet = 1;
2418 }
2419
2420 cmd_buf_len = priv->pFirmware.firmware_seg_container[priv->pFirmware.firmware_seg_index-1].seg_size;
2421 ptr_cmd_buf = priv->pFfirmware.firmware_seg_container[priv->pFfirmware.firmware_seg_index-1].seg_ptr;
2422 rtl819xU_tx_cmd(dev, ptr_cmd_buf, cmd_buf_len, last_init_packet, DESC_PACKET_TYPE_INIT);
2423 }
2424
2425 kfree(tx_cmd_urb->transfer_buffer);
2426#endif
2427 usb_free_urb(tx_cmd_urb);
2428}
2429
2430unsigned int txqueue2outpipe(struct r8192_priv* priv,unsigned int tx_queue) {
2431
2432 if(tx_queue >= 9)
2433 {
2434 RT_TRACE(COMP_ERR,"%s():Unknown queue ID!!!\n",__FUNCTION__);
2435 return 0x04;
2436 }
2437 return priv->txqueue_to_outpipemap[tx_queue];
2438}
2439
2440short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
2441{
2442 struct r8192_priv *priv = ieee80211_priv(dev);
2443 //u8 *tx;
2444 int status;
2445 struct urb *tx_urb;
2446 //int urb_buf_len;
2447 unsigned int idx_pipe;
2448 tx_desc_cmd_819x_usb *pdesc = (tx_desc_cmd_819x_usb *)skb->data;
2449 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
2450 u8 queue_index = tcb_desc->queue_index;
2451
2452 //printk("\n %s::queue_index = %d\n",__FUNCTION__, queue_index);
2453 atomic_inc(&priv->tx_pending[queue_index]);
2454#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2455 tx_urb = usb_alloc_urb(0,GFP_ATOMIC);
2456#else
2457 tx_urb = usb_alloc_urb(0);
2458#endif
2459 if(!tx_urb){
2460 dev_kfree_skb(skb);
2461 return -ENOMEM;
2462 }
2463
2464 memset(pdesc, 0, USB_HWDESC_HEADER_LEN);
2465 /* Tx descriptor ought to be set according to the skb->cb */
2466 pdesc->FirstSeg = 1;//bFirstSeg;
2467 pdesc->LastSeg = 1;//bLastSeg;
2468 pdesc->CmdInit = tcb_desc->bCmdOrInit;
2469 pdesc->TxBufferSize = tcb_desc->txbuf_size;
2470 pdesc->OWN = 1;
2471 pdesc->LINIP = tcb_desc->bLastIniPkt;
2472
2473 //----------------------------------------------------------------------------
2474 // Fill up USB_OUT_CONTEXT.
2475 //----------------------------------------------------------------------------
2476 // Get index to out pipe from specified QueueID.
2477#ifndef USE_ONE_PIPE
2478 idx_pipe = txqueue2outpipe(priv,queue_index);
2479#else
2480 idx_pipe = 0x04;
2481#endif
2482#ifdef JOHN_DUMP_TXDESC
2483 int i;
2484 printk("<Tx descriptor>--rate %x---",rate);
2485 for (i = 0; i < 8; i++)
2486 printk("%8x ", tx[i]);
2487 printk("\n");
2488#endif
2489 usb_fill_bulk_urb(tx_urb,priv->udev, usb_sndbulkpipe(priv->udev,idx_pipe), \
2490 skb->data, skb->len, rtl8192_tx_isr, skb);
2491
2492#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2493 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
2494#else
2495 status = usb_submit_urb(tx_urb);
2496#endif
2497
2498 if (!status){
2499 return 0;
2500 }else{
2501 DMESGE("Error TX CMD URB, error %d",
2502 status);
2503 return -1;
2504 }
2505}
2506
2507/*
2508 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
2509 * in TxFwInfo data structure
2510 * 2006.10.30 by Emily
2511 *
2512 * \param QUEUEID Software Queue
2513*/
2514u8 MapHwQueueToFirmwareQueue(u8 QueueID)
2515{
2516 u8 QueueSelect = 0x0; //defualt set to
2517
2518 switch(QueueID) {
2519 case BE_QUEUE:
2520 QueueSelect = QSLT_BE; //or QSelect = pTcb->priority;
2521 break;
2522
2523 case BK_QUEUE:
2524 QueueSelect = QSLT_BK; //or QSelect = pTcb->priority;
2525 break;
2526
2527 case VO_QUEUE:
2528 QueueSelect = QSLT_VO; //or QSelect = pTcb->priority;
2529 break;
2530
2531 case VI_QUEUE:
2532 QueueSelect = QSLT_VI; //or QSelect = pTcb->priority;
2533 break;
2534 case MGNT_QUEUE:
2535 QueueSelect = QSLT_MGNT;
2536 break;
2537
2538 case BEACON_QUEUE:
2539 QueueSelect = QSLT_BEACON;
2540 break;
2541
2542 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
2543 // TODO: Remove Assertions
2544//#if (RTL819X_FPGA_VER & RTL819X_FPGA_GUANGAN_070502)
2545 case TXCMD_QUEUE:
2546 QueueSelect = QSLT_CMD;
2547 break;
2548//#endif
2549 case HIGH_QUEUE:
2550 QueueSelect = QSLT_HIGH;
2551 break;
2552
2553 default:
2554 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
2555 break;
2556 }
2557 return QueueSelect;
2558}
2559
2560u8 MRateToHwRate8190Pci(u8 rate)
2561{
2562 u8 ret = DESC90_RATE1M;
2563
2564 switch(rate) {
2565 case MGN_1M: ret = DESC90_RATE1M; break;
2566 case MGN_2M: ret = DESC90_RATE2M; break;
2567 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
2568 case MGN_11M: ret = DESC90_RATE11M; break;
2569 case MGN_6M: ret = DESC90_RATE6M; break;
2570 case MGN_9M: ret = DESC90_RATE9M; break;
2571 case MGN_12M: ret = DESC90_RATE12M; break;
2572 case MGN_18M: ret = DESC90_RATE18M; break;
2573 case MGN_24M: ret = DESC90_RATE24M; break;
2574 case MGN_36M: ret = DESC90_RATE36M; break;
2575 case MGN_48M: ret = DESC90_RATE48M; break;
2576 case MGN_54M: ret = DESC90_RATE54M; break;
2577
2578 // HT rate since here
2579 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
2580 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
2581 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
2582 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
2583 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
2584 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
2585 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
2586 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
2587 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
2588 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
2589 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
2590 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
2591 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
2592 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
2593 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
2594 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
2595 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
2596
2597 default: break;
2598 }
2599 return ret;
2600}
2601
2602
2603u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
2604{
2605 u8 tmp_Short;
2606
2607 tmp_Short = (TxHT==1)?((tcb_desc->bUseShortGI)?1:0):((tcb_desc->bUseShortPreamble)?1:0);
2608
2609 if(TxHT==1 && TxRate != DESC90_RATEMCS15)
2610 tmp_Short = 0;
2611
2612 return tmp_Short;
2613}
2614
2615#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
2616static void tx_zero_isr(struct urb *tx_urb, struct pt_regs *reg)
2617#else
2618static void tx_zero_isr(struct urb *tx_urb)
2619#endif
2620{
2621 return;
2622}
2623
2624/*
2625 * The tx procedure is just as following,
2626 * skb->cb will contain all the following information,
2627 * priority, morefrag, rate, &dev.
2628 * */
2629short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
2630{
2631 struct r8192_priv *priv = ieee80211_priv(dev);
2632 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
2633 tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data;
2634 tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
2635 struct usb_device *udev = priv->udev;
2636 int pend;
2637 int status;
2638 struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
2639 //int urb_len;
2640 unsigned int idx_pipe;
2641// RT_DEBUG_DATA(COMP_SEND, tcb_desc, sizeof(cb_desc));
2642#if 0
2643 /* Added by Annie for filling Len_Adjust field. 2005-12-14. */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002644 RT_ENC_ALG EncAlg = NO_Encryption;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002645#endif
2646// printk("=============> %s\n", __FUNCTION__);
2647 pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]);
2648 /* we are locked here so the two atomic_read and inc are executed
2649 * without interleaves
2650 * !!! For debug purpose
2651 */
2652 if( pend > MAX_TX_URB){
2653#if 0
2654 switch (tcb_desc->queue_index) {
2655 case VO_PRIORITY:
2656 priv->stats.txvodrop++;
2657 break;
2658 case VI_PRIORITY:
2659 priv->stats.txvidrop++;
2660 break;
2661 case BE_PRIORITY:
2662 priv->stats.txbedrop++;
2663 break;
2664 default://BK_PRIORITY
2665 priv->stats.txbkdrop++;
2666 break;
2667 }
2668#endif
2669 printk("To discard skb packet!\n");
2670 dev_kfree_skb_any(skb);
2671 return -1;
2672 }
2673
2674#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2675 tx_urb = usb_alloc_urb(0,GFP_ATOMIC);
2676#else
2677 tx_urb = usb_alloc_urb(0);
2678#endif
2679 if(!tx_urb){
2680 dev_kfree_skb_any(skb);
2681 return -ENOMEM;
2682 }
2683
2684 /* Fill Tx firmware info */
2685 memset(tx_fwinfo,0,sizeof(tx_fwinfo_819x_usb));
2686 /* DWORD 0 */
2687 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0;
2688 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
2689 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
2690 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
2691 if(tcb_desc->bAMPDUEnable) {//AMPDU enabled
2692 tx_fwinfo->AllowAggregation = 1;
2693 /* DWORD 1 */
2694 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
2695 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
2696 } else {
2697 tx_fwinfo->AllowAggregation = 0;
2698 /* DWORD 1 */
2699 tx_fwinfo->RxMF = 0;
2700 tx_fwinfo->RxAMD = 0;
2701 }
2702
2703 /* Protection mode related */
2704 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0;
2705 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0;
2706 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0;
2707 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80)?1:0;
2708 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
2709 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT==0)?(tcb_desc->RTSSC):0;
2710 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT==1)?((tcb_desc->bRTSBW)?1:0):0;
2711 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):\
2712 (tcb_desc->bRTSUseShortGI?1:0);
2713
2714 /* Set Bandwidth and sub-channel settings. */
2715 if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
2716 {
2717 if(tcb_desc->bPacketBW) {
2718 tx_fwinfo->TxBandwidth = 1;
2719 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
2720 } else {
2721 tx_fwinfo->TxBandwidth = 0;
2722 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
2723 }
2724 } else {
2725 tx_fwinfo->TxBandwidth = 0;
2726 tx_fwinfo->TxSubCarrier = 0;
2727 }
2728
2729#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2730 if (tcb_desc->drv_agg_enable)
2731 {
2732 tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1;
2733 }
2734#endif
2735 /* Fill Tx descriptor */
2736 memset(tx_desc, 0, sizeof(tx_desc_819x_usb));
2737 /* DWORD 0 */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002738 tx_desc->LINIP = 0;
2739 tx_desc->CmdInit = 1;
2740 tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002741
2742#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2743 if (tcb_desc->drv_agg_enable) {
2744 tx_desc->PktSize = tcb_desc->pkt_size;
2745 } else
2746#endif
2747 {
2748 tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff;
2749 }
2750
2751 /*DWORD 1*/
2752 tx_desc->SecCAMID= 0;
2753 tx_desc->RATid = tcb_desc->RATRIndex;
2754#if 0
2755 /* Fill security related */
2756 if( pTcb->bEncrypt && !Adapter->MgntInfo.SecurityInfo.SWTxEncryptFlag)
2757 {
2758 EncAlg = SecGetEncryptionOverhead(
2759 Adapter,
2760 &EncryptionMPDUHeadOverhead,
2761 &EncryptionMPDUTailOverhead,
2762 NULL,
2763 NULL,
2764 FALSE,
2765 FALSE);
2766 //2004/07/22, kcwu, EncryptionMPDUHeadOverhead has been added in previous code
2767 //MPDUOverhead = EncryptionMPDUHeadOverhead + EncryptionMPDUTailOverhead;
2768 MPDUOverhead = EncryptionMPDUTailOverhead;
2769 tx_desc->NoEnc = 0;
2770 RT_TRACE(COMP_SEC, DBG_LOUD, ("******We in the loop SecCAMID is %d SecDescAssign is %d The Sec is %d********\n",tx_desc->SecCAMID,tx_desc->SecDescAssign,EncAlg));
2771 //CamDumpAll(Adapter);
2772 }
2773 else
2774#endif
2775 {
2776 //MPDUOverhead = 0;
2777 tx_desc->NoEnc = 1;
2778 }
2779#if 0
2780 switch(EncAlg){
2781 case NO_Encryption:
2782 tx_desc->SecType = 0x0;
2783 break;
2784 case WEP40_Encryption:
2785 case WEP104_Encryption:
2786 tx_desc->SecType = 0x1;
2787 break;
2788 case TKIP_Encryption:
2789 tx_desc->SecType = 0x2;
2790 break;
2791 case AESCCMP_Encryption:
2792 tx_desc->SecType = 0x3;
2793 break;
2794 default:
2795 tx_desc->SecType = 0x0;
2796 break;
2797 }
2798#else
2799 tx_desc->SecType = 0x0;
2800#endif
2801 if (tcb_desc->bHwSec)
2802 {
2803 switch (priv->ieee80211->pairwise_key_type)
2804 {
2805 case KEY_TYPE_WEP40:
2806 case KEY_TYPE_WEP104:
2807 tx_desc->SecType = 0x1;
2808 tx_desc->NoEnc = 0;
2809 break;
2810 case KEY_TYPE_TKIP:
2811 tx_desc->SecType = 0x2;
2812 tx_desc->NoEnc = 0;
2813 break;
2814 case KEY_TYPE_CCMP:
2815 tx_desc->SecType = 0x3;
2816 tx_desc->NoEnc = 0;
2817 break;
2818 case KEY_TYPE_NA:
2819 tx_desc->SecType = 0x0;
2820 tx_desc->NoEnc = 1;
2821 break;
2822 }
2823 }
2824
2825 tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
2826 tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
2827
2828 tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
2829 tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
2830
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002831 /* Fill fields that are required to be initialized in all of the descriptors */
2832 //DWORD 0
Jerry Chuang8fc85982009-11-03 07:17:11 -02002833#if 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002834 tx_desc->FirstSeg = (tcb_desc->bFirstSeg)? 1:0;
2835 tx_desc->LastSeg = (tcb_desc->bLastSeg)?1:0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002836#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002837 tx_desc->FirstSeg = 1;
2838 tx_desc->LastSeg = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002839#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002840 tx_desc->OWN = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002841
2842#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2843 if (tcb_desc->drv_agg_enable) {
2844 tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb);
2845 } else
2846#endif
2847 {
2848 //DWORD 2
2849 tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN);
2850 }
2851 /* Get index to out pipe from specified QueueID */
2852#ifndef USE_ONE_PIPE
2853 idx_pipe = txqueue2outpipe(priv,tcb_desc->queue_index);
2854#else
2855 idx_pipe = 0x5;
2856#endif
2857
2858 //RT_DEBUG_DATA(COMP_SEND,tx_fwinfo,sizeof(tx_fwinfo_819x_usb));
2859 //RT_DEBUG_DATA(COMP_SEND,tx_desc,sizeof(tx_desc_819x_usb));
2860
2861 /* To submit bulk urb */
2862 usb_fill_bulk_urb(tx_urb,udev,
2863 usb_sndbulkpipe(udev,idx_pipe), skb->data,
2864 skb->len, rtl8192_tx_isr, skb);
2865
2866#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2867 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
2868#else
2869 status = usb_submit_urb(tx_urb);
2870#endif
2871 if (!status){
2872//we need to send 0 byte packet whenever 512N bytes/64N(HIGN SPEED/NORMAL SPEED) bytes packet has been transmitted. Otherwise, it will be halt to wait for another packet. WB. 2008.08.27
2873 bool bSend0Byte = false;
2874 u8 zero = 0;
2875 if(udev->speed == USB_SPEED_HIGH)
2876 {
2877 if (skb->len > 0 && skb->len % 512 == 0)
2878 bSend0Byte = true;
2879 }
2880 else
2881 {
2882 if (skb->len > 0 && skb->len % 64 == 0)
2883 bSend0Byte = true;
2884 }
2885 if (bSend0Byte)
2886 {
2887#if 1
2888#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2889 tx_urb_zero = usb_alloc_urb(0,GFP_ATOMIC);
2890#else
2891 tx_urb_zero = usb_alloc_urb(0);
2892#endif
2893 if(!tx_urb_zero){
2894 RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
2895 return -ENOMEM;
2896 }
2897 usb_fill_bulk_urb(tx_urb_zero,udev,
2898 usb_sndbulkpipe(udev,idx_pipe), &zero,
2899 0, tx_zero_isr, dev);
2900#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2901 status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
2902#else
2903 status = usb_submit_urb(tx_urb_zero);
2904#endif
2905 if (status){
2906 RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
2907 return -1;
2908 }
2909#endif
2910 }
2911 dev->trans_start = jiffies;
2912 atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
2913 return 0;
2914 }else{
2915 RT_TRACE(COMP_ERR, "Error TX URB %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]),
2916 status);
2917 return -1;
2918 }
2919}
2920
2921short rtl8192_usb_initendpoints(struct net_device *dev)
2922{
2923 struct r8192_priv *priv = ieee80211_priv(dev);
2924
2925 priv->rx_urb = (struct urb**) kmalloc (sizeof(struct urb*) * (MAX_RX_URB+1), GFP_KERNEL);
2926
2927#ifndef JACKSON_NEW_RX
2928 for(i=0;i<(MAX_RX_URB+1);i++){
2929
2930#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2931 priv->rx_urb[i] = usb_alloc_urb(0,GFP_KERNEL);
2932#else
2933 priv->rx_urb[i] = usb_alloc_urb(0);
2934#endif
2935
2936 priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL);
2937
2938 priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE;
2939 }
2940#endif
2941
2942#ifdef THOMAS_BEACON
2943{
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002944 long align = 0;
2945 void *oldaddr, *newaddr;
2946
Jerry Chuang8fc85982009-11-03 07:17:11 -02002947 priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002948 priv->oldaddr = kmalloc(16, GFP_KERNEL);
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002949 oldaddr = priv->oldaddr;
2950 align = ((long)oldaddr) & 3;
2951 if (align) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002952 newaddr = oldaddr + 4 - align;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002953 priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align;
2954 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002955 newaddr = oldaddr;
2956 priv->rx_urb[16]->transfer_buffer_length = 16;
2957 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002958 priv->rx_urb[16]->transfer_buffer = newaddr;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002959}
2960#endif
2961
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002962 memset(priv->rx_urb, 0, sizeof(struct urb*) * MAX_RX_URB);
2963 priv->pp_rxskb = (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) * MAX_RX_URB, GFP_KERNEL);
2964 if (priv->pp_rxskb == NULL)
2965 goto destroy;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002966
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002967 memset(priv->pp_rxskb, 0, sizeof(struct sk_buff*) * MAX_RX_URB);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002968
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002969 goto _middle;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002970
2971
2972destroy:
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002973 if (priv->pp_rxskb) {
2974 kfree(priv->pp_rxskb);
2975 }
2976 if (priv->rx_urb) {
2977 kfree(priv->rx_urb);
2978 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002979
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002980 priv->pp_rxskb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002981 priv->rx_urb = NULL;
2982
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002983 DMESGE("Endpoint Alloc Failure");
2984 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002985
2986
2987_middle:
2988
2989 printk("End of initendpoints\n");
2990 return 0;
2991
2992}
2993#ifdef THOMAS_BEACON
2994void rtl8192_usb_deleteendpoints(struct net_device *dev)
2995{
2996 int i;
2997 struct r8192_priv *priv = ieee80211_priv(dev);
2998
2999 if(priv->rx_urb){
3000 for(i=0;i<(MAX_RX_URB+1);i++){
3001 usb_kill_urb(priv->rx_urb[i]);
3002 usb_free_urb(priv->rx_urb[i]);
3003 }
3004 kfree(priv->rx_urb);
3005 priv->rx_urb = NULL;
3006 }
3007 if(priv->oldaddr){
3008 kfree(priv->oldaddr);
3009 priv->oldaddr = NULL;
3010 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003011 if (priv->pp_rxskb) {
3012 kfree(priv->pp_rxskb);
3013 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003014 }
3015}
3016#else
3017void rtl8192_usb_deleteendpoints(struct net_device *dev)
3018{
3019 int i;
3020 struct r8192_priv *priv = ieee80211_priv(dev);
3021
3022#ifndef JACKSON_NEW_RX
3023
3024 if(priv->rx_urb){
3025 for(i=0;i<(MAX_RX_URB+1);i++){
3026 usb_kill_urb(priv->rx_urb[i]);
3027 kfree(priv->rx_urb[i]->transfer_buffer);
3028 usb_free_urb(priv->rx_urb[i]);
3029 }
3030 kfree(priv->rx_urb);
3031 priv->rx_urb = NULL;
3032
3033 }
3034#else
3035 if(priv->rx_urb){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003036 kfree(priv->rx_urb);
3037 priv->rx_urb = NULL;
3038 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003039 if(priv->oldaddr){
3040 kfree(priv->oldaddr);
3041 priv->oldaddr = NULL;
3042 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003043 if (priv->pp_rxskb) {
3044 kfree(priv->pp_rxskb);
3045 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003046
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003047 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003048
3049#endif
3050}
3051#endif
3052
3053#if 0
3054void rtl8192_set_rate(struct net_device *dev)
3055{
3056 int i;
3057 u16 word;
3058 int basic_rate,min_rr_rate,max_rr_rate;
3059
3060// struct r8192_priv *priv = ieee80211_priv(dev);
3061
3062 //if (ieee80211_is_54g(priv->ieee80211->current_network) &&
3063// priv->ieee80211->state == IEEE80211_LINKED){
3064 basic_rate = ieeerate2rtlrate(240);
3065 min_rr_rate = ieeerate2rtlrate(60);
3066 max_rr_rate = ieeerate2rtlrate(240);
3067
3068//
3069// }else{
3070// basic_rate = ieeerate2rtlrate(20);
3071// min_rr_rate = ieeerate2rtlrate(10);
3072// max_rr_rate = ieeerate2rtlrate(110);
3073// }
3074
3075 write_nic_byte(dev, RESP_RATE,
3076 max_rr_rate<<MAX_RESP_RATE_SHIFT| min_rr_rate<<MIN_RESP_RATE_SHIFT);
3077
3078 //word = read_nic_word(dev, BRSR);
3079 word = read_nic_word(dev, BRSR_8187);
3080 word &= ~BRSR_MBR_8185;
3081
3082
3083 for(i=0;i<=basic_rate;i++)
3084 word |= (1<<i);
3085
3086 //write_nic_word(dev, BRSR, word);
3087 write_nic_word(dev, BRSR_8187, word);
3088 //DMESG("RR:%x BRSR: %x", read_nic_byte(dev,RESP_RATE), read_nic_word(dev,BRSR));
3089}
3090#endif
3091extern void rtl8192_update_ratr_table(struct net_device* dev);
3092void rtl8192_link_change(struct net_device *dev)
3093{
3094// int i;
3095
3096 struct r8192_priv *priv = ieee80211_priv(dev);
3097 struct ieee80211_device* ieee = priv->ieee80211;
3098 //write_nic_word(dev, BCN_INTR_ITV, net->beacon_interval);
3099 if (ieee->state == IEEE80211_LINKED)
3100 {
3101 rtl8192_net_update(dev);
3102 rtl8192_update_ratr_table(dev);
3103#if 1
3104 //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
3105 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
3106 EnableHWSecurityConfig8192(dev);
3107#endif
3108 }
3109 /*update timing params*/
3110// RT_TRACE(COMP_CH, "========>%s(), chan:%d\n", __FUNCTION__, priv->chan);
3111// rtl8192_set_chan(dev, priv->chan);
3112 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
3113 {
3114 u32 reg = 0;
3115 reg = read_nic_dword(dev, RCR);
3116 if (priv->ieee80211->state == IEEE80211_LINKED)
3117 priv->ReceiveConfig = reg |= RCR_CBSSID;
3118 else
3119 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
3120 write_nic_dword(dev, RCR, reg);
3121 }
3122
3123// rtl8192_set_rxconf(dev);
3124}
3125
3126static struct ieee80211_qos_parameters def_qos_parameters = {
3127 {3,3,3,3},/* cw_min */
3128 {7,7,7,7},/* cw_max */
3129 {2,2,2,2},/* aifs */
3130 {0,0,0,0},/* flags */
3131 {0,0,0,0} /* tx_op_limit */
3132};
3133
3134
3135#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20)
3136void rtl8192_update_beacon(struct work_struct * work)
3137{
3138 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
3139 struct net_device *dev = priv->ieee80211->dev;
3140#else
3141void rtl8192_update_beacon(struct net_device *dev)
3142{
3143 struct r8192_priv *priv = ieee80211_priv(dev);
3144#endif
3145 struct ieee80211_device* ieee = priv->ieee80211;
3146 struct ieee80211_network* net = &ieee->current_network;
3147
3148 if (ieee->pHTInfo->bCurrentHTSupport)
3149 HTUpdateSelfAndPeerSetting(ieee, net);
3150 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
3151 rtl8192_update_cap(dev, net->capability);
3152}
3153/*
3154* background support to run QoS activate functionality
3155*/
3156int WDCAPARA_ADD[] = {EDCAPARA_BE,EDCAPARA_BK,EDCAPARA_VI,EDCAPARA_VO};
3157#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20)
3158void rtl8192_qos_activate(struct work_struct * work)
3159{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003160 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
3161 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003162#else
3163void rtl8192_qos_activate(struct net_device *dev)
3164{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003165 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003166#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003167 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
3168 u8 mode = priv->ieee80211->current_network.mode;
3169 //u32 size = sizeof(struct ieee80211_qos_parameters);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003170 u8 u1bAIFS;
3171 u32 u4bAcParam;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003172 int i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003173
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003174 if (priv == NULL)
3175 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003176
3177#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
3178 down(&priv->mutex);
3179#else
3180 mutex_lock(&priv->mutex);
3181#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003182 if(priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003183 goto success;
3184 RT_TRACE(COMP_QOS,"qos active process with associate response received\n");
3185 /* It better set slot time at first */
3186 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
3187 /* update the ac parameter to related registers */
3188 for(i = 0; i < QOS_QUEUE_NUM; i++) {
3189 //Mode G/A: slotTimeTimer = 9; Mode B: 20
3190 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime;
3191 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
3192 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
3193 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
3194 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
3195
3196 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
3197 //write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
3198 }
3199
3200success:
3201#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
3202 up(&priv->mutex);
3203#else
3204 mutex_unlock(&priv->mutex);
3205#endif
3206}
3207
3208static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
3209 int active_network,
3210 struct ieee80211_network *network)
3211{
3212 int ret = 0;
3213 u32 size = sizeof(struct ieee80211_qos_parameters);
3214
3215 if(priv->ieee80211->state !=IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003216 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003217
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003218 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
3219 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003220
3221 if (network->flags & NETWORK_HAS_QOS_MASK) {
3222 if (active_network &&
3223 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
3224 network->qos_data.active = network->qos_data.supported;
3225
3226 if ((network->qos_data.active == 1) && (active_network == 1) &&
3227 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
3228 (network->qos_data.old_param_count !=
3229 network->qos_data.param_count)) {
3230 network->qos_data.old_param_count =
3231 network->qos_data.param_count;
3232#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3233 queue_work(priv->priv_wq, &priv->qos_activate);
3234#else
3235 schedule_task(&priv->qos_activate);
3236#endif
3237 RT_TRACE (COMP_QOS, "QoS parameters change call "
3238 "qos_activate\n");
3239 }
3240 } else {
3241 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
3242 &def_qos_parameters, size);
3243
3244 if ((network->qos_data.active == 1) && (active_network == 1)) {
3245#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3246 queue_work(priv->priv_wq, &priv->qos_activate);
3247#else
3248 schedule_task(&priv->qos_activate);
3249#endif
3250 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
3251 }
3252 network->qos_data.active = 0;
3253 network->qos_data.supported = 0;
3254 }
3255
3256 return 0;
3257}
3258
3259/* handle manage frame frame beacon and probe response */
3260static int rtl8192_handle_beacon(struct net_device * dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003261 struct ieee80211_beacon * beacon,
3262 struct ieee80211_network * network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003263{
3264 struct r8192_priv *priv = ieee80211_priv(dev);
3265
3266 rtl8192_qos_handle_probe_response(priv,1,network);
3267#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
3268 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
3269#else
3270#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3271 schedule_task(&priv->update_beacon_wq);
3272#else
3273 queue_work(priv->priv_wq, &priv->update_beacon_wq);
3274#endif
3275
3276#endif
3277 return 0;
3278
3279}
3280
3281/*
3282* handling the beaconing responses. if we get different QoS setting
3283* off the network from the associated setting, adjust the QoS
3284* setting
3285*/
3286static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003287 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003288{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003289 int ret = 0;
3290 unsigned long flags;
3291 u32 size = sizeof(struct ieee80211_qos_parameters);
3292 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003293
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003294 if ((priv == NULL) || (network == NULL))
3295 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003296
3297 if(priv->ieee80211->state !=IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003298 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003299
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003300 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
3301 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003302
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003303 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003304 if(network->flags & NETWORK_HAS_QOS_PARAMETERS) {
3305 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
3306 &network->qos_data.parameters,\
3307 sizeof(struct ieee80211_qos_parameters));
3308 priv->ieee80211->current_network.qos_data.active = 1;
3309#if 0
3310 if((priv->ieee80211->current_network.qos_data.param_count != \
3311 network->qos_data.param_count))
3312#endif
3313 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003314 set_qos_param = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003315 /* update qos parameter for current network */
3316 priv->ieee80211->current_network.qos_data.old_param_count = \
3317 priv->ieee80211->current_network.qos_data.param_count;
3318 priv->ieee80211->current_network.qos_data.param_count = \
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003319 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003320 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003321 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003322 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
3323 &def_qos_parameters, size);
3324 priv->ieee80211->current_network.qos_data.active = 0;
3325 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003326 set_qos_param = 1;
3327 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003328
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003329 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003330
3331 RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n",__FUNCTION__,network->flags ,priv->ieee80211->current_network.qos_data.active);
3332 if (set_qos_param == 1)
3333#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3334 queue_work(priv->priv_wq, &priv->qos_activate);
3335#else
3336 schedule_task(&priv->qos_activate);
3337#endif
3338
3339
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003340 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003341}
3342
3343
3344static int rtl8192_handle_assoc_response(struct net_device *dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003345 struct ieee80211_assoc_response_frame *resp,
3346 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003347{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003348 struct r8192_priv *priv = ieee80211_priv(dev);
3349 rtl8192_qos_association_resp(priv, network);
3350 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003351}
3352
3353
3354void rtl8192_update_ratr_table(struct net_device* dev)
3355 // POCTET_STRING posLegacyRate,
3356 // u8* pMcsRate)
3357 // PRT_WLAN_STA pEntry)
3358{
3359 struct r8192_priv* priv = ieee80211_priv(dev);
3360 struct ieee80211_device* ieee = priv->ieee80211;
3361 u8* pMcsRate = ieee->dot11HTOperationalRateSet;
3362 //struct ieee80211_network *net = &ieee->current_network;
3363 u32 ratr_value = 0;
3364 u8 rate_index = 0;
3365 rtl8192_config_rate(dev, (u16*)(&ratr_value));
3366 ratr_value |= (*(u16*)(pMcsRate)) << 12;
3367// switch (net->mode)
3368 switch (ieee->mode)
3369 {
3370 case IEEE_A:
3371 ratr_value &= 0x00000FF0;
3372 break;
3373 case IEEE_B:
3374 ratr_value &= 0x0000000F;
3375 break;
3376 case IEEE_G:
3377 ratr_value &= 0x00000FF7;
3378 break;
3379 case IEEE_N_24G:
3380 case IEEE_N_5G:
3381 if (ieee->pHTInfo->PeerMimoPs == 0) //MIMO_PS_STATIC
3382 ratr_value &= 0x0007F007;
3383 else{
3384 if (priv->rf_type == RF_1T2R)
3385 ratr_value &= 0x000FF007;
3386 else
3387 ratr_value &= 0x0F81F007;
3388 }
3389 break;
3390 default:
3391 break;
3392 }
3393 ratr_value &= 0x0FFFFFFF;
3394 if(ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz){
3395 ratr_value |= 0x80000000;
3396 }else if(!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz){
3397 ratr_value |= 0x80000000;
3398 }
3399 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
3400 write_nic_byte(dev, UFWP, 1);
3401}
3402
3403static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
3404static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
3405bool GetNmodeSupportBySecCfg8192(struct net_device*dev)
3406{
3407#if 1
3408 struct r8192_priv* priv = ieee80211_priv(dev);
3409 struct ieee80211_device* ieee = priv->ieee80211;
3410 struct ieee80211_network * network = &ieee->current_network;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003411 int wpa_ie_len= ieee->wpa_ie_len;
3412 struct ieee80211_crypt_data* crypt;
3413 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003414
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003415 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02003416 //we use connecting AP's capability instead of only security config on our driver to distinguish whether it should use N mode or G mode
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003417 encrypt = (network->capability & WLAN_CAPABILITY_PRIVACY) || (ieee->host_encrypt && crypt && crypt->ops && (0 == strcmp(crypt->ops->name,"WEP")));
Jerry Chuang8fc85982009-11-03 07:17:11 -02003418
3419 /* simply judge */
3420 if(encrypt && (wpa_ie_len == 0)) {
3421 /* wep encryption, no N mode setting */
3422 return false;
3423// } else if((wpa_ie_len != 0)&&(memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) {
3424 } else if((wpa_ie_len != 0)) {
3425 /* parse pairwise key type */
3426 //if((pairwisekey = WEP40)||(pairwisekey = WEP104)||(pairwisekey = TKIP))
3427 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))))
3428 return true;
3429 else
3430 return false;
3431 } else {
3432 return true;
3433 }
3434
3435#if 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003436 //In here we discuss with SD4 David. He think we still can send TKIP in broadcast group key in MCS rate.
3437 //We can't force in G mode if Pairwie key is AES and group key is TKIP
3438 if((pSecInfo->GroupEncAlgorithm == WEP104_Encryption) || (pSecInfo->GroupEncAlgorithm == WEP40_Encryption) ||
3439 (pSecInfo->PairwiseEncAlgorithm == WEP104_Encryption) ||
3440 (pSecInfo->PairwiseEncAlgorithm == WEP40_Encryption) || (pSecInfo->PairwiseEncAlgorithm == TKIP_Encryption))
3441 {
3442 return false;
3443 }
3444 else
3445 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003446#endif
3447 return true;
3448#endif
3449}
3450
3451bool GetHalfNmodeSupportByAPs819xUsb(struct net_device* dev)
3452{
3453 bool Reval;
3454 struct r8192_priv* priv = ieee80211_priv(dev);
3455 struct ieee80211_device* ieee = priv->ieee80211;
3456
3457 if(ieee->bHalfWirelessN24GMode == true)
3458 Reval = true;
3459 else
3460 Reval = false;
3461
3462 return Reval;
3463}
3464
3465void rtl8192_refresh_supportrate(struct r8192_priv* priv)
3466{
3467 struct ieee80211_device* ieee = priv->ieee80211;
3468 //we donot consider set support rate for ABG mode, only HT MCS rate is set here.
3469 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
3470 {
3471 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
3472 //RT_DEBUG_DATA(COMP_INIT, ieee->RegHTSuppRateSet, 16);
3473 //RT_DEBUG_DATA(COMP_INIT, ieee->Regdot11HTOperationalRateSet, 16);
3474 }
3475 else
3476 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
3477 return;
3478}
3479
3480u8 rtl8192_getSupportedWireleeMode(struct net_device*dev)
3481{
3482 struct r8192_priv *priv = ieee80211_priv(dev);
3483 u8 ret = 0;
3484 switch(priv->rf_chip)
3485 {
3486 case RF_8225:
3487 case RF_8256:
3488 case RF_PSEUDO_11N:
3489 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
3490 break;
3491 case RF_8258:
3492 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
3493 break;
3494 default:
3495 ret = WIRELESS_MODE_B;
3496 break;
3497 }
3498 return ret;
3499}
3500void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode)
3501{
3502 struct r8192_priv *priv = ieee80211_priv(dev);
3503 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
3504
3505#if 1
3506 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode)==0))
3507 {
3508 if(bSupportMode & WIRELESS_MODE_N_24G)
3509 {
3510 wireless_mode = WIRELESS_MODE_N_24G;
3511 }
3512 else if(bSupportMode & WIRELESS_MODE_N_5G)
3513 {
3514 wireless_mode = WIRELESS_MODE_N_5G;
3515 }
3516 else if((bSupportMode & WIRELESS_MODE_A))
3517 {
3518 wireless_mode = WIRELESS_MODE_A;
3519 }
3520 else if((bSupportMode & WIRELESS_MODE_G))
3521 {
3522 wireless_mode = WIRELESS_MODE_G;
3523 }
3524 else if((bSupportMode & WIRELESS_MODE_B))
3525 {
3526 wireless_mode = WIRELESS_MODE_B;
3527 }
3528 else{
3529 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __FUNCTION__,bSupportMode);
3530 wireless_mode = WIRELESS_MODE_B;
3531 }
3532 }
3533#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we shoud wait for FPGA
3534 ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
3535#endif
3536 priv->ieee80211->mode = wireless_mode;
3537
3538 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
3539 priv->ieee80211->pHTInfo->bEnableHT = 1;
3540 else
3541 priv->ieee80211->pHTInfo->bEnableHT = 0;
3542 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
3543 rtl8192_refresh_supportrate(priv);
3544#endif
3545
3546}
3547//init priv variables here. only non_zero value should be initialized here.
3548static void rtl8192_init_priv_variable(struct net_device* dev)
3549{
3550 struct r8192_priv *priv = ieee80211_priv(dev);
3551 u8 i;
3552 priv->card_8192 = NIC_8192U;
3553 priv->chan = 1; //set to channel 1
3554 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
3555 priv->ieee80211->iw_mode = IW_MODE_INFRA;
3556 priv->ieee80211->ieee_up=0;
3557 priv->retry_rts = DEFAULT_RETRY_RTS;
3558 priv->retry_data = DEFAULT_RETRY_DATA;
3559 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
3560 priv->ieee80211->rate = 110; //11 mbps
3561 priv->ieee80211->short_slot = 1;
3562 priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0;
3563 priv->CckPwEnl = 6;
3564 //for silent reset
3565 priv->IrpPendingCount = 1;
3566 priv->ResetProgress = RESET_TYPE_NORESET;
3567 priv->bForcedSilentReset = 0;
3568 priv->bDisableNormalResetCheck = false;
3569 priv->force_reset = false;
3570
3571 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
3572 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
3573 priv->ieee80211->iw_mode = IW_MODE_INFRA;
3574 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
3575 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
3576 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
3577 IEEE_SOFTMAC_BEACONS;//added by amy 080604 //| //IEEE_SOFTMAC_SINGLE_QUEUE;
3578
3579 priv->ieee80211->active_scan = 1;
3580 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
3581 priv->ieee80211->host_encrypt = 1;
3582 priv->ieee80211->host_decrypt = 1;
3583 priv->ieee80211->start_send_beacons = NULL;//rtl819xusb_beacon_tx;//-by amy 080604
3584 priv->ieee80211->stop_send_beacons = NULL;//rtl8192_beacon_stop;//-by amy 080604
3585 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
3586 priv->ieee80211->set_chan = rtl8192_set_chan;
3587 priv->ieee80211->link_change = rtl8192_link_change;
3588 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
3589 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
3590 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
3591 priv->ieee80211->init_wmmparam_flag = 0;
3592 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
3593 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
3594 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
3595 priv->ieee80211->qos_support = 1;
3596
3597 //added by WB
3598// priv->ieee80211->SwChnlByTimerHandler = rtl8192_phy_SwChnl;
3599 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
3600 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
3601 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
3602 //added by david
3603 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
3604 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
3605 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
3606 //added by amy
3607 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
3608 priv->card_type = USB;
3609#ifdef TO_DO_LIST
3610 if(Adapter->bInHctTest)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003611 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003612 pHalData->ShortRetryLimit = 7;
3613 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003614 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003615#endif
3616 {
3617 priv->ShortRetryLimit = 0x30;
3618 priv->LongRetryLimit = 0x30;
3619 }
3620 priv->EarlyRxThreshold = 7;
3621 priv->enable_gpio0 = 0;
3622 priv->TransmitConfig =
3623 // TCR_DurProcMode | //for RTL8185B, duration setting by HW
3624 //? TCR_DISReqQsize |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003625 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reservied.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003626 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
3627 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
3628 (false ? TCR_SAT: 0); // FALSE: HW provies PLCP length and LENGEXT, TURE: SW proiveds them
3629#ifdef TO_DO_LIST
3630 if(Adapter->bInHctTest)
3631 pHalData->ReceiveConfig = pHalData->CSMethod |
3632 RCR_AMF | RCR_ADF | //RCR_AAP | //accept management/data
3633 //guangan200710
3634 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
3635 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
3636 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
3637 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
3638 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
3639 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt:0);
3640 else
3641
3642#endif
3643 priv->ReceiveConfig =
3644 RCR_AMF | RCR_ADF | //accept management/data
3645 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
3646 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
3647 //RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
3648 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
3649 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
3650 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT:0);
3651
3652 priv->AcmControl = 0;
3653 priv->pFirmware = (rt_firmware*)kmalloc(sizeof(rt_firmware), GFP_KERNEL);
3654 if (priv->pFirmware)
3655 memset(priv->pFirmware, 0, sizeof(rt_firmware));
3656
3657 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003658 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003659 skb_queue_head_init(&priv->skb_queue);
3660
3661 /* Tx related queue */
3662 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
3663 skb_queue_head_init(&priv->ieee80211->skb_waitQ [i]);
3664 }
3665 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
3666 skb_queue_head_init(&priv->ieee80211->skb_aggQ [i]);
3667 }
3668 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
3669 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ [i]);
3670 }
3671 priv->rf_set_chan = rtl8192_phy_SwChnl;
3672}
3673
3674//init lock here
3675static void rtl8192_init_priv_lock(struct r8192_priv* priv)
3676{
3677 spin_lock_init(&priv->tx_lock);
3678 spin_lock_init(&priv->irq_lock);//added by thomas
3679 //spin_lock_init(&priv->rf_lock);
3680 sema_init(&priv->wx_sem,1);
3681 sema_init(&priv->rf_sem,1);
3682#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
3683 sema_init(&priv->mutex, 1);
3684#else
3685 mutex_init(&priv->mutex);
3686#endif
3687}
3688
3689#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
3690extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
3691#else
3692extern void rtl819x_watchdog_wqcallback(struct net_device *dev);
3693#endif
3694
3695void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
3696//init tasklet and wait_queue here. only 2.6 above kernel is considered
3697#define DRV_NAME "wlan0"
3698static void rtl8192_init_priv_task(struct net_device* dev)
3699{
3700 struct r8192_priv *priv = ieee80211_priv(dev);
3701
3702#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3703#ifdef PF_SYNCTHREAD
3704 priv->priv_wq = create_workqueue(DRV_NAME,0);
3705#else
3706 priv->priv_wq = create_workqueue(DRV_NAME);
3707#endif
3708#endif
3709
3710#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
3711 INIT_WORK(&priv->reset_wq, rtl8192_restart);
3712
3713 //INIT_DELAYED_WORK(&priv->watch_dog_wq, hal_dm_watchdog);
3714 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
3715 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
3716// INIT_DELAYED_WORK(&priv->gpio_change_rf_wq, dm_gpio_change_rf_callback);
3717 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
3718 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
3719 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
3720 //INIT_WORK(&priv->SwChnlWorkItem, rtl8192_SwChnl_WorkItem);
3721 //INIT_WORK(&priv->SetBWModeWorkItem, rtl8192_SetBWModeWorkItem);
3722 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
3723#else
3724#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
3725 tq_init(&priv->reset_wq, (void*)rtl8192_restart, dev);
3726 tq_init(&priv->watch_dog_wq, (void*)rtl819x_watchdog_wqcallback, dev);
3727 tq_init(&priv->txpower_tracking_wq, (void*)dm_txpower_trackingcallback, dev);
3728 tq_init(&priv->rfpath_check_wq, (void*)dm_rf_pathcheck_workitemcallback, dev);
3729 tq_init(&priv->update_beacon_wq, (void*)rtl8192_update_beacon, dev);
3730 //tq_init(&priv->SwChnlWorkItem, (void*) rtl8192_SwChnl_WorkItem, dev);
3731 //tq_init(&priv->SetBWModeWorkItem, (void*)rtl8192_SetBWModeWorkItem, dev);
3732 tq_init(&priv->qos_activate, (void *)rtl8192_qos_activate, dev);
3733#else
3734 INIT_WORK(&priv->reset_wq,(void(*)(void*)) rtl8192_restart,dev);
3735 //INIT_WORK(&priv->watch_dog_wq, (void(*)(void*)) hal_dm_watchdog,dev);
3736 INIT_WORK(&priv->watch_dog_wq, (void(*)(void*)) rtl819x_watchdog_wqcallback,dev);
3737 INIT_WORK(&priv->txpower_tracking_wq, (void(*)(void*)) dm_txpower_trackingcallback,dev);
3738// INIT_WORK(&priv->gpio_change_rf_wq, (void(*)(void*)) dm_gpio_change_rf_callback,dev);
3739 INIT_WORK(&priv->rfpath_check_wq, (void(*)(void*)) dm_rf_pathcheck_workitemcallback,dev);
3740 INIT_WORK(&priv->update_beacon_wq, (void(*)(void*))rtl8192_update_beacon,dev);
3741 INIT_WORK(&priv->initialgain_operate_wq, (void(*)(void*))InitialGainOperateWorkItemCallBack,dev);
3742 //INIT_WORK(&priv->SwChnlWorkItem, (void(*)(void*)) rtl8192_SwChnl_WorkItem, dev);
3743 //INIT_WORK(&priv->SetBWModeWorkItem, (void(*)(void*)) rtl8192_SetBWModeWorkItem, dev);
3744 INIT_WORK(&priv->qos_activate, (void(*)(void *))rtl8192_qos_activate, dev);
3745#endif
3746#endif
3747
3748 tasklet_init(&priv->irq_rx_tasklet,
3749 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
3750 (unsigned long)priv);
3751}
3752
3753static void rtl8192_get_eeprom_size(struct net_device* dev)
3754{
3755 u16 curCR = 0;
3756 struct r8192_priv *priv = ieee80211_priv(dev);
3757 RT_TRACE(COMP_EPROM, "===========>%s()\n", __FUNCTION__);
3758 curCR = read_nic_word_E(dev,EPROM_CMD);
3759 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
3760 //whether need I consider BIT5?
3761 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
3762 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __FUNCTION__, priv->epromtype);
3763}
3764
3765//used to swap endian. as ntohl & htonl are not neccessary to swap endian, so use this instead.
3766static inline u16 endian_swap(u16* data)
3767{
3768 u16 tmp = *data;
3769 *data = (tmp >> 8) | (tmp << 8);
3770 return *data;
3771}
3772static void rtl8192_read_eeprom_info(struct net_device* dev)
3773{
3774 u16 wEPROM_ID = 0;
3775 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
3776 u8 bLoad_From_EEPOM = false;
3777 struct r8192_priv *priv = ieee80211_priv(dev);
3778 u16 tmpValue = 0;
3779 RT_TRACE(COMP_EPROM, "===========>%s()\n", __FUNCTION__);
3780 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
3781 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
3782
3783 if (wEPROM_ID != RTL8190_EEPROM_ID)
3784 {
3785 RT_TRACE(COMP_ERR, "EEPROM ID is invalid(is 0x%x(should be 0x%x)\n", wEPROM_ID, RTL8190_EEPROM_ID);
3786 }
3787 else
3788 bLoad_From_EEPOM = true;
3789
3790 if (bLoad_From_EEPOM)
3791 {
3792 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
3793 priv->eeprom_vid = endian_swap(&tmpValue);
3794 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
3795 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
3796 priv->eeprom_ChannelPlan =((tmpValue&0xff00)>>8);
3797 priv->btxpowerdata_readfromEEPORM = true;
3798 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
3799 }
3800 else
3801 {
3802 priv->eeprom_vid = 0;
3803 priv->eeprom_pid = 0;
3804 priv->card_8192_version = VERSION_819xU_B;
3805 priv->eeprom_ChannelPlan = 0;
3806 priv->eeprom_CustomerID = 0;
3807 }
3808 RT_TRACE(COMP_EPROM, "vid:0x%4x, pid:0x%4x, CustomID:0x%2x, ChanPlan:0x%x\n", priv->eeprom_vid, priv->eeprom_pid, priv->eeprom_CustomerID, priv->eeprom_ChannelPlan);
3809 //set channelplan from eeprom
3810 priv->ChannelPlan = priv->eeprom_ChannelPlan;
3811 if (bLoad_From_EEPOM)
3812 {
3813 int i;
3814 for (i=0; i<6; i+=2)
3815 {
3816 u16 tmp = 0;
3817 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
3818 *(u16*)(&dev->dev_addr[i]) = tmp;
3819 }
3820 }
3821 else
3822 {
3823 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
3824 //should I set IDR0 here?
3825 }
3826 RT_TRACE(COMP_EPROM, "MAC addr:"MAC_FMT"\n", MAC_ARG(dev->dev_addr));
3827 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
3828 priv->rf_chip = RF_8256;
3829
3830 if (priv->card_8192_version == (u8)VERSION_819xU_A)
3831 {
3832 //read Tx power gain offset of legacy OFDM to HT rate
3833 if (bLoad_From_EEPOM)
3834 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
3835 else
3836 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
3837 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
3838 //read ThermalMeter from EEPROM
3839 if (bLoad_From_EEPOM)
3840 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
3841 else
3842 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
3843 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
3844 //vivi, for tx power track
3845 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
3846 //read antenna tx power offset of B/C/D to A from EEPROM
3847 if (bLoad_From_EEPOM)
3848 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
3849 else
3850 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
3851 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
3852 // Read CrystalCap from EEPROM
3853 if (bLoad_From_EEPOM)
3854 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
3855 else
3856 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
3857 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
3858 //get per-channel Tx power level
3859 if (bLoad_From_EEPOM)
3860 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
3861 else
3862 priv->EEPROM_Def_Ver = 1;
3863 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
3864 if (priv->EEPROM_Def_Ver == 0) //old eeprom definition
3865 {
3866 int i;
3867 if (bLoad_From_EEPOM)
3868 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
3869 else
3870 priv->EEPROMTxPowerLevelCCK = 0x10;
3871 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
3872 for (i=0; i<3; i++)
3873 {
3874 if (bLoad_From_EEPOM)
3875 {
3876 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
3877 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
3878 tmpValue = tmpValue & 0x00ff;
3879 else
3880 tmpValue = (tmpValue & 0xff00) >> 8;
3881 }
3882 else
3883 tmpValue = 0x10;
3884 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
3885 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
3886 }
3887 }//end if EEPROM_DEF_VER == 0
3888 else if (priv->EEPROM_Def_Ver == 1)
3889 {
3890 if (bLoad_From_EEPOM)
3891 {
3892 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
3893 tmpValue = (tmpValue & 0xff00) >> 8;
3894 }
3895 else
3896 tmpValue = 0x10;
3897 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
3898
3899 if (bLoad_From_EEPOM)
3900 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
3901 else
3902 tmpValue = 0x1010;
3903 *((u16*)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
3904 if (bLoad_From_EEPOM)
3905 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
3906 else
3907 tmpValue = 0x1010;
3908 *((u16*)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
3909 if (bLoad_From_EEPOM)
3910 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
3911 else
3912 tmpValue = 0x10;
3913 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
3914 }//endif EEPROM_Def_Ver == 1
3915
3916 //update HAL variables
3917 //
3918 {
3919 int i;
3920 for (i=0; i<14; i++)
3921 {
3922 if (i<=3)
3923 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
3924 else if (i>=4 && i<=9)
3925 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
3926 else
3927 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
3928 }
3929
3930 for (i=0; i<14; i++)
3931 {
3932 if (priv->EEPROM_Def_Ver == 0)
3933 {
3934 if (i<=3)
3935 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
3936 else if (i>=4 && i<=9)
3937 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
3938 else
3939 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
3940 }
3941 else if (priv->EEPROM_Def_Ver == 1)
3942 {
3943 if (i<=3)
3944 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
3945 else if (i>=4 && i<=9)
3946 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
3947 else
3948 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
3949 }
3950 }
3951 }//end update HAL variables
3952 priv->TxPowerDiff = priv->EEPROMPwDiff;
3953// Antenna B gain offset to antenna A, bit0~3
3954 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
3955 // Antenna C gain offset to antenna A, bit4~7
3956 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
3957 // CrystalCap, bit12~15
3958 priv->CrystalCap = priv->EEPROMCrystalCap;
3959 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
3960 // 92U does not enable TX power tracking.
3961 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
3962 }//end if VersionID == VERSION_819xU_A
3963
3964//added by vivi, for dlink led, 20080416
3965 switch(priv->eeprom_CustomerID)
3966 {
3967 case EEPROM_CID_RUNTOP:
3968 priv->CustomerID = RT_CID_819x_RUNTOP;
3969 break;
3970
3971 case EEPROM_CID_DLINK:
3972 priv->CustomerID = RT_CID_DLINK;
3973 break;
3974
3975 default:
3976 priv->CustomerID = RT_CID_DEFAULT;
3977 break;
3978
3979 }
3980
3981 switch(priv->CustomerID)
3982 {
3983 case RT_CID_819x_RUNTOP:
3984 priv->LedStrategy = SW_LED_MODE2;
3985 break;
3986
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003987 case RT_CID_DLINK:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003988 priv->LedStrategy = SW_LED_MODE4;
3989 break;
3990
3991 default:
3992 priv->LedStrategy = SW_LED_MODE0;
3993 break;
3994
3995 }
3996
3997
3998 if(priv->rf_type == RF_1T2R)
3999 {
4000 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
4001 }
4002 else
4003 {
4004 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
4005 }
4006
4007 // 2008/01/16 MH We can only know RF type in the function. So we have to init
4008 // DIG RATR table again.
4009 init_rate_adaptive(dev);
4010 //we need init DIG RATR table here again.
4011
4012 RT_TRACE(COMP_EPROM, "<===========%s()\n", __FUNCTION__);
4013 return;
4014}
4015
4016short rtl8192_get_channel_map(struct net_device * dev)
4017{
4018 struct r8192_priv *priv = ieee80211_priv(dev);
4019#ifdef ENABLE_DOT11D
4020 if(priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN){
4021 printk("rtl8180_init:Error channel plan! Set to default.\n");
4022 priv->ChannelPlan= 0;
4023 }
4024 RT_TRACE(COMP_INIT, "Channel plan is %d\n",priv->ChannelPlan);
4025
4026 rtl819x_set_channel_map(priv->ChannelPlan, priv);
4027#else
4028 int ch,i;
4029 //Set Default Channel Plan
4030 if(!channels){
4031 DMESG("No channels, aborting");
4032 return -1;
4033 }
4034 ch=channels;
4035 priv->ChannelPlan= 0;//hikaru
4036 // set channels 1..14 allowed in given locale
4037 for (i=1; i<=14; i++) {
4038 (priv->ieee80211->channel_map)[i] = (u8)(ch & 0x01);
4039 ch >>= 1;
4040 }
4041#endif
4042 return 0;
4043}
4044
4045short rtl8192_init(struct net_device *dev)
4046{
4047
4048 struct r8192_priv *priv = ieee80211_priv(dev);
4049
4050 memset(&(priv->stats),0,sizeof(struct Stats));
4051 memset(priv->txqueue_to_outpipemap,0,9);
4052#ifdef PIPE12
4053 {
4054 int i=0;
4055 u8 queuetopipe[]={3,2,1,0,4,8,7,6,5};
4056 memcpy(priv->txqueue_to_outpipemap,queuetopipe,9);
4057/* for(i=0;i<9;i++)
4058 printk("%d ",priv->txqueue_to_outpipemap[i]);
4059 printk("\n");*/
4060 }
4061#else
4062 {
4063 u8 queuetopipe[]={3,2,1,0,4,4,0,4,4};
4064 memcpy(priv->txqueue_to_outpipemap,queuetopipe,9);
4065/* for(i=0;i<9;i++)
4066 printk("%d ",priv->txqueue_to_outpipemap[i]);
4067 printk("\n");*/
4068 }
4069#endif
4070 rtl8192_init_priv_variable(dev);
4071 rtl8192_init_priv_lock(priv);
4072 rtl8192_init_priv_task(dev);
4073 rtl8192_get_eeprom_size(dev);
4074 rtl8192_read_eeprom_info(dev);
4075 rtl8192_get_channel_map(dev);
4076 init_hal_dm(dev);
4077 init_timer(&priv->watch_dog_timer);
4078 priv->watch_dog_timer.data = (unsigned long)dev;
4079 priv->watch_dog_timer.function = watch_dog_timer_callback;
4080 if(rtl8192_usb_initendpoints(dev)!=0){
4081 DMESG("Endopoints initialization failed");
4082 return -ENOMEM;
4083 }
4084
4085 //rtl8192_adapter_start(dev);
4086#ifdef DEBUG_EPROM
4087 dump_eprom(dev);
4088#endif
4089 return 0;
4090}
4091
4092/******************************************************************************
4093 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
4094 * not to do all the hw config as its name says
4095 * input: net_device dev
4096 * output: none
4097 * return: none
4098 * notice: This part need to modified according to the rate set we filtered
4099 * ****************************************************************************/
4100void rtl8192_hwconfig(struct net_device* dev)
4101{
4102 u32 regRATR = 0, regRRSR = 0;
4103 u8 regBwOpMode = 0, regTmp = 0;
4104 struct r8192_priv *priv = ieee80211_priv(dev);
4105
4106// Set RRSR, RATR, and BW_OPMODE registers
4107 //
4108 switch(priv->ieee80211->mode)
4109 {
4110 case WIRELESS_MODE_B:
4111 regBwOpMode = BW_OPMODE_20MHZ;
4112 regRATR = RATE_ALL_CCK;
4113 regRRSR = RATE_ALL_CCK;
4114 break;
4115 case WIRELESS_MODE_A:
4116 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
4117 regRATR = RATE_ALL_OFDM_AG;
4118 regRRSR = RATE_ALL_OFDM_AG;
4119 break;
4120 case WIRELESS_MODE_G:
4121 regBwOpMode = BW_OPMODE_20MHZ;
4122 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
4123 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
4124 break;
4125 case WIRELESS_MODE_AUTO:
4126#ifdef TO_DO_LIST
4127 if (Adapter->bInHctTest)
4128 {
4129 regBwOpMode = BW_OPMODE_20MHZ;
4130 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
4131 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
4132 }
4133 else
4134#endif
4135 {
4136 regBwOpMode = BW_OPMODE_20MHZ;
4137 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
4138 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
4139 }
4140 break;
4141 case WIRELESS_MODE_N_24G:
4142 // It support CCK rate by default.
4143 // CCK rate will be filtered out only when associated AP does not support it.
4144 regBwOpMode = BW_OPMODE_20MHZ;
4145 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
4146 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
4147 break;
4148 case WIRELESS_MODE_N_5G:
4149 regBwOpMode = BW_OPMODE_5G;
4150 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
4151 regRRSR = RATE_ALL_OFDM_AG;
4152 break;
4153 }
4154
4155 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
4156 {
4157 u32 ratr_value = 0;
4158 ratr_value = regRATR;
4159 if (priv->rf_type == RF_1T2R)
4160 {
4161 ratr_value &= ~(RATE_ALL_OFDM_2SS);
4162 }
4163 write_nic_dword(dev, RATR0, ratr_value);
4164 write_nic_byte(dev, UFWP, 1);
4165 }
4166 regTmp = read_nic_byte(dev, 0x313);
4167 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
4168 write_nic_dword(dev, RRSR, regRRSR);
4169
4170 //
4171 // Set Retry Limit here
4172 //
4173 write_nic_word(dev, RETRY_LIMIT,
4174 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT | \
4175 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
4176 // Set Contention Window here
4177
4178 // Set Tx AGC
4179
4180 // Set Tx Antenna including Feedback control
4181
4182 // Set Auto Rate fallback control
4183
4184
4185}
4186
4187
4188//InitializeAdapter and PhyCfg
4189bool rtl8192_adapter_start(struct net_device *dev)
4190{
4191 struct r8192_priv *priv = ieee80211_priv(dev);
4192 u32 dwRegRead = 0;
4193 bool init_status = true;
4194 RT_TRACE(COMP_INIT, "====>%s()\n", __FUNCTION__);
4195 priv->Rf_Mode = RF_OP_By_SW_3wire;
4196 //for ASIC power on sequence
4197 write_nic_byte_E(dev, 0x5f, 0x80);
4198 mdelay(50);
4199 write_nic_byte_E(dev, 0x5f, 0xf0);
4200 write_nic_byte_E(dev, 0x5d, 0x00);
4201 write_nic_byte_E(dev, 0x5e, 0x80);
4202 write_nic_byte(dev, 0x17, 0x37);
4203 mdelay(10);
4204//#ifdef TO_DO_LIST
4205 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
4206 //config CPUReset Register
4207 //Firmware Reset or not?
4208 dwRegRead = read_nic_dword(dev, CPU_GEN);
4209 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
4210 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
4211 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
4212 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
4213 else
4214 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __FUNCTION__, priv->pFirmware->firmware_status);
4215
4216 write_nic_dword(dev, CPU_GEN, dwRegRead);
4217 //mdelay(30);
4218 //config BB.
4219 rtl8192_BBConfig(dev);
4220
4221#if 1
4222 //Loopback mode or not
4223 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
4224// priv->LoopbackMode = RTL819xU_MAC_LOOPBACK;
4225
4226 dwRegRead = read_nic_dword(dev, CPU_GEN);
4227 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
4228 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
4229 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
4230 dwRegRead |= CPU_CCK_LOOPBACK;
4231 else
4232 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __FUNCTION__, priv->LoopbackMode);
4233
4234 write_nic_dword(dev, CPU_GEN, dwRegRead);
4235
4236 //after reset cpu, we need wait for a seconds to write in register.
4237 udelay(500);
4238
4239 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
4240 write_nic_byte_E(dev, 0x5f, (read_nic_byte_E(dev, 0x5f)|0x20));
4241
4242 //Set Hardware
4243 rtl8192_hwconfig(dev);
4244
4245 //turn on Tx/Rx
4246 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
4247
4248 //set IDR0 here
4249 write_nic_dword(dev, MAC0, ((u32*)dev->dev_addr)[0]);
4250 write_nic_word(dev, MAC4, ((u16*)(dev->dev_addr + 4))[0]);
4251
4252 //set RCR
4253 write_nic_dword(dev, RCR, priv->ReceiveConfig);
4254
4255 //Initialize Number of Reserved Pages in Firmware Queue
4256 write_nic_dword(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << RSVD_FW_QUEUE_PAGE_BK_SHIFT |\
4257 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT | \
4258 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT | \
4259 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
4260 write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT |\
4261 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
4262 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW| \
4263 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT
4264// | NUM_OF_PAGE_IN_FW_QUEUE_PUB<<RSVD_FW_QUEUE_PAGE_PUB_SHIFT
4265 );
4266 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
4267
4268 //Set AckTimeout
4269 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
4270 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
4271
4272// RT_TRACE(COMP_INIT, "%s():priv->ResetProgress is %d\n", __FUNCTION__,priv->ResetProgress);
4273 if(priv->ResetProgress == RESET_TYPE_NORESET)
4274 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
4275 if(priv->ResetProgress == RESET_TYPE_NORESET){
4276 CamResetAllEntry(dev);
4277 {
4278 u8 SECR_value = 0x0;
4279 SECR_value |= SCR_TxEncEnable;
4280 SECR_value |= SCR_RxDecEnable;
4281 SECR_value |= SCR_NoSKMC;
4282 write_nic_byte(dev, SECR, SECR_value);
4283 }
4284 }
4285
4286 //Beacon related
4287 write_nic_word(dev, ATIMWND, 2);
4288 write_nic_word(dev, BCN_INTERVAL, 100);
4289
4290 {
4291#define DEFAULT_EDCA 0x005e4332
4292 int i;
4293 for (i=0; i<QOS_QUEUE_NUM; i++)
4294 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
4295 }
4296#ifdef USB_RX_AGGREGATION_SUPPORT
4297 //3 For usb rx firmware aggregation control
4298 if(priv->ResetProgress == RESET_TYPE_NORESET)
4299 {
4300 u32 ulValue;
4301 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
4302 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
4303 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
4304 /*
4305 * If usb rx firmware aggregation is enabled,
4306 * when anyone of three threshold conditions above is reached,
4307 * firmware will send aggregated packet to driver.
4308 */
4309 write_nic_dword(dev, 0x1a8, ulValue);
4310 priv->bCurrentRxAggrEnable = true;
4311 }
4312#endif
4313
4314 rtl8192_phy_configmac(dev);
4315
4316 if (priv->card_8192_version == (u8) VERSION_819xU_A)
4317 {
4318 rtl8192_phy_getTxPower(dev);
4319 rtl8192_phy_setTxPower(dev, priv->chan);
4320 }
4321
4322 //Firmware download
4323 init_status = init_firmware(dev);
4324 if(!init_status)
4325 {
4326 RT_TRACE(COMP_ERR,"ERR!!! %s(): Firmware download is failed\n", __FUNCTION__);
4327 return init_status;
4328 }
4329 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __FUNCTION__);
4330 //
4331#ifdef TO_DO_LIST
4332if(Adapter->ResetProgress == RESET_TYPE_NORESET)
4333 {
4334 if(pMgntInfo->RegRfOff == TRUE)
4335 { // User disable RF via registry.
4336 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
4337 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
4338 // Those action will be discard in MgntActSet_RF_State because off the same state
4339 for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
4340 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
4341 }
4342 else if(pMgntInfo->RfOffReason > RF_CHANGE_BY_PS)
4343 { // H/W or S/W RF OFF before sleep.
4344 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
4345 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
4346 }
4347 else
4348 {
4349 pHalData->eRFPowerState = eRfOn;
4350 pMgntInfo->RfOffReason = 0;
4351 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
4352 }
4353 }
4354 else
4355 {
4356 if(pHalData->eRFPowerState == eRfOff)
4357 {
4358 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
4359 // Those action will be discard in MgntActSet_RF_State because off the same state
4360 for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
4361 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
4362 }
4363 }
4364#endif
4365 //config RF.
4366 if(priv->ResetProgress == RESET_TYPE_NORESET){
4367 rtl8192_phy_RFConfig(dev);
4368 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __FUNCTION__);
4369 }
4370
4371
4372 if(priv->ieee80211->FwRWRF)
4373 // We can force firmware to do RF-R/W
4374 priv->Rf_Mode = RF_OP_By_FW;
4375 else
4376 priv->Rf_Mode = RF_OP_By_SW_3wire;
4377
4378
4379 rtl8192_phy_updateInitGain(dev);
4380 /*--set CCK and OFDM Block "ON"--*/
4381 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
4382 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
4383
4384 if(priv->ResetProgress == RESET_TYPE_NORESET)
4385 {
4386 //if D or C cut
4387 u8 tmpvalue = read_nic_byte(dev, 0x301);
4388 if(tmpvalue ==0x03)
4389 {
4390 priv->bDcut = TRUE;
4391 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
4392 }
4393 else
4394 {
4395 priv->bDcut = FALSE;
4396 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
4397 }
4398 dm_initialize_txpower_tracking(dev);
4399
4400 if(priv->bDcut == TRUE)
4401 {
4402 u32 i, TempCCk;
4403 u32 tmpRegA= rtl8192_QueryBBReg(dev,rOFDM0_XATxIQImbalance,bMaskDWord);
4404 // u32 tmpRegC= rtl8192_QueryBBReg(dev,rOFDM0_XCTxIQImbalance,bMaskDWord);
4405 for(i = 0; i<TxBBGainTableLength; i++)
4406 {
4407 if(tmpRegA == priv->txbbgain_table[i].txbbgain_value)
4408 {
4409 priv->rfa_txpowertrackingindex= (u8)i;
4410 priv->rfa_txpowertrackingindex_real= (u8)i;
4411 priv->rfa_txpowertracking_default= priv->rfa_txpowertrackingindex;
4412 break;
4413 }
4414 }
4415
4416 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
4417
4418 for(i=0 ; i<CCKTxBBGainTableLength ; i++)
4419 {
4420
4421 if(TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0])
4422 {
4423 priv->cck_present_attentuation_20Mdefault=(u8) i;
4424 break;
4425 }
4426 }
4427 priv->cck_present_attentuation_40Mdefault= 0;
4428 priv->cck_present_attentuation_difference= 0;
4429 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
4430
4431 // pMgntInfo->bTXPowerTracking = FALSE;//TEMPLY DISABLE
4432 }
4433 }
4434 write_nic_byte(dev, 0x87, 0x0);
4435
4436
4437#endif
4438 return init_status;
4439}
4440
4441/* this configures registers for beacon tx and enables it via
4442 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
4443 * be used to stop beacon transmission
4444 */
4445#if 0
4446void rtl8192_start_tx_beacon(struct net_device *dev)
4447{
4448 int i;
4449 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4450 u16 word;
4451 DMESG("Enabling beacon TX");
4452 //write_nic_byte(dev, TX_CONF,0xe6);// TX_CONF
4453 //rtl8192_init_beacon(dev);
4454 //set_nic_txring(dev);
4455// rtl8192_prepare_beacon(dev);
4456 rtl8192_irq_disable(dev);
4457// rtl8192_beacon_tx_enable(dev);
4458 rtl8192_set_mode(dev,EPROM_CMD_CONFIG);
4459 //write_nic_byte(dev,0x9d,0x20); //DMA Poll
4460 //write_nic_word(dev,0x7a,0);
4461 //write_nic_word(dev,0x7a,0x8000);
4462
4463
4464 word = read_nic_word(dev, BcnItv);
4465 word &= ~BcnItv_BcnItv; // clear Bcn_Itv
4466 write_nic_word(dev, BcnItv, word);
4467
4468 write_nic_word(dev, AtimWnd,
4469 read_nic_word(dev, AtimWnd) &~ AtimWnd_AtimWnd);
4470
4471 word = read_nic_word(dev, BCN_INTR_ITV);
4472 word &= ~BCN_INTR_ITV_MASK;
4473
4474 //word |= priv->ieee80211->beacon_interval *
4475 // ((priv->txbeaconcount > 1)?(priv->txbeaconcount-1):1);
4476 // FIXME:FIXME check if correct ^^ worked with 0x3e8;
4477
4478 write_nic_word(dev, BCN_INTR_ITV, word);
4479
4480 //write_nic_word(dev,0x2e,0xe002);
4481 //write_nic_dword(dev,0x30,0xb8c7832e);
4482 for(i=0; i<ETH_ALEN; i++)
4483 write_nic_byte(dev, BSSID+i, priv->ieee80211->beacon_cell_ssid[i]);
4484
4485// rtl8192_update_msr(dev);
4486
4487
4488 //write_nic_byte(dev,CONFIG4,3); /* !!!!!!!!!! */
4489
4490 rtl8192_set_mode(dev, EPROM_CMD_NORMAL);
4491
4492 rtl8192_irq_enable(dev);
4493
4494 /* VV !!!!!!!!!! VV*/
4495 /*
4496 rtl8192_set_mode(dev,EPROM_CMD_CONFIG);
4497 write_nic_byte(dev,0x9d,0x00);
4498 rtl8192_set_mode(dev,EPROM_CMD_NORMAL);
4499*/
4500}
4501#endif
4502/***************************************************************************
4503 -------------------------------NET STUFF---------------------------
4504***************************************************************************/
4505
4506static struct net_device_stats *rtl8192_stats(struct net_device *dev)
4507{
4508 struct r8192_priv *priv = ieee80211_priv(dev);
4509
4510 return &priv->ieee80211->stats;
4511}
4512
4513bool
4514HalTxCheckStuck819xUsb(
4515 struct net_device *dev
4516 )
4517{
4518 struct r8192_priv *priv = ieee80211_priv(dev);
4519 u16 RegTxCounter = read_nic_word(dev, 0x128);
4520 bool bStuck = FALSE;
4521 RT_TRACE(COMP_RESET,"%s():RegTxCounter is %d,TxCounter is %d\n",__FUNCTION__,RegTxCounter,priv->TxCounter);
4522 if(priv->TxCounter==RegTxCounter)
4523 bStuck = TRUE;
4524
4525 priv->TxCounter = RegTxCounter;
4526
4527 return bStuck;
4528}
4529
4530/*
4531* <Assumption: RT_TX_SPINLOCK is acquired.>
4532* First added: 2006.11.19 by emily
4533*/
4534RESET_TYPE
4535TxCheckStuck(struct net_device *dev)
4536{
4537 struct r8192_priv *priv = ieee80211_priv(dev);
4538 u8 QueueID;
4539// PRT_TCB pTcb;
4540// u8 ResetThreshold;
4541 bool bCheckFwTxCnt = false;
4542 //unsigned long flags;
4543
4544 //
4545 // Decide Stuch threshold according to current power save mode
4546 //
4547
4548// RT_TRACE(COMP_RESET, " ==> TxCheckStuck()\n");
4549// PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
4550// spin_lock_irqsave(&priv->ieee80211->lock,flags);
4551 for (QueueID = 0; QueueID<=BEACON_QUEUE;QueueID ++)
4552 {
4553 if(QueueID == TXCMD_QUEUE)
4554 continue;
4555#if 1
4556#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
4557 if((skb_queue_len(&priv->ieee80211->skb_waitQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_aggQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_drv_aggQ[QueueID]) == 0))
4558#else
4559 if((skb_queue_len(&priv->ieee80211->skb_waitQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_aggQ[QueueID]) == 0))
4560#endif
4561 continue;
4562#endif
4563
4564 bCheckFwTxCnt = true;
4565 }
4566// PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
4567// spin_unlock_irqrestore(&priv->ieee80211->lock,flags);
4568// RT_TRACE(COMP_RESET,"bCheckFwTxCnt is %d\n",bCheckFwTxCnt);
4569#if 1
4570 if(bCheckFwTxCnt)
4571 {
4572 if(HalTxCheckStuck819xUsb(dev))
4573 {
4574 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
4575 return RESET_TYPE_SILENT;
4576 }
4577 }
4578#endif
4579 return RESET_TYPE_NORESET;
4580}
4581
4582bool
4583HalRxCheckStuck819xUsb(struct net_device *dev)
4584{
4585 u16 RegRxCounter = read_nic_word(dev, 0x130);
4586 struct r8192_priv *priv = ieee80211_priv(dev);
4587 bool bStuck = FALSE;
4588 static u8 rx_chk_cnt = 0;
4589 RT_TRACE(COMP_RESET,"%s(): RegRxCounter is %d,RxCounter is %d\n",__FUNCTION__,RegRxCounter,priv->RxCounter);
4590 // If rssi is small, we should check rx for long time because of bad rx.
4591 // or maybe it will continuous silent reset every 2 seconds.
4592 rx_chk_cnt++;
4593 if(priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5))
4594 {
4595 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
4596 }
4597 else if(priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
4598 ((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_40M) ||
4599 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_20M)) )
4600 {
4601 if(rx_chk_cnt < 2)
4602 {
4603 return bStuck;
4604 }
4605 else
4606 {
4607 rx_chk_cnt = 0;
4608 }
4609 }
4610 else if(((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_40M) ||
4611 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_20M)) &&
4612 priv->undecorated_smoothed_pwdb >= VeryLowRSSI)
4613 {
4614 if(rx_chk_cnt < 4)
4615 {
4616 //DbgPrint("RSSI < %d && RSSI >= %d, no check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
4617 return bStuck;
4618 }
4619 else
4620 {
4621 rx_chk_cnt = 0;
4622 //DbgPrint("RSSI < %d && RSSI >= %d, check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
4623 }
4624 }
4625 else
4626 {
4627 if(rx_chk_cnt < 8)
4628 {
4629 //DbgPrint("RSSI <= %d, no check this time \n", VeryLowRSSI);
4630 return bStuck;
4631 }
4632 else
4633 {
4634 rx_chk_cnt = 0;
4635 //DbgPrint("RSSI <= %d, check this time \n", VeryLowRSSI);
4636 }
4637 }
4638
4639 if(priv->RxCounter==RegRxCounter)
4640 bStuck = TRUE;
4641
4642 priv->RxCounter = RegRxCounter;
4643
4644 return bStuck;
4645}
4646
4647RESET_TYPE
4648RxCheckStuck(struct net_device *dev)
4649{
4650 struct r8192_priv *priv = ieee80211_priv(dev);
4651 //int i;
4652 bool bRxCheck = FALSE;
4653
4654// RT_TRACE(COMP_RESET," ==> RxCheckStuck()\n");
4655 //PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK);
4656
4657 if(priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004658 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004659 //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK);
4660
4661// RT_TRACE(COMP_RESET,"bRxCheck is %d \n",bRxCheck);
4662 if(bRxCheck)
4663 {
4664 if(HalRxCheckStuck819xUsb(dev))
4665 {
4666 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
4667 return RESET_TYPE_SILENT;
4668 }
4669 }
4670 return RESET_TYPE_NORESET;
4671}
4672
4673
4674/**
4675* This function is called by Checkforhang to check whether we should ask OS to reset driver
4676*
4677* \param pAdapter The adapter context for this miniport
4678*
4679* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
4680* to judge whether there is tx stuck.
4681* Note: This function may be required to be rewrite for Vista OS.
4682* <<<Assumption: Tx spinlock has been acquired >>>
4683*
4684* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
4685*/
4686RESET_TYPE
4687rtl819x_ifcheck_resetornot(struct net_device *dev)
4688{
4689 struct r8192_priv *priv = ieee80211_priv(dev);
4690 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
4691 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
4692 RT_RF_POWER_STATE rfState;
4693
4694 rfState = priv->ieee80211->eRFPowerState;
4695
4696 TxResetType = TxCheckStuck(dev);
4697#if 1
4698 if( rfState != eRfOff ||
4699 /*ADAPTER_TEST_STATUS_FLAG(Adapter, ADAPTER_STATUS_FW_DOWNLOAD_FAILURE)) &&*/
4700 (priv->ieee80211->iw_mode != IW_MODE_ADHOC))
4701 {
4702 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
4703 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
4704 // if driver is in firmware download failure status, driver should initialize RF in the following
4705 // silent reset procedure Emily, 2008.01.21
4706
4707 // Driver should not check RX stuck in IBSS mode because it is required to
4708 // set Check BSSID in order to send beacon, however, if check BSSID is
4709 // set, STA cannot hear any packet a all. Emily, 2008.04.12
4710 RxResetType = RxCheckStuck(dev);
4711 }
4712#endif
4713 if(TxResetType==RESET_TYPE_NORMAL || RxResetType==RESET_TYPE_NORMAL)
4714 return RESET_TYPE_NORMAL;
4715 else if(TxResetType==RESET_TYPE_SILENT || RxResetType==RESET_TYPE_SILENT){
4716 RT_TRACE(COMP_RESET,"%s():silent reset\n",__FUNCTION__);
4717 return RESET_TYPE_SILENT;
4718 }
4719 else
4720 return RESET_TYPE_NORESET;
4721
4722}
4723
4724void rtl8192_cancel_deferred_work(struct r8192_priv* priv);
4725int _rtl8192_up(struct net_device *dev);
4726int rtl8192_close(struct net_device *dev);
4727
4728
4729
4730void
4731CamRestoreAllEntry( struct net_device *dev)
4732{
4733 u8 EntryId = 0;
4734 struct r8192_priv *priv = ieee80211_priv(dev);
4735 u8* MacAddr = priv->ieee80211->current_network.bssid;
4736
4737 static u8 CAM_CONST_ADDR[4][6] = {
4738 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
4739 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
4740 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
4741 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
4742 static u8 CAM_CONST_BROAD[] =
4743 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4744
4745 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
4746
4747
4748 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40)||
4749 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104))
4750 {
4751
4752 for(EntryId=0; EntryId<4; EntryId++)
4753 {
4754 {
4755 MacAddr = CAM_CONST_ADDR[EntryId];
4756 setKey(dev,
4757 EntryId ,
4758 EntryId,
4759 priv->ieee80211->pairwise_key_type,
4760 MacAddr,
4761 0,
4762 NULL);
4763 }
4764 }
4765
4766 }
4767 else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP)
4768 {
4769
4770 {
4771 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
4772 setKey(dev,
4773 4,
4774 0,
4775 priv->ieee80211->pairwise_key_type,
4776 (u8*)dev->dev_addr,
4777 0,
4778 NULL);
4779 else
4780 setKey(dev,
4781 4,
4782 0,
4783 priv->ieee80211->pairwise_key_type,
4784 MacAddr,
4785 0,
4786 NULL);
4787 }
4788 }
4789 else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP)
4790 {
4791
4792 {
4793 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
4794 setKey(dev,
4795 4,
4796 0,
4797 priv->ieee80211->pairwise_key_type,
4798 (u8*)dev->dev_addr,
4799 0,
4800 NULL);
4801 else
4802 setKey(dev,
4803 4,
4804 0,
4805 priv->ieee80211->pairwise_key_type,
4806 MacAddr,
4807 0,
4808 NULL);
4809 }
4810 }
4811
4812
4813
4814 if(priv->ieee80211->group_key_type == KEY_TYPE_TKIP)
4815 {
4816 MacAddr = CAM_CONST_BROAD;
4817 for(EntryId=1 ; EntryId<4 ; EntryId++)
4818 {
4819 {
4820 setKey(dev,
4821 EntryId,
4822 EntryId,
4823 priv->ieee80211->group_key_type,
4824 MacAddr,
4825 0,
4826 NULL);
4827 }
4828 }
4829 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
4830 setKey(dev,
4831 0,
4832 0,
4833 priv->ieee80211->group_key_type,
4834 CAM_CONST_ADDR[0],
4835 0,
4836 NULL);
4837 }
4838 else if(priv->ieee80211->group_key_type == KEY_TYPE_CCMP)
4839 {
4840 MacAddr = CAM_CONST_BROAD;
4841 for(EntryId=1; EntryId<4 ; EntryId++)
4842 {
4843 {
4844 setKey(dev,
4845 EntryId ,
4846 EntryId,
4847 priv->ieee80211->group_key_type,
4848 MacAddr,
4849 0,
4850 NULL);
4851 }
4852 }
4853
4854 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
4855 setKey(dev,
4856 0 ,
4857 0,
4858 priv->ieee80211->group_key_type,
4859 CAM_CONST_ADDR[0],
4860 0,
4861 NULL);
4862 }
4863}
4864//////////////////////////////////////////////////////////////
4865// This function is used to fix Tx/Rx stop bug temporarily.
4866// This function will do "system reset" to NIC when Tx or Rx is stuck.
4867// The method checking Tx/Rx stuck of this function is supported by FW,
4868// which reports Tx and Rx counter to register 0x128 and 0x130.
4869//////////////////////////////////////////////////////////////
4870void
4871rtl819x_ifsilentreset(struct net_device *dev)
4872{
4873 //OCTET_STRING asocpdu;
4874 struct r8192_priv *priv = ieee80211_priv(dev);
4875 u8 reset_times = 0;
4876 int reset_status = 0;
4877 struct ieee80211_device *ieee = priv->ieee80211;
4878
4879
4880 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
4881 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
4882
4883 if(priv->ResetProgress==RESET_TYPE_NORESET)
4884 {
4885RESET_START:
4886
4887 RT_TRACE(COMP_RESET,"=========>Reset progress!! \n");
4888
4889 // Set the variable for reset.
4890 priv->ResetProgress = RESET_TYPE_SILENT;
4891// rtl8192_close(dev);
4892#if 1
4893 down(&priv->wx_sem);
4894 if(priv->up == 0)
4895 {
4896 RT_TRACE(COMP_ERR,"%s():the driver is not up! return\n",__FUNCTION__);
4897 up(&priv->wx_sem);
4898 return ;
4899 }
4900 priv->up = 0;
4901 RT_TRACE(COMP_RESET,"%s():======>start to down the driver\n",__FUNCTION__);
4902// if(!netif_queue_stopped(dev))
4903// netif_stop_queue(dev);
4904
4905 rtl8192_rtx_disable(dev);
4906 rtl8192_cancel_deferred_work(priv);
4907 deinit_hal_dm(dev);
4908 del_timer_sync(&priv->watch_dog_timer);
4909
4910 ieee->sync_scan_hurryup = 1;
4911 if(ieee->state == IEEE80211_LINKED)
4912 {
4913 down(&ieee->wx_sem);
4914 printk("ieee->state is IEEE80211_LINKED\n");
4915 ieee80211_stop_send_beacons(priv->ieee80211);
4916 del_timer_sync(&ieee->associate_timer);
4917 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
4918 cancel_delayed_work(&ieee->associate_retry_wq);
4919 #endif
4920 ieee80211_stop_scan(ieee);
4921 netif_carrier_off(dev);
4922 up(&ieee->wx_sem);
4923 }
4924 else{
4925 printk("ieee->state is NOT LINKED\n");
4926 ieee80211_softmac_stop_protocol(priv->ieee80211); }
4927 up(&priv->wx_sem);
4928 RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__);
4929 //rtl8192_irq_disable(dev);
4930 RT_TRACE(COMP_RESET,"%s():===========>start to up the driver\n",__FUNCTION__);
4931 reset_status = _rtl8192_up(dev);
4932
4933 RT_TRACE(COMP_RESET,"%s():<===========up process is finished\n",__FUNCTION__);
4934 if(reset_status == -EAGAIN)
4935 {
4936 if(reset_times < 3)
4937 {
4938 reset_times++;
4939 goto RESET_START;
4940 }
4941 else
4942 {
4943 RT_TRACE(COMP_ERR," ERR!!! %s(): Reset Failed!!\n", __FUNCTION__);
4944 }
4945 }
4946#endif
4947 ieee->is_silent_reset = 1;
4948#if 1
4949 EnableHWSecurityConfig8192(dev);
4950#if 1
4951 if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA)
4952 {
4953 ieee->set_chan(ieee->dev, ieee->current_network.channel);
4954
4955#if 1
4956#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
4957 queue_work(ieee->wq, &ieee->associate_complete_wq);
4958#else
4959 schedule_task(&ieee->associate_complete_wq);
4960#endif
4961#endif
4962
4963 }
4964 else if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC)
4965 {
4966 ieee->set_chan(ieee->dev, ieee->current_network.channel);
4967 ieee->link_change(ieee->dev);
4968
4969 // notify_wx_assoc_event(ieee);
4970
4971 ieee80211_start_send_beacons(ieee);
4972
4973 if (ieee->data_hard_resume)
4974 ieee->data_hard_resume(ieee->dev);
4975 netif_carrier_on(ieee->dev);
4976 }
4977#endif
4978
4979 CamRestoreAllEntry(dev);
4980
4981 priv->ResetProgress = RESET_TYPE_NORESET;
4982 priv->reset_count++;
4983
4984 priv->bForcedSilentReset =false;
4985 priv->bResetInProgress = false;
4986
4987 // For test --> force write UFWP.
4988 write_nic_byte(dev, UFWP, 1);
4989 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
4990#endif
4991 }
4992}
4993
4994void CAM_read_entry(
4995 struct net_device *dev,
4996 u32 iIndex
4997)
4998{
4999 u32 target_command=0;
5000 u32 target_content=0;
5001 u8 entry_i=0;
5002 u32 ulStatus;
5003 s32 i=100;
5004// printk("=======>start read CAM\n");
5005 for(entry_i=0;entry_i<CAM_CONTENT_COUNT;entry_i++)
5006 {
5007 // polling bit, and No Write enable, and address
5008 target_command= entry_i+CAM_CONTENT_COUNT*iIndex;
5009 target_command= target_command | BIT31;
5010
5011 //Check polling bit is clear
5012// mdelay(1);
5013#if 1
5014 while((i--)>=0)
5015 {
5016 ulStatus = read_nic_dword(dev, RWCAM);
5017 if(ulStatus & BIT31){
5018 continue;
5019 }
5020 else{
5021 break;
5022 }
5023 }
5024#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005025 write_nic_dword(dev, RWCAM, target_command);
5026 RT_TRACE(COMP_SEC,"CAM_read_entry(): WRITE A0: %x \n",target_command);
5027 // printk("CAM_read_entry(): WRITE A0: %lx \n",target_command);
5028 target_content = read_nic_dword(dev, RCAMO);
5029 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n",target_content);
5030 // printk("CAM_read_entry(): WRITE A8: %lx \n",target_content);
5031 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005032 printk("\n");
5033}
5034
5035void rtl819x_update_rxcounts(
5036 struct r8192_priv *priv,
5037 u32* TotalRxBcnNum,
5038 u32* TotalRxDataNum
5039)
5040{
5041 u16 SlotIndex;
5042 u8 i;
5043
5044 *TotalRxBcnNum = 0;
5045 *TotalRxDataNum = 0;
5046
5047 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
5048 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
5049 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
5050 for( i=0; i<priv->ieee80211->LinkDetectInfo.SlotNum; i++ ){
5051 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
5052 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
5053 }
5054}
5055
5056
5057#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
5058extern void rtl819x_watchdog_wqcallback(struct work_struct *work)
5059{
5060 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
5061 struct r8192_priv *priv = container_of(dwork,struct r8192_priv,watch_dog_wq);
5062 struct net_device *dev = priv->ieee80211->dev;
5063#else
5064extern void rtl819x_watchdog_wqcallback(struct net_device *dev)
5065{
5066 struct r8192_priv *priv = ieee80211_priv(dev);
5067#endif
5068 struct ieee80211_device* ieee = priv->ieee80211;
5069 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005070 static u8 check_reset_cnt=0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005071 bool bBusyTraffic = false;
5072
5073 if(!priv->up)
5074 return;
5075 hal_dm_watchdog(dev);
5076
5077 {//to get busy traffic condition
5078 if(ieee->state == IEEE80211_LINKED)
5079 {
5080 if( ieee->LinkDetectInfo.NumRxOkInPeriod> 666 ||
5081 ieee->LinkDetectInfo.NumTxOkInPeriod> 666 ) {
5082 bBusyTraffic = true;
5083 }
5084 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
5085 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
5086 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
5087 }
5088 }
5089 //added by amy for AP roaming
5090 {
5091 if(priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA)
5092 {
5093 u32 TotalRxBcnNum = 0;
5094 u32 TotalRxDataNum = 0;
5095
5096 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
5097 if((TotalRxBcnNum+TotalRxDataNum) == 0)
5098 {
5099 #ifdef TODO
5100 if(rfState == eRfOff)
5101 RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__);
5102 #endif
5103 printk("===>%s(): AP is power off,connect another one\n",__FUNCTION__);
5104 // Dot11d_Reset(dev);
5105 priv->ieee80211->state = IEEE80211_ASSOCIATING;
5106 notify_wx_assoc_event(priv->ieee80211);
5107 RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
5108 priv->ieee80211->link_change(dev);
5109#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
5110 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
5111#else
5112 schedule_task(&priv->ieee80211->associate_procedure_wq);
5113#endif
5114
5115 }
5116 }
5117 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod=0;
5118 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod=0;
5119 }
5120// CAM_read_entry(dev,4);
5121 //check if reset the driver
5122 if(check_reset_cnt++ >= 3)
5123 {
5124 ResetType = rtl819x_ifcheck_resetornot(dev);
5125 check_reset_cnt = 3;
5126 //DbgPrint("Start to check silent reset\n");
5127 }
5128 // RT_TRACE(COMP_RESET,"%s():priv->force_reset is %d,priv->ResetProgress is %d, priv->bForcedSilentReset is %d,priv->bDisableNormalResetCheck is %d,ResetType is %d\n",__FUNCTION__,priv->force_reset,priv->ResetProgress,priv->bForcedSilentReset,priv->bDisableNormalResetCheck,ResetType);
5129#if 1
5130 if( (priv->force_reset) || (priv->ResetProgress==RESET_TYPE_NORESET &&
5131 (priv->bForcedSilentReset ||
5132 (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT)))) // This is control by OID set in Pomelo
5133 {
5134 RT_TRACE(COMP_RESET,"%s():priv->force_reset is %d,priv->ResetProgress is %d, priv->bForcedSilentReset is %d,priv->bDisableNormalResetCheck is %d,ResetType is %d\n",__FUNCTION__,priv->force_reset,priv->ResetProgress,priv->bForcedSilentReset,priv->bDisableNormalResetCheck,ResetType);
5135 rtl819x_ifsilentreset(dev);
5136 }
5137#endif
5138 priv->force_reset = false;
5139 priv->bForcedSilentReset = false;
5140 priv->bResetInProgress = false;
5141 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
5142
5143}
5144
5145void watch_dog_timer_callback(unsigned long data)
5146{
5147 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
5148 //printk("===============>watch_dog timer\n");
5149#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
5150 queue_delayed_work(priv->priv_wq,&priv->watch_dog_wq, 0);
5151#else
5152#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
5153 schedule_task(&priv->watch_dog_wq);
5154#else
5155 queue_work(priv->priv_wq,&priv->watch_dog_wq);
5156#endif
5157#endif
5158 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
5159#if 0
5160 priv->watch_dog_timer.expires = jiffies + MSECS(IEEE80211_WATCH_DOG_TIME);
5161 add_timer(&priv->watch_dog_timer);
5162#endif
5163}
5164int _rtl8192_up(struct net_device *dev)
5165{
5166 struct r8192_priv *priv = ieee80211_priv(dev);
5167 //int i;
5168 int init_status = 0;
5169 priv->up=1;
5170 priv->ieee80211->ieee_up=1;
5171 RT_TRACE(COMP_INIT, "Bringing up iface");
5172 init_status = rtl8192_adapter_start(dev);
5173 if(!init_status)
5174 {
5175 RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n", __FUNCTION__);
5176 priv->up=priv->ieee80211->ieee_up = 0;
5177 return -EAGAIN;
5178 }
5179 RT_TRACE(COMP_INIT, "start adapter finished\n");
5180 rtl8192_rx_enable(dev);
5181// rtl8192_tx_enable(dev);
5182 if(priv->ieee80211->state != IEEE80211_LINKED)
5183 ieee80211_softmac_start_protocol(priv->ieee80211);
5184 ieee80211_reset_queue(priv->ieee80211);
5185 watch_dog_timer_callback((unsigned long) dev);
5186 if(!netif_queue_stopped(dev))
5187 netif_start_queue(dev);
5188 else
5189 netif_wake_queue(dev);
5190
5191 return 0;
5192}
5193
5194
5195int rtl8192_open(struct net_device *dev)
5196{
5197 struct r8192_priv *priv = ieee80211_priv(dev);
5198 int ret;
5199 down(&priv->wx_sem);
5200 ret = rtl8192_up(dev);
5201 up(&priv->wx_sem);
5202 return ret;
5203
5204}
5205
5206
5207int rtl8192_up(struct net_device *dev)
5208{
5209 struct r8192_priv *priv = ieee80211_priv(dev);
5210
5211 if (priv->up == 1) return -1;
5212
5213 return _rtl8192_up(dev);
5214}
5215
5216
5217int rtl8192_close(struct net_device *dev)
5218{
5219 struct r8192_priv *priv = ieee80211_priv(dev);
5220 int ret;
5221
5222 down(&priv->wx_sem);
5223
5224 ret = rtl8192_down(dev);
5225
5226 up(&priv->wx_sem);
5227
5228 return ret;
5229
5230}
5231
5232int rtl8192_down(struct net_device *dev)
5233{
5234 struct r8192_priv *priv = ieee80211_priv(dev);
5235 int i;
5236
5237 if (priv->up == 0) return -1;
5238
5239 priv->up=0;
5240 priv->ieee80211->ieee_up = 0;
5241 RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
5242/* FIXME */
5243 if (!netif_queue_stopped(dev))
5244 netif_stop_queue(dev);
5245
5246 rtl8192_rtx_disable(dev);
5247 //rtl8192_irq_disable(dev);
5248
5249 /* Tx related queue release */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005250 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
5251 skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
5252 }
5253 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
5254 skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
5255 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005256
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005257 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
5258 skb_queue_purge(&priv->ieee80211->skb_drv_aggQ [i]);
5259 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005260
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005261 //as cancel_delayed_work will del work->timer, so if work is not definedas struct delayed_work, it will corrupt
Jerry Chuang8fc85982009-11-03 07:17:11 -02005262// flush_scheduled_work();
5263 rtl8192_cancel_deferred_work(priv);
5264 deinit_hal_dm(dev);
5265 del_timer_sync(&priv->watch_dog_timer);
5266
5267
5268 ieee80211_softmac_stop_protocol(priv->ieee80211);
5269 memset(&priv->ieee80211->current_network, 0 , offsetof(struct ieee80211_network, list));
5270 RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
5271
5272 return 0;
5273}
5274
5275
5276void rtl8192_commit(struct net_device *dev)
5277{
5278 struct r8192_priv *priv = ieee80211_priv(dev);
5279 int reset_status = 0;
5280 //u8 reset_times = 0;
5281 if (priv->up == 0) return ;
5282 priv->up = 0;
5283
5284 rtl8192_cancel_deferred_work(priv);
5285 del_timer_sync(&priv->watch_dog_timer);
5286 //cancel_delayed_work(&priv->SwChnlWorkItem);
5287
5288 ieee80211_softmac_stop_protocol(priv->ieee80211);
5289
5290 //rtl8192_irq_disable(dev);
5291 rtl8192_rtx_disable(dev);
5292 reset_status = _rtl8192_up(dev);
5293
5294}
5295
5296/*
5297void rtl8192_restart(struct net_device *dev)
5298{
5299 struct r8192_priv *priv = ieee80211_priv(dev);
5300*/
5301#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
5302void rtl8192_restart(struct work_struct *work)
5303{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005304 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
5305 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005306#else
5307void rtl8192_restart(struct net_device *dev)
5308{
5309
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005310 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005311#endif
5312
5313 down(&priv->wx_sem);
5314
5315 rtl8192_commit(dev);
5316
5317 up(&priv->wx_sem);
5318}
5319
5320static void r8192_set_multicast(struct net_device *dev)
5321{
5322 struct r8192_priv *priv = ieee80211_priv(dev);
5323 short promisc;
5324
5325 //down(&priv->wx_sem);
5326
5327 /* FIXME FIXME */
5328
5329 promisc = (dev->flags & IFF_PROMISC) ? 1:0;
5330
5331 if (promisc != priv->promisc)
5332 // rtl8192_commit(dev);
5333
5334 priv->promisc = promisc;
5335
5336 //schedule_work(&priv->reset_wq);
5337 //up(&priv->wx_sem);
5338}
5339
5340
5341int r8192_set_mac_adr(struct net_device *dev, void *mac)
5342{
5343 struct r8192_priv *priv = ieee80211_priv(dev);
5344 struct sockaddr *addr = mac;
5345
5346 down(&priv->wx_sem);
5347
5348 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
5349
5350#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
5351 schedule_work(&priv->reset_wq);
5352#else
5353 schedule_task(&priv->reset_wq);
5354#endif
5355 up(&priv->wx_sem);
5356
5357 return 0;
5358}
5359
5360/* based on ipw2200 driver */
5361int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
5362{
5363 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5364 struct iwreq *wrq = (struct iwreq *)rq;
5365 int ret=-1;
5366 struct ieee80211_device *ieee = priv->ieee80211;
5367 u32 key[4];
5368 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
5369 struct iw_point *p = &wrq->u.data;
5370 struct ieee_param *ipw = NULL;//(struct ieee_param *)wrq->u.data.pointer;
5371
5372 down(&priv->wx_sem);
5373
5374
5375 if (p->length < sizeof(struct ieee_param) || !p->pointer){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005376 ret = -EINVAL;
5377 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005378 }
5379
5380 ipw = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL);
5381 if (ipw == NULL){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005382 ret = -ENOMEM;
5383 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005384 }
5385 if (copy_from_user(ipw, p->pointer, p->length)) {
5386 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005387 ret = -EFAULT;
5388 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005389 }
5390
5391 switch (cmd) {
5392 case RTL_IOCTL_WPA_SUPPLICANT:
5393 //parse here for HW security
5394 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION)
5395 {
5396 if (ipw->u.crypt.set_tx)
5397 {
5398 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
5399 ieee->pairwise_key_type = KEY_TYPE_CCMP;
5400 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
5401 ieee->pairwise_key_type = KEY_TYPE_TKIP;
5402 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
5403 {
5404 if (ipw->u.crypt.key_len == 13)
5405 ieee->pairwise_key_type = KEY_TYPE_WEP104;
5406 else if (ipw->u.crypt.key_len == 5)
5407 ieee->pairwise_key_type = KEY_TYPE_WEP40;
5408 }
5409 else
5410 ieee->pairwise_key_type = KEY_TYPE_NA;
5411
5412 if (ieee->pairwise_key_type)
5413 {
5414 memcpy((u8*)key, ipw->u.crypt.key, 16);
5415 EnableHWSecurityConfig8192(dev);
5416 //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!
5417 //added by WB.
5418 setKey(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
5419 if (ieee->auth_mode != 2)
5420 setKey(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
5421 }
5422 }
5423 else //if (ipw->u.crypt.idx) //group key use idx > 0
5424 {
5425 memcpy((u8*)key, ipw->u.crypt.key, 16);
5426 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
5427 ieee->group_key_type= KEY_TYPE_CCMP;
5428 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
5429 ieee->group_key_type = KEY_TYPE_TKIP;
5430 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
5431 {
5432 if (ipw->u.crypt.key_len == 13)
5433 ieee->group_key_type = KEY_TYPE_WEP104;
5434 else if (ipw->u.crypt.key_len == 5)
5435 ieee->group_key_type = KEY_TYPE_WEP40;
5436 }
5437 else
5438 ieee->group_key_type = KEY_TYPE_NA;
5439
5440 if (ieee->group_key_type)
5441 {
5442 setKey( dev,
5443 ipw->u.crypt.idx,
5444 ipw->u.crypt.idx, //KeyIndex
5445 ieee->group_key_type, //KeyType
5446 broadcast_addr, //MacAddr
5447 0, //DefaultKey
5448 key); //KeyContent
5449 }
5450 }
5451 }
5452#ifdef JOHN_HWSEC_DEBUG
5453 //john's test 0711
5454 printk("@@ wrq->u pointer = ");
5455 for(i=0;i<wrq->u.data.length;i++){
5456 if(i%10==0) printk("\n");
5457 printk( "%8x|", ((u32*)wrq->u.data.pointer)[i] );
5458 }
5459 printk("\n");
5460#endif /*JOHN_HWSEC_DEBUG*/
5461 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
5462 break;
5463
5464 default:
5465 ret = -EOPNOTSUPP;
5466 break;
5467 }
5468 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005469 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005470out:
5471 up(&priv->wx_sem);
5472 return ret;
5473}
5474
5475u8 HwRateToMRate90(bool bIsHT, u8 rate)
5476{
5477 u8 ret_rate = 0xff;
5478
5479 if(!bIsHT) {
5480 switch(rate) {
5481 case DESC90_RATE1M: ret_rate = MGN_1M; break;
5482 case DESC90_RATE2M: ret_rate = MGN_2M; break;
5483 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
5484 case DESC90_RATE11M: ret_rate = MGN_11M; break;
5485 case DESC90_RATE6M: ret_rate = MGN_6M; break;
5486 case DESC90_RATE9M: ret_rate = MGN_9M; break;
5487 case DESC90_RATE12M: ret_rate = MGN_12M; break;
5488 case DESC90_RATE18M: ret_rate = MGN_18M; break;
5489 case DESC90_RATE24M: ret_rate = MGN_24M; break;
5490 case DESC90_RATE36M: ret_rate = MGN_36M; break;
5491 case DESC90_RATE48M: ret_rate = MGN_48M; break;
5492 case DESC90_RATE54M: ret_rate = MGN_54M; break;
5493
5494 default:
5495 ret_rate = 0xff;
5496 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
5497 break;
5498 }
5499
5500 } else {
5501 switch(rate) {
5502 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
5503 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
5504 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
5505 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
5506 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
5507 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
5508 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
5509 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
5510 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
5511 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
5512 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
5513 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
5514 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
5515 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
5516 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
5517 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
5518 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
5519
5520 default:
5521 ret_rate = 0xff;
5522 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n",rate, bIsHT);
5523 break;
5524 }
5525 }
5526
5527 return ret_rate;
5528}
5529
5530/**
5531 * Function: UpdateRxPktTimeStamp
5532 * Overview: Recored down the TSF time stamp when receiving a packet
5533 *
5534 * Input:
5535 * PADAPTER Adapter
5536 * PRT_RFD pRfd,
5537 *
5538 * Output:
5539 * PRT_RFD pRfd
5540 * (pRfd->Status.TimeStampHigh is updated)
5541 * (pRfd->Status.TimeStampLow is updated)
5542 * Return:
5543 * None
5544 */
5545void UpdateRxPktTimeStamp8190 (struct net_device *dev, struct ieee80211_rx_stats *stats)
5546{
5547 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5548
5549 if(stats->bIsAMPDU && !stats->bFirstMPDU) {
5550 stats->mac_time[0] = priv->LastRxDescTSFLow;
5551 stats->mac_time[1] = priv->LastRxDescTSFHigh;
5552 } else {
5553 priv->LastRxDescTSFLow = stats->mac_time[0];
5554 priv->LastRxDescTSFHigh = stats->mac_time[1];
5555 }
5556}
5557
5558//by amy 080606
5559
5560long rtl819x_translate_todbm(u8 signal_strength_index )// 0-100 index.
5561{
5562 long signal_power; // in dBm.
5563
5564 // Translate to dBm (x=0.5y-95).
5565 signal_power = (long)((signal_strength_index + 1) >> 1);
5566 signal_power -= 95;
5567
5568 return signal_power;
5569}
5570
5571
5572/* 2008/01/22 MH We can not delcare RSSI/EVM total value of sliding window to
5573 be a local static. Otherwise, it may increase when we return from S3/S4. The
5574 value will be kept in memory or disk. We must delcare the value in adapter
5575 and it will be reinitialized when return from S3/S4. */
5576void rtl8192_process_phyinfo(struct r8192_priv * priv,u8* buffer, struct ieee80211_rx_stats * pprevious_stats, struct ieee80211_rx_stats * pcurrent_stats)
5577{
5578 bool bcheck = false;
5579 u8 rfpath;
5580 u32 nspatial_stream, tmp_val;
5581 //u8 i;
5582 static u32 slide_rssi_index=0, slide_rssi_statistics=0;
5583 static u32 slide_evm_index=0, slide_evm_statistics=0;
5584 static u32 last_rssi=0, last_evm=0;
5585
5586 static u32 slide_beacon_adc_pwdb_index=0, slide_beacon_adc_pwdb_statistics=0;
5587 static u32 last_beacon_adc_pwdb=0;
5588
5589 struct ieee80211_hdr_3addr *hdr;
5590 u16 sc ;
5591 unsigned int frag,seq;
5592 hdr = (struct ieee80211_hdr_3addr *)buffer;
5593 sc = le16_to_cpu(hdr->seq_ctl);
5594 frag = WLAN_GET_SEQ_FRAG(sc);
5595 seq = WLAN_GET_SEQ_SEQ(sc);
5596 //cosa add 04292008 to record the sequence number
5597 pcurrent_stats->Seq_Num = seq;
5598 //
5599 // Check whether we should take the previous packet into accounting
5600 //
5601 if(!pprevious_stats->bIsAMPDU)
5602 {
5603 // if previous packet is not aggregated packet
5604 bcheck = true;
5605 }else
5606 {
5607 #if 0
5608 // if previous packet is aggregated packet, and current packet
5609 // (1) is not AMPDU
5610 // (2) is the first packet of one AMPDU
5611 // that means the previous packet is the last one aggregated packet
5612 if( !pcurrent_stats->bIsAMPDU || pcurrent_stats->bFirstMPDU)
5613 bcheck = true;
5614 #endif
5615 }
5616
5617
5618 if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX)
5619 {
5620 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
5621 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
5622 priv->stats.slide_rssi_total -= last_rssi;
5623 }
5624 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
5625
5626 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
5627 if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
5628 slide_rssi_index = 0;
5629
5630 // <1> Showed on UI for user, in dbm
5631 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
5632 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
5633 pcurrent_stats->rssi = priv->stats.signal_strength;
5634 //
5635 // If the previous packet does not match the criteria, neglect it
5636 //
5637 if(!pprevious_stats->bPacketMatchBSSID)
5638 {
5639 if(!pprevious_stats->bToSelfBA)
5640 return;
5641 }
5642
5643 if(!bcheck)
5644 return;
5645
5646
5647 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
5648
5649 //
5650 // Check RSSI
5651 //
5652 priv->stats.num_process_phyinfo++;
5653
5654 /* record the general signal strength to the sliding window. */
5655
5656
5657 // <2> Showed on UI for engineering
5658 // hardware does not provide rssi information for each rf path in CCK
5659 if(!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA))
5660 {
5661 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++)
5662 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005663 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
5664 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005665
5666 //Fixed by Jacken 2008-03-20
5667 if(priv->stats.rx_rssi_percentage[rfpath] == 0)
5668 {
5669 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
5670 //DbgPrint("MIMO RSSI initialize \n");
5671 }
5672 if(pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath])
5673 {
5674 priv->stats.rx_rssi_percentage[rfpath] =
5675 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
5676 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
5677 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
5678 }
5679 else
5680 {
5681 priv->stats.rx_rssi_percentage[rfpath] =
5682 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
5683 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
5684 }
5685 RT_TRACE(COMP_DBG,"priv->stats.rx_rssi_percentage[rfPath] = %d \n" ,priv->stats.rx_rssi_percentage[rfpath] );
5686 }
5687 }
5688
5689
5690 //
5691 // Check PWDB.
5692 //
5693 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
5694 pprevious_stats->bIsCCK? "CCK": "OFDM",
5695 pprevious_stats->RxPWDBAll);
5696
5697 if(pprevious_stats->bPacketBeacon)
5698 {
5699/* record the beacon pwdb to the sliding window. */
5700 if(slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX)
5701 {
5702 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
5703 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
5704 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
5705 //DbgPrint("slide_beacon_adc_pwdb_index = %d, last_beacon_adc_pwdb = %d, Adapter->RxStats.Slide_Beacon_Total = %d\n",
5706 // slide_beacon_adc_pwdb_index, last_beacon_adc_pwdb, Adapter->RxStats.Slide_Beacon_Total);
5707 }
5708 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
5709 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
5710 //DbgPrint("slide_beacon_adc_pwdb_index = %d, pPreviousRfd->Status.RxPWDBAll = %d\n", slide_beacon_adc_pwdb_index, pPreviousRfd->Status.RxPWDBAll);
5711 slide_beacon_adc_pwdb_index++;
5712 if(slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
5713 slide_beacon_adc_pwdb_index = 0;
5714 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
5715 if(pprevious_stats->RxPWDBAll >= 3)
5716 pprevious_stats->RxPWDBAll -= 3;
5717 }
5718
5719 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
5720 pprevious_stats->bIsCCK? "CCK": "OFDM",
5721 pprevious_stats->RxPWDBAll);
5722
5723
5724 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
5725 {
5726 if(priv->undecorated_smoothed_pwdb < 0) // initialize
5727 {
5728 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
5729 //DbgPrint("First pwdb initialize \n");
5730 }
5731#if 1
5732 if(pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb)
5733 {
5734 priv->undecorated_smoothed_pwdb =
5735 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
5736 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
5737 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
5738 }
5739 else
5740 {
5741 priv->undecorated_smoothed_pwdb =
5742 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
5743 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
5744 }
5745#else
5746 //Fixed by Jacken 2008-03-20
5747 if(pPreviousRfd->Status.RxPWDBAll > (u32)pHalData->UndecoratedSmoothedPWDB)
5748 {
5749 pHalData->UndecoratedSmoothedPWDB =
5750 ( ((pHalData->UndecoratedSmoothedPWDB)* 5) + (pPreviousRfd->Status.RxPWDBAll)) / 6;
5751 pHalData->UndecoratedSmoothedPWDB = pHalData->UndecoratedSmoothedPWDB + 1;
5752 }
5753 else
5754 {
5755 pHalData->UndecoratedSmoothedPWDB =
5756 ( ((pHalData->UndecoratedSmoothedPWDB)* 5) + (pPreviousRfd->Status.RxPWDBAll)) / 6;
5757 }
5758#endif
5759
5760 }
5761
5762 //
5763 // Check EVM
5764 //
5765 /* record the general EVM to the sliding window. */
5766 if(pprevious_stats->SignalQuality == 0)
5767 {
5768 }
5769 else
5770 {
5771 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA){
5772 if(slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX){
5773 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
5774 last_evm = priv->stats.slide_evm[slide_evm_index];
5775 priv->stats.slide_evm_total -= last_evm;
5776 }
5777
5778 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
5779
5780 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
5781 if(slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
5782 slide_evm_index = 0;
5783
5784 // <1> Showed on UI for user, in percentage.
5785 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
5786 priv->stats.signal_quality = tmp_val;
5787 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
5788 priv->stats.last_signal_strength_inpercent = tmp_val;
5789 }
5790
5791 // <2> Showed on UI for engineering
5792 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
5793 {
5794 for(nspatial_stream = 0; nspatial_stream<2 ; nspatial_stream++) // 2 spatial stream
5795 {
5796 if(pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1)
5797 {
5798 if(priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
5799 {
5800 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
5801 }
5802 priv->stats.rx_evm_percentage[nspatial_stream] =
5803 ( (priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
5804 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
5805 }
5806 }
5807 }
5808 }
5809
5810
5811}
5812
5813/*-----------------------------------------------------------------------------
5814 * Function: rtl819x_query_rxpwrpercentage()
5815 *
5816 * Overview:
5817 *
5818 * Input: char antpower
5819 *
5820 * Output: NONE
5821 *
5822 * Return: 0-100 percentage
5823 *
5824 * Revised History:
5825 * When Who Remark
5826 * 05/26/2008 amy Create Version 0 porting from windows code.
5827 *
5828 *---------------------------------------------------------------------------*/
5829static u8 rtl819x_query_rxpwrpercentage(
5830 char antpower
5831 )
5832{
5833 if ((antpower <= -100) || (antpower >= 20))
5834 {
5835 return 0;
5836 }
5837 else if (antpower >= 0)
5838 {
5839 return 100;
5840 }
5841 else
5842 {
5843 return (100+antpower);
5844 }
5845
5846} /* QueryRxPwrPercentage */
5847
5848static u8
5849rtl819x_evm_dbtopercentage(
5850 char value
5851 )
5852{
5853 char ret_val;
5854
5855 ret_val = value;
5856
5857 if(ret_val >= 0)
5858 ret_val = 0;
5859 if(ret_val <= -33)
5860 ret_val = -33;
5861 ret_val = 0 - ret_val;
5862 ret_val*=3;
5863 if(ret_val == 99)
5864 ret_val = 100;
5865 return(ret_val);
5866}
5867//
5868// Description:
5869// We want good-looking for signal strength/quality
5870// 2007/7/19 01:09, by cosa.
5871//
5872long
5873rtl819x_signal_scale_mapping(
5874 long currsig
5875 )
5876{
5877 long retsig;
5878
5879 // Step 1. Scale mapping.
5880 if(currsig >= 61 && currsig <= 100)
5881 {
5882 retsig = 90 + ((currsig - 60) / 4);
5883 }
5884 else if(currsig >= 41 && currsig <= 60)
5885 {
5886 retsig = 78 + ((currsig - 40) / 2);
5887 }
5888 else if(currsig >= 31 && currsig <= 40)
5889 {
5890 retsig = 66 + (currsig - 30);
5891 }
5892 else if(currsig >= 21 && currsig <= 30)
5893 {
5894 retsig = 54 + (currsig - 20);
5895 }
5896 else if(currsig >= 5 && currsig <= 20)
5897 {
5898 retsig = 42 + (((currsig - 5) * 2) / 3);
5899 }
5900 else if(currsig == 4)
5901 {
5902 retsig = 36;
5903 }
5904 else if(currsig == 3)
5905 {
5906 retsig = 27;
5907 }
5908 else if(currsig == 2)
5909 {
5910 retsig = 18;
5911 }
5912 else if(currsig == 1)
5913 {
5914 retsig = 9;
5915 }
5916 else
5917 {
5918 retsig = currsig;
5919 }
5920
5921 return retsig;
5922}
5923
5924static void rtl8192_query_rxphystatus(
5925 struct r8192_priv * priv,
5926 struct ieee80211_rx_stats * pstats,
5927 rx_drvinfo_819x_usb * pdrvinfo,
5928 struct ieee80211_rx_stats * precord_stats,
5929 bool bpacket_match_bssid,
5930 bool bpacket_toself,
5931 bool bPacketBeacon,
5932 bool bToSelfBA
5933 )
5934{
5935 //PRT_RFD_STATUS pRtRfdStatus = &(pRfd->Status);
5936 phy_sts_ofdm_819xusb_t* pofdm_buf;
5937 phy_sts_cck_819xusb_t * pcck_buf;
5938 phy_ofdm_rx_status_rxsc_sgien_exintfflag* prxsc;
5939 u8 *prxpkt;
5940 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
5941 char rx_pwr[4], rx_pwr_all=0;
5942 //long rx_avg_pwr = 0;
5943 char rx_snrX, rx_evmX;
5944 u8 evm, pwdb_all;
5945 u32 RSSI, total_rssi=0;//, total_evm=0;
5946// long signal_strength_index = 0;
5947 u8 is_cck_rate=0;
5948 u8 rf_rx_num = 0;
5949
5950
5951 priv->stats.numqry_phystatus++;
5952
5953 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
5954
5955 // Record it for next packet processing
5956 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
5957 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
5958 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
5959 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;//RX_HAL_IS_CCK_RATE(pDrvInfo);
5960 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
5961 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
5962
5963 prxpkt = (u8*)pdrvinfo;
5964
5965 /* Move pointer to the 16th bytes. Phy status start address. */
5966 prxpkt += sizeof(rx_drvinfo_819x_usb);
5967
5968 /* Initial the cck and ofdm buffer pointer */
5969 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
5970 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
5971
5972 pstats->RxMIMOSignalQuality[0] = -1;
5973 pstats->RxMIMOSignalQuality[1] = -1;
5974 precord_stats->RxMIMOSignalQuality[0] = -1;
5975 precord_stats->RxMIMOSignalQuality[1] = -1;
5976
5977 if(is_cck_rate)
5978 {
5979 //
5980 // (1)Hardware does not provide RSSI for CCK
5981 //
5982
5983 //
5984 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
5985 //
5986 u8 report;//, cck_agc_rpt;
5987
5988 priv->stats.numqry_phystatusCCK++;
5989
5990 if(!priv->bCckHighPower)
5991 {
5992 report = pcck_buf->cck_agc_rpt & 0xc0;
5993 report = report>>6;
5994 switch(report)
5995 {
5996 //Fixed by Jacken from Bryant 2008-03-20
5997 //Original value is -38 , -26 , -14 , -2
5998 //Fixed value is -35 , -23 , -11 , 6
5999 case 0x3:
6000 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
6001 break;
6002 case 0x2:
6003 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
6004 break;
6005 case 0x1:
6006 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
6007 break;
6008 case 0x0:
6009 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
6010 break;
6011 }
6012 }
6013 else
6014 {
6015 report = pcck_buf->cck_agc_rpt & 0x60;
6016 report = report>>5;
6017 switch(report)
6018 {
6019 case 0x3:
6020 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
6021 break;
6022 case 0x2:
6023 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
6024 break;
6025 case 0x1:
6026 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
6027 break;
6028 case 0x0:
6029 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
6030 break;
6031 }
6032 }
6033
6034 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
6035 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
6036 pstats->RecvSignalPower = pwdb_all;
6037
6038 //
6039 // (3) Get Signal Quality (EVM)
6040 //
6041 //if(bpacket_match_bssid)
6042 {
6043 u8 sq;
6044
6045 if(pstats->RxPWDBAll > 40)
6046 {
6047 sq = 100;
6048 }else
6049 {
6050 sq = pcck_buf->sq_rpt;
6051
6052 if(pcck_buf->sq_rpt > 64)
6053 sq = 0;
6054 else if (pcck_buf->sq_rpt < 20)
6055 sq = 100;
6056 else
6057 sq = ((64-sq) * 100) / 44;
6058 }
6059 pstats->SignalQuality = precord_stats->SignalQuality = sq;
6060 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
6061 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
6062 }
6063 }
6064 else
6065 {
6066 priv->stats.numqry_phystatusHT++;
6067 //
6068 // (1)Get RSSI for HT rate
6069 //
6070 for(i=RF90_PATH_A; i<priv->NumTotalRFPath; i++)
6071 {
6072 // 2008/01/30 MH we will judge RF RX path now.
6073 if (priv->brfpath_rxenable[i])
6074 rf_rx_num++;
6075 else
6076 continue;
6077
6078 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
6079 continue;
6080
6081 //Fixed by Jacken from Bryant 2008-03-20
6082 //Original value is 106
6083 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
6084
6085 //Get Rx snr value in DB
6086 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
6087 rx_snrX = (char)(tmp_rxsnr);
6088 //rx_snrX >>= 1;;
6089 rx_snrX /= 2;
6090 priv->stats.rxSNRdB[i] = (long)rx_snrX;
6091
6092 /* Translate DBM to percentage. */
6093 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
6094 total_rssi += RSSI;
6095
6096 /* Record Signal Strength for next packet */
6097 //if(bpacket_match_bssid)
6098 {
6099 pstats->RxMIMOSignalStrength[i] =(u8) RSSI;
6100 precord_stats->RxMIMOSignalStrength[i] =(u8) RSSI;
6101 }
6102 }
6103
6104
6105 //
6106 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
6107 //
6108 //Fixed by Jacken from Bryant 2008-03-20
6109 //Original value is 106
6110 rx_pwr_all = (((pofdm_buf->pwdb_all ) >> 1 )& 0x7f) -106;
6111 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
6112
6113 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
6114 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
6115
6116 //
6117 // (3)EVM of HT rate
6118 //
6119 if(pdrvinfo->RxHT && pdrvinfo->RxRate>=DESC90_RATEMCS8 &&
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006120 pdrvinfo->RxRate<=DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02006121 max_spatial_stream = 2; //both spatial stream make sense
6122 else
6123 max_spatial_stream = 1; //only spatial stream 1 makes sense
6124
6125 for(i=0; i<max_spatial_stream; i++)
6126 {
6127 tmp_rxevm = pofdm_buf->rxevm_X[i];
6128 rx_evmX = (char)(tmp_rxevm);
6129
6130 // Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment
6131 // fill most significant bit to "zero" when doing shifting operation which may change a negative
6132 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
6133 rx_evmX /= 2; //dbm
6134
6135 evm = rtl819x_evm_dbtopercentage(rx_evmX);
6136#if 0
6137 EVM = SignalScaleMapping(EVM);//make it good looking, from 0~100
6138#endif
6139 //if(bpacket_match_bssid)
6140 {
6141 if(i==0) // Fill value in RFD, Get the first spatial stream only
6142 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
6143 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
6144 }
6145 }
6146
6147
6148 /* record rx statistics for debug */
6149 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
6150 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
6151 if(pdrvinfo->BW) //40M channel
6152 priv->stats.received_bwtype[1+prxsc->rxsc]++;
6153 else //20M channel
6154 priv->stats.received_bwtype[0]++;
6155 }
6156
6157 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
6158 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
6159 if(is_cck_rate)
6160 {
6161 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));//PWDB_ALL;
6162
6163 }
6164 else
6165 {
6166 //pRfd->Status.SignalStrength = pRecordRfd->Status.SignalStrength = (u8)(SignalScaleMapping(total_rssi/=RF90_PATH_MAX));//(u8)(total_rssi/=RF90_PATH_MAX);
6167 // We can judge RX path number now.
6168 if (rf_rx_num != 0)
6169 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi/=rf_rx_num)));
6170 }
6171} /* QueryRxPhyStatus8190Pci */
6172
6173void
6174rtl8192_record_rxdesc_forlateruse(
6175 struct ieee80211_rx_stats * psrc_stats,
6176 struct ieee80211_rx_stats * ptarget_stats
6177)
6178{
6179 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
6180 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
6181 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
6182}
6183
6184
6185void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
6186 struct ieee80211_rx_stats * pstats,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006187 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02006188{
6189 // TODO: We must only check packet for current MAC address. Not finish
6190 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
6191 struct net_device *dev=info->dev;
6192 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
6193 bool bpacket_match_bssid, bpacket_toself;
6194 bool bPacketBeacon=FALSE, bToSelfBA=FALSE;
6195 static struct ieee80211_rx_stats previous_stats;
6196 struct ieee80211_hdr_3addr *hdr;//by amy
6197 u16 fc,type;
6198
6199 // Get Signal Quality for only RX data queue (but not command queue)
6200
6201 u8* tmp_buf;
6202 //u16 tmp_buf_len = 0;
6203 u8 *praddr;
6204
6205 /* Get MAC frame start address. */
6206 tmp_buf = (u8*)skb->data;// + get_rxpacket_shiftbytes_819xusb(pstats);
6207
6208 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
6209 fc = le16_to_cpu(hdr->frame_ctl);
6210 type = WLAN_FC_GET_TYPE(fc);
6211 praddr = hdr->addr1;
6212
6213 /* Check if the received packet is acceptabe. */
6214 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006215 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
6216 && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02006217 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
6218
6219#if 1//cosa
6220 if(WLAN_FC_GET_FRAMETYPE(fc)== IEEE80211_STYPE_BEACON)
6221 {
6222 bPacketBeacon = true;
6223 //DbgPrint("Beacon 2, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
6224 }
6225 if(WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK)
6226 {
6227 if((eqMacAddr(praddr,dev->dev_addr)))
6228 bToSelfBA = true;
6229 //DbgPrint("BlockAck, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
6230 }
6231
6232#endif
6233
6234
6235 if(bpacket_match_bssid)
6236 {
6237 priv->stats.numpacket_matchbssid++;
6238 }
6239 if(bpacket_toself){
6240 priv->stats.numpacket_toself++;
6241 }
6242 //
6243 // Process PHY information for previous packet (RSSI/PWDB/EVM)
6244 //
6245 // Because phy information is contained in the last packet of AMPDU only, so driver
6246 // should process phy information of previous packet
6247 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
6248 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid,bpacket_toself,bPacketBeacon,bToSelfBA);
6249 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
6250
6251}
6252
6253/**
6254* Function: UpdateReceivedRateHistogramStatistics
6255* Overview: Recored down the received data rate
6256*
6257* Input:
6258* struct net_device *dev
6259* struct ieee80211_rx_stats *stats
6260*
6261* Output:
6262*
6263* (priv->stats.ReceivedRateHistogram[] is updated)
6264* Return:
6265* None
6266*/
6267void
6268UpdateReceivedRateHistogramStatistics8190(
6269 struct net_device *dev,
6270 struct ieee80211_rx_stats *stats
6271 )
6272{
6273 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006274 u32 rcvType=1; //0: Total, 1:OK, 2:CRC, 3:ICV
6275 u32 rateIndex;
6276 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02006277
6278
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006279 if(stats->bCRC)
6280 rcvType = 2;
6281 else if(stats->bICV)
6282 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02006283
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006284 if(stats->bShortPreamble)
6285 preamble_guardinterval = 1;// short
6286 else
6287 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02006288
6289 switch(stats->rate)
6290 {
6291 //
6292 // CCK rate
6293 //
6294 case MGN_1M: rateIndex = 0; break;
6295 case MGN_2M: rateIndex = 1; break;
6296 case MGN_5_5M: rateIndex = 2; break;
6297 case MGN_11M: rateIndex = 3; break;
6298 //
6299 // Legacy OFDM rate
6300 //
6301 case MGN_6M: rateIndex = 4; break;
6302 case MGN_9M: rateIndex = 5; break;
6303 case MGN_12M: rateIndex = 6; break;
6304 case MGN_18M: rateIndex = 7; break;
6305 case MGN_24M: rateIndex = 8; break;
6306 case MGN_36M: rateIndex = 9; break;
6307 case MGN_48M: rateIndex = 10; break;
6308 case MGN_54M: rateIndex = 11; break;
6309 //
6310 // 11n High throughput rate
6311 //
6312 case MGN_MCS0: rateIndex = 12; break;
6313 case MGN_MCS1: rateIndex = 13; break;
6314 case MGN_MCS2: rateIndex = 14; break;
6315 case MGN_MCS3: rateIndex = 15; break;
6316 case MGN_MCS4: rateIndex = 16; break;
6317 case MGN_MCS5: rateIndex = 17; break;
6318 case MGN_MCS6: rateIndex = 18; break;
6319 case MGN_MCS7: rateIndex = 19; break;
6320 case MGN_MCS8: rateIndex = 20; break;
6321 case MGN_MCS9: rateIndex = 21; break;
6322 case MGN_MCS10: rateIndex = 22; break;
6323 case MGN_MCS11: rateIndex = 23; break;
6324 case MGN_MCS12: rateIndex = 24; break;
6325 case MGN_MCS13: rateIndex = 25; break;
6326 case MGN_MCS14: rateIndex = 26; break;
6327 case MGN_MCS15: rateIndex = 27; break;
6328 default: rateIndex = 28; break;
6329 }
6330 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
6331 priv->stats.received_rate_histogram[0][rateIndex]++; //total
6332 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
6333}
6334
6335
6336void query_rxdesc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats, bool bIsRxAggrSubframe)
6337{
6338 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
6339 struct net_device *dev=info->dev;
6340 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
6341 //rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
6342 rx_drvinfo_819x_usb *driver_info = NULL;
6343
6344 //
6345 //Get Rx Descriptor Information
6346 //
6347#ifdef USB_RX_AGGREGATION_SUPPORT
6348 if (bIsRxAggrSubframe)
6349 {
6350 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
6351 stats->Length = desc->Length ;
6352 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
6353 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
6354 stats->bICV = desc->ICV;
6355 stats->bCRC = desc->CRC32;
6356 stats->bHwError = stats->bCRC|stats->bICV;
6357 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
6358 } else
6359#endif
6360 {
6361 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
6362
6363 stats->Length = desc->Length;
6364 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
6365 stats->RxBufShift = 0;//desc->Shift&0x03;
6366 stats->bICV = desc->ICV;
6367 stats->bCRC = desc->CRC32;
6368 stats->bHwError = stats->bCRC|stats->bICV;
6369 //RTL8190 set this bit to indicate that Hw does not decrypt packet
6370 stats->Decrypted = !desc->SWDec;
6371 }
6372
6373 if((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
6374 {
6375 stats->bHwError = false;
6376 }
6377 else
6378 {
6379 stats->bHwError = stats->bCRC|stats->bICV;
6380 }
6381
6382 if(stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
6383 stats->bHwError |= 1;
6384 //
6385 //Get Driver Info
6386 //
6387 // TODO: Need to verify it on FGPA platform
6388 //Driver info are written to the RxBuffer following rx desc
6389 if (stats->RxDrvInfoSize != 0) {
6390 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) + \
6391 stats->RxBufShift);
6392 /* unit: 0.5M */
6393 /* TODO */
6394 if(!stats->bHwError){
6395 u8 ret_rate;
6396 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
6397 if(ret_rate == 0xff)
6398 {
6399 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
6400 // Special Error Handling here, 2008.05.16, by Emily
6401
6402 stats->bHwError = 1;
6403 stats->rate = MGN_1M; //Set 1M rate by default
6404 }else
6405 {
6406 stats->rate = ret_rate;
6407 }
6408 }
6409 else
6410 stats->rate = 0x02;
6411
6412 stats->bShortPreamble = driver_info->SPLCP;
6413
6414
6415 UpdateReceivedRateHistogramStatistics8190(dev, stats);
6416
6417 stats->bIsAMPDU = (driver_info->PartAggr==1);
6418 stats->bFirstMPDU = (driver_info->PartAggr==1) && (driver_info->FirstAGGR==1);
6419#if 0
6420 // TODO: it is debug only. It should be disabled in released driver. 2007.1.12 by Joseph
6421 UpdateRxAMPDUHistogramStatistics8190(Adapter, pRfd);
6422#endif
6423 stats->TimeStampLow = driver_info->TSFL;
6424 // xiong mask it, 070514
6425 //pRfd->Status.TimeStampHigh = PlatformEFIORead4Byte(Adapter, TSFR+4);
6426 // stats->TimeStampHigh = read_nic_dword(dev, TSFR+4);
6427
6428 UpdateRxPktTimeStamp8190(dev, stats);
6429
6430 //
6431 // Rx A-MPDU
6432 //
6433 if(driver_info->FirstAGGR==1 || driver_info->PartAggr == 1)
6434 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
6435 driver_info->FirstAGGR, driver_info->PartAggr);
6436
6437 }
6438
6439 skb_pull(skb,sizeof(rx_desc_819x_usb));
6440 //
6441 // Get Total offset of MPDU Frame Body
6442 //
6443 if((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
6444 stats->bShift = 1;
6445 skb_pull(skb,stats->RxBufShift + stats->RxDrvInfoSize);
6446 }
6447
6448#ifdef USB_RX_AGGREGATION_SUPPORT
6449 /* for the rx aggregated sub frame, the redundant space truelly contained in the packet */
6450 if(bIsRxAggrSubframe) {
6451 skb_pull(skb, 8);
6452 }
6453#endif
6454 /* for debug 2008.5.29 */
6455#if 0
6456 {
6457 int i;
6458 printk("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
6459 for(i = 0; i < skb->len; i++) {
6460 if(i % 10 == 0) printk("\n");
6461 printk("%02x ", skb->data[i]);
6462 }
6463 printk("\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
6464 }
6465#endif
6466
6467 //added by vivi, for MP, 20080108
6468 stats->RxIs40MHzPacket = driver_info->BW;
6469 if(stats->RxDrvInfoSize != 0)
6470 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
6471
6472}
6473
6474u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
6475{
6476#ifdef USB_RX_AGGREGATION_SUPPORT
6477 if (bIsRxAggrSubframe)
6478 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
6479 + Status->RxBufShift + 8);
6480 else
6481#endif
6482 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
6483 + Status->RxBufShift);
6484}
6485
6486void rtl8192_rx_nomal(struct sk_buff* skb)
6487{
6488 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
6489 struct net_device *dev=info->dev;
6490 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
6491 struct ieee80211_rx_stats stats = {
6492 .signal = 0,
6493 .noise = -98,
6494 .rate = 0,
6495 // .mac_time = jiffies,
6496 .freq = IEEE80211_24GHZ_BAND,
6497 };
6498 u32 rx_pkt_len = 0;
6499 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
6500 bool unicast_packet = false;
6501#ifdef USB_RX_AGGREGATION_SUPPORT
6502 struct sk_buff *agg_skb = NULL;
6503 u32 TotalLength = 0;
6504 u32 TempDWord = 0;
6505 u32 PacketLength = 0;
6506 u32 PacketOccupiedLendth = 0;
6507 u8 TempByte = 0;
6508 u32 PacketShiftBytes = 0;
6509 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
6510 u8 PaddingBytes = 0;
6511 //add just for testing
6512 u8 testing;
6513
6514#endif
6515
6516 /* 20 is for ps-poll */
6517 if((skb->len >=(20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
6518#ifdef USB_RX_AGGREGATION_SUPPORT
6519 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
6520#endif
6521 /* first packet should not contain Rx aggregation header */
6522 query_rxdesc_status(skb, &stats, false);
6523 /* TODO */
6524 /* hardware related info */
6525#ifdef USB_RX_AGGREGATION_SUPPORT
6526 if (TempByte & BIT0) {
6527 agg_skb = skb;
6528 //TotalLength = agg_skb->len - 4; /*sCrcLng*/
6529 TotalLength = stats.Length - 4; /*sCrcLng*/
6530 //RT_TRACE(COMP_RECV, "%s:first aggregated packet!Length=%d\n",__FUNCTION__,TotalLength);
6531 /* though the head pointer has passed this position */
6532 TempDWord = *(u32 *)(agg_skb->data - 4);
6533 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
6534 skb = dev_alloc_skb(PacketLength);
6535 memcpy(skb_put(skb,PacketLength),agg_skb->data,PacketLength);
6536 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
6537 }
6538#endif
6539 /* Process the MPDU recevied */
6540 skb_trim(skb, skb->len - 4/*sCrcLng*/);
6541
6542 rx_pkt_len = skb->len;
6543 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
6544 unicast_packet = false;
6545 if(is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
6546 //TODO
6547 }else if(is_multicast_ether_addr(ieee80211_hdr->addr1)){
6548 //TODO
6549 }else {
6550 /* unicast packet */
6551 unicast_packet = true;
6552 }
6553
6554 if(!ieee80211_rx(priv->ieee80211,skb, &stats)) {
6555 dev_kfree_skb_any(skb);
6556 } else {
6557 priv->stats.rxoktotal++;
6558 if(unicast_packet) {
6559 priv->stats.rxbytesunicast += rx_pkt_len;
6560 }
6561 }
6562#ifdef USB_RX_AGGREGATION_SUPPORT
6563 testing = 1;
6564 // (PipeIndex == 0) && (TempByte & BIT0) => TotalLength > 0.
6565 if (TotalLength > 0) {
6566 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
6567 if ((PacketOccupiedLendth & 0xFF) != 0)
6568 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
6569 PacketOccupiedLendth -= 8;
6570 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
6571 if (agg_skb->len > TempDWord)
6572 skb_pull(agg_skb, TempDWord);
6573 else
6574 agg_skb->len = 0;
6575
6576 while (agg_skb->len>=GetRxPacketShiftBytes819xUsb(&stats, true)) {
6577 u8 tmpCRC = 0, tmpICV = 0;
6578 //RT_TRACE(COMP_RECV,"%s:aggred pkt,total_len = %d\n",__FUNCTION__,agg_skb->len);
6579 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
6580 tmpCRC = RxDescr->CRC32;
6581 tmpICV = RxDescr->ICV;
6582 memcpy(agg_skb->data, &agg_skb->data[44], 2);
6583 RxDescr->CRC32 = tmpCRC;
6584 RxDescr->ICV = tmpICV;
6585
6586 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
6587 stats.signal = 0;
6588 stats.noise = -98;
6589 stats.rate = 0;
6590 stats.freq = IEEE80211_24GHZ_BAND;
6591 query_rxdesc_status(agg_skb, &stats, true);
6592 PacketLength = stats.Length;
6593
6594 if(PacketLength > agg_skb->len) {
6595 break;
6596 }
6597 /* Process the MPDU recevied */
6598 skb = dev_alloc_skb(PacketLength);
6599 memcpy(skb_put(skb,PacketLength),agg_skb->data, PacketLength);
6600 skb_trim(skb, skb->len - 4/*sCrcLng*/);
6601
6602 rx_pkt_len = skb->len;
6603 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
6604 unicast_packet = false;
6605 if(is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
6606 //TODO
6607 }else if(is_multicast_ether_addr(ieee80211_hdr->addr1)){
6608 //TODO
6609 }else {
6610 /* unicast packet */
6611 unicast_packet = true;
6612 }
6613 if(!ieee80211_rx(priv->ieee80211,skb, &stats)) {
6614 dev_kfree_skb_any(skb);
6615 } else {
6616 priv->stats.rxoktotal++;
6617 if(unicast_packet) {
6618 priv->stats.rxbytesunicast += rx_pkt_len;
6619 }
6620 }
6621 /* should trim the packet which has been copied to target skb */
6622 skb_pull(agg_skb, PacketLength);
6623 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
6624 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
6625 if ((PacketOccupiedLendth & 0xFF) != 0) {
6626 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
6627 if (agg_skb->len > PaddingBytes)
6628 skb_pull(agg_skb, PaddingBytes);
6629 else
6630 agg_skb->len = 0;
6631 }
6632 }
6633 dev_kfree_skb(agg_skb);
6634 }
6635#endif
6636 } else {
6637 priv->stats.rxurberr++;
6638 printk("actual_length:%d\n", skb->len);
6639 dev_kfree_skb_any(skb);
6640 }
6641
6642}
6643
6644void
6645rtl819xusb_process_received_packet(
6646 struct net_device *dev,
6647 struct ieee80211_rx_stats *pstats
6648 )
6649{
6650// bool bfreerfd=false, bqueued=false;
6651 u8* frame;
6652 u16 frame_len=0;
6653 struct r8192_priv *priv = ieee80211_priv(dev);
6654// u8 index = 0;
6655// u8 TID = 0;
6656 //u16 seqnum = 0;
6657 //PRX_TS_RECORD pts = NULL;
6658
6659 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
6660 //porting by amy 080508
6661 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
6662 frame = pstats->virtual_address;
6663 frame_len = pstats->packetlength;
6664#ifdef TODO // by amy about HCT
6665 if(!Adapter->bInHctTest)
6666 CountRxErrStatistics(Adapter, pRfd);
6667#endif
6668 {
6669 #ifdef ENABLE_PS //by amy for adding ps function in future
6670 RT_RF_POWER_STATE rtState;
6671 // When RF is off, we should not count the packet for hw/sw synchronize
6672 // reason, ie. there may be a duration while sw switch is changed and hw
6673 // switch is being changed. 2006.12.04, by shien chang.
6674 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8* )(&rtState));
6675 if (rtState == eRfOff)
6676 {
6677 return;
6678 }
6679 #endif
6680 priv->stats.rxframgment++;
6681
6682 }
6683#ifdef TODO
6684 RmMonitorSignalStrength(Adapter, pRfd);
6685#endif
6686 /* 2007/01/16 MH Add RX command packet handle here. */
6687 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
6688 if (rtl819xusb_rx_command_packet(dev, pstats))
6689 {
6690 return;
6691 }
6692
6693#ifdef SW_CRC_CHECK
6694 SwCrcCheck();
6695#endif
6696
6697
6698}
6699
6700void query_rx_cmdpkt_desc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats)
6701{
6702// rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
6703// struct net_device *dev=info->dev;
6704// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
6705 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
6706// rx_drvinfo_819x_usb *driver_info;
6707
6708 //
6709 //Get Rx Descriptor Information
6710 //
6711 stats->virtual_address = (u8*)skb->data;
6712 stats->Length = desc->Length;
6713 stats->RxDrvInfoSize = 0;
6714 stats->RxBufShift = 0;
6715 stats->packetlength = stats->Length-scrclng;
6716 stats->fraglength = stats->packetlength;
6717 stats->fragoffset = 0;
6718 stats->ntotalfrag = 1;
6719}
6720
6721
6722void rtl8192_rx_cmd(struct sk_buff *skb)
6723{
6724 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
6725 struct net_device *dev = info->dev;
6726 //int ret;
6727// struct urb *rx_urb = info->urb;
6728 /* TODO */
6729 struct ieee80211_rx_stats stats = {
6730 .signal = 0,
6731 .noise = -98,
6732 .rate = 0,
6733 // .mac_time = jiffies,
6734 .freq = IEEE80211_24GHZ_BAND,
6735 };
6736
6737 if((skb->len >=(20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE))
6738 {
6739
6740 query_rx_cmdpkt_desc_status(skb,&stats);
6741 // this is to be done by amy 080508 prfd->queue_id = 1;
6742
6743
6744 //
6745 // Process the command packet received.
6746 //
6747
6748 rtl819xusb_process_received_packet(dev,&stats);
6749
6750 dev_kfree_skb_any(skb);
6751 }
6752 else
6753 ;
6754
6755
6756#if 0
6757 desc = (u32*)(skb->data);
6758 cmd = (desc[0] >> 30) & 0x03;
6759
6760 if(cmd == 0x00) {//beacon interrupt
6761 //send beacon packet
6762 skb = ieee80211_get_beacon(priv->ieee80211);
6763
6764 if(!skb){
6765 DMESG("not enought memory for allocating beacon");
6766 return;
6767 }
6768 skb->cb[0] = BEACON_PRIORITY;
6769 skb->cb[1] = 0;
6770 skb->cb[2] = ieeerate2rtlrate(priv->ieee80211->basic_rate);
6771 ret = rtl8192_tx(dev, skb);
6772
6773 if( ret != 0 ){
6774 printk(KERN_ALERT "tx beacon packet error : %d !\n", ret);
6775 }
6776 dev_kfree_skb_any(skb);
6777 } else {//0x00
6778 //{ log the device information
6779 // At present, It is not implemented just now.
6780 //}
6781 }
6782#endif
6783}
6784
6785void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
6786{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006787 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02006788 struct rtl8192_rx_info *info;
6789
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006790 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02006791 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006792 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02006793 /* Nomal packet pipe */
6794 case 3:
6795 //RT_TRACE(COMP_RECV, "normal in-pipe index(%d)\n",info->out_pipe);
6796 priv->IrpPendingCount--;
6797 rtl8192_rx_nomal(skb);
6798 break;
6799
6800 /* Command packet pipe */
6801 case 9:
6802 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",\
6803 info->out_pipe);
6804
6805 rtl8192_rx_cmd(skb);
6806 break;
6807
6808 default: /* should never get here! */
6809 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",\
6810 info->out_pipe);
6811 dev_kfree_skb(skb);
6812 break;
6813
6814 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006815 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02006816}
6817
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02006818static const struct net_device_ops rtl8192_netdev_ops = {
6819 .ndo_open = rtl8192_open,
6820 .ndo_stop = rtl8192_close,
6821 .ndo_get_stats = rtl8192_stats,
6822 .ndo_tx_timeout = tx_timeout,
6823 .ndo_do_ioctl = rtl8192_ioctl,
6824 .ndo_set_multicast_list = r8192_set_multicast,
6825 .ndo_set_mac_address = r8192_set_mac_adr,
6826 .ndo_validate_addr = eth_validate_addr,
6827 .ndo_change_mtu = eth_change_mtu,
6828 .ndo_start_xmit = ieee80211_xmit,
6829};
Jerry Chuang8fc85982009-11-03 07:17:11 -02006830
6831
6832/****************************************************************************
6833 ---------------------------- USB_STUFF---------------------------
6834*****************************************************************************/
6835
6836#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
6837static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
6838 const struct usb_device_id *id)
6839#else
6840static void * __devinit rtl8192_usb_probe(struct usb_device *udev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006841 unsigned int ifnum,
6842 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02006843#endif
6844{
6845// unsigned long ioaddr = 0;
6846 struct net_device *dev = NULL;
6847 struct r8192_priv *priv= NULL;
6848#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
6849 struct usb_device *udev = interface_to_usbdev(intf);
6850#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006851 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02006852
6853 dev = alloc_ieee80211(sizeof(struct r8192_priv));
6854
6855#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
6856 SET_MODULE_OWNER(dev);
6857#endif
6858
6859#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
6860 usb_set_intfdata(intf, dev);
6861 SET_NETDEV_DEV(dev, &intf->dev);
6862#endif
6863 priv = ieee80211_priv(dev);
6864#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
6865 priv->ieee80211 = netdev_priv(dev);
6866#else
6867 priv->ieee80211 = (struct net_device *)dev->priv;
6868#endif
6869 priv->udev=udev;
6870
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006871 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02006872
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006873 //DMESG("Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02006874#if WIRELESS_EXT >= 12
6875#if WIRELESS_EXT < 17
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006876 dev->get_wireless_stats = r8192_get_wireless_stats;
Jerry Chuang8fc85982009-11-03 07:17:11 -02006877#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006878 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Jerry Chuang8fc85982009-11-03 07:17:11 -02006879#endif
6880 dev->type=ARPHRD_ETHER;
6881
6882 dev->watchdog_timeo = HZ*3; //modified by john, 0805
6883
6884 if (dev_alloc_name(dev, ifname) < 0){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006885 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02006886 ifname = "wlan%d";
6887 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006888 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02006889
6890 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
6891#if 1
6892 if(rtl8192_init(dev)!=0){
6893 RT_TRACE(COMP_ERR, "Initialization failed");
6894 goto fail;
6895 }
6896#endif
6897 netif_carrier_off(dev);
6898 netif_stop_queue(dev);
6899
6900 register_netdev(dev);
6901 RT_TRACE(COMP_INIT, "dev name=======> %s\n",dev->name);
6902 rtl8192_proc_init_one(dev);
6903
6904
6905 RT_TRACE(COMP_INIT, "Driver probe completed\n");
6906#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
6907 return dev;
6908#else
6909 return 0;
6910#endif
6911
6912
6913fail:
6914 free_ieee80211(dev);
6915
6916 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
6917#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
6918 return NULL;
6919#else
6920 return -ENODEV;
6921#endif
6922
6923}
6924
6925//detach all the work and timer structure declared or inititialize in r8192U_init function.
6926void rtl8192_cancel_deferred_work(struct r8192_priv* priv)
6927{
6928
6929#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
6930 cancel_work_sync(&priv->reset_wq);
6931 cancel_delayed_work(&priv->watch_dog_wq);
6932 cancel_delayed_work(&priv->update_beacon_wq);
6933 cancel_work_sync(&priv->qos_activate);
6934 //cancel_work_sync(&priv->SetBWModeWorkItem);
6935 //cancel_work_sync(&priv->SwChnlWorkItem);
6936#else
6937#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
6938// cancel_delayed_work(&priv->reset_wq);
6939 cancel_delayed_work(&priv->watch_dog_wq);
6940 cancel_delayed_work(&priv->update_beacon_wq);
6941// cancel_delayed_work(&priv->qos_activate);
6942 //cancel_delayed_work(&priv->SetBWModeWorkItem);
6943 //cancel_delayed_work(&priv->SwChnlWorkItem);
6944#endif
6945#endif
6946
6947}
6948
6949
6950#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
6951static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf)
6952#else
6953static void __devexit rtl8192_usb_disconnect(struct usb_device *udev, void *ptr)
6954#endif
6955{
6956#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
6957 struct net_device *dev = usb_get_intfdata(intf);
6958#else
6959 struct net_device *dev = (struct net_device *)ptr;
6960#endif
6961
6962 struct r8192_priv *priv = ieee80211_priv(dev);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006963 if(dev){
Jerry Chuang8fc85982009-11-03 07:17:11 -02006964
6965 unregister_netdev(dev);
6966
6967 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
6968 rtl8192_proc_remove_one(dev);
6969
6970 rtl8192_down(dev);
6971 if (priv->pFirmware)
6972 {
6973 kfree(priv->pFirmware);
6974 priv->pFirmware = NULL;
6975 }
6976 // priv->rf_close(dev);
6977// rtl8192_SetRFPowerState(dev, eRfOff);
6978 rtl8192_usb_deleteendpoints(dev);
6979#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
6980 destroy_workqueue(priv->priv_wq);
6981#endif
6982 //rtl8192_irq_disable(dev);
6983 //rtl8192_reset(dev);
6984 mdelay(10);
6985
6986 }
6987 free_ieee80211(dev);
6988 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
6989}
6990
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02006991/* fun with the built-in ieee80211 stack... */
6992extern int ieee80211_debug_init(void);
6993extern void ieee80211_debug_exit(void);
6994extern int ieee80211_crypto_init(void);
6995extern void ieee80211_crypto_deinit(void);
6996extern int ieee80211_crypto_tkip_init(void);
6997extern void ieee80211_crypto_tkip_exit(void);
6998extern int ieee80211_crypto_ccmp_init(void);
6999extern void ieee80211_crypto_ccmp_exit(void);
7000extern int ieee80211_crypto_wep_init(void);
7001extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02007002
7003static int __init rtl8192_usb_module_init(void)
7004{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02007005 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02007006
7007#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02007008 ret = ieee80211_debug_init();
7009 if (ret) {
7010 printk(KERN_ERR "ieee80211_debug_init() failed %d\n", ret);
7011 return ret;
7012 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02007013#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02007014 ret = ieee80211_crypto_init();
7015 if (ret) {
7016 printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret);
7017 return ret;
7018 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02007019
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02007020 ret = ieee80211_crypto_tkip_init();
7021 if (ret) {
7022 printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n",
7023 ret);
7024 return ret;
7025 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02007026
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02007027 ret = ieee80211_crypto_ccmp_init();
7028 if (ret) {
7029 printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n",
7030 ret);
7031 return ret;
7032 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02007033
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02007034 ret = ieee80211_crypto_wep_init();
7035 if (ret) {
7036 printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret);
7037 return ret;
7038 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02007039
Jerry Chuang8fc85982009-11-03 07:17:11 -02007040 printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n");
7041 printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n");
7042 RT_TRACE(COMP_INIT, "Initializing module");
7043 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
7044 rtl8192_proc_module_init();
7045 return usb_register(&rtl8192_usb_driver);
7046}
7047
7048
7049static void __exit rtl8192_usb_module_exit(void)
7050{
7051 usb_deregister(&rtl8192_usb_driver);
7052
7053 RT_TRACE(COMP_DOWN, "Exiting");
7054// rtl8192_proc_module_remove();
7055}
7056
7057
7058void rtl8192_try_wake_queue(struct net_device *dev, int pri)
7059{
7060 unsigned long flags;
7061 short enough_desc;
7062 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
7063
7064 spin_lock_irqsave(&priv->tx_lock,flags);
7065 enough_desc = check_nic_enough_desc(dev,pri);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02007066 spin_unlock_irqrestore(&priv->tx_lock,flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02007067
7068 if(enough_desc)
7069 ieee80211_wake_queue(priv->ieee80211);
7070}
7071
7072void EnableHWSecurityConfig8192(struct net_device *dev)
7073{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02007074 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02007075 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
7076 struct ieee80211_device* ieee = priv->ieee80211;
7077 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
7078#if 1
7079 if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->ieee80211->auth_mode != 2))
7080 {
7081 SECR_value |= SCR_RxUseDK;
7082 SECR_value |= SCR_TxUseDK;
7083 }
7084 else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP)))
7085 {
7086 SECR_value |= SCR_RxUseDK;
7087 SECR_value |= SCR_TxUseDK;
7088 }
7089#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02007090 //add HWSec active enable here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02007091//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
7092
7093 ieee->hwsec_active = 1;
7094
7095 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
7096 {
7097 ieee->hwsec_active = 0;
7098 SECR_value &= ~SCR_RxDecEnable;
7099 }
7100 RT_TRACE(COMP_SEC,"%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __FUNCTION__, \
7101 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
7102 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02007103 write_nic_byte(dev, SECR, SECR_value);//SECR_value | SCR_UseDK );
7104 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02007105}
7106
7107
7108void setKey( struct net_device *dev,
7109 u8 EntryNo,
7110 u8 KeyIndex,
7111 u16 KeyType,
7112 u8 *MacAddr,
7113 u8 DefaultKey,
7114 u32 *KeyContent )
7115{
7116 u32 TargetCommand = 0;
7117 u32 TargetContent = 0;
7118 u16 usConfig = 0;
7119 u8 i;
7120 if (EntryNo >= TOTAL_CAM_ENTRY)
7121 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
7122
7123 RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr"MAC_FMT"\n", dev,EntryNo, KeyIndex, KeyType, MAC_ARG(MacAddr));
7124
7125 if (DefaultKey)
7126 usConfig |= BIT15 | (KeyType<<2);
7127 else
7128 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
7129// usConfig |= BIT15 | (KeyType<<2) | (DefaultKey<<5) | KeyIndex;
7130
7131
7132 for(i=0 ; i<CAM_CONTENT_COUNT; i++){
7133 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
7134 TargetCommand |= BIT31|BIT16;
7135
7136 if(i==0){//MAC|Config
7137 TargetContent = (u32)(*(MacAddr+0)) << 16|
7138 (u32)(*(MacAddr+1)) << 24|
7139 (u32)usConfig;
7140
7141 write_nic_dword(dev, WCAMI, TargetContent);
7142 write_nic_dword(dev, RWCAM, TargetCommand);
7143 // printk("setkey cam =%8x\n", read_cam(dev, i+6*EntryNo));
7144 }
7145 else if(i==1){//MAC
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02007146 TargetContent = (u32)(*(MacAddr+2)) |
7147 (u32)(*(MacAddr+3)) << 8|
7148 (u32)(*(MacAddr+4)) << 16|
7149 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02007150 write_nic_dword(dev, WCAMI, TargetContent);
7151 write_nic_dword(dev, RWCAM, TargetCommand);
7152 }
7153 else {
7154 //Key Material
7155 if(KeyContent !=NULL){
7156 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)) );
7157 write_nic_dword(dev, RWCAM, TargetCommand);
7158 }
7159 }
7160 }
7161
7162}
7163
7164/***************************************************************************
7165 ------------------- module init / exit stubs ----------------
7166****************************************************************************/
7167module_init(rtl8192_usb_module_init);
7168module_exit(rtl8192_usb_module_exit);