blob: 8dc271e937f7e9e3a27a229da61d452eafa5184d [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>
David Howells0541f9d2013-04-08 15:17:33 +010074#include <linux/proc_fs.h>
75#include <linux/seq_file.h>
Jerry Chuang8fc85982009-11-03 07:17:11 -020076// FIXME: check if 2.6.7 is ok
Jerry Chuang8fc85982009-11-03 07:17:11 -020077
78#ifdef CONFIG_RTL8192_PM
79#include "r8192_pm.h"
80#endif
81
Jerry Chuang8fc85982009-11-03 07:17:11 -020082#include "dot11d.h"
Jerry Chuang8fc85982009-11-03 07:17:11 -020083//set here to open your trace code. //WB
84u32 rt_global_debug_component = \
Sebastian Hahn35997ff2012-12-05 21:40:18 +010085 // COMP_INIT |
Jerry Chuang8fc85982009-11-03 07:17:11 -020086// COMP_DBG |
Sebastian Hahn35997ff2012-12-05 21:40:18 +010087 // COMP_EPROM |
Jerry Chuang8fc85982009-11-03 07:17:11 -020088// COMP_PHY |
89 // COMP_RF |
90// COMP_FIRMWARE |
91// COMP_CH |
92 // COMP_POWER_TRACKING |
93// COMP_RATE |
94 // COMP_TXAGC |
95 // COMP_TRACE |
96 COMP_DOWN |
97 // COMP_RECV |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -020098 // COMP_SWBW |
Jerry Chuang8fc85982009-11-03 07:17:11 -020099 COMP_SEC |
100 // COMP_RESET |
101 // COMP_SEND |
102 // COMP_EVENTS |
103 COMP_ERR ; //always open err flags on
104
105#define TOTAL_CAM_ENTRY 32
106#define CAM_CONTENT_COUNT 8
107
Németh Mártona4577322010-01-10 00:18:34 +0100108static const struct usb_device_id rtl8192_usb_id_tbl[] = {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200109 /* Realtek */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200110 {USB_DEVICE(0x0bda, 0x8709)},
111 /* Corega */
112 {USB_DEVICE(0x07aa, 0x0043)},
113 /* Belkin */
114 {USB_DEVICE(0x050d, 0x805E)},
115 /* Sitecom */
116 {USB_DEVICE(0x0df6, 0x0031)},
117 /* EnGenius */
118 {USB_DEVICE(0x1740, 0x9201)},
119 /* Dlink */
120 {USB_DEVICE(0x2001, 0x3301)},
121 /* Zinwell */
122 {USB_DEVICE(0x5a57, 0x0290)},
Ben Hutchingse10ac152010-06-25 01:35:49 +0100123 /* LG */
124 {USB_DEVICE(0x043e, 0x7a01)},
Jerry Chuang8fc85982009-11-03 07:17:11 -0200125 {}
126};
127
128MODULE_LICENSE("GPL");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200129MODULE_VERSION("V 1.1");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200130MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl);
131MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards");
132
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300133static char *ifname = "wlan%d";
Jerry Chuang8fc85982009-11-03 07:17:11 -0200134static int hwwep = 1; //default use hw. set 0 to use software security
135static int channels = 0x3fff;
136
137
138
Jerry Chuang8fc85982009-11-03 07:17:11 -0200139module_param(ifname, charp, S_IRUGO|S_IWUSR );
140//module_param(hwseqnum,int, S_IRUGO|S_IWUSR);
141module_param(hwwep,int, S_IRUGO|S_IWUSR);
142module_param(channels,int, S_IRUGO|S_IWUSR);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200143
144MODULE_PARM_DESC(ifname," Net interface name, wlan%d=default");
145//MODULE_PARM_DESC(hwseqnum," Try to use hardware 802.11 header sequence numbers. Zero=default");
146MODULE_PARM_DESC(hwwep," Try to use hardware security support. ");
147MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI");
148
Bill Pemberton25794522012-11-19 13:22:04 -0500149static int rtl8192_usb_probe(struct usb_interface *intf,
Jerry Chuang8fc85982009-11-03 07:17:11 -0200150 const struct usb_device_id *id);
Bill Pembertona4a557e2012-11-19 13:26:46 -0500151static void rtl8192_usb_disconnect(struct usb_interface *intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200152
153
154static struct usb_driver rtl8192_usb_driver = {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200155 .name = RTL819xU_MODULE_NAME, /* Driver name */
156 .id_table = rtl8192_usb_id_tbl, /* PCI_ID table */
157 .probe = rtl8192_usb_probe, /* probe fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200158 .disconnect = rtl8192_usb_disconnect, /* remove fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200159#ifdef CONFIG_RTL8192_PM
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200160 .suspend = rtl8192_suspend, /* PM suspend fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200161 .resume = rtl8192_resume, /* PM resume fn */
162#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200163 .suspend = NULL, /* PM suspend fn */
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100164 .resume = NULL, /* PM resume fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200165#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -0200166};
167
Jerry Chuang8fc85982009-11-03 07:17:11 -0200168
Jennifer Naumann0db7a342012-12-05 21:40:19 +0100169typedef struct _CHANNEL_LIST {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200170 u8 Channel[32];
171 u8 Len;
172}CHANNEL_LIST, *PCHANNEL_LIST;
173
174static CHANNEL_LIST ChannelPlan[] = {
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100175 {{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
176 {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC
177 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //ETSI
Jerry Chuang8fc85982009-11-03 07:17:11 -0200178 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Spain. Change to ETSI.
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100179 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //France. Change to ETSI.
Jerry Chuang8fc85982009-11-03 07:17:11 -0200180 {{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
181 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1
182 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Israel.
183 {{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
184 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22}, //MIC
185 {{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
186};
187
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300188static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200189{
190 int i, max_chan=-1, min_chan=-1;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300191 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200192 switch (channel_plan)
193 {
Patrik Karlinf00c4932013-01-09 09:39:44 +0100194 case COUNTRY_CODE_FCC:
195 case COUNTRY_CODE_IC:
196 case COUNTRY_CODE_ETSI:
197 case COUNTRY_CODE_SPAIN:
198 case COUNTRY_CODE_FRANCE:
199 case COUNTRY_CODE_MKK:
200 case COUNTRY_CODE_MKK1:
201 case COUNTRY_CODE_ISRAEL:
202 case COUNTRY_CODE_TELEC:
203 case COUNTRY_CODE_MIC:
204 Dot11d_Init(ieee);
205 ieee->bGlobalDomain = false;
206 //actually 8225 & 8256 rf chips only support B,G,24N mode
207 if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256)) {
208 min_chan = 1;
209 max_chan = 14;
210 }
211 else {
212 RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __FUNCTION__);
213 }
214 if (ChannelPlan[channel_plan].Len != 0) {
215 // Clear old channel map
216 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
217 // Set new channel map
218 for (i=0;i<ChannelPlan[channel_plan].Len;i++) {
219 if (ChannelPlan[channel_plan].Channel[i] < min_chan || ChannelPlan[channel_plan].Channel[i] > max_chan)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200220 break;
Patrik Karlinf00c4932013-01-09 09:39:44 +0100221 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200222 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200223 }
Patrik Karlinf00c4932013-01-09 09:39:44 +0100224 break;
225
226 case COUNTRY_CODE_GLOBAL_DOMAIN:
227 GET_DOT11D_INFO(ieee)->bEnabled = 0;//this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain settings.
228 Dot11d_Reset(ieee);
229 ieee->bGlobalDomain = true;
230 break;
231
232 default:
233 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200234 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200235}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200236
Jerry Chuang8fc85982009-11-03 07:17:11 -0200237
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100238#define rx_hal_is_cck_rate(_pdrvinfo)\
Jerry Chuang8fc85982009-11-03 07:17:11 -0200239 (_pdrvinfo->RxRate == DESC90_RATE1M ||\
240 _pdrvinfo->RxRate == DESC90_RATE2M ||\
241 _pdrvinfo->RxRate == DESC90_RATE5_5M ||\
242 _pdrvinfo->RxRate == DESC90_RATE11M) &&\
243 !_pdrvinfo->RxHT\
244
245
246void CamResetAllEntry(struct net_device *dev)
247{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200248 u32 ulcommand = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200249 //2004/02/11 In static WEP, OID_ADD_KEY or OID_ADD_WEP are set before STA associate to AP.
250 // However, ResetKey is called on OID_802_11_INFRASTRUCTURE_MODE and MlmeAssociateRequest
251 // In this condition, Cam can not be reset because upper layer will not set this static key again.
252 //if(Adapter->EncAlgorithm == WEP_Encryption)
253 // return;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200254//debug
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200255 //DbgPrint("========================================\n");
256 //DbgPrint(" Call ResetAllEntry \n");
257 //DbgPrint("========================================\n\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200258 ulcommand |= BIT31|BIT30;
259 write_nic_dword(dev, RWCAM, ulcommand);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200260
261}
262
263
264void write_cam(struct net_device *dev, u8 addr, u32 data)
265{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200266 write_nic_dword(dev, WCAMI, data);
267 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff) );
Jerry Chuang8fc85982009-11-03 07:17:11 -0200268}
269
270u32 read_cam(struct net_device *dev, u8 addr)
271{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200272 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff) );
273 return read_nic_dword(dev, 0xa8);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200274}
275
276void write_nic_byte_E(struct net_device *dev, int indx, u8 data)
277{
278 int status;
279 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
280 struct usb_device *udev = priv->udev;
281
282 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
283 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
284 indx|0xfe00, 0, &data, 1, HZ / 2);
285
286 if (status < 0)
287 {
288 printk("write_nic_byte_E TimeOut! status:%d\n", status);
289 }
290}
291
292u8 read_nic_byte_E(struct net_device *dev, int indx)
293{
294 int status;
295 u8 data;
296 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
297 struct usb_device *udev = priv->udev;
298
299 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
300 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
301 indx|0xfe00, 0, &data, 1, HZ / 2);
302
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200303 if (status < 0)
304 {
305 printk("read_nic_byte_E TimeOut! status:%d\n", status);
306 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200307
308 return data;
309}
310//as 92U has extend page from 4 to 16, so modify functions below.
311void write_nic_byte(struct net_device *dev, int indx, u8 data)
312{
313 int status;
314
315 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
316 struct usb_device *udev = priv->udev;
317
318 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
319 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
320 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
321
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200322 if (status < 0)
323 {
324 printk("write_nic_byte TimeOut! status:%d\n", status);
325 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200326
327
328}
329
330
331void write_nic_word(struct net_device *dev, int indx, u16 data)
332{
333
334 int status;
335
336 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
337 struct usb_device *udev = priv->udev;
338
339 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
340 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
341 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2);
342
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200343 if (status < 0)
344 {
345 printk("write_nic_word TimeOut! status:%d\n", status);
346 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200347
348}
349
350
351void write_nic_dword(struct net_device *dev, int indx, u32 data)
352{
353
354 int status;
355
356 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
357 struct usb_device *udev = priv->udev;
358
359 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
360 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
361 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2);
362
363
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200364 if (status < 0)
365 {
366 printk("write_nic_dword TimeOut! status:%d\n", status);
367 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200368
369}
370
371
372
373u8 read_nic_byte(struct net_device *dev, int indx)
374{
375 u8 data;
376 int status;
377 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
378 struct usb_device *udev = priv->udev;
379
380 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
381 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
382 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
383
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200384 if (status < 0)
385 {
386 printk("read_nic_byte TimeOut! status:%d\n", status);
387 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200388
389 return data;
390}
391
392
393
394u16 read_nic_word(struct net_device *dev, int indx)
395{
396 u16 data;
397 int status;
398 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
399 struct usb_device *udev = priv->udev;
400
401 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Mike Gilks616f58f2010-06-03 18:29:23 +0800402 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
403 (indx&0xff)|0xff00, (indx>>8)&0x0f,
404 &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200405
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200406 if (status < 0)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200407 printk("read_nic_word TimeOut! status:%d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200408
409 return data;
410}
411
412u16 read_nic_word_E(struct net_device *dev, int indx)
413{
414 u16 data;
415 int status;
416 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
417 struct usb_device *udev = priv->udev;
418
419 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
420 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Mike Gilks616f58f2010-06-03 18:29:23 +0800421 indx|0xfe00, 0, &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200422
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200423 if (status < 0)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200424 printk("read_nic_word TimeOut! status:%d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200425
426 return data;
427}
428
429u32 read_nic_dword(struct net_device *dev, int indx)
430{
431 u32 data;
432 int status;
Mike Gilks616f58f2010-06-03 18:29:23 +0800433 /* int result; */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200434
435 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
436 struct usb_device *udev = priv->udev;
437
438 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Mike Gilks616f58f2010-06-03 18:29:23 +0800439 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
440 (indx&0xff)|0xff00, (indx>>8)&0x0f,
441 &data, 4, HZ / 2);
442 /* if(0 != result) {
443 * printk(KERN_WARNING "read size of data = %d\, date = %d\n",
444 * result, data);
445 * }
446 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200447
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200448 if (status < 0)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200449 printk("read_nic_dword TimeOut! status:%d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200450
451 return data;
452}
453
Mike Gilks616f58f2010-06-03 18:29:23 +0800454/* u8 read_phy_cck(struct net_device *dev, u8 adr); */
455/* u8 read_phy_ofdm(struct net_device *dev, u8 adr); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200456/* this might still called in what was the PHY rtl8185/rtl8192 common code
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300457 * plans are to possibility turn it again in one common code...
Jerry Chuang8fc85982009-11-03 07:17:11 -0200458 */
459inline void force_pci_posting(struct net_device *dev)
460{
461}
462
Jerry Chuang8fc85982009-11-03 07:17:11 -0200463static struct net_device_stats *rtl8192_stats(struct net_device *dev);
464void rtl8192_commit(struct net_device *dev);
Mike Gilks616f58f2010-06-03 18:29:23 +0800465/* void rtl8192_restart(struct net_device *dev); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200466void rtl8192_restart(struct work_struct *work);
Mike Gilks616f58f2010-06-03 18:29:23 +0800467/* void rtl8192_rq_tx_ack(struct work_struct *work); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200468void watch_dog_timer_callback(unsigned long data);
469
470/****************************************************************************
Mike Gilks616f58f2010-06-03 18:29:23 +0800471 * -----------------------------PROCFS STUFF-------------------------
472*****************************************************************************
473 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200474
Mike Gilks616f58f2010-06-03 18:29:23 +0800475static struct proc_dir_entry *rtl8192_proc;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200476
David Howells0541f9d2013-04-08 15:17:33 +0100477static int proc_get_stats_ap(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200478{
David Howells0541f9d2013-04-08 15:17:33 +0100479 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200480 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
481 struct ieee80211_device *ieee = priv->ieee80211;
482 struct ieee80211_network *target;
483
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200484 list_for_each_entry(target, &ieee->network_list, list) {
David Howells0541f9d2013-04-08 15:17:33 +0100485 const char *wpa = "non_WPA";
Mike Gilks616f58f2010-06-03 18:29:23 +0800486 if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0)
David Howells0541f9d2013-04-08 15:17:33 +0100487 wpa = "WPA";
488
489 seq_printf(m, "%s %s\n", target->ssid, wpa);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200490 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200491
David Howells0541f9d2013-04-08 15:17:33 +0100492 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200493}
494
David Howells0541f9d2013-04-08 15:17:33 +0100495static int proc_get_registers(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200496{
David Howells0541f9d2013-04-08 15:17:33 +0100497 struct net_device *dev = m->private;
498 int i,n, max = 0xff;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200499
David Howells0541f9d2013-04-08 15:17:33 +0100500 seq_puts(m, "\n####################page 0##################\n ");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200501
Patrik Karlin666b3bf22013-01-09 09:40:56 +0100502 for (n=0;n<=max;) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200503 //printk( "\nD: %2x> ", n);
David Howells0541f9d2013-04-08 15:17:33 +0100504 seq_printf(m, "\nD: %2x > ",n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200505
Patrik Karlin666b3bf22013-01-09 09:40:56 +0100506 for (i=0;i<16 && n<=max;i++,n++)
David Howells0541f9d2013-04-08 15:17:33 +0100507 seq_printf(m, "%2x ",read_nic_byte(dev,0x000|n));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200508
509 // printk("%2x ",read_nic_byte(dev,n));
510 }
David Howells0541f9d2013-04-08 15:17:33 +0100511
512 seq_puts(m, "\n####################page 1##################\n ");
Patrik Karlin666b3bf22013-01-09 09:40:56 +0100513 for (n=0;n<=max;) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200514 //printk( "\nD: %2x> ", n);
David Howells0541f9d2013-04-08 15:17:33 +0100515 seq_printf(m, "\nD: %2x > ",n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200516
Patrik Karlin666b3bf22013-01-09 09:40:56 +0100517 for (i=0;i<16 && n<=max;i++,n++)
David Howells0541f9d2013-04-08 15:17:33 +0100518 seq_printf(m, "%2x ",read_nic_byte(dev,0x100|n));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200519
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200520 // printk("%2x ",read_nic_byte(dev,n));
521 }
David Howells0541f9d2013-04-08 15:17:33 +0100522
523 seq_puts(m, "\n####################page 3##################\n ");
Patrik Karlin666b3bf22013-01-09 09:40:56 +0100524 for (n=0;n<=max;) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200525 //printk( "\nD: %2x> ", n);
David Howells0541f9d2013-04-08 15:17:33 +0100526 seq_printf(m, "\nD: %2x > ",n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200527
Xenia Ragiadakou212bff32013-05-22 18:22:34 +0300528 for (i=0;i<16 && n<=max;i++,n++)
David Howells0541f9d2013-04-08 15:17:33 +0100529 seq_printf(m, "%2x ",read_nic_byte(dev,0x300|n));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200530
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200531 // printk("%2x ",read_nic_byte(dev,n));
532 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200533
David Howells0541f9d2013-04-08 15:17:33 +0100534 seq_putc(m, '\n');
535 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200536}
537
David Howells0541f9d2013-04-08 15:17:33 +0100538static int proc_get_stats_tx(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200539{
David Howells0541f9d2013-04-08 15:17:33 +0100540 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200541 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
542
David Howells0541f9d2013-04-08 15:17:33 +0100543 seq_printf(m,
Jerry Chuang8fc85982009-11-03 07:17:11 -0200544 "TX VI priority ok int: %lu\n"
545 "TX VI priority error int: %lu\n"
546 "TX VO priority ok int: %lu\n"
547 "TX VO priority error int: %lu\n"
548 "TX BE priority ok int: %lu\n"
549 "TX BE priority error int: %lu\n"
550 "TX BK priority ok int: %lu\n"
551 "TX BK priority error int: %lu\n"
552 "TX MANAGE priority ok int: %lu\n"
553 "TX MANAGE priority error int: %lu\n"
554 "TX BEACON priority ok int: %lu\n"
555 "TX BEACON priority error int: %lu\n"
556// "TX high priority ok int: %lu\n"
557// "TX high priority failed error int: %lu\n"
558 "TX queue resume: %lu\n"
559 "TX queue stopped?: %d\n"
560 "TX fifo overflow: %lu\n"
561// "TX beacon: %lu\n"
562 "TX VI queue: %d\n"
563 "TX VO queue: %d\n"
564 "TX BE queue: %d\n"
565 "TX BK queue: %d\n"
566// "TX HW queue: %d\n"
567 "TX VI dropped: %lu\n"
568 "TX VO dropped: %lu\n"
569 "TX BE dropped: %lu\n"
570 "TX BK dropped: %lu\n"
571 "TX total data packets %lu\n",
572// "TX beacon aborted: %lu\n",
573 priv->stats.txviokint,
574 priv->stats.txvierr,
575 priv->stats.txvookint,
576 priv->stats.txvoerr,
577 priv->stats.txbeokint,
578 priv->stats.txbeerr,
579 priv->stats.txbkokint,
580 priv->stats.txbkerr,
581 priv->stats.txmanageokint,
582 priv->stats.txmanageerr,
583 priv->stats.txbeaconokint,
584 priv->stats.txbeaconerr,
585// priv->stats.txhpokint,
586// priv->stats.txhperr,
587 priv->stats.txresumed,
588 netif_queue_stopped(dev),
589 priv->stats.txoverflow,
590// priv->stats.txbeacon,
591 atomic_read(&(priv->tx_pending[VI_PRIORITY])),
592 atomic_read(&(priv->tx_pending[VO_PRIORITY])),
593 atomic_read(&(priv->tx_pending[BE_PRIORITY])),
594 atomic_read(&(priv->tx_pending[BK_PRIORITY])),
595// read_nic_byte(dev, TXFIFOCOUNT),
596 priv->stats.txvidrop,
597 priv->stats.txvodrop,
598 priv->stats.txbedrop,
599 priv->stats.txbkdrop,
600 priv->stats.txdatapkt
601// priv->stats.txbeaconerr
602 );
603
David Howells0541f9d2013-04-08 15:17:33 +0100604 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200605}
606
David Howells0541f9d2013-04-08 15:17:33 +0100607static int proc_get_stats_rx(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200608{
David Howells0541f9d2013-04-08 15:17:33 +0100609 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200610 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
611
David Howells0541f9d2013-04-08 15:17:33 +0100612 seq_printf(m,
Jerry Chuang8fc85982009-11-03 07:17:11 -0200613 "RX packets: %lu\n"
614 "RX urb status error: %lu\n"
615 "RX invalid urb error: %lu\n",
616 priv->stats.rxoktotal,
617 priv->stats.rxstaterr,
618 priv->stats.rxurberr);
619
David Howells0541f9d2013-04-08 15:17:33 +0100620 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200621}
David Howells0541f9d2013-04-08 15:17:33 +0100622
Jerry Chuang8fc85982009-11-03 07:17:11 -0200623void rtl8192_proc_module_init(void)
624{
625 RT_TRACE(COMP_INIT, "Initializing proc filesystem");
Al Viroe55d92b2011-07-24 02:07:46 -0400626 rtl8192_proc = proc_mkdir(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200627}
628
629
630void rtl8192_proc_module_remove(void)
631{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200632 remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200633}
634
David Howells0541f9d2013-04-08 15:17:33 +0100635/*
636 * seq_file wrappers for procfile show routines.
637 */
638static int rtl8192_proc_open(struct inode *inode, struct file *file)
639{
David Howells4a520d22013-04-12 14:06:01 +0100640 struct net_device *dev = proc_get_parent_data(inode);
David Howells0541f9d2013-04-08 15:17:33 +0100641 int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
642
643 return single_open(file, show, dev);
644}
645
646static const struct file_operations rtl8192_proc_fops = {
647 .open = rtl8192_proc_open,
648 .read = seq_read,
649 .llseek = seq_lseek,
Al Virobae301d2013-05-05 00:15:43 -0400650 .release = single_release,
David Howells0541f9d2013-04-08 15:17:33 +0100651};
652
653/*
654 * Table of proc files we need to create.
655 */
656struct rtl8192_proc_file {
657 char name[12];
658 int (*show)(struct seq_file *, void *);
659};
660
661static const struct rtl8192_proc_file rtl8192_proc_files[] = {
662 { "stats-rx", &proc_get_stats_rx },
663 { "stats-tx", &proc_get_stats_tx },
664 { "stats-ap", &proc_get_stats_ap },
665 { "registers", &proc_get_registers },
666 { "" }
667};
668
669void rtl8192_proc_init_one(struct net_device *dev)
670{
671 const struct rtl8192_proc_file *f;
David Howellscc87e0f2013-04-12 03:02:22 +0100672 struct proc_dir_entry *dir;
David Howells0541f9d2013-04-08 15:17:33 +0100673
674 if (rtl8192_proc) {
David Howellscc87e0f2013-04-12 03:02:22 +0100675 dir = proc_mkdir_data(dev->name, 0, rtl8192_proc, dev);
676 if (!dir) {
David Howells0541f9d2013-04-08 15:17:33 +0100677 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
678 dev->name);
679 return;
680 }
David Howells0541f9d2013-04-08 15:17:33 +0100681
682 for (f = rtl8192_proc_files; f->name[0]; f++) {
David Howellscc87e0f2013-04-12 03:02:22 +0100683 if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir,
684 &rtl8192_proc_fops, f->show)) {
David Howells0541f9d2013-04-08 15:17:33 +0100685 RT_TRACE(COMP_ERR, "Unable to initialize "
686 "/proc/net/rtl8192/%s/%s\n",
687 dev->name, f->name);
688 return;
689 }
690 }
691 }
692}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200693
694void rtl8192_proc_remove_one(struct net_device *dev)
695{
David Howellscc87e0f2013-04-12 03:02:22 +0100696 remove_proc_subtree(dev->name, rtl8192_proc);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200697}
698
Jerry Chuang8fc85982009-11-03 07:17:11 -0200699/****************************************************************************
700 -----------------------------MISC STUFF-------------------------
701*****************************************************************************/
702
703/* this is only for debugging */
704void print_buffer(u32 *buffer, int len)
705{
706 int i;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300707 u8 *buf =(u8 *)buffer;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200708
709 printk("ASCII BUFFER DUMP (len: %x):\n",len);
710
Xenia Ragiadakou212bff32013-05-22 18:22:34 +0300711 for (i=0;i<len;i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200712 printk("%c",buf[i]);
713
714 printk("\nBINARY BUFFER DUMP (len: %x):\n",len);
715
Xenia Ragiadakou212bff32013-05-22 18:22:34 +0300716 for (i=0;i<len;i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200717 printk("%x",buf[i]);
718
719 printk("\n");
720}
721
722//short check_nic_enough_desc(struct net_device *dev, priority_t priority)
723short check_nic_enough_desc(struct net_device *dev,int queue_index)
724{
725 struct r8192_priv *priv = ieee80211_priv(dev);
726 int used = atomic_read(&priv->tx_pending[queue_index]);
727
728 return (used < MAX_TX_URB);
729}
730
731void tx_timeout(struct net_device *dev)
732{
733 struct r8192_priv *priv = ieee80211_priv(dev);
734 //rtl8192_commit(dev);
735
Jerry Chuang8fc85982009-11-03 07:17:11 -0200736 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200737 //DMESG("TXTIMEOUT");
738}
739
740
741/* this is only for debug */
742void dump_eprom(struct net_device *dev)
743{
744 int i;
Xenia Ragiadakou212bff32013-05-22 18:22:34 +0300745 for (i=0; i<63; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200746 RT_TRACE(COMP_EPROM, "EEPROM addr %x : %x", i, eprom_read(dev,i));
747}
748
749/* this is only for debug */
750void rtl8192_dump_reg(struct net_device *dev)
751{
752 int i;
753 int n;
754 int max=0x1ff;
755
756 RT_TRACE(COMP_PHY, "Dumping NIC register map");
757
Xenia Ragiadakou212bff32013-05-22 18:22:34 +0300758 for (n=0;n<=max;)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200759 {
760 printk( "\nD: %2x> ", n);
Xenia Ragiadakou212bff32013-05-22 18:22:34 +0300761 for (i=0;i<16 && n<=max;i++,n++)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200762 printk("%2x ",read_nic_byte(dev,n));
763 }
764 printk("\n");
765}
766
767/****************************************************************************
768 ------------------------------HW STUFF---------------------------
769*****************************************************************************/
770
Jerry Chuang8fc85982009-11-03 07:17:11 -0200771
772void rtl8192_set_mode(struct net_device *dev,int mode)
773{
774 u8 ecmd;
775 ecmd=read_nic_byte(dev, EPROM_CMD);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300776 ecmd=ecmd & ~EPROM_CMD_OPERATING_MODE_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200777 ecmd=ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300778 ecmd=ecmd & ~(1<<EPROM_CS_SHIFT);
779 ecmd=ecmd & ~(1<<EPROM_CK_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200780 write_nic_byte(dev, EPROM_CMD, ecmd);
781}
782
783
784void rtl8192_update_msr(struct net_device *dev)
785{
786 struct r8192_priv *priv = ieee80211_priv(dev);
787 u8 msr;
788
789 msr = read_nic_byte(dev, MSR);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300790 msr &= ~MSR_LINK_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200791
792 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
793 * msr must be updated if the state is ASSOCIATING.
794 * this is intentional and make sense for ad-hoc and
795 * master (see the create BSS/IBSS func)
796 */
797 if (priv->ieee80211->state == IEEE80211_LINKED){
798
799 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
800 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
801 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
802 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
803 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
804 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
805
806 }else
807 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
808
809 write_nic_byte(dev, MSR, msr);
810}
811
812void rtl8192_set_chan(struct net_device *dev,short ch)
813{
814 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
815// u32 tx;
816 RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __FUNCTION__, ch);
817 priv->chan=ch;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200818
819 /* this hack should avoid frame TX during channel setting*/
820
821
822// tx = read_nic_dword(dev,TX_CONF);
823// tx &= ~TX_LOOPBACK_MASK;
824
825#ifndef LOOP_TEST
826// write_nic_dword(dev,TX_CONF, tx |( TX_LOOPBACK_MAC<<TX_LOOPBACK_SHIFT));
827
828 //need to implement rf set channel here WB
829
830 if (priv->rf_set_chan)
831 priv->rf_set_chan(dev,priv->chan);
832 mdelay(10);
833// write_nic_dword(dev,TX_CONF,tx | (TX_LOOPBACK_NONE<<TX_LOOPBACK_SHIFT));
834#endif
835}
836
Jerry Chuang8fc85982009-11-03 07:17:11 -0200837static void rtl8192_rx_isr(struct urb *urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200838//static void rtl8192_rx_isr(struct urb *rx_urb);
839
840u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
841{
842
843#ifdef USB_RX_AGGREGATION_SUPPORT
844 if (pstats->bisrxaggrsubframe)
845 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
846 + pstats->RxBufShift + 8);
847 else
848#endif
849 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
850 + pstats->RxBufShift);
851
852}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300853static int rtl8192_rx_initiate(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200854{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200855 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
856 struct urb *entry;
857 struct sk_buff *skb;
858 struct rtl8192_rx_info *info;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200859
860 /* nomal packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200861 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB) {
862 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
863 if (!skb)
864 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200865 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200866 if (!entry) {
867 kfree_skb(skb);
868 break;
869 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200870// printk("nomal packet IN request!\n");
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200871 usb_fill_bulk_urb(entry, priv->udev,
872 usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb),
873 RX_URB_SIZE, rtl8192_rx_isr, skb);
874 info = (struct rtl8192_rx_info *) skb->cb;
875 info->urb = entry;
876 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200877 info->out_pipe = 3; //denote rx normal packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200878 skb_queue_tail(&priv->rx_queue, skb);
879 usb_submit_urb(entry, GFP_KERNEL);
880 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200881
882 /* command packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200883 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200884// printk("command packet IN request!\n");
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200885 skb = __dev_alloc_skb(RX_URB_SIZE ,GFP_KERNEL);
886 if (!skb)
887 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200888 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200889 if (!entry) {
890 kfree_skb(skb);
891 break;
892 }
893 usb_fill_bulk_urb(entry, priv->udev,
894 usb_rcvbulkpipe(priv->udev, 9), skb_tail_pointer(skb),
895 RX_URB_SIZE, rtl8192_rx_isr, skb);
896 info = (struct rtl8192_rx_info *) skb->cb;
897 info->urb = entry;
898 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200899 info->out_pipe = 9; //denote rx cmd packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200900 skb_queue_tail(&priv->rx_queue, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200901 usb_submit_urb(entry, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200902 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200903
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200904 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200905}
906
907void rtl8192_set_rxconf(struct net_device *dev)
908{
909 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
910 u32 rxconf;
911
912 rxconf=read_nic_dword(dev,RCR);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300913 rxconf = rxconf & ~MAC_FILTER_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200914 rxconf = rxconf | RCR_AMF;
915 rxconf = rxconf | RCR_ADF;
916 rxconf = rxconf | RCR_AB;
917 rxconf = rxconf | RCR_AM;
918 //rxconf = rxconf | RCR_ACF;
919
920 if (dev->flags & IFF_PROMISC) {DMESG ("NIC in promisc mode");}
921
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300922 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || \
Jerry Chuang8fc85982009-11-03 07:17:11 -0200923 dev->flags & IFF_PROMISC){
924 rxconf = rxconf | RCR_AAP;
925 } /*else if(priv->ieee80211->iw_mode == IW_MODE_MASTER){
926 rxconf = rxconf | (1<<ACCEPT_ALLMAC_FRAME_SHIFT);
927 rxconf = rxconf | (1<<RX_CHECK_BSSID_SHIFT);
928 }*/else{
929 rxconf = rxconf | RCR_APM;
930 rxconf = rxconf | RCR_CBSSID;
931 }
932
933
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300934 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR){
Jerry Chuang8fc85982009-11-03 07:17:11 -0200935 rxconf = rxconf | RCR_AICV;
936 rxconf = rxconf | RCR_APWRMGT;
937 }
938
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300939 if ( priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200940 rxconf = rxconf | RCR_ACRC32;
941
942
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300943 rxconf = rxconf & ~RX_FIFO_THRESHOLD_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200944 rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE<<RX_FIFO_THRESHOLD_SHIFT);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300945 rxconf = rxconf & ~MAX_RX_DMA_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200946 rxconf = rxconf | ((u32)7<<RCR_MXDMA_OFFSET);
947
948// rxconf = rxconf | (1<<RX_AUTORESETPHY_SHIFT);
949 rxconf = rxconf | RCR_ONLYERLPKT;
950
951// rxconf = rxconf &~ RCR_CS_MASK;
952// rxconf = rxconf | (1<<RCR_CS_SHIFT);
953
954 write_nic_dword(dev, RCR, rxconf);
955
956 #ifdef DEBUG_RX
957 DMESG("rxconf: %x %x",rxconf ,read_nic_dword(dev,RCR));
958 #endif
959}
960//wait to be removed
961void rtl8192_rx_enable(struct net_device *dev)
962{
963 //u8 cmd;
964
965 //struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
966
967 rtl8192_rx_initiate(dev);
968
969// rtl8192_set_rxconf(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200970}
971
972
973void rtl8192_tx_enable(struct net_device *dev)
974{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200975}
976
Jerry Chuang8fc85982009-11-03 07:17:11 -0200977
978
979void rtl8192_rtx_disable(struct net_device *dev)
980{
981 u8 cmd;
982 struct r8192_priv *priv = ieee80211_priv(dev);
983 struct sk_buff *skb;
984 struct rtl8192_rx_info *info;
985
986 cmd=read_nic_byte(dev,CMDR);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300987 write_nic_byte(dev, CMDR, cmd & \
988 ~(CR_TE|CR_RE));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200989 force_pci_posting(dev);
990 mdelay(10);
991
992 while ((skb = __skb_dequeue(&priv->rx_queue))) {
993 info = (struct rtl8192_rx_info *) skb->cb;
994 if (!info->urb)
995 continue;
996
997 usb_kill_urb(info->urb);
998 kfree_skb(skb);
999 }
1000
1001 if (skb_queue_len(&priv->skb_queue)) {
1002 printk(KERN_WARNING "skb_queue not empty\n");
1003 }
1004
1005 skb_queue_purge(&priv->skb_queue);
1006 return;
1007}
1008
1009
1010int alloc_tx_beacon_desc_ring(struct net_device *dev, int count)
1011{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001012 return 0;
1013}
1014
Jerry Chuang8fc85982009-11-03 07:17:11 -02001015inline u16 ieeerate2rtlrate(int rate)
1016{
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001017 switch (rate){
Jerry Chuang8fc85982009-11-03 07:17:11 -02001018 case 10:
1019 return 0;
1020 case 20:
1021 return 1;
1022 case 55:
1023 return 2;
1024 case 110:
1025 return 3;
1026 case 60:
1027 return 4;
1028 case 90:
1029 return 5;
1030 case 120:
1031 return 6;
1032 case 180:
1033 return 7;
1034 case 240:
1035 return 8;
1036 case 360:
1037 return 9;
1038 case 480:
1039 return 10;
1040 case 540:
1041 return 11;
1042 default:
1043 return 3;
1044
1045 }
1046}
1047static u16 rtl_rate[] = {10,20,55,110,60,90,120,180,240,360,480,540};
1048inline u16 rtl8192_rate2rate(short rate)
1049{
1050 if (rate >11) return 0;
1051 return rtl_rate[rate];
1052}
1053
1054
Justin P. Mattock589b3d02012-04-30 07:41:36 -07001055/* The prototype of rx_isr has changed since one version of Linux Kernel */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001056static void rtl8192_rx_isr(struct urb *urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001057{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001058 struct sk_buff *skb = (struct sk_buff *) urb->context;
1059 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
1060 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001061 struct r8192_priv *priv = ieee80211_priv(dev);
1062 int out_pipe = info->out_pipe;
1063 int err;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001064 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001065 return;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001066 if (unlikely(urb->status)) {
1067 info->urb = NULL;
1068 priv->stats.rxstaterr++;
1069 priv->ieee80211->stats.rx_errors++;
1070 usb_free_urb(urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001071 // printk("%s():rx status err\n",__FUNCTION__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001072 return;
1073 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001074 skb_unlink(skb, &priv->rx_queue);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001075 skb_put(skb, urb->actual_length);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001076
1077 skb_queue_tail(&priv->skb_queue, skb);
1078 tasklet_schedule(&priv->irq_rx_tasklet);
1079
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001080 skb = dev_alloc_skb(RX_URB_SIZE);
1081 if (unlikely(!skb)) {
1082 usb_free_urb(urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001083 printk("%s():can,t alloc skb\n",__FUNCTION__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001084 /* TODO check rx queue length and refill *somewhere* */
1085 return;
1086 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001087
1088 usb_fill_bulk_urb(urb, priv->udev,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001089 usb_rcvbulkpipe(priv->udev, out_pipe), skb_tail_pointer(skb),
Jerry Chuang8fc85982009-11-03 07:17:11 -02001090 RX_URB_SIZE, rtl8192_rx_isr, skb);
1091
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001092 info = (struct rtl8192_rx_info *) skb->cb;
1093 info->urb = urb;
1094 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001095 info->out_pipe = out_pipe;
1096
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001097 urb->transfer_buffer = skb_tail_pointer(skb);
1098 urb->context = skb;
1099 skb_queue_tail(&priv->rx_queue, skb);
1100 err = usb_submit_urb(urb, GFP_ATOMIC);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001101 if (err && err != EPERM)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001102 printk("can not submit rxurb, err is %x,URB status is %x\n",err,urb->status);
1103}
1104
1105u32
1106rtl819xusb_rx_command_packet(
1107 struct net_device *dev,
1108 struct ieee80211_rx_stats *pstats
1109 )
1110{
1111 u32 status;
1112
1113 //RT_TRACE(COMP_RECV, DBG_TRACE, ("---> RxCommandPacketHandle819xUsb()\n"));
1114
1115 status = cmpk_message_handle_rx(dev, pstats);
1116 if (status)
1117 {
1118 DMESG("rxcommandpackethandle819xusb: It is a command packet\n");
1119 }
1120 else
1121 {
1122 //RT_TRACE(COMP_RECV, DBG_TRACE, ("RxCommandPacketHandle819xUsb: It is not a command packet\n"));
1123 }
1124
1125 //RT_TRACE(COMP_RECV, DBG_TRACE, ("<--- RxCommandPacketHandle819xUsb()\n"));
1126 return status;
1127}
1128
Jerry Chuang8fc85982009-11-03 07:17:11 -02001129
1130void rtl8192_data_hard_stop(struct net_device *dev)
1131{
1132 //FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001133}
1134
1135
1136void rtl8192_data_hard_resume(struct net_device *dev)
1137{
1138 // FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001139}
1140
1141/* this function TX data frames when the ieee80211 stack requires this.
1142 * It checks also if we need to stop the ieee tx queue, eventually do it
1143 */
1144void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
1145{
1146 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1147 int ret;
1148 unsigned long flags;
1149 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1150 u8 queue_index = tcb_desc->queue_index;
1151
1152 /* shall not be referred by command packet */
1153 assert(queue_index != TXCMD_QUEUE);
1154
1155 spin_lock_irqsave(&priv->tx_lock,flags);
1156
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001157 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001158// tcb_desc->RATRIndex = 7;
1159// tcb_desc->bTxDisableRateFallBack = 1;
1160// tcb_desc->bTxUseDriverAssingedRate = 1;
1161 tcb_desc->bTxEnableFwCalcDur = 1;
1162 skb_push(skb, priv->ieee80211->tx_headroom);
1163 ret = rtl8192_tx(dev, skb);
1164
1165 //priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom);
1166 //priv->ieee80211->stats.tx_packets++;
1167
1168 spin_unlock_irqrestore(&priv->tx_lock,flags);
1169
1170// return ret;
1171 return;
1172}
1173
1174/* This is a rough attempt to TX a frame
1175 * This is called by the ieee 80211 stack to TX management frames.
1176 * If the ring is full packet are dropped (for data frame the queue
1177 * is stopped before this can happen).
1178 */
1179int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
1180{
1181 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1182 int ret;
1183 unsigned long flags;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001184 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1185 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001186
1187
1188 spin_lock_irqsave(&priv->tx_lock,flags);
1189
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001190 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001191 if (queue_index == TXCMD_QUEUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001192 skb_push(skb, USB_HWDESC_HEADER_LEN);
1193 rtl819xU_tx_cmd(dev, skb);
1194 ret = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001195 spin_unlock_irqrestore(&priv->tx_lock,flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001196 return ret;
1197 } else {
1198 skb_push(skb, priv->ieee80211->tx_headroom);
1199 ret = rtl8192_tx(dev, skb);
1200 }
1201
1202 spin_unlock_irqrestore(&priv->tx_lock,flags);
1203
1204 return ret;
1205}
1206
1207
1208void rtl8192_try_wake_queue(struct net_device *dev, int pri);
1209
1210#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1211u16 DrvAggr_PaddingAdd(struct net_device *dev, struct sk_buff *skb)
1212{
1213 u16 PaddingNum = 256 - ((skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES) % 256);
1214 return (PaddingNum&0xff);
1215}
1216
1217u8 MRateToHwRate8190Pci(u8 rate);
1218u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc);
1219u8 MapHwQueueToFirmwareQueue(u8 QueueID);
1220struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv_agg_txb *pSendList)
1221{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001222 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001223 struct r8192_priv *priv = ieee80211_priv(dev);
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001224 cb_desc *tcb_desc = NULL;
1225 u8 i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001226 u32 TotalLength;
1227 struct sk_buff *skb;
1228 struct sk_buff *agg_skb;
1229 tx_desc_819x_usb_aggr_subframe *tx_agg_desc = NULL;
1230 tx_fwinfo_819x_usb *tx_fwinfo = NULL;
1231
1232 //
1233 // Local variable initialization.
1234 //
1235 /* first skb initialization */
1236 skb = pSendList->tx_agg_frames[0];
1237 TotalLength = skb->len;
1238
1239 /* Get the total aggregation length including the padding space and
1240 * sub frame header.
1241 */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001242 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001243 TotalLength += DrvAggr_PaddingAdd(dev, skb);
1244 skb = pSendList->tx_agg_frames[i];
1245 TotalLength += (skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1246 }
1247
1248 /* allocate skb to contain the aggregated packets */
1249 agg_skb = dev_alloc_skb(TotalLength + ieee->tx_headroom);
1250 memset(agg_skb->data, 0, agg_skb->len);
1251 skb_reserve(agg_skb, ieee->tx_headroom);
1252
1253// RT_DEBUG_DATA(COMP_SEND, skb->cb, sizeof(skb->cb));
1254 /* reserve info for first subframe Tx descriptor to be set in the tx function */
1255 skb = pSendList->tx_agg_frames[0];
1256 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1257 tcb_desc->drv_agg_enable = 1;
1258 tcb_desc->pkt_size = skb->len;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001259 tcb_desc->DrvAggrNum = pSendList->nr_drv_agg_frames;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001260 printk("DrvAggNum = %d\n", tcb_desc->DrvAggrNum);
1261// RT_DEBUG_DATA(COMP_SEND, skb->cb, sizeof(skb->cb));
1262// printk("========>skb->data ======> \n");
1263// RT_DEBUG_DATA(COMP_SEND, skb->data, skb->len);
1264 memcpy(agg_skb->cb, skb->cb, sizeof(skb->cb));
1265 memcpy(skb_put(agg_skb,skb->len),skb->data,skb->len);
1266
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001267 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001268 /* push the next sub frame to be 256 byte aline */
1269 skb_put(agg_skb,DrvAggr_PaddingAdd(dev,skb));
1270
1271 /* Subframe drv Tx descriptor and firmware info setting */
1272 skb = pSendList->tx_agg_frames[i];
1273 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1274 tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)agg_skb->tail;
1275 tx_fwinfo = (tx_fwinfo_819x_usb *)(agg_skb->tail + sizeof(tx_desc_819x_usb_aggr_subframe));
1276
1277 memset(tx_fwinfo,0,sizeof(tx_fwinfo_819x_usb));
1278 /* DWORD 0 */
1279 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0;
1280 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1281 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1282 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001283 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001284 tx_fwinfo->AllowAggregation = 1;
1285 /* DWORD 1 */
1286 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1287 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1288 } else {
1289 tx_fwinfo->AllowAggregation = 0;
1290 /* DWORD 1 */
1291 tx_fwinfo->RxMF = 0;
1292 tx_fwinfo->RxAMD = 0;
1293 }
1294
1295 /* Protection mode related */
1296 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0;
1297 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0;
1298 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0;
1299 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80)?1:0;
1300 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
1301 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT==0)?(tcb_desc->RTSSC):0;
1302 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT==1)?((tcb_desc->bRTSBW)?1:0):0;
1303 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):\
1304 (tcb_desc->bRTSUseShortGI?1:0);
1305
1306 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001307 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001308 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001309 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001310 tx_fwinfo->TxBandwidth = 1;
1311 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1312 } else {
1313 tx_fwinfo->TxBandwidth = 0;
1314 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1315 }
1316 } else {
1317 tx_fwinfo->TxBandwidth = 0;
1318 tx_fwinfo->TxSubCarrier = 0;
1319 }
1320
1321 /* Fill Tx descriptor */
1322 memset(tx_agg_desc, 0, sizeof(tx_desc_819x_usb_aggr_subframe));
1323 /* DWORD 0 */
1324 //tx_agg_desc->LINIP = 0;
1325 //tx_agg_desc->CmdInit = 1;
1326 tx_agg_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001327 /* already raw data, need not to subtract header length */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001328 tx_agg_desc->PktSize = skb->len & 0xffff;
1329
1330 /*DWORD 1*/
1331 tx_agg_desc->SecCAMID= 0;
1332 tx_agg_desc->RATid = tcb_desc->RATRIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001333 {
1334 //MPDUOverhead = 0;
1335 tx_agg_desc->NoEnc = 1;
1336 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001337 tx_agg_desc->SecType = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001338
1339 if (tcb_desc->bHwSec) {
1340 switch (priv->ieee80211->pairwise_key_type)
1341 {
1342 case KEY_TYPE_WEP40:
1343 case KEY_TYPE_WEP104:
1344 tx_agg_desc->SecType = 0x1;
1345 tx_agg_desc->NoEnc = 0;
1346 break;
1347 case KEY_TYPE_TKIP:
1348 tx_agg_desc->SecType = 0x2;
1349 tx_agg_desc->NoEnc = 0;
1350 break;
1351 case KEY_TYPE_CCMP:
1352 tx_agg_desc->SecType = 0x3;
1353 tx_agg_desc->NoEnc = 0;
1354 break;
1355 case KEY_TYPE_NA:
1356 tx_agg_desc->SecType = 0x0;
1357 tx_agg_desc->NoEnc = 1;
1358 break;
1359 }
1360 }
1361
1362 tx_agg_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1363 tx_agg_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1364
1365 tx_agg_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1366 tx_agg_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1367
1368 tx_agg_desc->OWN = 1;
1369
1370 //DWORD 2
1371 /* According windows driver, it seems that there no need to fill this field */
1372 //tx_agg_desc->TxBufferSize= (u32)(skb->len - USB_HWDESC_HEADER_LEN);
1373
1374 /* to fill next packet */
1375 skb_put(agg_skb,TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1376 memcpy(skb_put(agg_skb,skb->len),skb->data,skb->len);
1377 }
1378
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001379 for (i = 0; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001380 dev_kfree_skb_any(pSendList->tx_agg_frames[i]);
1381 }
1382
1383 return agg_skb;
1384}
1385
1386/* NOTE:
1387 This function return a list of PTCB which is proper to be aggregate with the input TCB.
1388 If no proper TCB is found to do aggregation, SendList will only contain the input TCB.
1389*/
1390u8 DrvAggr_GetAggregatibleList(struct net_device *dev, struct sk_buff *skb,
1391 struct ieee80211_drv_agg_txb *pSendList)
1392{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001393 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001394 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1395 u16 nMaxAggrNum = pHTInfo->UsbTxAggrNum;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001396 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001397 u8 QueueID = tcb_desc->queue_index;
1398
1399 do {
1400 pSendList->tx_agg_frames[pSendList->nr_drv_agg_frames++] = skb;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001401 if (pSendList->nr_drv_agg_frames >= nMaxAggrNum) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001402 break;
1403 }
1404
1405 } while((skb = skb_dequeue(&ieee->skb_drv_aggQ[QueueID])));
1406
1407 RT_TRACE(COMP_AMSDU, "DrvAggr_GetAggregatibleList, nAggrTcbNum = %d \n", pSendList->nr_drv_agg_frames);
1408 return pSendList->nr_drv_agg_frames;
1409}
1410#endif
1411
Jerry Chuang8fc85982009-11-03 07:17:11 -02001412static void rtl8192_tx_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001413{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001414 struct sk_buff *skb = (struct sk_buff *)tx_urb->context;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001415 struct net_device *dev = NULL;
1416 struct r8192_priv *priv = NULL;
1417 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1418 u8 queue_index = tcb_desc->queue_index;
1419// bool bToSend0Byte;
1420// u16 BufLen = skb->len;
1421
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001422 memcpy(&dev,(struct net_device *)(skb->cb),sizeof(struct net_device *));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001423 priv = ieee80211_priv(dev);
1424
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001425 if (tcb_desc->queue_index != TXCMD_QUEUE) {
1426 if (tx_urb->status == 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001427 dev->trans_start = jiffies;
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07001428 // Act as station mode, destination shall be unicast address.
Jerry Chuang8fc85982009-11-03 07:17:11 -02001429 //priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom);
1430 //priv->ieee80211->stats.tx_packets++;
1431 priv->stats.txoktotal++;
1432 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
1433 priv->stats.txbytesunicast += (skb->len - priv->ieee80211->tx_headroom);
1434 } else {
1435 priv->ieee80211->stats.tx_errors++;
1436 //priv->stats.txmanageerr++;
1437 /* TODO */
1438 }
1439 }
1440
1441 /* free skb and tx_urb */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001442 if (skb != NULL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001443 dev_kfree_skb_any(skb);
1444 usb_free_urb(tx_urb);
1445 atomic_dec(&priv->tx_pending[queue_index]);
1446 }
1447
Jerry Chuang8fc85982009-11-03 07:17:11 -02001448 {
1449 //
1450 // Handle HW Beacon:
Uwe Kleine-Königaf02b582010-10-26 21:57:53 +02001451 // We had transfer our beacon frame to host controller at this moment.
Jerry Chuang8fc85982009-11-03 07:17:11 -02001452 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02001453 //
1454 // Caution:
1455 // Handling the wait queue of command packets.
1456 // For Tx command packets, we must not do TCB fragment because it is not handled right now.
1457 // We must cut the packets to match the size of TX_CMD_PKT before we send it.
1458 //
1459
1460 /* Handle MPDU in wait queue. */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001461 if (queue_index != BEACON_QUEUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001462 /* Don't send data frame during scanning.*/
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001463 if ((skb_queue_len(&priv->ieee80211->skb_waitQ[queue_index]) != 0)&&\
Jerry Chuang8fc85982009-11-03 07:17:11 -02001464 (!(priv->ieee80211->queue_stop))) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001465 if (NULL != (skb = skb_dequeue(&(priv->ieee80211->skb_waitQ[queue_index]))))
Jerry Chuang8fc85982009-11-03 07:17:11 -02001466 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1467
1468 return; //modified by david to avoid further processing AMSDU
1469 }
1470#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1471 else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index])!= 0)&&\
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001472 (!(priv->ieee80211->queue_stop))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001473 // Tx Driver Aggregation process
Justin P. Mattock589b3d02012-04-30 07:41:36 -07001474 /* The driver will aggregation the packets according to the following stats
Jerry Chuang8fc85982009-11-03 07:17:11 -02001475 * 1. check whether there's tx irq available, for it's a completion return
1476 * function, it should contain enough tx irq;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07001477 * 2. check packet type;
Uwe Kleine-König9b0131c2010-09-01 15:40:25 +02001478 * 3. initialize sendlist, check whether the to-be send packet no greater than 1
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07001479 * 4. aggregates the packets, and fill firmware info and tx desc into it, etc.
1480 * 5. check whether the packet could be sent, otherwise just insert into wait head
Jerry Chuang8fc85982009-11-03 07:17:11 -02001481 * */
1482 skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001483 if (!check_nic_enough_desc(dev, queue_index)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001484 skb_queue_head(&(priv->ieee80211->skb_drv_aggQ[queue_index]), skb);
1485 return;
1486 }
1487
1488 {
1489 /*TODO*/
1490 /*
1491 u8* pHeader = skb->data;
1492
1493 if(IsMgntQosData(pHeader) ||
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001494 IsMgntQData_Ack(pHeader) ||
Jerry Chuang8fc85982009-11-03 07:17:11 -02001495 IsMgntQData_Poll(pHeader) ||
1496 IsMgntQData_Poll_Ack(pHeader)
1497 )
1498 */
1499 {
1500 struct ieee80211_drv_agg_txb SendList;
1501
1502 memset(&SendList, 0, sizeof(struct ieee80211_drv_agg_txb));
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001503 if (DrvAggr_GetAggregatibleList(dev, skb, &SendList) > 1) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001504 skb = DrvAggr_Aggregation(dev, &SendList);
1505
Jerry Chuang8fc85982009-11-03 07:17:11 -02001506 }
1507 }
1508 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1509 }
1510 }
1511#endif
1512 }
1513 }
1514
Jerry Chuang8fc85982009-11-03 07:17:11 -02001515}
1516
1517void rtl8192_beacon_stop(struct net_device *dev)
1518{
1519 u8 msr, msrm, msr2;
1520 struct r8192_priv *priv = ieee80211_priv(dev);
1521
1522 msr = read_nic_byte(dev, MSR);
1523 msrm = msr & MSR_LINK_MASK;
1524 msr2 = msr & ~MSR_LINK_MASK;
1525
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001526 if (NIC_8192U == priv->card_8192) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001527 usb_kill_urb(priv->rx_urb[MAX_RX_URB]);
1528 }
1529 if ((msrm == (MSR_LINK_ADHOC<<MSR_LINK_SHIFT) ||
1530 (msrm == (MSR_LINK_MASTER<<MSR_LINK_SHIFT)))){
1531 write_nic_byte(dev, MSR, msr2 | MSR_LINK_NONE);
1532 write_nic_byte(dev, MSR, msr);
1533 }
1534}
1535
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001536void rtl8192_config_rate(struct net_device *dev, u16 *rate_config)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001537{
1538 struct r8192_priv *priv = ieee80211_priv(dev);
1539 struct ieee80211_network *net;
1540 u8 i=0, basic_rate = 0;
1541 net = & priv->ieee80211->current_network;
1542
1543 for (i=0; i<net->rates_len; i++)
1544 {
1545 basic_rate = net->rates[i]&0x7f;
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001546 switch (basic_rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001547 {
1548 case MGN_1M: *rate_config |= RRSR_1M; break;
1549 case MGN_2M: *rate_config |= RRSR_2M; break;
1550 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1551 case MGN_11M: *rate_config |= RRSR_11M; break;
1552 case MGN_6M: *rate_config |= RRSR_6M; break;
1553 case MGN_9M: *rate_config |= RRSR_9M; break;
1554 case MGN_12M: *rate_config |= RRSR_12M; break;
1555 case MGN_18M: *rate_config |= RRSR_18M; break;
1556 case MGN_24M: *rate_config |= RRSR_24M; break;
1557 case MGN_36M: *rate_config |= RRSR_36M; break;
1558 case MGN_48M: *rate_config |= RRSR_48M; break;
1559 case MGN_54M: *rate_config |= RRSR_54M; break;
1560 }
1561 }
1562 for (i=0; i<net->rates_ex_len; i++)
1563 {
1564 basic_rate = net->rates_ex[i]&0x7f;
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001565 switch (basic_rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001566 {
1567 case MGN_1M: *rate_config |= RRSR_1M; break;
1568 case MGN_2M: *rate_config |= RRSR_2M; break;
1569 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1570 case MGN_11M: *rate_config |= RRSR_11M; break;
1571 case MGN_6M: *rate_config |= RRSR_6M; break;
1572 case MGN_9M: *rate_config |= RRSR_9M; break;
1573 case MGN_12M: *rate_config |= RRSR_12M; break;
1574 case MGN_18M: *rate_config |= RRSR_18M; break;
1575 case MGN_24M: *rate_config |= RRSR_24M; break;
1576 case MGN_36M: *rate_config |= RRSR_36M; break;
1577 case MGN_48M: *rate_config |= RRSR_48M; break;
1578 case MGN_54M: *rate_config |= RRSR_54M; break;
1579 }
1580 }
1581}
1582
1583
1584#define SHORT_SLOT_TIME 9
1585#define NON_SHORT_SLOT_TIME 20
1586
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001587void rtl8192_update_cap(struct net_device *dev, u16 cap)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001588{
1589 u32 tmp = 0;
1590 struct r8192_priv *priv = ieee80211_priv(dev);
1591 struct ieee80211_network *net = &priv->ieee80211->current_network;
1592 priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
1593 tmp = priv->basic_rate;
1594 if (priv->short_preamble)
1595 tmp |= BRSR_AckShortPmb;
1596 write_nic_dword(dev, RRSR, tmp);
1597
1598 if (net->mode & (IEEE_G|IEEE_N_24G))
1599 {
1600 u8 slot_time = 0;
1601 if ((cap & WLAN_CAPABILITY_SHORT_SLOT)&&(!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime))
1602 {//short slot time
1603 slot_time = SHORT_SLOT_TIME;
1604 }
1605 else //long slot time
1606 slot_time = NON_SHORT_SLOT_TIME;
1607 priv->slot_time = slot_time;
1608 write_nic_byte(dev, SLOT_TIME, slot_time);
1609 }
1610
1611}
1612void rtl8192_net_update(struct net_device *dev)
1613{
1614
1615 struct r8192_priv *priv = ieee80211_priv(dev);
1616 struct ieee80211_network *net;
1617 u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
1618 u16 rate_config = 0;
1619 net = & priv->ieee80211->current_network;
1620
1621 rtl8192_config_rate(dev, &rate_config);
1622 priv->basic_rate = rate_config &= 0x15f;
1623
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001624 write_nic_dword(dev,BSSIDR,((u32 *)net->bssid)[0]);
1625 write_nic_word(dev,BSSIDR+4,((u16 *)net->bssid)[2]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001626 //for(i=0;i<ETH_ALEN;i++)
1627 // write_nic_byte(dev,BSSID+i,net->bssid[i]);
1628
1629 rtl8192_update_msr(dev);
1630// rtl8192_update_cap(dev, net->capability);
1631 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
1632 {
1633 write_nic_word(dev, ATIMWND, 2);
1634 write_nic_word(dev, BCN_DMATIME, 1023);
1635 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
1636// write_nic_word(dev, BcnIntTime, 100);
1637 write_nic_word(dev, BCN_DRV_EARLY_INT, 1);
1638 write_nic_byte(dev, BCN_ERR_THRESH, 100);
1639 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
1640 // TODO: BcnIFS may required to be changed on ASIC
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001641 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001642
1643 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
1644 }
1645
1646
1647
1648}
1649
1650//temporary hw beacon is not used any more.
1651//open it when necessary
Jerry Chuang8fc85982009-11-03 07:17:11 -02001652void rtl819xusb_beacon_tx(struct net_device *dev,u16 tx_rate)
1653{
1654
Jerry Chuang8fc85982009-11-03 07:17:11 -02001655}
Jerry Chuang8fc85982009-11-03 07:17:11 -02001656inline u8 rtl8192_IsWirelessBMode(u16 rate)
1657{
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001658 if ( ((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220) )
Jerry Chuang8fc85982009-11-03 07:17:11 -02001659 return 1;
1660 else return 0;
1661}
1662
1663u16 N_DBPSOfRate(u16 DataRate);
1664
1665u16 ComputeTxTime(
1666 u16 FrameLength,
1667 u16 DataRate,
1668 u8 bManagementFrame,
1669 u8 bShortPreamble
1670)
1671{
1672 u16 FrameTime;
1673 u16 N_DBPS;
1674 u16 Ceiling;
1675
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001676 if ( rtl8192_IsWirelessBMode(DataRate) )
Jerry Chuang8fc85982009-11-03 07:17:11 -02001677 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001678 if ( bManagementFrame || !bShortPreamble || DataRate == 10 )
Jerry Chuang8fc85982009-11-03 07:17:11 -02001679 { // long preamble
1680 FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
1681 }
1682 else
1683 { // Short preamble
1684 FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
1685 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001686 if ( ( FrameLength*8 % (DataRate/10) ) != 0 ) //Get the Ceilling
Jerry Chuang8fc85982009-11-03 07:17:11 -02001687 FrameTime ++;
1688 } else { //802.11g DSSS-OFDM PLCP length field calculation.
1689 N_DBPS = N_DBPSOfRate(DataRate);
1690 Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
1691 + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
1692 FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
1693 }
1694 return FrameTime;
1695}
1696
1697u16 N_DBPSOfRate(u16 DataRate)
1698{
1699 u16 N_DBPS = 24;
1700
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001701 switch (DataRate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001702 {
1703 case 60:
1704 N_DBPS = 24;
1705 break;
1706
1707 case 90:
1708 N_DBPS = 36;
1709 break;
1710
1711 case 120:
1712 N_DBPS = 48;
1713 break;
1714
1715 case 180:
1716 N_DBPS = 72;
1717 break;
1718
1719 case 240:
1720 N_DBPS = 96;
1721 break;
1722
1723 case 360:
1724 N_DBPS = 144;
1725 break;
1726
1727 case 480:
1728 N_DBPS = 192;
1729 break;
1730
1731 case 540:
1732 N_DBPS = 216;
1733 break;
1734
1735 default:
1736 break;
1737 }
1738
1739 return N_DBPS;
1740}
1741
1742void rtl819xU_cmd_isr(struct urb *tx_cmd_urb, struct pt_regs *regs)
1743{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001744 usb_free_urb(tx_cmd_urb);
1745}
1746
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001747unsigned int txqueue2outpipe(struct r8192_priv *priv,unsigned int tx_queue) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001748
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001749 if (tx_queue >= 9)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001750 {
1751 RT_TRACE(COMP_ERR,"%s():Unknown queue ID!!!\n",__FUNCTION__);
1752 return 0x04;
1753 }
1754 return priv->txqueue_to_outpipemap[tx_queue];
1755}
1756
1757short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
1758{
1759 struct r8192_priv *priv = ieee80211_priv(dev);
1760 //u8 *tx;
1761 int status;
1762 struct urb *tx_urb;
1763 //int urb_buf_len;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001764 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001765 tx_desc_cmd_819x_usb *pdesc = (tx_desc_cmd_819x_usb *)skb->data;
1766 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1767 u8 queue_index = tcb_desc->queue_index;
1768
1769 //printk("\n %s::queue_index = %d\n",__FUNCTION__, queue_index);
1770 atomic_inc(&priv->tx_pending[queue_index]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001771 tx_urb = usb_alloc_urb(0,GFP_ATOMIC);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001772 if (!tx_urb){
Jerry Chuang8fc85982009-11-03 07:17:11 -02001773 dev_kfree_skb(skb);
1774 return -ENOMEM;
1775 }
1776
1777 memset(pdesc, 0, USB_HWDESC_HEADER_LEN);
1778 /* Tx descriptor ought to be set according to the skb->cb */
1779 pdesc->FirstSeg = 1;//bFirstSeg;
1780 pdesc->LastSeg = 1;//bLastSeg;
1781 pdesc->CmdInit = tcb_desc->bCmdOrInit;
1782 pdesc->TxBufferSize = tcb_desc->txbuf_size;
1783 pdesc->OWN = 1;
1784 pdesc->LINIP = tcb_desc->bLastIniPkt;
1785
1786 //----------------------------------------------------------------------------
1787 // Fill up USB_OUT_CONTEXT.
1788 //----------------------------------------------------------------------------
1789 // Get index to out pipe from specified QueueID.
1790#ifndef USE_ONE_PIPE
1791 idx_pipe = txqueue2outpipe(priv,queue_index);
1792#else
1793 idx_pipe = 0x04;
1794#endif
1795#ifdef JOHN_DUMP_TXDESC
1796 int i;
1797 printk("<Tx descriptor>--rate %x---",rate);
1798 for (i = 0; i < 8; i++)
1799 printk("%8x ", tx[i]);
1800 printk("\n");
1801#endif
1802 usb_fill_bulk_urb(tx_urb,priv->udev, usb_sndbulkpipe(priv->udev,idx_pipe), \
1803 skb->data, skb->len, rtl8192_tx_isr, skb);
1804
Jerry Chuang8fc85982009-11-03 07:17:11 -02001805 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001806
1807 if (!status){
1808 return 0;
1809 }else{
1810 DMESGE("Error TX CMD URB, error %d",
1811 status);
1812 return -1;
1813 }
1814}
1815
1816/*
1817 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1818 * in TxFwInfo data structure
1819 * 2006.10.30 by Emily
1820 *
1821 * \param QUEUEID Software Queue
1822*/
1823u8 MapHwQueueToFirmwareQueue(u8 QueueID)
1824{
1825 u8 QueueSelect = 0x0; //defualt set to
1826
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001827 switch (QueueID) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001828 case BE_QUEUE:
1829 QueueSelect = QSLT_BE; //or QSelect = pTcb->priority;
1830 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001831
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001832 case BK_QUEUE:
1833 QueueSelect = QSLT_BK; //or QSelect = pTcb->priority;
1834 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001835
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001836 case VO_QUEUE:
1837 QueueSelect = QSLT_VO; //or QSelect = pTcb->priority;
1838 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001839
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001840 case VI_QUEUE:
1841 QueueSelect = QSLT_VI; //or QSelect = pTcb->priority;
1842 break;
1843 case MGNT_QUEUE:
1844 QueueSelect = QSLT_MGNT;
1845 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001846
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001847 case BEACON_QUEUE:
1848 QueueSelect = QSLT_BEACON;
1849 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001850
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001851 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
1852 // TODO: Remove Assertions
Jerry Chuang8fc85982009-11-03 07:17:11 -02001853//#if (RTL819X_FPGA_VER & RTL819X_FPGA_GUANGAN_070502)
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001854 case TXCMD_QUEUE:
1855 QueueSelect = QSLT_CMD;
1856 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001857//#endif
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001858 case HIGH_QUEUE:
1859 QueueSelect = QSLT_HIGH;
1860 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001861
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001862 default:
1863 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
1864 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001865 }
1866 return QueueSelect;
1867}
1868
1869u8 MRateToHwRate8190Pci(u8 rate)
1870{
1871 u8 ret = DESC90_RATE1M;
1872
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001873 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001874 case MGN_1M: ret = DESC90_RATE1M; break;
1875 case MGN_2M: ret = DESC90_RATE2M; break;
1876 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1877 case MGN_11M: ret = DESC90_RATE11M; break;
1878 case MGN_6M: ret = DESC90_RATE6M; break;
1879 case MGN_9M: ret = DESC90_RATE9M; break;
1880 case MGN_12M: ret = DESC90_RATE12M; break;
1881 case MGN_18M: ret = DESC90_RATE18M; break;
1882 case MGN_24M: ret = DESC90_RATE24M; break;
1883 case MGN_36M: ret = DESC90_RATE36M; break;
1884 case MGN_48M: ret = DESC90_RATE48M; break;
1885 case MGN_54M: ret = DESC90_RATE54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001886
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001887 // HT rate since here
1888 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1889 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1890 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1891 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1892 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1893 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1894 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1895 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1896 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1897 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1898 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1899 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1900 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1901 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1902 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1903 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1904 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001905
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001906 default: break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001907 }
1908 return ret;
1909}
1910
1911
1912u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
1913{
1914 u8 tmp_Short;
1915
1916 tmp_Short = (TxHT==1)?((tcb_desc->bUseShortGI)?1:0):((tcb_desc->bUseShortPreamble)?1:0);
1917
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001918 if (TxHT==1 && TxRate != DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001919 tmp_Short = 0;
1920
1921 return tmp_Short;
1922}
1923
Jerry Chuang8fc85982009-11-03 07:17:11 -02001924static void tx_zero_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001925{
1926 return;
1927}
1928
1929/*
1930 * The tx procedure is just as following,
1931 * skb->cb will contain all the following information,
1932 * priority, morefrag, rate, &dev.
1933 * */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001934short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001935{
1936 struct r8192_priv *priv = ieee80211_priv(dev);
1937 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1938 tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data;
1939 tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
1940 struct usb_device *udev = priv->udev;
1941 int pend;
1942 int status;
1943 struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
1944 //int urb_len;
1945 unsigned int idx_pipe;
1946// RT_DEBUG_DATA(COMP_SEND, tcb_desc, sizeof(cb_desc));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001947// printk("=============> %s\n", __FUNCTION__);
1948 pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]);
1949 /* we are locked here so the two atomic_read and inc are executed
1950 * without interleaves
1951 * !!! For debug purpose
1952 */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001953 if ( pend > MAX_TX_URB){
Jerry Chuang8fc85982009-11-03 07:17:11 -02001954 printk("To discard skb packet!\n");
1955 dev_kfree_skb_any(skb);
1956 return -1;
1957 }
1958
Jerry Chuang8fc85982009-11-03 07:17:11 -02001959 tx_urb = usb_alloc_urb(0,GFP_ATOMIC);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001960 if (!tx_urb){
Jerry Chuang8fc85982009-11-03 07:17:11 -02001961 dev_kfree_skb_any(skb);
1962 return -ENOMEM;
1963 }
1964
1965 /* Fill Tx firmware info */
1966 memset(tx_fwinfo,0,sizeof(tx_fwinfo_819x_usb));
1967 /* DWORD 0 */
1968 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0;
1969 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1970 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1971 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001972 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001973 tx_fwinfo->AllowAggregation = 1;
1974 /* DWORD 1 */
1975 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1976 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1977 } else {
1978 tx_fwinfo->AllowAggregation = 0;
1979 /* DWORD 1 */
1980 tx_fwinfo->RxMF = 0;
1981 tx_fwinfo->RxAMD = 0;
1982 }
1983
1984 /* Protection mode related */
1985 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0;
1986 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0;
1987 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0;
1988 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80)?1:0;
1989 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
1990 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT==0)?(tcb_desc->RTSSC):0;
1991 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT==1)?((tcb_desc->bRTSBW)?1:0):0;
1992 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):\
1993 (tcb_desc->bRTSUseShortGI?1:0);
1994
1995 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001996 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001997 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001998 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001999 tx_fwinfo->TxBandwidth = 1;
2000 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
2001 } else {
2002 tx_fwinfo->TxBandwidth = 0;
2003 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
2004 }
2005 } else {
2006 tx_fwinfo->TxBandwidth = 0;
2007 tx_fwinfo->TxSubCarrier = 0;
2008 }
2009
2010#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2011 if (tcb_desc->drv_agg_enable)
2012 {
2013 tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1;
2014 }
2015#endif
2016 /* Fill Tx descriptor */
2017 memset(tx_desc, 0, sizeof(tx_desc_819x_usb));
2018 /* DWORD 0 */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002019 tx_desc->LINIP = 0;
2020 tx_desc->CmdInit = 1;
2021 tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002022
2023#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2024 if (tcb_desc->drv_agg_enable) {
2025 tx_desc->PktSize = tcb_desc->pkt_size;
2026 } else
2027#endif
2028 {
2029 tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff;
2030 }
2031
2032 /*DWORD 1*/
2033 tx_desc->SecCAMID= 0;
2034 tx_desc->RATid = tcb_desc->RATRIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002035 {
2036 //MPDUOverhead = 0;
2037 tx_desc->NoEnc = 1;
2038 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002039 tx_desc->SecType = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002040 if (tcb_desc->bHwSec)
2041 {
2042 switch (priv->ieee80211->pairwise_key_type)
2043 {
2044 case KEY_TYPE_WEP40:
2045 case KEY_TYPE_WEP104:
2046 tx_desc->SecType = 0x1;
2047 tx_desc->NoEnc = 0;
2048 break;
2049 case KEY_TYPE_TKIP:
2050 tx_desc->SecType = 0x2;
2051 tx_desc->NoEnc = 0;
2052 break;
2053 case KEY_TYPE_CCMP:
2054 tx_desc->SecType = 0x3;
2055 tx_desc->NoEnc = 0;
2056 break;
2057 case KEY_TYPE_NA:
2058 tx_desc->SecType = 0x0;
2059 tx_desc->NoEnc = 1;
2060 break;
2061 }
2062 }
2063
2064 tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
2065 tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
2066
2067 tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
2068 tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
2069
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002070 /* Fill fields that are required to be initialized in all of the descriptors */
2071 //DWORD 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002072 tx_desc->FirstSeg = 1;
2073 tx_desc->LastSeg = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002074 tx_desc->OWN = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002075
2076#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2077 if (tcb_desc->drv_agg_enable) {
2078 tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb);
2079 } else
2080#endif
2081 {
2082 //DWORD 2
2083 tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN);
2084 }
2085 /* Get index to out pipe from specified QueueID */
2086#ifndef USE_ONE_PIPE
2087 idx_pipe = txqueue2outpipe(priv,tcb_desc->queue_index);
2088#else
2089 idx_pipe = 0x5;
2090#endif
2091
2092 //RT_DEBUG_DATA(COMP_SEND,tx_fwinfo,sizeof(tx_fwinfo_819x_usb));
2093 //RT_DEBUG_DATA(COMP_SEND,tx_desc,sizeof(tx_desc_819x_usb));
2094
2095 /* To submit bulk urb */
2096 usb_fill_bulk_urb(tx_urb,udev,
2097 usb_sndbulkpipe(udev,idx_pipe), skb->data,
2098 skb->len, rtl8192_tx_isr, skb);
2099
Jerry Chuang8fc85982009-11-03 07:17:11 -02002100 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002101 if (!status){
2102//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
2103 bool bSend0Byte = false;
2104 u8 zero = 0;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002105 if (udev->speed == USB_SPEED_HIGH)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002106 {
2107 if (skb->len > 0 && skb->len % 512 == 0)
2108 bSend0Byte = true;
2109 }
2110 else
2111 {
2112 if (skb->len > 0 && skb->len % 64 == 0)
2113 bSend0Byte = true;
2114 }
2115 if (bSend0Byte)
2116 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002117 tx_urb_zero = usb_alloc_urb(0,GFP_ATOMIC);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002118 if (!tx_urb_zero){
Jerry Chuang8fc85982009-11-03 07:17:11 -02002119 RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
2120 return -ENOMEM;
2121 }
2122 usb_fill_bulk_urb(tx_urb_zero,udev,
2123 usb_sndbulkpipe(udev,idx_pipe), &zero,
2124 0, tx_zero_isr, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002125 status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002126 if (status){
2127 RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
2128 return -1;
2129 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002130 }
2131 dev->trans_start = jiffies;
2132 atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
2133 return 0;
Patrik Karlin29b48ae2013-01-09 09:40:23 +01002134 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002135 RT_TRACE(COMP_ERR, "Error TX URB %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]),
2136 status);
2137 return -1;
2138 }
2139}
2140
2141short rtl8192_usb_initendpoints(struct net_device *dev)
2142{
2143 struct r8192_priv *priv = ieee80211_priv(dev);
2144
Julia Lawall32414872010-05-11 20:26:57 +02002145 priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB+1),
2146 GFP_KERNEL);
David Chosrovab8345172010-12-01 13:42:16 +01002147 if (priv->rx_urb == NULL)
2148 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002149
2150#ifndef JACKSON_NEW_RX
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002151 for (i=0;i<(MAX_RX_URB+1);i++){
Jerry Chuang8fc85982009-11-03 07:17:11 -02002152
Jerry Chuang8fc85982009-11-03 07:17:11 -02002153 priv->rx_urb[i] = usb_alloc_urb(0,GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002154
2155 priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL);
2156
2157 priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE;
2158 }
2159#endif
2160
2161#ifdef THOMAS_BEACON
2162{
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002163 long align = 0;
2164 void *oldaddr, *newaddr;
2165
Jerry Chuang8fc85982009-11-03 07:17:11 -02002166 priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002167 priv->oldaddr = kmalloc(16, GFP_KERNEL);
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002168 oldaddr = priv->oldaddr;
2169 align = ((long)oldaddr) & 3;
2170 if (align) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002171 newaddr = oldaddr + 4 - align;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002172 priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align;
2173 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002174 newaddr = oldaddr;
2175 priv->rx_urb[16]->transfer_buffer_length = 16;
2176 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002177 priv->rx_urb[16]->transfer_buffer = newaddr;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002178}
2179#endif
2180
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002181 memset(priv->rx_urb, 0, sizeof(struct urb *) * MAX_RX_URB);
Julia Lawall7a6cb0d2010-05-13 22:00:05 +02002182 priv->pp_rxskb = kcalloc(MAX_RX_URB, sizeof(struct sk_buff *),
Julia Lawall32414872010-05-11 20:26:57 +02002183 GFP_KERNEL);
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02002184 if (!priv->pp_rxskb) {
2185 kfree(priv->rx_urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002186
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02002187 priv->pp_rxskb = NULL;
2188 priv->rx_urb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002189
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02002190 DMESGE("Endpoint Alloc Failure");
2191 return -ENOMEM;
2192 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002193
2194 printk("End of initendpoints\n");
2195 return 0;
2196
2197}
2198#ifdef THOMAS_BEACON
2199void rtl8192_usb_deleteendpoints(struct net_device *dev)
2200{
2201 int i;
2202 struct r8192_priv *priv = ieee80211_priv(dev);
2203
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002204 if (priv->rx_urb){
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002205 for (i=0;i<(MAX_RX_URB+1);i++){
Jerry Chuang8fc85982009-11-03 07:17:11 -02002206 usb_kill_urb(priv->rx_urb[i]);
2207 usb_free_urb(priv->rx_urb[i]);
2208 }
2209 kfree(priv->rx_urb);
2210 priv->rx_urb = NULL;
2211 }
Ilia Mirkine72714f2011-03-13 00:29:07 -05002212 kfree(priv->oldaddr);
2213 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002214 if (priv->pp_rxskb) {
2215 kfree(priv->pp_rxskb);
2216 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002217 }
2218}
2219#else
2220void rtl8192_usb_deleteendpoints(struct net_device *dev)
2221{
2222 int i;
2223 struct r8192_priv *priv = ieee80211_priv(dev);
2224
2225#ifndef JACKSON_NEW_RX
2226
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002227 if (priv->rx_urb){
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002228 for (i=0;i<(MAX_RX_URB+1);i++){
Jerry Chuang8fc85982009-11-03 07:17:11 -02002229 usb_kill_urb(priv->rx_urb[i]);
2230 kfree(priv->rx_urb[i]->transfer_buffer);
2231 usb_free_urb(priv->rx_urb[i]);
2232 }
2233 kfree(priv->rx_urb);
2234 priv->rx_urb = NULL;
2235
2236 }
2237#else
Ilia Mirkine72714f2011-03-13 00:29:07 -05002238 kfree(priv->rx_urb);
2239 priv->rx_urb = NULL;
2240 kfree(priv->oldaddr);
2241 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002242 if (priv->pp_rxskb) {
2243 kfree(priv->pp_rxskb);
2244 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002245
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002246 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002247
2248#endif
2249}
2250#endif
2251
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002252extern void rtl8192_update_ratr_table(struct net_device *dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002253void rtl8192_link_change(struct net_device *dev)
2254{
2255// int i;
2256
2257 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002258 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002259 //write_nic_word(dev, BCN_INTR_ITV, net->beacon_interval);
2260 if (ieee->state == IEEE80211_LINKED)
2261 {
2262 rtl8192_net_update(dev);
2263 rtl8192_update_ratr_table(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002264 //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
2265 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
2266 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002267 }
2268 /*update timing params*/
2269// RT_TRACE(COMP_CH, "========>%s(), chan:%d\n", __FUNCTION__, priv->chan);
2270// rtl8192_set_chan(dev, priv->chan);
2271 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002272 {
2273 u32 reg = 0;
2274 reg = read_nic_dword(dev, RCR);
2275 if (priv->ieee80211->state == IEEE80211_LINKED)
2276 priv->ReceiveConfig = reg |= RCR_CBSSID;
2277 else
2278 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
2279 write_nic_dword(dev, RCR, reg);
2280 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002281
2282// rtl8192_set_rxconf(dev);
2283}
2284
2285static struct ieee80211_qos_parameters def_qos_parameters = {
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002286 {3,3,3,3},/* cw_min */
2287 {7,7,7,7},/* cw_max */
2288 {2,2,2,2},/* aifs */
2289 {0,0,0,0},/* flags */
2290 {0,0,0,0} /* tx_op_limit */
Jerry Chuang8fc85982009-11-03 07:17:11 -02002291};
2292
2293
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002294void rtl8192_update_beacon(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002295{
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002296 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
2297 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002298 struct ieee80211_device *ieee = priv->ieee80211;
2299 struct ieee80211_network *net = &ieee->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002300
2301 if (ieee->pHTInfo->bCurrentHTSupport)
2302 HTUpdateSelfAndPeerSetting(ieee, net);
2303 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
2304 rtl8192_update_cap(dev, net->capability);
2305}
2306/*
2307* background support to run QoS activate functionality
2308*/
2309int WDCAPARA_ADD[] = {EDCAPARA_BE,EDCAPARA_BK,EDCAPARA_VI,EDCAPARA_VO};
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002310void rtl8192_qos_activate(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002311{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002312 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
2313 struct net_device *dev = priv->ieee80211->dev;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002314 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2315 u8 mode = priv->ieee80211->current_network.mode;
2316 //u32 size = sizeof(struct ieee80211_qos_parameters);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002317 u8 u1bAIFS;
2318 u32 u4bAcParam;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002319 int i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002320
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002321 if (priv == NULL)
2322 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002323
Jerry Chuang8fc85982009-11-03 07:17:11 -02002324 mutex_lock(&priv->mutex);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002325 if (priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002326 goto success;
2327 RT_TRACE(COMP_QOS,"qos active process with associate response received\n");
2328 /* It better set slot time at first */
2329 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2330 /* update the ac parameter to related registers */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002331 for (i = 0; i < QOS_QUEUE_NUM; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002332 //Mode G/A: slotTimeTimer = 9; Mode B: 20
2333 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime;
2334 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
2335 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2336 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2337 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
2338
2339 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
2340 //write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
2341 }
2342
2343success:
Jerry Chuang8fc85982009-11-03 07:17:11 -02002344 mutex_unlock(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002345}
2346
2347static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
2348 int active_network,
2349 struct ieee80211_network *network)
2350{
2351 int ret = 0;
2352 u32 size = sizeof(struct ieee80211_qos_parameters);
2353
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002354 if (priv->ieee80211->state !=IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002355 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002356
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002357 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2358 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002359
2360 if (network->flags & NETWORK_HAS_QOS_MASK) {
2361 if (active_network &&
2362 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
2363 network->qos_data.active = network->qos_data.supported;
2364
2365 if ((network->qos_data.active == 1) && (active_network == 1) &&
2366 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2367 (network->qos_data.old_param_count !=
2368 network->qos_data.param_count)) {
2369 network->qos_data.old_param_count =
2370 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002371 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002372 RT_TRACE (COMP_QOS, "QoS parameters change call "
2373 "qos_activate\n");
2374 }
2375 } else {
2376 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2377 &def_qos_parameters, size);
2378
2379 if ((network->qos_data.active == 1) && (active_network == 1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002380 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002381 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2382 }
2383 network->qos_data.active = 0;
2384 network->qos_data.supported = 0;
2385 }
2386
2387 return 0;
2388}
2389
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002390/* handle and manage frame from beacon and probe response */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002391static int rtl8192_handle_beacon(struct net_device *dev,
2392 struct ieee80211_beacon *beacon,
2393 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002394{
2395 struct r8192_priv *priv = ieee80211_priv(dev);
2396
2397 rtl8192_qos_handle_probe_response(priv,1,network);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002398 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002399 return 0;
2400
2401}
2402
2403/*
2404* handling the beaconing responses. if we get different QoS setting
2405* off the network from the associated setting, adjust the QoS
2406* setting
2407*/
2408static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002409 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002410{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002411 int ret = 0;
2412 unsigned long flags;
2413 u32 size = sizeof(struct ieee80211_qos_parameters);
2414 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002415
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002416 if ((priv == NULL) || (network == NULL))
2417 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002418
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002419 if (priv->ieee80211->state !=IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002420 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002421
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002422 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2423 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002424
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002425 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002426 if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002427 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2428 &network->qos_data.parameters,\
2429 sizeof(struct ieee80211_qos_parameters));
2430 priv->ieee80211->current_network.qos_data.active = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002431 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002432 set_qos_param = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002433 /* update qos parameter for current network */
2434 priv->ieee80211->current_network.qos_data.old_param_count = \
2435 priv->ieee80211->current_network.qos_data.param_count;
2436 priv->ieee80211->current_network.qos_data.param_count = \
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002437 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002438 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002439 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002440 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2441 &def_qos_parameters, size);
2442 priv->ieee80211->current_network.qos_data.active = 0;
2443 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002444 set_qos_param = 1;
2445 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002446
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002447 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002448
2449 RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n",__FUNCTION__,network->flags ,priv->ieee80211->current_network.qos_data.active);
2450 if (set_qos_param == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002451 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002452
2453
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002454 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002455}
2456
2457
2458static int rtl8192_handle_assoc_response(struct net_device *dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002459 struct ieee80211_assoc_response_frame *resp,
2460 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002461{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002462 struct r8192_priv *priv = ieee80211_priv(dev);
2463 rtl8192_qos_association_resp(priv, network);
2464 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002465}
2466
2467
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002468void rtl8192_update_ratr_table(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002469 // POCTET_STRING posLegacyRate,
2470 // u8* pMcsRate)
2471 // PRT_WLAN_STA pEntry)
2472{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002473 struct r8192_priv *priv = ieee80211_priv(dev);
2474 struct ieee80211_device *ieee = priv->ieee80211;
2475 u8 *pMcsRate = ieee->dot11HTOperationalRateSet;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002476 //struct ieee80211_network *net = &ieee->current_network;
2477 u32 ratr_value = 0;
2478 u8 rate_index = 0;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002479 rtl8192_config_rate(dev, (u16 *)(&ratr_value));
2480 ratr_value |= (*(u16 *)(pMcsRate)) << 12;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002481// switch (net->mode)
2482 switch (ieee->mode)
2483 {
2484 case IEEE_A:
2485 ratr_value &= 0x00000FF0;
2486 break;
2487 case IEEE_B:
2488 ratr_value &= 0x0000000F;
2489 break;
2490 case IEEE_G:
2491 ratr_value &= 0x00000FF7;
2492 break;
2493 case IEEE_N_24G:
2494 case IEEE_N_5G:
2495 if (ieee->pHTInfo->PeerMimoPs == 0) //MIMO_PS_STATIC
2496 ratr_value &= 0x0007F007;
2497 else{
2498 if (priv->rf_type == RF_1T2R)
2499 ratr_value &= 0x000FF007;
2500 else
2501 ratr_value &= 0x0F81F007;
2502 }
2503 break;
2504 default:
2505 break;
2506 }
2507 ratr_value &= 0x0FFFFFFF;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002508 if (ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz){
Jerry Chuang8fc85982009-11-03 07:17:11 -02002509 ratr_value |= 0x80000000;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002510 }else if (!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz){
Jerry Chuang8fc85982009-11-03 07:17:11 -02002511 ratr_value |= 0x80000000;
2512 }
2513 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2514 write_nic_byte(dev, UFWP, 1);
2515}
2516
2517static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
2518static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002519bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002520{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002521 struct r8192_priv *priv = ieee80211_priv(dev);
2522 struct ieee80211_device *ieee = priv->ieee80211;
2523 struct ieee80211_network *network = &ieee->current_network;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002524 int wpa_ie_len= ieee->wpa_ie_len;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002525 struct ieee80211_crypt_data *crypt;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002526 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002527
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002528 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002529 //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 -02002530 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 -02002531
2532 /* simply judge */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002533 if (encrypt && (wpa_ie_len == 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002534 /* wep encryption, no N mode setting */
2535 return false;
2536// } else if((wpa_ie_len != 0)&&(memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002537 } else if ((wpa_ie_len != 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002538 /* parse pairwise key type */
2539 //if((pairwisekey = WEP40)||(pairwisekey = WEP104)||(pairwisekey = TKIP))
2540 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))))
2541 return true;
2542 else
2543 return false;
2544 } else {
2545 return true;
2546 }
2547
Jerry Chuang8fc85982009-11-03 07:17:11 -02002548 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002549}
2550
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002551bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002552{
2553 bool Reval;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002554 struct r8192_priv *priv = ieee80211_priv(dev);
2555 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002556
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002557 if (ieee->bHalfWirelessN24GMode == true)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002558 Reval = true;
2559 else
2560 Reval = false;
2561
2562 return Reval;
2563}
2564
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002565void rtl8192_refresh_supportrate(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002566{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002567 struct ieee80211_device *ieee = priv->ieee80211;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002568 //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002569 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
2570 {
2571 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
2572 //RT_DEBUG_DATA(COMP_INIT, ieee->RegHTSuppRateSet, 16);
2573 //RT_DEBUG_DATA(COMP_INIT, ieee->Regdot11HTOperationalRateSet, 16);
2574 }
2575 else
2576 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2577 return;
2578}
2579
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002580u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002581{
2582 struct r8192_priv *priv = ieee80211_priv(dev);
2583 u8 ret = 0;
Xenia Ragiadakouad638452013-05-12 03:15:08 +03002584 switch (priv->rf_chip)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002585 {
2586 case RF_8225:
2587 case RF_8256:
2588 case RF_PSEUDO_11N:
2589 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2590 break;
2591 case RF_8258:
2592 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2593 break;
2594 default:
2595 ret = WIRELESS_MODE_B;
2596 break;
2597 }
2598 return ret;
2599}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002600void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002601{
2602 struct r8192_priv *priv = ieee80211_priv(dev);
2603 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002605 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode)==0))
2606 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002607 if (bSupportMode & WIRELESS_MODE_N_24G)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002608 {
2609 wireless_mode = WIRELESS_MODE_N_24G;
2610 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002611 else if (bSupportMode & WIRELESS_MODE_N_5G)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002612 {
2613 wireless_mode = WIRELESS_MODE_N_5G;
2614 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002615 else if ((bSupportMode & WIRELESS_MODE_A))
Jerry Chuang8fc85982009-11-03 07:17:11 -02002616 {
2617 wireless_mode = WIRELESS_MODE_A;
2618 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002619 else if ((bSupportMode & WIRELESS_MODE_G))
Jerry Chuang8fc85982009-11-03 07:17:11 -02002620 {
2621 wireless_mode = WIRELESS_MODE_G;
2622 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002623 else if ((bSupportMode & WIRELESS_MODE_B))
Jerry Chuang8fc85982009-11-03 07:17:11 -02002624 {
2625 wireless_mode = WIRELESS_MODE_B;
2626 }
2627 else{
2628 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __FUNCTION__,bSupportMode);
2629 wireless_mode = WIRELESS_MODE_B;
2630 }
2631 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002632#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 -02002633 ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
2634#endif
2635 priv->ieee80211->mode = wireless_mode;
2636
2637 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2638 priv->ieee80211->pHTInfo->bEnableHT = 1;
2639 else
2640 priv->ieee80211->pHTInfo->bEnableHT = 0;
2641 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2642 rtl8192_refresh_supportrate(priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002643
2644}
2645//init priv variables here. only non_zero value should be initialized here.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002646static void rtl8192_init_priv_variable(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002647{
2648 struct r8192_priv *priv = ieee80211_priv(dev);
2649 u8 i;
2650 priv->card_8192 = NIC_8192U;
2651 priv->chan = 1; //set to channel 1
2652 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2653 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2654 priv->ieee80211->ieee_up=0;
2655 priv->retry_rts = DEFAULT_RETRY_RTS;
2656 priv->retry_data = DEFAULT_RETRY_DATA;
2657 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2658 priv->ieee80211->rate = 110; //11 mbps
2659 priv->ieee80211->short_slot = 1;
2660 priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0;
2661 priv->CckPwEnl = 6;
2662 //for silent reset
2663 priv->IrpPendingCount = 1;
2664 priv->ResetProgress = RESET_TYPE_NORESET;
2665 priv->bForcedSilentReset = 0;
2666 priv->bDisableNormalResetCheck = false;
2667 priv->force_reset = false;
2668
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002669 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002670 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2671 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2672 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2673 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2674 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
2675 IEEE_SOFTMAC_BEACONS;//added by amy 080604 //| //IEEE_SOFTMAC_SINGLE_QUEUE;
2676
2677 priv->ieee80211->active_scan = 1;
2678 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2679 priv->ieee80211->host_encrypt = 1;
2680 priv->ieee80211->host_decrypt = 1;
2681 priv->ieee80211->start_send_beacons = NULL;//rtl819xusb_beacon_tx;//-by amy 080604
2682 priv->ieee80211->stop_send_beacons = NULL;//rtl8192_beacon_stop;//-by amy 080604
2683 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2684 priv->ieee80211->set_chan = rtl8192_set_chan;
2685 priv->ieee80211->link_change = rtl8192_link_change;
2686 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2687 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2688 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2689 priv->ieee80211->init_wmmparam_flag = 0;
2690 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2691 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2692 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
2693 priv->ieee80211->qos_support = 1;
2694
2695 //added by WB
2696// priv->ieee80211->SwChnlByTimerHandler = rtl8192_phy_SwChnl;
2697 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2698 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2699 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2700 //added by david
2701 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
2702 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
2703 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2704 //added by amy
2705 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
2706 priv->card_type = USB;
2707#ifdef TO_DO_LIST
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002708 if (Adapter->bInHctTest)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002709 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002710 pHalData->ShortRetryLimit = 7;
2711 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002712 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002713#endif
2714 {
2715 priv->ShortRetryLimit = 0x30;
2716 priv->LongRetryLimit = 0x30;
2717 }
2718 priv->EarlyRxThreshold = 7;
2719 priv->enable_gpio0 = 0;
2720 priv->TransmitConfig =
2721 // TCR_DurProcMode | //for RTL8185B, duration setting by HW
2722 //? TCR_DISReqQsize |
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002723 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002724 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
2725 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07002726 (false ? TCR_SAT: 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
Jerry Chuang8fc85982009-11-03 07:17:11 -02002727#ifdef TO_DO_LIST
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002728 if (Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002729 pHalData->ReceiveConfig = pHalData->CSMethod |
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002730 RCR_AMF | RCR_ADF | //RCR_AAP | //accept management/data
Jerry Chuang8fc85982009-11-03 07:17:11 -02002731 //guangan200710
2732 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2733 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002734 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002735 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2736 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
2737 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt:0);
2738 else
2739
2740#endif
2741 priv->ReceiveConfig =
2742 RCR_AMF | RCR_ADF | //accept management/data
2743 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2744 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002745 //RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002746 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2747 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
2748 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT:0);
2749
2750 priv->AcmControl = 0;
Devendra Nagab7553422012-08-26 11:06:33 +05302751 priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002752
2753 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002754 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002755 skb_queue_head_init(&priv->skb_queue);
2756
2757 /* Tx related queue */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002758 for (i = 0; i < MAX_QUEUE_SIZE; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002759 skb_queue_head_init(&priv->ieee80211->skb_waitQ [i]);
2760 }
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002761 for (i = 0; i < MAX_QUEUE_SIZE; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002762 skb_queue_head_init(&priv->ieee80211->skb_aggQ [i]);
2763 }
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002764 for (i = 0; i < MAX_QUEUE_SIZE; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002765 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ [i]);
2766 }
2767 priv->rf_set_chan = rtl8192_phy_SwChnl;
2768}
2769
2770//init lock here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002771static void rtl8192_init_priv_lock(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002772{
2773 spin_lock_init(&priv->tx_lock);
2774 spin_lock_init(&priv->irq_lock);//added by thomas
2775 //spin_lock_init(&priv->rf_lock);
2776 sema_init(&priv->wx_sem,1);
2777 sema_init(&priv->rf_sem,1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002778 mutex_init(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002779}
2780
Jerry Chuang8fc85982009-11-03 07:17:11 -02002781extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002782
2783void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
2784//init tasklet and wait_queue here. only 2.6 above kernel is considered
2785#define DRV_NAME "wlan0"
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002786static void rtl8192_init_priv_task(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002787{
2788 struct r8192_priv *priv = ieee80211_priv(dev);
2789
Jerry Chuang8fc85982009-11-03 07:17:11 -02002790 priv->priv_wq = create_workqueue(DRV_NAME);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002791
Jerry Chuang8fc85982009-11-03 07:17:11 -02002792 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2793
2794 //INIT_DELAYED_WORK(&priv->watch_dog_wq, hal_dm_watchdog);
2795 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2796 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
2797// INIT_DELAYED_WORK(&priv->gpio_change_rf_wq, dm_gpio_change_rf_callback);
2798 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2799 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2800 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
2801 //INIT_WORK(&priv->SwChnlWorkItem, rtl8192_SwChnl_WorkItem);
2802 //INIT_WORK(&priv->SetBWModeWorkItem, rtl8192_SetBWModeWorkItem);
2803 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002804
2805 tasklet_init(&priv->irq_rx_tasklet,
2806 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2807 (unsigned long)priv);
2808}
2809
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002810static void rtl8192_get_eeprom_size(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002811{
2812 u16 curCR = 0;
2813 struct r8192_priv *priv = ieee80211_priv(dev);
2814 RT_TRACE(COMP_EPROM, "===========>%s()\n", __FUNCTION__);
2815 curCR = read_nic_word_E(dev,EPROM_CMD);
2816 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
2817 //whether need I consider BIT5?
2818 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
2819 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __FUNCTION__, priv->epromtype);
2820}
2821
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002822//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002823static inline u16 endian_swap(u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002824{
2825 u16 tmp = *data;
2826 *data = (tmp >> 8) | (tmp << 8);
2827 return *data;
2828}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002829static void rtl8192_read_eeprom_info(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002830{
2831 u16 wEPROM_ID = 0;
2832 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
2833 u8 bLoad_From_EEPOM = false;
2834 struct r8192_priv *priv = ieee80211_priv(dev);
2835 u16 tmpValue = 0;
2836 RT_TRACE(COMP_EPROM, "===========>%s()\n", __FUNCTION__);
2837 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
2838 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
2839
2840 if (wEPROM_ID != RTL8190_EEPROM_ID)
2841 {
2842 RT_TRACE(COMP_ERR, "EEPROM ID is invalid(is 0x%x(should be 0x%x)\n", wEPROM_ID, RTL8190_EEPROM_ID);
2843 }
2844 else
2845 bLoad_From_EEPOM = true;
2846
2847 if (bLoad_From_EEPOM)
2848 {
2849 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
2850 priv->eeprom_vid = endian_swap(&tmpValue);
2851 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
2852 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
2853 priv->eeprom_ChannelPlan =((tmpValue&0xff00)>>8);
2854 priv->btxpowerdata_readfromEEPORM = true;
2855 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
2856 }
2857 else
2858 {
2859 priv->eeprom_vid = 0;
2860 priv->eeprom_pid = 0;
2861 priv->card_8192_version = VERSION_819xU_B;
2862 priv->eeprom_ChannelPlan = 0;
2863 priv->eeprom_CustomerID = 0;
2864 }
2865 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);
2866 //set channelplan from eeprom
2867 priv->ChannelPlan = priv->eeprom_ChannelPlan;
2868 if (bLoad_From_EEPOM)
2869 {
2870 int i;
2871 for (i=0; i<6; i+=2)
2872 {
2873 u16 tmp = 0;
2874 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002875 *(u16 *)(&dev->dev_addr[i]) = tmp;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002876 }
2877 }
2878 else
2879 {
2880 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2881 //should I set IDR0 here?
2882 }
Joe Perches0ee9f672009-12-06 11:34:52 -08002883 RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002884 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
2885 priv->rf_chip = RF_8256;
2886
2887 if (priv->card_8192_version == (u8)VERSION_819xU_A)
2888 {
2889 //read Tx power gain offset of legacy OFDM to HT rate
2890 if (bLoad_From_EEPOM)
2891 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
2892 else
2893 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
2894 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
2895 //read ThermalMeter from EEPROM
2896 if (bLoad_From_EEPOM)
2897 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
2898 else
2899 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2900 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
2901 //vivi, for tx power track
2902 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2903 //read antenna tx power offset of B/C/D to A from EEPROM
2904 if (bLoad_From_EEPOM)
2905 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
2906 else
2907 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
2908 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
2909 // Read CrystalCap from EEPROM
2910 if (bLoad_From_EEPOM)
2911 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
2912 else
2913 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
2914 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
2915 //get per-channel Tx power level
2916 if (bLoad_From_EEPOM)
2917 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
2918 else
2919 priv->EEPROM_Def_Ver = 1;
2920 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
2921 if (priv->EEPROM_Def_Ver == 0) //old eeprom definition
2922 {
2923 int i;
2924 if (bLoad_From_EEPOM)
2925 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
2926 else
2927 priv->EEPROMTxPowerLevelCCK = 0x10;
2928 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
2929 for (i=0; i<3; i++)
2930 {
2931 if (bLoad_From_EEPOM)
2932 {
2933 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
2934 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
2935 tmpValue = tmpValue & 0x00ff;
2936 else
2937 tmpValue = (tmpValue & 0xff00) >> 8;
2938 }
2939 else
2940 tmpValue = 0x10;
2941 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
2942 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
2943 }
2944 }//end if EEPROM_DEF_VER == 0
2945 else if (priv->EEPROM_Def_Ver == 1)
2946 {
2947 if (bLoad_From_EEPOM)
2948 {
2949 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
2950 tmpValue = (tmpValue & 0xff00) >> 8;
2951 }
2952 else
2953 tmpValue = 0x10;
2954 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
2955
2956 if (bLoad_From_EEPOM)
2957 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
2958 else
2959 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002960 *((u16 *)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002961 if (bLoad_From_EEPOM)
2962 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
2963 else
2964 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002965 *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002966 if (bLoad_From_EEPOM)
2967 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
2968 else
2969 tmpValue = 0x10;
2970 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
2971 }//endif EEPROM_Def_Ver == 1
2972
2973 //update HAL variables
2974 //
2975 {
2976 int i;
2977 for (i=0; i<14; i++)
2978 {
2979 if (i<=3)
2980 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
2981 else if (i>=4 && i<=9)
2982 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
2983 else
2984 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
2985 }
2986
2987 for (i=0; i<14; i++)
2988 {
2989 if (priv->EEPROM_Def_Ver == 0)
2990 {
2991 if (i<=3)
2992 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2993 else if (i>=4 && i<=9)
2994 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
2995 else
2996 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2997 }
2998 else if (priv->EEPROM_Def_Ver == 1)
2999 {
3000 if (i<=3)
3001 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
3002 else if (i>=4 && i<=9)
3003 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
3004 else
3005 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
3006 }
3007 }
3008 }//end update HAL variables
3009 priv->TxPowerDiff = priv->EEPROMPwDiff;
3010// Antenna B gain offset to antenna A, bit0~3
3011 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
3012 // Antenna C gain offset to antenna A, bit4~7
3013 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
3014 // CrystalCap, bit12~15
3015 priv->CrystalCap = priv->EEPROMCrystalCap;
3016 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
3017 // 92U does not enable TX power tracking.
3018 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
3019 }//end if VersionID == VERSION_819xU_A
3020
3021//added by vivi, for dlink led, 20080416
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003022 switch (priv->eeprom_CustomerID)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003023 {
3024 case EEPROM_CID_RUNTOP:
3025 priv->CustomerID = RT_CID_819x_RUNTOP;
3026 break;
3027
3028 case EEPROM_CID_DLINK:
3029 priv->CustomerID = RT_CID_DLINK;
3030 break;
3031
3032 default:
3033 priv->CustomerID = RT_CID_DEFAULT;
3034 break;
3035
3036 }
3037
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003038 switch (priv->CustomerID)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003039 {
3040 case RT_CID_819x_RUNTOP:
3041 priv->LedStrategy = SW_LED_MODE2;
3042 break;
3043
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003044 case RT_CID_DLINK:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003045 priv->LedStrategy = SW_LED_MODE4;
3046 break;
3047
3048 default:
3049 priv->LedStrategy = SW_LED_MODE0;
3050 break;
3051
3052 }
3053
3054
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003055 if (priv->rf_type == RF_1T2R)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003056 {
3057 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
3058 }
3059 else
3060 {
3061 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
3062 }
3063
3064 // 2008/01/16 MH We can only know RF type in the function. So we have to init
3065 // DIG RATR table again.
3066 init_rate_adaptive(dev);
3067 //we need init DIG RATR table here again.
3068
3069 RT_TRACE(COMP_EPROM, "<===========%s()\n", __FUNCTION__);
3070 return;
3071}
3072
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003073short rtl8192_get_channel_map(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003074{
3075 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003076 if (priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN){
Jerry Chuang8fc85982009-11-03 07:17:11 -02003077 printk("rtl8180_init:Error channel plan! Set to default.\n");
3078 priv->ChannelPlan= 0;
3079 }
3080 RT_TRACE(COMP_INIT, "Channel plan is %d\n",priv->ChannelPlan);
3081
3082 rtl819x_set_channel_map(priv->ChannelPlan, priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003083 return 0;
3084}
3085
3086short rtl8192_init(struct net_device *dev)
3087{
3088
3089 struct r8192_priv *priv = ieee80211_priv(dev);
3090
3091 memset(&(priv->stats),0,sizeof(struct Stats));
3092 memset(priv->txqueue_to_outpipemap,0,9);
3093#ifdef PIPE12
3094 {
3095 int i=0;
3096 u8 queuetopipe[]={3,2,1,0,4,8,7,6,5};
3097 memcpy(priv->txqueue_to_outpipemap,queuetopipe,9);
3098/* for(i=0;i<9;i++)
3099 printk("%d ",priv->txqueue_to_outpipemap[i]);
3100 printk("\n");*/
3101 }
3102#else
3103 {
3104 u8 queuetopipe[]={3,2,1,0,4,4,0,4,4};
3105 memcpy(priv->txqueue_to_outpipemap,queuetopipe,9);
3106/* for(i=0;i<9;i++)
3107 printk("%d ",priv->txqueue_to_outpipemap[i]);
3108 printk("\n");*/
3109 }
3110#endif
3111 rtl8192_init_priv_variable(dev);
3112 rtl8192_init_priv_lock(priv);
3113 rtl8192_init_priv_task(dev);
3114 rtl8192_get_eeprom_size(dev);
3115 rtl8192_read_eeprom_info(dev);
3116 rtl8192_get_channel_map(dev);
3117 init_hal_dm(dev);
3118 init_timer(&priv->watch_dog_timer);
3119 priv->watch_dog_timer.data = (unsigned long)dev;
3120 priv->watch_dog_timer.function = watch_dog_timer_callback;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003121 if (rtl8192_usb_initendpoints(dev)!=0){
Jerry Chuang8fc85982009-11-03 07:17:11 -02003122 DMESG("Endopoints initialization failed");
3123 return -ENOMEM;
3124 }
3125
3126 //rtl8192_adapter_start(dev);
3127#ifdef DEBUG_EPROM
3128 dump_eprom(dev);
3129#endif
3130 return 0;
3131}
3132
3133/******************************************************************************
3134 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
3135 * not to do all the hw config as its name says
3136 * input: net_device dev
3137 * output: none
3138 * return: none
3139 * notice: This part need to modified according to the rate set we filtered
3140 * ****************************************************************************/
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003141void rtl8192_hwconfig(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003142{
3143 u32 regRATR = 0, regRRSR = 0;
3144 u8 regBwOpMode = 0, regTmp = 0;
3145 struct r8192_priv *priv = ieee80211_priv(dev);
3146
3147// Set RRSR, RATR, and BW_OPMODE registers
3148 //
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003149 switch (priv->ieee80211->mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003150 {
3151 case WIRELESS_MODE_B:
3152 regBwOpMode = BW_OPMODE_20MHZ;
3153 regRATR = RATE_ALL_CCK;
3154 regRRSR = RATE_ALL_CCK;
3155 break;
3156 case WIRELESS_MODE_A:
3157 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
3158 regRATR = RATE_ALL_OFDM_AG;
3159 regRRSR = RATE_ALL_OFDM_AG;
3160 break;
3161 case WIRELESS_MODE_G:
3162 regBwOpMode = BW_OPMODE_20MHZ;
3163 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3164 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3165 break;
3166 case WIRELESS_MODE_AUTO:
3167#ifdef TO_DO_LIST
3168 if (Adapter->bInHctTest)
3169 {
3170 regBwOpMode = BW_OPMODE_20MHZ;
3171 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3172 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3173 }
3174 else
3175#endif
3176 {
3177 regBwOpMode = BW_OPMODE_20MHZ;
3178 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
3179 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3180 }
3181 break;
3182 case WIRELESS_MODE_N_24G:
3183 // It support CCK rate by default.
3184 // CCK rate will be filtered out only when associated AP does not support it.
3185 regBwOpMode = BW_OPMODE_20MHZ;
3186 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
3187 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3188 break;
3189 case WIRELESS_MODE_N_5G:
3190 regBwOpMode = BW_OPMODE_5G;
3191 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
3192 regRRSR = RATE_ALL_OFDM_AG;
3193 break;
3194 }
3195
3196 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
3197 {
3198 u32 ratr_value = 0;
3199 ratr_value = regRATR;
3200 if (priv->rf_type == RF_1T2R)
3201 {
3202 ratr_value &= ~(RATE_ALL_OFDM_2SS);
3203 }
3204 write_nic_dword(dev, RATR0, ratr_value);
3205 write_nic_byte(dev, UFWP, 1);
3206 }
3207 regTmp = read_nic_byte(dev, 0x313);
3208 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
3209 write_nic_dword(dev, RRSR, regRRSR);
3210
3211 //
3212 // Set Retry Limit here
3213 //
3214 write_nic_word(dev, RETRY_LIMIT,
3215 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT | \
3216 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
3217 // Set Contention Window here
3218
3219 // Set Tx AGC
3220
3221 // Set Tx Antenna including Feedback control
3222
3223 // Set Auto Rate fallback control
3224
3225
3226}
3227
3228
3229//InitializeAdapter and PhyCfg
3230bool rtl8192_adapter_start(struct net_device *dev)
3231{
3232 struct r8192_priv *priv = ieee80211_priv(dev);
3233 u32 dwRegRead = 0;
3234 bool init_status = true;
3235 RT_TRACE(COMP_INIT, "====>%s()\n", __FUNCTION__);
3236 priv->Rf_Mode = RF_OP_By_SW_3wire;
3237 //for ASIC power on sequence
3238 write_nic_byte_E(dev, 0x5f, 0x80);
3239 mdelay(50);
3240 write_nic_byte_E(dev, 0x5f, 0xf0);
3241 write_nic_byte_E(dev, 0x5d, 0x00);
3242 write_nic_byte_E(dev, 0x5e, 0x80);
3243 write_nic_byte(dev, 0x17, 0x37);
3244 mdelay(10);
3245//#ifdef TO_DO_LIST
3246 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
3247 //config CPUReset Register
3248 //Firmware Reset or not?
3249 dwRegRead = read_nic_dword(dev, CPU_GEN);
3250 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
3251 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
3252 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
3253 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
3254 else
3255 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __FUNCTION__, priv->pFirmware->firmware_status);
3256
3257 write_nic_dword(dev, CPU_GEN, dwRegRead);
3258 //mdelay(30);
3259 //config BB.
3260 rtl8192_BBConfig(dev);
3261
Jerry Chuang8fc85982009-11-03 07:17:11 -02003262 //Loopback mode or not
3263 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
3264// priv->LoopbackMode = RTL819xU_MAC_LOOPBACK;
3265
3266 dwRegRead = read_nic_dword(dev, CPU_GEN);
3267 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
3268 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
3269 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
3270 dwRegRead |= CPU_CCK_LOOPBACK;
3271 else
3272 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __FUNCTION__, priv->LoopbackMode);
3273
3274 write_nic_dword(dev, CPU_GEN, dwRegRead);
3275
3276 //after reset cpu, we need wait for a seconds to write in register.
3277 udelay(500);
3278
3279 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
3280 write_nic_byte_E(dev, 0x5f, (read_nic_byte_E(dev, 0x5f)|0x20));
3281
3282 //Set Hardware
3283 rtl8192_hwconfig(dev);
3284
3285 //turn on Tx/Rx
3286 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
3287
3288 //set IDR0 here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003289 write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
3290 write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003291
3292 //set RCR
3293 write_nic_dword(dev, RCR, priv->ReceiveConfig);
3294
3295 //Initialize Number of Reserved Pages in Firmware Queue
3296 write_nic_dword(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << RSVD_FW_QUEUE_PAGE_BK_SHIFT |\
3297 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT | \
3298 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT | \
3299 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
3300 write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT |\
3301 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
3302 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW| \
3303 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT
3304// | NUM_OF_PAGE_IN_FW_QUEUE_PUB<<RSVD_FW_QUEUE_PAGE_PUB_SHIFT
3305 );
3306 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
3307
3308 //Set AckTimeout
3309 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
3310 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
3311
3312// RT_TRACE(COMP_INIT, "%s():priv->ResetProgress is %d\n", __FUNCTION__,priv->ResetProgress);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003313 if (priv->ResetProgress == RESET_TYPE_NORESET)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003314 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003315 if (priv->ResetProgress == RESET_TYPE_NORESET){
Jerry Chuang8fc85982009-11-03 07:17:11 -02003316 CamResetAllEntry(dev);
3317 {
3318 u8 SECR_value = 0x0;
3319 SECR_value |= SCR_TxEncEnable;
3320 SECR_value |= SCR_RxDecEnable;
3321 SECR_value |= SCR_NoSKMC;
3322 write_nic_byte(dev, SECR, SECR_value);
3323 }
3324 }
3325
3326 //Beacon related
3327 write_nic_word(dev, ATIMWND, 2);
3328 write_nic_word(dev, BCN_INTERVAL, 100);
3329
3330 {
3331#define DEFAULT_EDCA 0x005e4332
3332 int i;
3333 for (i=0; i<QOS_QUEUE_NUM; i++)
3334 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
3335 }
3336#ifdef USB_RX_AGGREGATION_SUPPORT
3337 //3 For usb rx firmware aggregation control
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003338 if (priv->ResetProgress == RESET_TYPE_NORESET)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003339 {
3340 u32 ulValue;
3341 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
3342 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
3343 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
3344 /*
3345 * If usb rx firmware aggregation is enabled,
3346 * when anyone of three threshold conditions above is reached,
3347 * firmware will send aggregated packet to driver.
3348 */
3349 write_nic_dword(dev, 0x1a8, ulValue);
3350 priv->bCurrentRxAggrEnable = true;
3351 }
3352#endif
3353
3354 rtl8192_phy_configmac(dev);
3355
3356 if (priv->card_8192_version == (u8) VERSION_819xU_A)
3357 {
3358 rtl8192_phy_getTxPower(dev);
3359 rtl8192_phy_setTxPower(dev, priv->chan);
3360 }
3361
3362 //Firmware download
3363 init_status = init_firmware(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003364 if (!init_status)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003365 {
3366 RT_TRACE(COMP_ERR,"ERR!!! %s(): Firmware download is failed\n", __FUNCTION__);
3367 return init_status;
3368 }
3369 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __FUNCTION__);
3370 //
3371#ifdef TO_DO_LIST
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003372if (Adapter->ResetProgress == RESET_TYPE_NORESET)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003373 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003374 if (pMgntInfo->RegRfOff == TRUE)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003375 { // User disable RF via registry.
3376 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
3377 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003378 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03003379 for (eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003380 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3381 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003382 else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003383 { // H/W or S/W RF OFF before sleep.
3384 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
3385 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
3386 }
3387 else
3388 {
3389 pHalData->eRFPowerState = eRfOn;
3390 pMgntInfo->RfOffReason = 0;
3391 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
3392 }
3393 }
3394 else
3395 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003396 if (pHalData->eRFPowerState == eRfOff)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003397 {
3398 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003399 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03003400 for (eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003401 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3402 }
3403 }
3404#endif
3405 //config RF.
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003406 if (priv->ResetProgress == RESET_TYPE_NORESET){
Jerry Chuang8fc85982009-11-03 07:17:11 -02003407 rtl8192_phy_RFConfig(dev);
3408 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __FUNCTION__);
3409 }
3410
3411
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003412 if (priv->ieee80211->FwRWRF)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003413 // We can force firmware to do RF-R/W
3414 priv->Rf_Mode = RF_OP_By_FW;
3415 else
3416 priv->Rf_Mode = RF_OP_By_SW_3wire;
3417
3418
3419 rtl8192_phy_updateInitGain(dev);
3420 /*--set CCK and OFDM Block "ON"--*/
3421 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3422 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3423
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003424 if (priv->ResetProgress == RESET_TYPE_NORESET)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003425 {
3426 //if D or C cut
3427 u8 tmpvalue = read_nic_byte(dev, 0x301);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003428 if (tmpvalue ==0x03)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003429 {
3430 priv->bDcut = TRUE;
3431 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
3432 }
3433 else
3434 {
3435 priv->bDcut = FALSE;
3436 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
3437 }
3438 dm_initialize_txpower_tracking(dev);
3439
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003440 if (priv->bDcut == TRUE)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003441 {
3442 u32 i, TempCCk;
3443 u32 tmpRegA= rtl8192_QueryBBReg(dev,rOFDM0_XATxIQImbalance,bMaskDWord);
3444 // u32 tmpRegC= rtl8192_QueryBBReg(dev,rOFDM0_XCTxIQImbalance,bMaskDWord);
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03003445 for (i = 0; i<TxBBGainTableLength; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003446 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003447 if (tmpRegA == priv->txbbgain_table[i].txbbgain_value)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003448 {
3449 priv->rfa_txpowertrackingindex= (u8)i;
3450 priv->rfa_txpowertrackingindex_real= (u8)i;
3451 priv->rfa_txpowertracking_default= priv->rfa_txpowertrackingindex;
3452 break;
3453 }
3454 }
3455
3456 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3457
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03003458 for (i=0 ; i<CCKTxBBGainTableLength ; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003459 {
3460
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003461 if (TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0])
Jerry Chuang8fc85982009-11-03 07:17:11 -02003462 {
3463 priv->cck_present_attentuation_20Mdefault=(u8) i;
3464 break;
3465 }
3466 }
3467 priv->cck_present_attentuation_40Mdefault= 0;
3468 priv->cck_present_attentuation_difference= 0;
3469 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
3470
3471 // pMgntInfo->bTXPowerTracking = FALSE;//TEMPLY DISABLE
3472 }
3473 }
3474 write_nic_byte(dev, 0x87, 0x0);
3475
3476
Jerry Chuang8fc85982009-11-03 07:17:11 -02003477 return init_status;
3478}
3479
3480/* this configures registers for beacon tx and enables it via
3481 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3482 * be used to stop beacon transmission
3483 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003484/***************************************************************************
3485 -------------------------------NET STUFF---------------------------
3486***************************************************************************/
3487
3488static struct net_device_stats *rtl8192_stats(struct net_device *dev)
3489{
3490 struct r8192_priv *priv = ieee80211_priv(dev);
3491
3492 return &priv->ieee80211->stats;
3493}
3494
3495bool
3496HalTxCheckStuck819xUsb(
3497 struct net_device *dev
3498 )
3499{
3500 struct r8192_priv *priv = ieee80211_priv(dev);
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003501 u16 RegTxCounter = read_nic_word(dev, 0x128);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003502 bool bStuck = FALSE;
3503 RT_TRACE(COMP_RESET,"%s():RegTxCounter is %d,TxCounter is %d\n",__FUNCTION__,RegTxCounter,priv->TxCounter);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003504 if (priv->TxCounter==RegTxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003505 bStuck = TRUE;
3506
3507 priv->TxCounter = RegTxCounter;
3508
3509 return bStuck;
3510}
3511
3512/*
3513* <Assumption: RT_TX_SPINLOCK is acquired.>
3514* First added: 2006.11.19 by emily
3515*/
3516RESET_TYPE
3517TxCheckStuck(struct net_device *dev)
3518{
3519 struct r8192_priv *priv = ieee80211_priv(dev);
3520 u8 QueueID;
3521// PRT_TCB pTcb;
3522// u8 ResetThreshold;
3523 bool bCheckFwTxCnt = false;
3524 //unsigned long flags;
3525
3526 //
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003527 // Decide such threshold according to current power save mode
Jerry Chuang8fc85982009-11-03 07:17:11 -02003528 //
3529
3530// RT_TRACE(COMP_RESET, " ==> TxCheckStuck()\n");
3531// PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
3532// spin_lock_irqsave(&priv->ieee80211->lock,flags);
3533 for (QueueID = 0; QueueID<=BEACON_QUEUE;QueueID ++)
3534 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003535 if (QueueID == TXCMD_QUEUE)
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01003536 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003537#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003538 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))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003539#else
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003540 if ((skb_queue_len(&priv->ieee80211->skb_waitQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_aggQ[QueueID]) == 0))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003541#endif
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003542 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003543
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01003544 bCheckFwTxCnt = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003545 }
3546// PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
3547// spin_unlock_irqrestore(&priv->ieee80211->lock,flags);
3548// RT_TRACE(COMP_RESET,"bCheckFwTxCnt is %d\n",bCheckFwTxCnt);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003549 if (bCheckFwTxCnt)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003550 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003551 if (HalTxCheckStuck819xUsb(dev))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003552 {
3553 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
3554 return RESET_TYPE_SILENT;
3555 }
3556 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003557 return RESET_TYPE_NORESET;
3558}
3559
3560bool
3561HalRxCheckStuck819xUsb(struct net_device *dev)
3562{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003563 u16 RegRxCounter = read_nic_word(dev, 0x130);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003564 struct r8192_priv *priv = ieee80211_priv(dev);
3565 bool bStuck = FALSE;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003566 static u8 rx_chk_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003567 RT_TRACE(COMP_RESET,"%s(): RegRxCounter is %d,RxCounter is %d\n",__FUNCTION__,RegRxCounter,priv->RxCounter);
3568 // If rssi is small, we should check rx for long time because of bad rx.
3569 // or maybe it will continuous silent reset every 2 seconds.
3570 rx_chk_cnt++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003571 if (priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003572 {
3573 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
3574 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003575 else if (priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
Jerry Chuang8fc85982009-11-03 07:17:11 -02003576 ((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_40M) ||
3577 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_20M)) )
3578 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003579 if (rx_chk_cnt < 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003580 {
3581 return bStuck;
3582 }
3583 else
3584 {
3585 rx_chk_cnt = 0;
3586 }
3587 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003588 else if (((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_40M) ||
Jerry Chuang8fc85982009-11-03 07:17:11 -02003589 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_20M)) &&
3590 priv->undecorated_smoothed_pwdb >= VeryLowRSSI)
3591 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003592 if (rx_chk_cnt < 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003593 {
3594 //DbgPrint("RSSI < %d && RSSI >= %d, no check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
3595 return bStuck;
3596 }
3597 else
3598 {
3599 rx_chk_cnt = 0;
3600 //DbgPrint("RSSI < %d && RSSI >= %d, check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
3601 }
3602 }
3603 else
3604 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003605 if (rx_chk_cnt < 8)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003606 {
3607 //DbgPrint("RSSI <= %d, no check this time \n", VeryLowRSSI);
3608 return bStuck;
3609 }
3610 else
3611 {
3612 rx_chk_cnt = 0;
3613 //DbgPrint("RSSI <= %d, check this time \n", VeryLowRSSI);
3614 }
3615 }
3616
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003617 if (priv->RxCounter==RegRxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003618 bStuck = TRUE;
3619
3620 priv->RxCounter = RegRxCounter;
3621
3622 return bStuck;
3623}
3624
3625RESET_TYPE
3626RxCheckStuck(struct net_device *dev)
3627{
3628 struct r8192_priv *priv = ieee80211_priv(dev);
3629 //int i;
3630 bool bRxCheck = FALSE;
3631
3632// RT_TRACE(COMP_RESET," ==> RxCheckStuck()\n");
3633 //PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK);
3634
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003635 if (priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003636 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003637 //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK);
3638
3639// RT_TRACE(COMP_RESET,"bRxCheck is %d \n",bRxCheck);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003640 if (bRxCheck)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003641 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003642 if (HalRxCheckStuck819xUsb(dev))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003643 {
3644 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
3645 return RESET_TYPE_SILENT;
3646 }
3647 }
3648 return RESET_TYPE_NORESET;
3649}
3650
3651
3652/**
3653* This function is called by Checkforhang to check whether we should ask OS to reset driver
3654*
3655* \param pAdapter The adapter context for this miniport
3656*
3657* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
3658* to judge whether there is tx stuck.
3659* Note: This function may be required to be rewrite for Vista OS.
3660* <<<Assumption: Tx spinlock has been acquired >>>
3661*
3662* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
3663*/
3664RESET_TYPE
3665rtl819x_ifcheck_resetornot(struct net_device *dev)
3666{
3667 struct r8192_priv *priv = ieee80211_priv(dev);
3668 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
3669 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003670 RT_RF_POWER_STATE rfState;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003671
3672 rfState = priv->ieee80211->eRFPowerState;
3673
3674 TxResetType = TxCheckStuck(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003675 if ( rfState != eRfOff ||
Jerry Chuang8fc85982009-11-03 07:17:11 -02003676 /*ADAPTER_TEST_STATUS_FLAG(Adapter, ADAPTER_STATUS_FW_DOWNLOAD_FAILURE)) &&*/
3677 (priv->ieee80211->iw_mode != IW_MODE_ADHOC))
3678 {
3679 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
3680 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
3681 // if driver is in firmware download failure status, driver should initialize RF in the following
3682 // silent reset procedure Emily, 2008.01.21
3683
3684 // Driver should not check RX stuck in IBSS mode because it is required to
3685 // set Check BSSID in order to send beacon, however, if check BSSID is
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003686 // set, STA cannot hear any packet at all. Emily, 2008.04.12
Jerry Chuang8fc85982009-11-03 07:17:11 -02003687 RxResetType = RxCheckStuck(dev);
3688 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003689 if (TxResetType==RESET_TYPE_NORMAL || RxResetType==RESET_TYPE_NORMAL)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003690 return RESET_TYPE_NORMAL;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003691 else if (TxResetType==RESET_TYPE_SILENT || RxResetType==RESET_TYPE_SILENT){
Jerry Chuang8fc85982009-11-03 07:17:11 -02003692 RT_TRACE(COMP_RESET,"%s():silent reset\n",__FUNCTION__);
3693 return RESET_TYPE_SILENT;
3694 }
3695 else
3696 return RESET_TYPE_NORESET;
3697
3698}
3699
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003700void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003701int _rtl8192_up(struct net_device *dev);
3702int rtl8192_close(struct net_device *dev);
3703
3704
3705
3706void
3707CamRestoreAllEntry( struct net_device *dev)
3708{
3709 u8 EntryId = 0;
3710 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003711 u8 *MacAddr = priv->ieee80211->current_network.bssid;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003712
3713 static u8 CAM_CONST_ADDR[4][6] = {
3714 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3715 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
3716 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
3717 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
3718 static u8 CAM_CONST_BROAD[] =
3719 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3720
3721 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
3722
3723
3724 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40)||
3725 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104))
3726 {
3727
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03003728 for (EntryId=0; EntryId<4; EntryId++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003729 {
3730 {
3731 MacAddr = CAM_CONST_ADDR[EntryId];
3732 setKey(dev,
3733 EntryId ,
3734 EntryId,
3735 priv->ieee80211->pairwise_key_type,
3736 MacAddr,
3737 0,
3738 NULL);
3739 }
3740 }
3741
3742 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003743 else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003744 {
3745
3746 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003747 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003748 setKey(dev,
3749 4,
3750 0,
3751 priv->ieee80211->pairwise_key_type,
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003752 (u8 *)dev->dev_addr,
Jerry Chuang8fc85982009-11-03 07:17:11 -02003753 0,
3754 NULL);
3755 else
3756 setKey(dev,
3757 4,
3758 0,
3759 priv->ieee80211->pairwise_key_type,
3760 MacAddr,
3761 0,
3762 NULL);
3763 }
3764 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003765 else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003766 {
3767
3768 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003769 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003770 setKey(dev,
3771 4,
3772 0,
3773 priv->ieee80211->pairwise_key_type,
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003774 (u8 *)dev->dev_addr,
Jerry Chuang8fc85982009-11-03 07:17:11 -02003775 0,
3776 NULL);
3777 else
3778 setKey(dev,
3779 4,
3780 0,
3781 priv->ieee80211->pairwise_key_type,
3782 MacAddr,
3783 0,
3784 NULL);
3785 }
3786 }
3787
3788
3789
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003790 if (priv->ieee80211->group_key_type == KEY_TYPE_TKIP)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003791 {
3792 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03003793 for (EntryId=1 ; EntryId<4 ; EntryId++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003794 {
3795 {
3796 setKey(dev,
3797 EntryId,
3798 EntryId,
3799 priv->ieee80211->group_key_type,
3800 MacAddr,
3801 0,
3802 NULL);
3803 }
3804 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003805 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003806 setKey(dev,
3807 0,
3808 0,
3809 priv->ieee80211->group_key_type,
3810 CAM_CONST_ADDR[0],
3811 0,
3812 NULL);
3813 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003814 else if (priv->ieee80211->group_key_type == KEY_TYPE_CCMP)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003815 {
3816 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03003817 for (EntryId=1; EntryId<4 ; EntryId++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003818 {
3819 {
3820 setKey(dev,
3821 EntryId ,
3822 EntryId,
3823 priv->ieee80211->group_key_type,
3824 MacAddr,
3825 0,
3826 NULL);
3827 }
3828 }
3829
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003830 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003831 setKey(dev,
3832 0 ,
3833 0,
3834 priv->ieee80211->group_key_type,
3835 CAM_CONST_ADDR[0],
3836 0,
3837 NULL);
3838 }
3839}
3840//////////////////////////////////////////////////////////////
3841// This function is used to fix Tx/Rx stop bug temporarily.
3842// This function will do "system reset" to NIC when Tx or Rx is stuck.
3843// The method checking Tx/Rx stuck of this function is supported by FW,
3844// which reports Tx and Rx counter to register 0x128 and 0x130.
3845//////////////////////////////////////////////////////////////
3846void
3847rtl819x_ifsilentreset(struct net_device *dev)
3848{
3849 //OCTET_STRING asocpdu;
3850 struct r8192_priv *priv = ieee80211_priv(dev);
3851 u8 reset_times = 0;
3852 int reset_status = 0;
3853 struct ieee80211_device *ieee = priv->ieee80211;
3854
3855
3856 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
3857 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
3858
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003859 if (priv->ResetProgress==RESET_TYPE_NORESET)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003860 {
3861RESET_START:
3862
3863 RT_TRACE(COMP_RESET,"=========>Reset progress!! \n");
3864
3865 // Set the variable for reset.
3866 priv->ResetProgress = RESET_TYPE_SILENT;
3867// rtl8192_close(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003868 down(&priv->wx_sem);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003869 if (priv->up == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003870 {
3871 RT_TRACE(COMP_ERR,"%s():the driver is not up! return\n",__FUNCTION__);
3872 up(&priv->wx_sem);
3873 return ;
3874 }
3875 priv->up = 0;
3876 RT_TRACE(COMP_RESET,"%s():======>start to down the driver\n",__FUNCTION__);
3877// if(!netif_queue_stopped(dev))
3878// netif_stop_queue(dev);
3879
3880 rtl8192_rtx_disable(dev);
3881 rtl8192_cancel_deferred_work(priv);
3882 deinit_hal_dm(dev);
3883 del_timer_sync(&priv->watch_dog_timer);
3884
3885 ieee->sync_scan_hurryup = 1;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003886 if (ieee->state == IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003887 {
3888 down(&ieee->wx_sem);
3889 printk("ieee->state is IEEE80211_LINKED\n");
3890 ieee80211_stop_send_beacons(priv->ieee80211);
3891 del_timer_sync(&ieee->associate_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003892 cancel_delayed_work(&ieee->associate_retry_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003893 ieee80211_stop_scan(ieee);
3894 netif_carrier_off(dev);
3895 up(&ieee->wx_sem);
3896 }
3897 else{
3898 printk("ieee->state is NOT LINKED\n");
3899 ieee80211_softmac_stop_protocol(priv->ieee80211); }
3900 up(&priv->wx_sem);
3901 RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__);
3902 //rtl8192_irq_disable(dev);
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003903 RT_TRACE(COMP_RESET,"%s():===========>start up the driver\n",__FUNCTION__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003904 reset_status = _rtl8192_up(dev);
3905
3906 RT_TRACE(COMP_RESET,"%s():<===========up process is finished\n",__FUNCTION__);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003907 if (reset_status == -EAGAIN)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003908 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003909 if (reset_times < 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003910 {
3911 reset_times++;
3912 goto RESET_START;
3913 }
3914 else
3915 {
3916 RT_TRACE(COMP_ERR," ERR!!! %s(): Reset Failed!!\n", __FUNCTION__);
3917 }
3918 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003919 ieee->is_silent_reset = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003920 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003921 if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003922 {
3923 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3924
Jerry Chuang8fc85982009-11-03 07:17:11 -02003925 queue_work(ieee->wq, &ieee->associate_complete_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003926
3927 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003928 else if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003929 {
3930 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3931 ieee->link_change(ieee->dev);
3932
3933 // notify_wx_assoc_event(ieee);
3934
3935 ieee80211_start_send_beacons(ieee);
3936
3937 if (ieee->data_hard_resume)
3938 ieee->data_hard_resume(ieee->dev);
3939 netif_carrier_on(ieee->dev);
3940 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003941
3942 CamRestoreAllEntry(dev);
3943
3944 priv->ResetProgress = RESET_TYPE_NORESET;
3945 priv->reset_count++;
3946
3947 priv->bForcedSilentReset =false;
3948 priv->bResetInProgress = false;
3949
3950 // For test --> force write UFWP.
3951 write_nic_byte(dev, UFWP, 1);
3952 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003953 }
3954}
3955
3956void CAM_read_entry(
3957 struct net_device *dev,
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003958 u32 iIndex
Jerry Chuang8fc85982009-11-03 07:17:11 -02003959)
3960{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003961 u32 target_command=0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003962 u32 target_content=0;
3963 u8 entry_i=0;
3964 u32 ulStatus;
3965 s32 i=100;
3966// printk("=======>start read CAM\n");
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03003967 for (entry_i=0;entry_i<CAM_CONTENT_COUNT;entry_i++)
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003968 {
3969 // polling bit, and No Write enable, and address
Jerry Chuang8fc85982009-11-03 07:17:11 -02003970 target_command= entry_i+CAM_CONTENT_COUNT*iIndex;
3971 target_command= target_command | BIT31;
3972
3973 //Check polling bit is clear
3974// mdelay(1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003975 while((i--)>=0)
3976 {
3977 ulStatus = read_nic_dword(dev, RWCAM);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003978 if (ulStatus & BIT31){
Jerry Chuang8fc85982009-11-03 07:17:11 -02003979 continue;
3980 }
3981 else{
3982 break;
3983 }
3984 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003985 write_nic_dword(dev, RWCAM, target_command);
3986 RT_TRACE(COMP_SEC,"CAM_read_entry(): WRITE A0: %x \n",target_command);
3987 // printk("CAM_read_entry(): WRITE A0: %lx \n",target_command);
3988 target_content = read_nic_dword(dev, RCAMO);
3989 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n",target_content);
3990 // printk("CAM_read_entry(): WRITE A8: %lx \n",target_content);
3991 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003992 printk("\n");
3993}
3994
3995void rtl819x_update_rxcounts(
3996 struct r8192_priv *priv,
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003997 u32 *TotalRxBcnNum,
3998 u32 *TotalRxDataNum
Jerry Chuang8fc85982009-11-03 07:17:11 -02003999)
4000{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004001 u16 SlotIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004002 u8 i;
4003
4004 *TotalRxBcnNum = 0;
4005 *TotalRxDataNum = 0;
4006
4007 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
4008 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
4009 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03004010 for ( i=0; i<priv->ieee80211->LinkDetectInfo.SlotNum; i++ ){
Jerry Chuang8fc85982009-11-03 07:17:11 -02004011 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
4012 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
4013 }
4014}
4015
4016
Jerry Chuang8fc85982009-11-03 07:17:11 -02004017extern void rtl819x_watchdog_wqcallback(struct work_struct *work)
4018{
4019 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
4020 struct r8192_priv *priv = container_of(dwork,struct r8192_priv,watch_dog_wq);
4021 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004022 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004023 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01004024 static u8 check_reset_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004025 bool bBusyTraffic = false;
4026
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004027 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004028 return;
4029 hal_dm_watchdog(dev);
4030
4031 {//to get busy traffic condition
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004032 if (ieee->state == IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004033 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004034 if ( ieee->LinkDetectInfo.NumRxOkInPeriod> 666 ||
Jerry Chuang8fc85982009-11-03 07:17:11 -02004035 ieee->LinkDetectInfo.NumTxOkInPeriod> 666 ) {
4036 bBusyTraffic = true;
4037 }
4038 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
4039 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
4040 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
4041 }
4042 }
4043 //added by amy for AP roaming
4044 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004045 if (priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004046 {
4047 u32 TotalRxBcnNum = 0;
4048 u32 TotalRxDataNum = 0;
4049
4050 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004051 if ((TotalRxBcnNum+TotalRxDataNum) == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004052 {
4053 #ifdef TODO
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004054 if (rfState == eRfOff)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004055 RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__);
4056 #endif
4057 printk("===>%s(): AP is power off,connect another one\n",__FUNCTION__);
4058 // Dot11d_Reset(dev);
4059 priv->ieee80211->state = IEEE80211_ASSOCIATING;
4060 notify_wx_assoc_event(priv->ieee80211);
4061 RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
4062 priv->ieee80211->link_change(dev);
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01004063 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004064
4065 }
4066 }
4067 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod=0;
4068 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod=0;
4069 }
4070// CAM_read_entry(dev,4);
4071 //check if reset the driver
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004072 if (check_reset_cnt++ >= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004073 {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004074 ResetType = rtl819x_ifcheck_resetornot(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004075 check_reset_cnt = 3;
4076 //DbgPrint("Start to check silent reset\n");
4077 }
4078 // 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);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004079 if ( (priv->force_reset) || (priv->ResetProgress==RESET_TYPE_NORESET &&
Jerry Chuang8fc85982009-11-03 07:17:11 -02004080 (priv->bForcedSilentReset ||
4081 (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT)))) // This is control by OID set in Pomelo
4082 {
4083 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);
4084 rtl819x_ifsilentreset(dev);
4085 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004086 priv->force_reset = false;
4087 priv->bForcedSilentReset = false;
4088 priv->bResetInProgress = false;
4089 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
4090
4091}
4092
4093void watch_dog_timer_callback(unsigned long data)
4094{
4095 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004096 //printk("===============>watch_dog timer\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02004097 queue_delayed_work(priv->priv_wq,&priv->watch_dog_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004098 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004099}
4100int _rtl8192_up(struct net_device *dev)
4101{
4102 struct r8192_priv *priv = ieee80211_priv(dev);
4103 //int i;
4104 int init_status = 0;
4105 priv->up=1;
4106 priv->ieee80211->ieee_up=1;
4107 RT_TRACE(COMP_INIT, "Bringing up iface");
4108 init_status = rtl8192_adapter_start(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004109 if (!init_status)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004110 {
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004111 RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization failed!\n", __FUNCTION__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004112 priv->up=priv->ieee80211->ieee_up = 0;
4113 return -EAGAIN;
4114 }
4115 RT_TRACE(COMP_INIT, "start adapter finished\n");
4116 rtl8192_rx_enable(dev);
4117// rtl8192_tx_enable(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004118 if (priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004119 ieee80211_softmac_start_protocol(priv->ieee80211);
4120 ieee80211_reset_queue(priv->ieee80211);
4121 watch_dog_timer_callback((unsigned long) dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004122 if (!netif_queue_stopped(dev))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004123 netif_start_queue(dev);
4124 else
4125 netif_wake_queue(dev);
4126
4127 return 0;
4128}
4129
4130
4131int rtl8192_open(struct net_device *dev)
4132{
4133 struct r8192_priv *priv = ieee80211_priv(dev);
4134 int ret;
4135 down(&priv->wx_sem);
4136 ret = rtl8192_up(dev);
4137 up(&priv->wx_sem);
4138 return ret;
4139
4140}
4141
4142
4143int rtl8192_up(struct net_device *dev)
4144{
4145 struct r8192_priv *priv = ieee80211_priv(dev);
4146
4147 if (priv->up == 1) return -1;
4148
4149 return _rtl8192_up(dev);
4150}
4151
4152
4153int rtl8192_close(struct net_device *dev)
4154{
4155 struct r8192_priv *priv = ieee80211_priv(dev);
4156 int ret;
4157
4158 down(&priv->wx_sem);
4159
4160 ret = rtl8192_down(dev);
4161
4162 up(&priv->wx_sem);
4163
4164 return ret;
4165
4166}
4167
4168int rtl8192_down(struct net_device *dev)
4169{
4170 struct r8192_priv *priv = ieee80211_priv(dev);
4171 int i;
4172
4173 if (priv->up == 0) return -1;
4174
4175 priv->up=0;
4176 priv->ieee80211->ieee_up = 0;
4177 RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
4178/* FIXME */
4179 if (!netif_queue_stopped(dev))
4180 netif_stop_queue(dev);
4181
4182 rtl8192_rtx_disable(dev);
4183 //rtl8192_irq_disable(dev);
4184
4185 /* Tx related queue release */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03004186 for (i = 0; i < MAX_QUEUE_SIZE; i++) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004187 skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
4188 }
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03004189 for (i = 0; i < MAX_QUEUE_SIZE; i++) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004190 skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
4191 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004192
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03004193 for (i = 0; i < MAX_QUEUE_SIZE; i++) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004194 skb_queue_purge(&priv->ieee80211->skb_drv_aggQ [i]);
4195 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004196
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004197 //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 -02004198// flush_scheduled_work();
4199 rtl8192_cancel_deferred_work(priv);
4200 deinit_hal_dm(dev);
4201 del_timer_sync(&priv->watch_dog_timer);
4202
4203
4204 ieee80211_softmac_stop_protocol(priv->ieee80211);
4205 memset(&priv->ieee80211->current_network, 0 , offsetof(struct ieee80211_network, list));
4206 RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
4207
4208 return 0;
4209}
4210
4211
4212void rtl8192_commit(struct net_device *dev)
4213{
4214 struct r8192_priv *priv = ieee80211_priv(dev);
4215 int reset_status = 0;
4216 //u8 reset_times = 0;
4217 if (priv->up == 0) return ;
4218 priv->up = 0;
4219
4220 rtl8192_cancel_deferred_work(priv);
4221 del_timer_sync(&priv->watch_dog_timer);
4222 //cancel_delayed_work(&priv->SwChnlWorkItem);
4223
4224 ieee80211_softmac_stop_protocol(priv->ieee80211);
4225
4226 //rtl8192_irq_disable(dev);
4227 rtl8192_rtx_disable(dev);
4228 reset_status = _rtl8192_up(dev);
4229
4230}
4231
4232/*
4233void rtl8192_restart(struct net_device *dev)
4234{
4235 struct r8192_priv *priv = ieee80211_priv(dev);
4236*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02004237void rtl8192_restart(struct work_struct *work)
4238{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004239 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
4240 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004241
4242 down(&priv->wx_sem);
4243
4244 rtl8192_commit(dev);
4245
4246 up(&priv->wx_sem);
4247}
4248
4249static void r8192_set_multicast(struct net_device *dev)
4250{
4251 struct r8192_priv *priv = ieee80211_priv(dev);
4252 short promisc;
4253
4254 //down(&priv->wx_sem);
4255
4256 /* FIXME FIXME */
4257
4258 promisc = (dev->flags & IFF_PROMISC) ? 1:0;
4259
4260 if (promisc != priv->promisc)
4261 // rtl8192_commit(dev);
4262
4263 priv->promisc = promisc;
4264
4265 //schedule_work(&priv->reset_wq);
4266 //up(&priv->wx_sem);
4267}
4268
4269
4270int r8192_set_mac_adr(struct net_device *dev, void *mac)
4271{
4272 struct r8192_priv *priv = ieee80211_priv(dev);
4273 struct sockaddr *addr = mac;
4274
4275 down(&priv->wx_sem);
4276
4277 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
4278
Jerry Chuang8fc85982009-11-03 07:17:11 -02004279 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004280 up(&priv->wx_sem);
4281
4282 return 0;
4283}
4284
4285/* based on ipw2200 driver */
4286int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
4287{
4288 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4289 struct iwreq *wrq = (struct iwreq *)rq;
4290 int ret=-1;
4291 struct ieee80211_device *ieee = priv->ieee80211;
4292 u32 key[4];
4293 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
4294 struct iw_point *p = &wrq->u.data;
4295 struct ieee_param *ipw = NULL;//(struct ieee_param *)wrq->u.data.pointer;
4296
4297 down(&priv->wx_sem);
4298
4299
4300 if (p->length < sizeof(struct ieee_param) || !p->pointer){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004301 ret = -EINVAL;
4302 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004303 }
4304
Julia Lawall32414872010-05-11 20:26:57 +02004305 ipw = kmalloc(p->length, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004306 if (ipw == NULL){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004307 ret = -ENOMEM;
4308 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004309 }
4310 if (copy_from_user(ipw, p->pointer, p->length)) {
4311 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004312 ret = -EFAULT;
4313 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004314 }
4315
4316 switch (cmd) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004317 case RTL_IOCTL_WPA_SUPPLICANT:
Jerry Chuang8fc85982009-11-03 07:17:11 -02004318 //parse here for HW security
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004319 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION)
4320 {
4321 if (ipw->u.crypt.set_tx)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004322 {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004323 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
4324 ieee->pairwise_key_type = KEY_TYPE_CCMP;
4325 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
4326 ieee->pairwise_key_type = KEY_TYPE_TKIP;
4327 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004328 {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004329 if (ipw->u.crypt.key_len == 13)
4330 ieee->pairwise_key_type = KEY_TYPE_WEP104;
4331 else if (ipw->u.crypt.key_len == 5)
4332 ieee->pairwise_key_type = KEY_TYPE_WEP40;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004333 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004334 else
4335 ieee->pairwise_key_type = KEY_TYPE_NA;
4336
4337 if (ieee->pairwise_key_type)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004338 {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004339 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004340 EnableHWSecurityConfig8192(dev);
4341 //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!
4342 //added by WB.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004343 setKey(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8 *)ieee->ap_mac_addr, 0, key);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004344 if (ieee->auth_mode != 2)
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004345 setKey(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8 *)ieee->ap_mac_addr, 0, key);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004346 }
4347 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004348 else //if (ipw->u.crypt.idx) //group key use idx > 0
4349 {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004350 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004351 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
4352 ieee->group_key_type= KEY_TYPE_CCMP;
4353 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
4354 ieee->group_key_type = KEY_TYPE_TKIP;
4355 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
4356 {
4357 if (ipw->u.crypt.key_len == 13)
4358 ieee->group_key_type = KEY_TYPE_WEP104;
4359 else if (ipw->u.crypt.key_len == 5)
4360 ieee->group_key_type = KEY_TYPE_WEP40;
4361 }
4362 else
4363 ieee->group_key_type = KEY_TYPE_NA;
4364
4365 if (ieee->group_key_type)
4366 {
4367 setKey( dev,
4368 ipw->u.crypt.idx,
4369 ipw->u.crypt.idx, //KeyIndex
4370 ieee->group_key_type, //KeyType
4371 broadcast_addr, //MacAddr
4372 0, //DefaultKey
4373 key); //KeyContent
4374 }
4375 }
4376 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004377#ifdef JOHN_HWSEC_DEBUG
4378 //john's test 0711
4379 printk("@@ wrq->u pointer = ");
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03004380 for (i=0;i<wrq->u.data.length;i++){
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004381 if (i%10==0) printk("\n");
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004382 printk( "%8x|", ((u32 *)wrq->u.data.pointer)[i] );
Jerry Chuang8fc85982009-11-03 07:17:11 -02004383 }
4384 printk("\n");
4385#endif /*JOHN_HWSEC_DEBUG*/
4386 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
4387 break;
4388
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004389 default:
Jerry Chuang8fc85982009-11-03 07:17:11 -02004390 ret = -EOPNOTSUPP;
4391 break;
4392 }
4393 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004394 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004395out:
4396 up(&priv->wx_sem);
4397 return ret;
4398}
4399
4400u8 HwRateToMRate90(bool bIsHT, u8 rate)
4401{
4402 u8 ret_rate = 0xff;
4403
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004404 if (!bIsHT) {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03004405 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004406 case DESC90_RATE1M: ret_rate = MGN_1M; break;
4407 case DESC90_RATE2M: ret_rate = MGN_2M; break;
4408 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
4409 case DESC90_RATE11M: ret_rate = MGN_11M; break;
4410 case DESC90_RATE6M: ret_rate = MGN_6M; break;
4411 case DESC90_RATE9M: ret_rate = MGN_9M; break;
4412 case DESC90_RATE12M: ret_rate = MGN_12M; break;
4413 case DESC90_RATE18M: ret_rate = MGN_18M; break;
4414 case DESC90_RATE24M: ret_rate = MGN_24M; break;
4415 case DESC90_RATE36M: ret_rate = MGN_36M; break;
4416 case DESC90_RATE48M: ret_rate = MGN_48M; break;
4417 case DESC90_RATE54M: ret_rate = MGN_54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004418
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004419 default:
4420 ret_rate = 0xff;
4421 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
4422 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004423 }
4424
4425 } else {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03004426 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004427 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
4428 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
4429 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
4430 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
4431 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
4432 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
4433 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
4434 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
4435 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
4436 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
4437 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
4438 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
4439 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
4440 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
4441 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
4442 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
4443 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004444
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004445 default:
4446 ret_rate = 0xff;
4447 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n",rate, bIsHT);
4448 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004449 }
4450 }
4451
4452 return ret_rate;
4453}
4454
4455/**
4456 * Function: UpdateRxPktTimeStamp
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004457 * Overview: Record the TSF time stamp when receiving a packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02004458 *
4459 * Input:
4460 * PADAPTER Adapter
4461 * PRT_RFD pRfd,
4462 *
4463 * Output:
4464 * PRT_RFD pRfd
4465 * (pRfd->Status.TimeStampHigh is updated)
4466 * (pRfd->Status.TimeStampLow is updated)
4467 * Return:
4468 * None
4469 */
4470void UpdateRxPktTimeStamp8190 (struct net_device *dev, struct ieee80211_rx_stats *stats)
4471{
4472 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4473
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004474 if (stats->bIsAMPDU && !stats->bFirstMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004475 stats->mac_time[0] = priv->LastRxDescTSFLow;
4476 stats->mac_time[1] = priv->LastRxDescTSFHigh;
4477 } else {
4478 priv->LastRxDescTSFLow = stats->mac_time[0];
4479 priv->LastRxDescTSFHigh = stats->mac_time[1];
4480 }
4481}
4482
4483//by amy 080606
4484
4485long rtl819x_translate_todbm(u8 signal_strength_index )// 0-100 index.
4486{
4487 long signal_power; // in dBm.
4488
4489 // Translate to dBm (x=0.5y-95).
4490 signal_power = (long)((signal_strength_index + 1) >> 1);
4491 signal_power -= 95;
4492
4493 return signal_power;
4494}
4495
4496
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004497/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
Jerry Chuang8fc85982009-11-03 07:17:11 -02004498 be a local static. Otherwise, it may increase when we return from S3/S4. The
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004499 value will be kept in memory or disk. Declare the value in the adaptor
4500 and it will be reinitialized when returned from S3/S4. */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004501void rtl8192_process_phyinfo(struct r8192_priv *priv,u8 *buffer, struct ieee80211_rx_stats *pprevious_stats, struct ieee80211_rx_stats *pcurrent_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004502{
4503 bool bcheck = false;
4504 u8 rfpath;
4505 u32 nspatial_stream, tmp_val;
4506 //u8 i;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01004507 static u32 slide_rssi_index, slide_rssi_statistics;
4508 static u32 slide_evm_index, slide_evm_statistics;
4509 static u32 last_rssi, last_evm;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004510
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01004511 static u32 slide_beacon_adc_pwdb_index, slide_beacon_adc_pwdb_statistics;
4512 static u32 last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004513
4514 struct ieee80211_hdr_3addr *hdr;
4515 u16 sc ;
4516 unsigned int frag,seq;
4517 hdr = (struct ieee80211_hdr_3addr *)buffer;
4518 sc = le16_to_cpu(hdr->seq_ctl);
4519 frag = WLAN_GET_SEQ_FRAG(sc);
4520 seq = WLAN_GET_SEQ_SEQ(sc);
4521 //cosa add 04292008 to record the sequence number
4522 pcurrent_stats->Seq_Num = seq;
4523 //
4524 // Check whether we should take the previous packet into accounting
4525 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004526 if (!pprevious_stats->bIsAMPDU)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004527 {
4528 // if previous packet is not aggregated packet
4529 bcheck = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004530 }
4531
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004532 if (slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004533 {
4534 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
4535 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
4536 priv->stats.slide_rssi_total -= last_rssi;
4537 }
4538 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
4539
4540 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004541 if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004542 slide_rssi_index = 0;
4543
4544 // <1> Showed on UI for user, in dbm
4545 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
4546 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
4547 pcurrent_stats->rssi = priv->stats.signal_strength;
4548 //
4549 // If the previous packet does not match the criteria, neglect it
4550 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004551 if (!pprevious_stats->bPacketMatchBSSID)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004552 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004553 if (!pprevious_stats->bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004554 return;
4555 }
4556
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004557 if (!bcheck)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004558 return;
4559
4560
4561 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
4562
4563 //
4564 // Check RSSI
4565 //
4566 priv->stats.num_process_phyinfo++;
4567
4568 /* record the general signal strength to the sliding window. */
4569
4570
4571 // <2> Showed on UI for engineering
4572 // hardware does not provide rssi information for each rf path in CCK
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004573 if (!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004574 {
4575 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++)
4576 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004577 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
4578 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004579
4580 //Fixed by Jacken 2008-03-20
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004581 if (priv->stats.rx_rssi_percentage[rfpath] == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004582 {
4583 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
4584 //DbgPrint("MIMO RSSI initialize \n");
4585 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004586 if (pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath])
Jerry Chuang8fc85982009-11-03 07:17:11 -02004587 {
4588 priv->stats.rx_rssi_percentage[rfpath] =
4589 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
4590 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
4591 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
4592 }
4593 else
4594 {
4595 priv->stats.rx_rssi_percentage[rfpath] =
4596 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
4597 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
4598 }
4599 RT_TRACE(COMP_DBG,"priv->stats.rx_rssi_percentage[rfPath] = %d \n" ,priv->stats.rx_rssi_percentage[rfpath] );
4600 }
4601 }
4602
4603
4604 //
4605 // Check PWDB.
4606 //
4607 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
4608 pprevious_stats->bIsCCK? "CCK": "OFDM",
4609 pprevious_stats->RxPWDBAll);
4610
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004611 if (pprevious_stats->bPacketBeacon)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004612 {
4613/* record the beacon pwdb to the sliding window. */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004614 if (slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004615 {
4616 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
4617 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
4618 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
4619 //DbgPrint("slide_beacon_adc_pwdb_index = %d, last_beacon_adc_pwdb = %d, Adapter->RxStats.Slide_Beacon_Total = %d\n",
4620 // slide_beacon_adc_pwdb_index, last_beacon_adc_pwdb, Adapter->RxStats.Slide_Beacon_Total);
4621 }
4622 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
4623 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
4624 //DbgPrint("slide_beacon_adc_pwdb_index = %d, pPreviousRfd->Status.RxPWDBAll = %d\n", slide_beacon_adc_pwdb_index, pPreviousRfd->Status.RxPWDBAll);
4625 slide_beacon_adc_pwdb_index++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004626 if (slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004627 slide_beacon_adc_pwdb_index = 0;
4628 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004629 if (pprevious_stats->RxPWDBAll >= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004630 pprevious_stats->RxPWDBAll -= 3;
4631 }
4632
4633 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
4634 pprevious_stats->bIsCCK? "CCK": "OFDM",
4635 pprevious_stats->RxPWDBAll);
4636
4637
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004638 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004639 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004640 if (priv->undecorated_smoothed_pwdb < 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004641 {
4642 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
4643 //DbgPrint("First pwdb initialize \n");
4644 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004645 if (pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004646 {
4647 priv->undecorated_smoothed_pwdb =
4648 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4649 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
4650 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
4651 }
4652 else
4653 {
4654 priv->undecorated_smoothed_pwdb =
4655 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4656 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
4657 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004658
4659 }
4660
4661 //
4662 // Check EVM
4663 //
4664 /* record the general EVM to the sliding window. */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004665 if (pprevious_stats->SignalQuality == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004666 {
4667 }
4668 else
4669 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004670 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA){
4671 if (slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX){
Jerry Chuang8fc85982009-11-03 07:17:11 -02004672 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
4673 last_evm = priv->stats.slide_evm[slide_evm_index];
4674 priv->stats.slide_evm_total -= last_evm;
4675 }
4676
4677 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
4678
4679 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004680 if (slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004681 slide_evm_index = 0;
4682
4683 // <1> Showed on UI for user, in percentage.
4684 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
4685 priv->stats.signal_quality = tmp_val;
4686 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
4687 priv->stats.last_signal_strength_inpercent = tmp_val;
4688 }
4689
4690 // <2> Showed on UI for engineering
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004691 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004692 {
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03004693 for (nspatial_stream = 0; nspatial_stream<2 ; nspatial_stream++) // 2 spatial stream
Jerry Chuang8fc85982009-11-03 07:17:11 -02004694 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004695 if (pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004696 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004697 if (priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004698 {
4699 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
4700 }
4701 priv->stats.rx_evm_percentage[nspatial_stream] =
4702 ( (priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
4703 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
4704 }
4705 }
4706 }
4707 }
4708
4709
4710}
4711
4712/*-----------------------------------------------------------------------------
4713 * Function: rtl819x_query_rxpwrpercentage()
4714 *
4715 * Overview:
4716 *
4717 * Input: char antpower
4718 *
4719 * Output: NONE
4720 *
4721 * Return: 0-100 percentage
4722 *
4723 * Revised History:
4724 * When Who Remark
4725 * 05/26/2008 amy Create Version 0 porting from windows code.
4726 *
4727 *---------------------------------------------------------------------------*/
4728static u8 rtl819x_query_rxpwrpercentage(
4729 char antpower
4730 )
4731{
4732 if ((antpower <= -100) || (antpower >= 20))
4733 {
4734 return 0;
4735 }
4736 else if (antpower >= 0)
4737 {
4738 return 100;
4739 }
4740 else
4741 {
4742 return (100+antpower);
4743 }
4744
4745} /* QueryRxPwrPercentage */
4746
4747static u8
4748rtl819x_evm_dbtopercentage(
4749 char value
4750 )
4751{
4752 char ret_val;
4753
4754 ret_val = value;
4755
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004756 if (ret_val >= 0)
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01004757 ret_val = 0;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004758 if (ret_val <= -33)
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01004759 ret_val = -33;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004760 ret_val = 0 - ret_val;
4761 ret_val*=3;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004762 if (ret_val == 99)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004763 ret_val = 100;
4764 return(ret_val);
4765}
4766//
4767// Description:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004768// We want good-looking for signal strength/quality
Jerry Chuang8fc85982009-11-03 07:17:11 -02004769// 2007/7/19 01:09, by cosa.
4770//
4771long
4772rtl819x_signal_scale_mapping(
4773 long currsig
4774 )
4775{
4776 long retsig;
4777
4778 // Step 1. Scale mapping.
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004779 if (currsig >= 61 && currsig <= 100)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004780 {
4781 retsig = 90 + ((currsig - 60) / 4);
4782 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004783 else if (currsig >= 41 && currsig <= 60)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004784 {
4785 retsig = 78 + ((currsig - 40) / 2);
4786 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004787 else if (currsig >= 31 && currsig <= 40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004788 {
4789 retsig = 66 + (currsig - 30);
4790 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004791 else if (currsig >= 21 && currsig <= 30)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004792 {
4793 retsig = 54 + (currsig - 20);
4794 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004795 else if (currsig >= 5 && currsig <= 20)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004796 {
4797 retsig = 42 + (((currsig - 5) * 2) / 3);
4798 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004799 else if (currsig == 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004800 {
4801 retsig = 36;
4802 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004803 else if (currsig == 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004804 {
4805 retsig = 27;
4806 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004807 else if (currsig == 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004808 {
4809 retsig = 18;
4810 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004811 else if (currsig == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004812 {
4813 retsig = 9;
4814 }
4815 else
4816 {
4817 retsig = currsig;
4818 }
4819
4820 return retsig;
4821}
4822
4823static void rtl8192_query_rxphystatus(
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004824 struct r8192_priv *priv,
4825 struct ieee80211_rx_stats *pstats,
4826 rx_drvinfo_819x_usb *pdrvinfo,
4827 struct ieee80211_rx_stats *precord_stats,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004828 bool bpacket_match_bssid,
4829 bool bpacket_toself,
4830 bool bPacketBeacon,
4831 bool bToSelfBA
4832 )
4833{
4834 //PRT_RFD_STATUS pRtRfdStatus = &(pRfd->Status);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004835 phy_sts_ofdm_819xusb_t *pofdm_buf;
4836 phy_sts_cck_819xusb_t *pcck_buf;
4837 phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004838 u8 *prxpkt;
4839 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
4840 char rx_pwr[4], rx_pwr_all=0;
4841 //long rx_avg_pwr = 0;
4842 char rx_snrX, rx_evmX;
4843 u8 evm, pwdb_all;
4844 u32 RSSI, total_rssi=0;//, total_evm=0;
4845// long signal_strength_index = 0;
4846 u8 is_cck_rate=0;
4847 u8 rf_rx_num = 0;
4848
4849
4850 priv->stats.numqry_phystatus++;
4851
4852 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4853
4854 // Record it for next packet processing
4855 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4856 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4857 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
4858 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;//RX_HAL_IS_CCK_RATE(pDrvInfo);
4859 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4860 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4861
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004862 prxpkt = (u8 *)pdrvinfo;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004863
4864 /* Move pointer to the 16th bytes. Phy status start address. */
4865 prxpkt += sizeof(rx_drvinfo_819x_usb);
4866
4867 /* Initial the cck and ofdm buffer pointer */
4868 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
4869 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
4870
4871 pstats->RxMIMOSignalQuality[0] = -1;
4872 pstats->RxMIMOSignalQuality[1] = -1;
4873 precord_stats->RxMIMOSignalQuality[0] = -1;
4874 precord_stats->RxMIMOSignalQuality[1] = -1;
4875
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004876 if (is_cck_rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004877 {
4878 //
4879 // (1)Hardware does not provide RSSI for CCK
4880 //
4881
4882 //
4883 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4884 //
4885 u8 report;//, cck_agc_rpt;
4886
4887 priv->stats.numqry_phystatusCCK++;
4888
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004889 if (!priv->bCckHighPower)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004890 {
4891 report = pcck_buf->cck_agc_rpt & 0xc0;
4892 report = report>>6;
Xenia Ragiadakouad638452013-05-12 03:15:08 +03004893 switch (report)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004894 {
4895 //Fixed by Jacken from Bryant 2008-03-20
4896 //Original value is -38 , -26 , -14 , -2
4897 //Fixed value is -35 , -23 , -11 , 6
4898 case 0x3:
4899 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4900 break;
4901 case 0x2:
4902 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4903 break;
4904 case 0x1:
4905 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4906 break;
4907 case 0x0:
4908 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
4909 break;
4910 }
4911 }
4912 else
4913 {
4914 report = pcck_buf->cck_agc_rpt & 0x60;
4915 report = report>>5;
Xenia Ragiadakouad638452013-05-12 03:15:08 +03004916 switch (report)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004917 {
4918 case 0x3:
4919 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4920 break;
4921 case 0x2:
4922 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4923 break;
4924 case 0x1:
4925 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4926 break;
4927 case 0x0:
4928 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4929 break;
4930 }
4931 }
4932
4933 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4934 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4935 pstats->RecvSignalPower = pwdb_all;
4936
4937 //
4938 // (3) Get Signal Quality (EVM)
4939 //
4940 //if(bpacket_match_bssid)
4941 {
4942 u8 sq;
4943
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004944 if (pstats->RxPWDBAll > 40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004945 {
4946 sq = 100;
4947 }else
4948 {
4949 sq = pcck_buf->sq_rpt;
4950
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004951 if (pcck_buf->sq_rpt > 64)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004952 sq = 0;
4953 else if (pcck_buf->sq_rpt < 20)
4954 sq = 100;
4955 else
4956 sq = ((64-sq) * 100) / 44;
4957 }
4958 pstats->SignalQuality = precord_stats->SignalQuality = sq;
4959 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
4960 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
4961 }
4962 }
4963 else
4964 {
4965 priv->stats.numqry_phystatusHT++;
4966 //
4967 // (1)Get RSSI for HT rate
4968 //
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03004969 for (i=RF90_PATH_A; i<priv->NumTotalRFPath; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004970 {
4971 // 2008/01/30 MH we will judge RF RX path now.
4972 if (priv->brfpath_rxenable[i])
4973 rf_rx_num++;
4974 else
4975 continue;
4976
4977 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
4978 continue;
4979
4980 //Fixed by Jacken from Bryant 2008-03-20
4981 //Original value is 106
4982 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
4983
4984 //Get Rx snr value in DB
4985 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
4986 rx_snrX = (char)(tmp_rxsnr);
Joe Perches859171c2010-11-14 19:04:48 -08004987 //rx_snrX >>= 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004988 rx_snrX /= 2;
4989 priv->stats.rxSNRdB[i] = (long)rx_snrX;
4990
4991 /* Translate DBM to percentage. */
4992 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
4993 total_rssi += RSSI;
4994
4995 /* Record Signal Strength for next packet */
4996 //if(bpacket_match_bssid)
4997 {
4998 pstats->RxMIMOSignalStrength[i] =(u8) RSSI;
4999 precord_stats->RxMIMOSignalStrength[i] =(u8) RSSI;
5000 }
5001 }
5002
5003
5004 //
5005 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
5006 //
5007 //Fixed by Jacken from Bryant 2008-03-20
5008 //Original value is 106
5009 rx_pwr_all = (((pofdm_buf->pwdb_all ) >> 1 )& 0x7f) -106;
5010 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
5011
5012 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
5013 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
5014
5015 //
5016 // (3)EVM of HT rate
5017 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005018 if (pdrvinfo->RxHT && pdrvinfo->RxRate>=DESC90_RATEMCS8 &&
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005019 pdrvinfo->RxRate<=DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005020 max_spatial_stream = 2; //both spatial stream make sense
5021 else
5022 max_spatial_stream = 1; //only spatial stream 1 makes sense
5023
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03005024 for (i=0; i<max_spatial_stream; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005025 {
5026 tmp_rxevm = pofdm_buf->rxevm_X[i];
5027 rx_evmX = (char)(tmp_rxevm);
5028
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005029 // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07005030 // will set the most significant bit to "zero" when doing shifting operation which may change a negative
Jerry Chuang8fc85982009-11-03 07:17:11 -02005031 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
5032 rx_evmX /= 2; //dbm
5033
5034 evm = rtl819x_evm_dbtopercentage(rx_evmX);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005035 //if(bpacket_match_bssid)
5036 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005037 if (i==0) // Fill value in RFD, Get the first spatial stream only
Jerry Chuang8fc85982009-11-03 07:17:11 -02005038 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
5039 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
5040 }
5041 }
5042
5043
5044 /* record rx statistics for debug */
5045 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
5046 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005047 if (pdrvinfo->BW) //40M channel
Jerry Chuang8fc85982009-11-03 07:17:11 -02005048 priv->stats.received_bwtype[1+prxsc->rxsc]++;
5049 else //20M channel
5050 priv->stats.received_bwtype[0]++;
5051 }
5052
5053 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
5054 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005055 if (is_cck_rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005056 {
5057 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));//PWDB_ALL;
5058
5059 }
5060 else
5061 {
5062 //pRfd->Status.SignalStrength = pRecordRfd->Status.SignalStrength = (u8)(SignalScaleMapping(total_rssi/=RF90_PATH_MAX));//(u8)(total_rssi/=RF90_PATH_MAX);
5063 // We can judge RX path number now.
5064 if (rf_rx_num != 0)
5065 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi/=rf_rx_num)));
5066 }
5067} /* QueryRxPhyStatus8190Pci */
5068
5069void
5070rtl8192_record_rxdesc_forlateruse(
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005071 struct ieee80211_rx_stats *psrc_stats,
5072 struct ieee80211_rx_stats *ptarget_stats
Jerry Chuang8fc85982009-11-03 07:17:11 -02005073)
5074{
5075 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
5076 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
5077 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
5078}
5079
5080
5081void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005082 struct ieee80211_rx_stats *pstats,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005083 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005084{
5085 // TODO: We must only check packet for current MAC address. Not finish
5086 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5087 struct net_device *dev=info->dev;
5088 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5089 bool bpacket_match_bssid, bpacket_toself;
5090 bool bPacketBeacon=FALSE, bToSelfBA=FALSE;
5091 static struct ieee80211_rx_stats previous_stats;
5092 struct ieee80211_hdr_3addr *hdr;//by amy
5093 u16 fc,type;
5094
5095 // Get Signal Quality for only RX data queue (but not command queue)
5096
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005097 u8 *tmp_buf;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005098 //u16 tmp_buf_len = 0;
5099 u8 *praddr;
5100
5101 /* Get MAC frame start address. */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005102 tmp_buf = (u8 *)skb->data;// + get_rxpacket_shiftbytes_819xusb(pstats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005103
5104 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
5105 fc = le16_to_cpu(hdr->frame_ctl);
5106 type = WLAN_FC_GET_TYPE(fc);
5107 praddr = hdr->addr1;
5108
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005109 /* Check if the received packet is acceptable. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005110 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005111 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
5112 && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02005113 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
5114
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005115 if (WLAN_FC_GET_FRAMETYPE(fc)== IEEE80211_STYPE_BEACON)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005116 {
5117 bPacketBeacon = true;
5118 //DbgPrint("Beacon 2, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
5119 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005120 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005121 {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005122 if ((eqMacAddr(praddr,dev->dev_addr)))
Jerry Chuang8fc85982009-11-03 07:17:11 -02005123 bToSelfBA = true;
5124 //DbgPrint("BlockAck, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
5125 }
5126
Jerry Chuang8fc85982009-11-03 07:17:11 -02005127
5128
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005129 if (bpacket_match_bssid)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005130 {
5131 priv->stats.numpacket_matchbssid++;
5132 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005133 if (bpacket_toself){
Jerry Chuang8fc85982009-11-03 07:17:11 -02005134 priv->stats.numpacket_toself++;
5135 }
5136 //
5137 // Process PHY information for previous packet (RSSI/PWDB/EVM)
5138 //
5139 // Because phy information is contained in the last packet of AMPDU only, so driver
5140 // should process phy information of previous packet
5141 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
5142 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid,bpacket_toself,bPacketBeacon,bToSelfBA);
5143 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
5144
5145}
5146
5147/**
5148* Function: UpdateReceivedRateHistogramStatistics
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07005149* Overview: Record the received data rate
Jerry Chuang8fc85982009-11-03 07:17:11 -02005150*
5151* Input:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005152* struct net_device *dev
Jerry Chuang8fc85982009-11-03 07:17:11 -02005153* struct ieee80211_rx_stats *stats
5154*
5155* Output:
5156*
5157* (priv->stats.ReceivedRateHistogram[] is updated)
5158* Return:
5159* None
5160*/
5161void
5162UpdateReceivedRateHistogramStatistics8190(
5163 struct net_device *dev,
5164 struct ieee80211_rx_stats *stats
5165 )
5166{
5167 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005168 u32 rcvType=1; //0: Total, 1:OK, 2:CRC, 3:ICV
5169 u32 rateIndex;
5170 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02005171
5172
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005173 if (stats->bCRC)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005174 rcvType = 2;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005175 else if (stats->bICV)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005176 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005177
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005178 if (stats->bShortPreamble)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005179 preamble_guardinterval = 1;// short
5180 else
5181 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02005182
Xenia Ragiadakouad638452013-05-12 03:15:08 +03005183 switch (stats->rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005184 {
5185 //
5186 // CCK rate
5187 //
5188 case MGN_1M: rateIndex = 0; break;
5189 case MGN_2M: rateIndex = 1; break;
5190 case MGN_5_5M: rateIndex = 2; break;
5191 case MGN_11M: rateIndex = 3; break;
5192 //
5193 // Legacy OFDM rate
5194 //
5195 case MGN_6M: rateIndex = 4; break;
5196 case MGN_9M: rateIndex = 5; break;
5197 case MGN_12M: rateIndex = 6; break;
5198 case MGN_18M: rateIndex = 7; break;
5199 case MGN_24M: rateIndex = 8; break;
5200 case MGN_36M: rateIndex = 9; break;
5201 case MGN_48M: rateIndex = 10; break;
5202 case MGN_54M: rateIndex = 11; break;
5203 //
5204 // 11n High throughput rate
5205 //
5206 case MGN_MCS0: rateIndex = 12; break;
5207 case MGN_MCS1: rateIndex = 13; break;
5208 case MGN_MCS2: rateIndex = 14; break;
5209 case MGN_MCS3: rateIndex = 15; break;
5210 case MGN_MCS4: rateIndex = 16; break;
5211 case MGN_MCS5: rateIndex = 17; break;
5212 case MGN_MCS6: rateIndex = 18; break;
5213 case MGN_MCS7: rateIndex = 19; break;
5214 case MGN_MCS8: rateIndex = 20; break;
5215 case MGN_MCS9: rateIndex = 21; break;
5216 case MGN_MCS10: rateIndex = 22; break;
5217 case MGN_MCS11: rateIndex = 23; break;
5218 case MGN_MCS12: rateIndex = 24; break;
5219 case MGN_MCS13: rateIndex = 25; break;
5220 case MGN_MCS14: rateIndex = 26; break;
5221 case MGN_MCS15: rateIndex = 27; break;
5222 default: rateIndex = 28; break;
5223 }
5224 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
5225 priv->stats.received_rate_histogram[0][rateIndex]++; //total
5226 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
5227}
5228
5229
5230void query_rxdesc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats, bool bIsRxAggrSubframe)
5231{
5232 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5233 struct net_device *dev=info->dev;
5234 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5235 //rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
5236 rx_drvinfo_819x_usb *driver_info = NULL;
5237
5238 //
5239 //Get Rx Descriptor Information
5240 //
5241#ifdef USB_RX_AGGREGATION_SUPPORT
5242 if (bIsRxAggrSubframe)
5243 {
5244 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
5245 stats->Length = desc->Length ;
5246 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
5247 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
5248 stats->bICV = desc->ICV;
5249 stats->bCRC = desc->CRC32;
5250 stats->bHwError = stats->bCRC|stats->bICV;
5251 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
5252 } else
5253#endif
5254 {
5255 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
5256
5257 stats->Length = desc->Length;
5258 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
5259 stats->RxBufShift = 0;//desc->Shift&0x03;
5260 stats->bICV = desc->ICV;
5261 stats->bCRC = desc->CRC32;
5262 stats->bHwError = stats->bCRC|stats->bICV;
5263 //RTL8190 set this bit to indicate that Hw does not decrypt packet
5264 stats->Decrypted = !desc->SWDec;
5265 }
5266
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005267 if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
Jerry Chuang8fc85982009-11-03 07:17:11 -02005268 {
5269 stats->bHwError = false;
5270 }
5271 else
5272 {
5273 stats->bHwError = stats->bCRC|stats->bICV;
5274 }
5275
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005276 if (stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005277 stats->bHwError |= 1;
5278 //
5279 //Get Driver Info
5280 //
5281 // TODO: Need to verify it on FGPA platform
5282 //Driver info are written to the RxBuffer following rx desc
5283 if (stats->RxDrvInfoSize != 0) {
5284 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) + \
5285 stats->RxBufShift);
5286 /* unit: 0.5M */
5287 /* TODO */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005288 if (!stats->bHwError){
Jerry Chuang8fc85982009-11-03 07:17:11 -02005289 u8 ret_rate;
5290 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005291 if (ret_rate == 0xff)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005292 {
5293 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
5294 // Special Error Handling here, 2008.05.16, by Emily
5295
5296 stats->bHwError = 1;
5297 stats->rate = MGN_1M; //Set 1M rate by default
5298 }else
5299 {
5300 stats->rate = ret_rate;
5301 }
5302 }
5303 else
5304 stats->rate = 0x02;
5305
5306 stats->bShortPreamble = driver_info->SPLCP;
5307
5308
5309 UpdateReceivedRateHistogramStatistics8190(dev, stats);
5310
5311 stats->bIsAMPDU = (driver_info->PartAggr==1);
5312 stats->bFirstMPDU = (driver_info->PartAggr==1) && (driver_info->FirstAGGR==1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005313 stats->TimeStampLow = driver_info->TSFL;
5314 // xiong mask it, 070514
5315 //pRfd->Status.TimeStampHigh = PlatformEFIORead4Byte(Adapter, TSFR+4);
5316 // stats->TimeStampHigh = read_nic_dword(dev, TSFR+4);
5317
5318 UpdateRxPktTimeStamp8190(dev, stats);
5319
5320 //
5321 // Rx A-MPDU
5322 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005323 if (driver_info->FirstAGGR==1 || driver_info->PartAggr == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005324 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
5325 driver_info->FirstAGGR, driver_info->PartAggr);
5326
5327 }
5328
5329 skb_pull(skb,sizeof(rx_desc_819x_usb));
5330 //
5331 // Get Total offset of MPDU Frame Body
5332 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005333 if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005334 stats->bShift = 1;
5335 skb_pull(skb,stats->RxBufShift + stats->RxDrvInfoSize);
5336 }
5337
5338#ifdef USB_RX_AGGREGATION_SUPPORT
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005339 /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005340 if (bIsRxAggrSubframe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005341 skb_pull(skb, 8);
5342 }
5343#endif
5344 /* for debug 2008.5.29 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005345
5346 //added by vivi, for MP, 20080108
5347 stats->RxIs40MHzPacket = driver_info->BW;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005348 if (stats->RxDrvInfoSize != 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005349 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
5350
5351}
5352
5353u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
5354{
5355#ifdef USB_RX_AGGREGATION_SUPPORT
5356 if (bIsRxAggrSubframe)
5357 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
5358 + Status->RxBufShift + 8);
5359 else
5360#endif
5361 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
5362 + Status->RxBufShift);
5363}
5364
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005365void rtl8192_rx_nomal(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005366{
5367 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5368 struct net_device *dev=info->dev;
5369 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5370 struct ieee80211_rx_stats stats = {
5371 .signal = 0,
5372 .noise = -98,
5373 .rate = 0,
5374 // .mac_time = jiffies,
5375 .freq = IEEE80211_24GHZ_BAND,
5376 };
5377 u32 rx_pkt_len = 0;
5378 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
5379 bool unicast_packet = false;
5380#ifdef USB_RX_AGGREGATION_SUPPORT
5381 struct sk_buff *agg_skb = NULL;
5382 u32 TotalLength = 0;
5383 u32 TempDWord = 0;
5384 u32 PacketLength = 0;
5385 u32 PacketOccupiedLendth = 0;
5386 u8 TempByte = 0;
5387 u32 PacketShiftBytes = 0;
5388 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
5389 u8 PaddingBytes = 0;
5390 //add just for testing
5391 u8 testing;
5392
5393#endif
5394
5395 /* 20 is for ps-poll */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005396 if ((skb->len >=(20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005397#ifdef USB_RX_AGGREGATION_SUPPORT
5398 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
5399#endif
5400 /* first packet should not contain Rx aggregation header */
5401 query_rxdesc_status(skb, &stats, false);
5402 /* TODO */
5403 /* hardware related info */
5404#ifdef USB_RX_AGGREGATION_SUPPORT
5405 if (TempByte & BIT0) {
5406 agg_skb = skb;
5407 //TotalLength = agg_skb->len - 4; /*sCrcLng*/
5408 TotalLength = stats.Length - 4; /*sCrcLng*/
5409 //RT_TRACE(COMP_RECV, "%s:first aggregated packet!Length=%d\n",__FUNCTION__,TotalLength);
5410 /* though the head pointer has passed this position */
5411 TempDWord = *(u32 *)(agg_skb->data - 4);
5412 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
5413 skb = dev_alloc_skb(PacketLength);
5414 memcpy(skb_put(skb,PacketLength),agg_skb->data,PacketLength);
5415 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
5416 }
5417#endif
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005418 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005419 skb_trim(skb, skb->len - 4/*sCrcLng*/);
5420
5421 rx_pkt_len = skb->len;
5422 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
5423 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005424 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005425 //TODO
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005426 }else if (is_multicast_ether_addr(ieee80211_hdr->addr1)){
Jerry Chuang8fc85982009-11-03 07:17:11 -02005427 //TODO
5428 }else {
5429 /* unicast packet */
5430 unicast_packet = true;
5431 }
5432
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005433 if (!ieee80211_rx(priv->ieee80211,skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005434 dev_kfree_skb_any(skb);
5435 } else {
5436 priv->stats.rxoktotal++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005437 if (unicast_packet) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005438 priv->stats.rxbytesunicast += rx_pkt_len;
5439 }
5440 }
5441#ifdef USB_RX_AGGREGATION_SUPPORT
5442 testing = 1;
5443 // (PipeIndex == 0) && (TempByte & BIT0) => TotalLength > 0.
5444 if (TotalLength > 0) {
5445 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
5446 if ((PacketOccupiedLendth & 0xFF) != 0)
5447 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
5448 PacketOccupiedLendth -= 8;
5449 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
5450 if (agg_skb->len > TempDWord)
5451 skb_pull(agg_skb, TempDWord);
5452 else
5453 agg_skb->len = 0;
5454
5455 while (agg_skb->len>=GetRxPacketShiftBytes819xUsb(&stats, true)) {
5456 u8 tmpCRC = 0, tmpICV = 0;
5457 //RT_TRACE(COMP_RECV,"%s:aggred pkt,total_len = %d\n",__FUNCTION__,agg_skb->len);
5458 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
5459 tmpCRC = RxDescr->CRC32;
5460 tmpICV = RxDescr->ICV;
5461 memcpy(agg_skb->data, &agg_skb->data[44], 2);
5462 RxDescr->CRC32 = tmpCRC;
5463 RxDescr->ICV = tmpICV;
5464
5465 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
5466 stats.signal = 0;
5467 stats.noise = -98;
5468 stats.rate = 0;
5469 stats.freq = IEEE80211_24GHZ_BAND;
5470 query_rxdesc_status(agg_skb, &stats, true);
5471 PacketLength = stats.Length;
5472
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005473 if (PacketLength > agg_skb->len) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005474 break;
5475 }
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005476 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005477 skb = dev_alloc_skb(PacketLength);
5478 memcpy(skb_put(skb,PacketLength),agg_skb->data, PacketLength);
5479 skb_trim(skb, skb->len - 4/*sCrcLng*/);
5480
5481 rx_pkt_len = skb->len;
5482 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
5483 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005484 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005485 //TODO
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005486 }else if (is_multicast_ether_addr(ieee80211_hdr->addr1)){
Jerry Chuang8fc85982009-11-03 07:17:11 -02005487 //TODO
5488 }else {
5489 /* unicast packet */
5490 unicast_packet = true;
5491 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005492 if (!ieee80211_rx(priv->ieee80211,skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005493 dev_kfree_skb_any(skb);
5494 } else {
5495 priv->stats.rxoktotal++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005496 if (unicast_packet) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005497 priv->stats.rxbytesunicast += rx_pkt_len;
5498 }
5499 }
5500 /* should trim the packet which has been copied to target skb */
5501 skb_pull(agg_skb, PacketLength);
5502 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
5503 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
5504 if ((PacketOccupiedLendth & 0xFF) != 0) {
5505 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
5506 if (agg_skb->len > PaddingBytes)
5507 skb_pull(agg_skb, PaddingBytes);
5508 else
5509 agg_skb->len = 0;
5510 }
5511 }
5512 dev_kfree_skb(agg_skb);
5513 }
5514#endif
5515 } else {
5516 priv->stats.rxurberr++;
5517 printk("actual_length:%d\n", skb->len);
5518 dev_kfree_skb_any(skb);
5519 }
5520
5521}
5522
5523void
5524rtl819xusb_process_received_packet(
5525 struct net_device *dev,
5526 struct ieee80211_rx_stats *pstats
5527 )
5528{
5529// bool bfreerfd=false, bqueued=false;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005530 u8 *frame;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005531 u16 frame_len=0;
5532 struct r8192_priv *priv = ieee80211_priv(dev);
5533// u8 index = 0;
5534// u8 TID = 0;
5535 //u16 seqnum = 0;
5536 //PRX_TS_RECORD pts = NULL;
5537
5538 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
5539 //porting by amy 080508
5540 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
5541 frame = pstats->virtual_address;
5542 frame_len = pstats->packetlength;
5543#ifdef TODO // by amy about HCT
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005544 if (!Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005545 CountRxErrStatistics(Adapter, pRfd);
5546#endif
5547 {
5548 #ifdef ENABLE_PS //by amy for adding ps function in future
5549 RT_RF_POWER_STATE rtState;
5550 // When RF is off, we should not count the packet for hw/sw synchronize
5551 // reason, ie. there may be a duration while sw switch is changed and hw
5552 // switch is being changed. 2006.12.04, by shien chang.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005553 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8 *)(&rtState));
Jerry Chuang8fc85982009-11-03 07:17:11 -02005554 if (rtState == eRfOff)
5555 {
5556 return;
5557 }
5558 #endif
5559 priv->stats.rxframgment++;
5560
5561 }
5562#ifdef TODO
5563 RmMonitorSignalStrength(Adapter, pRfd);
5564#endif
5565 /* 2007/01/16 MH Add RX command packet handle here. */
5566 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
5567 if (rtl819xusb_rx_command_packet(dev, pstats))
5568 {
5569 return;
5570 }
5571
5572#ifdef SW_CRC_CHECK
5573 SwCrcCheck();
5574#endif
5575
5576
5577}
5578
5579void query_rx_cmdpkt_desc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats)
5580{
5581// rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5582// struct net_device *dev=info->dev;
5583// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5584 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
5585// rx_drvinfo_819x_usb *driver_info;
5586
5587 //
5588 //Get Rx Descriptor Information
5589 //
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005590 stats->virtual_address = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005591 stats->Length = desc->Length;
5592 stats->RxDrvInfoSize = 0;
5593 stats->RxBufShift = 0;
5594 stats->packetlength = stats->Length-scrclng;
5595 stats->fraglength = stats->packetlength;
5596 stats->fragoffset = 0;
5597 stats->ntotalfrag = 1;
5598}
5599
5600
5601void rtl8192_rx_cmd(struct sk_buff *skb)
5602{
5603 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5604 struct net_device *dev = info->dev;
5605 //int ret;
5606// struct urb *rx_urb = info->urb;
5607 /* TODO */
5608 struct ieee80211_rx_stats stats = {
5609 .signal = 0,
5610 .noise = -98,
5611 .rate = 0,
5612 // .mac_time = jiffies,
5613 .freq = IEEE80211_24GHZ_BAND,
5614 };
5615
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005616 if ((skb->len >=(20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE))
Jerry Chuang8fc85982009-11-03 07:17:11 -02005617 {
5618
5619 query_rx_cmdpkt_desc_status(skb,&stats);
5620 // this is to be done by amy 080508 prfd->queue_id = 1;
5621
5622
5623 //
5624 // Process the command packet received.
5625 //
5626
5627 rtl819xusb_process_received_packet(dev,&stats);
5628
5629 dev_kfree_skb_any(skb);
5630 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005631}
5632
5633void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
5634{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005635 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005636 struct rtl8192_rx_info *info;
5637
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005638 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005639 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005640 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005641 /* Nomal packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005642 case 3:
5643 //RT_TRACE(COMP_RECV, "normal in-pipe index(%d)\n",info->out_pipe);
5644 priv->IrpPendingCount--;
5645 rtl8192_rx_nomal(skb);
5646 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005647
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005648 /* Command packet pipe */
5649 case 9:
5650 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",\
5651 info->out_pipe);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005652
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005653 rtl8192_rx_cmd(skb);
5654 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005655
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005656 default: /* should never get here! */
5657 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",\
5658 info->out_pipe);
5659 dev_kfree_skb(skb);
5660 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005661
5662 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005663 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005664}
5665
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005666static const struct net_device_ops rtl8192_netdev_ops = {
5667 .ndo_open = rtl8192_open,
5668 .ndo_stop = rtl8192_close,
5669 .ndo_get_stats = rtl8192_stats,
5670 .ndo_tx_timeout = tx_timeout,
5671 .ndo_do_ioctl = rtl8192_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00005672 .ndo_set_rx_mode = r8192_set_multicast,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005673 .ndo_set_mac_address = r8192_set_mac_adr,
5674 .ndo_validate_addr = eth_validate_addr,
5675 .ndo_change_mtu = eth_change_mtu,
5676 .ndo_start_xmit = ieee80211_xmit,
5677};
Jerry Chuang8fc85982009-11-03 07:17:11 -02005678
5679
5680/****************************************************************************
5681 ---------------------------- USB_STUFF---------------------------
5682*****************************************************************************/
5683
Bill Pemberton25794522012-11-19 13:22:04 -05005684static int rtl8192_usb_probe(struct usb_interface *intf,
Jerry Chuang8fc85982009-11-03 07:17:11 -02005685 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005686{
5687// unsigned long ioaddr = 0;
5688 struct net_device *dev = NULL;
5689 struct r8192_priv *priv= NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005690 struct usb_device *udev = interface_to_usbdev(intf);
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005691 int ret;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005692 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005693
5694 dev = alloc_ieee80211(sizeof(struct r8192_priv));
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005695 if (dev == NULL)
5696 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005697
Jerry Chuang8fc85982009-11-03 07:17:11 -02005698 usb_set_intfdata(intf, dev);
5699 SET_NETDEV_DEV(dev, &intf->dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005700 priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005701 priv->ieee80211 = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005702 priv->udev=udev;
5703
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005704 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005705
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005706 //DMESG("Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005707#if WIRELESS_EXT >= 12
5708#if WIRELESS_EXT < 17
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005709 dev->get_wireless_stats = r8192_get_wireless_stats;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005710#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005711 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005712#endif
5713 dev->type=ARPHRD_ETHER;
5714
5715 dev->watchdog_timeo = HZ*3; //modified by john, 0805
5716
5717 if (dev_alloc_name(dev, ifname) < 0){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005718 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005719 ifname = "wlan%d";
5720 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005721 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005722
5723 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005724 if (rtl8192_init(dev)!=0){
Jerry Chuang8fc85982009-11-03 07:17:11 -02005725 RT_TRACE(COMP_ERR, "Initialization failed");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005726 ret = -ENODEV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005727 goto fail;
5728 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005729 netif_carrier_off(dev);
5730 netif_stop_queue(dev);
5731
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005732 ret = register_netdev(dev);
5733 if (ret)
5734 goto fail2;
5735
Jerry Chuang8fc85982009-11-03 07:17:11 -02005736 RT_TRACE(COMP_INIT, "dev name=======> %s\n",dev->name);
5737 rtl8192_proc_init_one(dev);
5738
5739
5740 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005741 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005742
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005743fail2:
5744 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005745 kfree(priv->pFirmware);
5746 priv->pFirmware = NULL;
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005747 rtl8192_usb_deleteendpoints(dev);
5748 destroy_workqueue(priv->priv_wq);
5749 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005750fail:
5751 free_ieee80211(dev);
5752
5753 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005754 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005755}
5756
5757//detach all the work and timer structure declared or inititialize in r8192U_init function.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005758void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005759{
5760
Jerry Chuang8fc85982009-11-03 07:17:11 -02005761 cancel_work_sync(&priv->reset_wq);
5762 cancel_delayed_work(&priv->watch_dog_wq);
5763 cancel_delayed_work(&priv->update_beacon_wq);
5764 cancel_work_sync(&priv->qos_activate);
5765 //cancel_work_sync(&priv->SetBWModeWorkItem);
5766 //cancel_work_sync(&priv->SwChnlWorkItem);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005767
5768}
5769
5770
Bill Pembertona4a557e2012-11-19 13:26:46 -05005771static void rtl8192_usb_disconnect(struct usb_interface *intf)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005772{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005773 struct net_device *dev = usb_get_intfdata(intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005774
5775 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005776 if (dev){
Jerry Chuang8fc85982009-11-03 07:17:11 -02005777
5778 unregister_netdev(dev);
5779
5780 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
5781 rtl8192_proc_remove_one(dev);
5782
5783 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005784 kfree(priv->pFirmware);
5785 priv->pFirmware = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005786 // priv->rf_close(dev);
5787// rtl8192_SetRFPowerState(dev, eRfOff);
5788 rtl8192_usb_deleteendpoints(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005789 destroy_workqueue(priv->priv_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005790 //rtl8192_irq_disable(dev);
5791 //rtl8192_reset(dev);
5792 mdelay(10);
5793
5794 }
5795 free_ieee80211(dev);
5796 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
5797}
5798
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005799/* fun with the built-in ieee80211 stack... */
5800extern int ieee80211_debug_init(void);
5801extern void ieee80211_debug_exit(void);
5802extern int ieee80211_crypto_init(void);
5803extern void ieee80211_crypto_deinit(void);
5804extern int ieee80211_crypto_tkip_init(void);
5805extern void ieee80211_crypto_tkip_exit(void);
5806extern int ieee80211_crypto_ccmp_init(void);
5807extern void ieee80211_crypto_ccmp_exit(void);
5808extern int ieee80211_crypto_wep_init(void);
5809extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005810
5811static int __init rtl8192_usb_module_init(void)
5812{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005813 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005814
5815#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005816 ret = ieee80211_debug_init();
5817 if (ret) {
5818 printk(KERN_ERR "ieee80211_debug_init() failed %d\n", ret);
5819 return ret;
5820 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005821#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005822 ret = ieee80211_crypto_init();
5823 if (ret) {
5824 printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret);
5825 return ret;
5826 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005827
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005828 ret = ieee80211_crypto_tkip_init();
5829 if (ret) {
5830 printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n",
5831 ret);
5832 return ret;
5833 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005834
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005835 ret = ieee80211_crypto_ccmp_init();
5836 if (ret) {
5837 printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n",
5838 ret);
5839 return ret;
5840 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005841
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005842 ret = ieee80211_crypto_wep_init();
5843 if (ret) {
5844 printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret);
5845 return ret;
5846 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005847
Jerry Chuang8fc85982009-11-03 07:17:11 -02005848 printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n");
5849 printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n");
5850 RT_TRACE(COMP_INIT, "Initializing module");
5851 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
5852 rtl8192_proc_module_init();
5853 return usb_register(&rtl8192_usb_driver);
5854}
5855
5856
5857static void __exit rtl8192_usb_module_exit(void)
5858{
5859 usb_deregister(&rtl8192_usb_driver);
5860
5861 RT_TRACE(COMP_DOWN, "Exiting");
5862// rtl8192_proc_module_remove();
5863}
5864
5865
5866void rtl8192_try_wake_queue(struct net_device *dev, int pri)
5867{
5868 unsigned long flags;
5869 short enough_desc;
5870 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5871
5872 spin_lock_irqsave(&priv->tx_lock,flags);
5873 enough_desc = check_nic_enough_desc(dev,pri);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005874 spin_unlock_irqrestore(&priv->tx_lock,flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005875
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005876 if (enough_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005877 ieee80211_wake_queue(priv->ieee80211);
5878}
5879
5880void EnableHWSecurityConfig8192(struct net_device *dev)
5881{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005882 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005883 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005884 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005885 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005886 if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->ieee80211->auth_mode != 2))
5887 {
5888 SECR_value |= SCR_RxUseDK;
5889 SECR_value |= SCR_TxUseDK;
5890 }
5891 else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP)))
5892 {
5893 SECR_value |= SCR_RxUseDK;
5894 SECR_value |= SCR_TxUseDK;
5895 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005896 //add HWSec active enable here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02005897//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
5898
5899 ieee->hwsec_active = 1;
5900
5901 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
5902 {
5903 ieee->hwsec_active = 0;
5904 SECR_value &= ~SCR_RxDecEnable;
5905 }
5906 RT_TRACE(COMP_SEC,"%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __FUNCTION__, \
5907 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
5908 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005909 write_nic_byte(dev, SECR, SECR_value);//SECR_value | SCR_UseDK );
5910 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005911}
5912
5913
5914void setKey( struct net_device *dev,
5915 u8 EntryNo,
5916 u8 KeyIndex,
5917 u16 KeyType,
5918 u8 *MacAddr,
5919 u8 DefaultKey,
5920 u32 *KeyContent )
5921{
5922 u32 TargetCommand = 0;
5923 u32 TargetContent = 0;
5924 u16 usConfig = 0;
5925 u8 i;
5926 if (EntryNo >= TOTAL_CAM_ENTRY)
5927 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
5928
Joe Perches0ee9f672009-12-06 11:34:52 -08005929 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 -02005930
5931 if (DefaultKey)
5932 usConfig |= BIT15 | (KeyType<<2);
5933 else
5934 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
5935// usConfig |= BIT15 | (KeyType<<2) | (DefaultKey<<5) | KeyIndex;
5936
5937
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03005938 for (i=0 ; i<CAM_CONTENT_COUNT; i++){
Jerry Chuang8fc85982009-11-03 07:17:11 -02005939 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
5940 TargetCommand |= BIT31|BIT16;
5941
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005942 if (i==0){//MAC|Config
Jerry Chuang8fc85982009-11-03 07:17:11 -02005943 TargetContent = (u32)(*(MacAddr+0)) << 16|
5944 (u32)(*(MacAddr+1)) << 24|
5945 (u32)usConfig;
5946
5947 write_nic_dword(dev, WCAMI, TargetContent);
5948 write_nic_dword(dev, RWCAM, TargetCommand);
5949 // printk("setkey cam =%8x\n", read_cam(dev, i+6*EntryNo));
5950 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005951 else if (i==1){//MAC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005952 TargetContent = (u32)(*(MacAddr+2)) |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005953 (u32)(*(MacAddr+3)) << 8|
5954 (u32)(*(MacAddr+4)) << 16|
5955 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005956 write_nic_dword(dev, WCAMI, TargetContent);
5957 write_nic_dword(dev, RWCAM, TargetCommand);
5958 }
5959 else {
5960 //Key Material
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005961 if (KeyContent !=NULL){
Jerry Chuang8fc85982009-11-03 07:17:11 -02005962 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)) );
5963 write_nic_dword(dev, RWCAM, TargetCommand);
5964 }
5965 }
5966 }
5967
5968}
5969
5970/***************************************************************************
5971 ------------------- module init / exit stubs ----------------
5972****************************************************************************/
5973module_init(rtl8192_usb_module_init);
5974module_exit(rtl8192_usb_module_exit);