blob: 5c132ac7647d22466c935429891bfd1ff13db444 [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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090073#include <linux/slab.h>
Jerry Chuang8fc85982009-11-03 07:17:11 -020074// FIXME: check if 2.6.7 is ok
Jerry Chuang8fc85982009-11-03 07:17:11 -020075
76#ifdef CONFIG_RTL8192_PM
77#include "r8192_pm.h"
78#endif
79
Jerry Chuang8fc85982009-11-03 07:17:11 -020080#include "dot11d.h"
Jerry Chuang8fc85982009-11-03 07:17:11 -020081//set here to open your trace code. //WB
82u32 rt_global_debug_component = \
83 // COMP_INIT |
84// COMP_DBG |
85 // COMP_EPROM |
86// COMP_PHY |
87 // COMP_RF |
88// COMP_FIRMWARE |
89// COMP_CH |
90 // COMP_POWER_TRACKING |
91// COMP_RATE |
92 // COMP_TXAGC |
93 // COMP_TRACE |
94 COMP_DOWN |
95 // COMP_RECV |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -020096 // COMP_SWBW |
Jerry Chuang8fc85982009-11-03 07:17:11 -020097 COMP_SEC |
98 // COMP_RESET |
99 // COMP_SEND |
100 // COMP_EVENTS |
101 COMP_ERR ; //always open err flags on
102
103#define TOTAL_CAM_ENTRY 32
104#define CAM_CONTENT_COUNT 8
105
Németh Mártona4577322010-01-10 00:18:34 +0100106static const struct usb_device_id rtl8192_usb_id_tbl[] = {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200107 /* Realtek */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200108 {USB_DEVICE(0x0bda, 0x8709)},
109 /* Corega */
110 {USB_DEVICE(0x07aa, 0x0043)},
111 /* Belkin */
112 {USB_DEVICE(0x050d, 0x805E)},
113 /* Sitecom */
114 {USB_DEVICE(0x0df6, 0x0031)},
115 /* EnGenius */
116 {USB_DEVICE(0x1740, 0x9201)},
117 /* Dlink */
118 {USB_DEVICE(0x2001, 0x3301)},
119 /* Zinwell */
120 {USB_DEVICE(0x5a57, 0x0290)},
Ben Hutchingse10ac152010-06-25 01:35:49 +0100121 /* LG */
122 {USB_DEVICE(0x043e, 0x7a01)},
Jerry Chuang8fc85982009-11-03 07:17:11 -0200123 {}
124};
125
126MODULE_LICENSE("GPL");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200127MODULE_VERSION("V 1.1");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200128MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl);
129MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards");
130
131static char* ifname = "wlan%d";
Jerry Chuang8fc85982009-11-03 07:17:11 -0200132static int hwwep = 1; //default use hw. set 0 to use software security
133static int channels = 0x3fff;
134
135
136
Jerry Chuang8fc85982009-11-03 07:17:11 -0200137module_param(ifname, charp, S_IRUGO|S_IWUSR );
138//module_param(hwseqnum,int, S_IRUGO|S_IWUSR);
139module_param(hwwep,int, S_IRUGO|S_IWUSR);
140module_param(channels,int, S_IRUGO|S_IWUSR);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200141
142MODULE_PARM_DESC(ifname," Net interface name, wlan%d=default");
143//MODULE_PARM_DESC(hwseqnum," Try to use hardware 802.11 header sequence numbers. Zero=default");
144MODULE_PARM_DESC(hwwep," Try to use hardware security support. ");
145MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI");
146
Jerry Chuang8fc85982009-11-03 07:17:11 -0200147static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
148 const struct usb_device_id *id);
149static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200150
151
152static struct usb_driver rtl8192_usb_driver = {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200153 .name = RTL819xU_MODULE_NAME, /* Driver name */
154 .id_table = rtl8192_usb_id_tbl, /* PCI_ID table */
155 .probe = rtl8192_usb_probe, /* probe fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200156 .disconnect = rtl8192_usb_disconnect, /* remove fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200157#ifdef CONFIG_RTL8192_PM
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200158 .suspend = rtl8192_suspend, /* PM suspend fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200159 .resume = rtl8192_resume, /* PM resume fn */
160#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200161 .suspend = NULL, /* PM suspend fn */
162 .resume = NULL, /* PM resume fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200163#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -0200164};
165
Jerry Chuang8fc85982009-11-03 07:17:11 -0200166
167typedef struct _CHANNEL_LIST
168{
169 u8 Channel[32];
170 u8 Len;
171}CHANNEL_LIST, *PCHANNEL_LIST;
172
173static CHANNEL_LIST ChannelPlan[] = {
174 {{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
175 {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC
176 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //ETSI
177 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Spain. Change to ETSI.
178 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //France. Change to ETSI.
179 {{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
180 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1
181 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Israel.
182 {{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
183 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22}, //MIC
184 {{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
185};
186
187static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv* priv)
188{
189 int i, max_chan=-1, min_chan=-1;
190 struct ieee80211_device* ieee = priv->ieee80211;
191 switch (channel_plan)
192 {
193 case COUNTRY_CODE_FCC:
194 case COUNTRY_CODE_IC:
195 case COUNTRY_CODE_ETSI:
196 case COUNTRY_CODE_SPAIN:
197 case COUNTRY_CODE_FRANCE:
198 case COUNTRY_CODE_MKK:
199 case COUNTRY_CODE_MKK1:
200 case COUNTRY_CODE_ISRAEL:
201 case COUNTRY_CODE_TELEC:
202 case COUNTRY_CODE_MIC:
203 {
204 Dot11d_Init(ieee);
205 ieee->bGlobalDomain = false;
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -0700206 //actually 8225 & 8256 rf chips only support B,G,24N mode
Jerry Chuang8fc85982009-11-03 07:17:11 -0200207 if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256))
208 {
209 min_chan = 1;
210 max_chan = 14;
211 }
212 else
213 {
214 RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __FUNCTION__);
215 }
216 if (ChannelPlan[channel_plan].Len != 0){
217 // Clear old channel map
218 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
219 // Set new channel map
220 for (i=0;i<ChannelPlan[channel_plan].Len;i++)
221 {
222 if (ChannelPlan[channel_plan].Channel[i] < min_chan || ChannelPlan[channel_plan].Channel[i] > max_chan)
223 break;
224 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
225 }
226 }
227 break;
228 }
229 case COUNTRY_CODE_GLOBAL_DOMAIN:
230 {
231 GET_DOT11D_INFO(ieee)->bEnabled = 0;//this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain settings.
232 Dot11d_Reset(ieee);
233 ieee->bGlobalDomain = true;
234 break;
235 }
236 default:
237 break;
238 }
239 return;
240}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200241
Jerry Chuang8fc85982009-11-03 07:17:11 -0200242
243#define rx_hal_is_cck_rate(_pdrvinfo)\
244 (_pdrvinfo->RxRate == DESC90_RATE1M ||\
245 _pdrvinfo->RxRate == DESC90_RATE2M ||\
246 _pdrvinfo->RxRate == DESC90_RATE5_5M ||\
247 _pdrvinfo->RxRate == DESC90_RATE11M) &&\
248 !_pdrvinfo->RxHT\
249
250
251void CamResetAllEntry(struct net_device *dev)
252{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200253 u32 ulcommand = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200254 //2004/02/11 In static WEP, OID_ADD_KEY or OID_ADD_WEP are set before STA associate to AP.
255 // However, ResetKey is called on OID_802_11_INFRASTRUCTURE_MODE and MlmeAssociateRequest
256 // In this condition, Cam can not be reset because upper layer will not set this static key again.
257 //if(Adapter->EncAlgorithm == WEP_Encryption)
258 // return;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200259//debug
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200260 //DbgPrint("========================================\n");
261 //DbgPrint(" Call ResetAllEntry \n");
262 //DbgPrint("========================================\n\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200263 ulcommand |= BIT31|BIT30;
264 write_nic_dword(dev, RWCAM, ulcommand);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200265
266}
267
268
269void write_cam(struct net_device *dev, u8 addr, u32 data)
270{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200271 write_nic_dword(dev, WCAMI, data);
272 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff) );
Jerry Chuang8fc85982009-11-03 07:17:11 -0200273}
274
275u32 read_cam(struct net_device *dev, u8 addr)
276{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200277 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff) );
278 return read_nic_dword(dev, 0xa8);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200279}
280
281void write_nic_byte_E(struct net_device *dev, int indx, u8 data)
282{
283 int status;
284 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
285 struct usb_device *udev = priv->udev;
286
287 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
288 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
289 indx|0xfe00, 0, &data, 1, HZ / 2);
290
291 if (status < 0)
292 {
293 printk("write_nic_byte_E TimeOut! status:%d\n", status);
294 }
295}
296
297u8 read_nic_byte_E(struct net_device *dev, int indx)
298{
299 int status;
300 u8 data;
301 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
302 struct usb_device *udev = priv->udev;
303
304 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
305 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
306 indx|0xfe00, 0, &data, 1, HZ / 2);
307
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200308 if (status < 0)
309 {
310 printk("read_nic_byte_E TimeOut! status:%d\n", status);
311 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200312
313 return data;
314}
315//as 92U has extend page from 4 to 16, so modify functions below.
316void write_nic_byte(struct net_device *dev, int indx, u8 data)
317{
318 int status;
319
320 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
321 struct usb_device *udev = priv->udev;
322
323 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
324 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
325 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
326
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200327 if (status < 0)
328 {
329 printk("write_nic_byte TimeOut! status:%d\n", status);
330 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200331
332
333}
334
335
336void write_nic_word(struct net_device *dev, int indx, u16 data)
337{
338
339 int status;
340
341 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
342 struct usb_device *udev = priv->udev;
343
344 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
345 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
346 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2);
347
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200348 if (status < 0)
349 {
350 printk("write_nic_word TimeOut! status:%d\n", status);
351 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200352
353}
354
355
356void write_nic_dword(struct net_device *dev, int indx, u32 data)
357{
358
359 int status;
360
361 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
362 struct usb_device *udev = priv->udev;
363
364 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
365 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
366 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2);
367
368
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200369 if (status < 0)
370 {
371 printk("write_nic_dword TimeOut! status:%d\n", status);
372 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200373
374}
375
376
377
378u8 read_nic_byte(struct net_device *dev, int indx)
379{
380 u8 data;
381 int status;
382 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
383 struct usb_device *udev = priv->udev;
384
385 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
386 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
387 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
388
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200389 if (status < 0)
390 {
391 printk("read_nic_byte TimeOut! status:%d\n", status);
392 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200393
394 return data;
395}
396
397
398
399u16 read_nic_word(struct net_device *dev, int indx)
400{
401 u16 data;
402 int status;
403 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
404 struct usb_device *udev = priv->udev;
405
406 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Mike Gilks616f58f2010-06-03 18:29:23 +0800407 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
408 (indx&0xff)|0xff00, (indx>>8)&0x0f,
409 &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200410
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200411 if (status < 0)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200412 printk("read_nic_word TimeOut! status:%d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200413
414 return data;
415}
416
417u16 read_nic_word_E(struct net_device *dev, int indx)
418{
419 u16 data;
420 int status;
421 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
422 struct usb_device *udev = priv->udev;
423
424 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
425 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Mike Gilks616f58f2010-06-03 18:29:23 +0800426 indx|0xfe00, 0, &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200427
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200428 if (status < 0)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200429 printk("read_nic_word TimeOut! status:%d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200430
431 return data;
432}
433
434u32 read_nic_dword(struct net_device *dev, int indx)
435{
436 u32 data;
437 int status;
Mike Gilks616f58f2010-06-03 18:29:23 +0800438 /* int result; */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200439
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),
Mike Gilks616f58f2010-06-03 18:29:23 +0800444 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
445 (indx&0xff)|0xff00, (indx>>8)&0x0f,
446 &data, 4, HZ / 2);
447 /* if(0 != result) {
448 * printk(KERN_WARNING "read size of data = %d\, date = %d\n",
449 * result, data);
450 * }
451 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200452
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200453 if (status < 0)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200454 printk("read_nic_dword TimeOut! status:%d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200455
456 return data;
457}
458
Mike Gilks616f58f2010-06-03 18:29:23 +0800459/* u8 read_phy_cck(struct net_device *dev, u8 adr); */
460/* u8 read_phy_ofdm(struct net_device *dev, u8 adr); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200461/* this might still called in what was the PHY rtl8185/rtl8192 common code
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300462 * plans are to possibility turn it again in one common code...
Jerry Chuang8fc85982009-11-03 07:17:11 -0200463 */
464inline void force_pci_posting(struct net_device *dev)
465{
466}
467
Jerry Chuang8fc85982009-11-03 07:17:11 -0200468static struct net_device_stats *rtl8192_stats(struct net_device *dev);
469void rtl8192_commit(struct net_device *dev);
Mike Gilks616f58f2010-06-03 18:29:23 +0800470/* void rtl8192_restart(struct net_device *dev); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200471void rtl8192_restart(struct work_struct *work);
Mike Gilks616f58f2010-06-03 18:29:23 +0800472/* void rtl8192_rq_tx_ack(struct work_struct *work); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200473void watch_dog_timer_callback(unsigned long data);
474
475/****************************************************************************
Mike Gilks616f58f2010-06-03 18:29:23 +0800476 * -----------------------------PROCFS STUFF-------------------------
477*****************************************************************************
478 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200479
Mike Gilks616f58f2010-06-03 18:29:23 +0800480static struct proc_dir_entry *rtl8192_proc;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200481
Mike Gilks616f58f2010-06-03 18:29:23 +0800482static int proc_get_stats_ap(char *page, char **start, off_t offset, int count,
483 int *eof, void *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200484{
485 struct net_device *dev = data;
486 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
487 struct ieee80211_device *ieee = priv->ieee80211;
488 struct ieee80211_network *target;
489
490 int len = 0;
491
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200492 list_for_each_entry(target, &ieee->network_list, list) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200493
Mike Gilks616f58f2010-06-03 18:29:23 +0800494 len += snprintf(page + len, count - len, "%s ", target->ssid);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200495
Mike Gilks616f58f2010-06-03 18:29:23 +0800496 if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0)
497 len += snprintf(page + len, count - len, "WPA\n");
498 else
499 len += snprintf(page + len, count - len, "non_WPA\n");
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200500 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200501
502 *eof = 1;
503 return len;
504}
505
506static int proc_get_registers(char *page, char **start,
507 off_t offset, int count,
508 int *eof, void *data)
509{
510 struct net_device *dev = data;
511// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
512
513 int len = 0;
514 int i,n;
515
516 int max=0xff;
517
518 /* This dump the current register page */
519len += snprintf(page + len, count - len,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200520 "\n####################page 0##################\n ");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200521
522 for(n=0;n<=max;)
523 {
524 //printk( "\nD: %2x> ", n);
525 len += snprintf(page + len, count - len,
526 "\nD: %2x > ",n);
527
528 for(i=0;i<16 && n<=max;i++,n++)
529 len += snprintf(page + len, count - len,
530 "%2x ",read_nic_byte(dev,0x000|n));
531
532 // printk("%2x ",read_nic_byte(dev,n));
533 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200534len += snprintf(page + len, count - len,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200535 "\n####################page 1##################\n ");
536 for(n=0;n<=max;)
537 {
538 //printk( "\nD: %2x> ", n);
539 len += snprintf(page + len, count - len,
540 "\nD: %2x > ",n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200541
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200542 for(i=0;i<16 && n<=max;i++,n++)
543 len += snprintf(page + len, count - len,
544 "%2x ",read_nic_byte(dev,0x100|n));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200545
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200546 // printk("%2x ",read_nic_byte(dev,n));
547 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200548len += snprintf(page + len, count - len,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200549 "\n####################page 3##################\n ");
550 for(n=0;n<=max;)
551 {
552 //printk( "\nD: %2x> ", n);
553 len += snprintf(page + len, count - len,
554 "\nD: %2x > ",n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200555
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200556 for(i=0;i<16 && n<=max;i++,n++)
557 len += snprintf(page + len, count - len,
558 "%2x ",read_nic_byte(dev,0x300|n));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200559
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200560 // printk("%2x ",read_nic_byte(dev,n));
561 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200562
Jerry Chuang8fc85982009-11-03 07:17:11 -0200563
564 len += snprintf(page + len, count - len,"\n");
565 *eof = 1;
566 return len;
567
568}
569
570
Jerry Chuang8fc85982009-11-03 07:17:11 -0200571
572
Jerry Chuang8fc85982009-11-03 07:17:11 -0200573
574static int proc_get_stats_tx(char *page, char **start,
575 off_t offset, int count,
576 int *eof, void *data)
577{
578 struct net_device *dev = data;
579 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
580
581 int len = 0;
582
583 len += snprintf(page + len, count - len,
584 "TX VI priority ok int: %lu\n"
585 "TX VI priority error int: %lu\n"
586 "TX VO priority ok int: %lu\n"
587 "TX VO priority error int: %lu\n"
588 "TX BE priority ok int: %lu\n"
589 "TX BE priority error int: %lu\n"
590 "TX BK priority ok int: %lu\n"
591 "TX BK priority error int: %lu\n"
592 "TX MANAGE priority ok int: %lu\n"
593 "TX MANAGE priority error int: %lu\n"
594 "TX BEACON priority ok int: %lu\n"
595 "TX BEACON priority error int: %lu\n"
596// "TX high priority ok int: %lu\n"
597// "TX high priority failed error int: %lu\n"
598 "TX queue resume: %lu\n"
599 "TX queue stopped?: %d\n"
600 "TX fifo overflow: %lu\n"
601// "TX beacon: %lu\n"
602 "TX VI queue: %d\n"
603 "TX VO queue: %d\n"
604 "TX BE queue: %d\n"
605 "TX BK queue: %d\n"
606// "TX HW queue: %d\n"
607 "TX VI dropped: %lu\n"
608 "TX VO dropped: %lu\n"
609 "TX BE dropped: %lu\n"
610 "TX BK dropped: %lu\n"
611 "TX total data packets %lu\n",
612// "TX beacon aborted: %lu\n",
613 priv->stats.txviokint,
614 priv->stats.txvierr,
615 priv->stats.txvookint,
616 priv->stats.txvoerr,
617 priv->stats.txbeokint,
618 priv->stats.txbeerr,
619 priv->stats.txbkokint,
620 priv->stats.txbkerr,
621 priv->stats.txmanageokint,
622 priv->stats.txmanageerr,
623 priv->stats.txbeaconokint,
624 priv->stats.txbeaconerr,
625// priv->stats.txhpokint,
626// priv->stats.txhperr,
627 priv->stats.txresumed,
628 netif_queue_stopped(dev),
629 priv->stats.txoverflow,
630// priv->stats.txbeacon,
631 atomic_read(&(priv->tx_pending[VI_PRIORITY])),
632 atomic_read(&(priv->tx_pending[VO_PRIORITY])),
633 atomic_read(&(priv->tx_pending[BE_PRIORITY])),
634 atomic_read(&(priv->tx_pending[BK_PRIORITY])),
635// read_nic_byte(dev, TXFIFOCOUNT),
636 priv->stats.txvidrop,
637 priv->stats.txvodrop,
638 priv->stats.txbedrop,
639 priv->stats.txbkdrop,
640 priv->stats.txdatapkt
641// priv->stats.txbeaconerr
642 );
643
644 *eof = 1;
645 return len;
646}
647
648
649
650static int proc_get_stats_rx(char *page, char **start,
651 off_t offset, int count,
652 int *eof, void *data)
653{
654 struct net_device *dev = data;
655 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
656
657 int len = 0;
658
659 len += snprintf(page + len, count - len,
660 "RX packets: %lu\n"
661 "RX urb status error: %lu\n"
662 "RX invalid urb error: %lu\n",
663 priv->stats.rxoktotal,
664 priv->stats.rxstaterr,
665 priv->stats.rxurberr);
666
667 *eof = 1;
668 return len;
669}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200670void rtl8192_proc_module_init(void)
671{
672 RT_TRACE(COMP_INIT, "Initializing proc filesystem");
Al Viroe55d92b2011-07-24 02:07:46 -0400673 rtl8192_proc = proc_mkdir(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200674}
675
676
677void rtl8192_proc_module_remove(void)
678{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200679 remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200680}
681
682
683void rtl8192_proc_remove_one(struct net_device *dev)
684{
685 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
686
687
688 if (priv->dir_dev) {
689 // remove_proc_entry("stats-hw", priv->dir_dev);
690 remove_proc_entry("stats-tx", priv->dir_dev);
691 remove_proc_entry("stats-rx", priv->dir_dev);
692 // remove_proc_entry("stats-ieee", priv->dir_dev);
693 remove_proc_entry("stats-ap", priv->dir_dev);
694 remove_proc_entry("registers", priv->dir_dev);
695 // remove_proc_entry("cck-registers",priv->dir_dev);
696 // remove_proc_entry("ofdm-registers",priv->dir_dev);
697 //remove_proc_entry(dev->name, rtl8192_proc);
698 remove_proc_entry("wlan0", rtl8192_proc);
699 priv->dir_dev = NULL;
700 }
701}
702
703
704void rtl8192_proc_init_one(struct net_device *dev)
705{
706 struct proc_dir_entry *e;
707 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Al Viroe55d92b2011-07-24 02:07:46 -0400708 priv->dir_dev = proc_mkdir(dev->name, rtl8192_proc);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200709 if (!priv->dir_dev) {
710 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
711 dev->name);
712 return;
713 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200714 e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
715 priv->dir_dev, proc_get_stats_rx, dev);
716
717 if (!e) {
718 RT_TRACE(COMP_ERR,"Unable to initialize "
719 "/proc/net/rtl8192/%s/stats-rx\n",
720 dev->name);
721 }
722
723
724 e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
725 priv->dir_dev, proc_get_stats_tx, dev);
726
727 if (!e) {
728 RT_TRACE(COMP_ERR, "Unable to initialize "
729 "/proc/net/rtl8192/%s/stats-tx\n",
730 dev->name);
731 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200732
733 e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO,
734 priv->dir_dev, proc_get_stats_ap, dev);
735
736 if (!e) {
737 RT_TRACE(COMP_ERR, "Unable to initialize "
738 "/proc/net/rtl8192/%s/stats-ap\n",
739 dev->name);
740 }
741
742 e = create_proc_read_entry("registers", S_IFREG | S_IRUGO,
743 priv->dir_dev, proc_get_registers, dev);
744 if (!e) {
745 RT_TRACE(COMP_ERR, "Unable to initialize "
746 "/proc/net/rtl8192/%s/registers\n",
747 dev->name);
748 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200749}
750/****************************************************************************
751 -----------------------------MISC STUFF-------------------------
752*****************************************************************************/
753
754/* this is only for debugging */
755void print_buffer(u32 *buffer, int len)
756{
757 int i;
758 u8 *buf =(u8*)buffer;
759
760 printk("ASCII BUFFER DUMP (len: %x):\n",len);
761
762 for(i=0;i<len;i++)
763 printk("%c",buf[i]);
764
765 printk("\nBINARY BUFFER DUMP (len: %x):\n",len);
766
767 for(i=0;i<len;i++)
768 printk("%x",buf[i]);
769
770 printk("\n");
771}
772
773//short check_nic_enough_desc(struct net_device *dev, priority_t priority)
774short check_nic_enough_desc(struct net_device *dev,int queue_index)
775{
776 struct r8192_priv *priv = ieee80211_priv(dev);
777 int used = atomic_read(&priv->tx_pending[queue_index]);
778
779 return (used < MAX_TX_URB);
780}
781
782void tx_timeout(struct net_device *dev)
783{
784 struct r8192_priv *priv = ieee80211_priv(dev);
785 //rtl8192_commit(dev);
786
Jerry Chuang8fc85982009-11-03 07:17:11 -0200787 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200788 //DMESG("TXTIMEOUT");
789}
790
791
792/* this is only for debug */
793void dump_eprom(struct net_device *dev)
794{
795 int i;
796 for(i=0; i<63; i++)
797 RT_TRACE(COMP_EPROM, "EEPROM addr %x : %x", i, eprom_read(dev,i));
798}
799
800/* this is only for debug */
801void rtl8192_dump_reg(struct net_device *dev)
802{
803 int i;
804 int n;
805 int max=0x1ff;
806
807 RT_TRACE(COMP_PHY, "Dumping NIC register map");
808
809 for(n=0;n<=max;)
810 {
811 printk( "\nD: %2x> ", n);
812 for(i=0;i<16 && n<=max;i++,n++)
813 printk("%2x ",read_nic_byte(dev,n));
814 }
815 printk("\n");
816}
817
818/****************************************************************************
819 ------------------------------HW STUFF---------------------------
820*****************************************************************************/
821
Jerry Chuang8fc85982009-11-03 07:17:11 -0200822
823void rtl8192_set_mode(struct net_device *dev,int mode)
824{
825 u8 ecmd;
826 ecmd=read_nic_byte(dev, EPROM_CMD);
827 ecmd=ecmd &~ EPROM_CMD_OPERATING_MODE_MASK;
828 ecmd=ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
829 ecmd=ecmd &~ (1<<EPROM_CS_SHIFT);
830 ecmd=ecmd &~ (1<<EPROM_CK_SHIFT);
831 write_nic_byte(dev, EPROM_CMD, ecmd);
832}
833
834
835void rtl8192_update_msr(struct net_device *dev)
836{
837 struct r8192_priv *priv = ieee80211_priv(dev);
838 u8 msr;
839
840 msr = read_nic_byte(dev, MSR);
841 msr &= ~ MSR_LINK_MASK;
842
843 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
844 * msr must be updated if the state is ASSOCIATING.
845 * this is intentional and make sense for ad-hoc and
846 * master (see the create BSS/IBSS func)
847 */
848 if (priv->ieee80211->state == IEEE80211_LINKED){
849
850 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
851 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
852 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
853 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
854 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
855 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
856
857 }else
858 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
859
860 write_nic_byte(dev, MSR, msr);
861}
862
863void rtl8192_set_chan(struct net_device *dev,short ch)
864{
865 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
866// u32 tx;
867 RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __FUNCTION__, ch);
868 priv->chan=ch;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200869
870 /* this hack should avoid frame TX during channel setting*/
871
872
873// tx = read_nic_dword(dev,TX_CONF);
874// tx &= ~TX_LOOPBACK_MASK;
875
876#ifndef LOOP_TEST
877// write_nic_dword(dev,TX_CONF, tx |( TX_LOOPBACK_MAC<<TX_LOOPBACK_SHIFT));
878
879 //need to implement rf set channel here WB
880
881 if (priv->rf_set_chan)
882 priv->rf_set_chan(dev,priv->chan);
883 mdelay(10);
884// write_nic_dword(dev,TX_CONF,tx | (TX_LOOPBACK_NONE<<TX_LOOPBACK_SHIFT));
885#endif
886}
887
Jerry Chuang8fc85982009-11-03 07:17:11 -0200888static void rtl8192_rx_isr(struct urb *urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200889//static void rtl8192_rx_isr(struct urb *rx_urb);
890
891u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
892{
893
894#ifdef USB_RX_AGGREGATION_SUPPORT
895 if (pstats->bisrxaggrsubframe)
896 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
897 + pstats->RxBufShift + 8);
898 else
899#endif
900 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
901 + pstats->RxBufShift);
902
903}
904static int rtl8192_rx_initiate(struct net_device*dev)
905{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200906 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
907 struct urb *entry;
908 struct sk_buff *skb;
909 struct rtl8192_rx_info *info;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200910
911 /* nomal packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200912 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB) {
913 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
914 if (!skb)
915 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200916 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200917 if (!entry) {
918 kfree_skb(skb);
919 break;
920 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200921// printk("nomal packet IN request!\n");
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200922 usb_fill_bulk_urb(entry, priv->udev,
923 usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb),
924 RX_URB_SIZE, rtl8192_rx_isr, skb);
925 info = (struct rtl8192_rx_info *) skb->cb;
926 info->urb = entry;
927 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200928 info->out_pipe = 3; //denote rx normal packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200929 skb_queue_tail(&priv->rx_queue, skb);
930 usb_submit_urb(entry, GFP_KERNEL);
931 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200932
933 /* command packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200934 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200935// printk("command packet IN request!\n");
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200936 skb = __dev_alloc_skb(RX_URB_SIZE ,GFP_KERNEL);
937 if (!skb)
938 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200939 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200940 if (!entry) {
941 kfree_skb(skb);
942 break;
943 }
944 usb_fill_bulk_urb(entry, priv->udev,
945 usb_rcvbulkpipe(priv->udev, 9), skb_tail_pointer(skb),
946 RX_URB_SIZE, rtl8192_rx_isr, skb);
947 info = (struct rtl8192_rx_info *) skb->cb;
948 info->urb = entry;
949 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200950 info->out_pipe = 9; //denote rx cmd packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200951 skb_queue_tail(&priv->rx_queue, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200952 usb_submit_urb(entry, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200953 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200954
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200955 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200956}
957
958void rtl8192_set_rxconf(struct net_device *dev)
959{
960 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
961 u32 rxconf;
962
963 rxconf=read_nic_dword(dev,RCR);
964 rxconf = rxconf &~ MAC_FILTER_MASK;
965 rxconf = rxconf | RCR_AMF;
966 rxconf = rxconf | RCR_ADF;
967 rxconf = rxconf | RCR_AB;
968 rxconf = rxconf | RCR_AM;
969 //rxconf = rxconf | RCR_ACF;
970
971 if (dev->flags & IFF_PROMISC) {DMESG ("NIC in promisc mode");}
972
973 if(priv->ieee80211->iw_mode == IW_MODE_MONITOR || \
974 dev->flags & IFF_PROMISC){
975 rxconf = rxconf | RCR_AAP;
976 } /*else if(priv->ieee80211->iw_mode == IW_MODE_MASTER){
977 rxconf = rxconf | (1<<ACCEPT_ALLMAC_FRAME_SHIFT);
978 rxconf = rxconf | (1<<RX_CHECK_BSSID_SHIFT);
979 }*/else{
980 rxconf = rxconf | RCR_APM;
981 rxconf = rxconf | RCR_CBSSID;
982 }
983
984
985 if(priv->ieee80211->iw_mode == IW_MODE_MONITOR){
986 rxconf = rxconf | RCR_AICV;
987 rxconf = rxconf | RCR_APWRMGT;
988 }
989
990 if( priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
991 rxconf = rxconf | RCR_ACRC32;
992
993
994 rxconf = rxconf &~ RX_FIFO_THRESHOLD_MASK;
995 rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE<<RX_FIFO_THRESHOLD_SHIFT);
996 rxconf = rxconf &~ MAX_RX_DMA_MASK;
997 rxconf = rxconf | ((u32)7<<RCR_MXDMA_OFFSET);
998
999// rxconf = rxconf | (1<<RX_AUTORESETPHY_SHIFT);
1000 rxconf = rxconf | RCR_ONLYERLPKT;
1001
1002// rxconf = rxconf &~ RCR_CS_MASK;
1003// rxconf = rxconf | (1<<RCR_CS_SHIFT);
1004
1005 write_nic_dword(dev, RCR, rxconf);
1006
1007 #ifdef DEBUG_RX
1008 DMESG("rxconf: %x %x",rxconf ,read_nic_dword(dev,RCR));
1009 #endif
1010}
1011//wait to be removed
1012void rtl8192_rx_enable(struct net_device *dev)
1013{
1014 //u8 cmd;
1015
1016 //struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1017
1018 rtl8192_rx_initiate(dev);
1019
1020// rtl8192_set_rxconf(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001021}
1022
1023
1024void rtl8192_tx_enable(struct net_device *dev)
1025{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001026}
1027
Jerry Chuang8fc85982009-11-03 07:17:11 -02001028
1029
1030void rtl8192_rtx_disable(struct net_device *dev)
1031{
1032 u8 cmd;
1033 struct r8192_priv *priv = ieee80211_priv(dev);
1034 struct sk_buff *skb;
1035 struct rtl8192_rx_info *info;
1036
1037 cmd=read_nic_byte(dev,CMDR);
1038 write_nic_byte(dev, CMDR, cmd &~ \
1039 (CR_TE|CR_RE));
1040 force_pci_posting(dev);
1041 mdelay(10);
1042
1043 while ((skb = __skb_dequeue(&priv->rx_queue))) {
1044 info = (struct rtl8192_rx_info *) skb->cb;
1045 if (!info->urb)
1046 continue;
1047
1048 usb_kill_urb(info->urb);
1049 kfree_skb(skb);
1050 }
1051
1052 if (skb_queue_len(&priv->skb_queue)) {
1053 printk(KERN_WARNING "skb_queue not empty\n");
1054 }
1055
1056 skb_queue_purge(&priv->skb_queue);
1057 return;
1058}
1059
1060
1061int alloc_tx_beacon_desc_ring(struct net_device *dev, int count)
1062{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001063 return 0;
1064}
1065
Jerry Chuang8fc85982009-11-03 07:17:11 -02001066inline u16 ieeerate2rtlrate(int rate)
1067{
1068 switch(rate){
1069 case 10:
1070 return 0;
1071 case 20:
1072 return 1;
1073 case 55:
1074 return 2;
1075 case 110:
1076 return 3;
1077 case 60:
1078 return 4;
1079 case 90:
1080 return 5;
1081 case 120:
1082 return 6;
1083 case 180:
1084 return 7;
1085 case 240:
1086 return 8;
1087 case 360:
1088 return 9;
1089 case 480:
1090 return 10;
1091 case 540:
1092 return 11;
1093 default:
1094 return 3;
1095
1096 }
1097}
1098static u16 rtl_rate[] = {10,20,55,110,60,90,120,180,240,360,480,540};
1099inline u16 rtl8192_rate2rate(short rate)
1100{
1101 if (rate >11) return 0;
1102 return rtl_rate[rate];
1103}
1104
1105
Justin P. Mattock589b3d02012-04-30 07:41:36 -07001106/* The prototype of rx_isr has changed since one version of Linux Kernel */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001107static void rtl8192_rx_isr(struct urb *urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001108{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001109 struct sk_buff *skb = (struct sk_buff *) urb->context;
1110 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
1111 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001112 struct r8192_priv *priv = ieee80211_priv(dev);
1113 int out_pipe = info->out_pipe;
1114 int err;
1115 if(!priv->up)
1116 return;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001117 if (unlikely(urb->status)) {
1118 info->urb = NULL;
1119 priv->stats.rxstaterr++;
1120 priv->ieee80211->stats.rx_errors++;
1121 usb_free_urb(urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001122 // printk("%s():rx status err\n",__FUNCTION__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001123 return;
1124 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001125 skb_unlink(skb, &priv->rx_queue);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001126 skb_put(skb, urb->actual_length);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001127
1128 skb_queue_tail(&priv->skb_queue, skb);
1129 tasklet_schedule(&priv->irq_rx_tasklet);
1130
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001131 skb = dev_alloc_skb(RX_URB_SIZE);
1132 if (unlikely(!skb)) {
1133 usb_free_urb(urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001134 printk("%s():can,t alloc skb\n",__FUNCTION__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001135 /* TODO check rx queue length and refill *somewhere* */
1136 return;
1137 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001138
1139 usb_fill_bulk_urb(urb, priv->udev,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001140 usb_rcvbulkpipe(priv->udev, out_pipe), skb_tail_pointer(skb),
Jerry Chuang8fc85982009-11-03 07:17:11 -02001141 RX_URB_SIZE, rtl8192_rx_isr, skb);
1142
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001143 info = (struct rtl8192_rx_info *) skb->cb;
1144 info->urb = urb;
1145 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001146 info->out_pipe = out_pipe;
1147
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001148 urb->transfer_buffer = skb_tail_pointer(skb);
1149 urb->context = skb;
1150 skb_queue_tail(&priv->rx_queue, skb);
1151 err = usb_submit_urb(urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001152 if(err && err != EPERM)
1153 printk("can not submit rxurb, err is %x,URB status is %x\n",err,urb->status);
1154}
1155
1156u32
1157rtl819xusb_rx_command_packet(
1158 struct net_device *dev,
1159 struct ieee80211_rx_stats *pstats
1160 )
1161{
1162 u32 status;
1163
1164 //RT_TRACE(COMP_RECV, DBG_TRACE, ("---> RxCommandPacketHandle819xUsb()\n"));
1165
1166 status = cmpk_message_handle_rx(dev, pstats);
1167 if (status)
1168 {
1169 DMESG("rxcommandpackethandle819xusb: It is a command packet\n");
1170 }
1171 else
1172 {
1173 //RT_TRACE(COMP_RECV, DBG_TRACE, ("RxCommandPacketHandle819xUsb: It is not a command packet\n"));
1174 }
1175
1176 //RT_TRACE(COMP_RECV, DBG_TRACE, ("<--- RxCommandPacketHandle819xUsb()\n"));
1177 return status;
1178}
1179
Jerry Chuang8fc85982009-11-03 07:17:11 -02001180
1181void rtl8192_data_hard_stop(struct net_device *dev)
1182{
1183 //FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001184}
1185
1186
1187void rtl8192_data_hard_resume(struct net_device *dev)
1188{
1189 // FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001190}
1191
1192/* this function TX data frames when the ieee80211 stack requires this.
1193 * It checks also if we need to stop the ieee tx queue, eventually do it
1194 */
1195void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
1196{
1197 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1198 int ret;
1199 unsigned long flags;
1200 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1201 u8 queue_index = tcb_desc->queue_index;
1202
1203 /* shall not be referred by command packet */
1204 assert(queue_index != TXCMD_QUEUE);
1205
1206 spin_lock_irqsave(&priv->tx_lock,flags);
1207
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001208 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001209// tcb_desc->RATRIndex = 7;
1210// tcb_desc->bTxDisableRateFallBack = 1;
1211// tcb_desc->bTxUseDriverAssingedRate = 1;
1212 tcb_desc->bTxEnableFwCalcDur = 1;
1213 skb_push(skb, priv->ieee80211->tx_headroom);
1214 ret = rtl8192_tx(dev, skb);
1215
1216 //priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom);
1217 //priv->ieee80211->stats.tx_packets++;
1218
1219 spin_unlock_irqrestore(&priv->tx_lock,flags);
1220
1221// return ret;
1222 return;
1223}
1224
1225/* This is a rough attempt to TX a frame
1226 * This is called by the ieee 80211 stack to TX management frames.
1227 * If the ring is full packet are dropped (for data frame the queue
1228 * is stopped before this can happen).
1229 */
1230int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
1231{
1232 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1233 int ret;
1234 unsigned long flags;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001235 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1236 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001237
1238
1239 spin_lock_irqsave(&priv->tx_lock,flags);
1240
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001241 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001242 if(queue_index == TXCMD_QUEUE) {
1243 skb_push(skb, USB_HWDESC_HEADER_LEN);
1244 rtl819xU_tx_cmd(dev, skb);
1245 ret = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001246 spin_unlock_irqrestore(&priv->tx_lock,flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001247 return ret;
1248 } else {
1249 skb_push(skb, priv->ieee80211->tx_headroom);
1250 ret = rtl8192_tx(dev, skb);
1251 }
1252
1253 spin_unlock_irqrestore(&priv->tx_lock,flags);
1254
1255 return ret;
1256}
1257
1258
1259void rtl8192_try_wake_queue(struct net_device *dev, int pri);
1260
1261#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1262u16 DrvAggr_PaddingAdd(struct net_device *dev, struct sk_buff *skb)
1263{
1264 u16 PaddingNum = 256 - ((skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES) % 256);
1265 return (PaddingNum&0xff);
1266}
1267
1268u8 MRateToHwRate8190Pci(u8 rate);
1269u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc);
1270u8 MapHwQueueToFirmwareQueue(u8 QueueID);
1271struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv_agg_txb *pSendList)
1272{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001273 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001274 struct r8192_priv *priv = ieee80211_priv(dev);
1275 cb_desc *tcb_desc = NULL;
1276 u8 i;
1277 u32 TotalLength;
1278 struct sk_buff *skb;
1279 struct sk_buff *agg_skb;
1280 tx_desc_819x_usb_aggr_subframe *tx_agg_desc = NULL;
1281 tx_fwinfo_819x_usb *tx_fwinfo = NULL;
1282
1283 //
1284 // Local variable initialization.
1285 //
1286 /* first skb initialization */
1287 skb = pSendList->tx_agg_frames[0];
1288 TotalLength = skb->len;
1289
1290 /* Get the total aggregation length including the padding space and
1291 * sub frame header.
1292 */
1293 for(i = 1; i < pSendList->nr_drv_agg_frames; i++) {
1294 TotalLength += DrvAggr_PaddingAdd(dev, skb);
1295 skb = pSendList->tx_agg_frames[i];
1296 TotalLength += (skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1297 }
1298
1299 /* allocate skb to contain the aggregated packets */
1300 agg_skb = dev_alloc_skb(TotalLength + ieee->tx_headroom);
1301 memset(agg_skb->data, 0, agg_skb->len);
1302 skb_reserve(agg_skb, ieee->tx_headroom);
1303
1304// RT_DEBUG_DATA(COMP_SEND, skb->cb, sizeof(skb->cb));
1305 /* reserve info for first subframe Tx descriptor to be set in the tx function */
1306 skb = pSendList->tx_agg_frames[0];
1307 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1308 tcb_desc->drv_agg_enable = 1;
1309 tcb_desc->pkt_size = skb->len;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001310 tcb_desc->DrvAggrNum = pSendList->nr_drv_agg_frames;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001311 printk("DrvAggNum = %d\n", tcb_desc->DrvAggrNum);
1312// RT_DEBUG_DATA(COMP_SEND, skb->cb, sizeof(skb->cb));
1313// printk("========>skb->data ======> \n");
1314// RT_DEBUG_DATA(COMP_SEND, skb->data, skb->len);
1315 memcpy(agg_skb->cb, skb->cb, sizeof(skb->cb));
1316 memcpy(skb_put(agg_skb,skb->len),skb->data,skb->len);
1317
1318 for(i = 1; i < pSendList->nr_drv_agg_frames; i++) {
1319 /* push the next sub frame to be 256 byte aline */
1320 skb_put(agg_skb,DrvAggr_PaddingAdd(dev,skb));
1321
1322 /* Subframe drv Tx descriptor and firmware info setting */
1323 skb = pSendList->tx_agg_frames[i];
1324 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1325 tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)agg_skb->tail;
1326 tx_fwinfo = (tx_fwinfo_819x_usb *)(agg_skb->tail + sizeof(tx_desc_819x_usb_aggr_subframe));
1327
1328 memset(tx_fwinfo,0,sizeof(tx_fwinfo_819x_usb));
1329 /* DWORD 0 */
1330 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0;
1331 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1332 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1333 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
1334 if(tcb_desc->bAMPDUEnable) {//AMPDU enabled
1335 tx_fwinfo->AllowAggregation = 1;
1336 /* DWORD 1 */
1337 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1338 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1339 } else {
1340 tx_fwinfo->AllowAggregation = 0;
1341 /* DWORD 1 */
1342 tx_fwinfo->RxMF = 0;
1343 tx_fwinfo->RxAMD = 0;
1344 }
1345
1346 /* Protection mode related */
1347 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0;
1348 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0;
1349 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0;
1350 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80)?1:0;
1351 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
1352 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT==0)?(tcb_desc->RTSSC):0;
1353 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT==1)?((tcb_desc->bRTSBW)?1:0):0;
1354 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):\
1355 (tcb_desc->bRTSUseShortGI?1:0);
1356
1357 /* Set Bandwidth and sub-channel settings. */
1358 if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
1359 {
1360 if(tcb_desc->bPacketBW) {
1361 tx_fwinfo->TxBandwidth = 1;
1362 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1363 } else {
1364 tx_fwinfo->TxBandwidth = 0;
1365 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1366 }
1367 } else {
1368 tx_fwinfo->TxBandwidth = 0;
1369 tx_fwinfo->TxSubCarrier = 0;
1370 }
1371
1372 /* Fill Tx descriptor */
1373 memset(tx_agg_desc, 0, sizeof(tx_desc_819x_usb_aggr_subframe));
1374 /* DWORD 0 */
1375 //tx_agg_desc->LINIP = 0;
1376 //tx_agg_desc->CmdInit = 1;
1377 tx_agg_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001378 /* already raw data, need not to subtract header length */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001379 tx_agg_desc->PktSize = skb->len & 0xffff;
1380
1381 /*DWORD 1*/
1382 tx_agg_desc->SecCAMID= 0;
1383 tx_agg_desc->RATid = tcb_desc->RATRIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001384 {
1385 //MPDUOverhead = 0;
1386 tx_agg_desc->NoEnc = 1;
1387 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001388 tx_agg_desc->SecType = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001389
1390 if (tcb_desc->bHwSec) {
1391 switch (priv->ieee80211->pairwise_key_type)
1392 {
1393 case KEY_TYPE_WEP40:
1394 case KEY_TYPE_WEP104:
1395 tx_agg_desc->SecType = 0x1;
1396 tx_agg_desc->NoEnc = 0;
1397 break;
1398 case KEY_TYPE_TKIP:
1399 tx_agg_desc->SecType = 0x2;
1400 tx_agg_desc->NoEnc = 0;
1401 break;
1402 case KEY_TYPE_CCMP:
1403 tx_agg_desc->SecType = 0x3;
1404 tx_agg_desc->NoEnc = 0;
1405 break;
1406 case KEY_TYPE_NA:
1407 tx_agg_desc->SecType = 0x0;
1408 tx_agg_desc->NoEnc = 1;
1409 break;
1410 }
1411 }
1412
1413 tx_agg_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1414 tx_agg_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1415
1416 tx_agg_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1417 tx_agg_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1418
1419 tx_agg_desc->OWN = 1;
1420
1421 //DWORD 2
1422 /* According windows driver, it seems that there no need to fill this field */
1423 //tx_agg_desc->TxBufferSize= (u32)(skb->len - USB_HWDESC_HEADER_LEN);
1424
1425 /* to fill next packet */
1426 skb_put(agg_skb,TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1427 memcpy(skb_put(agg_skb,skb->len),skb->data,skb->len);
1428 }
1429
1430 for(i = 0; i < pSendList->nr_drv_agg_frames; i++) {
1431 dev_kfree_skb_any(pSendList->tx_agg_frames[i]);
1432 }
1433
1434 return agg_skb;
1435}
1436
1437/* NOTE:
1438 This function return a list of PTCB which is proper to be aggregate with the input TCB.
1439 If no proper TCB is found to do aggregation, SendList will only contain the input TCB.
1440*/
1441u8 DrvAggr_GetAggregatibleList(struct net_device *dev, struct sk_buff *skb,
1442 struct ieee80211_drv_agg_txb *pSendList)
1443{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001444 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001445 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1446 u16 nMaxAggrNum = pHTInfo->UsbTxAggrNum;
1447 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1448 u8 QueueID = tcb_desc->queue_index;
1449
1450 do {
1451 pSendList->tx_agg_frames[pSendList->nr_drv_agg_frames++] = skb;
1452 if(pSendList->nr_drv_agg_frames >= nMaxAggrNum) {
1453 break;
1454 }
1455
1456 } while((skb = skb_dequeue(&ieee->skb_drv_aggQ[QueueID])));
1457
1458 RT_TRACE(COMP_AMSDU, "DrvAggr_GetAggregatibleList, nAggrTcbNum = %d \n", pSendList->nr_drv_agg_frames);
1459 return pSendList->nr_drv_agg_frames;
1460}
1461#endif
1462
Jerry Chuang8fc85982009-11-03 07:17:11 -02001463static void rtl8192_tx_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001464{
1465 struct sk_buff *skb = (struct sk_buff*)tx_urb->context;
1466 struct net_device *dev = NULL;
1467 struct r8192_priv *priv = NULL;
1468 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1469 u8 queue_index = tcb_desc->queue_index;
1470// bool bToSend0Byte;
1471// u16 BufLen = skb->len;
1472
1473 memcpy(&dev,(struct net_device*)(skb->cb),sizeof(struct net_device*));
1474 priv = ieee80211_priv(dev);
1475
1476 if(tcb_desc->queue_index != TXCMD_QUEUE) {
1477 if(tx_urb->status == 0) {
1478 dev->trans_start = jiffies;
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07001479 // Act as station mode, destination shall be unicast address.
Jerry Chuang8fc85982009-11-03 07:17:11 -02001480 //priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom);
1481 //priv->ieee80211->stats.tx_packets++;
1482 priv->stats.txoktotal++;
1483 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
1484 priv->stats.txbytesunicast += (skb->len - priv->ieee80211->tx_headroom);
1485 } else {
1486 priv->ieee80211->stats.tx_errors++;
1487 //priv->stats.txmanageerr++;
1488 /* TODO */
1489 }
1490 }
1491
1492 /* free skb and tx_urb */
1493 if(skb != NULL) {
1494 dev_kfree_skb_any(skb);
1495 usb_free_urb(tx_urb);
1496 atomic_dec(&priv->tx_pending[queue_index]);
1497 }
1498
Jerry Chuang8fc85982009-11-03 07:17:11 -02001499 {
1500 //
1501 // Handle HW Beacon:
Uwe Kleine-Königaf02b582010-10-26 21:57:53 +02001502 // We had transfer our beacon frame to host controller at this moment.
Jerry Chuang8fc85982009-11-03 07:17:11 -02001503 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02001504 //
1505 // Caution:
1506 // Handling the wait queue of command packets.
1507 // For Tx command packets, we must not do TCB fragment because it is not handled right now.
1508 // We must cut the packets to match the size of TX_CMD_PKT before we send it.
1509 //
1510
1511 /* Handle MPDU in wait queue. */
1512 if(queue_index != BEACON_QUEUE) {
1513 /* Don't send data frame during scanning.*/
1514 if((skb_queue_len(&priv->ieee80211->skb_waitQ[queue_index]) != 0)&&\
1515 (!(priv->ieee80211->queue_stop))) {
1516 if(NULL != (skb = skb_dequeue(&(priv->ieee80211->skb_waitQ[queue_index]))))
1517 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1518
1519 return; //modified by david to avoid further processing AMSDU
1520 }
1521#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1522 else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index])!= 0)&&\
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001523 (!(priv->ieee80211->queue_stop))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001524 // Tx Driver Aggregation process
Justin P. Mattock589b3d02012-04-30 07:41:36 -07001525 /* The driver will aggregation the packets according to the following stats
Jerry Chuang8fc85982009-11-03 07:17:11 -02001526 * 1. check whether there's tx irq available, for it's a completion return
1527 * function, it should contain enough tx irq;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07001528 * 2. check packet type;
Uwe Kleine-König9b0131c2010-09-01 15:40:25 +02001529 * 3. initialize sendlist, check whether the to-be send packet no greater than 1
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07001530 * 4. aggregates the packets, and fill firmware info and tx desc into it, etc.
1531 * 5. check whether the packet could be sent, otherwise just insert into wait head
Jerry Chuang8fc85982009-11-03 07:17:11 -02001532 * */
1533 skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]);
1534 if(!check_nic_enough_desc(dev, queue_index)) {
1535 skb_queue_head(&(priv->ieee80211->skb_drv_aggQ[queue_index]), skb);
1536 return;
1537 }
1538
1539 {
1540 /*TODO*/
1541 /*
1542 u8* pHeader = skb->data;
1543
1544 if(IsMgntQosData(pHeader) ||
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001545 IsMgntQData_Ack(pHeader) ||
Jerry Chuang8fc85982009-11-03 07:17:11 -02001546 IsMgntQData_Poll(pHeader) ||
1547 IsMgntQData_Poll_Ack(pHeader)
1548 )
1549 */
1550 {
1551 struct ieee80211_drv_agg_txb SendList;
1552
1553 memset(&SendList, 0, sizeof(struct ieee80211_drv_agg_txb));
1554 if(DrvAggr_GetAggregatibleList(dev, skb, &SendList) > 1) {
1555 skb = DrvAggr_Aggregation(dev, &SendList);
1556
Jerry Chuang8fc85982009-11-03 07:17:11 -02001557 }
1558 }
1559 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1560 }
1561 }
1562#endif
1563 }
1564 }
1565
Jerry Chuang8fc85982009-11-03 07:17:11 -02001566}
1567
1568void rtl8192_beacon_stop(struct net_device *dev)
1569{
1570 u8 msr, msrm, msr2;
1571 struct r8192_priv *priv = ieee80211_priv(dev);
1572
1573 msr = read_nic_byte(dev, MSR);
1574 msrm = msr & MSR_LINK_MASK;
1575 msr2 = msr & ~MSR_LINK_MASK;
1576
1577 if(NIC_8192U == priv->card_8192) {
1578 usb_kill_urb(priv->rx_urb[MAX_RX_URB]);
1579 }
1580 if ((msrm == (MSR_LINK_ADHOC<<MSR_LINK_SHIFT) ||
1581 (msrm == (MSR_LINK_MASTER<<MSR_LINK_SHIFT)))){
1582 write_nic_byte(dev, MSR, msr2 | MSR_LINK_NONE);
1583 write_nic_byte(dev, MSR, msr);
1584 }
1585}
1586
1587void rtl8192_config_rate(struct net_device* dev, u16* rate_config)
1588{
1589 struct r8192_priv *priv = ieee80211_priv(dev);
1590 struct ieee80211_network *net;
1591 u8 i=0, basic_rate = 0;
1592 net = & priv->ieee80211->current_network;
1593
1594 for (i=0; i<net->rates_len; i++)
1595 {
1596 basic_rate = net->rates[i]&0x7f;
1597 switch(basic_rate)
1598 {
1599 case MGN_1M: *rate_config |= RRSR_1M; break;
1600 case MGN_2M: *rate_config |= RRSR_2M; break;
1601 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1602 case MGN_11M: *rate_config |= RRSR_11M; break;
1603 case MGN_6M: *rate_config |= RRSR_6M; break;
1604 case MGN_9M: *rate_config |= RRSR_9M; break;
1605 case MGN_12M: *rate_config |= RRSR_12M; break;
1606 case MGN_18M: *rate_config |= RRSR_18M; break;
1607 case MGN_24M: *rate_config |= RRSR_24M; break;
1608 case MGN_36M: *rate_config |= RRSR_36M; break;
1609 case MGN_48M: *rate_config |= RRSR_48M; break;
1610 case MGN_54M: *rate_config |= RRSR_54M; break;
1611 }
1612 }
1613 for (i=0; i<net->rates_ex_len; i++)
1614 {
1615 basic_rate = net->rates_ex[i]&0x7f;
1616 switch(basic_rate)
1617 {
1618 case MGN_1M: *rate_config |= RRSR_1M; break;
1619 case MGN_2M: *rate_config |= RRSR_2M; break;
1620 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1621 case MGN_11M: *rate_config |= RRSR_11M; break;
1622 case MGN_6M: *rate_config |= RRSR_6M; break;
1623 case MGN_9M: *rate_config |= RRSR_9M; break;
1624 case MGN_12M: *rate_config |= RRSR_12M; break;
1625 case MGN_18M: *rate_config |= RRSR_18M; break;
1626 case MGN_24M: *rate_config |= RRSR_24M; break;
1627 case MGN_36M: *rate_config |= RRSR_36M; break;
1628 case MGN_48M: *rate_config |= RRSR_48M; break;
1629 case MGN_54M: *rate_config |= RRSR_54M; break;
1630 }
1631 }
1632}
1633
1634
1635#define SHORT_SLOT_TIME 9
1636#define NON_SHORT_SLOT_TIME 20
1637
1638void rtl8192_update_cap(struct net_device* dev, u16 cap)
1639{
1640 u32 tmp = 0;
1641 struct r8192_priv *priv = ieee80211_priv(dev);
1642 struct ieee80211_network *net = &priv->ieee80211->current_network;
1643 priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
1644 tmp = priv->basic_rate;
1645 if (priv->short_preamble)
1646 tmp |= BRSR_AckShortPmb;
1647 write_nic_dword(dev, RRSR, tmp);
1648
1649 if (net->mode & (IEEE_G|IEEE_N_24G))
1650 {
1651 u8 slot_time = 0;
1652 if ((cap & WLAN_CAPABILITY_SHORT_SLOT)&&(!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime))
1653 {//short slot time
1654 slot_time = SHORT_SLOT_TIME;
1655 }
1656 else //long slot time
1657 slot_time = NON_SHORT_SLOT_TIME;
1658 priv->slot_time = slot_time;
1659 write_nic_byte(dev, SLOT_TIME, slot_time);
1660 }
1661
1662}
1663void rtl8192_net_update(struct net_device *dev)
1664{
1665
1666 struct r8192_priv *priv = ieee80211_priv(dev);
1667 struct ieee80211_network *net;
1668 u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
1669 u16 rate_config = 0;
1670 net = & priv->ieee80211->current_network;
1671
1672 rtl8192_config_rate(dev, &rate_config);
1673 priv->basic_rate = rate_config &= 0x15f;
1674
1675 write_nic_dword(dev,BSSIDR,((u32*)net->bssid)[0]);
1676 write_nic_word(dev,BSSIDR+4,((u16*)net->bssid)[2]);
1677 //for(i=0;i<ETH_ALEN;i++)
1678 // write_nic_byte(dev,BSSID+i,net->bssid[i]);
1679
1680 rtl8192_update_msr(dev);
1681// rtl8192_update_cap(dev, net->capability);
1682 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
1683 {
1684 write_nic_word(dev, ATIMWND, 2);
1685 write_nic_word(dev, BCN_DMATIME, 1023);
1686 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
1687// write_nic_word(dev, BcnIntTime, 100);
1688 write_nic_word(dev, BCN_DRV_EARLY_INT, 1);
1689 write_nic_byte(dev, BCN_ERR_THRESH, 100);
1690 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
1691 // TODO: BcnIFS may required to be changed on ASIC
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001692 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001693
1694 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
1695 }
1696
1697
1698
1699}
1700
1701//temporary hw beacon is not used any more.
1702//open it when necessary
Jerry Chuang8fc85982009-11-03 07:17:11 -02001703void rtl819xusb_beacon_tx(struct net_device *dev,u16 tx_rate)
1704{
1705
Jerry Chuang8fc85982009-11-03 07:17:11 -02001706}
Jerry Chuang8fc85982009-11-03 07:17:11 -02001707inline u8 rtl8192_IsWirelessBMode(u16 rate)
1708{
1709 if( ((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220) )
1710 return 1;
1711 else return 0;
1712}
1713
1714u16 N_DBPSOfRate(u16 DataRate);
1715
1716u16 ComputeTxTime(
1717 u16 FrameLength,
1718 u16 DataRate,
1719 u8 bManagementFrame,
1720 u8 bShortPreamble
1721)
1722{
1723 u16 FrameTime;
1724 u16 N_DBPS;
1725 u16 Ceiling;
1726
1727 if( rtl8192_IsWirelessBMode(DataRate) )
1728 {
1729 if( bManagementFrame || !bShortPreamble || DataRate == 10 )
1730 { // long preamble
1731 FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
1732 }
1733 else
1734 { // Short preamble
1735 FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
1736 }
1737 if( ( FrameLength*8 % (DataRate/10) ) != 0 ) //Get the Ceilling
1738 FrameTime ++;
1739 } else { //802.11g DSSS-OFDM PLCP length field calculation.
1740 N_DBPS = N_DBPSOfRate(DataRate);
1741 Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
1742 + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
1743 FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
1744 }
1745 return FrameTime;
1746}
1747
1748u16 N_DBPSOfRate(u16 DataRate)
1749{
1750 u16 N_DBPS = 24;
1751
1752 switch(DataRate)
1753 {
1754 case 60:
1755 N_DBPS = 24;
1756 break;
1757
1758 case 90:
1759 N_DBPS = 36;
1760 break;
1761
1762 case 120:
1763 N_DBPS = 48;
1764 break;
1765
1766 case 180:
1767 N_DBPS = 72;
1768 break;
1769
1770 case 240:
1771 N_DBPS = 96;
1772 break;
1773
1774 case 360:
1775 N_DBPS = 144;
1776 break;
1777
1778 case 480:
1779 N_DBPS = 192;
1780 break;
1781
1782 case 540:
1783 N_DBPS = 216;
1784 break;
1785
1786 default:
1787 break;
1788 }
1789
1790 return N_DBPS;
1791}
1792
1793void rtl819xU_cmd_isr(struct urb *tx_cmd_urb, struct pt_regs *regs)
1794{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001795 usb_free_urb(tx_cmd_urb);
1796}
1797
1798unsigned int txqueue2outpipe(struct r8192_priv* priv,unsigned int tx_queue) {
1799
1800 if(tx_queue >= 9)
1801 {
1802 RT_TRACE(COMP_ERR,"%s():Unknown queue ID!!!\n",__FUNCTION__);
1803 return 0x04;
1804 }
1805 return priv->txqueue_to_outpipemap[tx_queue];
1806}
1807
1808short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
1809{
1810 struct r8192_priv *priv = ieee80211_priv(dev);
1811 //u8 *tx;
1812 int status;
1813 struct urb *tx_urb;
1814 //int urb_buf_len;
1815 unsigned int idx_pipe;
1816 tx_desc_cmd_819x_usb *pdesc = (tx_desc_cmd_819x_usb *)skb->data;
1817 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1818 u8 queue_index = tcb_desc->queue_index;
1819
1820 //printk("\n %s::queue_index = %d\n",__FUNCTION__, queue_index);
1821 atomic_inc(&priv->tx_pending[queue_index]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001822 tx_urb = usb_alloc_urb(0,GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001823 if(!tx_urb){
1824 dev_kfree_skb(skb);
1825 return -ENOMEM;
1826 }
1827
1828 memset(pdesc, 0, USB_HWDESC_HEADER_LEN);
1829 /* Tx descriptor ought to be set according to the skb->cb */
1830 pdesc->FirstSeg = 1;//bFirstSeg;
1831 pdesc->LastSeg = 1;//bLastSeg;
1832 pdesc->CmdInit = tcb_desc->bCmdOrInit;
1833 pdesc->TxBufferSize = tcb_desc->txbuf_size;
1834 pdesc->OWN = 1;
1835 pdesc->LINIP = tcb_desc->bLastIniPkt;
1836
1837 //----------------------------------------------------------------------------
1838 // Fill up USB_OUT_CONTEXT.
1839 //----------------------------------------------------------------------------
1840 // Get index to out pipe from specified QueueID.
1841#ifndef USE_ONE_PIPE
1842 idx_pipe = txqueue2outpipe(priv,queue_index);
1843#else
1844 idx_pipe = 0x04;
1845#endif
1846#ifdef JOHN_DUMP_TXDESC
1847 int i;
1848 printk("<Tx descriptor>--rate %x---",rate);
1849 for (i = 0; i < 8; i++)
1850 printk("%8x ", tx[i]);
1851 printk("\n");
1852#endif
1853 usb_fill_bulk_urb(tx_urb,priv->udev, usb_sndbulkpipe(priv->udev,idx_pipe), \
1854 skb->data, skb->len, rtl8192_tx_isr, skb);
1855
Jerry Chuang8fc85982009-11-03 07:17:11 -02001856 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001857
1858 if (!status){
1859 return 0;
1860 }else{
1861 DMESGE("Error TX CMD URB, error %d",
1862 status);
1863 return -1;
1864 }
1865}
1866
1867/*
1868 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1869 * in TxFwInfo data structure
1870 * 2006.10.30 by Emily
1871 *
1872 * \param QUEUEID Software Queue
1873*/
1874u8 MapHwQueueToFirmwareQueue(u8 QueueID)
1875{
1876 u8 QueueSelect = 0x0; //defualt set to
1877
1878 switch(QueueID) {
1879 case BE_QUEUE:
1880 QueueSelect = QSLT_BE; //or QSelect = pTcb->priority;
1881 break;
1882
1883 case BK_QUEUE:
1884 QueueSelect = QSLT_BK; //or QSelect = pTcb->priority;
1885 break;
1886
1887 case VO_QUEUE:
1888 QueueSelect = QSLT_VO; //or QSelect = pTcb->priority;
1889 break;
1890
1891 case VI_QUEUE:
1892 QueueSelect = QSLT_VI; //or QSelect = pTcb->priority;
1893 break;
1894 case MGNT_QUEUE:
1895 QueueSelect = QSLT_MGNT;
1896 break;
1897
1898 case BEACON_QUEUE:
1899 QueueSelect = QSLT_BEACON;
1900 break;
1901
1902 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
1903 // TODO: Remove Assertions
1904//#if (RTL819X_FPGA_VER & RTL819X_FPGA_GUANGAN_070502)
1905 case TXCMD_QUEUE:
1906 QueueSelect = QSLT_CMD;
1907 break;
1908//#endif
1909 case HIGH_QUEUE:
1910 QueueSelect = QSLT_HIGH;
1911 break;
1912
1913 default:
1914 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
1915 break;
1916 }
1917 return QueueSelect;
1918}
1919
1920u8 MRateToHwRate8190Pci(u8 rate)
1921{
1922 u8 ret = DESC90_RATE1M;
1923
1924 switch(rate) {
1925 case MGN_1M: ret = DESC90_RATE1M; break;
1926 case MGN_2M: ret = DESC90_RATE2M; break;
1927 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1928 case MGN_11M: ret = DESC90_RATE11M; break;
1929 case MGN_6M: ret = DESC90_RATE6M; break;
1930 case MGN_9M: ret = DESC90_RATE9M; break;
1931 case MGN_12M: ret = DESC90_RATE12M; break;
1932 case MGN_18M: ret = DESC90_RATE18M; break;
1933 case MGN_24M: ret = DESC90_RATE24M; break;
1934 case MGN_36M: ret = DESC90_RATE36M; break;
1935 case MGN_48M: ret = DESC90_RATE48M; break;
1936 case MGN_54M: ret = DESC90_RATE54M; break;
1937
1938 // HT rate since here
1939 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1940 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1941 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1942 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1943 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1944 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1945 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1946 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1947 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1948 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1949 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1950 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1951 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1952 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1953 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1954 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1955 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
1956
1957 default: break;
1958 }
1959 return ret;
1960}
1961
1962
1963u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
1964{
1965 u8 tmp_Short;
1966
1967 tmp_Short = (TxHT==1)?((tcb_desc->bUseShortGI)?1:0):((tcb_desc->bUseShortPreamble)?1:0);
1968
1969 if(TxHT==1 && TxRate != DESC90_RATEMCS15)
1970 tmp_Short = 0;
1971
1972 return tmp_Short;
1973}
1974
Jerry Chuang8fc85982009-11-03 07:17:11 -02001975static void tx_zero_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001976{
1977 return;
1978}
1979
1980/*
1981 * The tx procedure is just as following,
1982 * skb->cb will contain all the following information,
1983 * priority, morefrag, rate, &dev.
1984 * */
1985short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
1986{
1987 struct r8192_priv *priv = ieee80211_priv(dev);
1988 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1989 tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data;
1990 tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
1991 struct usb_device *udev = priv->udev;
1992 int pend;
1993 int status;
1994 struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
1995 //int urb_len;
1996 unsigned int idx_pipe;
1997// RT_DEBUG_DATA(COMP_SEND, tcb_desc, sizeof(cb_desc));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001998// printk("=============> %s\n", __FUNCTION__);
1999 pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]);
2000 /* we are locked here so the two atomic_read and inc are executed
2001 * without interleaves
2002 * !!! For debug purpose
2003 */
2004 if( pend > MAX_TX_URB){
Jerry Chuang8fc85982009-11-03 07:17:11 -02002005 printk("To discard skb packet!\n");
2006 dev_kfree_skb_any(skb);
2007 return -1;
2008 }
2009
Jerry Chuang8fc85982009-11-03 07:17:11 -02002010 tx_urb = usb_alloc_urb(0,GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002011 if(!tx_urb){
2012 dev_kfree_skb_any(skb);
2013 return -ENOMEM;
2014 }
2015
2016 /* Fill Tx firmware info */
2017 memset(tx_fwinfo,0,sizeof(tx_fwinfo_819x_usb));
2018 /* DWORD 0 */
2019 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0;
2020 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
2021 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
2022 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
2023 if(tcb_desc->bAMPDUEnable) {//AMPDU enabled
2024 tx_fwinfo->AllowAggregation = 1;
2025 /* DWORD 1 */
2026 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
2027 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
2028 } else {
2029 tx_fwinfo->AllowAggregation = 0;
2030 /* DWORD 1 */
2031 tx_fwinfo->RxMF = 0;
2032 tx_fwinfo->RxAMD = 0;
2033 }
2034
2035 /* Protection mode related */
2036 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0;
2037 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0;
2038 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0;
2039 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80)?1:0;
2040 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
2041 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT==0)?(tcb_desc->RTSSC):0;
2042 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT==1)?((tcb_desc->bRTSBW)?1:0):0;
2043 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):\
2044 (tcb_desc->bRTSUseShortGI?1:0);
2045
2046 /* Set Bandwidth and sub-channel settings. */
2047 if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
2048 {
2049 if(tcb_desc->bPacketBW) {
2050 tx_fwinfo->TxBandwidth = 1;
2051 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
2052 } else {
2053 tx_fwinfo->TxBandwidth = 0;
2054 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
2055 }
2056 } else {
2057 tx_fwinfo->TxBandwidth = 0;
2058 tx_fwinfo->TxSubCarrier = 0;
2059 }
2060
2061#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2062 if (tcb_desc->drv_agg_enable)
2063 {
2064 tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1;
2065 }
2066#endif
2067 /* Fill Tx descriptor */
2068 memset(tx_desc, 0, sizeof(tx_desc_819x_usb));
2069 /* DWORD 0 */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002070 tx_desc->LINIP = 0;
2071 tx_desc->CmdInit = 1;
2072 tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002073
2074#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2075 if (tcb_desc->drv_agg_enable) {
2076 tx_desc->PktSize = tcb_desc->pkt_size;
2077 } else
2078#endif
2079 {
2080 tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff;
2081 }
2082
2083 /*DWORD 1*/
2084 tx_desc->SecCAMID= 0;
2085 tx_desc->RATid = tcb_desc->RATRIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002086 {
2087 //MPDUOverhead = 0;
2088 tx_desc->NoEnc = 1;
2089 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002090 tx_desc->SecType = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002091 if (tcb_desc->bHwSec)
2092 {
2093 switch (priv->ieee80211->pairwise_key_type)
2094 {
2095 case KEY_TYPE_WEP40:
2096 case KEY_TYPE_WEP104:
2097 tx_desc->SecType = 0x1;
2098 tx_desc->NoEnc = 0;
2099 break;
2100 case KEY_TYPE_TKIP:
2101 tx_desc->SecType = 0x2;
2102 tx_desc->NoEnc = 0;
2103 break;
2104 case KEY_TYPE_CCMP:
2105 tx_desc->SecType = 0x3;
2106 tx_desc->NoEnc = 0;
2107 break;
2108 case KEY_TYPE_NA:
2109 tx_desc->SecType = 0x0;
2110 tx_desc->NoEnc = 1;
2111 break;
2112 }
2113 }
2114
2115 tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
2116 tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
2117
2118 tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
2119 tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
2120
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002121 /* Fill fields that are required to be initialized in all of the descriptors */
2122 //DWORD 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002123 tx_desc->FirstSeg = 1;
2124 tx_desc->LastSeg = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002125 tx_desc->OWN = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002126
2127#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2128 if (tcb_desc->drv_agg_enable) {
2129 tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb);
2130 } else
2131#endif
2132 {
2133 //DWORD 2
2134 tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN);
2135 }
2136 /* Get index to out pipe from specified QueueID */
2137#ifndef USE_ONE_PIPE
2138 idx_pipe = txqueue2outpipe(priv,tcb_desc->queue_index);
2139#else
2140 idx_pipe = 0x5;
2141#endif
2142
2143 //RT_DEBUG_DATA(COMP_SEND,tx_fwinfo,sizeof(tx_fwinfo_819x_usb));
2144 //RT_DEBUG_DATA(COMP_SEND,tx_desc,sizeof(tx_desc_819x_usb));
2145
2146 /* To submit bulk urb */
2147 usb_fill_bulk_urb(tx_urb,udev,
2148 usb_sndbulkpipe(udev,idx_pipe), skb->data,
2149 skb->len, rtl8192_tx_isr, skb);
2150
Jerry Chuang8fc85982009-11-03 07:17:11 -02002151 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002152 if (!status){
2153//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
2154 bool bSend0Byte = false;
2155 u8 zero = 0;
2156 if(udev->speed == USB_SPEED_HIGH)
2157 {
2158 if (skb->len > 0 && skb->len % 512 == 0)
2159 bSend0Byte = true;
2160 }
2161 else
2162 {
2163 if (skb->len > 0 && skb->len % 64 == 0)
2164 bSend0Byte = true;
2165 }
2166 if (bSend0Byte)
2167 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002168 tx_urb_zero = usb_alloc_urb(0,GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002169 if(!tx_urb_zero){
2170 RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
2171 return -ENOMEM;
2172 }
2173 usb_fill_bulk_urb(tx_urb_zero,udev,
2174 usb_sndbulkpipe(udev,idx_pipe), &zero,
2175 0, tx_zero_isr, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002176 status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002177 if (status){
2178 RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
2179 return -1;
2180 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002181 }
2182 dev->trans_start = jiffies;
2183 atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
2184 return 0;
2185 }else{
2186 RT_TRACE(COMP_ERR, "Error TX URB %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]),
2187 status);
2188 return -1;
2189 }
2190}
2191
2192short rtl8192_usb_initendpoints(struct net_device *dev)
2193{
2194 struct r8192_priv *priv = ieee80211_priv(dev);
2195
Julia Lawall32414872010-05-11 20:26:57 +02002196 priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB+1),
2197 GFP_KERNEL);
David Chosrovab8345172010-12-01 13:42:16 +01002198 if (priv->rx_urb == NULL)
2199 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002200
2201#ifndef JACKSON_NEW_RX
2202 for(i=0;i<(MAX_RX_URB+1);i++){
2203
Jerry Chuang8fc85982009-11-03 07:17:11 -02002204 priv->rx_urb[i] = usb_alloc_urb(0,GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002205
2206 priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL);
2207
2208 priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE;
2209 }
2210#endif
2211
2212#ifdef THOMAS_BEACON
2213{
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002214 long align = 0;
2215 void *oldaddr, *newaddr;
2216
Jerry Chuang8fc85982009-11-03 07:17:11 -02002217 priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002218 priv->oldaddr = kmalloc(16, GFP_KERNEL);
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002219 oldaddr = priv->oldaddr;
2220 align = ((long)oldaddr) & 3;
2221 if (align) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002222 newaddr = oldaddr + 4 - align;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002223 priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align;
2224 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002225 newaddr = oldaddr;
2226 priv->rx_urb[16]->transfer_buffer_length = 16;
2227 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002228 priv->rx_urb[16]->transfer_buffer = newaddr;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002229}
2230#endif
2231
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002232 memset(priv->rx_urb, 0, sizeof(struct urb*) * MAX_RX_URB);
Julia Lawall7a6cb0d2010-05-13 22:00:05 +02002233 priv->pp_rxskb = kcalloc(MAX_RX_URB, sizeof(struct sk_buff *),
Julia Lawall32414872010-05-11 20:26:57 +02002234 GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002235 if (priv->pp_rxskb == NULL)
2236 goto destroy;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002237
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002238 goto _middle;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002239
2240
2241destroy:
Ilia Mirkine72714f2011-03-13 00:29:07 -05002242 kfree(priv->pp_rxskb);
2243 kfree(priv->rx_urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002244
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002245 priv->pp_rxskb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002246 priv->rx_urb = NULL;
2247
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002248 DMESGE("Endpoint Alloc Failure");
2249 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002250
2251
2252_middle:
2253
2254 printk("End of initendpoints\n");
2255 return 0;
2256
2257}
2258#ifdef THOMAS_BEACON
2259void rtl8192_usb_deleteendpoints(struct net_device *dev)
2260{
2261 int i;
2262 struct r8192_priv *priv = ieee80211_priv(dev);
2263
2264 if(priv->rx_urb){
2265 for(i=0;i<(MAX_RX_URB+1);i++){
2266 usb_kill_urb(priv->rx_urb[i]);
2267 usb_free_urb(priv->rx_urb[i]);
2268 }
2269 kfree(priv->rx_urb);
2270 priv->rx_urb = NULL;
2271 }
Ilia Mirkine72714f2011-03-13 00:29:07 -05002272 kfree(priv->oldaddr);
2273 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002274 if (priv->pp_rxskb) {
2275 kfree(priv->pp_rxskb);
2276 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002277 }
2278}
2279#else
2280void rtl8192_usb_deleteendpoints(struct net_device *dev)
2281{
2282 int i;
2283 struct r8192_priv *priv = ieee80211_priv(dev);
2284
2285#ifndef JACKSON_NEW_RX
2286
2287 if(priv->rx_urb){
2288 for(i=0;i<(MAX_RX_URB+1);i++){
2289 usb_kill_urb(priv->rx_urb[i]);
2290 kfree(priv->rx_urb[i]->transfer_buffer);
2291 usb_free_urb(priv->rx_urb[i]);
2292 }
2293 kfree(priv->rx_urb);
2294 priv->rx_urb = NULL;
2295
2296 }
2297#else
Ilia Mirkine72714f2011-03-13 00:29:07 -05002298 kfree(priv->rx_urb);
2299 priv->rx_urb = NULL;
2300 kfree(priv->oldaddr);
2301 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002302 if (priv->pp_rxskb) {
2303 kfree(priv->pp_rxskb);
2304 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002305
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002306 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002307
2308#endif
2309}
2310#endif
2311
Jerry Chuang8fc85982009-11-03 07:17:11 -02002312extern void rtl8192_update_ratr_table(struct net_device* dev);
2313void rtl8192_link_change(struct net_device *dev)
2314{
2315// int i;
2316
2317 struct r8192_priv *priv = ieee80211_priv(dev);
2318 struct ieee80211_device* ieee = priv->ieee80211;
2319 //write_nic_word(dev, BCN_INTR_ITV, net->beacon_interval);
2320 if (ieee->state == IEEE80211_LINKED)
2321 {
2322 rtl8192_net_update(dev);
2323 rtl8192_update_ratr_table(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002324 //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
2325 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
2326 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002327 }
2328 /*update timing params*/
2329// RT_TRACE(COMP_CH, "========>%s(), chan:%d\n", __FUNCTION__, priv->chan);
2330// rtl8192_set_chan(dev, priv->chan);
2331 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
2332 {
2333 u32 reg = 0;
2334 reg = read_nic_dword(dev, RCR);
2335 if (priv->ieee80211->state == IEEE80211_LINKED)
2336 priv->ReceiveConfig = reg |= RCR_CBSSID;
2337 else
2338 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
2339 write_nic_dword(dev, RCR, reg);
2340 }
2341
2342// rtl8192_set_rxconf(dev);
2343}
2344
2345static struct ieee80211_qos_parameters def_qos_parameters = {
2346 {3,3,3,3},/* cw_min */
2347 {7,7,7,7},/* cw_max */
2348 {2,2,2,2},/* aifs */
2349 {0,0,0,0},/* flags */
2350 {0,0,0,0} /* tx_op_limit */
2351};
2352
2353
Jerry Chuang8fc85982009-11-03 07:17:11 -02002354void rtl8192_update_beacon(struct work_struct * work)
2355{
2356 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
2357 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002358 struct ieee80211_device* ieee = priv->ieee80211;
2359 struct ieee80211_network* net = &ieee->current_network;
2360
2361 if (ieee->pHTInfo->bCurrentHTSupport)
2362 HTUpdateSelfAndPeerSetting(ieee, net);
2363 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
2364 rtl8192_update_cap(dev, net->capability);
2365}
2366/*
2367* background support to run QoS activate functionality
2368*/
2369int WDCAPARA_ADD[] = {EDCAPARA_BE,EDCAPARA_BK,EDCAPARA_VI,EDCAPARA_VO};
Jerry Chuang8fc85982009-11-03 07:17:11 -02002370void rtl8192_qos_activate(struct work_struct * work)
2371{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002372 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
2373 struct net_device *dev = priv->ieee80211->dev;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002374 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2375 u8 mode = priv->ieee80211->current_network.mode;
2376 //u32 size = sizeof(struct ieee80211_qos_parameters);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002377 u8 u1bAIFS;
2378 u32 u4bAcParam;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002379 int i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002380
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002381 if (priv == NULL)
2382 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002383
Jerry Chuang8fc85982009-11-03 07:17:11 -02002384 mutex_lock(&priv->mutex);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002385 if(priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002386 goto success;
2387 RT_TRACE(COMP_QOS,"qos active process with associate response received\n");
2388 /* It better set slot time at first */
2389 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2390 /* update the ac parameter to related registers */
2391 for(i = 0; i < QOS_QUEUE_NUM; i++) {
2392 //Mode G/A: slotTimeTimer = 9; Mode B: 20
2393 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime;
2394 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
2395 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2396 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2397 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
2398
2399 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
2400 //write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
2401 }
2402
2403success:
Jerry Chuang8fc85982009-11-03 07:17:11 -02002404 mutex_unlock(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002405}
2406
2407static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
2408 int active_network,
2409 struct ieee80211_network *network)
2410{
2411 int ret = 0;
2412 u32 size = sizeof(struct ieee80211_qos_parameters);
2413
2414 if(priv->ieee80211->state !=IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002415 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002416
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002417 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2418 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002419
2420 if (network->flags & NETWORK_HAS_QOS_MASK) {
2421 if (active_network &&
2422 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
2423 network->qos_data.active = network->qos_data.supported;
2424
2425 if ((network->qos_data.active == 1) && (active_network == 1) &&
2426 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2427 (network->qos_data.old_param_count !=
2428 network->qos_data.param_count)) {
2429 network->qos_data.old_param_count =
2430 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002431 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002432 RT_TRACE (COMP_QOS, "QoS parameters change call "
2433 "qos_activate\n");
2434 }
2435 } else {
2436 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2437 &def_qos_parameters, size);
2438
2439 if ((network->qos_data.active == 1) && (active_network == 1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002440 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002441 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2442 }
2443 network->qos_data.active = 0;
2444 network->qos_data.supported = 0;
2445 }
2446
2447 return 0;
2448}
2449
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002450/* handle and manage frame from beacon and probe response */
Jerry Chuang8fc85982009-11-03 07:17:11 -02002451static int rtl8192_handle_beacon(struct net_device * dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002452 struct ieee80211_beacon * beacon,
2453 struct ieee80211_network * network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002454{
2455 struct r8192_priv *priv = ieee80211_priv(dev);
2456
2457 rtl8192_qos_handle_probe_response(priv,1,network);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002458 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002459 return 0;
2460
2461}
2462
2463/*
2464* handling the beaconing responses. if we get different QoS setting
2465* off the network from the associated setting, adjust the QoS
2466* setting
2467*/
2468static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002469 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002470{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002471 int ret = 0;
2472 unsigned long flags;
2473 u32 size = sizeof(struct ieee80211_qos_parameters);
2474 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002475
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002476 if ((priv == NULL) || (network == NULL))
2477 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002478
2479 if(priv->ieee80211->state !=IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002480 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002481
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002482 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2483 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002484
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002485 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002486 if(network->flags & NETWORK_HAS_QOS_PARAMETERS) {
2487 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2488 &network->qos_data.parameters,\
2489 sizeof(struct ieee80211_qos_parameters));
2490 priv->ieee80211->current_network.qos_data.active = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002491 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002492 set_qos_param = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002493 /* update qos parameter for current network */
2494 priv->ieee80211->current_network.qos_data.old_param_count = \
2495 priv->ieee80211->current_network.qos_data.param_count;
2496 priv->ieee80211->current_network.qos_data.param_count = \
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002497 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002498 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002499 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002500 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2501 &def_qos_parameters, size);
2502 priv->ieee80211->current_network.qos_data.active = 0;
2503 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002504 set_qos_param = 1;
2505 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002506
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002507 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002508
2509 RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n",__FUNCTION__,network->flags ,priv->ieee80211->current_network.qos_data.active);
2510 if (set_qos_param == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002511 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002512
2513
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002514 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002515}
2516
2517
2518static int rtl8192_handle_assoc_response(struct net_device *dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002519 struct ieee80211_assoc_response_frame *resp,
2520 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002521{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002522 struct r8192_priv *priv = ieee80211_priv(dev);
2523 rtl8192_qos_association_resp(priv, network);
2524 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002525}
2526
2527
2528void rtl8192_update_ratr_table(struct net_device* dev)
2529 // POCTET_STRING posLegacyRate,
2530 // u8* pMcsRate)
2531 // PRT_WLAN_STA pEntry)
2532{
2533 struct r8192_priv* priv = ieee80211_priv(dev);
2534 struct ieee80211_device* ieee = priv->ieee80211;
2535 u8* pMcsRate = ieee->dot11HTOperationalRateSet;
2536 //struct ieee80211_network *net = &ieee->current_network;
2537 u32 ratr_value = 0;
2538 u8 rate_index = 0;
2539 rtl8192_config_rate(dev, (u16*)(&ratr_value));
2540 ratr_value |= (*(u16*)(pMcsRate)) << 12;
2541// switch (net->mode)
2542 switch (ieee->mode)
2543 {
2544 case IEEE_A:
2545 ratr_value &= 0x00000FF0;
2546 break;
2547 case IEEE_B:
2548 ratr_value &= 0x0000000F;
2549 break;
2550 case IEEE_G:
2551 ratr_value &= 0x00000FF7;
2552 break;
2553 case IEEE_N_24G:
2554 case IEEE_N_5G:
2555 if (ieee->pHTInfo->PeerMimoPs == 0) //MIMO_PS_STATIC
2556 ratr_value &= 0x0007F007;
2557 else{
2558 if (priv->rf_type == RF_1T2R)
2559 ratr_value &= 0x000FF007;
2560 else
2561 ratr_value &= 0x0F81F007;
2562 }
2563 break;
2564 default:
2565 break;
2566 }
2567 ratr_value &= 0x0FFFFFFF;
2568 if(ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz){
2569 ratr_value |= 0x80000000;
2570 }else if(!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz){
2571 ratr_value |= 0x80000000;
2572 }
2573 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2574 write_nic_byte(dev, UFWP, 1);
2575}
2576
2577static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
2578static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
2579bool GetNmodeSupportBySecCfg8192(struct net_device*dev)
2580{
Jerry Chuang8fc85982009-11-03 07:17:11 -02002581 struct r8192_priv* priv = ieee80211_priv(dev);
2582 struct ieee80211_device* ieee = priv->ieee80211;
2583 struct ieee80211_network * network = &ieee->current_network;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002584 int wpa_ie_len= ieee->wpa_ie_len;
2585 struct ieee80211_crypt_data* crypt;
2586 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002587
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002588 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002589 //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 -02002590 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 -02002591
2592 /* simply judge */
2593 if(encrypt && (wpa_ie_len == 0)) {
2594 /* wep encryption, no N mode setting */
2595 return false;
2596// } else if((wpa_ie_len != 0)&&(memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) {
2597 } else if((wpa_ie_len != 0)) {
2598 /* parse pairwise key type */
2599 //if((pairwisekey = WEP40)||(pairwisekey = WEP104)||(pairwisekey = TKIP))
2600 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))))
2601 return true;
2602 else
2603 return false;
2604 } else {
2605 return true;
2606 }
2607
Jerry Chuang8fc85982009-11-03 07:17:11 -02002608 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002609}
2610
2611bool GetHalfNmodeSupportByAPs819xUsb(struct net_device* dev)
2612{
2613 bool Reval;
2614 struct r8192_priv* priv = ieee80211_priv(dev);
2615 struct ieee80211_device* ieee = priv->ieee80211;
2616
2617 if(ieee->bHalfWirelessN24GMode == true)
2618 Reval = true;
2619 else
2620 Reval = false;
2621
2622 return Reval;
2623}
2624
2625void rtl8192_refresh_supportrate(struct r8192_priv* priv)
2626{
2627 struct ieee80211_device* ieee = priv->ieee80211;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002628 //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002629 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
2630 {
2631 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
2632 //RT_DEBUG_DATA(COMP_INIT, ieee->RegHTSuppRateSet, 16);
2633 //RT_DEBUG_DATA(COMP_INIT, ieee->Regdot11HTOperationalRateSet, 16);
2634 }
2635 else
2636 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2637 return;
2638}
2639
2640u8 rtl8192_getSupportedWireleeMode(struct net_device*dev)
2641{
2642 struct r8192_priv *priv = ieee80211_priv(dev);
2643 u8 ret = 0;
2644 switch(priv->rf_chip)
2645 {
2646 case RF_8225:
2647 case RF_8256:
2648 case RF_PSEUDO_11N:
2649 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2650 break;
2651 case RF_8258:
2652 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2653 break;
2654 default:
2655 ret = WIRELESS_MODE_B;
2656 break;
2657 }
2658 return ret;
2659}
2660void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode)
2661{
2662 struct r8192_priv *priv = ieee80211_priv(dev);
2663 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2664
Jerry Chuang8fc85982009-11-03 07:17:11 -02002665 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode)==0))
2666 {
2667 if(bSupportMode & WIRELESS_MODE_N_24G)
2668 {
2669 wireless_mode = WIRELESS_MODE_N_24G;
2670 }
2671 else if(bSupportMode & WIRELESS_MODE_N_5G)
2672 {
2673 wireless_mode = WIRELESS_MODE_N_5G;
2674 }
2675 else if((bSupportMode & WIRELESS_MODE_A))
2676 {
2677 wireless_mode = WIRELESS_MODE_A;
2678 }
2679 else if((bSupportMode & WIRELESS_MODE_G))
2680 {
2681 wireless_mode = WIRELESS_MODE_G;
2682 }
2683 else if((bSupportMode & WIRELESS_MODE_B))
2684 {
2685 wireless_mode = WIRELESS_MODE_B;
2686 }
2687 else{
2688 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __FUNCTION__,bSupportMode);
2689 wireless_mode = WIRELESS_MODE_B;
2690 }
2691 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002692#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we should wait for FPGA
Jerry Chuang8fc85982009-11-03 07:17:11 -02002693 ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
2694#endif
2695 priv->ieee80211->mode = wireless_mode;
2696
2697 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2698 priv->ieee80211->pHTInfo->bEnableHT = 1;
2699 else
2700 priv->ieee80211->pHTInfo->bEnableHT = 0;
2701 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2702 rtl8192_refresh_supportrate(priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002703
2704}
2705//init priv variables here. only non_zero value should be initialized here.
2706static void rtl8192_init_priv_variable(struct net_device* dev)
2707{
2708 struct r8192_priv *priv = ieee80211_priv(dev);
2709 u8 i;
2710 priv->card_8192 = NIC_8192U;
2711 priv->chan = 1; //set to channel 1
2712 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2713 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2714 priv->ieee80211->ieee_up=0;
2715 priv->retry_rts = DEFAULT_RETRY_RTS;
2716 priv->retry_data = DEFAULT_RETRY_DATA;
2717 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2718 priv->ieee80211->rate = 110; //11 mbps
2719 priv->ieee80211->short_slot = 1;
2720 priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0;
2721 priv->CckPwEnl = 6;
2722 //for silent reset
2723 priv->IrpPendingCount = 1;
2724 priv->ResetProgress = RESET_TYPE_NORESET;
2725 priv->bForcedSilentReset = 0;
2726 priv->bDisableNormalResetCheck = false;
2727 priv->force_reset = false;
2728
2729 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
2730 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2731 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2732 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2733 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2734 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
2735 IEEE_SOFTMAC_BEACONS;//added by amy 080604 //| //IEEE_SOFTMAC_SINGLE_QUEUE;
2736
2737 priv->ieee80211->active_scan = 1;
2738 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2739 priv->ieee80211->host_encrypt = 1;
2740 priv->ieee80211->host_decrypt = 1;
2741 priv->ieee80211->start_send_beacons = NULL;//rtl819xusb_beacon_tx;//-by amy 080604
2742 priv->ieee80211->stop_send_beacons = NULL;//rtl8192_beacon_stop;//-by amy 080604
2743 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2744 priv->ieee80211->set_chan = rtl8192_set_chan;
2745 priv->ieee80211->link_change = rtl8192_link_change;
2746 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2747 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2748 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2749 priv->ieee80211->init_wmmparam_flag = 0;
2750 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2751 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2752 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
2753 priv->ieee80211->qos_support = 1;
2754
2755 //added by WB
2756// priv->ieee80211->SwChnlByTimerHandler = rtl8192_phy_SwChnl;
2757 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2758 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2759 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2760 //added by david
2761 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
2762 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
2763 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2764 //added by amy
2765 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
2766 priv->card_type = USB;
2767#ifdef TO_DO_LIST
2768 if(Adapter->bInHctTest)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002769 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002770 pHalData->ShortRetryLimit = 7;
2771 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002772 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002773#endif
2774 {
2775 priv->ShortRetryLimit = 0x30;
2776 priv->LongRetryLimit = 0x30;
2777 }
2778 priv->EarlyRxThreshold = 7;
2779 priv->enable_gpio0 = 0;
2780 priv->TransmitConfig =
2781 // TCR_DurProcMode | //for RTL8185B, duration setting by HW
2782 //? TCR_DISReqQsize |
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002783 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002784 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
2785 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07002786 (false ? TCR_SAT: 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
Jerry Chuang8fc85982009-11-03 07:17:11 -02002787#ifdef TO_DO_LIST
2788 if(Adapter->bInHctTest)
2789 pHalData->ReceiveConfig = pHalData->CSMethod |
2790 RCR_AMF | RCR_ADF | //RCR_AAP | //accept management/data
2791 //guangan200710
2792 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2793 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
2794 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
2795 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2796 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
2797 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt:0);
2798 else
2799
2800#endif
2801 priv->ReceiveConfig =
2802 RCR_AMF | RCR_ADF | //accept management/data
2803 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2804 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
2805 //RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
2806 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2807 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
2808 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT:0);
2809
2810 priv->AcmControl = 0;
Devendra Nagab7553422012-08-26 11:06:33 +05302811 priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002812
2813 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002814 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002815 skb_queue_head_init(&priv->skb_queue);
2816
2817 /* Tx related queue */
2818 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
2819 skb_queue_head_init(&priv->ieee80211->skb_waitQ [i]);
2820 }
2821 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
2822 skb_queue_head_init(&priv->ieee80211->skb_aggQ [i]);
2823 }
2824 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
2825 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ [i]);
2826 }
2827 priv->rf_set_chan = rtl8192_phy_SwChnl;
2828}
2829
2830//init lock here
2831static void rtl8192_init_priv_lock(struct r8192_priv* priv)
2832{
2833 spin_lock_init(&priv->tx_lock);
2834 spin_lock_init(&priv->irq_lock);//added by thomas
2835 //spin_lock_init(&priv->rf_lock);
2836 sema_init(&priv->wx_sem,1);
2837 sema_init(&priv->rf_sem,1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002838 mutex_init(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002839}
2840
Jerry Chuang8fc85982009-11-03 07:17:11 -02002841extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002842
2843void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
2844//init tasklet and wait_queue here. only 2.6 above kernel is considered
2845#define DRV_NAME "wlan0"
2846static void rtl8192_init_priv_task(struct net_device* dev)
2847{
2848 struct r8192_priv *priv = ieee80211_priv(dev);
2849
Jerry Chuang8fc85982009-11-03 07:17:11 -02002850 priv->priv_wq = create_workqueue(DRV_NAME);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002851
Jerry Chuang8fc85982009-11-03 07:17:11 -02002852 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2853
2854 //INIT_DELAYED_WORK(&priv->watch_dog_wq, hal_dm_watchdog);
2855 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2856 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
2857// INIT_DELAYED_WORK(&priv->gpio_change_rf_wq, dm_gpio_change_rf_callback);
2858 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2859 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2860 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
2861 //INIT_WORK(&priv->SwChnlWorkItem, rtl8192_SwChnl_WorkItem);
2862 //INIT_WORK(&priv->SetBWModeWorkItem, rtl8192_SetBWModeWorkItem);
2863 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002864
2865 tasklet_init(&priv->irq_rx_tasklet,
2866 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2867 (unsigned long)priv);
2868}
2869
2870static void rtl8192_get_eeprom_size(struct net_device* dev)
2871{
2872 u16 curCR = 0;
2873 struct r8192_priv *priv = ieee80211_priv(dev);
2874 RT_TRACE(COMP_EPROM, "===========>%s()\n", __FUNCTION__);
2875 curCR = read_nic_word_E(dev,EPROM_CMD);
2876 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
2877 //whether need I consider BIT5?
2878 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
2879 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __FUNCTION__, priv->epromtype);
2880}
2881
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002882//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002883static inline u16 endian_swap(u16* data)
2884{
2885 u16 tmp = *data;
2886 *data = (tmp >> 8) | (tmp << 8);
2887 return *data;
2888}
2889static void rtl8192_read_eeprom_info(struct net_device* dev)
2890{
2891 u16 wEPROM_ID = 0;
2892 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
2893 u8 bLoad_From_EEPOM = false;
2894 struct r8192_priv *priv = ieee80211_priv(dev);
2895 u16 tmpValue = 0;
2896 RT_TRACE(COMP_EPROM, "===========>%s()\n", __FUNCTION__);
2897 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
2898 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
2899
2900 if (wEPROM_ID != RTL8190_EEPROM_ID)
2901 {
2902 RT_TRACE(COMP_ERR, "EEPROM ID is invalid(is 0x%x(should be 0x%x)\n", wEPROM_ID, RTL8190_EEPROM_ID);
2903 }
2904 else
2905 bLoad_From_EEPOM = true;
2906
2907 if (bLoad_From_EEPOM)
2908 {
2909 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
2910 priv->eeprom_vid = endian_swap(&tmpValue);
2911 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
2912 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
2913 priv->eeprom_ChannelPlan =((tmpValue&0xff00)>>8);
2914 priv->btxpowerdata_readfromEEPORM = true;
2915 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
2916 }
2917 else
2918 {
2919 priv->eeprom_vid = 0;
2920 priv->eeprom_pid = 0;
2921 priv->card_8192_version = VERSION_819xU_B;
2922 priv->eeprom_ChannelPlan = 0;
2923 priv->eeprom_CustomerID = 0;
2924 }
2925 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);
2926 //set channelplan from eeprom
2927 priv->ChannelPlan = priv->eeprom_ChannelPlan;
2928 if (bLoad_From_EEPOM)
2929 {
2930 int i;
2931 for (i=0; i<6; i+=2)
2932 {
2933 u16 tmp = 0;
2934 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
2935 *(u16*)(&dev->dev_addr[i]) = tmp;
2936 }
2937 }
2938 else
2939 {
2940 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2941 //should I set IDR0 here?
2942 }
Joe Perches0ee9f672009-12-06 11:34:52 -08002943 RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002944 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
2945 priv->rf_chip = RF_8256;
2946
2947 if (priv->card_8192_version == (u8)VERSION_819xU_A)
2948 {
2949 //read Tx power gain offset of legacy OFDM to HT rate
2950 if (bLoad_From_EEPOM)
2951 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
2952 else
2953 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
2954 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
2955 //read ThermalMeter from EEPROM
2956 if (bLoad_From_EEPOM)
2957 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
2958 else
2959 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2960 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
2961 //vivi, for tx power track
2962 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2963 //read antenna tx power offset of B/C/D to A from EEPROM
2964 if (bLoad_From_EEPOM)
2965 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
2966 else
2967 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
2968 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
2969 // Read CrystalCap from EEPROM
2970 if (bLoad_From_EEPOM)
2971 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
2972 else
2973 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
2974 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
2975 //get per-channel Tx power level
2976 if (bLoad_From_EEPOM)
2977 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
2978 else
2979 priv->EEPROM_Def_Ver = 1;
2980 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
2981 if (priv->EEPROM_Def_Ver == 0) //old eeprom definition
2982 {
2983 int i;
2984 if (bLoad_From_EEPOM)
2985 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
2986 else
2987 priv->EEPROMTxPowerLevelCCK = 0x10;
2988 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
2989 for (i=0; i<3; i++)
2990 {
2991 if (bLoad_From_EEPOM)
2992 {
2993 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
2994 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
2995 tmpValue = tmpValue & 0x00ff;
2996 else
2997 tmpValue = (tmpValue & 0xff00) >> 8;
2998 }
2999 else
3000 tmpValue = 0x10;
3001 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
3002 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
3003 }
3004 }//end if EEPROM_DEF_VER == 0
3005 else if (priv->EEPROM_Def_Ver == 1)
3006 {
3007 if (bLoad_From_EEPOM)
3008 {
3009 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
3010 tmpValue = (tmpValue & 0xff00) >> 8;
3011 }
3012 else
3013 tmpValue = 0x10;
3014 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
3015
3016 if (bLoad_From_EEPOM)
3017 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
3018 else
3019 tmpValue = 0x1010;
3020 *((u16*)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
3021 if (bLoad_From_EEPOM)
3022 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
3023 else
3024 tmpValue = 0x1010;
3025 *((u16*)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
3026 if (bLoad_From_EEPOM)
3027 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
3028 else
3029 tmpValue = 0x10;
3030 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
3031 }//endif EEPROM_Def_Ver == 1
3032
3033 //update HAL variables
3034 //
3035 {
3036 int i;
3037 for (i=0; i<14; i++)
3038 {
3039 if (i<=3)
3040 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
3041 else if (i>=4 && i<=9)
3042 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
3043 else
3044 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
3045 }
3046
3047 for (i=0; i<14; i++)
3048 {
3049 if (priv->EEPROM_Def_Ver == 0)
3050 {
3051 if (i<=3)
3052 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
3053 else if (i>=4 && i<=9)
3054 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
3055 else
3056 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
3057 }
3058 else if (priv->EEPROM_Def_Ver == 1)
3059 {
3060 if (i<=3)
3061 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
3062 else if (i>=4 && i<=9)
3063 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
3064 else
3065 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
3066 }
3067 }
3068 }//end update HAL variables
3069 priv->TxPowerDiff = priv->EEPROMPwDiff;
3070// Antenna B gain offset to antenna A, bit0~3
3071 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
3072 // Antenna C gain offset to antenna A, bit4~7
3073 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
3074 // CrystalCap, bit12~15
3075 priv->CrystalCap = priv->EEPROMCrystalCap;
3076 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
3077 // 92U does not enable TX power tracking.
3078 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
3079 }//end if VersionID == VERSION_819xU_A
3080
3081//added by vivi, for dlink led, 20080416
3082 switch(priv->eeprom_CustomerID)
3083 {
3084 case EEPROM_CID_RUNTOP:
3085 priv->CustomerID = RT_CID_819x_RUNTOP;
3086 break;
3087
3088 case EEPROM_CID_DLINK:
3089 priv->CustomerID = RT_CID_DLINK;
3090 break;
3091
3092 default:
3093 priv->CustomerID = RT_CID_DEFAULT;
3094 break;
3095
3096 }
3097
3098 switch(priv->CustomerID)
3099 {
3100 case RT_CID_819x_RUNTOP:
3101 priv->LedStrategy = SW_LED_MODE2;
3102 break;
3103
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003104 case RT_CID_DLINK:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003105 priv->LedStrategy = SW_LED_MODE4;
3106 break;
3107
3108 default:
3109 priv->LedStrategy = SW_LED_MODE0;
3110 break;
3111
3112 }
3113
3114
3115 if(priv->rf_type == RF_1T2R)
3116 {
3117 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
3118 }
3119 else
3120 {
3121 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
3122 }
3123
3124 // 2008/01/16 MH We can only know RF type in the function. So we have to init
3125 // DIG RATR table again.
3126 init_rate_adaptive(dev);
3127 //we need init DIG RATR table here again.
3128
3129 RT_TRACE(COMP_EPROM, "<===========%s()\n", __FUNCTION__);
3130 return;
3131}
3132
3133short rtl8192_get_channel_map(struct net_device * dev)
3134{
3135 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003136 if(priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN){
3137 printk("rtl8180_init:Error channel plan! Set to default.\n");
3138 priv->ChannelPlan= 0;
3139 }
3140 RT_TRACE(COMP_INIT, "Channel plan is %d\n",priv->ChannelPlan);
3141
3142 rtl819x_set_channel_map(priv->ChannelPlan, priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003143 return 0;
3144}
3145
3146short rtl8192_init(struct net_device *dev)
3147{
3148
3149 struct r8192_priv *priv = ieee80211_priv(dev);
3150
3151 memset(&(priv->stats),0,sizeof(struct Stats));
3152 memset(priv->txqueue_to_outpipemap,0,9);
3153#ifdef PIPE12
3154 {
3155 int i=0;
3156 u8 queuetopipe[]={3,2,1,0,4,8,7,6,5};
3157 memcpy(priv->txqueue_to_outpipemap,queuetopipe,9);
3158/* for(i=0;i<9;i++)
3159 printk("%d ",priv->txqueue_to_outpipemap[i]);
3160 printk("\n");*/
3161 }
3162#else
3163 {
3164 u8 queuetopipe[]={3,2,1,0,4,4,0,4,4};
3165 memcpy(priv->txqueue_to_outpipemap,queuetopipe,9);
3166/* for(i=0;i<9;i++)
3167 printk("%d ",priv->txqueue_to_outpipemap[i]);
3168 printk("\n");*/
3169 }
3170#endif
3171 rtl8192_init_priv_variable(dev);
3172 rtl8192_init_priv_lock(priv);
3173 rtl8192_init_priv_task(dev);
3174 rtl8192_get_eeprom_size(dev);
3175 rtl8192_read_eeprom_info(dev);
3176 rtl8192_get_channel_map(dev);
3177 init_hal_dm(dev);
3178 init_timer(&priv->watch_dog_timer);
3179 priv->watch_dog_timer.data = (unsigned long)dev;
3180 priv->watch_dog_timer.function = watch_dog_timer_callback;
3181 if(rtl8192_usb_initendpoints(dev)!=0){
3182 DMESG("Endopoints initialization failed");
3183 return -ENOMEM;
3184 }
3185
3186 //rtl8192_adapter_start(dev);
3187#ifdef DEBUG_EPROM
3188 dump_eprom(dev);
3189#endif
3190 return 0;
3191}
3192
3193/******************************************************************************
3194 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
3195 * not to do all the hw config as its name says
3196 * input: net_device dev
3197 * output: none
3198 * return: none
3199 * notice: This part need to modified according to the rate set we filtered
3200 * ****************************************************************************/
3201void rtl8192_hwconfig(struct net_device* dev)
3202{
3203 u32 regRATR = 0, regRRSR = 0;
3204 u8 regBwOpMode = 0, regTmp = 0;
3205 struct r8192_priv *priv = ieee80211_priv(dev);
3206
3207// Set RRSR, RATR, and BW_OPMODE registers
3208 //
3209 switch(priv->ieee80211->mode)
3210 {
3211 case WIRELESS_MODE_B:
3212 regBwOpMode = BW_OPMODE_20MHZ;
3213 regRATR = RATE_ALL_CCK;
3214 regRRSR = RATE_ALL_CCK;
3215 break;
3216 case WIRELESS_MODE_A:
3217 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
3218 regRATR = RATE_ALL_OFDM_AG;
3219 regRRSR = RATE_ALL_OFDM_AG;
3220 break;
3221 case WIRELESS_MODE_G:
3222 regBwOpMode = BW_OPMODE_20MHZ;
3223 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3224 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3225 break;
3226 case WIRELESS_MODE_AUTO:
3227#ifdef TO_DO_LIST
3228 if (Adapter->bInHctTest)
3229 {
3230 regBwOpMode = BW_OPMODE_20MHZ;
3231 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3232 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3233 }
3234 else
3235#endif
3236 {
3237 regBwOpMode = BW_OPMODE_20MHZ;
3238 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
3239 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3240 }
3241 break;
3242 case WIRELESS_MODE_N_24G:
3243 // It support CCK rate by default.
3244 // CCK rate will be filtered out only when associated AP does not support it.
3245 regBwOpMode = BW_OPMODE_20MHZ;
3246 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
3247 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3248 break;
3249 case WIRELESS_MODE_N_5G:
3250 regBwOpMode = BW_OPMODE_5G;
3251 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
3252 regRRSR = RATE_ALL_OFDM_AG;
3253 break;
3254 }
3255
3256 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
3257 {
3258 u32 ratr_value = 0;
3259 ratr_value = regRATR;
3260 if (priv->rf_type == RF_1T2R)
3261 {
3262 ratr_value &= ~(RATE_ALL_OFDM_2SS);
3263 }
3264 write_nic_dword(dev, RATR0, ratr_value);
3265 write_nic_byte(dev, UFWP, 1);
3266 }
3267 regTmp = read_nic_byte(dev, 0x313);
3268 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
3269 write_nic_dword(dev, RRSR, regRRSR);
3270
3271 //
3272 // Set Retry Limit here
3273 //
3274 write_nic_word(dev, RETRY_LIMIT,
3275 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT | \
3276 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
3277 // Set Contention Window here
3278
3279 // Set Tx AGC
3280
3281 // Set Tx Antenna including Feedback control
3282
3283 // Set Auto Rate fallback control
3284
3285
3286}
3287
3288
3289//InitializeAdapter and PhyCfg
3290bool rtl8192_adapter_start(struct net_device *dev)
3291{
3292 struct r8192_priv *priv = ieee80211_priv(dev);
3293 u32 dwRegRead = 0;
3294 bool init_status = true;
3295 RT_TRACE(COMP_INIT, "====>%s()\n", __FUNCTION__);
3296 priv->Rf_Mode = RF_OP_By_SW_3wire;
3297 //for ASIC power on sequence
3298 write_nic_byte_E(dev, 0x5f, 0x80);
3299 mdelay(50);
3300 write_nic_byte_E(dev, 0x5f, 0xf0);
3301 write_nic_byte_E(dev, 0x5d, 0x00);
3302 write_nic_byte_E(dev, 0x5e, 0x80);
3303 write_nic_byte(dev, 0x17, 0x37);
3304 mdelay(10);
3305//#ifdef TO_DO_LIST
3306 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
3307 //config CPUReset Register
3308 //Firmware Reset or not?
3309 dwRegRead = read_nic_dword(dev, CPU_GEN);
3310 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
3311 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
3312 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
3313 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
3314 else
3315 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __FUNCTION__, priv->pFirmware->firmware_status);
3316
3317 write_nic_dword(dev, CPU_GEN, dwRegRead);
3318 //mdelay(30);
3319 //config BB.
3320 rtl8192_BBConfig(dev);
3321
Jerry Chuang8fc85982009-11-03 07:17:11 -02003322 //Loopback mode or not
3323 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
3324// priv->LoopbackMode = RTL819xU_MAC_LOOPBACK;
3325
3326 dwRegRead = read_nic_dword(dev, CPU_GEN);
3327 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
3328 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
3329 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
3330 dwRegRead |= CPU_CCK_LOOPBACK;
3331 else
3332 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __FUNCTION__, priv->LoopbackMode);
3333
3334 write_nic_dword(dev, CPU_GEN, dwRegRead);
3335
3336 //after reset cpu, we need wait for a seconds to write in register.
3337 udelay(500);
3338
3339 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
3340 write_nic_byte_E(dev, 0x5f, (read_nic_byte_E(dev, 0x5f)|0x20));
3341
3342 //Set Hardware
3343 rtl8192_hwconfig(dev);
3344
3345 //turn on Tx/Rx
3346 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
3347
3348 //set IDR0 here
3349 write_nic_dword(dev, MAC0, ((u32*)dev->dev_addr)[0]);
3350 write_nic_word(dev, MAC4, ((u16*)(dev->dev_addr + 4))[0]);
3351
3352 //set RCR
3353 write_nic_dword(dev, RCR, priv->ReceiveConfig);
3354
3355 //Initialize Number of Reserved Pages in Firmware Queue
3356 write_nic_dword(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << RSVD_FW_QUEUE_PAGE_BK_SHIFT |\
3357 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT | \
3358 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT | \
3359 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
3360 write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT |\
3361 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
3362 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW| \
3363 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT
3364// | NUM_OF_PAGE_IN_FW_QUEUE_PUB<<RSVD_FW_QUEUE_PAGE_PUB_SHIFT
3365 );
3366 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
3367
3368 //Set AckTimeout
3369 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
3370 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
3371
3372// RT_TRACE(COMP_INIT, "%s():priv->ResetProgress is %d\n", __FUNCTION__,priv->ResetProgress);
3373 if(priv->ResetProgress == RESET_TYPE_NORESET)
3374 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
3375 if(priv->ResetProgress == RESET_TYPE_NORESET){
3376 CamResetAllEntry(dev);
3377 {
3378 u8 SECR_value = 0x0;
3379 SECR_value |= SCR_TxEncEnable;
3380 SECR_value |= SCR_RxDecEnable;
3381 SECR_value |= SCR_NoSKMC;
3382 write_nic_byte(dev, SECR, SECR_value);
3383 }
3384 }
3385
3386 //Beacon related
3387 write_nic_word(dev, ATIMWND, 2);
3388 write_nic_word(dev, BCN_INTERVAL, 100);
3389
3390 {
3391#define DEFAULT_EDCA 0x005e4332
3392 int i;
3393 for (i=0; i<QOS_QUEUE_NUM; i++)
3394 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
3395 }
3396#ifdef USB_RX_AGGREGATION_SUPPORT
3397 //3 For usb rx firmware aggregation control
3398 if(priv->ResetProgress == RESET_TYPE_NORESET)
3399 {
3400 u32 ulValue;
3401 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
3402 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
3403 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
3404 /*
3405 * If usb rx firmware aggregation is enabled,
3406 * when anyone of three threshold conditions above is reached,
3407 * firmware will send aggregated packet to driver.
3408 */
3409 write_nic_dword(dev, 0x1a8, ulValue);
3410 priv->bCurrentRxAggrEnable = true;
3411 }
3412#endif
3413
3414 rtl8192_phy_configmac(dev);
3415
3416 if (priv->card_8192_version == (u8) VERSION_819xU_A)
3417 {
3418 rtl8192_phy_getTxPower(dev);
3419 rtl8192_phy_setTxPower(dev, priv->chan);
3420 }
3421
3422 //Firmware download
3423 init_status = init_firmware(dev);
3424 if(!init_status)
3425 {
3426 RT_TRACE(COMP_ERR,"ERR!!! %s(): Firmware download is failed\n", __FUNCTION__);
3427 return init_status;
3428 }
3429 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __FUNCTION__);
3430 //
3431#ifdef TO_DO_LIST
3432if(Adapter->ResetProgress == RESET_TYPE_NORESET)
3433 {
3434 if(pMgntInfo->RegRfOff == TRUE)
3435 { // User disable RF via registry.
3436 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
3437 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003438 // Those actions will be discard in MgntActSet_RF_State because of the same state
Jerry Chuang8fc85982009-11-03 07:17:11 -02003439 for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
3440 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3441 }
3442 else if(pMgntInfo->RfOffReason > RF_CHANGE_BY_PS)
3443 { // H/W or S/W RF OFF before sleep.
3444 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
3445 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
3446 }
3447 else
3448 {
3449 pHalData->eRFPowerState = eRfOn;
3450 pMgntInfo->RfOffReason = 0;
3451 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
3452 }
3453 }
3454 else
3455 {
3456 if(pHalData->eRFPowerState == eRfOff)
3457 {
3458 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003459 // Those actions will be discard in MgntActSet_RF_State because of the same state
Jerry Chuang8fc85982009-11-03 07:17:11 -02003460 for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
3461 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3462 }
3463 }
3464#endif
3465 //config RF.
3466 if(priv->ResetProgress == RESET_TYPE_NORESET){
3467 rtl8192_phy_RFConfig(dev);
3468 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __FUNCTION__);
3469 }
3470
3471
3472 if(priv->ieee80211->FwRWRF)
3473 // We can force firmware to do RF-R/W
3474 priv->Rf_Mode = RF_OP_By_FW;
3475 else
3476 priv->Rf_Mode = RF_OP_By_SW_3wire;
3477
3478
3479 rtl8192_phy_updateInitGain(dev);
3480 /*--set CCK and OFDM Block "ON"--*/
3481 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3482 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3483
3484 if(priv->ResetProgress == RESET_TYPE_NORESET)
3485 {
3486 //if D or C cut
3487 u8 tmpvalue = read_nic_byte(dev, 0x301);
3488 if(tmpvalue ==0x03)
3489 {
3490 priv->bDcut = TRUE;
3491 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
3492 }
3493 else
3494 {
3495 priv->bDcut = FALSE;
3496 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
3497 }
3498 dm_initialize_txpower_tracking(dev);
3499
3500 if(priv->bDcut == TRUE)
3501 {
3502 u32 i, TempCCk;
3503 u32 tmpRegA= rtl8192_QueryBBReg(dev,rOFDM0_XATxIQImbalance,bMaskDWord);
3504 // u32 tmpRegC= rtl8192_QueryBBReg(dev,rOFDM0_XCTxIQImbalance,bMaskDWord);
3505 for(i = 0; i<TxBBGainTableLength; i++)
3506 {
3507 if(tmpRegA == priv->txbbgain_table[i].txbbgain_value)
3508 {
3509 priv->rfa_txpowertrackingindex= (u8)i;
3510 priv->rfa_txpowertrackingindex_real= (u8)i;
3511 priv->rfa_txpowertracking_default= priv->rfa_txpowertrackingindex;
3512 break;
3513 }
3514 }
3515
3516 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3517
3518 for(i=0 ; i<CCKTxBBGainTableLength ; i++)
3519 {
3520
3521 if(TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0])
3522 {
3523 priv->cck_present_attentuation_20Mdefault=(u8) i;
3524 break;
3525 }
3526 }
3527 priv->cck_present_attentuation_40Mdefault= 0;
3528 priv->cck_present_attentuation_difference= 0;
3529 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
3530
3531 // pMgntInfo->bTXPowerTracking = FALSE;//TEMPLY DISABLE
3532 }
3533 }
3534 write_nic_byte(dev, 0x87, 0x0);
3535
3536
Jerry Chuang8fc85982009-11-03 07:17:11 -02003537 return init_status;
3538}
3539
3540/* this configures registers for beacon tx and enables it via
3541 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3542 * be used to stop beacon transmission
3543 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003544/***************************************************************************
3545 -------------------------------NET STUFF---------------------------
3546***************************************************************************/
3547
3548static struct net_device_stats *rtl8192_stats(struct net_device *dev)
3549{
3550 struct r8192_priv *priv = ieee80211_priv(dev);
3551
3552 return &priv->ieee80211->stats;
3553}
3554
3555bool
3556HalTxCheckStuck819xUsb(
3557 struct net_device *dev
3558 )
3559{
3560 struct r8192_priv *priv = ieee80211_priv(dev);
3561 u16 RegTxCounter = read_nic_word(dev, 0x128);
3562 bool bStuck = FALSE;
3563 RT_TRACE(COMP_RESET,"%s():RegTxCounter is %d,TxCounter is %d\n",__FUNCTION__,RegTxCounter,priv->TxCounter);
3564 if(priv->TxCounter==RegTxCounter)
3565 bStuck = TRUE;
3566
3567 priv->TxCounter = RegTxCounter;
3568
3569 return bStuck;
3570}
3571
3572/*
3573* <Assumption: RT_TX_SPINLOCK is acquired.>
3574* First added: 2006.11.19 by emily
3575*/
3576RESET_TYPE
3577TxCheckStuck(struct net_device *dev)
3578{
3579 struct r8192_priv *priv = ieee80211_priv(dev);
3580 u8 QueueID;
3581// PRT_TCB pTcb;
3582// u8 ResetThreshold;
3583 bool bCheckFwTxCnt = false;
3584 //unsigned long flags;
3585
3586 //
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003587 // Decide such threshold according to current power save mode
Jerry Chuang8fc85982009-11-03 07:17:11 -02003588 //
3589
3590// RT_TRACE(COMP_RESET, " ==> TxCheckStuck()\n");
3591// PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
3592// spin_lock_irqsave(&priv->ieee80211->lock,flags);
3593 for (QueueID = 0; QueueID<=BEACON_QUEUE;QueueID ++)
3594 {
3595 if(QueueID == TXCMD_QUEUE)
3596 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003597#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
3598 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))
3599#else
3600 if((skb_queue_len(&priv->ieee80211->skb_waitQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_aggQ[QueueID]) == 0))
3601#endif
3602 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003603
3604 bCheckFwTxCnt = true;
3605 }
3606// PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
3607// spin_unlock_irqrestore(&priv->ieee80211->lock,flags);
3608// RT_TRACE(COMP_RESET,"bCheckFwTxCnt is %d\n",bCheckFwTxCnt);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003609 if(bCheckFwTxCnt)
3610 {
3611 if(HalTxCheckStuck819xUsb(dev))
3612 {
3613 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
3614 return RESET_TYPE_SILENT;
3615 }
3616 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003617 return RESET_TYPE_NORESET;
3618}
3619
3620bool
3621HalRxCheckStuck819xUsb(struct net_device *dev)
3622{
3623 u16 RegRxCounter = read_nic_word(dev, 0x130);
3624 struct r8192_priv *priv = ieee80211_priv(dev);
3625 bool bStuck = FALSE;
3626 static u8 rx_chk_cnt = 0;
3627 RT_TRACE(COMP_RESET,"%s(): RegRxCounter is %d,RxCounter is %d\n",__FUNCTION__,RegRxCounter,priv->RxCounter);
3628 // If rssi is small, we should check rx for long time because of bad rx.
3629 // or maybe it will continuous silent reset every 2 seconds.
3630 rx_chk_cnt++;
3631 if(priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5))
3632 {
3633 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
3634 }
3635 else if(priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
3636 ((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_40M) ||
3637 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_20M)) )
3638 {
3639 if(rx_chk_cnt < 2)
3640 {
3641 return bStuck;
3642 }
3643 else
3644 {
3645 rx_chk_cnt = 0;
3646 }
3647 }
3648 else if(((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_40M) ||
3649 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_20M)) &&
3650 priv->undecorated_smoothed_pwdb >= VeryLowRSSI)
3651 {
3652 if(rx_chk_cnt < 4)
3653 {
3654 //DbgPrint("RSSI < %d && RSSI >= %d, no check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
3655 return bStuck;
3656 }
3657 else
3658 {
3659 rx_chk_cnt = 0;
3660 //DbgPrint("RSSI < %d && RSSI >= %d, check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
3661 }
3662 }
3663 else
3664 {
3665 if(rx_chk_cnt < 8)
3666 {
3667 //DbgPrint("RSSI <= %d, no check this time \n", VeryLowRSSI);
3668 return bStuck;
3669 }
3670 else
3671 {
3672 rx_chk_cnt = 0;
3673 //DbgPrint("RSSI <= %d, check this time \n", VeryLowRSSI);
3674 }
3675 }
3676
3677 if(priv->RxCounter==RegRxCounter)
3678 bStuck = TRUE;
3679
3680 priv->RxCounter = RegRxCounter;
3681
3682 return bStuck;
3683}
3684
3685RESET_TYPE
3686RxCheckStuck(struct net_device *dev)
3687{
3688 struct r8192_priv *priv = ieee80211_priv(dev);
3689 //int i;
3690 bool bRxCheck = FALSE;
3691
3692// RT_TRACE(COMP_RESET," ==> RxCheckStuck()\n");
3693 //PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK);
3694
3695 if(priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003696 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003697 //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK);
3698
3699// RT_TRACE(COMP_RESET,"bRxCheck is %d \n",bRxCheck);
3700 if(bRxCheck)
3701 {
3702 if(HalRxCheckStuck819xUsb(dev))
3703 {
3704 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
3705 return RESET_TYPE_SILENT;
3706 }
3707 }
3708 return RESET_TYPE_NORESET;
3709}
3710
3711
3712/**
3713* This function is called by Checkforhang to check whether we should ask OS to reset driver
3714*
3715* \param pAdapter The adapter context for this miniport
3716*
3717* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
3718* to judge whether there is tx stuck.
3719* Note: This function may be required to be rewrite for Vista OS.
3720* <<<Assumption: Tx spinlock has been acquired >>>
3721*
3722* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
3723*/
3724RESET_TYPE
3725rtl819x_ifcheck_resetornot(struct net_device *dev)
3726{
3727 struct r8192_priv *priv = ieee80211_priv(dev);
3728 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
3729 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
3730 RT_RF_POWER_STATE rfState;
3731
3732 rfState = priv->ieee80211->eRFPowerState;
3733
3734 TxResetType = TxCheckStuck(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003735 if( rfState != eRfOff ||
3736 /*ADAPTER_TEST_STATUS_FLAG(Adapter, ADAPTER_STATUS_FW_DOWNLOAD_FAILURE)) &&*/
3737 (priv->ieee80211->iw_mode != IW_MODE_ADHOC))
3738 {
3739 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
3740 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
3741 // if driver is in firmware download failure status, driver should initialize RF in the following
3742 // silent reset procedure Emily, 2008.01.21
3743
3744 // Driver should not check RX stuck in IBSS mode because it is required to
3745 // set Check BSSID in order to send beacon, however, if check BSSID is
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003746 // set, STA cannot hear any packet at all. Emily, 2008.04.12
Jerry Chuang8fc85982009-11-03 07:17:11 -02003747 RxResetType = RxCheckStuck(dev);
3748 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003749 if(TxResetType==RESET_TYPE_NORMAL || RxResetType==RESET_TYPE_NORMAL)
3750 return RESET_TYPE_NORMAL;
3751 else if(TxResetType==RESET_TYPE_SILENT || RxResetType==RESET_TYPE_SILENT){
3752 RT_TRACE(COMP_RESET,"%s():silent reset\n",__FUNCTION__);
3753 return RESET_TYPE_SILENT;
3754 }
3755 else
3756 return RESET_TYPE_NORESET;
3757
3758}
3759
3760void rtl8192_cancel_deferred_work(struct r8192_priv* priv);
3761int _rtl8192_up(struct net_device *dev);
3762int rtl8192_close(struct net_device *dev);
3763
3764
3765
3766void
3767CamRestoreAllEntry( struct net_device *dev)
3768{
3769 u8 EntryId = 0;
3770 struct r8192_priv *priv = ieee80211_priv(dev);
3771 u8* MacAddr = priv->ieee80211->current_network.bssid;
3772
3773 static u8 CAM_CONST_ADDR[4][6] = {
3774 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3775 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
3776 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
3777 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
3778 static u8 CAM_CONST_BROAD[] =
3779 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3780
3781 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
3782
3783
3784 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40)||
3785 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104))
3786 {
3787
3788 for(EntryId=0; EntryId<4; EntryId++)
3789 {
3790 {
3791 MacAddr = CAM_CONST_ADDR[EntryId];
3792 setKey(dev,
3793 EntryId ,
3794 EntryId,
3795 priv->ieee80211->pairwise_key_type,
3796 MacAddr,
3797 0,
3798 NULL);
3799 }
3800 }
3801
3802 }
3803 else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP)
3804 {
3805
3806 {
3807 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3808 setKey(dev,
3809 4,
3810 0,
3811 priv->ieee80211->pairwise_key_type,
3812 (u8*)dev->dev_addr,
3813 0,
3814 NULL);
3815 else
3816 setKey(dev,
3817 4,
3818 0,
3819 priv->ieee80211->pairwise_key_type,
3820 MacAddr,
3821 0,
3822 NULL);
3823 }
3824 }
3825 else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP)
3826 {
3827
3828 {
3829 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3830 setKey(dev,
3831 4,
3832 0,
3833 priv->ieee80211->pairwise_key_type,
3834 (u8*)dev->dev_addr,
3835 0,
3836 NULL);
3837 else
3838 setKey(dev,
3839 4,
3840 0,
3841 priv->ieee80211->pairwise_key_type,
3842 MacAddr,
3843 0,
3844 NULL);
3845 }
3846 }
3847
3848
3849
3850 if(priv->ieee80211->group_key_type == KEY_TYPE_TKIP)
3851 {
3852 MacAddr = CAM_CONST_BROAD;
3853 for(EntryId=1 ; EntryId<4 ; EntryId++)
3854 {
3855 {
3856 setKey(dev,
3857 EntryId,
3858 EntryId,
3859 priv->ieee80211->group_key_type,
3860 MacAddr,
3861 0,
3862 NULL);
3863 }
3864 }
3865 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3866 setKey(dev,
3867 0,
3868 0,
3869 priv->ieee80211->group_key_type,
3870 CAM_CONST_ADDR[0],
3871 0,
3872 NULL);
3873 }
3874 else if(priv->ieee80211->group_key_type == KEY_TYPE_CCMP)
3875 {
3876 MacAddr = CAM_CONST_BROAD;
3877 for(EntryId=1; EntryId<4 ; EntryId++)
3878 {
3879 {
3880 setKey(dev,
3881 EntryId ,
3882 EntryId,
3883 priv->ieee80211->group_key_type,
3884 MacAddr,
3885 0,
3886 NULL);
3887 }
3888 }
3889
3890 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3891 setKey(dev,
3892 0 ,
3893 0,
3894 priv->ieee80211->group_key_type,
3895 CAM_CONST_ADDR[0],
3896 0,
3897 NULL);
3898 }
3899}
3900//////////////////////////////////////////////////////////////
3901// This function is used to fix Tx/Rx stop bug temporarily.
3902// This function will do "system reset" to NIC when Tx or Rx is stuck.
3903// The method checking Tx/Rx stuck of this function is supported by FW,
3904// which reports Tx and Rx counter to register 0x128 and 0x130.
3905//////////////////////////////////////////////////////////////
3906void
3907rtl819x_ifsilentreset(struct net_device *dev)
3908{
3909 //OCTET_STRING asocpdu;
3910 struct r8192_priv *priv = ieee80211_priv(dev);
3911 u8 reset_times = 0;
3912 int reset_status = 0;
3913 struct ieee80211_device *ieee = priv->ieee80211;
3914
3915
3916 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
3917 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
3918
3919 if(priv->ResetProgress==RESET_TYPE_NORESET)
3920 {
3921RESET_START:
3922
3923 RT_TRACE(COMP_RESET,"=========>Reset progress!! \n");
3924
3925 // Set the variable for reset.
3926 priv->ResetProgress = RESET_TYPE_SILENT;
3927// rtl8192_close(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003928 down(&priv->wx_sem);
3929 if(priv->up == 0)
3930 {
3931 RT_TRACE(COMP_ERR,"%s():the driver is not up! return\n",__FUNCTION__);
3932 up(&priv->wx_sem);
3933 return ;
3934 }
3935 priv->up = 0;
3936 RT_TRACE(COMP_RESET,"%s():======>start to down the driver\n",__FUNCTION__);
3937// if(!netif_queue_stopped(dev))
3938// netif_stop_queue(dev);
3939
3940 rtl8192_rtx_disable(dev);
3941 rtl8192_cancel_deferred_work(priv);
3942 deinit_hal_dm(dev);
3943 del_timer_sync(&priv->watch_dog_timer);
3944
3945 ieee->sync_scan_hurryup = 1;
3946 if(ieee->state == IEEE80211_LINKED)
3947 {
3948 down(&ieee->wx_sem);
3949 printk("ieee->state is IEEE80211_LINKED\n");
3950 ieee80211_stop_send_beacons(priv->ieee80211);
3951 del_timer_sync(&ieee->associate_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003952 cancel_delayed_work(&ieee->associate_retry_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003953 ieee80211_stop_scan(ieee);
3954 netif_carrier_off(dev);
3955 up(&ieee->wx_sem);
3956 }
3957 else{
3958 printk("ieee->state is NOT LINKED\n");
3959 ieee80211_softmac_stop_protocol(priv->ieee80211); }
3960 up(&priv->wx_sem);
3961 RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__);
3962 //rtl8192_irq_disable(dev);
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003963 RT_TRACE(COMP_RESET,"%s():===========>start up the driver\n",__FUNCTION__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003964 reset_status = _rtl8192_up(dev);
3965
3966 RT_TRACE(COMP_RESET,"%s():<===========up process is finished\n",__FUNCTION__);
3967 if(reset_status == -EAGAIN)
3968 {
3969 if(reset_times < 3)
3970 {
3971 reset_times++;
3972 goto RESET_START;
3973 }
3974 else
3975 {
3976 RT_TRACE(COMP_ERR," ERR!!! %s(): Reset Failed!!\n", __FUNCTION__);
3977 }
3978 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003979 ieee->is_silent_reset = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003980 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003981 if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA)
3982 {
3983 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3984
Jerry Chuang8fc85982009-11-03 07:17:11 -02003985 queue_work(ieee->wq, &ieee->associate_complete_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003986
3987 }
3988 else if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC)
3989 {
3990 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3991 ieee->link_change(ieee->dev);
3992
3993 // notify_wx_assoc_event(ieee);
3994
3995 ieee80211_start_send_beacons(ieee);
3996
3997 if (ieee->data_hard_resume)
3998 ieee->data_hard_resume(ieee->dev);
3999 netif_carrier_on(ieee->dev);
4000 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004001
4002 CamRestoreAllEntry(dev);
4003
4004 priv->ResetProgress = RESET_TYPE_NORESET;
4005 priv->reset_count++;
4006
4007 priv->bForcedSilentReset =false;
4008 priv->bResetInProgress = false;
4009
4010 // For test --> force write UFWP.
4011 write_nic_byte(dev, UFWP, 1);
4012 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004013 }
4014}
4015
4016void CAM_read_entry(
4017 struct net_device *dev,
4018 u32 iIndex
4019)
4020{
4021 u32 target_command=0;
4022 u32 target_content=0;
4023 u8 entry_i=0;
4024 u32 ulStatus;
4025 s32 i=100;
4026// printk("=======>start read CAM\n");
4027 for(entry_i=0;entry_i<CAM_CONTENT_COUNT;entry_i++)
4028 {
4029 // polling bit, and No Write enable, and address
4030 target_command= entry_i+CAM_CONTENT_COUNT*iIndex;
4031 target_command= target_command | BIT31;
4032
4033 //Check polling bit is clear
4034// mdelay(1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004035 while((i--)>=0)
4036 {
4037 ulStatus = read_nic_dword(dev, RWCAM);
4038 if(ulStatus & BIT31){
4039 continue;
4040 }
4041 else{
4042 break;
4043 }
4044 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004045 write_nic_dword(dev, RWCAM, target_command);
4046 RT_TRACE(COMP_SEC,"CAM_read_entry(): WRITE A0: %x \n",target_command);
4047 // printk("CAM_read_entry(): WRITE A0: %lx \n",target_command);
4048 target_content = read_nic_dword(dev, RCAMO);
4049 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n",target_content);
4050 // printk("CAM_read_entry(): WRITE A8: %lx \n",target_content);
4051 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004052 printk("\n");
4053}
4054
4055void rtl819x_update_rxcounts(
4056 struct r8192_priv *priv,
4057 u32* TotalRxBcnNum,
4058 u32* TotalRxDataNum
4059)
4060{
4061 u16 SlotIndex;
4062 u8 i;
4063
4064 *TotalRxBcnNum = 0;
4065 *TotalRxDataNum = 0;
4066
4067 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
4068 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
4069 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
4070 for( i=0; i<priv->ieee80211->LinkDetectInfo.SlotNum; i++ ){
4071 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
4072 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
4073 }
4074}
4075
4076
Jerry Chuang8fc85982009-11-03 07:17:11 -02004077extern void rtl819x_watchdog_wqcallback(struct work_struct *work)
4078{
4079 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
4080 struct r8192_priv *priv = container_of(dwork,struct r8192_priv,watch_dog_wq);
4081 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004082 struct ieee80211_device* ieee = priv->ieee80211;
4083 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004084 static u8 check_reset_cnt=0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004085 bool bBusyTraffic = false;
4086
4087 if(!priv->up)
4088 return;
4089 hal_dm_watchdog(dev);
4090
4091 {//to get busy traffic condition
4092 if(ieee->state == IEEE80211_LINKED)
4093 {
4094 if( ieee->LinkDetectInfo.NumRxOkInPeriod> 666 ||
4095 ieee->LinkDetectInfo.NumTxOkInPeriod> 666 ) {
4096 bBusyTraffic = true;
4097 }
4098 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
4099 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
4100 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
4101 }
4102 }
4103 //added by amy for AP roaming
4104 {
4105 if(priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA)
4106 {
4107 u32 TotalRxBcnNum = 0;
4108 u32 TotalRxDataNum = 0;
4109
4110 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
4111 if((TotalRxBcnNum+TotalRxDataNum) == 0)
4112 {
4113 #ifdef TODO
4114 if(rfState == eRfOff)
4115 RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__);
4116 #endif
4117 printk("===>%s(): AP is power off,connect another one\n",__FUNCTION__);
4118 // Dot11d_Reset(dev);
4119 priv->ieee80211->state = IEEE80211_ASSOCIATING;
4120 notify_wx_assoc_event(priv->ieee80211);
4121 RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
4122 priv->ieee80211->link_change(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004123 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004124
4125 }
4126 }
4127 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod=0;
4128 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod=0;
4129 }
4130// CAM_read_entry(dev,4);
4131 //check if reset the driver
4132 if(check_reset_cnt++ >= 3)
4133 {
4134 ResetType = rtl819x_ifcheck_resetornot(dev);
4135 check_reset_cnt = 3;
4136 //DbgPrint("Start to check silent reset\n");
4137 }
4138 // 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);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004139 if( (priv->force_reset) || (priv->ResetProgress==RESET_TYPE_NORESET &&
4140 (priv->bForcedSilentReset ||
4141 (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT)))) // This is control by OID set in Pomelo
4142 {
4143 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);
4144 rtl819x_ifsilentreset(dev);
4145 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004146 priv->force_reset = false;
4147 priv->bForcedSilentReset = false;
4148 priv->bResetInProgress = false;
4149 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
4150
4151}
4152
4153void watch_dog_timer_callback(unsigned long data)
4154{
4155 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004156 //printk("===============>watch_dog timer\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02004157 queue_delayed_work(priv->priv_wq,&priv->watch_dog_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004158 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004159}
4160int _rtl8192_up(struct net_device *dev)
4161{
4162 struct r8192_priv *priv = ieee80211_priv(dev);
4163 //int i;
4164 int init_status = 0;
4165 priv->up=1;
4166 priv->ieee80211->ieee_up=1;
4167 RT_TRACE(COMP_INIT, "Bringing up iface");
4168 init_status = rtl8192_adapter_start(dev);
4169 if(!init_status)
4170 {
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004171 RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization failed!\n", __FUNCTION__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004172 priv->up=priv->ieee80211->ieee_up = 0;
4173 return -EAGAIN;
4174 }
4175 RT_TRACE(COMP_INIT, "start adapter finished\n");
4176 rtl8192_rx_enable(dev);
4177// rtl8192_tx_enable(dev);
4178 if(priv->ieee80211->state != IEEE80211_LINKED)
4179 ieee80211_softmac_start_protocol(priv->ieee80211);
4180 ieee80211_reset_queue(priv->ieee80211);
4181 watch_dog_timer_callback((unsigned long) dev);
4182 if(!netif_queue_stopped(dev))
4183 netif_start_queue(dev);
4184 else
4185 netif_wake_queue(dev);
4186
4187 return 0;
4188}
4189
4190
4191int rtl8192_open(struct net_device *dev)
4192{
4193 struct r8192_priv *priv = ieee80211_priv(dev);
4194 int ret;
4195 down(&priv->wx_sem);
4196 ret = rtl8192_up(dev);
4197 up(&priv->wx_sem);
4198 return ret;
4199
4200}
4201
4202
4203int rtl8192_up(struct net_device *dev)
4204{
4205 struct r8192_priv *priv = ieee80211_priv(dev);
4206
4207 if (priv->up == 1) return -1;
4208
4209 return _rtl8192_up(dev);
4210}
4211
4212
4213int rtl8192_close(struct net_device *dev)
4214{
4215 struct r8192_priv *priv = ieee80211_priv(dev);
4216 int ret;
4217
4218 down(&priv->wx_sem);
4219
4220 ret = rtl8192_down(dev);
4221
4222 up(&priv->wx_sem);
4223
4224 return ret;
4225
4226}
4227
4228int rtl8192_down(struct net_device *dev)
4229{
4230 struct r8192_priv *priv = ieee80211_priv(dev);
4231 int i;
4232
4233 if (priv->up == 0) return -1;
4234
4235 priv->up=0;
4236 priv->ieee80211->ieee_up = 0;
4237 RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
4238/* FIXME */
4239 if (!netif_queue_stopped(dev))
4240 netif_stop_queue(dev);
4241
4242 rtl8192_rtx_disable(dev);
4243 //rtl8192_irq_disable(dev);
4244
4245 /* Tx related queue release */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004246 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
4247 skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
4248 }
4249 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
4250 skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
4251 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004252
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004253 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
4254 skb_queue_purge(&priv->ieee80211->skb_drv_aggQ [i]);
4255 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004256
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004257 //as cancel_delayed_work will del work->timer, so if work is not defined as struct delayed_work, it will corrupt
Jerry Chuang8fc85982009-11-03 07:17:11 -02004258// flush_scheduled_work();
4259 rtl8192_cancel_deferred_work(priv);
4260 deinit_hal_dm(dev);
4261 del_timer_sync(&priv->watch_dog_timer);
4262
4263
4264 ieee80211_softmac_stop_protocol(priv->ieee80211);
4265 memset(&priv->ieee80211->current_network, 0 , offsetof(struct ieee80211_network, list));
4266 RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
4267
4268 return 0;
4269}
4270
4271
4272void rtl8192_commit(struct net_device *dev)
4273{
4274 struct r8192_priv *priv = ieee80211_priv(dev);
4275 int reset_status = 0;
4276 //u8 reset_times = 0;
4277 if (priv->up == 0) return ;
4278 priv->up = 0;
4279
4280 rtl8192_cancel_deferred_work(priv);
4281 del_timer_sync(&priv->watch_dog_timer);
4282 //cancel_delayed_work(&priv->SwChnlWorkItem);
4283
4284 ieee80211_softmac_stop_protocol(priv->ieee80211);
4285
4286 //rtl8192_irq_disable(dev);
4287 rtl8192_rtx_disable(dev);
4288 reset_status = _rtl8192_up(dev);
4289
4290}
4291
4292/*
4293void rtl8192_restart(struct net_device *dev)
4294{
4295 struct r8192_priv *priv = ieee80211_priv(dev);
4296*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02004297void rtl8192_restart(struct work_struct *work)
4298{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004299 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
4300 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004301
4302 down(&priv->wx_sem);
4303
4304 rtl8192_commit(dev);
4305
4306 up(&priv->wx_sem);
4307}
4308
4309static void r8192_set_multicast(struct net_device *dev)
4310{
4311 struct r8192_priv *priv = ieee80211_priv(dev);
4312 short promisc;
4313
4314 //down(&priv->wx_sem);
4315
4316 /* FIXME FIXME */
4317
4318 promisc = (dev->flags & IFF_PROMISC) ? 1:0;
4319
4320 if (promisc != priv->promisc)
4321 // rtl8192_commit(dev);
4322
4323 priv->promisc = promisc;
4324
4325 //schedule_work(&priv->reset_wq);
4326 //up(&priv->wx_sem);
4327}
4328
4329
4330int r8192_set_mac_adr(struct net_device *dev, void *mac)
4331{
4332 struct r8192_priv *priv = ieee80211_priv(dev);
4333 struct sockaddr *addr = mac;
4334
4335 down(&priv->wx_sem);
4336
4337 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
4338
Jerry Chuang8fc85982009-11-03 07:17:11 -02004339 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004340 up(&priv->wx_sem);
4341
4342 return 0;
4343}
4344
4345/* based on ipw2200 driver */
4346int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
4347{
4348 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4349 struct iwreq *wrq = (struct iwreq *)rq;
4350 int ret=-1;
4351 struct ieee80211_device *ieee = priv->ieee80211;
4352 u32 key[4];
4353 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
4354 struct iw_point *p = &wrq->u.data;
4355 struct ieee_param *ipw = NULL;//(struct ieee_param *)wrq->u.data.pointer;
4356
4357 down(&priv->wx_sem);
4358
4359
4360 if (p->length < sizeof(struct ieee_param) || !p->pointer){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004361 ret = -EINVAL;
4362 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004363 }
4364
Julia Lawall32414872010-05-11 20:26:57 +02004365 ipw = kmalloc(p->length, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004366 if (ipw == NULL){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004367 ret = -ENOMEM;
4368 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004369 }
4370 if (copy_from_user(ipw, p->pointer, p->length)) {
4371 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004372 ret = -EFAULT;
4373 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004374 }
4375
4376 switch (cmd) {
4377 case RTL_IOCTL_WPA_SUPPLICANT:
4378 //parse here for HW security
4379 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION)
4380 {
4381 if (ipw->u.crypt.set_tx)
4382 {
4383 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
4384 ieee->pairwise_key_type = KEY_TYPE_CCMP;
4385 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
4386 ieee->pairwise_key_type = KEY_TYPE_TKIP;
4387 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
4388 {
4389 if (ipw->u.crypt.key_len == 13)
4390 ieee->pairwise_key_type = KEY_TYPE_WEP104;
4391 else if (ipw->u.crypt.key_len == 5)
4392 ieee->pairwise_key_type = KEY_TYPE_WEP40;
4393 }
4394 else
4395 ieee->pairwise_key_type = KEY_TYPE_NA;
4396
4397 if (ieee->pairwise_key_type)
4398 {
4399 memcpy((u8*)key, ipw->u.crypt.key, 16);
4400 EnableHWSecurityConfig8192(dev);
4401 //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!
4402 //added by WB.
4403 setKey(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
4404 if (ieee->auth_mode != 2)
4405 setKey(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
4406 }
4407 }
4408 else //if (ipw->u.crypt.idx) //group key use idx > 0
4409 {
4410 memcpy((u8*)key, ipw->u.crypt.key, 16);
4411 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
4412 ieee->group_key_type= KEY_TYPE_CCMP;
4413 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
4414 ieee->group_key_type = KEY_TYPE_TKIP;
4415 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
4416 {
4417 if (ipw->u.crypt.key_len == 13)
4418 ieee->group_key_type = KEY_TYPE_WEP104;
4419 else if (ipw->u.crypt.key_len == 5)
4420 ieee->group_key_type = KEY_TYPE_WEP40;
4421 }
4422 else
4423 ieee->group_key_type = KEY_TYPE_NA;
4424
4425 if (ieee->group_key_type)
4426 {
4427 setKey( dev,
4428 ipw->u.crypt.idx,
4429 ipw->u.crypt.idx, //KeyIndex
4430 ieee->group_key_type, //KeyType
4431 broadcast_addr, //MacAddr
4432 0, //DefaultKey
4433 key); //KeyContent
4434 }
4435 }
4436 }
4437#ifdef JOHN_HWSEC_DEBUG
4438 //john's test 0711
4439 printk("@@ wrq->u pointer = ");
4440 for(i=0;i<wrq->u.data.length;i++){
4441 if(i%10==0) printk("\n");
4442 printk( "%8x|", ((u32*)wrq->u.data.pointer)[i] );
4443 }
4444 printk("\n");
4445#endif /*JOHN_HWSEC_DEBUG*/
4446 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
4447 break;
4448
4449 default:
4450 ret = -EOPNOTSUPP;
4451 break;
4452 }
4453 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004454 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004455out:
4456 up(&priv->wx_sem);
4457 return ret;
4458}
4459
4460u8 HwRateToMRate90(bool bIsHT, u8 rate)
4461{
4462 u8 ret_rate = 0xff;
4463
4464 if(!bIsHT) {
4465 switch(rate) {
4466 case DESC90_RATE1M: ret_rate = MGN_1M; break;
4467 case DESC90_RATE2M: ret_rate = MGN_2M; break;
4468 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
4469 case DESC90_RATE11M: ret_rate = MGN_11M; break;
4470 case DESC90_RATE6M: ret_rate = MGN_6M; break;
4471 case DESC90_RATE9M: ret_rate = MGN_9M; break;
4472 case DESC90_RATE12M: ret_rate = MGN_12M; break;
4473 case DESC90_RATE18M: ret_rate = MGN_18M; break;
4474 case DESC90_RATE24M: ret_rate = MGN_24M; break;
4475 case DESC90_RATE36M: ret_rate = MGN_36M; break;
4476 case DESC90_RATE48M: ret_rate = MGN_48M; break;
4477 case DESC90_RATE54M: ret_rate = MGN_54M; break;
4478
4479 default:
4480 ret_rate = 0xff;
4481 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
4482 break;
4483 }
4484
4485 } else {
4486 switch(rate) {
4487 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
4488 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
4489 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
4490 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
4491 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
4492 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
4493 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
4494 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
4495 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
4496 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
4497 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
4498 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
4499 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
4500 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
4501 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
4502 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
4503 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
4504
4505 default:
4506 ret_rate = 0xff;
4507 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n",rate, bIsHT);
4508 break;
4509 }
4510 }
4511
4512 return ret_rate;
4513}
4514
4515/**
4516 * Function: UpdateRxPktTimeStamp
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004517 * Overview: Record the TSF time stamp when receiving a packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02004518 *
4519 * Input:
4520 * PADAPTER Adapter
4521 * PRT_RFD pRfd,
4522 *
4523 * Output:
4524 * PRT_RFD pRfd
4525 * (pRfd->Status.TimeStampHigh is updated)
4526 * (pRfd->Status.TimeStampLow is updated)
4527 * Return:
4528 * None
4529 */
4530void UpdateRxPktTimeStamp8190 (struct net_device *dev, struct ieee80211_rx_stats *stats)
4531{
4532 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4533
4534 if(stats->bIsAMPDU && !stats->bFirstMPDU) {
4535 stats->mac_time[0] = priv->LastRxDescTSFLow;
4536 stats->mac_time[1] = priv->LastRxDescTSFHigh;
4537 } else {
4538 priv->LastRxDescTSFLow = stats->mac_time[0];
4539 priv->LastRxDescTSFHigh = stats->mac_time[1];
4540 }
4541}
4542
4543//by amy 080606
4544
4545long rtl819x_translate_todbm(u8 signal_strength_index )// 0-100 index.
4546{
4547 long signal_power; // in dBm.
4548
4549 // Translate to dBm (x=0.5y-95).
4550 signal_power = (long)((signal_strength_index + 1) >> 1);
4551 signal_power -= 95;
4552
4553 return signal_power;
4554}
4555
4556
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004557/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
Jerry Chuang8fc85982009-11-03 07:17:11 -02004558 be a local static. Otherwise, it may increase when we return from S3/S4. The
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004559 value will be kept in memory or disk. Declare the value in the adaptor
4560 and it will be reinitialized when returned from S3/S4. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004561void rtl8192_process_phyinfo(struct r8192_priv * priv,u8* buffer, struct ieee80211_rx_stats * pprevious_stats, struct ieee80211_rx_stats * pcurrent_stats)
4562{
4563 bool bcheck = false;
4564 u8 rfpath;
4565 u32 nspatial_stream, tmp_val;
4566 //u8 i;
4567 static u32 slide_rssi_index=0, slide_rssi_statistics=0;
4568 static u32 slide_evm_index=0, slide_evm_statistics=0;
4569 static u32 last_rssi=0, last_evm=0;
4570
4571 static u32 slide_beacon_adc_pwdb_index=0, slide_beacon_adc_pwdb_statistics=0;
4572 static u32 last_beacon_adc_pwdb=0;
4573
4574 struct ieee80211_hdr_3addr *hdr;
4575 u16 sc ;
4576 unsigned int frag,seq;
4577 hdr = (struct ieee80211_hdr_3addr *)buffer;
4578 sc = le16_to_cpu(hdr->seq_ctl);
4579 frag = WLAN_GET_SEQ_FRAG(sc);
4580 seq = WLAN_GET_SEQ_SEQ(sc);
4581 //cosa add 04292008 to record the sequence number
4582 pcurrent_stats->Seq_Num = seq;
4583 //
4584 // Check whether we should take the previous packet into accounting
4585 //
4586 if(!pprevious_stats->bIsAMPDU)
4587 {
4588 // if previous packet is not aggregated packet
4589 bcheck = true;
4590 }else
4591 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004592 }
4593
4594
4595 if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX)
4596 {
4597 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
4598 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
4599 priv->stats.slide_rssi_total -= last_rssi;
4600 }
4601 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
4602
4603 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
4604 if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
4605 slide_rssi_index = 0;
4606
4607 // <1> Showed on UI for user, in dbm
4608 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
4609 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
4610 pcurrent_stats->rssi = priv->stats.signal_strength;
4611 //
4612 // If the previous packet does not match the criteria, neglect it
4613 //
4614 if(!pprevious_stats->bPacketMatchBSSID)
4615 {
4616 if(!pprevious_stats->bToSelfBA)
4617 return;
4618 }
4619
4620 if(!bcheck)
4621 return;
4622
4623
4624 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
4625
4626 //
4627 // Check RSSI
4628 //
4629 priv->stats.num_process_phyinfo++;
4630
4631 /* record the general signal strength to the sliding window. */
4632
4633
4634 // <2> Showed on UI for engineering
4635 // hardware does not provide rssi information for each rf path in CCK
4636 if(!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA))
4637 {
4638 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++)
4639 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004640 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
4641 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004642
4643 //Fixed by Jacken 2008-03-20
4644 if(priv->stats.rx_rssi_percentage[rfpath] == 0)
4645 {
4646 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
4647 //DbgPrint("MIMO RSSI initialize \n");
4648 }
4649 if(pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath])
4650 {
4651 priv->stats.rx_rssi_percentage[rfpath] =
4652 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
4653 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
4654 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
4655 }
4656 else
4657 {
4658 priv->stats.rx_rssi_percentage[rfpath] =
4659 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
4660 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
4661 }
4662 RT_TRACE(COMP_DBG,"priv->stats.rx_rssi_percentage[rfPath] = %d \n" ,priv->stats.rx_rssi_percentage[rfpath] );
4663 }
4664 }
4665
4666
4667 //
4668 // Check PWDB.
4669 //
4670 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
4671 pprevious_stats->bIsCCK? "CCK": "OFDM",
4672 pprevious_stats->RxPWDBAll);
4673
4674 if(pprevious_stats->bPacketBeacon)
4675 {
4676/* record the beacon pwdb to the sliding window. */
4677 if(slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX)
4678 {
4679 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
4680 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
4681 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
4682 //DbgPrint("slide_beacon_adc_pwdb_index = %d, last_beacon_adc_pwdb = %d, Adapter->RxStats.Slide_Beacon_Total = %d\n",
4683 // slide_beacon_adc_pwdb_index, last_beacon_adc_pwdb, Adapter->RxStats.Slide_Beacon_Total);
4684 }
4685 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
4686 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
4687 //DbgPrint("slide_beacon_adc_pwdb_index = %d, pPreviousRfd->Status.RxPWDBAll = %d\n", slide_beacon_adc_pwdb_index, pPreviousRfd->Status.RxPWDBAll);
4688 slide_beacon_adc_pwdb_index++;
4689 if(slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
4690 slide_beacon_adc_pwdb_index = 0;
4691 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
4692 if(pprevious_stats->RxPWDBAll >= 3)
4693 pprevious_stats->RxPWDBAll -= 3;
4694 }
4695
4696 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
4697 pprevious_stats->bIsCCK? "CCK": "OFDM",
4698 pprevious_stats->RxPWDBAll);
4699
4700
4701 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
4702 {
4703 if(priv->undecorated_smoothed_pwdb < 0) // initialize
4704 {
4705 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
4706 //DbgPrint("First pwdb initialize \n");
4707 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004708 if(pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb)
4709 {
4710 priv->undecorated_smoothed_pwdb =
4711 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4712 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
4713 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
4714 }
4715 else
4716 {
4717 priv->undecorated_smoothed_pwdb =
4718 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4719 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
4720 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004721
4722 }
4723
4724 //
4725 // Check EVM
4726 //
4727 /* record the general EVM to the sliding window. */
4728 if(pprevious_stats->SignalQuality == 0)
4729 {
4730 }
4731 else
4732 {
4733 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA){
4734 if(slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX){
4735 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
4736 last_evm = priv->stats.slide_evm[slide_evm_index];
4737 priv->stats.slide_evm_total -= last_evm;
4738 }
4739
4740 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
4741
4742 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
4743 if(slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
4744 slide_evm_index = 0;
4745
4746 // <1> Showed on UI for user, in percentage.
4747 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
4748 priv->stats.signal_quality = tmp_val;
4749 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
4750 priv->stats.last_signal_strength_inpercent = tmp_val;
4751 }
4752
4753 // <2> Showed on UI for engineering
4754 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
4755 {
4756 for(nspatial_stream = 0; nspatial_stream<2 ; nspatial_stream++) // 2 spatial stream
4757 {
4758 if(pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1)
4759 {
4760 if(priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
4761 {
4762 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
4763 }
4764 priv->stats.rx_evm_percentage[nspatial_stream] =
4765 ( (priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
4766 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
4767 }
4768 }
4769 }
4770 }
4771
4772
4773}
4774
4775/*-----------------------------------------------------------------------------
4776 * Function: rtl819x_query_rxpwrpercentage()
4777 *
4778 * Overview:
4779 *
4780 * Input: char antpower
4781 *
4782 * Output: NONE
4783 *
4784 * Return: 0-100 percentage
4785 *
4786 * Revised History:
4787 * When Who Remark
4788 * 05/26/2008 amy Create Version 0 porting from windows code.
4789 *
4790 *---------------------------------------------------------------------------*/
4791static u8 rtl819x_query_rxpwrpercentage(
4792 char antpower
4793 )
4794{
4795 if ((antpower <= -100) || (antpower >= 20))
4796 {
4797 return 0;
4798 }
4799 else if (antpower >= 0)
4800 {
4801 return 100;
4802 }
4803 else
4804 {
4805 return (100+antpower);
4806 }
4807
4808} /* QueryRxPwrPercentage */
4809
4810static u8
4811rtl819x_evm_dbtopercentage(
4812 char value
4813 )
4814{
4815 char ret_val;
4816
4817 ret_val = value;
4818
4819 if(ret_val >= 0)
4820 ret_val = 0;
4821 if(ret_val <= -33)
4822 ret_val = -33;
4823 ret_val = 0 - ret_val;
4824 ret_val*=3;
4825 if(ret_val == 99)
4826 ret_val = 100;
4827 return(ret_val);
4828}
4829//
4830// Description:
4831// We want good-looking for signal strength/quality
4832// 2007/7/19 01:09, by cosa.
4833//
4834long
4835rtl819x_signal_scale_mapping(
4836 long currsig
4837 )
4838{
4839 long retsig;
4840
4841 // Step 1. Scale mapping.
4842 if(currsig >= 61 && currsig <= 100)
4843 {
4844 retsig = 90 + ((currsig - 60) / 4);
4845 }
4846 else if(currsig >= 41 && currsig <= 60)
4847 {
4848 retsig = 78 + ((currsig - 40) / 2);
4849 }
4850 else if(currsig >= 31 && currsig <= 40)
4851 {
4852 retsig = 66 + (currsig - 30);
4853 }
4854 else if(currsig >= 21 && currsig <= 30)
4855 {
4856 retsig = 54 + (currsig - 20);
4857 }
4858 else if(currsig >= 5 && currsig <= 20)
4859 {
4860 retsig = 42 + (((currsig - 5) * 2) / 3);
4861 }
4862 else if(currsig == 4)
4863 {
4864 retsig = 36;
4865 }
4866 else if(currsig == 3)
4867 {
4868 retsig = 27;
4869 }
4870 else if(currsig == 2)
4871 {
4872 retsig = 18;
4873 }
4874 else if(currsig == 1)
4875 {
4876 retsig = 9;
4877 }
4878 else
4879 {
4880 retsig = currsig;
4881 }
4882
4883 return retsig;
4884}
4885
4886static void rtl8192_query_rxphystatus(
4887 struct r8192_priv * priv,
4888 struct ieee80211_rx_stats * pstats,
4889 rx_drvinfo_819x_usb * pdrvinfo,
4890 struct ieee80211_rx_stats * precord_stats,
4891 bool bpacket_match_bssid,
4892 bool bpacket_toself,
4893 bool bPacketBeacon,
4894 bool bToSelfBA
4895 )
4896{
4897 //PRT_RFD_STATUS pRtRfdStatus = &(pRfd->Status);
4898 phy_sts_ofdm_819xusb_t* pofdm_buf;
4899 phy_sts_cck_819xusb_t * pcck_buf;
4900 phy_ofdm_rx_status_rxsc_sgien_exintfflag* prxsc;
4901 u8 *prxpkt;
4902 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
4903 char rx_pwr[4], rx_pwr_all=0;
4904 //long rx_avg_pwr = 0;
4905 char rx_snrX, rx_evmX;
4906 u8 evm, pwdb_all;
4907 u32 RSSI, total_rssi=0;//, total_evm=0;
4908// long signal_strength_index = 0;
4909 u8 is_cck_rate=0;
4910 u8 rf_rx_num = 0;
4911
4912
4913 priv->stats.numqry_phystatus++;
4914
4915 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4916
4917 // Record it for next packet processing
4918 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4919 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4920 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
4921 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;//RX_HAL_IS_CCK_RATE(pDrvInfo);
4922 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4923 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4924
4925 prxpkt = (u8*)pdrvinfo;
4926
4927 /* Move pointer to the 16th bytes. Phy status start address. */
4928 prxpkt += sizeof(rx_drvinfo_819x_usb);
4929
4930 /* Initial the cck and ofdm buffer pointer */
4931 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
4932 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
4933
4934 pstats->RxMIMOSignalQuality[0] = -1;
4935 pstats->RxMIMOSignalQuality[1] = -1;
4936 precord_stats->RxMIMOSignalQuality[0] = -1;
4937 precord_stats->RxMIMOSignalQuality[1] = -1;
4938
4939 if(is_cck_rate)
4940 {
4941 //
4942 // (1)Hardware does not provide RSSI for CCK
4943 //
4944
4945 //
4946 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4947 //
4948 u8 report;//, cck_agc_rpt;
4949
4950 priv->stats.numqry_phystatusCCK++;
4951
4952 if(!priv->bCckHighPower)
4953 {
4954 report = pcck_buf->cck_agc_rpt & 0xc0;
4955 report = report>>6;
4956 switch(report)
4957 {
4958 //Fixed by Jacken from Bryant 2008-03-20
4959 //Original value is -38 , -26 , -14 , -2
4960 //Fixed value is -35 , -23 , -11 , 6
4961 case 0x3:
4962 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4963 break;
4964 case 0x2:
4965 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4966 break;
4967 case 0x1:
4968 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4969 break;
4970 case 0x0:
4971 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
4972 break;
4973 }
4974 }
4975 else
4976 {
4977 report = pcck_buf->cck_agc_rpt & 0x60;
4978 report = report>>5;
4979 switch(report)
4980 {
4981 case 0x3:
4982 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4983 break;
4984 case 0x2:
4985 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4986 break;
4987 case 0x1:
4988 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4989 break;
4990 case 0x0:
4991 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4992 break;
4993 }
4994 }
4995
4996 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4997 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4998 pstats->RecvSignalPower = pwdb_all;
4999
5000 //
5001 // (3) Get Signal Quality (EVM)
5002 //
5003 //if(bpacket_match_bssid)
5004 {
5005 u8 sq;
5006
5007 if(pstats->RxPWDBAll > 40)
5008 {
5009 sq = 100;
5010 }else
5011 {
5012 sq = pcck_buf->sq_rpt;
5013
5014 if(pcck_buf->sq_rpt > 64)
5015 sq = 0;
5016 else if (pcck_buf->sq_rpt < 20)
5017 sq = 100;
5018 else
5019 sq = ((64-sq) * 100) / 44;
5020 }
5021 pstats->SignalQuality = precord_stats->SignalQuality = sq;
5022 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
5023 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
5024 }
5025 }
5026 else
5027 {
5028 priv->stats.numqry_phystatusHT++;
5029 //
5030 // (1)Get RSSI for HT rate
5031 //
5032 for(i=RF90_PATH_A; i<priv->NumTotalRFPath; i++)
5033 {
5034 // 2008/01/30 MH we will judge RF RX path now.
5035 if (priv->brfpath_rxenable[i])
5036 rf_rx_num++;
5037 else
5038 continue;
5039
5040 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
5041 continue;
5042
5043 //Fixed by Jacken from Bryant 2008-03-20
5044 //Original value is 106
5045 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
5046
5047 //Get Rx snr value in DB
5048 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
5049 rx_snrX = (char)(tmp_rxsnr);
Joe Perches859171c2010-11-14 19:04:48 -08005050 //rx_snrX >>= 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005051 rx_snrX /= 2;
5052 priv->stats.rxSNRdB[i] = (long)rx_snrX;
5053
5054 /* Translate DBM to percentage. */
5055 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
5056 total_rssi += RSSI;
5057
5058 /* Record Signal Strength for next packet */
5059 //if(bpacket_match_bssid)
5060 {
5061 pstats->RxMIMOSignalStrength[i] =(u8) RSSI;
5062 precord_stats->RxMIMOSignalStrength[i] =(u8) RSSI;
5063 }
5064 }
5065
5066
5067 //
5068 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
5069 //
5070 //Fixed by Jacken from Bryant 2008-03-20
5071 //Original value is 106
5072 rx_pwr_all = (((pofdm_buf->pwdb_all ) >> 1 )& 0x7f) -106;
5073 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
5074
5075 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
5076 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
5077
5078 //
5079 // (3)EVM of HT rate
5080 //
5081 if(pdrvinfo->RxHT && pdrvinfo->RxRate>=DESC90_RATEMCS8 &&
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005082 pdrvinfo->RxRate<=DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005083 max_spatial_stream = 2; //both spatial stream make sense
5084 else
5085 max_spatial_stream = 1; //only spatial stream 1 makes sense
5086
5087 for(i=0; i<max_spatial_stream; i++)
5088 {
5089 tmp_rxevm = pofdm_buf->rxevm_X[i];
5090 rx_evmX = (char)(tmp_rxevm);
5091
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005092 // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07005093 // will set the most significant bit to "zero" when doing shifting operation which may change a negative
Jerry Chuang8fc85982009-11-03 07:17:11 -02005094 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
5095 rx_evmX /= 2; //dbm
5096
5097 evm = rtl819x_evm_dbtopercentage(rx_evmX);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005098 //if(bpacket_match_bssid)
5099 {
5100 if(i==0) // Fill value in RFD, Get the first spatial stream only
5101 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
5102 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
5103 }
5104 }
5105
5106
5107 /* record rx statistics for debug */
5108 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
5109 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
5110 if(pdrvinfo->BW) //40M channel
5111 priv->stats.received_bwtype[1+prxsc->rxsc]++;
5112 else //20M channel
5113 priv->stats.received_bwtype[0]++;
5114 }
5115
5116 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
5117 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
5118 if(is_cck_rate)
5119 {
5120 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));//PWDB_ALL;
5121
5122 }
5123 else
5124 {
5125 //pRfd->Status.SignalStrength = pRecordRfd->Status.SignalStrength = (u8)(SignalScaleMapping(total_rssi/=RF90_PATH_MAX));//(u8)(total_rssi/=RF90_PATH_MAX);
5126 // We can judge RX path number now.
5127 if (rf_rx_num != 0)
5128 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi/=rf_rx_num)));
5129 }
5130} /* QueryRxPhyStatus8190Pci */
5131
5132void
5133rtl8192_record_rxdesc_forlateruse(
5134 struct ieee80211_rx_stats * psrc_stats,
5135 struct ieee80211_rx_stats * ptarget_stats
5136)
5137{
5138 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
5139 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
5140 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
5141}
5142
5143
5144void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
5145 struct ieee80211_rx_stats * pstats,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005146 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005147{
5148 // TODO: We must only check packet for current MAC address. Not finish
5149 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5150 struct net_device *dev=info->dev;
5151 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5152 bool bpacket_match_bssid, bpacket_toself;
5153 bool bPacketBeacon=FALSE, bToSelfBA=FALSE;
5154 static struct ieee80211_rx_stats previous_stats;
5155 struct ieee80211_hdr_3addr *hdr;//by amy
5156 u16 fc,type;
5157
5158 // Get Signal Quality for only RX data queue (but not command queue)
5159
5160 u8* tmp_buf;
5161 //u16 tmp_buf_len = 0;
5162 u8 *praddr;
5163
5164 /* Get MAC frame start address. */
5165 tmp_buf = (u8*)skb->data;// + get_rxpacket_shiftbytes_819xusb(pstats);
5166
5167 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
5168 fc = le16_to_cpu(hdr->frame_ctl);
5169 type = WLAN_FC_GET_TYPE(fc);
5170 praddr = hdr->addr1;
5171
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005172 /* Check if the received packet is acceptable. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005173 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005174 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
5175 && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02005176 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
5177
Jerry Chuang8fc85982009-11-03 07:17:11 -02005178 if(WLAN_FC_GET_FRAMETYPE(fc)== IEEE80211_STYPE_BEACON)
5179 {
5180 bPacketBeacon = true;
5181 //DbgPrint("Beacon 2, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
5182 }
5183 if(WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK)
5184 {
5185 if((eqMacAddr(praddr,dev->dev_addr)))
5186 bToSelfBA = true;
5187 //DbgPrint("BlockAck, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
5188 }
5189
Jerry Chuang8fc85982009-11-03 07:17:11 -02005190
5191
5192 if(bpacket_match_bssid)
5193 {
5194 priv->stats.numpacket_matchbssid++;
5195 }
5196 if(bpacket_toself){
5197 priv->stats.numpacket_toself++;
5198 }
5199 //
5200 // Process PHY information for previous packet (RSSI/PWDB/EVM)
5201 //
5202 // Because phy information is contained in the last packet of AMPDU only, so driver
5203 // should process phy information of previous packet
5204 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
5205 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid,bpacket_toself,bPacketBeacon,bToSelfBA);
5206 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
5207
5208}
5209
5210/**
5211* Function: UpdateReceivedRateHistogramStatistics
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07005212* Overview: Record the received data rate
Jerry Chuang8fc85982009-11-03 07:17:11 -02005213*
5214* Input:
5215* struct net_device *dev
5216* struct ieee80211_rx_stats *stats
5217*
5218* Output:
5219*
5220* (priv->stats.ReceivedRateHistogram[] is updated)
5221* Return:
5222* None
5223*/
5224void
5225UpdateReceivedRateHistogramStatistics8190(
5226 struct net_device *dev,
5227 struct ieee80211_rx_stats *stats
5228 )
5229{
5230 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005231 u32 rcvType=1; //0: Total, 1:OK, 2:CRC, 3:ICV
5232 u32 rateIndex;
5233 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02005234
5235
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005236 if(stats->bCRC)
5237 rcvType = 2;
5238 else if(stats->bICV)
5239 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005240
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005241 if(stats->bShortPreamble)
5242 preamble_guardinterval = 1;// short
5243 else
5244 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02005245
5246 switch(stats->rate)
5247 {
5248 //
5249 // CCK rate
5250 //
5251 case MGN_1M: rateIndex = 0; break;
5252 case MGN_2M: rateIndex = 1; break;
5253 case MGN_5_5M: rateIndex = 2; break;
5254 case MGN_11M: rateIndex = 3; break;
5255 //
5256 // Legacy OFDM rate
5257 //
5258 case MGN_6M: rateIndex = 4; break;
5259 case MGN_9M: rateIndex = 5; break;
5260 case MGN_12M: rateIndex = 6; break;
5261 case MGN_18M: rateIndex = 7; break;
5262 case MGN_24M: rateIndex = 8; break;
5263 case MGN_36M: rateIndex = 9; break;
5264 case MGN_48M: rateIndex = 10; break;
5265 case MGN_54M: rateIndex = 11; break;
5266 //
5267 // 11n High throughput rate
5268 //
5269 case MGN_MCS0: rateIndex = 12; break;
5270 case MGN_MCS1: rateIndex = 13; break;
5271 case MGN_MCS2: rateIndex = 14; break;
5272 case MGN_MCS3: rateIndex = 15; break;
5273 case MGN_MCS4: rateIndex = 16; break;
5274 case MGN_MCS5: rateIndex = 17; break;
5275 case MGN_MCS6: rateIndex = 18; break;
5276 case MGN_MCS7: rateIndex = 19; break;
5277 case MGN_MCS8: rateIndex = 20; break;
5278 case MGN_MCS9: rateIndex = 21; break;
5279 case MGN_MCS10: rateIndex = 22; break;
5280 case MGN_MCS11: rateIndex = 23; break;
5281 case MGN_MCS12: rateIndex = 24; break;
5282 case MGN_MCS13: rateIndex = 25; break;
5283 case MGN_MCS14: rateIndex = 26; break;
5284 case MGN_MCS15: rateIndex = 27; break;
5285 default: rateIndex = 28; break;
5286 }
5287 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
5288 priv->stats.received_rate_histogram[0][rateIndex]++; //total
5289 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
5290}
5291
5292
5293void query_rxdesc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats, bool bIsRxAggrSubframe)
5294{
5295 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5296 struct net_device *dev=info->dev;
5297 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5298 //rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
5299 rx_drvinfo_819x_usb *driver_info = NULL;
5300
5301 //
5302 //Get Rx Descriptor Information
5303 //
5304#ifdef USB_RX_AGGREGATION_SUPPORT
5305 if (bIsRxAggrSubframe)
5306 {
5307 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
5308 stats->Length = desc->Length ;
5309 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
5310 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
5311 stats->bICV = desc->ICV;
5312 stats->bCRC = desc->CRC32;
5313 stats->bHwError = stats->bCRC|stats->bICV;
5314 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
5315 } else
5316#endif
5317 {
5318 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
5319
5320 stats->Length = desc->Length;
5321 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
5322 stats->RxBufShift = 0;//desc->Shift&0x03;
5323 stats->bICV = desc->ICV;
5324 stats->bCRC = desc->CRC32;
5325 stats->bHwError = stats->bCRC|stats->bICV;
5326 //RTL8190 set this bit to indicate that Hw does not decrypt packet
5327 stats->Decrypted = !desc->SWDec;
5328 }
5329
5330 if((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
5331 {
5332 stats->bHwError = false;
5333 }
5334 else
5335 {
5336 stats->bHwError = stats->bCRC|stats->bICV;
5337 }
5338
5339 if(stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
5340 stats->bHwError |= 1;
5341 //
5342 //Get Driver Info
5343 //
5344 // TODO: Need to verify it on FGPA platform
5345 //Driver info are written to the RxBuffer following rx desc
5346 if (stats->RxDrvInfoSize != 0) {
5347 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) + \
5348 stats->RxBufShift);
5349 /* unit: 0.5M */
5350 /* TODO */
5351 if(!stats->bHwError){
5352 u8 ret_rate;
5353 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
5354 if(ret_rate == 0xff)
5355 {
5356 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
5357 // Special Error Handling here, 2008.05.16, by Emily
5358
5359 stats->bHwError = 1;
5360 stats->rate = MGN_1M; //Set 1M rate by default
5361 }else
5362 {
5363 stats->rate = ret_rate;
5364 }
5365 }
5366 else
5367 stats->rate = 0x02;
5368
5369 stats->bShortPreamble = driver_info->SPLCP;
5370
5371
5372 UpdateReceivedRateHistogramStatistics8190(dev, stats);
5373
5374 stats->bIsAMPDU = (driver_info->PartAggr==1);
5375 stats->bFirstMPDU = (driver_info->PartAggr==1) && (driver_info->FirstAGGR==1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005376 stats->TimeStampLow = driver_info->TSFL;
5377 // xiong mask it, 070514
5378 //pRfd->Status.TimeStampHigh = PlatformEFIORead4Byte(Adapter, TSFR+4);
5379 // stats->TimeStampHigh = read_nic_dword(dev, TSFR+4);
5380
5381 UpdateRxPktTimeStamp8190(dev, stats);
5382
5383 //
5384 // Rx A-MPDU
5385 //
5386 if(driver_info->FirstAGGR==1 || driver_info->PartAggr == 1)
5387 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
5388 driver_info->FirstAGGR, driver_info->PartAggr);
5389
5390 }
5391
5392 skb_pull(skb,sizeof(rx_desc_819x_usb));
5393 //
5394 // Get Total offset of MPDU Frame Body
5395 //
5396 if((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
5397 stats->bShift = 1;
5398 skb_pull(skb,stats->RxBufShift + stats->RxDrvInfoSize);
5399 }
5400
5401#ifdef USB_RX_AGGREGATION_SUPPORT
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005402 /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005403 if(bIsRxAggrSubframe) {
5404 skb_pull(skb, 8);
5405 }
5406#endif
5407 /* for debug 2008.5.29 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005408
5409 //added by vivi, for MP, 20080108
5410 stats->RxIs40MHzPacket = driver_info->BW;
5411 if(stats->RxDrvInfoSize != 0)
5412 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
5413
5414}
5415
5416u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
5417{
5418#ifdef USB_RX_AGGREGATION_SUPPORT
5419 if (bIsRxAggrSubframe)
5420 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
5421 + Status->RxBufShift + 8);
5422 else
5423#endif
5424 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
5425 + Status->RxBufShift);
5426}
5427
5428void rtl8192_rx_nomal(struct sk_buff* skb)
5429{
5430 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5431 struct net_device *dev=info->dev;
5432 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5433 struct ieee80211_rx_stats stats = {
5434 .signal = 0,
5435 .noise = -98,
5436 .rate = 0,
5437 // .mac_time = jiffies,
5438 .freq = IEEE80211_24GHZ_BAND,
5439 };
5440 u32 rx_pkt_len = 0;
5441 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
5442 bool unicast_packet = false;
5443#ifdef USB_RX_AGGREGATION_SUPPORT
5444 struct sk_buff *agg_skb = NULL;
5445 u32 TotalLength = 0;
5446 u32 TempDWord = 0;
5447 u32 PacketLength = 0;
5448 u32 PacketOccupiedLendth = 0;
5449 u8 TempByte = 0;
5450 u32 PacketShiftBytes = 0;
5451 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
5452 u8 PaddingBytes = 0;
5453 //add just for testing
5454 u8 testing;
5455
5456#endif
5457
5458 /* 20 is for ps-poll */
5459 if((skb->len >=(20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
5460#ifdef USB_RX_AGGREGATION_SUPPORT
5461 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
5462#endif
5463 /* first packet should not contain Rx aggregation header */
5464 query_rxdesc_status(skb, &stats, false);
5465 /* TODO */
5466 /* hardware related info */
5467#ifdef USB_RX_AGGREGATION_SUPPORT
5468 if (TempByte & BIT0) {
5469 agg_skb = skb;
5470 //TotalLength = agg_skb->len - 4; /*sCrcLng*/
5471 TotalLength = stats.Length - 4; /*sCrcLng*/
5472 //RT_TRACE(COMP_RECV, "%s:first aggregated packet!Length=%d\n",__FUNCTION__,TotalLength);
5473 /* though the head pointer has passed this position */
5474 TempDWord = *(u32 *)(agg_skb->data - 4);
5475 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
5476 skb = dev_alloc_skb(PacketLength);
5477 memcpy(skb_put(skb,PacketLength),agg_skb->data,PacketLength);
5478 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
5479 }
5480#endif
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005481 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005482 skb_trim(skb, skb->len - 4/*sCrcLng*/);
5483
5484 rx_pkt_len = skb->len;
5485 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
5486 unicast_packet = false;
5487 if(is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
5488 //TODO
5489 }else if(is_multicast_ether_addr(ieee80211_hdr->addr1)){
5490 //TODO
5491 }else {
5492 /* unicast packet */
5493 unicast_packet = true;
5494 }
5495
5496 if(!ieee80211_rx(priv->ieee80211,skb, &stats)) {
5497 dev_kfree_skb_any(skb);
5498 } else {
5499 priv->stats.rxoktotal++;
5500 if(unicast_packet) {
5501 priv->stats.rxbytesunicast += rx_pkt_len;
5502 }
5503 }
5504#ifdef USB_RX_AGGREGATION_SUPPORT
5505 testing = 1;
5506 // (PipeIndex == 0) && (TempByte & BIT0) => TotalLength > 0.
5507 if (TotalLength > 0) {
5508 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
5509 if ((PacketOccupiedLendth & 0xFF) != 0)
5510 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
5511 PacketOccupiedLendth -= 8;
5512 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
5513 if (agg_skb->len > TempDWord)
5514 skb_pull(agg_skb, TempDWord);
5515 else
5516 agg_skb->len = 0;
5517
5518 while (agg_skb->len>=GetRxPacketShiftBytes819xUsb(&stats, true)) {
5519 u8 tmpCRC = 0, tmpICV = 0;
5520 //RT_TRACE(COMP_RECV,"%s:aggred pkt,total_len = %d\n",__FUNCTION__,agg_skb->len);
5521 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
5522 tmpCRC = RxDescr->CRC32;
5523 tmpICV = RxDescr->ICV;
5524 memcpy(agg_skb->data, &agg_skb->data[44], 2);
5525 RxDescr->CRC32 = tmpCRC;
5526 RxDescr->ICV = tmpICV;
5527
5528 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
5529 stats.signal = 0;
5530 stats.noise = -98;
5531 stats.rate = 0;
5532 stats.freq = IEEE80211_24GHZ_BAND;
5533 query_rxdesc_status(agg_skb, &stats, true);
5534 PacketLength = stats.Length;
5535
5536 if(PacketLength > agg_skb->len) {
5537 break;
5538 }
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005539 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005540 skb = dev_alloc_skb(PacketLength);
5541 memcpy(skb_put(skb,PacketLength),agg_skb->data, PacketLength);
5542 skb_trim(skb, skb->len - 4/*sCrcLng*/);
5543
5544 rx_pkt_len = skb->len;
5545 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
5546 unicast_packet = false;
5547 if(is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
5548 //TODO
5549 }else if(is_multicast_ether_addr(ieee80211_hdr->addr1)){
5550 //TODO
5551 }else {
5552 /* unicast packet */
5553 unicast_packet = true;
5554 }
5555 if(!ieee80211_rx(priv->ieee80211,skb, &stats)) {
5556 dev_kfree_skb_any(skb);
5557 } else {
5558 priv->stats.rxoktotal++;
5559 if(unicast_packet) {
5560 priv->stats.rxbytesunicast += rx_pkt_len;
5561 }
5562 }
5563 /* should trim the packet which has been copied to target skb */
5564 skb_pull(agg_skb, PacketLength);
5565 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
5566 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
5567 if ((PacketOccupiedLendth & 0xFF) != 0) {
5568 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
5569 if (agg_skb->len > PaddingBytes)
5570 skb_pull(agg_skb, PaddingBytes);
5571 else
5572 agg_skb->len = 0;
5573 }
5574 }
5575 dev_kfree_skb(agg_skb);
5576 }
5577#endif
5578 } else {
5579 priv->stats.rxurberr++;
5580 printk("actual_length:%d\n", skb->len);
5581 dev_kfree_skb_any(skb);
5582 }
5583
5584}
5585
5586void
5587rtl819xusb_process_received_packet(
5588 struct net_device *dev,
5589 struct ieee80211_rx_stats *pstats
5590 )
5591{
5592// bool bfreerfd=false, bqueued=false;
5593 u8* frame;
5594 u16 frame_len=0;
5595 struct r8192_priv *priv = ieee80211_priv(dev);
5596// u8 index = 0;
5597// u8 TID = 0;
5598 //u16 seqnum = 0;
5599 //PRX_TS_RECORD pts = NULL;
5600
5601 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
5602 //porting by amy 080508
5603 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
5604 frame = pstats->virtual_address;
5605 frame_len = pstats->packetlength;
5606#ifdef TODO // by amy about HCT
5607 if(!Adapter->bInHctTest)
5608 CountRxErrStatistics(Adapter, pRfd);
5609#endif
5610 {
5611 #ifdef ENABLE_PS //by amy for adding ps function in future
5612 RT_RF_POWER_STATE rtState;
5613 // When RF is off, we should not count the packet for hw/sw synchronize
5614 // reason, ie. there may be a duration while sw switch is changed and hw
5615 // switch is being changed. 2006.12.04, by shien chang.
5616 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8* )(&rtState));
5617 if (rtState == eRfOff)
5618 {
5619 return;
5620 }
5621 #endif
5622 priv->stats.rxframgment++;
5623
5624 }
5625#ifdef TODO
5626 RmMonitorSignalStrength(Adapter, pRfd);
5627#endif
5628 /* 2007/01/16 MH Add RX command packet handle here. */
5629 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
5630 if (rtl819xusb_rx_command_packet(dev, pstats))
5631 {
5632 return;
5633 }
5634
5635#ifdef SW_CRC_CHECK
5636 SwCrcCheck();
5637#endif
5638
5639
5640}
5641
5642void query_rx_cmdpkt_desc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats)
5643{
5644// rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5645// struct net_device *dev=info->dev;
5646// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5647 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
5648// rx_drvinfo_819x_usb *driver_info;
5649
5650 //
5651 //Get Rx Descriptor Information
5652 //
5653 stats->virtual_address = (u8*)skb->data;
5654 stats->Length = desc->Length;
5655 stats->RxDrvInfoSize = 0;
5656 stats->RxBufShift = 0;
5657 stats->packetlength = stats->Length-scrclng;
5658 stats->fraglength = stats->packetlength;
5659 stats->fragoffset = 0;
5660 stats->ntotalfrag = 1;
5661}
5662
5663
5664void rtl8192_rx_cmd(struct sk_buff *skb)
5665{
5666 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5667 struct net_device *dev = info->dev;
5668 //int ret;
5669// struct urb *rx_urb = info->urb;
5670 /* TODO */
5671 struct ieee80211_rx_stats stats = {
5672 .signal = 0,
5673 .noise = -98,
5674 .rate = 0,
5675 // .mac_time = jiffies,
5676 .freq = IEEE80211_24GHZ_BAND,
5677 };
5678
5679 if((skb->len >=(20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE))
5680 {
5681
5682 query_rx_cmdpkt_desc_status(skb,&stats);
5683 // this is to be done by amy 080508 prfd->queue_id = 1;
5684
5685
5686 //
5687 // Process the command packet received.
5688 //
5689
5690 rtl819xusb_process_received_packet(dev,&stats);
5691
5692 dev_kfree_skb_any(skb);
5693 }
5694 else
5695 ;
5696
5697
Jerry Chuang8fc85982009-11-03 07:17:11 -02005698}
5699
5700void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
5701{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005702 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005703 struct rtl8192_rx_info *info;
5704
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005705 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005706 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005707 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005708 /* Nomal packet pipe */
5709 case 3:
5710 //RT_TRACE(COMP_RECV, "normal in-pipe index(%d)\n",info->out_pipe);
5711 priv->IrpPendingCount--;
5712 rtl8192_rx_nomal(skb);
5713 break;
5714
5715 /* Command packet pipe */
5716 case 9:
5717 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",\
5718 info->out_pipe);
5719
5720 rtl8192_rx_cmd(skb);
5721 break;
5722
5723 default: /* should never get here! */
5724 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",\
5725 info->out_pipe);
5726 dev_kfree_skb(skb);
5727 break;
5728
5729 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005730 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005731}
5732
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005733static const struct net_device_ops rtl8192_netdev_ops = {
5734 .ndo_open = rtl8192_open,
5735 .ndo_stop = rtl8192_close,
5736 .ndo_get_stats = rtl8192_stats,
5737 .ndo_tx_timeout = tx_timeout,
5738 .ndo_do_ioctl = rtl8192_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00005739 .ndo_set_rx_mode = r8192_set_multicast,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005740 .ndo_set_mac_address = r8192_set_mac_adr,
5741 .ndo_validate_addr = eth_validate_addr,
5742 .ndo_change_mtu = eth_change_mtu,
5743 .ndo_start_xmit = ieee80211_xmit,
5744};
Jerry Chuang8fc85982009-11-03 07:17:11 -02005745
5746
5747/****************************************************************************
5748 ---------------------------- USB_STUFF---------------------------
5749*****************************************************************************/
5750
Jerry Chuang8fc85982009-11-03 07:17:11 -02005751static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
5752 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005753{
5754// unsigned long ioaddr = 0;
5755 struct net_device *dev = NULL;
5756 struct r8192_priv *priv= NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005757 struct usb_device *udev = interface_to_usbdev(intf);
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005758 int ret;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005759 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005760
5761 dev = alloc_ieee80211(sizeof(struct r8192_priv));
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005762 if (dev == NULL)
5763 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005764
Jerry Chuang8fc85982009-11-03 07:17:11 -02005765 usb_set_intfdata(intf, dev);
5766 SET_NETDEV_DEV(dev, &intf->dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005767 priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005768 priv->ieee80211 = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005769 priv->udev=udev;
5770
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005771 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005772
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005773 //DMESG("Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005774#if WIRELESS_EXT >= 12
5775#if WIRELESS_EXT < 17
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005776 dev->get_wireless_stats = r8192_get_wireless_stats;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005777#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005778 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005779#endif
5780 dev->type=ARPHRD_ETHER;
5781
5782 dev->watchdog_timeo = HZ*3; //modified by john, 0805
5783
5784 if (dev_alloc_name(dev, ifname) < 0){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005785 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005786 ifname = "wlan%d";
5787 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005788 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005789
5790 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005791 if(rtl8192_init(dev)!=0){
5792 RT_TRACE(COMP_ERR, "Initialization failed");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005793 ret = -ENODEV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005794 goto fail;
5795 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005796 netif_carrier_off(dev);
5797 netif_stop_queue(dev);
5798
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005799 ret = register_netdev(dev);
5800 if (ret)
5801 goto fail2;
5802
Jerry Chuang8fc85982009-11-03 07:17:11 -02005803 RT_TRACE(COMP_INIT, "dev name=======> %s\n",dev->name);
5804 rtl8192_proc_init_one(dev);
5805
5806
5807 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005808 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005809
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005810fail2:
5811 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005812 kfree(priv->pFirmware);
5813 priv->pFirmware = NULL;
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005814 rtl8192_usb_deleteendpoints(dev);
5815 destroy_workqueue(priv->priv_wq);
5816 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005817fail:
5818 free_ieee80211(dev);
5819
5820 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005821 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005822}
5823
5824//detach all the work and timer structure declared or inititialize in r8192U_init function.
5825void rtl8192_cancel_deferred_work(struct r8192_priv* priv)
5826{
5827
Jerry Chuang8fc85982009-11-03 07:17:11 -02005828 cancel_work_sync(&priv->reset_wq);
5829 cancel_delayed_work(&priv->watch_dog_wq);
5830 cancel_delayed_work(&priv->update_beacon_wq);
5831 cancel_work_sync(&priv->qos_activate);
5832 //cancel_work_sync(&priv->SetBWModeWorkItem);
5833 //cancel_work_sync(&priv->SwChnlWorkItem);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005834
5835}
5836
5837
Jerry Chuang8fc85982009-11-03 07:17:11 -02005838static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005839{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005840 struct net_device *dev = usb_get_intfdata(intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005841
5842 struct r8192_priv *priv = ieee80211_priv(dev);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005843 if(dev){
Jerry Chuang8fc85982009-11-03 07:17:11 -02005844
5845 unregister_netdev(dev);
5846
5847 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
5848 rtl8192_proc_remove_one(dev);
5849
5850 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005851 kfree(priv->pFirmware);
5852 priv->pFirmware = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005853 // priv->rf_close(dev);
5854// rtl8192_SetRFPowerState(dev, eRfOff);
5855 rtl8192_usb_deleteendpoints(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005856 destroy_workqueue(priv->priv_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005857 //rtl8192_irq_disable(dev);
5858 //rtl8192_reset(dev);
5859 mdelay(10);
5860
5861 }
5862 free_ieee80211(dev);
5863 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
5864}
5865
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005866/* fun with the built-in ieee80211 stack... */
5867extern int ieee80211_debug_init(void);
5868extern void ieee80211_debug_exit(void);
5869extern int ieee80211_crypto_init(void);
5870extern void ieee80211_crypto_deinit(void);
5871extern int ieee80211_crypto_tkip_init(void);
5872extern void ieee80211_crypto_tkip_exit(void);
5873extern int ieee80211_crypto_ccmp_init(void);
5874extern void ieee80211_crypto_ccmp_exit(void);
5875extern int ieee80211_crypto_wep_init(void);
5876extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005877
5878static int __init rtl8192_usb_module_init(void)
5879{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005880 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005881
5882#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005883 ret = ieee80211_debug_init();
5884 if (ret) {
5885 printk(KERN_ERR "ieee80211_debug_init() failed %d\n", ret);
5886 return ret;
5887 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005888#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005889 ret = ieee80211_crypto_init();
5890 if (ret) {
5891 printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret);
5892 return ret;
5893 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005894
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005895 ret = ieee80211_crypto_tkip_init();
5896 if (ret) {
5897 printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n",
5898 ret);
5899 return ret;
5900 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005901
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005902 ret = ieee80211_crypto_ccmp_init();
5903 if (ret) {
5904 printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n",
5905 ret);
5906 return ret;
5907 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005908
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005909 ret = ieee80211_crypto_wep_init();
5910 if (ret) {
5911 printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret);
5912 return ret;
5913 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005914
Jerry Chuang8fc85982009-11-03 07:17:11 -02005915 printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n");
5916 printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n");
5917 RT_TRACE(COMP_INIT, "Initializing module");
5918 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
5919 rtl8192_proc_module_init();
5920 return usb_register(&rtl8192_usb_driver);
5921}
5922
5923
5924static void __exit rtl8192_usb_module_exit(void)
5925{
5926 usb_deregister(&rtl8192_usb_driver);
5927
5928 RT_TRACE(COMP_DOWN, "Exiting");
5929// rtl8192_proc_module_remove();
5930}
5931
5932
5933void rtl8192_try_wake_queue(struct net_device *dev, int pri)
5934{
5935 unsigned long flags;
5936 short enough_desc;
5937 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5938
5939 spin_lock_irqsave(&priv->tx_lock,flags);
5940 enough_desc = check_nic_enough_desc(dev,pri);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005941 spin_unlock_irqrestore(&priv->tx_lock,flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005942
5943 if(enough_desc)
5944 ieee80211_wake_queue(priv->ieee80211);
5945}
5946
5947void EnableHWSecurityConfig8192(struct net_device *dev)
5948{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005949 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005950 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5951 struct ieee80211_device* ieee = priv->ieee80211;
5952 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005953 if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->ieee80211->auth_mode != 2))
5954 {
5955 SECR_value |= SCR_RxUseDK;
5956 SECR_value |= SCR_TxUseDK;
5957 }
5958 else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP)))
5959 {
5960 SECR_value |= SCR_RxUseDK;
5961 SECR_value |= SCR_TxUseDK;
5962 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005963 //add HWSec active enable here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02005964//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
5965
5966 ieee->hwsec_active = 1;
5967
5968 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
5969 {
5970 ieee->hwsec_active = 0;
5971 SECR_value &= ~SCR_RxDecEnable;
5972 }
5973 RT_TRACE(COMP_SEC,"%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __FUNCTION__, \
5974 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
5975 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005976 write_nic_byte(dev, SECR, SECR_value);//SECR_value | SCR_UseDK );
5977 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005978}
5979
5980
5981void setKey( struct net_device *dev,
5982 u8 EntryNo,
5983 u8 KeyIndex,
5984 u16 KeyType,
5985 u8 *MacAddr,
5986 u8 DefaultKey,
5987 u32 *KeyContent )
5988{
5989 u32 TargetCommand = 0;
5990 u32 TargetContent = 0;
5991 u16 usConfig = 0;
5992 u8 i;
5993 if (EntryNo >= TOTAL_CAM_ENTRY)
5994 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
5995
Joe Perches0ee9f672009-12-06 11:34:52 -08005996 RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", dev,EntryNo, KeyIndex, KeyType, MacAddr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005997
5998 if (DefaultKey)
5999 usConfig |= BIT15 | (KeyType<<2);
6000 else
6001 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
6002// usConfig |= BIT15 | (KeyType<<2) | (DefaultKey<<5) | KeyIndex;
6003
6004
6005 for(i=0 ; i<CAM_CONTENT_COUNT; i++){
6006 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
6007 TargetCommand |= BIT31|BIT16;
6008
6009 if(i==0){//MAC|Config
6010 TargetContent = (u32)(*(MacAddr+0)) << 16|
6011 (u32)(*(MacAddr+1)) << 24|
6012 (u32)usConfig;
6013
6014 write_nic_dword(dev, WCAMI, TargetContent);
6015 write_nic_dword(dev, RWCAM, TargetCommand);
6016 // printk("setkey cam =%8x\n", read_cam(dev, i+6*EntryNo));
6017 }
6018 else if(i==1){//MAC
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006019 TargetContent = (u32)(*(MacAddr+2)) |
6020 (u32)(*(MacAddr+3)) << 8|
6021 (u32)(*(MacAddr+4)) << 16|
6022 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02006023 write_nic_dword(dev, WCAMI, TargetContent);
6024 write_nic_dword(dev, RWCAM, TargetCommand);
6025 }
6026 else {
6027 //Key Material
6028 if(KeyContent !=NULL){
6029 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)) );
6030 write_nic_dword(dev, RWCAM, TargetCommand);
6031 }
6032 }
6033 }
6034
6035}
6036
6037/***************************************************************************
6038 ------------------- module init / exit stubs ----------------
6039****************************************************************************/
6040module_init(rtl8192_usb_module_init);
6041module_exit(rtl8192_usb_module_exit);