blob: 01f82d36fcf6772d70aea5aa60f9d1fd95b062e4 [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 = \
Sebastian Hahn35997ff2012-12-05 21:40:18 +010083 // COMP_INIT |
Jerry Chuang8fc85982009-11-03 07:17:11 -020084// COMP_DBG |
Sebastian Hahn35997ff2012-12-05 21:40:18 +010085 // COMP_EPROM |
Jerry Chuang8fc85982009-11-03 07:17:11 -020086// 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 */
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100162 .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
Jennifer Naumann0db7a342012-12-05 21:40:19 +0100167typedef struct _CHANNEL_LIST {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200168 u8 Channel[32];
169 u8 Len;
170}CHANNEL_LIST, *PCHANNEL_LIST;
171
172static CHANNEL_LIST ChannelPlan[] = {
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100173 {{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
174 {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC
175 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //ETSI
Jerry Chuang8fc85982009-11-03 07:17:11 -0200176 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Spain. Change to ETSI.
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100177 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //France. Change to ETSI.
Jerry Chuang8fc85982009-11-03 07:17:11 -0200178 {{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
179 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1
180 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Israel.
181 {{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
182 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22}, //MIC
183 {{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
184};
185
186static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv* priv)
187{
188 int i, max_chan=-1, min_chan=-1;
189 struct ieee80211_device* ieee = priv->ieee80211;
190 switch (channel_plan)
191 {
192 case COUNTRY_CODE_FCC:
193 case COUNTRY_CODE_IC:
194 case COUNTRY_CODE_ETSI:
195 case COUNTRY_CODE_SPAIN:
196 case COUNTRY_CODE_FRANCE:
197 case COUNTRY_CODE_MKK:
198 case COUNTRY_CODE_MKK1:
199 case COUNTRY_CODE_ISRAEL:
200 case COUNTRY_CODE_TELEC:
201 case COUNTRY_CODE_MIC:
202 {
203 Dot11d_Init(ieee);
204 ieee->bGlobalDomain = false;
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -0700205 //actually 8225 & 8256 rf chips only support B,G,24N mode
Jerry Chuang8fc85982009-11-03 07:17:11 -0200206 if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256))
207 {
208 min_chan = 1;
209 max_chan = 14;
210 }
211 else
212 {
213 RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __FUNCTION__);
214 }
215 if (ChannelPlan[channel_plan].Len != 0){
216 // Clear old channel map
217 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
218 // Set new channel map
219 for (i=0;i<ChannelPlan[channel_plan].Len;i++)
220 {
221 if (ChannelPlan[channel_plan].Channel[i] < min_chan || ChannelPlan[channel_plan].Channel[i] > max_chan)
222 break;
223 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
224 }
225 }
226 break;
227 }
228 case COUNTRY_CODE_GLOBAL_DOMAIN:
229 {
230 GET_DOT11D_INFO(ieee)->bEnabled = 0;//this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain settings.
231 Dot11d_Reset(ieee);
232 ieee->bGlobalDomain = true;
233 break;
234 }
235 default:
236 break;
237 }
238 return;
239}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200240
Jerry Chuang8fc85982009-11-03 07:17:11 -0200241
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100242#define rx_hal_is_cck_rate(_pdrvinfo)\
Jerry Chuang8fc85982009-11-03 07:17:11 -0200243 (_pdrvinfo->RxRate == DESC90_RATE1M ||\
244 _pdrvinfo->RxRate == DESC90_RATE2M ||\
245 _pdrvinfo->RxRate == DESC90_RATE5_5M ||\
246 _pdrvinfo->RxRate == DESC90_RATE11M) &&\
247 !_pdrvinfo->RxHT\
248
249
250void CamResetAllEntry(struct net_device *dev)
251{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200252 u32 ulcommand = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200253 //2004/02/11 In static WEP, OID_ADD_KEY or OID_ADD_WEP are set before STA associate to AP.
254 // However, ResetKey is called on OID_802_11_INFRASTRUCTURE_MODE and MlmeAssociateRequest
255 // In this condition, Cam can not be reset because upper layer will not set this static key again.
256 //if(Adapter->EncAlgorithm == WEP_Encryption)
257 // return;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200258//debug
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200259 //DbgPrint("========================================\n");
260 //DbgPrint(" Call ResetAllEntry \n");
261 //DbgPrint("========================================\n\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200262 ulcommand |= BIT31|BIT30;
263 write_nic_dword(dev, RWCAM, ulcommand);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200264
265}
266
267
268void write_cam(struct net_device *dev, u8 addr, u32 data)
269{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200270 write_nic_dword(dev, WCAMI, data);
271 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff) );
Jerry Chuang8fc85982009-11-03 07:17:11 -0200272}
273
274u32 read_cam(struct net_device *dev, u8 addr)
275{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200276 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff) );
277 return read_nic_dword(dev, 0xa8);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200278}
279
280void write_nic_byte_E(struct net_device *dev, int indx, u8 data)
281{
282 int status;
283 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
284 struct usb_device *udev = priv->udev;
285
286 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
287 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
288 indx|0xfe00, 0, &data, 1, HZ / 2);
289
290 if (status < 0)
291 {
292 printk("write_nic_byte_E TimeOut! status:%d\n", status);
293 }
294}
295
296u8 read_nic_byte_E(struct net_device *dev, int indx)
297{
298 int status;
299 u8 data;
300 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
301 struct usb_device *udev = priv->udev;
302
303 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
304 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
305 indx|0xfe00, 0, &data, 1, HZ / 2);
306
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200307 if (status < 0)
308 {
309 printk("read_nic_byte_E TimeOut! status:%d\n", status);
310 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200311
312 return data;
313}
314//as 92U has extend page from 4 to 16, so modify functions below.
315void write_nic_byte(struct net_device *dev, int indx, u8 data)
316{
317 int status;
318
319 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
320 struct usb_device *udev = priv->udev;
321
322 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
323 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
324 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
325
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200326 if (status < 0)
327 {
328 printk("write_nic_byte TimeOut! status:%d\n", status);
329 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200330
331
332}
333
334
335void write_nic_word(struct net_device *dev, int indx, u16 data)
336{
337
338 int status;
339
340 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
341 struct usb_device *udev = priv->udev;
342
343 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
344 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
345 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2);
346
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200347 if (status < 0)
348 {
349 printk("write_nic_word TimeOut! status:%d\n", status);
350 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200351
352}
353
354
355void write_nic_dword(struct net_device *dev, int indx, u32 data)
356{
357
358 int status;
359
360 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
361 struct usb_device *udev = priv->udev;
362
363 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
364 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
365 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2);
366
367
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200368 if (status < 0)
369 {
370 printk("write_nic_dword TimeOut! status:%d\n", status);
371 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200372
373}
374
375
376
377u8 read_nic_byte(struct net_device *dev, int indx)
378{
379 u8 data;
380 int status;
381 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
382 struct usb_device *udev = priv->udev;
383
384 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
385 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
386 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
387
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200388 if (status < 0)
389 {
390 printk("read_nic_byte TimeOut! status:%d\n", status);
391 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200392
393 return data;
394}
395
396
397
398u16 read_nic_word(struct net_device *dev, int indx)
399{
400 u16 data;
401 int status;
402 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
403 struct usb_device *udev = priv->udev;
404
405 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Mike Gilks616f58f2010-06-03 18:29:23 +0800406 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
407 (indx&0xff)|0xff00, (indx>>8)&0x0f,
408 &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200409
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200410 if (status < 0)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200411 printk("read_nic_word TimeOut! status:%d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200412
413 return data;
414}
415
416u16 read_nic_word_E(struct net_device *dev, int indx)
417{
418 u16 data;
419 int status;
420 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
421 struct usb_device *udev = priv->udev;
422
423 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
424 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Mike Gilks616f58f2010-06-03 18:29:23 +0800425 indx|0xfe00, 0, &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200426
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200427 if (status < 0)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200428 printk("read_nic_word TimeOut! status:%d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200429
430 return data;
431}
432
433u32 read_nic_dword(struct net_device *dev, int indx)
434{
435 u32 data;
436 int status;
Mike Gilks616f58f2010-06-03 18:29:23 +0800437 /* int result; */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200438
439 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
440 struct usb_device *udev = priv->udev;
441
442 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Mike Gilks616f58f2010-06-03 18:29:23 +0800443 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
444 (indx&0xff)|0xff00, (indx>>8)&0x0f,
445 &data, 4, HZ / 2);
446 /* if(0 != result) {
447 * printk(KERN_WARNING "read size of data = %d\, date = %d\n",
448 * result, data);
449 * }
450 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200451
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200452 if (status < 0)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200453 printk("read_nic_dword TimeOut! status:%d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200454
455 return data;
456}
457
Mike Gilks616f58f2010-06-03 18:29:23 +0800458/* u8 read_phy_cck(struct net_device *dev, u8 adr); */
459/* u8 read_phy_ofdm(struct net_device *dev, u8 adr); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200460/* this might still called in what was the PHY rtl8185/rtl8192 common code
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300461 * plans are to possibility turn it again in one common code...
Jerry Chuang8fc85982009-11-03 07:17:11 -0200462 */
463inline void force_pci_posting(struct net_device *dev)
464{
465}
466
Jerry Chuang8fc85982009-11-03 07:17:11 -0200467static struct net_device_stats *rtl8192_stats(struct net_device *dev);
468void rtl8192_commit(struct net_device *dev);
Mike Gilks616f58f2010-06-03 18:29:23 +0800469/* void rtl8192_restart(struct net_device *dev); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200470void rtl8192_restart(struct work_struct *work);
Mike Gilks616f58f2010-06-03 18:29:23 +0800471/* void rtl8192_rq_tx_ack(struct work_struct *work); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200472void watch_dog_timer_callback(unsigned long data);
473
474/****************************************************************************
Mike Gilks616f58f2010-06-03 18:29:23 +0800475 * -----------------------------PROCFS STUFF-------------------------
476*****************************************************************************
477 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200478
Mike Gilks616f58f2010-06-03 18:29:23 +0800479static struct proc_dir_entry *rtl8192_proc;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200480
Mike Gilks616f58f2010-06-03 18:29:23 +0800481static int proc_get_stats_ap(char *page, char **start, off_t offset, int count,
482 int *eof, void *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200483{
484 struct net_device *dev = data;
485 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
486 struct ieee80211_device *ieee = priv->ieee80211;
487 struct ieee80211_network *target;
488
489 int len = 0;
490
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200491 list_for_each_entry(target, &ieee->network_list, list) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200492
Mike Gilks616f58f2010-06-03 18:29:23 +0800493 len += snprintf(page + len, count - len, "%s ", target->ssid);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200494
Mike Gilks616f58f2010-06-03 18:29:23 +0800495 if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0)
496 len += snprintf(page + len, count - len, "WPA\n");
497 else
498 len += snprintf(page + len, count - len, "non_WPA\n");
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200499 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200500
501 *eof = 1;
502 return len;
503}
504
505static int proc_get_registers(char *page, char **start,
506 off_t offset, int count,
507 int *eof, void *data)
508{
509 struct net_device *dev = data;
510// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
511
512 int len = 0;
513 int i,n;
514
515 int max=0xff;
516
517 /* This dump the current register page */
518len += snprintf(page + len, count - len,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200519 "\n####################page 0##################\n ");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200520
521 for(n=0;n<=max;)
522 {
523 //printk( "\nD: %2x> ", n);
524 len += snprintf(page + len, count - len,
525 "\nD: %2x > ",n);
526
527 for(i=0;i<16 && n<=max;i++,n++)
528 len += snprintf(page + len, count - len,
529 "%2x ",read_nic_byte(dev,0x000|n));
530
531 // printk("%2x ",read_nic_byte(dev,n));
532 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200533len += snprintf(page + len, count - len,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200534 "\n####################page 1##################\n ");
535 for(n=0;n<=max;)
536 {
537 //printk( "\nD: %2x> ", n);
538 len += snprintf(page + len, count - len,
539 "\nD: %2x > ",n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200540
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200541 for(i=0;i<16 && n<=max;i++,n++)
542 len += snprintf(page + len, count - len,
543 "%2x ",read_nic_byte(dev,0x100|n));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200544
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200545 // printk("%2x ",read_nic_byte(dev,n));
546 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200547len += snprintf(page + len, count - len,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200548 "\n####################page 3##################\n ");
549 for(n=0;n<=max;)
550 {
551 //printk( "\nD: %2x> ", n);
552 len += snprintf(page + len, count - len,
553 "\nD: %2x > ",n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200554
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200555 for(i=0;i<16 && n<=max;i++,n++)
556 len += snprintf(page + len, count - len,
557 "%2x ",read_nic_byte(dev,0x300|n));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200558
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200559 // printk("%2x ",read_nic_byte(dev,n));
560 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200561
Jerry Chuang8fc85982009-11-03 07:17:11 -0200562
563 len += snprintf(page + len, count - len,"\n");
564 *eof = 1;
565 return len;
566
567}
568
569
Jerry Chuang8fc85982009-11-03 07:17:11 -0200570
571
Jerry Chuang8fc85982009-11-03 07:17:11 -0200572
573static int proc_get_stats_tx(char *page, char **start,
574 off_t offset, int count,
575 int *eof, void *data)
576{
577 struct net_device *dev = data;
578 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
579
580 int len = 0;
581
582 len += snprintf(page + len, count - len,
583 "TX VI priority ok int: %lu\n"
584 "TX VI priority error int: %lu\n"
585 "TX VO priority ok int: %lu\n"
586 "TX VO priority error int: %lu\n"
587 "TX BE priority ok int: %lu\n"
588 "TX BE priority error int: %lu\n"
589 "TX BK priority ok int: %lu\n"
590 "TX BK priority error int: %lu\n"
591 "TX MANAGE priority ok int: %lu\n"
592 "TX MANAGE priority error int: %lu\n"
593 "TX BEACON priority ok int: %lu\n"
594 "TX BEACON priority error int: %lu\n"
595// "TX high priority ok int: %lu\n"
596// "TX high priority failed error int: %lu\n"
597 "TX queue resume: %lu\n"
598 "TX queue stopped?: %d\n"
599 "TX fifo overflow: %lu\n"
600// "TX beacon: %lu\n"
601 "TX VI queue: %d\n"
602 "TX VO queue: %d\n"
603 "TX BE queue: %d\n"
604 "TX BK queue: %d\n"
605// "TX HW queue: %d\n"
606 "TX VI dropped: %lu\n"
607 "TX VO dropped: %lu\n"
608 "TX BE dropped: %lu\n"
609 "TX BK dropped: %lu\n"
610 "TX total data packets %lu\n",
611// "TX beacon aborted: %lu\n",
612 priv->stats.txviokint,
613 priv->stats.txvierr,
614 priv->stats.txvookint,
615 priv->stats.txvoerr,
616 priv->stats.txbeokint,
617 priv->stats.txbeerr,
618 priv->stats.txbkokint,
619 priv->stats.txbkerr,
620 priv->stats.txmanageokint,
621 priv->stats.txmanageerr,
622 priv->stats.txbeaconokint,
623 priv->stats.txbeaconerr,
624// priv->stats.txhpokint,
625// priv->stats.txhperr,
626 priv->stats.txresumed,
627 netif_queue_stopped(dev),
628 priv->stats.txoverflow,
629// priv->stats.txbeacon,
630 atomic_read(&(priv->tx_pending[VI_PRIORITY])),
631 atomic_read(&(priv->tx_pending[VO_PRIORITY])),
632 atomic_read(&(priv->tx_pending[BE_PRIORITY])),
633 atomic_read(&(priv->tx_pending[BK_PRIORITY])),
634// read_nic_byte(dev, TXFIFOCOUNT),
635 priv->stats.txvidrop,
636 priv->stats.txvodrop,
637 priv->stats.txbedrop,
638 priv->stats.txbkdrop,
639 priv->stats.txdatapkt
640// priv->stats.txbeaconerr
641 );
642
643 *eof = 1;
644 return len;
645}
646
647
648
649static int proc_get_stats_rx(char *page, char **start,
650 off_t offset, int count,
651 int *eof, void *data)
652{
653 struct net_device *dev = data;
654 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
655
656 int len = 0;
657
658 len += snprintf(page + len, count - len,
659 "RX packets: %lu\n"
660 "RX urb status error: %lu\n"
661 "RX invalid urb error: %lu\n",
662 priv->stats.rxoktotal,
663 priv->stats.rxstaterr,
664 priv->stats.rxurberr);
665
666 *eof = 1;
667 return len;
668}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200669void rtl8192_proc_module_init(void)
670{
671 RT_TRACE(COMP_INIT, "Initializing proc filesystem");
Al Viroe55d92b2011-07-24 02:07:46 -0400672 rtl8192_proc = proc_mkdir(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200673}
674
675
676void rtl8192_proc_module_remove(void)
677{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200678 remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200679}
680
681
682void rtl8192_proc_remove_one(struct net_device *dev)
683{
684 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
685
686
687 if (priv->dir_dev) {
688 // remove_proc_entry("stats-hw", priv->dir_dev);
689 remove_proc_entry("stats-tx", priv->dir_dev);
690 remove_proc_entry("stats-rx", priv->dir_dev);
691 // remove_proc_entry("stats-ieee", priv->dir_dev);
692 remove_proc_entry("stats-ap", priv->dir_dev);
693 remove_proc_entry("registers", priv->dir_dev);
694 // remove_proc_entry("cck-registers",priv->dir_dev);
695 // remove_proc_entry("ofdm-registers",priv->dir_dev);
696 //remove_proc_entry(dev->name, rtl8192_proc);
697 remove_proc_entry("wlan0", rtl8192_proc);
698 priv->dir_dev = NULL;
699 }
700}
701
702
703void rtl8192_proc_init_one(struct net_device *dev)
704{
705 struct proc_dir_entry *e;
706 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Al Viroe55d92b2011-07-24 02:07:46 -0400707 priv->dir_dev = proc_mkdir(dev->name, rtl8192_proc);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200708 if (!priv->dir_dev) {
709 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
710 dev->name);
711 return;
712 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200713 e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
714 priv->dir_dev, proc_get_stats_rx, dev);
715
716 if (!e) {
717 RT_TRACE(COMP_ERR,"Unable to initialize "
718 "/proc/net/rtl8192/%s/stats-rx\n",
719 dev->name);
720 }
721
722
723 e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
724 priv->dir_dev, proc_get_stats_tx, dev);
725
726 if (!e) {
727 RT_TRACE(COMP_ERR, "Unable to initialize "
728 "/proc/net/rtl8192/%s/stats-tx\n",
729 dev->name);
730 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200731
732 e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO,
733 priv->dir_dev, proc_get_stats_ap, dev);
734
735 if (!e) {
736 RT_TRACE(COMP_ERR, "Unable to initialize "
737 "/proc/net/rtl8192/%s/stats-ap\n",
738 dev->name);
739 }
740
741 e = create_proc_read_entry("registers", S_IFREG | S_IRUGO,
742 priv->dir_dev, proc_get_registers, dev);
743 if (!e) {
744 RT_TRACE(COMP_ERR, "Unable to initialize "
745 "/proc/net/rtl8192/%s/registers\n",
746 dev->name);
747 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200748}
749/****************************************************************************
750 -----------------------------MISC STUFF-------------------------
751*****************************************************************************/
752
753/* this is only for debugging */
754void print_buffer(u32 *buffer, int len)
755{
756 int i;
757 u8 *buf =(u8*)buffer;
758
759 printk("ASCII BUFFER DUMP (len: %x):\n",len);
760
761 for(i=0;i<len;i++)
762 printk("%c",buf[i]);
763
764 printk("\nBINARY BUFFER DUMP (len: %x):\n",len);
765
766 for(i=0;i<len;i++)
767 printk("%x",buf[i]);
768
769 printk("\n");
770}
771
772//short check_nic_enough_desc(struct net_device *dev, priority_t priority)
773short check_nic_enough_desc(struct net_device *dev,int queue_index)
774{
775 struct r8192_priv *priv = ieee80211_priv(dev);
776 int used = atomic_read(&priv->tx_pending[queue_index]);
777
778 return (used < MAX_TX_URB);
779}
780
781void tx_timeout(struct net_device *dev)
782{
783 struct r8192_priv *priv = ieee80211_priv(dev);
784 //rtl8192_commit(dev);
785
Jerry Chuang8fc85982009-11-03 07:17:11 -0200786 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200787 //DMESG("TXTIMEOUT");
788}
789
790
791/* this is only for debug */
792void dump_eprom(struct net_device *dev)
793{
794 int i;
795 for(i=0; i<63; i++)
796 RT_TRACE(COMP_EPROM, "EEPROM addr %x : %x", i, eprom_read(dev,i));
797}
798
799/* this is only for debug */
800void rtl8192_dump_reg(struct net_device *dev)
801{
802 int i;
803 int n;
804 int max=0x1ff;
805
806 RT_TRACE(COMP_PHY, "Dumping NIC register map");
807
808 for(n=0;n<=max;)
809 {
810 printk( "\nD: %2x> ", n);
811 for(i=0;i<16 && n<=max;i++,n++)
812 printk("%2x ",read_nic_byte(dev,n));
813 }
814 printk("\n");
815}
816
817/****************************************************************************
818 ------------------------------HW STUFF---------------------------
819*****************************************************************************/
820
Jerry Chuang8fc85982009-11-03 07:17:11 -0200821
822void rtl8192_set_mode(struct net_device *dev,int mode)
823{
824 u8 ecmd;
825 ecmd=read_nic_byte(dev, EPROM_CMD);
826 ecmd=ecmd &~ EPROM_CMD_OPERATING_MODE_MASK;
827 ecmd=ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
828 ecmd=ecmd &~ (1<<EPROM_CS_SHIFT);
829 ecmd=ecmd &~ (1<<EPROM_CK_SHIFT);
830 write_nic_byte(dev, EPROM_CMD, ecmd);
831}
832
833
834void rtl8192_update_msr(struct net_device *dev)
835{
836 struct r8192_priv *priv = ieee80211_priv(dev);
837 u8 msr;
838
839 msr = read_nic_byte(dev, MSR);
840 msr &= ~ MSR_LINK_MASK;
841
842 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
843 * msr must be updated if the state is ASSOCIATING.
844 * this is intentional and make sense for ad-hoc and
845 * master (see the create BSS/IBSS func)
846 */
847 if (priv->ieee80211->state == IEEE80211_LINKED){
848
849 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
850 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
851 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
852 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
853 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
854 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
855
856 }else
857 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
858
859 write_nic_byte(dev, MSR, msr);
860}
861
862void rtl8192_set_chan(struct net_device *dev,short ch)
863{
864 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
865// u32 tx;
866 RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __FUNCTION__, ch);
867 priv->chan=ch;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200868
869 /* this hack should avoid frame TX during channel setting*/
870
871
872// tx = read_nic_dword(dev,TX_CONF);
873// tx &= ~TX_LOOPBACK_MASK;
874
875#ifndef LOOP_TEST
876// write_nic_dword(dev,TX_CONF, tx |( TX_LOOPBACK_MAC<<TX_LOOPBACK_SHIFT));
877
878 //need to implement rf set channel here WB
879
880 if (priv->rf_set_chan)
881 priv->rf_set_chan(dev,priv->chan);
882 mdelay(10);
883// write_nic_dword(dev,TX_CONF,tx | (TX_LOOPBACK_NONE<<TX_LOOPBACK_SHIFT));
884#endif
885}
886
Jerry Chuang8fc85982009-11-03 07:17:11 -0200887static void rtl8192_rx_isr(struct urb *urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200888//static void rtl8192_rx_isr(struct urb *rx_urb);
889
890u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
891{
892
893#ifdef USB_RX_AGGREGATION_SUPPORT
894 if (pstats->bisrxaggrsubframe)
895 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
896 + pstats->RxBufShift + 8);
897 else
898#endif
899 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
900 + pstats->RxBufShift);
901
902}
903static int rtl8192_rx_initiate(struct net_device*dev)
904{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200905 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
906 struct urb *entry;
907 struct sk_buff *skb;
908 struct rtl8192_rx_info *info;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200909
910 /* nomal packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200911 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB) {
912 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
913 if (!skb)
914 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200915 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200916 if (!entry) {
917 kfree_skb(skb);
918 break;
919 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200920// printk("nomal packet IN request!\n");
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200921 usb_fill_bulk_urb(entry, priv->udev,
922 usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb),
923 RX_URB_SIZE, rtl8192_rx_isr, skb);
924 info = (struct rtl8192_rx_info *) skb->cb;
925 info->urb = entry;
926 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200927 info->out_pipe = 3; //denote rx normal packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200928 skb_queue_tail(&priv->rx_queue, skb);
929 usb_submit_urb(entry, GFP_KERNEL);
930 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200931
932 /* command packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200933 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200934// printk("command packet IN request!\n");
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200935 skb = __dev_alloc_skb(RX_URB_SIZE ,GFP_KERNEL);
936 if (!skb)
937 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200938 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200939 if (!entry) {
940 kfree_skb(skb);
941 break;
942 }
943 usb_fill_bulk_urb(entry, priv->udev,
944 usb_rcvbulkpipe(priv->udev, 9), skb_tail_pointer(skb),
945 RX_URB_SIZE, rtl8192_rx_isr, skb);
946 info = (struct rtl8192_rx_info *) skb->cb;
947 info->urb = entry;
948 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200949 info->out_pipe = 9; //denote rx cmd packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200950 skb_queue_tail(&priv->rx_queue, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200951 usb_submit_urb(entry, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200952 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200953
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200954 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200955}
956
957void rtl8192_set_rxconf(struct net_device *dev)
958{
959 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
960 u32 rxconf;
961
962 rxconf=read_nic_dword(dev,RCR);
963 rxconf = rxconf &~ MAC_FILTER_MASK;
964 rxconf = rxconf | RCR_AMF;
965 rxconf = rxconf | RCR_ADF;
966 rxconf = rxconf | RCR_AB;
967 rxconf = rxconf | RCR_AM;
968 //rxconf = rxconf | RCR_ACF;
969
970 if (dev->flags & IFF_PROMISC) {DMESG ("NIC in promisc mode");}
971
972 if(priv->ieee80211->iw_mode == IW_MODE_MONITOR || \
973 dev->flags & IFF_PROMISC){
974 rxconf = rxconf | RCR_AAP;
975 } /*else if(priv->ieee80211->iw_mode == IW_MODE_MASTER){
976 rxconf = rxconf | (1<<ACCEPT_ALLMAC_FRAME_SHIFT);
977 rxconf = rxconf | (1<<RX_CHECK_BSSID_SHIFT);
978 }*/else{
979 rxconf = rxconf | RCR_APM;
980 rxconf = rxconf | RCR_CBSSID;
981 }
982
983
984 if(priv->ieee80211->iw_mode == IW_MODE_MONITOR){
985 rxconf = rxconf | RCR_AICV;
986 rxconf = rxconf | RCR_APWRMGT;
987 }
988
989 if( priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
990 rxconf = rxconf | RCR_ACRC32;
991
992
993 rxconf = rxconf &~ RX_FIFO_THRESHOLD_MASK;
994 rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE<<RX_FIFO_THRESHOLD_SHIFT);
995 rxconf = rxconf &~ MAX_RX_DMA_MASK;
996 rxconf = rxconf | ((u32)7<<RCR_MXDMA_OFFSET);
997
998// rxconf = rxconf | (1<<RX_AUTORESETPHY_SHIFT);
999 rxconf = rxconf | RCR_ONLYERLPKT;
1000
1001// rxconf = rxconf &~ RCR_CS_MASK;
1002// rxconf = rxconf | (1<<RCR_CS_SHIFT);
1003
1004 write_nic_dword(dev, RCR, rxconf);
1005
1006 #ifdef DEBUG_RX
1007 DMESG("rxconf: %x %x",rxconf ,read_nic_dword(dev,RCR));
1008 #endif
1009}
1010//wait to be removed
1011void rtl8192_rx_enable(struct net_device *dev)
1012{
1013 //u8 cmd;
1014
1015 //struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1016
1017 rtl8192_rx_initiate(dev);
1018
1019// rtl8192_set_rxconf(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001020}
1021
1022
1023void rtl8192_tx_enable(struct net_device *dev)
1024{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001025}
1026
Jerry Chuang8fc85982009-11-03 07:17:11 -02001027
1028
1029void rtl8192_rtx_disable(struct net_device *dev)
1030{
1031 u8 cmd;
1032 struct r8192_priv *priv = ieee80211_priv(dev);
1033 struct sk_buff *skb;
1034 struct rtl8192_rx_info *info;
1035
1036 cmd=read_nic_byte(dev,CMDR);
1037 write_nic_byte(dev, CMDR, cmd &~ \
1038 (CR_TE|CR_RE));
1039 force_pci_posting(dev);
1040 mdelay(10);
1041
1042 while ((skb = __skb_dequeue(&priv->rx_queue))) {
1043 info = (struct rtl8192_rx_info *) skb->cb;
1044 if (!info->urb)
1045 continue;
1046
1047 usb_kill_urb(info->urb);
1048 kfree_skb(skb);
1049 }
1050
1051 if (skb_queue_len(&priv->skb_queue)) {
1052 printk(KERN_WARNING "skb_queue not empty\n");
1053 }
1054
1055 skb_queue_purge(&priv->skb_queue);
1056 return;
1057}
1058
1059
1060int alloc_tx_beacon_desc_ring(struct net_device *dev, int count)
1061{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001062 return 0;
1063}
1064
Jerry Chuang8fc85982009-11-03 07:17:11 -02001065inline u16 ieeerate2rtlrate(int rate)
1066{
1067 switch(rate){
1068 case 10:
1069 return 0;
1070 case 20:
1071 return 1;
1072 case 55:
1073 return 2;
1074 case 110:
1075 return 3;
1076 case 60:
1077 return 4;
1078 case 90:
1079 return 5;
1080 case 120:
1081 return 6;
1082 case 180:
1083 return 7;
1084 case 240:
1085 return 8;
1086 case 360:
1087 return 9;
1088 case 480:
1089 return 10;
1090 case 540:
1091 return 11;
1092 default:
1093 return 3;
1094
1095 }
1096}
1097static u16 rtl_rate[] = {10,20,55,110,60,90,120,180,240,360,480,540};
1098inline u16 rtl8192_rate2rate(short rate)
1099{
1100 if (rate >11) return 0;
1101 return rtl_rate[rate];
1102}
1103
1104
Justin P. Mattock589b3d02012-04-30 07:41:36 -07001105/* The prototype of rx_isr has changed since one version of Linux Kernel */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001106static void rtl8192_rx_isr(struct urb *urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001107{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001108 struct sk_buff *skb = (struct sk_buff *) urb->context;
1109 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
1110 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001111 struct r8192_priv *priv = ieee80211_priv(dev);
1112 int out_pipe = info->out_pipe;
1113 int err;
1114 if(!priv->up)
1115 return;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001116 if (unlikely(urb->status)) {
1117 info->urb = NULL;
1118 priv->stats.rxstaterr++;
1119 priv->ieee80211->stats.rx_errors++;
1120 usb_free_urb(urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001121 // printk("%s():rx status err\n",__FUNCTION__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001122 return;
1123 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001124 skb_unlink(skb, &priv->rx_queue);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001125 skb_put(skb, urb->actual_length);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001126
1127 skb_queue_tail(&priv->skb_queue, skb);
1128 tasklet_schedule(&priv->irq_rx_tasklet);
1129
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001130 skb = dev_alloc_skb(RX_URB_SIZE);
1131 if (unlikely(!skb)) {
1132 usb_free_urb(urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001133 printk("%s():can,t alloc skb\n",__FUNCTION__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001134 /* TODO check rx queue length and refill *somewhere* */
1135 return;
1136 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001137
1138 usb_fill_bulk_urb(urb, priv->udev,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001139 usb_rcvbulkpipe(priv->udev, out_pipe), skb_tail_pointer(skb),
Jerry Chuang8fc85982009-11-03 07:17:11 -02001140 RX_URB_SIZE, rtl8192_rx_isr, skb);
1141
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001142 info = (struct rtl8192_rx_info *) skb->cb;
1143 info->urb = urb;
1144 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001145 info->out_pipe = out_pipe;
1146
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001147 urb->transfer_buffer = skb_tail_pointer(skb);
1148 urb->context = skb;
1149 skb_queue_tail(&priv->rx_queue, skb);
1150 err = usb_submit_urb(urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001151 if(err && err != EPERM)
1152 printk("can not submit rxurb, err is %x,URB status is %x\n",err,urb->status);
1153}
1154
1155u32
1156rtl819xusb_rx_command_packet(
1157 struct net_device *dev,
1158 struct ieee80211_rx_stats *pstats
1159 )
1160{
1161 u32 status;
1162
1163 //RT_TRACE(COMP_RECV, DBG_TRACE, ("---> RxCommandPacketHandle819xUsb()\n"));
1164
1165 status = cmpk_message_handle_rx(dev, pstats);
1166 if (status)
1167 {
1168 DMESG("rxcommandpackethandle819xusb: It is a command packet\n");
1169 }
1170 else
1171 {
1172 //RT_TRACE(COMP_RECV, DBG_TRACE, ("RxCommandPacketHandle819xUsb: It is not a command packet\n"));
1173 }
1174
1175 //RT_TRACE(COMP_RECV, DBG_TRACE, ("<--- RxCommandPacketHandle819xUsb()\n"));
1176 return status;
1177}
1178
Jerry Chuang8fc85982009-11-03 07:17:11 -02001179
1180void rtl8192_data_hard_stop(struct net_device *dev)
1181{
1182 //FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001183}
1184
1185
1186void rtl8192_data_hard_resume(struct net_device *dev)
1187{
1188 // FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001189}
1190
1191/* this function TX data frames when the ieee80211 stack requires this.
1192 * It checks also if we need to stop the ieee tx queue, eventually do it
1193 */
1194void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
1195{
1196 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1197 int ret;
1198 unsigned long flags;
1199 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1200 u8 queue_index = tcb_desc->queue_index;
1201
1202 /* shall not be referred by command packet */
1203 assert(queue_index != TXCMD_QUEUE);
1204
1205 spin_lock_irqsave(&priv->tx_lock,flags);
1206
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001207 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001208// tcb_desc->RATRIndex = 7;
1209// tcb_desc->bTxDisableRateFallBack = 1;
1210// tcb_desc->bTxUseDriverAssingedRate = 1;
1211 tcb_desc->bTxEnableFwCalcDur = 1;
1212 skb_push(skb, priv->ieee80211->tx_headroom);
1213 ret = rtl8192_tx(dev, skb);
1214
1215 //priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom);
1216 //priv->ieee80211->stats.tx_packets++;
1217
1218 spin_unlock_irqrestore(&priv->tx_lock,flags);
1219
1220// return ret;
1221 return;
1222}
1223
1224/* This is a rough attempt to TX a frame
1225 * This is called by the ieee 80211 stack to TX management frames.
1226 * If the ring is full packet are dropped (for data frame the queue
1227 * is stopped before this can happen).
1228 */
1229int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
1230{
1231 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1232 int ret;
1233 unsigned long flags;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001234 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1235 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001236
1237
1238 spin_lock_irqsave(&priv->tx_lock,flags);
1239
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001240 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001241 if(queue_index == TXCMD_QUEUE) {
1242 skb_push(skb, USB_HWDESC_HEADER_LEN);
1243 rtl819xU_tx_cmd(dev, skb);
1244 ret = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001245 spin_unlock_irqrestore(&priv->tx_lock,flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001246 return ret;
1247 } else {
1248 skb_push(skb, priv->ieee80211->tx_headroom);
1249 ret = rtl8192_tx(dev, skb);
1250 }
1251
1252 spin_unlock_irqrestore(&priv->tx_lock,flags);
1253
1254 return ret;
1255}
1256
1257
1258void rtl8192_try_wake_queue(struct net_device *dev, int pri);
1259
1260#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1261u16 DrvAggr_PaddingAdd(struct net_device *dev, struct sk_buff *skb)
1262{
1263 u16 PaddingNum = 256 - ((skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES) % 256);
1264 return (PaddingNum&0xff);
1265}
1266
1267u8 MRateToHwRate8190Pci(u8 rate);
1268u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc);
1269u8 MapHwQueueToFirmwareQueue(u8 QueueID);
1270struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv_agg_txb *pSendList)
1271{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001272 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001273 struct r8192_priv *priv = ieee80211_priv(dev);
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001274 cb_desc *tcb_desc = NULL;
1275 u8 i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001276 u32 TotalLength;
1277 struct sk_buff *skb;
1278 struct sk_buff *agg_skb;
1279 tx_desc_819x_usb_aggr_subframe *tx_agg_desc = NULL;
1280 tx_fwinfo_819x_usb *tx_fwinfo = NULL;
1281
1282 //
1283 // Local variable initialization.
1284 //
1285 /* first skb initialization */
1286 skb = pSendList->tx_agg_frames[0];
1287 TotalLength = skb->len;
1288
1289 /* Get the total aggregation length including the padding space and
1290 * sub frame header.
1291 */
1292 for(i = 1; i < pSendList->nr_drv_agg_frames; i++) {
1293 TotalLength += DrvAggr_PaddingAdd(dev, skb);
1294 skb = pSendList->tx_agg_frames[i];
1295 TotalLength += (skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1296 }
1297
1298 /* allocate skb to contain the aggregated packets */
1299 agg_skb = dev_alloc_skb(TotalLength + ieee->tx_headroom);
1300 memset(agg_skb->data, 0, agg_skb->len);
1301 skb_reserve(agg_skb, ieee->tx_headroom);
1302
1303// RT_DEBUG_DATA(COMP_SEND, skb->cb, sizeof(skb->cb));
1304 /* reserve info for first subframe Tx descriptor to be set in the tx function */
1305 skb = pSendList->tx_agg_frames[0];
1306 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1307 tcb_desc->drv_agg_enable = 1;
1308 tcb_desc->pkt_size = skb->len;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001309 tcb_desc->DrvAggrNum = pSendList->nr_drv_agg_frames;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001310 printk("DrvAggNum = %d\n", tcb_desc->DrvAggrNum);
1311// RT_DEBUG_DATA(COMP_SEND, skb->cb, sizeof(skb->cb));
1312// printk("========>skb->data ======> \n");
1313// RT_DEBUG_DATA(COMP_SEND, skb->data, skb->len);
1314 memcpy(agg_skb->cb, skb->cb, sizeof(skb->cb));
1315 memcpy(skb_put(agg_skb,skb->len),skb->data,skb->len);
1316
1317 for(i = 1; i < pSendList->nr_drv_agg_frames; i++) {
1318 /* push the next sub frame to be 256 byte aline */
1319 skb_put(agg_skb,DrvAggr_PaddingAdd(dev,skb));
1320
1321 /* Subframe drv Tx descriptor and firmware info setting */
1322 skb = pSendList->tx_agg_frames[i];
1323 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1324 tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)agg_skb->tail;
1325 tx_fwinfo = (tx_fwinfo_819x_usb *)(agg_skb->tail + sizeof(tx_desc_819x_usb_aggr_subframe));
1326
1327 memset(tx_fwinfo,0,sizeof(tx_fwinfo_819x_usb));
1328 /* DWORD 0 */
1329 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0;
1330 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1331 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1332 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
1333 if(tcb_desc->bAMPDUEnable) {//AMPDU enabled
1334 tx_fwinfo->AllowAggregation = 1;
1335 /* DWORD 1 */
1336 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1337 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1338 } else {
1339 tx_fwinfo->AllowAggregation = 0;
1340 /* DWORD 1 */
1341 tx_fwinfo->RxMF = 0;
1342 tx_fwinfo->RxAMD = 0;
1343 }
1344
1345 /* Protection mode related */
1346 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0;
1347 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0;
1348 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0;
1349 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80)?1:0;
1350 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
1351 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT==0)?(tcb_desc->RTSSC):0;
1352 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT==1)?((tcb_desc->bRTSBW)?1:0):0;
1353 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):\
1354 (tcb_desc->bRTSUseShortGI?1:0);
1355
1356 /* Set Bandwidth and sub-channel settings. */
1357 if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
1358 {
1359 if(tcb_desc->bPacketBW) {
1360 tx_fwinfo->TxBandwidth = 1;
1361 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1362 } else {
1363 tx_fwinfo->TxBandwidth = 0;
1364 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1365 }
1366 } else {
1367 tx_fwinfo->TxBandwidth = 0;
1368 tx_fwinfo->TxSubCarrier = 0;
1369 }
1370
1371 /* Fill Tx descriptor */
1372 memset(tx_agg_desc, 0, sizeof(tx_desc_819x_usb_aggr_subframe));
1373 /* DWORD 0 */
1374 //tx_agg_desc->LINIP = 0;
1375 //tx_agg_desc->CmdInit = 1;
1376 tx_agg_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001377 /* already raw data, need not to subtract header length */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001378 tx_agg_desc->PktSize = skb->len & 0xffff;
1379
1380 /*DWORD 1*/
1381 tx_agg_desc->SecCAMID= 0;
1382 tx_agg_desc->RATid = tcb_desc->RATRIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001383 {
1384 //MPDUOverhead = 0;
1385 tx_agg_desc->NoEnc = 1;
1386 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001387 tx_agg_desc->SecType = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001388
1389 if (tcb_desc->bHwSec) {
1390 switch (priv->ieee80211->pairwise_key_type)
1391 {
1392 case KEY_TYPE_WEP40:
1393 case KEY_TYPE_WEP104:
1394 tx_agg_desc->SecType = 0x1;
1395 tx_agg_desc->NoEnc = 0;
1396 break;
1397 case KEY_TYPE_TKIP:
1398 tx_agg_desc->SecType = 0x2;
1399 tx_agg_desc->NoEnc = 0;
1400 break;
1401 case KEY_TYPE_CCMP:
1402 tx_agg_desc->SecType = 0x3;
1403 tx_agg_desc->NoEnc = 0;
1404 break;
1405 case KEY_TYPE_NA:
1406 tx_agg_desc->SecType = 0x0;
1407 tx_agg_desc->NoEnc = 1;
1408 break;
1409 }
1410 }
1411
1412 tx_agg_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1413 tx_agg_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1414
1415 tx_agg_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1416 tx_agg_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1417
1418 tx_agg_desc->OWN = 1;
1419
1420 //DWORD 2
1421 /* According windows driver, it seems that there no need to fill this field */
1422 //tx_agg_desc->TxBufferSize= (u32)(skb->len - USB_HWDESC_HEADER_LEN);
1423
1424 /* to fill next packet */
1425 skb_put(agg_skb,TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1426 memcpy(skb_put(agg_skb,skb->len),skb->data,skb->len);
1427 }
1428
1429 for(i = 0; i < pSendList->nr_drv_agg_frames; i++) {
1430 dev_kfree_skb_any(pSendList->tx_agg_frames[i]);
1431 }
1432
1433 return agg_skb;
1434}
1435
1436/* NOTE:
1437 This function return a list of PTCB which is proper to be aggregate with the input TCB.
1438 If no proper TCB is found to do aggregation, SendList will only contain the input TCB.
1439*/
1440u8 DrvAggr_GetAggregatibleList(struct net_device *dev, struct sk_buff *skb,
1441 struct ieee80211_drv_agg_txb *pSendList)
1442{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001443 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001444 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1445 u16 nMaxAggrNum = pHTInfo->UsbTxAggrNum;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001446 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001447 u8 QueueID = tcb_desc->queue_index;
1448
1449 do {
1450 pSendList->tx_agg_frames[pSendList->nr_drv_agg_frames++] = skb;
1451 if(pSendList->nr_drv_agg_frames >= nMaxAggrNum) {
1452 break;
1453 }
1454
1455 } while((skb = skb_dequeue(&ieee->skb_drv_aggQ[QueueID])));
1456
1457 RT_TRACE(COMP_AMSDU, "DrvAggr_GetAggregatibleList, nAggrTcbNum = %d \n", pSendList->nr_drv_agg_frames);
1458 return pSendList->nr_drv_agg_frames;
1459}
1460#endif
1461
Jerry Chuang8fc85982009-11-03 07:17:11 -02001462static void rtl8192_tx_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001463{
1464 struct sk_buff *skb = (struct sk_buff*)tx_urb->context;
1465 struct net_device *dev = NULL;
1466 struct r8192_priv *priv = NULL;
1467 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1468 u8 queue_index = tcb_desc->queue_index;
1469// bool bToSend0Byte;
1470// u16 BufLen = skb->len;
1471
1472 memcpy(&dev,(struct net_device*)(skb->cb),sizeof(struct net_device*));
1473 priv = ieee80211_priv(dev);
1474
1475 if(tcb_desc->queue_index != TXCMD_QUEUE) {
1476 if(tx_urb->status == 0) {
1477 dev->trans_start = jiffies;
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07001478 // Act as station mode, destination shall be unicast address.
Jerry Chuang8fc85982009-11-03 07:17:11 -02001479 //priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom);
1480 //priv->ieee80211->stats.tx_packets++;
1481 priv->stats.txoktotal++;
1482 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
1483 priv->stats.txbytesunicast += (skb->len - priv->ieee80211->tx_headroom);
1484 } else {
1485 priv->ieee80211->stats.tx_errors++;
1486 //priv->stats.txmanageerr++;
1487 /* TODO */
1488 }
1489 }
1490
1491 /* free skb and tx_urb */
1492 if(skb != NULL) {
1493 dev_kfree_skb_any(skb);
1494 usb_free_urb(tx_urb);
1495 atomic_dec(&priv->tx_pending[queue_index]);
1496 }
1497
Jerry Chuang8fc85982009-11-03 07:17:11 -02001498 {
1499 //
1500 // Handle HW Beacon:
Uwe Kleine-Königaf02b582010-10-26 21:57:53 +02001501 // We had transfer our beacon frame to host controller at this moment.
Jerry Chuang8fc85982009-11-03 07:17:11 -02001502 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02001503 //
1504 // Caution:
1505 // Handling the wait queue of command packets.
1506 // For Tx command packets, we must not do TCB fragment because it is not handled right now.
1507 // We must cut the packets to match the size of TX_CMD_PKT before we send it.
1508 //
1509
1510 /* Handle MPDU in wait queue. */
1511 if(queue_index != BEACON_QUEUE) {
1512 /* Don't send data frame during scanning.*/
1513 if((skb_queue_len(&priv->ieee80211->skb_waitQ[queue_index]) != 0)&&\
1514 (!(priv->ieee80211->queue_stop))) {
1515 if(NULL != (skb = skb_dequeue(&(priv->ieee80211->skb_waitQ[queue_index]))))
1516 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1517
1518 return; //modified by david to avoid further processing AMSDU
1519 }
1520#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1521 else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index])!= 0)&&\
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001522 (!(priv->ieee80211->queue_stop))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001523 // Tx Driver Aggregation process
Justin P. Mattock589b3d02012-04-30 07:41:36 -07001524 /* The driver will aggregation the packets according to the following stats
Jerry Chuang8fc85982009-11-03 07:17:11 -02001525 * 1. check whether there's tx irq available, for it's a completion return
1526 * function, it should contain enough tx irq;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07001527 * 2. check packet type;
Uwe Kleine-König9b0131c2010-09-01 15:40:25 +02001528 * 3. initialize sendlist, check whether the to-be send packet no greater than 1
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07001529 * 4. aggregates the packets, and fill firmware info and tx desc into it, etc.
1530 * 5. check whether the packet could be sent, otherwise just insert into wait head
Jerry Chuang8fc85982009-11-03 07:17:11 -02001531 * */
1532 skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]);
1533 if(!check_nic_enough_desc(dev, queue_index)) {
1534 skb_queue_head(&(priv->ieee80211->skb_drv_aggQ[queue_index]), skb);
1535 return;
1536 }
1537
1538 {
1539 /*TODO*/
1540 /*
1541 u8* pHeader = skb->data;
1542
1543 if(IsMgntQosData(pHeader) ||
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001544 IsMgntQData_Ack(pHeader) ||
Jerry Chuang8fc85982009-11-03 07:17:11 -02001545 IsMgntQData_Poll(pHeader) ||
1546 IsMgntQData_Poll_Ack(pHeader)
1547 )
1548 */
1549 {
1550 struct ieee80211_drv_agg_txb SendList;
1551
1552 memset(&SendList, 0, sizeof(struct ieee80211_drv_agg_txb));
1553 if(DrvAggr_GetAggregatibleList(dev, skb, &SendList) > 1) {
1554 skb = DrvAggr_Aggregation(dev, &SendList);
1555
Jerry Chuang8fc85982009-11-03 07:17:11 -02001556 }
1557 }
1558 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1559 }
1560 }
1561#endif
1562 }
1563 }
1564
Jerry Chuang8fc85982009-11-03 07:17:11 -02001565}
1566
1567void rtl8192_beacon_stop(struct net_device *dev)
1568{
1569 u8 msr, msrm, msr2;
1570 struct r8192_priv *priv = ieee80211_priv(dev);
1571
1572 msr = read_nic_byte(dev, MSR);
1573 msrm = msr & MSR_LINK_MASK;
1574 msr2 = msr & ~MSR_LINK_MASK;
1575
1576 if(NIC_8192U == priv->card_8192) {
1577 usb_kill_urb(priv->rx_urb[MAX_RX_URB]);
1578 }
1579 if ((msrm == (MSR_LINK_ADHOC<<MSR_LINK_SHIFT) ||
1580 (msrm == (MSR_LINK_MASTER<<MSR_LINK_SHIFT)))){
1581 write_nic_byte(dev, MSR, msr2 | MSR_LINK_NONE);
1582 write_nic_byte(dev, MSR, msr);
1583 }
1584}
1585
1586void rtl8192_config_rate(struct net_device* dev, u16* rate_config)
1587{
1588 struct r8192_priv *priv = ieee80211_priv(dev);
1589 struct ieee80211_network *net;
1590 u8 i=0, basic_rate = 0;
1591 net = & priv->ieee80211->current_network;
1592
1593 for (i=0; i<net->rates_len; i++)
1594 {
1595 basic_rate = net->rates[i]&0x7f;
1596 switch(basic_rate)
1597 {
1598 case MGN_1M: *rate_config |= RRSR_1M; break;
1599 case MGN_2M: *rate_config |= RRSR_2M; break;
1600 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1601 case MGN_11M: *rate_config |= RRSR_11M; break;
1602 case MGN_6M: *rate_config |= RRSR_6M; break;
1603 case MGN_9M: *rate_config |= RRSR_9M; break;
1604 case MGN_12M: *rate_config |= RRSR_12M; break;
1605 case MGN_18M: *rate_config |= RRSR_18M; break;
1606 case MGN_24M: *rate_config |= RRSR_24M; break;
1607 case MGN_36M: *rate_config |= RRSR_36M; break;
1608 case MGN_48M: *rate_config |= RRSR_48M; break;
1609 case MGN_54M: *rate_config |= RRSR_54M; break;
1610 }
1611 }
1612 for (i=0; i<net->rates_ex_len; i++)
1613 {
1614 basic_rate = net->rates_ex[i]&0x7f;
1615 switch(basic_rate)
1616 {
1617 case MGN_1M: *rate_config |= RRSR_1M; break;
1618 case MGN_2M: *rate_config |= RRSR_2M; break;
1619 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1620 case MGN_11M: *rate_config |= RRSR_11M; break;
1621 case MGN_6M: *rate_config |= RRSR_6M; break;
1622 case MGN_9M: *rate_config |= RRSR_9M; break;
1623 case MGN_12M: *rate_config |= RRSR_12M; break;
1624 case MGN_18M: *rate_config |= RRSR_18M; break;
1625 case MGN_24M: *rate_config |= RRSR_24M; break;
1626 case MGN_36M: *rate_config |= RRSR_36M; break;
1627 case MGN_48M: *rate_config |= RRSR_48M; break;
1628 case MGN_54M: *rate_config |= RRSR_54M; break;
1629 }
1630 }
1631}
1632
1633
1634#define SHORT_SLOT_TIME 9
1635#define NON_SHORT_SLOT_TIME 20
1636
1637void rtl8192_update_cap(struct net_device* dev, u16 cap)
1638{
1639 u32 tmp = 0;
1640 struct r8192_priv *priv = ieee80211_priv(dev);
1641 struct ieee80211_network *net = &priv->ieee80211->current_network;
1642 priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
1643 tmp = priv->basic_rate;
1644 if (priv->short_preamble)
1645 tmp |= BRSR_AckShortPmb;
1646 write_nic_dword(dev, RRSR, tmp);
1647
1648 if (net->mode & (IEEE_G|IEEE_N_24G))
1649 {
1650 u8 slot_time = 0;
1651 if ((cap & WLAN_CAPABILITY_SHORT_SLOT)&&(!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime))
1652 {//short slot time
1653 slot_time = SHORT_SLOT_TIME;
1654 }
1655 else //long slot time
1656 slot_time = NON_SHORT_SLOT_TIME;
1657 priv->slot_time = slot_time;
1658 write_nic_byte(dev, SLOT_TIME, slot_time);
1659 }
1660
1661}
1662void rtl8192_net_update(struct net_device *dev)
1663{
1664
1665 struct r8192_priv *priv = ieee80211_priv(dev);
1666 struct ieee80211_network *net;
1667 u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
1668 u16 rate_config = 0;
1669 net = & priv->ieee80211->current_network;
1670
1671 rtl8192_config_rate(dev, &rate_config);
1672 priv->basic_rate = rate_config &= 0x15f;
1673
1674 write_nic_dword(dev,BSSIDR,((u32*)net->bssid)[0]);
1675 write_nic_word(dev,BSSIDR+4,((u16*)net->bssid)[2]);
1676 //for(i=0;i<ETH_ALEN;i++)
1677 // write_nic_byte(dev,BSSID+i,net->bssid[i]);
1678
1679 rtl8192_update_msr(dev);
1680// rtl8192_update_cap(dev, net->capability);
1681 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
1682 {
1683 write_nic_word(dev, ATIMWND, 2);
1684 write_nic_word(dev, BCN_DMATIME, 1023);
1685 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
1686// write_nic_word(dev, BcnIntTime, 100);
1687 write_nic_word(dev, BCN_DRV_EARLY_INT, 1);
1688 write_nic_byte(dev, BCN_ERR_THRESH, 100);
1689 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
1690 // TODO: BcnIFS may required to be changed on ASIC
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001691 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001692
1693 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
1694 }
1695
1696
1697
1698}
1699
1700//temporary hw beacon is not used any more.
1701//open it when necessary
Jerry Chuang8fc85982009-11-03 07:17:11 -02001702void rtl819xusb_beacon_tx(struct net_device *dev,u16 tx_rate)
1703{
1704
Jerry Chuang8fc85982009-11-03 07:17:11 -02001705}
Jerry Chuang8fc85982009-11-03 07:17:11 -02001706inline u8 rtl8192_IsWirelessBMode(u16 rate)
1707{
1708 if( ((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220) )
1709 return 1;
1710 else return 0;
1711}
1712
1713u16 N_DBPSOfRate(u16 DataRate);
1714
1715u16 ComputeTxTime(
1716 u16 FrameLength,
1717 u16 DataRate,
1718 u8 bManagementFrame,
1719 u8 bShortPreamble
1720)
1721{
1722 u16 FrameTime;
1723 u16 N_DBPS;
1724 u16 Ceiling;
1725
1726 if( rtl8192_IsWirelessBMode(DataRate) )
1727 {
1728 if( bManagementFrame || !bShortPreamble || DataRate == 10 )
1729 { // long preamble
1730 FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
1731 }
1732 else
1733 { // Short preamble
1734 FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
1735 }
1736 if( ( FrameLength*8 % (DataRate/10) ) != 0 ) //Get the Ceilling
1737 FrameTime ++;
1738 } else { //802.11g DSSS-OFDM PLCP length field calculation.
1739 N_DBPS = N_DBPSOfRate(DataRate);
1740 Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
1741 + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
1742 FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
1743 }
1744 return FrameTime;
1745}
1746
1747u16 N_DBPSOfRate(u16 DataRate)
1748{
1749 u16 N_DBPS = 24;
1750
1751 switch(DataRate)
1752 {
1753 case 60:
1754 N_DBPS = 24;
1755 break;
1756
1757 case 90:
1758 N_DBPS = 36;
1759 break;
1760
1761 case 120:
1762 N_DBPS = 48;
1763 break;
1764
1765 case 180:
1766 N_DBPS = 72;
1767 break;
1768
1769 case 240:
1770 N_DBPS = 96;
1771 break;
1772
1773 case 360:
1774 N_DBPS = 144;
1775 break;
1776
1777 case 480:
1778 N_DBPS = 192;
1779 break;
1780
1781 case 540:
1782 N_DBPS = 216;
1783 break;
1784
1785 default:
1786 break;
1787 }
1788
1789 return N_DBPS;
1790}
1791
1792void rtl819xU_cmd_isr(struct urb *tx_cmd_urb, struct pt_regs *regs)
1793{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001794 usb_free_urb(tx_cmd_urb);
1795}
1796
1797unsigned int txqueue2outpipe(struct r8192_priv* priv,unsigned int tx_queue) {
1798
1799 if(tx_queue >= 9)
1800 {
1801 RT_TRACE(COMP_ERR,"%s():Unknown queue ID!!!\n",__FUNCTION__);
1802 return 0x04;
1803 }
1804 return priv->txqueue_to_outpipemap[tx_queue];
1805}
1806
1807short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
1808{
1809 struct r8192_priv *priv = ieee80211_priv(dev);
1810 //u8 *tx;
1811 int status;
1812 struct urb *tx_urb;
1813 //int urb_buf_len;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001814 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001815 tx_desc_cmd_819x_usb *pdesc = (tx_desc_cmd_819x_usb *)skb->data;
1816 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1817 u8 queue_index = tcb_desc->queue_index;
1818
1819 //printk("\n %s::queue_index = %d\n",__FUNCTION__, queue_index);
1820 atomic_inc(&priv->tx_pending[queue_index]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001821 tx_urb = usb_alloc_urb(0,GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001822 if(!tx_urb){
1823 dev_kfree_skb(skb);
1824 return -ENOMEM;
1825 }
1826
1827 memset(pdesc, 0, USB_HWDESC_HEADER_LEN);
1828 /* Tx descriptor ought to be set according to the skb->cb */
1829 pdesc->FirstSeg = 1;//bFirstSeg;
1830 pdesc->LastSeg = 1;//bLastSeg;
1831 pdesc->CmdInit = tcb_desc->bCmdOrInit;
1832 pdesc->TxBufferSize = tcb_desc->txbuf_size;
1833 pdesc->OWN = 1;
1834 pdesc->LINIP = tcb_desc->bLastIniPkt;
1835
1836 //----------------------------------------------------------------------------
1837 // Fill up USB_OUT_CONTEXT.
1838 //----------------------------------------------------------------------------
1839 // Get index to out pipe from specified QueueID.
1840#ifndef USE_ONE_PIPE
1841 idx_pipe = txqueue2outpipe(priv,queue_index);
1842#else
1843 idx_pipe = 0x04;
1844#endif
1845#ifdef JOHN_DUMP_TXDESC
1846 int i;
1847 printk("<Tx descriptor>--rate %x---",rate);
1848 for (i = 0; i < 8; i++)
1849 printk("%8x ", tx[i]);
1850 printk("\n");
1851#endif
1852 usb_fill_bulk_urb(tx_urb,priv->udev, usb_sndbulkpipe(priv->udev,idx_pipe), \
1853 skb->data, skb->len, rtl8192_tx_isr, skb);
1854
Jerry Chuang8fc85982009-11-03 07:17:11 -02001855 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001856
1857 if (!status){
1858 return 0;
1859 }else{
1860 DMESGE("Error TX CMD URB, error %d",
1861 status);
1862 return -1;
1863 }
1864}
1865
1866/*
1867 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1868 * in TxFwInfo data structure
1869 * 2006.10.30 by Emily
1870 *
1871 * \param QUEUEID Software Queue
1872*/
1873u8 MapHwQueueToFirmwareQueue(u8 QueueID)
1874{
1875 u8 QueueSelect = 0x0; //defualt set to
1876
1877 switch(QueueID) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001878 case BE_QUEUE:
1879 QueueSelect = QSLT_BE; //or QSelect = pTcb->priority;
1880 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001881
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001882 case BK_QUEUE:
1883 QueueSelect = QSLT_BK; //or QSelect = pTcb->priority;
1884 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001885
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001886 case VO_QUEUE:
1887 QueueSelect = QSLT_VO; //or QSelect = pTcb->priority;
1888 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001889
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001890 case VI_QUEUE:
1891 QueueSelect = QSLT_VI; //or QSelect = pTcb->priority;
1892 break;
1893 case MGNT_QUEUE:
1894 QueueSelect = QSLT_MGNT;
1895 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001896
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001897 case BEACON_QUEUE:
1898 QueueSelect = QSLT_BEACON;
1899 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001900
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001901 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
1902 // TODO: Remove Assertions
Jerry Chuang8fc85982009-11-03 07:17:11 -02001903//#if (RTL819X_FPGA_VER & RTL819X_FPGA_GUANGAN_070502)
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001904 case TXCMD_QUEUE:
1905 QueueSelect = QSLT_CMD;
1906 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001907//#endif
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001908 case HIGH_QUEUE:
1909 QueueSelect = QSLT_HIGH;
1910 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001911
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001912 default:
1913 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
1914 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001915 }
1916 return QueueSelect;
1917}
1918
1919u8 MRateToHwRate8190Pci(u8 rate)
1920{
1921 u8 ret = DESC90_RATE1M;
1922
1923 switch(rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001924 case MGN_1M: ret = DESC90_RATE1M; break;
1925 case MGN_2M: ret = DESC90_RATE2M; break;
1926 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1927 case MGN_11M: ret = DESC90_RATE11M; break;
1928 case MGN_6M: ret = DESC90_RATE6M; break;
1929 case MGN_9M: ret = DESC90_RATE9M; break;
1930 case MGN_12M: ret = DESC90_RATE12M; break;
1931 case MGN_18M: ret = DESC90_RATE18M; break;
1932 case MGN_24M: ret = DESC90_RATE24M; break;
1933 case MGN_36M: ret = DESC90_RATE36M; break;
1934 case MGN_48M: ret = DESC90_RATE48M; break;
1935 case MGN_54M: ret = DESC90_RATE54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001936
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001937 // HT rate since here
1938 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1939 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1940 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1941 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1942 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1943 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1944 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1945 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1946 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1947 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1948 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1949 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1950 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1951 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1952 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1953 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1954 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001955
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001956 default: break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001957 }
1958 return ret;
1959}
1960
1961
1962u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
1963{
1964 u8 tmp_Short;
1965
1966 tmp_Short = (TxHT==1)?((tcb_desc->bUseShortGI)?1:0):((tcb_desc->bUseShortPreamble)?1:0);
1967
1968 if(TxHT==1 && TxRate != DESC90_RATEMCS15)
1969 tmp_Short = 0;
1970
1971 return tmp_Short;
1972}
1973
Jerry Chuang8fc85982009-11-03 07:17:11 -02001974static void tx_zero_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001975{
1976 return;
1977}
1978
1979/*
1980 * The tx procedure is just as following,
1981 * skb->cb will contain all the following information,
1982 * priority, morefrag, rate, &dev.
1983 * */
1984short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
1985{
1986 struct r8192_priv *priv = ieee80211_priv(dev);
1987 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1988 tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data;
1989 tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
1990 struct usb_device *udev = priv->udev;
1991 int pend;
1992 int status;
1993 struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
1994 //int urb_len;
1995 unsigned int idx_pipe;
1996// RT_DEBUG_DATA(COMP_SEND, tcb_desc, sizeof(cb_desc));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001997// printk("=============> %s\n", __FUNCTION__);
1998 pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]);
1999 /* we are locked here so the two atomic_read and inc are executed
2000 * without interleaves
2001 * !!! For debug purpose
2002 */
2003 if( pend > MAX_TX_URB){
Jerry Chuang8fc85982009-11-03 07:17:11 -02002004 printk("To discard skb packet!\n");
2005 dev_kfree_skb_any(skb);
2006 return -1;
2007 }
2008
Jerry Chuang8fc85982009-11-03 07:17:11 -02002009 tx_urb = usb_alloc_urb(0,GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002010 if(!tx_urb){
2011 dev_kfree_skb_any(skb);
2012 return -ENOMEM;
2013 }
2014
2015 /* Fill Tx firmware info */
2016 memset(tx_fwinfo,0,sizeof(tx_fwinfo_819x_usb));
2017 /* DWORD 0 */
2018 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0;
2019 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
2020 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
2021 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
2022 if(tcb_desc->bAMPDUEnable) {//AMPDU enabled
2023 tx_fwinfo->AllowAggregation = 1;
2024 /* DWORD 1 */
2025 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
2026 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
2027 } else {
2028 tx_fwinfo->AllowAggregation = 0;
2029 /* DWORD 1 */
2030 tx_fwinfo->RxMF = 0;
2031 tx_fwinfo->RxAMD = 0;
2032 }
2033
2034 /* Protection mode related */
2035 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0;
2036 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0;
2037 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0;
2038 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80)?1:0;
2039 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
2040 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT==0)?(tcb_desc->RTSSC):0;
2041 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT==1)?((tcb_desc->bRTSBW)?1:0):0;
2042 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):\
2043 (tcb_desc->bRTSUseShortGI?1:0);
2044
2045 /* Set Bandwidth and sub-channel settings. */
2046 if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
2047 {
2048 if(tcb_desc->bPacketBW) {
2049 tx_fwinfo->TxBandwidth = 1;
2050 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
2051 } else {
2052 tx_fwinfo->TxBandwidth = 0;
2053 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
2054 }
2055 } else {
2056 tx_fwinfo->TxBandwidth = 0;
2057 tx_fwinfo->TxSubCarrier = 0;
2058 }
2059
2060#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2061 if (tcb_desc->drv_agg_enable)
2062 {
2063 tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1;
2064 }
2065#endif
2066 /* Fill Tx descriptor */
2067 memset(tx_desc, 0, sizeof(tx_desc_819x_usb));
2068 /* DWORD 0 */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002069 tx_desc->LINIP = 0;
2070 tx_desc->CmdInit = 1;
2071 tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002072
2073#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2074 if (tcb_desc->drv_agg_enable) {
2075 tx_desc->PktSize = tcb_desc->pkt_size;
2076 } else
2077#endif
2078 {
2079 tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff;
2080 }
2081
2082 /*DWORD 1*/
2083 tx_desc->SecCAMID= 0;
2084 tx_desc->RATid = tcb_desc->RATRIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002085 {
2086 //MPDUOverhead = 0;
2087 tx_desc->NoEnc = 1;
2088 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002089 tx_desc->SecType = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002090 if (tcb_desc->bHwSec)
2091 {
2092 switch (priv->ieee80211->pairwise_key_type)
2093 {
2094 case KEY_TYPE_WEP40:
2095 case KEY_TYPE_WEP104:
2096 tx_desc->SecType = 0x1;
2097 tx_desc->NoEnc = 0;
2098 break;
2099 case KEY_TYPE_TKIP:
2100 tx_desc->SecType = 0x2;
2101 tx_desc->NoEnc = 0;
2102 break;
2103 case KEY_TYPE_CCMP:
2104 tx_desc->SecType = 0x3;
2105 tx_desc->NoEnc = 0;
2106 break;
2107 case KEY_TYPE_NA:
2108 tx_desc->SecType = 0x0;
2109 tx_desc->NoEnc = 1;
2110 break;
2111 }
2112 }
2113
2114 tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
2115 tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
2116
2117 tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
2118 tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
2119
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002120 /* Fill fields that are required to be initialized in all of the descriptors */
2121 //DWORD 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002122 tx_desc->FirstSeg = 1;
2123 tx_desc->LastSeg = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002124 tx_desc->OWN = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002125
2126#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2127 if (tcb_desc->drv_agg_enable) {
2128 tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb);
2129 } else
2130#endif
2131 {
2132 //DWORD 2
2133 tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN);
2134 }
2135 /* Get index to out pipe from specified QueueID */
2136#ifndef USE_ONE_PIPE
2137 idx_pipe = txqueue2outpipe(priv,tcb_desc->queue_index);
2138#else
2139 idx_pipe = 0x5;
2140#endif
2141
2142 //RT_DEBUG_DATA(COMP_SEND,tx_fwinfo,sizeof(tx_fwinfo_819x_usb));
2143 //RT_DEBUG_DATA(COMP_SEND,tx_desc,sizeof(tx_desc_819x_usb));
2144
2145 /* To submit bulk urb */
2146 usb_fill_bulk_urb(tx_urb,udev,
2147 usb_sndbulkpipe(udev,idx_pipe), skb->data,
2148 skb->len, rtl8192_tx_isr, skb);
2149
Jerry Chuang8fc85982009-11-03 07:17:11 -02002150 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002151 if (!status){
2152//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
2153 bool bSend0Byte = false;
2154 u8 zero = 0;
2155 if(udev->speed == USB_SPEED_HIGH)
2156 {
2157 if (skb->len > 0 && skb->len % 512 == 0)
2158 bSend0Byte = true;
2159 }
2160 else
2161 {
2162 if (skb->len > 0 && skb->len % 64 == 0)
2163 bSend0Byte = true;
2164 }
2165 if (bSend0Byte)
2166 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002167 tx_urb_zero = usb_alloc_urb(0,GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002168 if(!tx_urb_zero){
2169 RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
2170 return -ENOMEM;
2171 }
2172 usb_fill_bulk_urb(tx_urb_zero,udev,
2173 usb_sndbulkpipe(udev,idx_pipe), &zero,
2174 0, tx_zero_isr, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002175 status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002176 if (status){
2177 RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
2178 return -1;
2179 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002180 }
2181 dev->trans_start = jiffies;
2182 atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
2183 return 0;
2184 }else{
2185 RT_TRACE(COMP_ERR, "Error TX URB %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]),
2186 status);
2187 return -1;
2188 }
2189}
2190
2191short rtl8192_usb_initendpoints(struct net_device *dev)
2192{
2193 struct r8192_priv *priv = ieee80211_priv(dev);
2194
Julia Lawall32414872010-05-11 20:26:57 +02002195 priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB+1),
2196 GFP_KERNEL);
David Chosrovab8345172010-12-01 13:42:16 +01002197 if (priv->rx_urb == NULL)
2198 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002199
2200#ifndef JACKSON_NEW_RX
2201 for(i=0;i<(MAX_RX_URB+1);i++){
2202
Jerry Chuang8fc85982009-11-03 07:17:11 -02002203 priv->rx_urb[i] = usb_alloc_urb(0,GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002204
2205 priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL);
2206
2207 priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE;
2208 }
2209#endif
2210
2211#ifdef THOMAS_BEACON
2212{
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002213 long align = 0;
2214 void *oldaddr, *newaddr;
2215
Jerry Chuang8fc85982009-11-03 07:17:11 -02002216 priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002217 priv->oldaddr = kmalloc(16, GFP_KERNEL);
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002218 oldaddr = priv->oldaddr;
2219 align = ((long)oldaddr) & 3;
2220 if (align) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002221 newaddr = oldaddr + 4 - align;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002222 priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align;
2223 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002224 newaddr = oldaddr;
2225 priv->rx_urb[16]->transfer_buffer_length = 16;
2226 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02002227 priv->rx_urb[16]->transfer_buffer = newaddr;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002228}
2229#endif
2230
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002231 memset(priv->rx_urb, 0, sizeof(struct urb*) * MAX_RX_URB);
Julia Lawall7a6cb0d2010-05-13 22:00:05 +02002232 priv->pp_rxskb = kcalloc(MAX_RX_URB, sizeof(struct sk_buff *),
Julia Lawall32414872010-05-11 20:26:57 +02002233 GFP_KERNEL);
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02002234 if (!priv->pp_rxskb) {
2235 kfree(priv->rx_urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002236
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02002237 priv->pp_rxskb = NULL;
2238 priv->rx_urb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002239
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02002240 DMESGE("Endpoint Alloc Failure");
2241 return -ENOMEM;
2242 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002243
2244 printk("End of initendpoints\n");
2245 return 0;
2246
2247}
2248#ifdef THOMAS_BEACON
2249void rtl8192_usb_deleteendpoints(struct net_device *dev)
2250{
2251 int i;
2252 struct r8192_priv *priv = ieee80211_priv(dev);
2253
2254 if(priv->rx_urb){
2255 for(i=0;i<(MAX_RX_URB+1);i++){
2256 usb_kill_urb(priv->rx_urb[i]);
2257 usb_free_urb(priv->rx_urb[i]);
2258 }
2259 kfree(priv->rx_urb);
2260 priv->rx_urb = NULL;
2261 }
Ilia Mirkine72714f2011-03-13 00:29:07 -05002262 kfree(priv->oldaddr);
2263 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002264 if (priv->pp_rxskb) {
2265 kfree(priv->pp_rxskb);
2266 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002267 }
2268}
2269#else
2270void rtl8192_usb_deleteendpoints(struct net_device *dev)
2271{
2272 int i;
2273 struct r8192_priv *priv = ieee80211_priv(dev);
2274
2275#ifndef JACKSON_NEW_RX
2276
2277 if(priv->rx_urb){
2278 for(i=0;i<(MAX_RX_URB+1);i++){
2279 usb_kill_urb(priv->rx_urb[i]);
2280 kfree(priv->rx_urb[i]->transfer_buffer);
2281 usb_free_urb(priv->rx_urb[i]);
2282 }
2283 kfree(priv->rx_urb);
2284 priv->rx_urb = NULL;
2285
2286 }
2287#else
Ilia Mirkine72714f2011-03-13 00:29:07 -05002288 kfree(priv->rx_urb);
2289 priv->rx_urb = NULL;
2290 kfree(priv->oldaddr);
2291 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002292 if (priv->pp_rxskb) {
2293 kfree(priv->pp_rxskb);
2294 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002295
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002296 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002297
2298#endif
2299}
2300#endif
2301
Jerry Chuang8fc85982009-11-03 07:17:11 -02002302extern void rtl8192_update_ratr_table(struct net_device* dev);
2303void rtl8192_link_change(struct net_device *dev)
2304{
2305// int i;
2306
2307 struct r8192_priv *priv = ieee80211_priv(dev);
2308 struct ieee80211_device* ieee = priv->ieee80211;
2309 //write_nic_word(dev, BCN_INTR_ITV, net->beacon_interval);
2310 if (ieee->state == IEEE80211_LINKED)
2311 {
2312 rtl8192_net_update(dev);
2313 rtl8192_update_ratr_table(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002314 //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
2315 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
2316 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002317 }
2318 /*update timing params*/
2319// RT_TRACE(COMP_CH, "========>%s(), chan:%d\n", __FUNCTION__, priv->chan);
2320// rtl8192_set_chan(dev, priv->chan);
2321 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002322 {
2323 u32 reg = 0;
2324 reg = read_nic_dword(dev, RCR);
2325 if (priv->ieee80211->state == IEEE80211_LINKED)
2326 priv->ReceiveConfig = reg |= RCR_CBSSID;
2327 else
2328 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
2329 write_nic_dword(dev, RCR, reg);
2330 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002331
2332// rtl8192_set_rxconf(dev);
2333}
2334
2335static struct ieee80211_qos_parameters def_qos_parameters = {
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002336 {3,3,3,3},/* cw_min */
2337 {7,7,7,7},/* cw_max */
2338 {2,2,2,2},/* aifs */
2339 {0,0,0,0},/* flags */
2340 {0,0,0,0} /* tx_op_limit */
Jerry Chuang8fc85982009-11-03 07:17:11 -02002341};
2342
2343
Jerry Chuang8fc85982009-11-03 07:17:11 -02002344void rtl8192_update_beacon(struct work_struct * work)
2345{
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002346 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
2347 struct net_device *dev = priv->ieee80211->dev;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002348 struct ieee80211_device* ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002349 struct ieee80211_network* net = &ieee->current_network;
2350
2351 if (ieee->pHTInfo->bCurrentHTSupport)
2352 HTUpdateSelfAndPeerSetting(ieee, net);
2353 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
2354 rtl8192_update_cap(dev, net->capability);
2355}
2356/*
2357* background support to run QoS activate functionality
2358*/
2359int WDCAPARA_ADD[] = {EDCAPARA_BE,EDCAPARA_BK,EDCAPARA_VI,EDCAPARA_VO};
Jerry Chuang8fc85982009-11-03 07:17:11 -02002360void rtl8192_qos_activate(struct work_struct * work)
2361{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002362 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
2363 struct net_device *dev = priv->ieee80211->dev;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002364 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2365 u8 mode = priv->ieee80211->current_network.mode;
2366 //u32 size = sizeof(struct ieee80211_qos_parameters);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002367 u8 u1bAIFS;
2368 u32 u4bAcParam;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002369 int i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002370
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002371 if (priv == NULL)
2372 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002373
Jerry Chuang8fc85982009-11-03 07:17:11 -02002374 mutex_lock(&priv->mutex);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002375 if(priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002376 goto success;
2377 RT_TRACE(COMP_QOS,"qos active process with associate response received\n");
2378 /* It better set slot time at first */
2379 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2380 /* update the ac parameter to related registers */
2381 for(i = 0; i < QOS_QUEUE_NUM; i++) {
2382 //Mode G/A: slotTimeTimer = 9; Mode B: 20
2383 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime;
2384 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
2385 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2386 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2387 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
2388
2389 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
2390 //write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
2391 }
2392
2393success:
Jerry Chuang8fc85982009-11-03 07:17:11 -02002394 mutex_unlock(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002395}
2396
2397static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
2398 int active_network,
2399 struct ieee80211_network *network)
2400{
2401 int ret = 0;
2402 u32 size = sizeof(struct ieee80211_qos_parameters);
2403
2404 if(priv->ieee80211->state !=IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002405 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002406
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002407 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2408 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002409
2410 if (network->flags & NETWORK_HAS_QOS_MASK) {
2411 if (active_network &&
2412 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
2413 network->qos_data.active = network->qos_data.supported;
2414
2415 if ((network->qos_data.active == 1) && (active_network == 1) &&
2416 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2417 (network->qos_data.old_param_count !=
2418 network->qos_data.param_count)) {
2419 network->qos_data.old_param_count =
2420 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002421 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002422 RT_TRACE (COMP_QOS, "QoS parameters change call "
2423 "qos_activate\n");
2424 }
2425 } else {
2426 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2427 &def_qos_parameters, size);
2428
2429 if ((network->qos_data.active == 1) && (active_network == 1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002430 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002431 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2432 }
2433 network->qos_data.active = 0;
2434 network->qos_data.supported = 0;
2435 }
2436
2437 return 0;
2438}
2439
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002440/* handle and manage frame from beacon and probe response */
Jerry Chuang8fc85982009-11-03 07:17:11 -02002441static int rtl8192_handle_beacon(struct net_device * dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002442 struct ieee80211_beacon * beacon,
2443 struct ieee80211_network * network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002444{
2445 struct r8192_priv *priv = ieee80211_priv(dev);
2446
2447 rtl8192_qos_handle_probe_response(priv,1,network);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002448 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002449 return 0;
2450
2451}
2452
2453/*
2454* handling the beaconing responses. if we get different QoS setting
2455* off the network from the associated setting, adjust the QoS
2456* setting
2457*/
2458static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002459 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002460{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002461 int ret = 0;
2462 unsigned long flags;
2463 u32 size = sizeof(struct ieee80211_qos_parameters);
2464 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002465
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002466 if ((priv == NULL) || (network == NULL))
2467 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002468
2469 if(priv->ieee80211->state !=IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002470 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002471
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002472 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2473 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002474
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002475 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002476 if(network->flags & NETWORK_HAS_QOS_PARAMETERS) {
2477 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2478 &network->qos_data.parameters,\
2479 sizeof(struct ieee80211_qos_parameters));
2480 priv->ieee80211->current_network.qos_data.active = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002481 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002482 set_qos_param = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002483 /* update qos parameter for current network */
2484 priv->ieee80211->current_network.qos_data.old_param_count = \
2485 priv->ieee80211->current_network.qos_data.param_count;
2486 priv->ieee80211->current_network.qos_data.param_count = \
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002487 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002488 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002489 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002490 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2491 &def_qos_parameters, size);
2492 priv->ieee80211->current_network.qos_data.active = 0;
2493 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002494 set_qos_param = 1;
2495 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002496
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002497 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002498
2499 RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n",__FUNCTION__,network->flags ,priv->ieee80211->current_network.qos_data.active);
2500 if (set_qos_param == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002501 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002502
2503
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002504 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002505}
2506
2507
2508static int rtl8192_handle_assoc_response(struct net_device *dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002509 struct ieee80211_assoc_response_frame *resp,
2510 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002511{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002512 struct r8192_priv *priv = ieee80211_priv(dev);
2513 rtl8192_qos_association_resp(priv, network);
2514 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002515}
2516
2517
2518void rtl8192_update_ratr_table(struct net_device* dev)
2519 // POCTET_STRING posLegacyRate,
2520 // u8* pMcsRate)
2521 // PRT_WLAN_STA pEntry)
2522{
2523 struct r8192_priv* priv = ieee80211_priv(dev);
2524 struct ieee80211_device* ieee = priv->ieee80211;
2525 u8* pMcsRate = ieee->dot11HTOperationalRateSet;
2526 //struct ieee80211_network *net = &ieee->current_network;
2527 u32 ratr_value = 0;
2528 u8 rate_index = 0;
2529 rtl8192_config_rate(dev, (u16*)(&ratr_value));
2530 ratr_value |= (*(u16*)(pMcsRate)) << 12;
2531// switch (net->mode)
2532 switch (ieee->mode)
2533 {
2534 case IEEE_A:
2535 ratr_value &= 0x00000FF0;
2536 break;
2537 case IEEE_B:
2538 ratr_value &= 0x0000000F;
2539 break;
2540 case IEEE_G:
2541 ratr_value &= 0x00000FF7;
2542 break;
2543 case IEEE_N_24G:
2544 case IEEE_N_5G:
2545 if (ieee->pHTInfo->PeerMimoPs == 0) //MIMO_PS_STATIC
2546 ratr_value &= 0x0007F007;
2547 else{
2548 if (priv->rf_type == RF_1T2R)
2549 ratr_value &= 0x000FF007;
2550 else
2551 ratr_value &= 0x0F81F007;
2552 }
2553 break;
2554 default:
2555 break;
2556 }
2557 ratr_value &= 0x0FFFFFFF;
2558 if(ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz){
2559 ratr_value |= 0x80000000;
2560 }else if(!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz){
2561 ratr_value |= 0x80000000;
2562 }
2563 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2564 write_nic_byte(dev, UFWP, 1);
2565}
2566
2567static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
2568static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
2569bool GetNmodeSupportBySecCfg8192(struct net_device*dev)
2570{
Jerry Chuang8fc85982009-11-03 07:17:11 -02002571 struct r8192_priv* priv = ieee80211_priv(dev);
2572 struct ieee80211_device* ieee = priv->ieee80211;
2573 struct ieee80211_network * network = &ieee->current_network;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002574 int wpa_ie_len= ieee->wpa_ie_len;
2575 struct ieee80211_crypt_data* crypt;
2576 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002577
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002578 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002579 //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 -02002580 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 -02002581
2582 /* simply judge */
2583 if(encrypt && (wpa_ie_len == 0)) {
2584 /* wep encryption, no N mode setting */
2585 return false;
2586// } else if((wpa_ie_len != 0)&&(memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) {
2587 } else if((wpa_ie_len != 0)) {
2588 /* parse pairwise key type */
2589 //if((pairwisekey = WEP40)||(pairwisekey = WEP104)||(pairwisekey = TKIP))
2590 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))))
2591 return true;
2592 else
2593 return false;
2594 } else {
2595 return true;
2596 }
2597
Jerry Chuang8fc85982009-11-03 07:17:11 -02002598 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002599}
2600
2601bool GetHalfNmodeSupportByAPs819xUsb(struct net_device* dev)
2602{
2603 bool Reval;
2604 struct r8192_priv* priv = ieee80211_priv(dev);
2605 struct ieee80211_device* ieee = priv->ieee80211;
2606
2607 if(ieee->bHalfWirelessN24GMode == true)
2608 Reval = true;
2609 else
2610 Reval = false;
2611
2612 return Reval;
2613}
2614
2615void rtl8192_refresh_supportrate(struct r8192_priv* priv)
2616{
2617 struct ieee80211_device* ieee = priv->ieee80211;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002618 //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002619 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
2620 {
2621 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
2622 //RT_DEBUG_DATA(COMP_INIT, ieee->RegHTSuppRateSet, 16);
2623 //RT_DEBUG_DATA(COMP_INIT, ieee->Regdot11HTOperationalRateSet, 16);
2624 }
2625 else
2626 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2627 return;
2628}
2629
2630u8 rtl8192_getSupportedWireleeMode(struct net_device*dev)
2631{
2632 struct r8192_priv *priv = ieee80211_priv(dev);
2633 u8 ret = 0;
2634 switch(priv->rf_chip)
2635 {
2636 case RF_8225:
2637 case RF_8256:
2638 case RF_PSEUDO_11N:
2639 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2640 break;
2641 case RF_8258:
2642 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2643 break;
2644 default:
2645 ret = WIRELESS_MODE_B;
2646 break;
2647 }
2648 return ret;
2649}
2650void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode)
2651{
2652 struct r8192_priv *priv = ieee80211_priv(dev);
2653 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2654
Jerry Chuang8fc85982009-11-03 07:17:11 -02002655 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode)==0))
2656 {
2657 if(bSupportMode & WIRELESS_MODE_N_24G)
2658 {
2659 wireless_mode = WIRELESS_MODE_N_24G;
2660 }
2661 else if(bSupportMode & WIRELESS_MODE_N_5G)
2662 {
2663 wireless_mode = WIRELESS_MODE_N_5G;
2664 }
2665 else if((bSupportMode & WIRELESS_MODE_A))
2666 {
2667 wireless_mode = WIRELESS_MODE_A;
2668 }
2669 else if((bSupportMode & WIRELESS_MODE_G))
2670 {
2671 wireless_mode = WIRELESS_MODE_G;
2672 }
2673 else if((bSupportMode & WIRELESS_MODE_B))
2674 {
2675 wireless_mode = WIRELESS_MODE_B;
2676 }
2677 else{
2678 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __FUNCTION__,bSupportMode);
2679 wireless_mode = WIRELESS_MODE_B;
2680 }
2681 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002682#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 -02002683 ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
2684#endif
2685 priv->ieee80211->mode = wireless_mode;
2686
2687 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2688 priv->ieee80211->pHTInfo->bEnableHT = 1;
2689 else
2690 priv->ieee80211->pHTInfo->bEnableHT = 0;
2691 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2692 rtl8192_refresh_supportrate(priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002693
2694}
2695//init priv variables here. only non_zero value should be initialized here.
2696static void rtl8192_init_priv_variable(struct net_device* dev)
2697{
2698 struct r8192_priv *priv = ieee80211_priv(dev);
2699 u8 i;
2700 priv->card_8192 = NIC_8192U;
2701 priv->chan = 1; //set to channel 1
2702 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2703 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2704 priv->ieee80211->ieee_up=0;
2705 priv->retry_rts = DEFAULT_RETRY_RTS;
2706 priv->retry_data = DEFAULT_RETRY_DATA;
2707 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2708 priv->ieee80211->rate = 110; //11 mbps
2709 priv->ieee80211->short_slot = 1;
2710 priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0;
2711 priv->CckPwEnl = 6;
2712 //for silent reset
2713 priv->IrpPendingCount = 1;
2714 priv->ResetProgress = RESET_TYPE_NORESET;
2715 priv->bForcedSilentReset = 0;
2716 priv->bDisableNormalResetCheck = false;
2717 priv->force_reset = false;
2718
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002719 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002720 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2721 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2722 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2723 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2724 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
2725 IEEE_SOFTMAC_BEACONS;//added by amy 080604 //| //IEEE_SOFTMAC_SINGLE_QUEUE;
2726
2727 priv->ieee80211->active_scan = 1;
2728 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2729 priv->ieee80211->host_encrypt = 1;
2730 priv->ieee80211->host_decrypt = 1;
2731 priv->ieee80211->start_send_beacons = NULL;//rtl819xusb_beacon_tx;//-by amy 080604
2732 priv->ieee80211->stop_send_beacons = NULL;//rtl8192_beacon_stop;//-by amy 080604
2733 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2734 priv->ieee80211->set_chan = rtl8192_set_chan;
2735 priv->ieee80211->link_change = rtl8192_link_change;
2736 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2737 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2738 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2739 priv->ieee80211->init_wmmparam_flag = 0;
2740 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2741 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2742 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
2743 priv->ieee80211->qos_support = 1;
2744
2745 //added by WB
2746// priv->ieee80211->SwChnlByTimerHandler = rtl8192_phy_SwChnl;
2747 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2748 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2749 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2750 //added by david
2751 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
2752 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
2753 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2754 //added by amy
2755 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
2756 priv->card_type = USB;
2757#ifdef TO_DO_LIST
2758 if(Adapter->bInHctTest)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002759 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002760 pHalData->ShortRetryLimit = 7;
2761 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002762 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002763#endif
2764 {
2765 priv->ShortRetryLimit = 0x30;
2766 priv->LongRetryLimit = 0x30;
2767 }
2768 priv->EarlyRxThreshold = 7;
2769 priv->enable_gpio0 = 0;
2770 priv->TransmitConfig =
2771 // TCR_DurProcMode | //for RTL8185B, duration setting by HW
2772 //? TCR_DISReqQsize |
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002773 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002774 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
2775 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07002776 (false ? TCR_SAT: 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
Jerry Chuang8fc85982009-11-03 07:17:11 -02002777#ifdef TO_DO_LIST
2778 if(Adapter->bInHctTest)
2779 pHalData->ReceiveConfig = pHalData->CSMethod |
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002780 RCR_AMF | RCR_ADF | //RCR_AAP | //accept management/data
Jerry Chuang8fc85982009-11-03 07:17:11 -02002781 //guangan200710
2782 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2783 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002784 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002785 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2786 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
2787 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt:0);
2788 else
2789
2790#endif
2791 priv->ReceiveConfig =
2792 RCR_AMF | RCR_ADF | //accept management/data
2793 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2794 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002795 //RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002796 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2797 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
2798 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT:0);
2799
2800 priv->AcmControl = 0;
Devendra Nagab7553422012-08-26 11:06:33 +05302801 priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002802
2803 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002804 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002805 skb_queue_head_init(&priv->skb_queue);
2806
2807 /* Tx related queue */
2808 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
2809 skb_queue_head_init(&priv->ieee80211->skb_waitQ [i]);
2810 }
2811 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
2812 skb_queue_head_init(&priv->ieee80211->skb_aggQ [i]);
2813 }
2814 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
2815 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ [i]);
2816 }
2817 priv->rf_set_chan = rtl8192_phy_SwChnl;
2818}
2819
2820//init lock here
2821static void rtl8192_init_priv_lock(struct r8192_priv* priv)
2822{
2823 spin_lock_init(&priv->tx_lock);
2824 spin_lock_init(&priv->irq_lock);//added by thomas
2825 //spin_lock_init(&priv->rf_lock);
2826 sema_init(&priv->wx_sem,1);
2827 sema_init(&priv->rf_sem,1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002828 mutex_init(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002829}
2830
Jerry Chuang8fc85982009-11-03 07:17:11 -02002831extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002832
2833void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
2834//init tasklet and wait_queue here. only 2.6 above kernel is considered
2835#define DRV_NAME "wlan0"
2836static void rtl8192_init_priv_task(struct net_device* dev)
2837{
2838 struct r8192_priv *priv = ieee80211_priv(dev);
2839
Jerry Chuang8fc85982009-11-03 07:17:11 -02002840 priv->priv_wq = create_workqueue(DRV_NAME);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002841
Jerry Chuang8fc85982009-11-03 07:17:11 -02002842 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2843
2844 //INIT_DELAYED_WORK(&priv->watch_dog_wq, hal_dm_watchdog);
2845 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2846 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
2847// INIT_DELAYED_WORK(&priv->gpio_change_rf_wq, dm_gpio_change_rf_callback);
2848 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2849 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2850 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
2851 //INIT_WORK(&priv->SwChnlWorkItem, rtl8192_SwChnl_WorkItem);
2852 //INIT_WORK(&priv->SetBWModeWorkItem, rtl8192_SetBWModeWorkItem);
2853 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002854
2855 tasklet_init(&priv->irq_rx_tasklet,
2856 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2857 (unsigned long)priv);
2858}
2859
2860static void rtl8192_get_eeprom_size(struct net_device* dev)
2861{
2862 u16 curCR = 0;
2863 struct r8192_priv *priv = ieee80211_priv(dev);
2864 RT_TRACE(COMP_EPROM, "===========>%s()\n", __FUNCTION__);
2865 curCR = read_nic_word_E(dev,EPROM_CMD);
2866 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
2867 //whether need I consider BIT5?
2868 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
2869 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __FUNCTION__, priv->epromtype);
2870}
2871
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002872//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002873static inline u16 endian_swap(u16* data)
2874{
2875 u16 tmp = *data;
2876 *data = (tmp >> 8) | (tmp << 8);
2877 return *data;
2878}
2879static void rtl8192_read_eeprom_info(struct net_device* dev)
2880{
2881 u16 wEPROM_ID = 0;
2882 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
2883 u8 bLoad_From_EEPOM = false;
2884 struct r8192_priv *priv = ieee80211_priv(dev);
2885 u16 tmpValue = 0;
2886 RT_TRACE(COMP_EPROM, "===========>%s()\n", __FUNCTION__);
2887 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
2888 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
2889
2890 if (wEPROM_ID != RTL8190_EEPROM_ID)
2891 {
2892 RT_TRACE(COMP_ERR, "EEPROM ID is invalid(is 0x%x(should be 0x%x)\n", wEPROM_ID, RTL8190_EEPROM_ID);
2893 }
2894 else
2895 bLoad_From_EEPOM = true;
2896
2897 if (bLoad_From_EEPOM)
2898 {
2899 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
2900 priv->eeprom_vid = endian_swap(&tmpValue);
2901 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
2902 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
2903 priv->eeprom_ChannelPlan =((tmpValue&0xff00)>>8);
2904 priv->btxpowerdata_readfromEEPORM = true;
2905 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
2906 }
2907 else
2908 {
2909 priv->eeprom_vid = 0;
2910 priv->eeprom_pid = 0;
2911 priv->card_8192_version = VERSION_819xU_B;
2912 priv->eeprom_ChannelPlan = 0;
2913 priv->eeprom_CustomerID = 0;
2914 }
2915 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);
2916 //set channelplan from eeprom
2917 priv->ChannelPlan = priv->eeprom_ChannelPlan;
2918 if (bLoad_From_EEPOM)
2919 {
2920 int i;
2921 for (i=0; i<6; i+=2)
2922 {
2923 u16 tmp = 0;
2924 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
2925 *(u16*)(&dev->dev_addr[i]) = tmp;
2926 }
2927 }
2928 else
2929 {
2930 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2931 //should I set IDR0 here?
2932 }
Joe Perches0ee9f672009-12-06 11:34:52 -08002933 RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002934 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
2935 priv->rf_chip = RF_8256;
2936
2937 if (priv->card_8192_version == (u8)VERSION_819xU_A)
2938 {
2939 //read Tx power gain offset of legacy OFDM to HT rate
2940 if (bLoad_From_EEPOM)
2941 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
2942 else
2943 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
2944 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
2945 //read ThermalMeter from EEPROM
2946 if (bLoad_From_EEPOM)
2947 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
2948 else
2949 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2950 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
2951 //vivi, for tx power track
2952 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2953 //read antenna tx power offset of B/C/D to A from EEPROM
2954 if (bLoad_From_EEPOM)
2955 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
2956 else
2957 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
2958 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
2959 // Read CrystalCap from EEPROM
2960 if (bLoad_From_EEPOM)
2961 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
2962 else
2963 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
2964 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
2965 //get per-channel Tx power level
2966 if (bLoad_From_EEPOM)
2967 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
2968 else
2969 priv->EEPROM_Def_Ver = 1;
2970 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
2971 if (priv->EEPROM_Def_Ver == 0) //old eeprom definition
2972 {
2973 int i;
2974 if (bLoad_From_EEPOM)
2975 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
2976 else
2977 priv->EEPROMTxPowerLevelCCK = 0x10;
2978 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
2979 for (i=0; i<3; i++)
2980 {
2981 if (bLoad_From_EEPOM)
2982 {
2983 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
2984 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
2985 tmpValue = tmpValue & 0x00ff;
2986 else
2987 tmpValue = (tmpValue & 0xff00) >> 8;
2988 }
2989 else
2990 tmpValue = 0x10;
2991 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
2992 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
2993 }
2994 }//end if EEPROM_DEF_VER == 0
2995 else if (priv->EEPROM_Def_Ver == 1)
2996 {
2997 if (bLoad_From_EEPOM)
2998 {
2999 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
3000 tmpValue = (tmpValue & 0xff00) >> 8;
3001 }
3002 else
3003 tmpValue = 0x10;
3004 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
3005
3006 if (bLoad_From_EEPOM)
3007 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
3008 else
3009 tmpValue = 0x1010;
3010 *((u16*)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
3011 if (bLoad_From_EEPOM)
3012 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
3013 else
3014 tmpValue = 0x1010;
3015 *((u16*)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
3016 if (bLoad_From_EEPOM)
3017 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
3018 else
3019 tmpValue = 0x10;
3020 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
3021 }//endif EEPROM_Def_Ver == 1
3022
3023 //update HAL variables
3024 //
3025 {
3026 int i;
3027 for (i=0; i<14; i++)
3028 {
3029 if (i<=3)
3030 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
3031 else if (i>=4 && i<=9)
3032 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
3033 else
3034 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
3035 }
3036
3037 for (i=0; i<14; i++)
3038 {
3039 if (priv->EEPROM_Def_Ver == 0)
3040 {
3041 if (i<=3)
3042 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
3043 else if (i>=4 && i<=9)
3044 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
3045 else
3046 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
3047 }
3048 else if (priv->EEPROM_Def_Ver == 1)
3049 {
3050 if (i<=3)
3051 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
3052 else if (i>=4 && i<=9)
3053 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
3054 else
3055 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
3056 }
3057 }
3058 }//end update HAL variables
3059 priv->TxPowerDiff = priv->EEPROMPwDiff;
3060// Antenna B gain offset to antenna A, bit0~3
3061 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
3062 // Antenna C gain offset to antenna A, bit4~7
3063 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
3064 // CrystalCap, bit12~15
3065 priv->CrystalCap = priv->EEPROMCrystalCap;
3066 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
3067 // 92U does not enable TX power tracking.
3068 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
3069 }//end if VersionID == VERSION_819xU_A
3070
3071//added by vivi, for dlink led, 20080416
3072 switch(priv->eeprom_CustomerID)
3073 {
3074 case EEPROM_CID_RUNTOP:
3075 priv->CustomerID = RT_CID_819x_RUNTOP;
3076 break;
3077
3078 case EEPROM_CID_DLINK:
3079 priv->CustomerID = RT_CID_DLINK;
3080 break;
3081
3082 default:
3083 priv->CustomerID = RT_CID_DEFAULT;
3084 break;
3085
3086 }
3087
3088 switch(priv->CustomerID)
3089 {
3090 case RT_CID_819x_RUNTOP:
3091 priv->LedStrategy = SW_LED_MODE2;
3092 break;
3093
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003094 case RT_CID_DLINK:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003095 priv->LedStrategy = SW_LED_MODE4;
3096 break;
3097
3098 default:
3099 priv->LedStrategy = SW_LED_MODE0;
3100 break;
3101
3102 }
3103
3104
3105 if(priv->rf_type == RF_1T2R)
3106 {
3107 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
3108 }
3109 else
3110 {
3111 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
3112 }
3113
3114 // 2008/01/16 MH We can only know RF type in the function. So we have to init
3115 // DIG RATR table again.
3116 init_rate_adaptive(dev);
3117 //we need init DIG RATR table here again.
3118
3119 RT_TRACE(COMP_EPROM, "<===========%s()\n", __FUNCTION__);
3120 return;
3121}
3122
3123short rtl8192_get_channel_map(struct net_device * dev)
3124{
3125 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003126 if(priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN){
3127 printk("rtl8180_init:Error channel plan! Set to default.\n");
3128 priv->ChannelPlan= 0;
3129 }
3130 RT_TRACE(COMP_INIT, "Channel plan is %d\n",priv->ChannelPlan);
3131
3132 rtl819x_set_channel_map(priv->ChannelPlan, priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003133 return 0;
3134}
3135
3136short rtl8192_init(struct net_device *dev)
3137{
3138
3139 struct r8192_priv *priv = ieee80211_priv(dev);
3140
3141 memset(&(priv->stats),0,sizeof(struct Stats));
3142 memset(priv->txqueue_to_outpipemap,0,9);
3143#ifdef PIPE12
3144 {
3145 int i=0;
3146 u8 queuetopipe[]={3,2,1,0,4,8,7,6,5};
3147 memcpy(priv->txqueue_to_outpipemap,queuetopipe,9);
3148/* for(i=0;i<9;i++)
3149 printk("%d ",priv->txqueue_to_outpipemap[i]);
3150 printk("\n");*/
3151 }
3152#else
3153 {
3154 u8 queuetopipe[]={3,2,1,0,4,4,0,4,4};
3155 memcpy(priv->txqueue_to_outpipemap,queuetopipe,9);
3156/* for(i=0;i<9;i++)
3157 printk("%d ",priv->txqueue_to_outpipemap[i]);
3158 printk("\n");*/
3159 }
3160#endif
3161 rtl8192_init_priv_variable(dev);
3162 rtl8192_init_priv_lock(priv);
3163 rtl8192_init_priv_task(dev);
3164 rtl8192_get_eeprom_size(dev);
3165 rtl8192_read_eeprom_info(dev);
3166 rtl8192_get_channel_map(dev);
3167 init_hal_dm(dev);
3168 init_timer(&priv->watch_dog_timer);
3169 priv->watch_dog_timer.data = (unsigned long)dev;
3170 priv->watch_dog_timer.function = watch_dog_timer_callback;
3171 if(rtl8192_usb_initendpoints(dev)!=0){
3172 DMESG("Endopoints initialization failed");
3173 return -ENOMEM;
3174 }
3175
3176 //rtl8192_adapter_start(dev);
3177#ifdef DEBUG_EPROM
3178 dump_eprom(dev);
3179#endif
3180 return 0;
3181}
3182
3183/******************************************************************************
3184 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
3185 * not to do all the hw config as its name says
3186 * input: net_device dev
3187 * output: none
3188 * return: none
3189 * notice: This part need to modified according to the rate set we filtered
3190 * ****************************************************************************/
3191void rtl8192_hwconfig(struct net_device* dev)
3192{
3193 u32 regRATR = 0, regRRSR = 0;
3194 u8 regBwOpMode = 0, regTmp = 0;
3195 struct r8192_priv *priv = ieee80211_priv(dev);
3196
3197// Set RRSR, RATR, and BW_OPMODE registers
3198 //
3199 switch(priv->ieee80211->mode)
3200 {
3201 case WIRELESS_MODE_B:
3202 regBwOpMode = BW_OPMODE_20MHZ;
3203 regRATR = RATE_ALL_CCK;
3204 regRRSR = RATE_ALL_CCK;
3205 break;
3206 case WIRELESS_MODE_A:
3207 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
3208 regRATR = RATE_ALL_OFDM_AG;
3209 regRRSR = RATE_ALL_OFDM_AG;
3210 break;
3211 case WIRELESS_MODE_G:
3212 regBwOpMode = BW_OPMODE_20MHZ;
3213 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3214 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3215 break;
3216 case WIRELESS_MODE_AUTO:
3217#ifdef TO_DO_LIST
3218 if (Adapter->bInHctTest)
3219 {
3220 regBwOpMode = BW_OPMODE_20MHZ;
3221 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3222 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3223 }
3224 else
3225#endif
3226 {
3227 regBwOpMode = BW_OPMODE_20MHZ;
3228 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
3229 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3230 }
3231 break;
3232 case WIRELESS_MODE_N_24G:
3233 // It support CCK rate by default.
3234 // CCK rate will be filtered out only when associated AP does not support it.
3235 regBwOpMode = BW_OPMODE_20MHZ;
3236 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
3237 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
3238 break;
3239 case WIRELESS_MODE_N_5G:
3240 regBwOpMode = BW_OPMODE_5G;
3241 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
3242 regRRSR = RATE_ALL_OFDM_AG;
3243 break;
3244 }
3245
3246 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
3247 {
3248 u32 ratr_value = 0;
3249 ratr_value = regRATR;
3250 if (priv->rf_type == RF_1T2R)
3251 {
3252 ratr_value &= ~(RATE_ALL_OFDM_2SS);
3253 }
3254 write_nic_dword(dev, RATR0, ratr_value);
3255 write_nic_byte(dev, UFWP, 1);
3256 }
3257 regTmp = read_nic_byte(dev, 0x313);
3258 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
3259 write_nic_dword(dev, RRSR, regRRSR);
3260
3261 //
3262 // Set Retry Limit here
3263 //
3264 write_nic_word(dev, RETRY_LIMIT,
3265 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT | \
3266 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
3267 // Set Contention Window here
3268
3269 // Set Tx AGC
3270
3271 // Set Tx Antenna including Feedback control
3272
3273 // Set Auto Rate fallback control
3274
3275
3276}
3277
3278
3279//InitializeAdapter and PhyCfg
3280bool rtl8192_adapter_start(struct net_device *dev)
3281{
3282 struct r8192_priv *priv = ieee80211_priv(dev);
3283 u32 dwRegRead = 0;
3284 bool init_status = true;
3285 RT_TRACE(COMP_INIT, "====>%s()\n", __FUNCTION__);
3286 priv->Rf_Mode = RF_OP_By_SW_3wire;
3287 //for ASIC power on sequence
3288 write_nic_byte_E(dev, 0x5f, 0x80);
3289 mdelay(50);
3290 write_nic_byte_E(dev, 0x5f, 0xf0);
3291 write_nic_byte_E(dev, 0x5d, 0x00);
3292 write_nic_byte_E(dev, 0x5e, 0x80);
3293 write_nic_byte(dev, 0x17, 0x37);
3294 mdelay(10);
3295//#ifdef TO_DO_LIST
3296 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
3297 //config CPUReset Register
3298 //Firmware Reset or not?
3299 dwRegRead = read_nic_dword(dev, CPU_GEN);
3300 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
3301 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
3302 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
3303 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
3304 else
3305 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __FUNCTION__, priv->pFirmware->firmware_status);
3306
3307 write_nic_dword(dev, CPU_GEN, dwRegRead);
3308 //mdelay(30);
3309 //config BB.
3310 rtl8192_BBConfig(dev);
3311
Jerry Chuang8fc85982009-11-03 07:17:11 -02003312 //Loopback mode or not
3313 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
3314// priv->LoopbackMode = RTL819xU_MAC_LOOPBACK;
3315
3316 dwRegRead = read_nic_dword(dev, CPU_GEN);
3317 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
3318 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
3319 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
3320 dwRegRead |= CPU_CCK_LOOPBACK;
3321 else
3322 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __FUNCTION__, priv->LoopbackMode);
3323
3324 write_nic_dword(dev, CPU_GEN, dwRegRead);
3325
3326 //after reset cpu, we need wait for a seconds to write in register.
3327 udelay(500);
3328
3329 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
3330 write_nic_byte_E(dev, 0x5f, (read_nic_byte_E(dev, 0x5f)|0x20));
3331
3332 //Set Hardware
3333 rtl8192_hwconfig(dev);
3334
3335 //turn on Tx/Rx
3336 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
3337
3338 //set IDR0 here
3339 write_nic_dword(dev, MAC0, ((u32*)dev->dev_addr)[0]);
3340 write_nic_word(dev, MAC4, ((u16*)(dev->dev_addr + 4))[0]);
3341
3342 //set RCR
3343 write_nic_dword(dev, RCR, priv->ReceiveConfig);
3344
3345 //Initialize Number of Reserved Pages in Firmware Queue
3346 write_nic_dword(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << RSVD_FW_QUEUE_PAGE_BK_SHIFT |\
3347 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT | \
3348 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT | \
3349 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
3350 write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT |\
3351 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
3352 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW| \
3353 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT
3354// | NUM_OF_PAGE_IN_FW_QUEUE_PUB<<RSVD_FW_QUEUE_PAGE_PUB_SHIFT
3355 );
3356 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
3357
3358 //Set AckTimeout
3359 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
3360 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
3361
3362// RT_TRACE(COMP_INIT, "%s():priv->ResetProgress is %d\n", __FUNCTION__,priv->ResetProgress);
3363 if(priv->ResetProgress == RESET_TYPE_NORESET)
3364 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
3365 if(priv->ResetProgress == RESET_TYPE_NORESET){
3366 CamResetAllEntry(dev);
3367 {
3368 u8 SECR_value = 0x0;
3369 SECR_value |= SCR_TxEncEnable;
3370 SECR_value |= SCR_RxDecEnable;
3371 SECR_value |= SCR_NoSKMC;
3372 write_nic_byte(dev, SECR, SECR_value);
3373 }
3374 }
3375
3376 //Beacon related
3377 write_nic_word(dev, ATIMWND, 2);
3378 write_nic_word(dev, BCN_INTERVAL, 100);
3379
3380 {
3381#define DEFAULT_EDCA 0x005e4332
3382 int i;
3383 for (i=0; i<QOS_QUEUE_NUM; i++)
3384 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
3385 }
3386#ifdef USB_RX_AGGREGATION_SUPPORT
3387 //3 For usb rx firmware aggregation control
3388 if(priv->ResetProgress == RESET_TYPE_NORESET)
3389 {
3390 u32 ulValue;
3391 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
3392 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
3393 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
3394 /*
3395 * If usb rx firmware aggregation is enabled,
3396 * when anyone of three threshold conditions above is reached,
3397 * firmware will send aggregated packet to driver.
3398 */
3399 write_nic_dword(dev, 0x1a8, ulValue);
3400 priv->bCurrentRxAggrEnable = true;
3401 }
3402#endif
3403
3404 rtl8192_phy_configmac(dev);
3405
3406 if (priv->card_8192_version == (u8) VERSION_819xU_A)
3407 {
3408 rtl8192_phy_getTxPower(dev);
3409 rtl8192_phy_setTxPower(dev, priv->chan);
3410 }
3411
3412 //Firmware download
3413 init_status = init_firmware(dev);
3414 if(!init_status)
3415 {
3416 RT_TRACE(COMP_ERR,"ERR!!! %s(): Firmware download is failed\n", __FUNCTION__);
3417 return init_status;
3418 }
3419 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __FUNCTION__);
3420 //
3421#ifdef TO_DO_LIST
3422if(Adapter->ResetProgress == RESET_TYPE_NORESET)
3423 {
3424 if(pMgntInfo->RegRfOff == TRUE)
3425 { // User disable RF via registry.
3426 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
3427 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003428 // Those actions will be discard in MgntActSet_RF_State because of the same state
Jerry Chuang8fc85982009-11-03 07:17:11 -02003429 for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
3430 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3431 }
3432 else if(pMgntInfo->RfOffReason > RF_CHANGE_BY_PS)
3433 { // H/W or S/W RF OFF before sleep.
3434 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
3435 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
3436 }
3437 else
3438 {
3439 pHalData->eRFPowerState = eRfOn;
3440 pMgntInfo->RfOffReason = 0;
3441 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
3442 }
3443 }
3444 else
3445 {
3446 if(pHalData->eRFPowerState == eRfOff)
3447 {
3448 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003449 // Those actions will be discard in MgntActSet_RF_State because of the same state
Jerry Chuang8fc85982009-11-03 07:17:11 -02003450 for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
3451 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3452 }
3453 }
3454#endif
3455 //config RF.
3456 if(priv->ResetProgress == RESET_TYPE_NORESET){
3457 rtl8192_phy_RFConfig(dev);
3458 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __FUNCTION__);
3459 }
3460
3461
3462 if(priv->ieee80211->FwRWRF)
3463 // We can force firmware to do RF-R/W
3464 priv->Rf_Mode = RF_OP_By_FW;
3465 else
3466 priv->Rf_Mode = RF_OP_By_SW_3wire;
3467
3468
3469 rtl8192_phy_updateInitGain(dev);
3470 /*--set CCK and OFDM Block "ON"--*/
3471 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3472 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3473
3474 if(priv->ResetProgress == RESET_TYPE_NORESET)
3475 {
3476 //if D or C cut
3477 u8 tmpvalue = read_nic_byte(dev, 0x301);
3478 if(tmpvalue ==0x03)
3479 {
3480 priv->bDcut = TRUE;
3481 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
3482 }
3483 else
3484 {
3485 priv->bDcut = FALSE;
3486 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
3487 }
3488 dm_initialize_txpower_tracking(dev);
3489
3490 if(priv->bDcut == TRUE)
3491 {
3492 u32 i, TempCCk;
3493 u32 tmpRegA= rtl8192_QueryBBReg(dev,rOFDM0_XATxIQImbalance,bMaskDWord);
3494 // u32 tmpRegC= rtl8192_QueryBBReg(dev,rOFDM0_XCTxIQImbalance,bMaskDWord);
3495 for(i = 0; i<TxBBGainTableLength; i++)
3496 {
3497 if(tmpRegA == priv->txbbgain_table[i].txbbgain_value)
3498 {
3499 priv->rfa_txpowertrackingindex= (u8)i;
3500 priv->rfa_txpowertrackingindex_real= (u8)i;
3501 priv->rfa_txpowertracking_default= priv->rfa_txpowertrackingindex;
3502 break;
3503 }
3504 }
3505
3506 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3507
3508 for(i=0 ; i<CCKTxBBGainTableLength ; i++)
3509 {
3510
3511 if(TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0])
3512 {
3513 priv->cck_present_attentuation_20Mdefault=(u8) i;
3514 break;
3515 }
3516 }
3517 priv->cck_present_attentuation_40Mdefault= 0;
3518 priv->cck_present_attentuation_difference= 0;
3519 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
3520
3521 // pMgntInfo->bTXPowerTracking = FALSE;//TEMPLY DISABLE
3522 }
3523 }
3524 write_nic_byte(dev, 0x87, 0x0);
3525
3526
Jerry Chuang8fc85982009-11-03 07:17:11 -02003527 return init_status;
3528}
3529
3530/* this configures registers for beacon tx and enables it via
3531 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3532 * be used to stop beacon transmission
3533 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003534/***************************************************************************
3535 -------------------------------NET STUFF---------------------------
3536***************************************************************************/
3537
3538static struct net_device_stats *rtl8192_stats(struct net_device *dev)
3539{
3540 struct r8192_priv *priv = ieee80211_priv(dev);
3541
3542 return &priv->ieee80211->stats;
3543}
3544
3545bool
3546HalTxCheckStuck819xUsb(
3547 struct net_device *dev
3548 )
3549{
3550 struct r8192_priv *priv = ieee80211_priv(dev);
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003551 u16 RegTxCounter = read_nic_word(dev, 0x128);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003552 bool bStuck = FALSE;
3553 RT_TRACE(COMP_RESET,"%s():RegTxCounter is %d,TxCounter is %d\n",__FUNCTION__,RegTxCounter,priv->TxCounter);
3554 if(priv->TxCounter==RegTxCounter)
3555 bStuck = TRUE;
3556
3557 priv->TxCounter = RegTxCounter;
3558
3559 return bStuck;
3560}
3561
3562/*
3563* <Assumption: RT_TX_SPINLOCK is acquired.>
3564* First added: 2006.11.19 by emily
3565*/
3566RESET_TYPE
3567TxCheckStuck(struct net_device *dev)
3568{
3569 struct r8192_priv *priv = ieee80211_priv(dev);
3570 u8 QueueID;
3571// PRT_TCB pTcb;
3572// u8 ResetThreshold;
3573 bool bCheckFwTxCnt = false;
3574 //unsigned long flags;
3575
3576 //
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003577 // Decide such threshold according to current power save mode
Jerry Chuang8fc85982009-11-03 07:17:11 -02003578 //
3579
3580// RT_TRACE(COMP_RESET, " ==> TxCheckStuck()\n");
3581// PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
3582// spin_lock_irqsave(&priv->ieee80211->lock,flags);
3583 for (QueueID = 0; QueueID<=BEACON_QUEUE;QueueID ++)
3584 {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003585 if(QueueID == TXCMD_QUEUE)
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01003586 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003587#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
3588 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))
3589#else
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003590 if((skb_queue_len(&priv->ieee80211->skb_waitQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_aggQ[QueueID]) == 0))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003591#endif
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003592 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003593
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01003594 bCheckFwTxCnt = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003595 }
3596// PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
3597// spin_unlock_irqrestore(&priv->ieee80211->lock,flags);
3598// RT_TRACE(COMP_RESET,"bCheckFwTxCnt is %d\n",bCheckFwTxCnt);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003599 if(bCheckFwTxCnt)
3600 {
3601 if(HalTxCheckStuck819xUsb(dev))
3602 {
3603 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
3604 return RESET_TYPE_SILENT;
3605 }
3606 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003607 return RESET_TYPE_NORESET;
3608}
3609
3610bool
3611HalRxCheckStuck819xUsb(struct net_device *dev)
3612{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003613 u16 RegRxCounter = read_nic_word(dev, 0x130);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003614 struct r8192_priv *priv = ieee80211_priv(dev);
3615 bool bStuck = FALSE;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003616 static u8 rx_chk_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003617 RT_TRACE(COMP_RESET,"%s(): RegRxCounter is %d,RxCounter is %d\n",__FUNCTION__,RegRxCounter,priv->RxCounter);
3618 // If rssi is small, we should check rx for long time because of bad rx.
3619 // or maybe it will continuous silent reset every 2 seconds.
3620 rx_chk_cnt++;
3621 if(priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5))
3622 {
3623 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
3624 }
3625 else if(priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
3626 ((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_40M) ||
3627 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_20M)) )
3628 {
3629 if(rx_chk_cnt < 2)
3630 {
3631 return bStuck;
3632 }
3633 else
3634 {
3635 rx_chk_cnt = 0;
3636 }
3637 }
3638 else if(((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_40M) ||
3639 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_20M)) &&
3640 priv->undecorated_smoothed_pwdb >= VeryLowRSSI)
3641 {
3642 if(rx_chk_cnt < 4)
3643 {
3644 //DbgPrint("RSSI < %d && RSSI >= %d, no check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
3645 return bStuck;
3646 }
3647 else
3648 {
3649 rx_chk_cnt = 0;
3650 //DbgPrint("RSSI < %d && RSSI >= %d, check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
3651 }
3652 }
3653 else
3654 {
3655 if(rx_chk_cnt < 8)
3656 {
3657 //DbgPrint("RSSI <= %d, no check this time \n", VeryLowRSSI);
3658 return bStuck;
3659 }
3660 else
3661 {
3662 rx_chk_cnt = 0;
3663 //DbgPrint("RSSI <= %d, check this time \n", VeryLowRSSI);
3664 }
3665 }
3666
3667 if(priv->RxCounter==RegRxCounter)
3668 bStuck = TRUE;
3669
3670 priv->RxCounter = RegRxCounter;
3671
3672 return bStuck;
3673}
3674
3675RESET_TYPE
3676RxCheckStuck(struct net_device *dev)
3677{
3678 struct r8192_priv *priv = ieee80211_priv(dev);
3679 //int i;
3680 bool bRxCheck = FALSE;
3681
3682// RT_TRACE(COMP_RESET," ==> RxCheckStuck()\n");
3683 //PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK);
3684
3685 if(priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003686 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003687 //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK);
3688
3689// RT_TRACE(COMP_RESET,"bRxCheck is %d \n",bRxCheck);
3690 if(bRxCheck)
3691 {
3692 if(HalRxCheckStuck819xUsb(dev))
3693 {
3694 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
3695 return RESET_TYPE_SILENT;
3696 }
3697 }
3698 return RESET_TYPE_NORESET;
3699}
3700
3701
3702/**
3703* This function is called by Checkforhang to check whether we should ask OS to reset driver
3704*
3705* \param pAdapter The adapter context for this miniport
3706*
3707* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
3708* to judge whether there is tx stuck.
3709* Note: This function may be required to be rewrite for Vista OS.
3710* <<<Assumption: Tx spinlock has been acquired >>>
3711*
3712* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
3713*/
3714RESET_TYPE
3715rtl819x_ifcheck_resetornot(struct net_device *dev)
3716{
3717 struct r8192_priv *priv = ieee80211_priv(dev);
3718 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
3719 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003720 RT_RF_POWER_STATE rfState;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003721
3722 rfState = priv->ieee80211->eRFPowerState;
3723
3724 TxResetType = TxCheckStuck(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003725 if( rfState != eRfOff ||
3726 /*ADAPTER_TEST_STATUS_FLAG(Adapter, ADAPTER_STATUS_FW_DOWNLOAD_FAILURE)) &&*/
3727 (priv->ieee80211->iw_mode != IW_MODE_ADHOC))
3728 {
3729 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
3730 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
3731 // if driver is in firmware download failure status, driver should initialize RF in the following
3732 // silent reset procedure Emily, 2008.01.21
3733
3734 // Driver should not check RX stuck in IBSS mode because it is required to
3735 // set Check BSSID in order to send beacon, however, if check BSSID is
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003736 // set, STA cannot hear any packet at all. Emily, 2008.04.12
Jerry Chuang8fc85982009-11-03 07:17:11 -02003737 RxResetType = RxCheckStuck(dev);
3738 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003739 if(TxResetType==RESET_TYPE_NORMAL || RxResetType==RESET_TYPE_NORMAL)
3740 return RESET_TYPE_NORMAL;
3741 else if(TxResetType==RESET_TYPE_SILENT || RxResetType==RESET_TYPE_SILENT){
3742 RT_TRACE(COMP_RESET,"%s():silent reset\n",__FUNCTION__);
3743 return RESET_TYPE_SILENT;
3744 }
3745 else
3746 return RESET_TYPE_NORESET;
3747
3748}
3749
3750void rtl8192_cancel_deferred_work(struct r8192_priv* priv);
3751int _rtl8192_up(struct net_device *dev);
3752int rtl8192_close(struct net_device *dev);
3753
3754
3755
3756void
3757CamRestoreAllEntry( struct net_device *dev)
3758{
3759 u8 EntryId = 0;
3760 struct r8192_priv *priv = ieee80211_priv(dev);
3761 u8* MacAddr = priv->ieee80211->current_network.bssid;
3762
3763 static u8 CAM_CONST_ADDR[4][6] = {
3764 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3765 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
3766 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
3767 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
3768 static u8 CAM_CONST_BROAD[] =
3769 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3770
3771 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
3772
3773
3774 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40)||
3775 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104))
3776 {
3777
3778 for(EntryId=0; EntryId<4; EntryId++)
3779 {
3780 {
3781 MacAddr = CAM_CONST_ADDR[EntryId];
3782 setKey(dev,
3783 EntryId ,
3784 EntryId,
3785 priv->ieee80211->pairwise_key_type,
3786 MacAddr,
3787 0,
3788 NULL);
3789 }
3790 }
3791
3792 }
3793 else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP)
3794 {
3795
3796 {
3797 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3798 setKey(dev,
3799 4,
3800 0,
3801 priv->ieee80211->pairwise_key_type,
3802 (u8*)dev->dev_addr,
3803 0,
3804 NULL);
3805 else
3806 setKey(dev,
3807 4,
3808 0,
3809 priv->ieee80211->pairwise_key_type,
3810 MacAddr,
3811 0,
3812 NULL);
3813 }
3814 }
3815 else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP)
3816 {
3817
3818 {
3819 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3820 setKey(dev,
3821 4,
3822 0,
3823 priv->ieee80211->pairwise_key_type,
3824 (u8*)dev->dev_addr,
3825 0,
3826 NULL);
3827 else
3828 setKey(dev,
3829 4,
3830 0,
3831 priv->ieee80211->pairwise_key_type,
3832 MacAddr,
3833 0,
3834 NULL);
3835 }
3836 }
3837
3838
3839
3840 if(priv->ieee80211->group_key_type == KEY_TYPE_TKIP)
3841 {
3842 MacAddr = CAM_CONST_BROAD;
3843 for(EntryId=1 ; EntryId<4 ; EntryId++)
3844 {
3845 {
3846 setKey(dev,
3847 EntryId,
3848 EntryId,
3849 priv->ieee80211->group_key_type,
3850 MacAddr,
3851 0,
3852 NULL);
3853 }
3854 }
3855 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3856 setKey(dev,
3857 0,
3858 0,
3859 priv->ieee80211->group_key_type,
3860 CAM_CONST_ADDR[0],
3861 0,
3862 NULL);
3863 }
3864 else if(priv->ieee80211->group_key_type == KEY_TYPE_CCMP)
3865 {
3866 MacAddr = CAM_CONST_BROAD;
3867 for(EntryId=1; EntryId<4 ; EntryId++)
3868 {
3869 {
3870 setKey(dev,
3871 EntryId ,
3872 EntryId,
3873 priv->ieee80211->group_key_type,
3874 MacAddr,
3875 0,
3876 NULL);
3877 }
3878 }
3879
3880 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3881 setKey(dev,
3882 0 ,
3883 0,
3884 priv->ieee80211->group_key_type,
3885 CAM_CONST_ADDR[0],
3886 0,
3887 NULL);
3888 }
3889}
3890//////////////////////////////////////////////////////////////
3891// This function is used to fix Tx/Rx stop bug temporarily.
3892// This function will do "system reset" to NIC when Tx or Rx is stuck.
3893// The method checking Tx/Rx stuck of this function is supported by FW,
3894// which reports Tx and Rx counter to register 0x128 and 0x130.
3895//////////////////////////////////////////////////////////////
3896void
3897rtl819x_ifsilentreset(struct net_device *dev)
3898{
3899 //OCTET_STRING asocpdu;
3900 struct r8192_priv *priv = ieee80211_priv(dev);
3901 u8 reset_times = 0;
3902 int reset_status = 0;
3903 struct ieee80211_device *ieee = priv->ieee80211;
3904
3905
3906 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
3907 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
3908
3909 if(priv->ResetProgress==RESET_TYPE_NORESET)
3910 {
3911RESET_START:
3912
3913 RT_TRACE(COMP_RESET,"=========>Reset progress!! \n");
3914
3915 // Set the variable for reset.
3916 priv->ResetProgress = RESET_TYPE_SILENT;
3917// rtl8192_close(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003918 down(&priv->wx_sem);
3919 if(priv->up == 0)
3920 {
3921 RT_TRACE(COMP_ERR,"%s():the driver is not up! return\n",__FUNCTION__);
3922 up(&priv->wx_sem);
3923 return ;
3924 }
3925 priv->up = 0;
3926 RT_TRACE(COMP_RESET,"%s():======>start to down the driver\n",__FUNCTION__);
3927// if(!netif_queue_stopped(dev))
3928// netif_stop_queue(dev);
3929
3930 rtl8192_rtx_disable(dev);
3931 rtl8192_cancel_deferred_work(priv);
3932 deinit_hal_dm(dev);
3933 del_timer_sync(&priv->watch_dog_timer);
3934
3935 ieee->sync_scan_hurryup = 1;
3936 if(ieee->state == IEEE80211_LINKED)
3937 {
3938 down(&ieee->wx_sem);
3939 printk("ieee->state is IEEE80211_LINKED\n");
3940 ieee80211_stop_send_beacons(priv->ieee80211);
3941 del_timer_sync(&ieee->associate_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003942 cancel_delayed_work(&ieee->associate_retry_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003943 ieee80211_stop_scan(ieee);
3944 netif_carrier_off(dev);
3945 up(&ieee->wx_sem);
3946 }
3947 else{
3948 printk("ieee->state is NOT LINKED\n");
3949 ieee80211_softmac_stop_protocol(priv->ieee80211); }
3950 up(&priv->wx_sem);
3951 RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__);
3952 //rtl8192_irq_disable(dev);
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003953 RT_TRACE(COMP_RESET,"%s():===========>start up the driver\n",__FUNCTION__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003954 reset_status = _rtl8192_up(dev);
3955
3956 RT_TRACE(COMP_RESET,"%s():<===========up process is finished\n",__FUNCTION__);
3957 if(reset_status == -EAGAIN)
3958 {
3959 if(reset_times < 3)
3960 {
3961 reset_times++;
3962 goto RESET_START;
3963 }
3964 else
3965 {
3966 RT_TRACE(COMP_ERR," ERR!!! %s(): Reset Failed!!\n", __FUNCTION__);
3967 }
3968 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003969 ieee->is_silent_reset = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003970 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003971 if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA)
3972 {
3973 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3974
Jerry Chuang8fc85982009-11-03 07:17:11 -02003975 queue_work(ieee->wq, &ieee->associate_complete_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003976
3977 }
3978 else if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC)
3979 {
3980 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3981 ieee->link_change(ieee->dev);
3982
3983 // notify_wx_assoc_event(ieee);
3984
3985 ieee80211_start_send_beacons(ieee);
3986
3987 if (ieee->data_hard_resume)
3988 ieee->data_hard_resume(ieee->dev);
3989 netif_carrier_on(ieee->dev);
3990 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003991
3992 CamRestoreAllEntry(dev);
3993
3994 priv->ResetProgress = RESET_TYPE_NORESET;
3995 priv->reset_count++;
3996
3997 priv->bForcedSilentReset =false;
3998 priv->bResetInProgress = false;
3999
4000 // For test --> force write UFWP.
4001 write_nic_byte(dev, UFWP, 1);
4002 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004003 }
4004}
4005
4006void CAM_read_entry(
4007 struct net_device *dev,
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004008 u32 iIndex
Jerry Chuang8fc85982009-11-03 07:17:11 -02004009)
4010{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004011 u32 target_command=0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004012 u32 target_content=0;
4013 u8 entry_i=0;
4014 u32 ulStatus;
4015 s32 i=100;
4016// printk("=======>start read CAM\n");
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004017 for(entry_i=0;entry_i<CAM_CONTENT_COUNT;entry_i++)
4018 {
4019 // polling bit, and No Write enable, and address
Jerry Chuang8fc85982009-11-03 07:17:11 -02004020 target_command= entry_i+CAM_CONTENT_COUNT*iIndex;
4021 target_command= target_command | BIT31;
4022
4023 //Check polling bit is clear
4024// mdelay(1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004025 while((i--)>=0)
4026 {
4027 ulStatus = read_nic_dword(dev, RWCAM);
4028 if(ulStatus & BIT31){
4029 continue;
4030 }
4031 else{
4032 break;
4033 }
4034 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004035 write_nic_dword(dev, RWCAM, target_command);
4036 RT_TRACE(COMP_SEC,"CAM_read_entry(): WRITE A0: %x \n",target_command);
4037 // printk("CAM_read_entry(): WRITE A0: %lx \n",target_command);
4038 target_content = read_nic_dword(dev, RCAMO);
4039 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n",target_content);
4040 // printk("CAM_read_entry(): WRITE A8: %lx \n",target_content);
4041 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004042 printk("\n");
4043}
4044
4045void rtl819x_update_rxcounts(
4046 struct r8192_priv *priv,
4047 u32* TotalRxBcnNum,
4048 u32* TotalRxDataNum
4049)
4050{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004051 u16 SlotIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004052 u8 i;
4053
4054 *TotalRxBcnNum = 0;
4055 *TotalRxDataNum = 0;
4056
4057 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
4058 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
4059 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
4060 for( i=0; i<priv->ieee80211->LinkDetectInfo.SlotNum; i++ ){
4061 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
4062 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
4063 }
4064}
4065
4066
Jerry Chuang8fc85982009-11-03 07:17:11 -02004067extern void rtl819x_watchdog_wqcallback(struct work_struct *work)
4068{
4069 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
4070 struct r8192_priv *priv = container_of(dwork,struct r8192_priv,watch_dog_wq);
4071 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004072 struct ieee80211_device* ieee = priv->ieee80211;
4073 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01004074 static u8 check_reset_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004075 bool bBusyTraffic = false;
4076
4077 if(!priv->up)
4078 return;
4079 hal_dm_watchdog(dev);
4080
4081 {//to get busy traffic condition
4082 if(ieee->state == IEEE80211_LINKED)
4083 {
4084 if( ieee->LinkDetectInfo.NumRxOkInPeriod> 666 ||
4085 ieee->LinkDetectInfo.NumTxOkInPeriod> 666 ) {
4086 bBusyTraffic = true;
4087 }
4088 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
4089 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
4090 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
4091 }
4092 }
4093 //added by amy for AP roaming
4094 {
4095 if(priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA)
4096 {
4097 u32 TotalRxBcnNum = 0;
4098 u32 TotalRxDataNum = 0;
4099
4100 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
4101 if((TotalRxBcnNum+TotalRxDataNum) == 0)
4102 {
4103 #ifdef TODO
4104 if(rfState == eRfOff)
4105 RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__);
4106 #endif
4107 printk("===>%s(): AP is power off,connect another one\n",__FUNCTION__);
4108 // Dot11d_Reset(dev);
4109 priv->ieee80211->state = IEEE80211_ASSOCIATING;
4110 notify_wx_assoc_event(priv->ieee80211);
4111 RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
4112 priv->ieee80211->link_change(dev);
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01004113 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004114
4115 }
4116 }
4117 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod=0;
4118 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod=0;
4119 }
4120// CAM_read_entry(dev,4);
4121 //check if reset the driver
4122 if(check_reset_cnt++ >= 3)
4123 {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004124 ResetType = rtl819x_ifcheck_resetornot(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004125 check_reset_cnt = 3;
4126 //DbgPrint("Start to check silent reset\n");
4127 }
4128 // 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 -02004129 if( (priv->force_reset) || (priv->ResetProgress==RESET_TYPE_NORESET &&
4130 (priv->bForcedSilentReset ||
4131 (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT)))) // This is control by OID set in Pomelo
4132 {
4133 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);
4134 rtl819x_ifsilentreset(dev);
4135 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004136 priv->force_reset = false;
4137 priv->bForcedSilentReset = false;
4138 priv->bResetInProgress = false;
4139 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
4140
4141}
4142
4143void watch_dog_timer_callback(unsigned long data)
4144{
4145 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004146 //printk("===============>watch_dog timer\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02004147 queue_delayed_work(priv->priv_wq,&priv->watch_dog_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004148 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004149}
4150int _rtl8192_up(struct net_device *dev)
4151{
4152 struct r8192_priv *priv = ieee80211_priv(dev);
4153 //int i;
4154 int init_status = 0;
4155 priv->up=1;
4156 priv->ieee80211->ieee_up=1;
4157 RT_TRACE(COMP_INIT, "Bringing up iface");
4158 init_status = rtl8192_adapter_start(dev);
4159 if(!init_status)
4160 {
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004161 RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization failed!\n", __FUNCTION__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004162 priv->up=priv->ieee80211->ieee_up = 0;
4163 return -EAGAIN;
4164 }
4165 RT_TRACE(COMP_INIT, "start adapter finished\n");
4166 rtl8192_rx_enable(dev);
4167// rtl8192_tx_enable(dev);
4168 if(priv->ieee80211->state != IEEE80211_LINKED)
4169 ieee80211_softmac_start_protocol(priv->ieee80211);
4170 ieee80211_reset_queue(priv->ieee80211);
4171 watch_dog_timer_callback((unsigned long) dev);
4172 if(!netif_queue_stopped(dev))
4173 netif_start_queue(dev);
4174 else
4175 netif_wake_queue(dev);
4176
4177 return 0;
4178}
4179
4180
4181int rtl8192_open(struct net_device *dev)
4182{
4183 struct r8192_priv *priv = ieee80211_priv(dev);
4184 int ret;
4185 down(&priv->wx_sem);
4186 ret = rtl8192_up(dev);
4187 up(&priv->wx_sem);
4188 return ret;
4189
4190}
4191
4192
4193int rtl8192_up(struct net_device *dev)
4194{
4195 struct r8192_priv *priv = ieee80211_priv(dev);
4196
4197 if (priv->up == 1) return -1;
4198
4199 return _rtl8192_up(dev);
4200}
4201
4202
4203int rtl8192_close(struct net_device *dev)
4204{
4205 struct r8192_priv *priv = ieee80211_priv(dev);
4206 int ret;
4207
4208 down(&priv->wx_sem);
4209
4210 ret = rtl8192_down(dev);
4211
4212 up(&priv->wx_sem);
4213
4214 return ret;
4215
4216}
4217
4218int rtl8192_down(struct net_device *dev)
4219{
4220 struct r8192_priv *priv = ieee80211_priv(dev);
4221 int i;
4222
4223 if (priv->up == 0) return -1;
4224
4225 priv->up=0;
4226 priv->ieee80211->ieee_up = 0;
4227 RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
4228/* FIXME */
4229 if (!netif_queue_stopped(dev))
4230 netif_stop_queue(dev);
4231
4232 rtl8192_rtx_disable(dev);
4233 //rtl8192_irq_disable(dev);
4234
4235 /* Tx related queue release */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004236 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
4237 skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
4238 }
4239 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
4240 skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
4241 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004242
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004243 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
4244 skb_queue_purge(&priv->ieee80211->skb_drv_aggQ [i]);
4245 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004246
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004247 //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 -02004248// flush_scheduled_work();
4249 rtl8192_cancel_deferred_work(priv);
4250 deinit_hal_dm(dev);
4251 del_timer_sync(&priv->watch_dog_timer);
4252
4253
4254 ieee80211_softmac_stop_protocol(priv->ieee80211);
4255 memset(&priv->ieee80211->current_network, 0 , offsetof(struct ieee80211_network, list));
4256 RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
4257
4258 return 0;
4259}
4260
4261
4262void rtl8192_commit(struct net_device *dev)
4263{
4264 struct r8192_priv *priv = ieee80211_priv(dev);
4265 int reset_status = 0;
4266 //u8 reset_times = 0;
4267 if (priv->up == 0) return ;
4268 priv->up = 0;
4269
4270 rtl8192_cancel_deferred_work(priv);
4271 del_timer_sync(&priv->watch_dog_timer);
4272 //cancel_delayed_work(&priv->SwChnlWorkItem);
4273
4274 ieee80211_softmac_stop_protocol(priv->ieee80211);
4275
4276 //rtl8192_irq_disable(dev);
4277 rtl8192_rtx_disable(dev);
4278 reset_status = _rtl8192_up(dev);
4279
4280}
4281
4282/*
4283void rtl8192_restart(struct net_device *dev)
4284{
4285 struct r8192_priv *priv = ieee80211_priv(dev);
4286*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02004287void rtl8192_restart(struct work_struct *work)
4288{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004289 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
4290 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004291
4292 down(&priv->wx_sem);
4293
4294 rtl8192_commit(dev);
4295
4296 up(&priv->wx_sem);
4297}
4298
4299static void r8192_set_multicast(struct net_device *dev)
4300{
4301 struct r8192_priv *priv = ieee80211_priv(dev);
4302 short promisc;
4303
4304 //down(&priv->wx_sem);
4305
4306 /* FIXME FIXME */
4307
4308 promisc = (dev->flags & IFF_PROMISC) ? 1:0;
4309
4310 if (promisc != priv->promisc)
4311 // rtl8192_commit(dev);
4312
4313 priv->promisc = promisc;
4314
4315 //schedule_work(&priv->reset_wq);
4316 //up(&priv->wx_sem);
4317}
4318
4319
4320int r8192_set_mac_adr(struct net_device *dev, void *mac)
4321{
4322 struct r8192_priv *priv = ieee80211_priv(dev);
4323 struct sockaddr *addr = mac;
4324
4325 down(&priv->wx_sem);
4326
4327 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
4328
Jerry Chuang8fc85982009-11-03 07:17:11 -02004329 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004330 up(&priv->wx_sem);
4331
4332 return 0;
4333}
4334
4335/* based on ipw2200 driver */
4336int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
4337{
4338 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4339 struct iwreq *wrq = (struct iwreq *)rq;
4340 int ret=-1;
4341 struct ieee80211_device *ieee = priv->ieee80211;
4342 u32 key[4];
4343 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
4344 struct iw_point *p = &wrq->u.data;
4345 struct ieee_param *ipw = NULL;//(struct ieee_param *)wrq->u.data.pointer;
4346
4347 down(&priv->wx_sem);
4348
4349
4350 if (p->length < sizeof(struct ieee_param) || !p->pointer){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004351 ret = -EINVAL;
4352 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004353 }
4354
Julia Lawall32414872010-05-11 20:26:57 +02004355 ipw = kmalloc(p->length, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004356 if (ipw == NULL){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004357 ret = -ENOMEM;
4358 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004359 }
4360 if (copy_from_user(ipw, p->pointer, p->length)) {
4361 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004362 ret = -EFAULT;
4363 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004364 }
4365
4366 switch (cmd) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004367 case RTL_IOCTL_WPA_SUPPLICANT:
Jerry Chuang8fc85982009-11-03 07:17:11 -02004368 //parse here for HW security
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004369 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION)
4370 {
4371 if (ipw->u.crypt.set_tx)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004372 {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004373 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
4374 ieee->pairwise_key_type = KEY_TYPE_CCMP;
4375 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
4376 ieee->pairwise_key_type = KEY_TYPE_TKIP;
4377 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004378 {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004379 if (ipw->u.crypt.key_len == 13)
4380 ieee->pairwise_key_type = KEY_TYPE_WEP104;
4381 else if (ipw->u.crypt.key_len == 5)
4382 ieee->pairwise_key_type = KEY_TYPE_WEP40;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004383 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004384 else
4385 ieee->pairwise_key_type = KEY_TYPE_NA;
4386
4387 if (ieee->pairwise_key_type)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004388 {
4389 memcpy((u8*)key, ipw->u.crypt.key, 16);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004390 EnableHWSecurityConfig8192(dev);
4391 //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!
4392 //added by WB.
4393 setKey(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
4394 if (ieee->auth_mode != 2)
4395 setKey(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004396 }
4397 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004398 else //if (ipw->u.crypt.idx) //group key use idx > 0
4399 {
4400 memcpy((u8*)key, ipw->u.crypt.key, 16);
4401 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
4402 ieee->group_key_type= KEY_TYPE_CCMP;
4403 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
4404 ieee->group_key_type = KEY_TYPE_TKIP;
4405 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
4406 {
4407 if (ipw->u.crypt.key_len == 13)
4408 ieee->group_key_type = KEY_TYPE_WEP104;
4409 else if (ipw->u.crypt.key_len == 5)
4410 ieee->group_key_type = KEY_TYPE_WEP40;
4411 }
4412 else
4413 ieee->group_key_type = KEY_TYPE_NA;
4414
4415 if (ieee->group_key_type)
4416 {
4417 setKey( dev,
4418 ipw->u.crypt.idx,
4419 ipw->u.crypt.idx, //KeyIndex
4420 ieee->group_key_type, //KeyType
4421 broadcast_addr, //MacAddr
4422 0, //DefaultKey
4423 key); //KeyContent
4424 }
4425 }
4426 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004427#ifdef JOHN_HWSEC_DEBUG
4428 //john's test 0711
4429 printk("@@ wrq->u pointer = ");
4430 for(i=0;i<wrq->u.data.length;i++){
4431 if(i%10==0) printk("\n");
4432 printk( "%8x|", ((u32*)wrq->u.data.pointer)[i] );
4433 }
4434 printk("\n");
4435#endif /*JOHN_HWSEC_DEBUG*/
4436 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
4437 break;
4438
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004439 default:
Jerry Chuang8fc85982009-11-03 07:17:11 -02004440 ret = -EOPNOTSUPP;
4441 break;
4442 }
4443 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004444 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004445out:
4446 up(&priv->wx_sem);
4447 return ret;
4448}
4449
4450u8 HwRateToMRate90(bool bIsHT, u8 rate)
4451{
4452 u8 ret_rate = 0xff;
4453
4454 if(!bIsHT) {
4455 switch(rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004456 case DESC90_RATE1M: ret_rate = MGN_1M; break;
4457 case DESC90_RATE2M: ret_rate = MGN_2M; break;
4458 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
4459 case DESC90_RATE11M: ret_rate = MGN_11M; break;
4460 case DESC90_RATE6M: ret_rate = MGN_6M; break;
4461 case DESC90_RATE9M: ret_rate = MGN_9M; break;
4462 case DESC90_RATE12M: ret_rate = MGN_12M; break;
4463 case DESC90_RATE18M: ret_rate = MGN_18M; break;
4464 case DESC90_RATE24M: ret_rate = MGN_24M; break;
4465 case DESC90_RATE36M: ret_rate = MGN_36M; break;
4466 case DESC90_RATE48M: ret_rate = MGN_48M; break;
4467 case DESC90_RATE54M: ret_rate = MGN_54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004468
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004469 default:
4470 ret_rate = 0xff;
4471 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
4472 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004473 }
4474
4475 } else {
4476 switch(rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004477 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
4478 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
4479 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
4480 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
4481 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
4482 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
4483 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
4484 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
4485 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
4486 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
4487 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
4488 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
4489 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
4490 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
4491 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
4492 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
4493 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004494
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004495 default:
4496 ret_rate = 0xff;
4497 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n",rate, bIsHT);
4498 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004499 }
4500 }
4501
4502 return ret_rate;
4503}
4504
4505/**
4506 * Function: UpdateRxPktTimeStamp
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004507 * Overview: Record the TSF time stamp when receiving a packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02004508 *
4509 * Input:
4510 * PADAPTER Adapter
4511 * PRT_RFD pRfd,
4512 *
4513 * Output:
4514 * PRT_RFD pRfd
4515 * (pRfd->Status.TimeStampHigh is updated)
4516 * (pRfd->Status.TimeStampLow is updated)
4517 * Return:
4518 * None
4519 */
4520void UpdateRxPktTimeStamp8190 (struct net_device *dev, struct ieee80211_rx_stats *stats)
4521{
4522 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4523
4524 if(stats->bIsAMPDU && !stats->bFirstMPDU) {
4525 stats->mac_time[0] = priv->LastRxDescTSFLow;
4526 stats->mac_time[1] = priv->LastRxDescTSFHigh;
4527 } else {
4528 priv->LastRxDescTSFLow = stats->mac_time[0];
4529 priv->LastRxDescTSFHigh = stats->mac_time[1];
4530 }
4531}
4532
4533//by amy 080606
4534
4535long rtl819x_translate_todbm(u8 signal_strength_index )// 0-100 index.
4536{
4537 long signal_power; // in dBm.
4538
4539 // Translate to dBm (x=0.5y-95).
4540 signal_power = (long)((signal_strength_index + 1) >> 1);
4541 signal_power -= 95;
4542
4543 return signal_power;
4544}
4545
4546
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004547/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
Jerry Chuang8fc85982009-11-03 07:17:11 -02004548 be a local static. Otherwise, it may increase when we return from S3/S4. The
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004549 value will be kept in memory or disk. Declare the value in the adaptor
4550 and it will be reinitialized when returned from S3/S4. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004551void rtl8192_process_phyinfo(struct r8192_priv * priv,u8* buffer, struct ieee80211_rx_stats * pprevious_stats, struct ieee80211_rx_stats * pcurrent_stats)
4552{
4553 bool bcheck = false;
4554 u8 rfpath;
4555 u32 nspatial_stream, tmp_val;
4556 //u8 i;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01004557 static u32 slide_rssi_index, slide_rssi_statistics;
4558 static u32 slide_evm_index, slide_evm_statistics;
4559 static u32 last_rssi, last_evm;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004560
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01004561 static u32 slide_beacon_adc_pwdb_index, slide_beacon_adc_pwdb_statistics;
4562 static u32 last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004563
4564 struct ieee80211_hdr_3addr *hdr;
4565 u16 sc ;
4566 unsigned int frag,seq;
4567 hdr = (struct ieee80211_hdr_3addr *)buffer;
4568 sc = le16_to_cpu(hdr->seq_ctl);
4569 frag = WLAN_GET_SEQ_FRAG(sc);
4570 seq = WLAN_GET_SEQ_SEQ(sc);
4571 //cosa add 04292008 to record the sequence number
4572 pcurrent_stats->Seq_Num = seq;
4573 //
4574 // Check whether we should take the previous packet into accounting
4575 //
4576 if(!pprevious_stats->bIsAMPDU)
4577 {
4578 // if previous packet is not aggregated packet
4579 bcheck = true;
4580 }else
4581 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004582 }
4583
4584
4585 if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX)
4586 {
4587 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
4588 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
4589 priv->stats.slide_rssi_total -= last_rssi;
4590 }
4591 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
4592
4593 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
4594 if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
4595 slide_rssi_index = 0;
4596
4597 // <1> Showed on UI for user, in dbm
4598 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
4599 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
4600 pcurrent_stats->rssi = priv->stats.signal_strength;
4601 //
4602 // If the previous packet does not match the criteria, neglect it
4603 //
4604 if(!pprevious_stats->bPacketMatchBSSID)
4605 {
4606 if(!pprevious_stats->bToSelfBA)
4607 return;
4608 }
4609
4610 if(!bcheck)
4611 return;
4612
4613
4614 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
4615
4616 //
4617 // Check RSSI
4618 //
4619 priv->stats.num_process_phyinfo++;
4620
4621 /* record the general signal strength to the sliding window. */
4622
4623
4624 // <2> Showed on UI for engineering
4625 // hardware does not provide rssi information for each rf path in CCK
4626 if(!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA))
4627 {
4628 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++)
4629 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004630 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
4631 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004632
4633 //Fixed by Jacken 2008-03-20
4634 if(priv->stats.rx_rssi_percentage[rfpath] == 0)
4635 {
4636 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
4637 //DbgPrint("MIMO RSSI initialize \n");
4638 }
4639 if(pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath])
4640 {
4641 priv->stats.rx_rssi_percentage[rfpath] =
4642 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
4643 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
4644 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
4645 }
4646 else
4647 {
4648 priv->stats.rx_rssi_percentage[rfpath] =
4649 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
4650 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
4651 }
4652 RT_TRACE(COMP_DBG,"priv->stats.rx_rssi_percentage[rfPath] = %d \n" ,priv->stats.rx_rssi_percentage[rfpath] );
4653 }
4654 }
4655
4656
4657 //
4658 // Check PWDB.
4659 //
4660 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
4661 pprevious_stats->bIsCCK? "CCK": "OFDM",
4662 pprevious_stats->RxPWDBAll);
4663
4664 if(pprevious_stats->bPacketBeacon)
4665 {
4666/* record the beacon pwdb to the sliding window. */
4667 if(slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX)
4668 {
4669 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
4670 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
4671 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
4672 //DbgPrint("slide_beacon_adc_pwdb_index = %d, last_beacon_adc_pwdb = %d, Adapter->RxStats.Slide_Beacon_Total = %d\n",
4673 // slide_beacon_adc_pwdb_index, last_beacon_adc_pwdb, Adapter->RxStats.Slide_Beacon_Total);
4674 }
4675 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
4676 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
4677 //DbgPrint("slide_beacon_adc_pwdb_index = %d, pPreviousRfd->Status.RxPWDBAll = %d\n", slide_beacon_adc_pwdb_index, pPreviousRfd->Status.RxPWDBAll);
4678 slide_beacon_adc_pwdb_index++;
4679 if(slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
4680 slide_beacon_adc_pwdb_index = 0;
4681 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
4682 if(pprevious_stats->RxPWDBAll >= 3)
4683 pprevious_stats->RxPWDBAll -= 3;
4684 }
4685
4686 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
4687 pprevious_stats->bIsCCK? "CCK": "OFDM",
4688 pprevious_stats->RxPWDBAll);
4689
4690
4691 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
4692 {
4693 if(priv->undecorated_smoothed_pwdb < 0) // initialize
4694 {
4695 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
4696 //DbgPrint("First pwdb initialize \n");
4697 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004698 if(pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb)
4699 {
4700 priv->undecorated_smoothed_pwdb =
4701 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4702 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
4703 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
4704 }
4705 else
4706 {
4707 priv->undecorated_smoothed_pwdb =
4708 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4709 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
4710 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004711
4712 }
4713
4714 //
4715 // Check EVM
4716 //
4717 /* record the general EVM to the sliding window. */
4718 if(pprevious_stats->SignalQuality == 0)
4719 {
4720 }
4721 else
4722 {
4723 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA){
4724 if(slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX){
4725 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
4726 last_evm = priv->stats.slide_evm[slide_evm_index];
4727 priv->stats.slide_evm_total -= last_evm;
4728 }
4729
4730 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
4731
4732 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
4733 if(slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
4734 slide_evm_index = 0;
4735
4736 // <1> Showed on UI for user, in percentage.
4737 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
4738 priv->stats.signal_quality = tmp_val;
4739 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
4740 priv->stats.last_signal_strength_inpercent = tmp_val;
4741 }
4742
4743 // <2> Showed on UI for engineering
4744 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
4745 {
4746 for(nspatial_stream = 0; nspatial_stream<2 ; nspatial_stream++) // 2 spatial stream
4747 {
4748 if(pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1)
4749 {
4750 if(priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
4751 {
4752 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
4753 }
4754 priv->stats.rx_evm_percentage[nspatial_stream] =
4755 ( (priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
4756 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
4757 }
4758 }
4759 }
4760 }
4761
4762
4763}
4764
4765/*-----------------------------------------------------------------------------
4766 * Function: rtl819x_query_rxpwrpercentage()
4767 *
4768 * Overview:
4769 *
4770 * Input: char antpower
4771 *
4772 * Output: NONE
4773 *
4774 * Return: 0-100 percentage
4775 *
4776 * Revised History:
4777 * When Who Remark
4778 * 05/26/2008 amy Create Version 0 porting from windows code.
4779 *
4780 *---------------------------------------------------------------------------*/
4781static u8 rtl819x_query_rxpwrpercentage(
4782 char antpower
4783 )
4784{
4785 if ((antpower <= -100) || (antpower >= 20))
4786 {
4787 return 0;
4788 }
4789 else if (antpower >= 0)
4790 {
4791 return 100;
4792 }
4793 else
4794 {
4795 return (100+antpower);
4796 }
4797
4798} /* QueryRxPwrPercentage */
4799
4800static u8
4801rtl819x_evm_dbtopercentage(
4802 char value
4803 )
4804{
4805 char ret_val;
4806
4807 ret_val = value;
4808
4809 if(ret_val >= 0)
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01004810 ret_val = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004811 if(ret_val <= -33)
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01004812 ret_val = -33;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004813 ret_val = 0 - ret_val;
4814 ret_val*=3;
4815 if(ret_val == 99)
4816 ret_val = 100;
4817 return(ret_val);
4818}
4819//
4820// Description:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004821// We want good-looking for signal strength/quality
Jerry Chuang8fc85982009-11-03 07:17:11 -02004822// 2007/7/19 01:09, by cosa.
4823//
4824long
4825rtl819x_signal_scale_mapping(
4826 long currsig
4827 )
4828{
4829 long retsig;
4830
4831 // Step 1. Scale mapping.
4832 if(currsig >= 61 && currsig <= 100)
4833 {
4834 retsig = 90 + ((currsig - 60) / 4);
4835 }
4836 else if(currsig >= 41 && currsig <= 60)
4837 {
4838 retsig = 78 + ((currsig - 40) / 2);
4839 }
4840 else if(currsig >= 31 && currsig <= 40)
4841 {
4842 retsig = 66 + (currsig - 30);
4843 }
4844 else if(currsig >= 21 && currsig <= 30)
4845 {
4846 retsig = 54 + (currsig - 20);
4847 }
4848 else if(currsig >= 5 && currsig <= 20)
4849 {
4850 retsig = 42 + (((currsig - 5) * 2) / 3);
4851 }
4852 else if(currsig == 4)
4853 {
4854 retsig = 36;
4855 }
4856 else if(currsig == 3)
4857 {
4858 retsig = 27;
4859 }
4860 else if(currsig == 2)
4861 {
4862 retsig = 18;
4863 }
4864 else if(currsig == 1)
4865 {
4866 retsig = 9;
4867 }
4868 else
4869 {
4870 retsig = currsig;
4871 }
4872
4873 return retsig;
4874}
4875
4876static void rtl8192_query_rxphystatus(
4877 struct r8192_priv * priv,
4878 struct ieee80211_rx_stats * pstats,
4879 rx_drvinfo_819x_usb * pdrvinfo,
4880 struct ieee80211_rx_stats * precord_stats,
4881 bool bpacket_match_bssid,
4882 bool bpacket_toself,
4883 bool bPacketBeacon,
4884 bool bToSelfBA
4885 )
4886{
4887 //PRT_RFD_STATUS pRtRfdStatus = &(pRfd->Status);
4888 phy_sts_ofdm_819xusb_t* pofdm_buf;
4889 phy_sts_cck_819xusb_t * pcck_buf;
4890 phy_ofdm_rx_status_rxsc_sgien_exintfflag* prxsc;
4891 u8 *prxpkt;
4892 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
4893 char rx_pwr[4], rx_pwr_all=0;
4894 //long rx_avg_pwr = 0;
4895 char rx_snrX, rx_evmX;
4896 u8 evm, pwdb_all;
4897 u32 RSSI, total_rssi=0;//, total_evm=0;
4898// long signal_strength_index = 0;
4899 u8 is_cck_rate=0;
4900 u8 rf_rx_num = 0;
4901
4902
4903 priv->stats.numqry_phystatus++;
4904
4905 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4906
4907 // Record it for next packet processing
4908 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4909 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4910 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
4911 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;//RX_HAL_IS_CCK_RATE(pDrvInfo);
4912 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4913 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4914
4915 prxpkt = (u8*)pdrvinfo;
4916
4917 /* Move pointer to the 16th bytes. Phy status start address. */
4918 prxpkt += sizeof(rx_drvinfo_819x_usb);
4919
4920 /* Initial the cck and ofdm buffer pointer */
4921 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
4922 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
4923
4924 pstats->RxMIMOSignalQuality[0] = -1;
4925 pstats->RxMIMOSignalQuality[1] = -1;
4926 precord_stats->RxMIMOSignalQuality[0] = -1;
4927 precord_stats->RxMIMOSignalQuality[1] = -1;
4928
4929 if(is_cck_rate)
4930 {
4931 //
4932 // (1)Hardware does not provide RSSI for CCK
4933 //
4934
4935 //
4936 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4937 //
4938 u8 report;//, cck_agc_rpt;
4939
4940 priv->stats.numqry_phystatusCCK++;
4941
4942 if(!priv->bCckHighPower)
4943 {
4944 report = pcck_buf->cck_agc_rpt & 0xc0;
4945 report = report>>6;
4946 switch(report)
4947 {
4948 //Fixed by Jacken from Bryant 2008-03-20
4949 //Original value is -38 , -26 , -14 , -2
4950 //Fixed value is -35 , -23 , -11 , 6
4951 case 0x3:
4952 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4953 break;
4954 case 0x2:
4955 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4956 break;
4957 case 0x1:
4958 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4959 break;
4960 case 0x0:
4961 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
4962 break;
4963 }
4964 }
4965 else
4966 {
4967 report = pcck_buf->cck_agc_rpt & 0x60;
4968 report = report>>5;
4969 switch(report)
4970 {
4971 case 0x3:
4972 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4973 break;
4974 case 0x2:
4975 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4976 break;
4977 case 0x1:
4978 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4979 break;
4980 case 0x0:
4981 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4982 break;
4983 }
4984 }
4985
4986 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4987 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4988 pstats->RecvSignalPower = pwdb_all;
4989
4990 //
4991 // (3) Get Signal Quality (EVM)
4992 //
4993 //if(bpacket_match_bssid)
4994 {
4995 u8 sq;
4996
4997 if(pstats->RxPWDBAll > 40)
4998 {
4999 sq = 100;
5000 }else
5001 {
5002 sq = pcck_buf->sq_rpt;
5003
5004 if(pcck_buf->sq_rpt > 64)
5005 sq = 0;
5006 else if (pcck_buf->sq_rpt < 20)
5007 sq = 100;
5008 else
5009 sq = ((64-sq) * 100) / 44;
5010 }
5011 pstats->SignalQuality = precord_stats->SignalQuality = sq;
5012 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
5013 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
5014 }
5015 }
5016 else
5017 {
5018 priv->stats.numqry_phystatusHT++;
5019 //
5020 // (1)Get RSSI for HT rate
5021 //
5022 for(i=RF90_PATH_A; i<priv->NumTotalRFPath; i++)
5023 {
5024 // 2008/01/30 MH we will judge RF RX path now.
5025 if (priv->brfpath_rxenable[i])
5026 rf_rx_num++;
5027 else
5028 continue;
5029
5030 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
5031 continue;
5032
5033 //Fixed by Jacken from Bryant 2008-03-20
5034 //Original value is 106
5035 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
5036
5037 //Get Rx snr value in DB
5038 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
5039 rx_snrX = (char)(tmp_rxsnr);
Joe Perches859171c2010-11-14 19:04:48 -08005040 //rx_snrX >>= 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005041 rx_snrX /= 2;
5042 priv->stats.rxSNRdB[i] = (long)rx_snrX;
5043
5044 /* Translate DBM to percentage. */
5045 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
5046 total_rssi += RSSI;
5047
5048 /* Record Signal Strength for next packet */
5049 //if(bpacket_match_bssid)
5050 {
5051 pstats->RxMIMOSignalStrength[i] =(u8) RSSI;
5052 precord_stats->RxMIMOSignalStrength[i] =(u8) RSSI;
5053 }
5054 }
5055
5056
5057 //
5058 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
5059 //
5060 //Fixed by Jacken from Bryant 2008-03-20
5061 //Original value is 106
5062 rx_pwr_all = (((pofdm_buf->pwdb_all ) >> 1 )& 0x7f) -106;
5063 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
5064
5065 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
5066 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
5067
5068 //
5069 // (3)EVM of HT rate
5070 //
5071 if(pdrvinfo->RxHT && pdrvinfo->RxRate>=DESC90_RATEMCS8 &&
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005072 pdrvinfo->RxRate<=DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005073 max_spatial_stream = 2; //both spatial stream make sense
5074 else
5075 max_spatial_stream = 1; //only spatial stream 1 makes sense
5076
5077 for(i=0; i<max_spatial_stream; i++)
5078 {
5079 tmp_rxevm = pofdm_buf->rxevm_X[i];
5080 rx_evmX = (char)(tmp_rxevm);
5081
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005082 // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07005083 // will set the most significant bit to "zero" when doing shifting operation which may change a negative
Jerry Chuang8fc85982009-11-03 07:17:11 -02005084 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
5085 rx_evmX /= 2; //dbm
5086
5087 evm = rtl819x_evm_dbtopercentage(rx_evmX);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005088 //if(bpacket_match_bssid)
5089 {
5090 if(i==0) // Fill value in RFD, Get the first spatial stream only
5091 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
5092 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
5093 }
5094 }
5095
5096
5097 /* record rx statistics for debug */
5098 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
5099 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
5100 if(pdrvinfo->BW) //40M channel
5101 priv->stats.received_bwtype[1+prxsc->rxsc]++;
5102 else //20M channel
5103 priv->stats.received_bwtype[0]++;
5104 }
5105
5106 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
5107 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
5108 if(is_cck_rate)
5109 {
5110 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));//PWDB_ALL;
5111
5112 }
5113 else
5114 {
5115 //pRfd->Status.SignalStrength = pRecordRfd->Status.SignalStrength = (u8)(SignalScaleMapping(total_rssi/=RF90_PATH_MAX));//(u8)(total_rssi/=RF90_PATH_MAX);
5116 // We can judge RX path number now.
5117 if (rf_rx_num != 0)
5118 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi/=rf_rx_num)));
5119 }
5120} /* QueryRxPhyStatus8190Pci */
5121
5122void
5123rtl8192_record_rxdesc_forlateruse(
5124 struct ieee80211_rx_stats * psrc_stats,
5125 struct ieee80211_rx_stats * ptarget_stats
5126)
5127{
5128 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
5129 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
5130 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
5131}
5132
5133
5134void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
5135 struct ieee80211_rx_stats * pstats,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005136 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005137{
5138 // TODO: We must only check packet for current MAC address. Not finish
5139 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5140 struct net_device *dev=info->dev;
5141 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5142 bool bpacket_match_bssid, bpacket_toself;
5143 bool bPacketBeacon=FALSE, bToSelfBA=FALSE;
5144 static struct ieee80211_rx_stats previous_stats;
5145 struct ieee80211_hdr_3addr *hdr;//by amy
5146 u16 fc,type;
5147
5148 // Get Signal Quality for only RX data queue (but not command queue)
5149
5150 u8* tmp_buf;
5151 //u16 tmp_buf_len = 0;
5152 u8 *praddr;
5153
5154 /* Get MAC frame start address. */
5155 tmp_buf = (u8*)skb->data;// + get_rxpacket_shiftbytes_819xusb(pstats);
5156
5157 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
5158 fc = le16_to_cpu(hdr->frame_ctl);
5159 type = WLAN_FC_GET_TYPE(fc);
5160 praddr = hdr->addr1;
5161
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005162 /* Check if the received packet is acceptable. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005163 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005164 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
5165 && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02005166 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
5167
Jerry Chuang8fc85982009-11-03 07:17:11 -02005168 if(WLAN_FC_GET_FRAMETYPE(fc)== IEEE80211_STYPE_BEACON)
5169 {
5170 bPacketBeacon = true;
5171 //DbgPrint("Beacon 2, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
5172 }
5173 if(WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK)
5174 {
5175 if((eqMacAddr(praddr,dev->dev_addr)))
5176 bToSelfBA = true;
5177 //DbgPrint("BlockAck, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
5178 }
5179
Jerry Chuang8fc85982009-11-03 07:17:11 -02005180
5181
5182 if(bpacket_match_bssid)
5183 {
5184 priv->stats.numpacket_matchbssid++;
5185 }
5186 if(bpacket_toself){
5187 priv->stats.numpacket_toself++;
5188 }
5189 //
5190 // Process PHY information for previous packet (RSSI/PWDB/EVM)
5191 //
5192 // Because phy information is contained in the last packet of AMPDU only, so driver
5193 // should process phy information of previous packet
5194 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
5195 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid,bpacket_toself,bPacketBeacon,bToSelfBA);
5196 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
5197
5198}
5199
5200/**
5201* Function: UpdateReceivedRateHistogramStatistics
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07005202* Overview: Record the received data rate
Jerry Chuang8fc85982009-11-03 07:17:11 -02005203*
5204* Input:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005205* struct net_device *dev
Jerry Chuang8fc85982009-11-03 07:17:11 -02005206* struct ieee80211_rx_stats *stats
5207*
5208* Output:
5209*
5210* (priv->stats.ReceivedRateHistogram[] is updated)
5211* Return:
5212* None
5213*/
5214void
5215UpdateReceivedRateHistogramStatistics8190(
5216 struct net_device *dev,
5217 struct ieee80211_rx_stats *stats
5218 )
5219{
5220 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005221 u32 rcvType=1; //0: Total, 1:OK, 2:CRC, 3:ICV
5222 u32 rateIndex;
5223 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02005224
5225
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005226 if(stats->bCRC)
5227 rcvType = 2;
5228 else if(stats->bICV)
5229 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005230
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005231 if(stats->bShortPreamble)
5232 preamble_guardinterval = 1;// short
5233 else
5234 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02005235
5236 switch(stats->rate)
5237 {
5238 //
5239 // CCK rate
5240 //
5241 case MGN_1M: rateIndex = 0; break;
5242 case MGN_2M: rateIndex = 1; break;
5243 case MGN_5_5M: rateIndex = 2; break;
5244 case MGN_11M: rateIndex = 3; break;
5245 //
5246 // Legacy OFDM rate
5247 //
5248 case MGN_6M: rateIndex = 4; break;
5249 case MGN_9M: rateIndex = 5; break;
5250 case MGN_12M: rateIndex = 6; break;
5251 case MGN_18M: rateIndex = 7; break;
5252 case MGN_24M: rateIndex = 8; break;
5253 case MGN_36M: rateIndex = 9; break;
5254 case MGN_48M: rateIndex = 10; break;
5255 case MGN_54M: rateIndex = 11; break;
5256 //
5257 // 11n High throughput rate
5258 //
5259 case MGN_MCS0: rateIndex = 12; break;
5260 case MGN_MCS1: rateIndex = 13; break;
5261 case MGN_MCS2: rateIndex = 14; break;
5262 case MGN_MCS3: rateIndex = 15; break;
5263 case MGN_MCS4: rateIndex = 16; break;
5264 case MGN_MCS5: rateIndex = 17; break;
5265 case MGN_MCS6: rateIndex = 18; break;
5266 case MGN_MCS7: rateIndex = 19; break;
5267 case MGN_MCS8: rateIndex = 20; break;
5268 case MGN_MCS9: rateIndex = 21; break;
5269 case MGN_MCS10: rateIndex = 22; break;
5270 case MGN_MCS11: rateIndex = 23; break;
5271 case MGN_MCS12: rateIndex = 24; break;
5272 case MGN_MCS13: rateIndex = 25; break;
5273 case MGN_MCS14: rateIndex = 26; break;
5274 case MGN_MCS15: rateIndex = 27; break;
5275 default: rateIndex = 28; break;
5276 }
5277 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
5278 priv->stats.received_rate_histogram[0][rateIndex]++; //total
5279 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
5280}
5281
5282
5283void query_rxdesc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats, bool bIsRxAggrSubframe)
5284{
5285 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5286 struct net_device *dev=info->dev;
5287 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5288 //rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
5289 rx_drvinfo_819x_usb *driver_info = NULL;
5290
5291 //
5292 //Get Rx Descriptor Information
5293 //
5294#ifdef USB_RX_AGGREGATION_SUPPORT
5295 if (bIsRxAggrSubframe)
5296 {
5297 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
5298 stats->Length = desc->Length ;
5299 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
5300 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
5301 stats->bICV = desc->ICV;
5302 stats->bCRC = desc->CRC32;
5303 stats->bHwError = stats->bCRC|stats->bICV;
5304 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
5305 } else
5306#endif
5307 {
5308 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
5309
5310 stats->Length = desc->Length;
5311 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
5312 stats->RxBufShift = 0;//desc->Shift&0x03;
5313 stats->bICV = desc->ICV;
5314 stats->bCRC = desc->CRC32;
5315 stats->bHwError = stats->bCRC|stats->bICV;
5316 //RTL8190 set this bit to indicate that Hw does not decrypt packet
5317 stats->Decrypted = !desc->SWDec;
5318 }
5319
5320 if((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
5321 {
5322 stats->bHwError = false;
5323 }
5324 else
5325 {
5326 stats->bHwError = stats->bCRC|stats->bICV;
5327 }
5328
5329 if(stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
5330 stats->bHwError |= 1;
5331 //
5332 //Get Driver Info
5333 //
5334 // TODO: Need to verify it on FGPA platform
5335 //Driver info are written to the RxBuffer following rx desc
5336 if (stats->RxDrvInfoSize != 0) {
5337 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) + \
5338 stats->RxBufShift);
5339 /* unit: 0.5M */
5340 /* TODO */
5341 if(!stats->bHwError){
5342 u8 ret_rate;
5343 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
5344 if(ret_rate == 0xff)
5345 {
5346 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
5347 // Special Error Handling here, 2008.05.16, by Emily
5348
5349 stats->bHwError = 1;
5350 stats->rate = MGN_1M; //Set 1M rate by default
5351 }else
5352 {
5353 stats->rate = ret_rate;
5354 }
5355 }
5356 else
5357 stats->rate = 0x02;
5358
5359 stats->bShortPreamble = driver_info->SPLCP;
5360
5361
5362 UpdateReceivedRateHistogramStatistics8190(dev, stats);
5363
5364 stats->bIsAMPDU = (driver_info->PartAggr==1);
5365 stats->bFirstMPDU = (driver_info->PartAggr==1) && (driver_info->FirstAGGR==1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005366 stats->TimeStampLow = driver_info->TSFL;
5367 // xiong mask it, 070514
5368 //pRfd->Status.TimeStampHigh = PlatformEFIORead4Byte(Adapter, TSFR+4);
5369 // stats->TimeStampHigh = read_nic_dword(dev, TSFR+4);
5370
5371 UpdateRxPktTimeStamp8190(dev, stats);
5372
5373 //
5374 // Rx A-MPDU
5375 //
5376 if(driver_info->FirstAGGR==1 || driver_info->PartAggr == 1)
5377 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
5378 driver_info->FirstAGGR, driver_info->PartAggr);
5379
5380 }
5381
5382 skb_pull(skb,sizeof(rx_desc_819x_usb));
5383 //
5384 // Get Total offset of MPDU Frame Body
5385 //
5386 if((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
5387 stats->bShift = 1;
5388 skb_pull(skb,stats->RxBufShift + stats->RxDrvInfoSize);
5389 }
5390
5391#ifdef USB_RX_AGGREGATION_SUPPORT
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005392 /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005393 if(bIsRxAggrSubframe) {
5394 skb_pull(skb, 8);
5395 }
5396#endif
5397 /* for debug 2008.5.29 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005398
5399 //added by vivi, for MP, 20080108
5400 stats->RxIs40MHzPacket = driver_info->BW;
5401 if(stats->RxDrvInfoSize != 0)
5402 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
5403
5404}
5405
5406u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
5407{
5408#ifdef USB_RX_AGGREGATION_SUPPORT
5409 if (bIsRxAggrSubframe)
5410 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
5411 + Status->RxBufShift + 8);
5412 else
5413#endif
5414 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
5415 + Status->RxBufShift);
5416}
5417
5418void rtl8192_rx_nomal(struct sk_buff* skb)
5419{
5420 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5421 struct net_device *dev=info->dev;
5422 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5423 struct ieee80211_rx_stats stats = {
5424 .signal = 0,
5425 .noise = -98,
5426 .rate = 0,
5427 // .mac_time = jiffies,
5428 .freq = IEEE80211_24GHZ_BAND,
5429 };
5430 u32 rx_pkt_len = 0;
5431 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
5432 bool unicast_packet = false;
5433#ifdef USB_RX_AGGREGATION_SUPPORT
5434 struct sk_buff *agg_skb = NULL;
5435 u32 TotalLength = 0;
5436 u32 TempDWord = 0;
5437 u32 PacketLength = 0;
5438 u32 PacketOccupiedLendth = 0;
5439 u8 TempByte = 0;
5440 u32 PacketShiftBytes = 0;
5441 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
5442 u8 PaddingBytes = 0;
5443 //add just for testing
5444 u8 testing;
5445
5446#endif
5447
5448 /* 20 is for ps-poll */
5449 if((skb->len >=(20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
5450#ifdef USB_RX_AGGREGATION_SUPPORT
5451 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
5452#endif
5453 /* first packet should not contain Rx aggregation header */
5454 query_rxdesc_status(skb, &stats, false);
5455 /* TODO */
5456 /* hardware related info */
5457#ifdef USB_RX_AGGREGATION_SUPPORT
5458 if (TempByte & BIT0) {
5459 agg_skb = skb;
5460 //TotalLength = agg_skb->len - 4; /*sCrcLng*/
5461 TotalLength = stats.Length - 4; /*sCrcLng*/
5462 //RT_TRACE(COMP_RECV, "%s:first aggregated packet!Length=%d\n",__FUNCTION__,TotalLength);
5463 /* though the head pointer has passed this position */
5464 TempDWord = *(u32 *)(agg_skb->data - 4);
5465 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
5466 skb = dev_alloc_skb(PacketLength);
5467 memcpy(skb_put(skb,PacketLength),agg_skb->data,PacketLength);
5468 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
5469 }
5470#endif
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005471 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005472 skb_trim(skb, skb->len - 4/*sCrcLng*/);
5473
5474 rx_pkt_len = skb->len;
5475 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
5476 unicast_packet = false;
5477 if(is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
5478 //TODO
5479 }else if(is_multicast_ether_addr(ieee80211_hdr->addr1)){
5480 //TODO
5481 }else {
5482 /* unicast packet */
5483 unicast_packet = true;
5484 }
5485
5486 if(!ieee80211_rx(priv->ieee80211,skb, &stats)) {
5487 dev_kfree_skb_any(skb);
5488 } else {
5489 priv->stats.rxoktotal++;
5490 if(unicast_packet) {
5491 priv->stats.rxbytesunicast += rx_pkt_len;
5492 }
5493 }
5494#ifdef USB_RX_AGGREGATION_SUPPORT
5495 testing = 1;
5496 // (PipeIndex == 0) && (TempByte & BIT0) => TotalLength > 0.
5497 if (TotalLength > 0) {
5498 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
5499 if ((PacketOccupiedLendth & 0xFF) != 0)
5500 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
5501 PacketOccupiedLendth -= 8;
5502 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
5503 if (agg_skb->len > TempDWord)
5504 skb_pull(agg_skb, TempDWord);
5505 else
5506 agg_skb->len = 0;
5507
5508 while (agg_skb->len>=GetRxPacketShiftBytes819xUsb(&stats, true)) {
5509 u8 tmpCRC = 0, tmpICV = 0;
5510 //RT_TRACE(COMP_RECV,"%s:aggred pkt,total_len = %d\n",__FUNCTION__,agg_skb->len);
5511 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
5512 tmpCRC = RxDescr->CRC32;
5513 tmpICV = RxDescr->ICV;
5514 memcpy(agg_skb->data, &agg_skb->data[44], 2);
5515 RxDescr->CRC32 = tmpCRC;
5516 RxDescr->ICV = tmpICV;
5517
5518 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
5519 stats.signal = 0;
5520 stats.noise = -98;
5521 stats.rate = 0;
5522 stats.freq = IEEE80211_24GHZ_BAND;
5523 query_rxdesc_status(agg_skb, &stats, true);
5524 PacketLength = stats.Length;
5525
5526 if(PacketLength > agg_skb->len) {
5527 break;
5528 }
Justin P. Mattock589b3d02012-04-30 07:41:36 -07005529 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02005530 skb = dev_alloc_skb(PacketLength);
5531 memcpy(skb_put(skb,PacketLength),agg_skb->data, PacketLength);
5532 skb_trim(skb, skb->len - 4/*sCrcLng*/);
5533
5534 rx_pkt_len = skb->len;
5535 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
5536 unicast_packet = false;
5537 if(is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
5538 //TODO
5539 }else if(is_multicast_ether_addr(ieee80211_hdr->addr1)){
5540 //TODO
5541 }else {
5542 /* unicast packet */
5543 unicast_packet = true;
5544 }
5545 if(!ieee80211_rx(priv->ieee80211,skb, &stats)) {
5546 dev_kfree_skb_any(skb);
5547 } else {
5548 priv->stats.rxoktotal++;
5549 if(unicast_packet) {
5550 priv->stats.rxbytesunicast += rx_pkt_len;
5551 }
5552 }
5553 /* should trim the packet which has been copied to target skb */
5554 skb_pull(agg_skb, PacketLength);
5555 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
5556 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
5557 if ((PacketOccupiedLendth & 0xFF) != 0) {
5558 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
5559 if (agg_skb->len > PaddingBytes)
5560 skb_pull(agg_skb, PaddingBytes);
5561 else
5562 agg_skb->len = 0;
5563 }
5564 }
5565 dev_kfree_skb(agg_skb);
5566 }
5567#endif
5568 } else {
5569 priv->stats.rxurberr++;
5570 printk("actual_length:%d\n", skb->len);
5571 dev_kfree_skb_any(skb);
5572 }
5573
5574}
5575
5576void
5577rtl819xusb_process_received_packet(
5578 struct net_device *dev,
5579 struct ieee80211_rx_stats *pstats
5580 )
5581{
5582// bool bfreerfd=false, bqueued=false;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005583 u8* frame;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005584 u16 frame_len=0;
5585 struct r8192_priv *priv = ieee80211_priv(dev);
5586// u8 index = 0;
5587// u8 TID = 0;
5588 //u16 seqnum = 0;
5589 //PRX_TS_RECORD pts = NULL;
5590
5591 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
5592 //porting by amy 080508
5593 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
5594 frame = pstats->virtual_address;
5595 frame_len = pstats->packetlength;
5596#ifdef TODO // by amy about HCT
5597 if(!Adapter->bInHctTest)
5598 CountRxErrStatistics(Adapter, pRfd);
5599#endif
5600 {
5601 #ifdef ENABLE_PS //by amy for adding ps function in future
5602 RT_RF_POWER_STATE rtState;
5603 // When RF is off, we should not count the packet for hw/sw synchronize
5604 // reason, ie. there may be a duration while sw switch is changed and hw
5605 // switch is being changed. 2006.12.04, by shien chang.
5606 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8* )(&rtState));
5607 if (rtState == eRfOff)
5608 {
5609 return;
5610 }
5611 #endif
5612 priv->stats.rxframgment++;
5613
5614 }
5615#ifdef TODO
5616 RmMonitorSignalStrength(Adapter, pRfd);
5617#endif
5618 /* 2007/01/16 MH Add RX command packet handle here. */
5619 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
5620 if (rtl819xusb_rx_command_packet(dev, pstats))
5621 {
5622 return;
5623 }
5624
5625#ifdef SW_CRC_CHECK
5626 SwCrcCheck();
5627#endif
5628
5629
5630}
5631
5632void query_rx_cmdpkt_desc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats)
5633{
5634// rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5635// struct net_device *dev=info->dev;
5636// struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5637 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
5638// rx_drvinfo_819x_usb *driver_info;
5639
5640 //
5641 //Get Rx Descriptor Information
5642 //
5643 stats->virtual_address = (u8*)skb->data;
5644 stats->Length = desc->Length;
5645 stats->RxDrvInfoSize = 0;
5646 stats->RxBufShift = 0;
5647 stats->packetlength = stats->Length-scrclng;
5648 stats->fraglength = stats->packetlength;
5649 stats->fragoffset = 0;
5650 stats->ntotalfrag = 1;
5651}
5652
5653
5654void rtl8192_rx_cmd(struct sk_buff *skb)
5655{
5656 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5657 struct net_device *dev = info->dev;
5658 //int ret;
5659// struct urb *rx_urb = info->urb;
5660 /* TODO */
5661 struct ieee80211_rx_stats stats = {
5662 .signal = 0,
5663 .noise = -98,
5664 .rate = 0,
5665 // .mac_time = jiffies,
5666 .freq = IEEE80211_24GHZ_BAND,
5667 };
5668
5669 if((skb->len >=(20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE))
5670 {
5671
5672 query_rx_cmdpkt_desc_status(skb,&stats);
5673 // this is to be done by amy 080508 prfd->queue_id = 1;
5674
5675
5676 //
5677 // Process the command packet received.
5678 //
5679
5680 rtl819xusb_process_received_packet(dev,&stats);
5681
5682 dev_kfree_skb_any(skb);
5683 }
5684 else
5685 ;
5686
5687
Jerry Chuang8fc85982009-11-03 07:17:11 -02005688}
5689
5690void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
5691{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005692 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005693 struct rtl8192_rx_info *info;
5694
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005695 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005696 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005697 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005698 /* Nomal packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005699 case 3:
5700 //RT_TRACE(COMP_RECV, "normal in-pipe index(%d)\n",info->out_pipe);
5701 priv->IrpPendingCount--;
5702 rtl8192_rx_nomal(skb);
5703 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005704
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005705 /* Command packet pipe */
5706 case 9:
5707 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",\
5708 info->out_pipe);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005709
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005710 rtl8192_rx_cmd(skb);
5711 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005712
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005713 default: /* should never get here! */
5714 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",\
5715 info->out_pipe);
5716 dev_kfree_skb(skb);
5717 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005718
5719 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005720 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005721}
5722
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005723static const struct net_device_ops rtl8192_netdev_ops = {
5724 .ndo_open = rtl8192_open,
5725 .ndo_stop = rtl8192_close,
5726 .ndo_get_stats = rtl8192_stats,
5727 .ndo_tx_timeout = tx_timeout,
5728 .ndo_do_ioctl = rtl8192_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00005729 .ndo_set_rx_mode = r8192_set_multicast,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005730 .ndo_set_mac_address = r8192_set_mac_adr,
5731 .ndo_validate_addr = eth_validate_addr,
5732 .ndo_change_mtu = eth_change_mtu,
5733 .ndo_start_xmit = ieee80211_xmit,
5734};
Jerry Chuang8fc85982009-11-03 07:17:11 -02005735
5736
5737/****************************************************************************
5738 ---------------------------- USB_STUFF---------------------------
5739*****************************************************************************/
5740
Bill Pemberton25794522012-11-19 13:22:04 -05005741static int rtl8192_usb_probe(struct usb_interface *intf,
Jerry Chuang8fc85982009-11-03 07:17:11 -02005742 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005743{
5744// unsigned long ioaddr = 0;
5745 struct net_device *dev = NULL;
5746 struct r8192_priv *priv= NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005747 struct usb_device *udev = interface_to_usbdev(intf);
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005748 int ret;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005749 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005750
5751 dev = alloc_ieee80211(sizeof(struct r8192_priv));
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005752 if (dev == NULL)
5753 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005754
Jerry Chuang8fc85982009-11-03 07:17:11 -02005755 usb_set_intfdata(intf, dev);
5756 SET_NETDEV_DEV(dev, &intf->dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005757 priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005758 priv->ieee80211 = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005759 priv->udev=udev;
5760
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005761 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005762
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005763 //DMESG("Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005764#if WIRELESS_EXT >= 12
5765#if WIRELESS_EXT < 17
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005766 dev->get_wireless_stats = r8192_get_wireless_stats;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005767#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005768 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005769#endif
5770 dev->type=ARPHRD_ETHER;
5771
5772 dev->watchdog_timeo = HZ*3; //modified by john, 0805
5773
5774 if (dev_alloc_name(dev, ifname) < 0){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005775 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005776 ifname = "wlan%d";
5777 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005778 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005779
5780 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005781 if(rtl8192_init(dev)!=0){
5782 RT_TRACE(COMP_ERR, "Initialization failed");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005783 ret = -ENODEV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005784 goto fail;
5785 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005786 netif_carrier_off(dev);
5787 netif_stop_queue(dev);
5788
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005789 ret = register_netdev(dev);
5790 if (ret)
5791 goto fail2;
5792
Jerry Chuang8fc85982009-11-03 07:17:11 -02005793 RT_TRACE(COMP_INIT, "dev name=======> %s\n",dev->name);
5794 rtl8192_proc_init_one(dev);
5795
5796
5797 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005798 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005799
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005800fail2:
5801 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005802 kfree(priv->pFirmware);
5803 priv->pFirmware = NULL;
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005804 rtl8192_usb_deleteendpoints(dev);
5805 destroy_workqueue(priv->priv_wq);
5806 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005807fail:
5808 free_ieee80211(dev);
5809
5810 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005811 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005812}
5813
5814//detach all the work and timer structure declared or inititialize in r8192U_init function.
5815void rtl8192_cancel_deferred_work(struct r8192_priv* priv)
5816{
5817
Jerry Chuang8fc85982009-11-03 07:17:11 -02005818 cancel_work_sync(&priv->reset_wq);
5819 cancel_delayed_work(&priv->watch_dog_wq);
5820 cancel_delayed_work(&priv->update_beacon_wq);
5821 cancel_work_sync(&priv->qos_activate);
5822 //cancel_work_sync(&priv->SetBWModeWorkItem);
5823 //cancel_work_sync(&priv->SwChnlWorkItem);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005824
5825}
5826
5827
Bill Pembertona4a557e2012-11-19 13:26:46 -05005828static void rtl8192_usb_disconnect(struct usb_interface *intf)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005829{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005830 struct net_device *dev = usb_get_intfdata(intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005831
5832 struct r8192_priv *priv = ieee80211_priv(dev);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005833 if(dev){
Jerry Chuang8fc85982009-11-03 07:17:11 -02005834
5835 unregister_netdev(dev);
5836
5837 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
5838 rtl8192_proc_remove_one(dev);
5839
5840 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005841 kfree(priv->pFirmware);
5842 priv->pFirmware = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005843 // priv->rf_close(dev);
5844// rtl8192_SetRFPowerState(dev, eRfOff);
5845 rtl8192_usb_deleteendpoints(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005846 destroy_workqueue(priv->priv_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005847 //rtl8192_irq_disable(dev);
5848 //rtl8192_reset(dev);
5849 mdelay(10);
5850
5851 }
5852 free_ieee80211(dev);
5853 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
5854}
5855
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005856/* fun with the built-in ieee80211 stack... */
5857extern int ieee80211_debug_init(void);
5858extern void ieee80211_debug_exit(void);
5859extern int ieee80211_crypto_init(void);
5860extern void ieee80211_crypto_deinit(void);
5861extern int ieee80211_crypto_tkip_init(void);
5862extern void ieee80211_crypto_tkip_exit(void);
5863extern int ieee80211_crypto_ccmp_init(void);
5864extern void ieee80211_crypto_ccmp_exit(void);
5865extern int ieee80211_crypto_wep_init(void);
5866extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005867
5868static int __init rtl8192_usb_module_init(void)
5869{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005870 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005871
5872#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005873 ret = ieee80211_debug_init();
5874 if (ret) {
5875 printk(KERN_ERR "ieee80211_debug_init() failed %d\n", ret);
5876 return ret;
5877 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005878#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005879 ret = ieee80211_crypto_init();
5880 if (ret) {
5881 printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret);
5882 return ret;
5883 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005884
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005885 ret = ieee80211_crypto_tkip_init();
5886 if (ret) {
5887 printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n",
5888 ret);
5889 return ret;
5890 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005891
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005892 ret = ieee80211_crypto_ccmp_init();
5893 if (ret) {
5894 printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n",
5895 ret);
5896 return ret;
5897 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005898
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005899 ret = ieee80211_crypto_wep_init();
5900 if (ret) {
5901 printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret);
5902 return ret;
5903 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005904
Jerry Chuang8fc85982009-11-03 07:17:11 -02005905 printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n");
5906 printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n");
5907 RT_TRACE(COMP_INIT, "Initializing module");
5908 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
5909 rtl8192_proc_module_init();
5910 return usb_register(&rtl8192_usb_driver);
5911}
5912
5913
5914static void __exit rtl8192_usb_module_exit(void)
5915{
5916 usb_deregister(&rtl8192_usb_driver);
5917
5918 RT_TRACE(COMP_DOWN, "Exiting");
5919// rtl8192_proc_module_remove();
5920}
5921
5922
5923void rtl8192_try_wake_queue(struct net_device *dev, int pri)
5924{
5925 unsigned long flags;
5926 short enough_desc;
5927 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5928
5929 spin_lock_irqsave(&priv->tx_lock,flags);
5930 enough_desc = check_nic_enough_desc(dev,pri);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005931 spin_unlock_irqrestore(&priv->tx_lock,flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005932
5933 if(enough_desc)
5934 ieee80211_wake_queue(priv->ieee80211);
5935}
5936
5937void EnableHWSecurityConfig8192(struct net_device *dev)
5938{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005939 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005940 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5941 struct ieee80211_device* ieee = priv->ieee80211;
5942 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005943 if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->ieee80211->auth_mode != 2))
5944 {
5945 SECR_value |= SCR_RxUseDK;
5946 SECR_value |= SCR_TxUseDK;
5947 }
5948 else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP)))
5949 {
5950 SECR_value |= SCR_RxUseDK;
5951 SECR_value |= SCR_TxUseDK;
5952 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005953 //add HWSec active enable here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02005954//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
5955
5956 ieee->hwsec_active = 1;
5957
5958 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
5959 {
5960 ieee->hwsec_active = 0;
5961 SECR_value &= ~SCR_RxDecEnable;
5962 }
5963 RT_TRACE(COMP_SEC,"%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __FUNCTION__, \
5964 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
5965 {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005966 write_nic_byte(dev, SECR, SECR_value);//SECR_value | SCR_UseDK );
5967 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005968}
5969
5970
5971void setKey( struct net_device *dev,
5972 u8 EntryNo,
5973 u8 KeyIndex,
5974 u16 KeyType,
5975 u8 *MacAddr,
5976 u8 DefaultKey,
5977 u32 *KeyContent )
5978{
5979 u32 TargetCommand = 0;
5980 u32 TargetContent = 0;
5981 u16 usConfig = 0;
5982 u8 i;
5983 if (EntryNo >= TOTAL_CAM_ENTRY)
5984 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
5985
Joe Perches0ee9f672009-12-06 11:34:52 -08005986 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 -02005987
5988 if (DefaultKey)
5989 usConfig |= BIT15 | (KeyType<<2);
5990 else
5991 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
5992// usConfig |= BIT15 | (KeyType<<2) | (DefaultKey<<5) | KeyIndex;
5993
5994
5995 for(i=0 ; i<CAM_CONTENT_COUNT; i++){
5996 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
5997 TargetCommand |= BIT31|BIT16;
5998
5999 if(i==0){//MAC|Config
6000 TargetContent = (u32)(*(MacAddr+0)) << 16|
6001 (u32)(*(MacAddr+1)) << 24|
6002 (u32)usConfig;
6003
6004 write_nic_dword(dev, WCAMI, TargetContent);
6005 write_nic_dword(dev, RWCAM, TargetCommand);
6006 // printk("setkey cam =%8x\n", read_cam(dev, i+6*EntryNo));
6007 }
6008 else if(i==1){//MAC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01006009 TargetContent = (u32)(*(MacAddr+2)) |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02006010 (u32)(*(MacAddr+3)) << 8|
6011 (u32)(*(MacAddr+4)) << 16|
6012 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02006013 write_nic_dword(dev, WCAMI, TargetContent);
6014 write_nic_dword(dev, RWCAM, TargetCommand);
6015 }
6016 else {
6017 //Key Material
6018 if(KeyContent !=NULL){
6019 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)) );
6020 write_nic_dword(dev, RWCAM, TargetCommand);
6021 }
6022 }
6023 }
6024
6025}
6026
6027/***************************************************************************
6028 ------------------- module init / exit stubs ----------------
6029****************************************************************************/
6030module_init(rtl8192_usb_module_init);
6031module_exit(rtl8192_usb_module_exit);