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