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