• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/rtl8192e/ieee80211/
1/******************************************************************************
2
3  Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
4
5  This program is free software; you can redistribute it and/or modify it
6  under the terms of version 2 of the GNU General Public License as
7  published by the Free Software Foundation.
8
9  This program is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  more details.
13
14  You should have received a copy of the GNU General Public License along with
15  this program; if not, write to the Free Software Foundation, Inc., 59
16  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18  The full GNU General Public License is included in this distribution in the
19  file called LICENSE.
20
21  Contact Information:
22  James P. Ketrenos <ipw2100-admin@linux.intel.com>
23  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24
25******************************************************************************
26
27  Few modifications for Realtek's Wi-Fi drivers by
28  Andrea Merello <andreamrl@tiscali.it>
29
30  A special thanks goes to Realtek for their support !
31
32******************************************************************************/
33
34#include <linux/compiler.h>
35//#include <linux/config.h>
36#include <linux/errno.h>
37#include <linux/if_arp.h>
38#include <linux/in6.h>
39#include <linux/in.h>
40#include <linux/ip.h>
41#include <linux/kernel.h>
42#include <linux/module.h>
43#include <linux/netdevice.h>
44#include <linux/pci.h>
45#include <linux/proc_fs.h>
46#include <linux/skbuff.h>
47#include <linux/slab.h>
48#include <linux/tcp.h>
49#include <linux/types.h>
50#include <linux/version.h>
51#include <linux/wireless.h>
52#include <linux/etherdevice.h>
53#include <asm/uaccess.h>
54#include <linux/if_vlan.h>
55
56#include "ieee80211.h"
57
58
59/*
60
61
62802.11 Data Frame
63
64
65802.11 frame_contorl for data frames - 2 bytes
66     ,-----------------------------------------------------------------------------------------.
67bits | 0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  a  |  b  |  c  |  d  |  e   |
68     |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
69val  | 0  |  0  |  0  |  1  |  x  |  0  |  0  |  0  |  1  |  0  |  x  |  x  |  x  |  x  |  x   |
70     |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
71desc | ^-ver-^  |  ^type-^  |  ^-----subtype-----^  | to  |from |more |retry| pwr |more |wep   |
72     |          |           | x=0 data,x=1 data+ack | DS  | DS  |frag |     | mgm |data |      |
73     '-----------------------------------------------------------------------------------------'
74		                                    /\
75                                                    |
76802.11 Data Frame                                   |
77           ,--------- 'ctrl' expands to >-----------'
78          |
79      ,--'---,-------------------------------------------------------------.
80Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
81      |------|------|---------|---------|---------|------|---------|------|
82Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  Frame  |  fcs |
83      |      | tion | (BSSID) |         |         | ence |  data   |      |
84      `--------------------------------------------------|         |------'
85Total: 28 non-data bytes                                 `----.----'
86                                                              |
87       .- 'Frame data' expands to <---------------------------'
88       |
89       V
90      ,---------------------------------------------------.
91Bytes |  1   |  1   |    1    |    3     |  2   |  0-2304 |
92      |------|------|---------|----------|------|---------|
93Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP      |
94      | DSAP | SSAP |         |          |      | Packet  |
95      | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8|      |         |
96      `-----------------------------------------|         |
97Total: 8 non-data bytes                         `----.----'
98                                                     |
99       .- 'IP Packet' expands, if WEP enabled, to <--'
100       |
101       V
102      ,-----------------------.
103Bytes |  4  |   0-2296  |  4  |
104      |-----|-----------|-----|
105Desc. | IV  | Encrypted | ICV |
106      |     | IP Packet |     |
107      `-----------------------'
108Total: 8 non-data bytes
109
110
111802.3 Ethernet Data Frame
112
113      ,-----------------------------------------.
114Bytes |   6   |   6   |  2   |  Variable |   4  |
115      |-------|-------|------|-----------|------|
116Desc. | Dest. | Source| Type | IP Packet |  fcs |
117      |  MAC  |  MAC  |      |           |      |
118      `-----------------------------------------'
119Total: 18 non-data bytes
120
121In the event that fragmentation is required, the incoming payload is split into
122N parts of size ieee->fts.  The first fragment contains the SNAP header and the
123remaining packets are just data.
124
125If encryption is enabled, each fragment payload size is reduced by enough space
126to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
127So if you have 1500 bytes of payload with ieee->fts set to 500 without
128encryption it will take 3 frames.  With WEP it will take 4 frames as the
129payload of each frame is reduced to 492 bytes.
130
131* SKB visualization
132*
133*  ,- skb->data
134* |
135* |    ETHERNET HEADER        ,-<-- PAYLOAD
136* |                           |     14 bytes from skb->data
137* |  2 bytes for Type --> ,T. |     (sizeof ethhdr)
138* |                       | | |
139* |,-Dest.--. ,--Src.---. | | |
140* |  6 bytes| | 6 bytes | | | |
141* v         | |         | | | |
142* 0         | v       1 | v | v           2
143* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
144*     ^     | ^         | ^ |
145*     |     | |         | | |
146*     |     | |         | `T' <---- 2 bytes for Type
147*     |     | |         |
148*     |     | '---SNAP--' <-------- 6 bytes for SNAP
149*     |     |
150*     `-IV--' <-------------------- 4 bytes for IV (WEP)
151*
152*      SNAP HEADER
153*
154*/
155
156static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
157static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
158
159static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
160{
161	struct ieee80211_snap_hdr *snap;
162	u8 *oui;
163
164	snap = (struct ieee80211_snap_hdr *)data;
165	snap->dsap = 0xaa;
166	snap->ssap = 0xaa;
167	snap->ctrl = 0x03;
168
169	if (h_proto == 0x8137 || h_proto == 0x80f3)
170		oui = P802_1H_OUI;
171	else
172		oui = RFC1042_OUI;
173	snap->oui[0] = oui[0];
174	snap->oui[1] = oui[1];
175	snap->oui[2] = oui[2];
176
177	*(u16 *)(data + SNAP_SIZE) = htons(h_proto);
178
179	return SNAP_SIZE + sizeof(u16);
180}
181
182int ieee80211_encrypt_fragment(
183	struct ieee80211_device *ieee,
184	struct sk_buff *frag,
185	int hdr_len)
186{
187	struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
188	int res;
189
190	if (!(crypt && crypt->ops))
191	{
192		printk("=========>%s(), crypt is null\n", __FUNCTION__);
193		return -1;
194	}
195#ifdef CONFIG_IEEE80211_CRYPT_TKIP
196	struct ieee80211_hdr *header;
197
198	if (ieee->tkip_countermeasures &&
199	    crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
200		header = (struct ieee80211_hdr *) frag->data;
201		if (net_ratelimit()) {
202			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
203			       "TX packet to %pM\n",
204			       ieee->dev->name, header->addr1);
205		}
206		return -1;
207	}
208#endif
209	/* To encrypt, frame format is:
210	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
211
212	/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
213	 * call both MSDU and MPDU encryption functions from here. */
214	atomic_inc(&crypt->refcnt);
215	res = 0;
216	if (crypt->ops->encrypt_msdu)
217		res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
218	if (res == 0 && crypt->ops->encrypt_mpdu)
219		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
220
221	atomic_dec(&crypt->refcnt);
222	if (res < 0) {
223		printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
224		       ieee->dev->name, frag->len);
225		ieee->ieee_stats.tx_discards++;
226		return -1;
227	}
228
229	return 0;
230}
231
232
233void ieee80211_txb_free(struct ieee80211_txb *txb) {
234	//int i;
235	if (unlikely(!txb))
236		return;
237	kfree(txb);
238}
239
240struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
241					  int gfp_mask)
242{
243	struct ieee80211_txb *txb;
244	int i;
245	txb = kmalloc(
246		sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags),
247		gfp_mask);
248	if (!txb)
249		return NULL;
250
251	memset(txb, 0, sizeof(struct ieee80211_txb));
252	txb->nr_frags = nr_frags;
253	txb->frag_size = txb_size;
254
255	for (i = 0; i < nr_frags; i++) {
256		txb->fragments[i] = dev_alloc_skb(txb_size);
257		if (unlikely(!txb->fragments[i])) {
258			i--;
259			break;
260		}
261		memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb));
262	}
263	if (unlikely(i != nr_frags)) {
264		while (i >= 0)
265			dev_kfree_skb_any(txb->fragments[i--]);
266		kfree(txb);
267		return NULL;
268	}
269	return txb;
270}
271
272// Classify the to-be send data packet
273// Need to acquire the sent queue index.
274static int
275ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network)
276{
277	struct ethhdr *eth;
278	struct iphdr *ip;
279	eth = (struct ethhdr *)skb->data;
280	if (eth->h_proto != htons(ETH_P_IP))
281		return 0;
282
283	ip = ip_hdr(skb);
284	switch (ip->tos & 0xfc) {
285		case 0x20:
286			return 2;
287		case 0x40:
288			return 1;
289		case 0x60:
290			return 3;
291		case 0x80:
292			return 4;
293		case 0xa0:
294			return 5;
295		case 0xc0:
296			return 6;
297		case 0xe0:
298			return 7;
299		default:
300			return 0;
301	}
302}
303
304#define SN_LESS(a, b)		(((a-b)&0x800)!=0)
305void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc)
306{
307	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
308	PTX_TS_RECORD			pTxTs = NULL;
309	struct ieee80211_hdr_1addr* hdr = (struct ieee80211_hdr_1addr*)skb->data;
310
311	if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
312		return;
313	if (!IsQoSDataFrame(skb->data))
314		return;
315
316	if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1))
317		return;
318	//check packet and mode later
319#ifdef TO_DO_LIST
320	if(pTcb->PacketLength >= 4096)
321		return;
322	// For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation.
323	if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
324		return;
325#endif
326
327        if(tcb_desc->bdhcp)// || ieee->CntAfterLink<2)
328        {
329                return;
330        }
331
332
333	if(!ieee->GetNmodeSupportBySecCfg(ieee->dev))
334	{
335		return;
336	}
337	if(pHTInfo->bCurrentAMPDUEnable)
338	{
339		if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true))
340		{
341			printk("===>can't get TS\n");
342			return;
343		}
344		if (pTxTs->TxAdmittedBARecord.bValid == false)
345		{
346			//as some AP will refuse our action frame until key handshake has been finished. WB
347			if (ieee->wpa_ie_len && (ieee->pairwise_key_type == KEY_TYPE_NA))
348			;
349			else
350			TsStartAddBaProcess(ieee, pTxTs);
351			goto FORCED_AGG_SETTING;
352		}
353		else if (pTxTs->bUsingBa == false)
354		{
355			if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096))
356				pTxTs->bUsingBa = true;
357			else
358				goto FORCED_AGG_SETTING;
359		}
360
361		if (ieee->iw_mode == IW_MODE_INFRA)
362		{
363			tcb_desc->bAMPDUEnable = true;
364			tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
365			tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
366		}
367	}
368FORCED_AGG_SETTING:
369	switch(pHTInfo->ForcedAMPDUMode )
370	{
371		case HT_AGG_AUTO:
372			break;
373
374		case HT_AGG_FORCE_ENABLE:
375			tcb_desc->bAMPDUEnable = true;
376			tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
377			tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
378			break;
379
380		case HT_AGG_FORCE_DISABLE:
381			tcb_desc->bAMPDUEnable = false;
382			tcb_desc->ampdu_density = 0;
383			tcb_desc->ampdu_factor = 0;
384			break;
385
386	}
387		return;
388}
389
390extern void ieee80211_qurey_ShortPreambleMode(struct ieee80211_device* ieee, cb_desc* tcb_desc)
391{
392	tcb_desc->bUseShortPreamble = false;
393	if (tcb_desc->data_rate == 2)
394	{//// 1M can only use Long Preamble. 11B spec
395		return;
396	}
397	else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
398	{
399		tcb_desc->bUseShortPreamble = true;
400	}
401	return;
402}
403extern	void
404ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, cb_desc *tcb_desc)
405{
406	PRT_HIGH_THROUGHPUT		pHTInfo = ieee->pHTInfo;
407
408	tcb_desc->bUseShortGI 		= false;
409
410	if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
411		return;
412
413	if(pHTInfo->bForcedShortGI)
414	{
415		tcb_desc->bUseShortGI = true;
416		return;
417	}
418
419	if((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz)
420		tcb_desc->bUseShortGI = true;
421	else if((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz)
422		tcb_desc->bUseShortGI = true;
423}
424
425void ieee80211_query_BandwidthMode(struct ieee80211_device* ieee, cb_desc *tcb_desc)
426{
427	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
428
429	tcb_desc->bPacketBW = false;
430
431	if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
432		return;
433
434	if(tcb_desc->bMulticast || tcb_desc->bBroadcast)
435		return;
436
437	if((tcb_desc->data_rate & 0x80)==0) // If using legacy rate, it shall use 20MHz channel.
438		return;
439	//BandWidthAutoSwitch is for auto switch to 20 or 40 in long distance
440	if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
441		tcb_desc->bPacketBW = true;
442	return;
443}
444
445void ieee80211_query_protectionmode(struct ieee80211_device* ieee, cb_desc* tcb_desc, struct sk_buff* skb)
446{
447	// Common Settings
448	tcb_desc->bRTSSTBC			= false;
449	tcb_desc->bRTSUseShortGI		= false; // Since protection frames are always sent by legacy rate, ShortGI will never be used.
450	tcb_desc->bCTSEnable			= false; // Most of protection using RTS/CTS
451	tcb_desc->RTSSC				= 0;		// 20MHz: Don't care;  40MHz: Duplicate.
452	tcb_desc->bRTSBW			= false; // RTS frame bandwidth is always 20MHz
453
454	if(tcb_desc->bBroadcast || tcb_desc->bMulticast)//only unicast frame will use rts/cts
455		return;
456
457	if (is_broadcast_ether_addr(skb->data+16))  //check addr3 as infrastructure add3 is DA.
458		return;
459
460	if (ieee->mode < IEEE_N_24G) //b, g mode
461	{
462			// (1) RTS_Threshold is compared to the MPDU, not MSDU.
463			// (2) If there are more than one frag in  this MSDU, only the first frag uses protection frame.
464			//		Other fragments are protected by previous fragment.
465			//		So we only need to check the length of first fragment.
466		if (skb->len > ieee->rts)
467		{
468			tcb_desc->bRTSEnable = true;
469			tcb_desc->rts_rate = MGN_24M;
470		}
471		else if (ieee->current_network.buseprotection)
472		{
473			// Use CTS-to-SELF in protection mode.
474			tcb_desc->bRTSEnable = true;
475			tcb_desc->bCTSEnable = true;
476			tcb_desc->rts_rate = MGN_24M;
477		}
478		//otherwise return;
479		return;
480	}
481	else
482	{// 11n High throughput case.
483		PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
484		while (true)
485		{
486			//check ERP protection
487			if (ieee->current_network.buseprotection)
488			{// CTS-to-SELF
489				tcb_desc->bRTSEnable = true;
490				tcb_desc->bCTSEnable = true;
491				tcb_desc->rts_rate = MGN_24M;
492				break;
493			}
494			//check HT op mode
495			if(pHTInfo->bCurrentHTSupport  && pHTInfo->bEnableHT)
496			{
497				u8 HTOpMode = pHTInfo->CurrentOpMode;
498				if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) ||
499							(!pHTInfo->bCurBW40MHz && HTOpMode == 3) )
500				{
501					tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
502					tcb_desc->bRTSEnable = true;
503					break;
504				}
505			}
506			//check rts
507			if (skb->len > ieee->rts)
508			{
509				tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
510				tcb_desc->bRTSEnable = true;
511				break;
512			}
513			//to do list: check MIMO power save condition.
514			//check AMPDU aggregation for TXOP
515			if(tcb_desc->bAMPDUEnable)
516			{
517				tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
518				// According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads
519				// throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily
520				tcb_desc->bRTSEnable = false;
521				break;
522			}
523			//check IOT action
524			if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF)
525			{
526				tcb_desc->bCTSEnable	= true;
527				tcb_desc->rts_rate  = 	MGN_24M;
528				tcb_desc->bRTSEnable = true;
529				break;
530			}
531			// Totally no protection case!!
532			goto NO_PROTECTION;
533		}
534		}
535	// For test , CTS replace with RTS
536	if( 0 )
537	{
538		tcb_desc->bCTSEnable	= true;
539		tcb_desc->rts_rate = MGN_24M;
540		tcb_desc->bRTSEnable 	= true;
541	}
542	if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
543		tcb_desc->bUseShortPreamble = true;
544	if (ieee->mode == IW_MODE_MASTER)
545			goto NO_PROTECTION;
546	return;
547NO_PROTECTION:
548	tcb_desc->bRTSEnable	= false;
549	tcb_desc->bCTSEnable	= false;
550	tcb_desc->rts_rate		= 0;
551	tcb_desc->RTSSC		= 0;
552	tcb_desc->bRTSBW		= false;
553}
554
555
556void ieee80211_txrate_selectmode(struct ieee80211_device* ieee, cb_desc* tcb_desc)
557{
558#ifdef TO_DO_LIST
559	if(!IsDataFrame(pFrame))
560	{
561		pTcb->bTxDisableRateFallBack = TRUE;
562		pTcb->bTxUseDriverAssingedRate = TRUE;
563		pTcb->RATRIndex = 7;
564		return;
565	}
566
567	if(pMgntInfo->ForcedDataRate!= 0)
568	{
569		pTcb->bTxDisableRateFallBack = TRUE;
570		pTcb->bTxUseDriverAssingedRate = TRUE;
571		return;
572	}
573#endif
574	if(ieee->bTxDisableRateFallBack)
575		tcb_desc->bTxDisableRateFallBack = true;
576
577	if(ieee->bTxUseDriverAssingedRate)
578		tcb_desc->bTxUseDriverAssingedRate = true;
579	if(!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate)
580	{
581		if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
582			tcb_desc->RATRIndex = 0;
583	}
584}
585
586void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u8* dst)
587{
588	if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst))
589		return;
590	if (IsQoSDataFrame(skb->data)) //we deal qos data only
591	{
592		PTX_TS_RECORD pTS = NULL;
593		if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTS), dst, skb->priority, TX_DIR, true))
594		{
595			return;
596		}
597		pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
598	}
599}
600
601int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
602{
603	struct ieee80211_device *ieee = netdev_priv(dev);
604	struct ieee80211_txb *txb = NULL;
605	struct ieee80211_hdr_3addrqos *frag_hdr;
606	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
607	unsigned long flags;
608	struct net_device_stats *stats = &ieee->stats;
609	int ether_type = 0, encrypt;
610	int bytes, fc, qos_ctl = 0, hdr_len;
611	struct sk_buff *skb_frag;
612	struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */
613		.duration_id = 0,
614		.seq_ctl = 0,
615		.qos_ctl = 0
616	};
617	u8 dest[ETH_ALEN], src[ETH_ALEN];
618	int qos_actived = ieee->current_network.qos_data.active;
619
620	struct ieee80211_crypt_data* crypt;
621	bool    bdhcp =false;
622
623	cb_desc *tcb_desc;
624
625	spin_lock_irqsave(&ieee->lock, flags);
626
627	/* If there is no driver handler to take the TXB, dont' bother
628	 * creating it... */
629	if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))||
630	   ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
631		printk(KERN_WARNING "%s: No xmit handler.\n",
632		       ieee->dev->name);
633		goto success;
634	}
635
636
637	if(likely(ieee->raw_tx == 0)){
638		if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
639			printk(KERN_WARNING "%s: skb too small (%d).\n",
640			ieee->dev->name, skb->len);
641			goto success;
642		}
643
644		memset(skb->cb, 0, sizeof(skb->cb));
645		ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
646
647		crypt = ieee->crypt[ieee->tx_keyidx];
648
649		encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
650			ieee->host_encrypt && crypt && crypt->ops;
651
652		if (!encrypt && ieee->ieee802_1x &&
653		ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
654			stats->tx_dropped++;
655			goto success;
656		}
657	#ifdef CONFIG_IEEE80211_DEBUG
658		if (crypt && !encrypt && ether_type == ETH_P_PAE) {
659			struct eapol *eap = (struct eapol *)(skb->data +
660				sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
661			IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
662				eap_get_type(eap->type));
663		}
664	#endif
665
666		// The following is for DHCP and ARP packet, we use cck1M to tx these packets and let LPS awake some time
667		// to prevent DHCP protocol fail
668		if (skb->len > 282){//MINIMUM_DHCP_PACKET_SIZE) {
669			if (ETH_P_IP == ether_type) {// IP header
670				const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14);
671				if (IPPROTO_UDP == ip->protocol) {
672					struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
673					//if(((ntohs(udp->source) == 68) && (ntohs(udp->dest) == 67)) ||
674					///   ((ntohs(udp->source) == 67) && (ntohs(udp->dest) == 68))) {
675					if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) ||
676							((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) {
677						// 68 : UDP BOOTP client
678						// 67 : UDP BOOTP server
679						printk("DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]);
680						// Use low rate to send DHCP packet.
681						//if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
682						//{
683						//      tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m
684						//      tcb_desc->bTxDisableRateFallBack = false;
685						//}
686						//else
687						//pTcb->DataRate = Adapter->MgntInfo.LowestBasicRate;
688						//RTPRINT(FDM, WA_IOT, ("DHCP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate));
689
690						bdhcp = true;
691#ifdef _RTL8192_EXT_PATCH_
692						ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2; //AMY,090701
693#else
694						ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2;
695#endif
696					}
697				}
698				}else if(ETH_P_ARP == ether_type){// IP ARP packet
699					printk("=================>DHCP Protocol start tx ARP pkt!!\n");
700					bdhcp = true;
701					ieee->LPSDelayCnt = ieee->current_network.tim.tim_count;
702
703					//if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
704					//{
705					//      tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(Adapter->MgntInfo.mBrates);//0xc;//ofdm 6m
706					//      tcb_desc->bTxDisableRateFallBack = FALSE;
707					//}
708					//else
709					//      tcb_desc->DataRate = Adapter->MgntInfo.LowestBasicRate;
710					//RTPRINT(FDM, WA_IOT, ("ARP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate));
711
712				}
713			}
714
715		/* Save source and destination addresses */
716		memcpy(&dest, skb->data, ETH_ALEN);
717		memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
718
719                /* Advance the SKB to the start of the payload */
720                skb_pull(skb, sizeof(struct ethhdr));
721
722                /* Determine total amount of storage required for TXB packets */
723                bytes = skb->len + SNAP_SIZE + sizeof(u16);
724
725		if (encrypt)
726			fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_WEP;
727		else
728
729                        fc = IEEE80211_FTYPE_DATA;
730
731		//if(ieee->current_network.QoS_Enable)
732		if(qos_actived)
733			fc |= IEEE80211_STYPE_QOS_DATA;
734		else
735			fc |= IEEE80211_STYPE_DATA;
736
737		if (ieee->iw_mode == IW_MODE_INFRA) {
738			fc |= IEEE80211_FCTL_TODS;
739			/* To DS: Addr1 = BSSID, Addr2 = SA,
740			Addr3 = DA */
741			memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
742			memcpy(&header.addr2, &src, ETH_ALEN);
743			memcpy(&header.addr3, &dest, ETH_ALEN);
744		} else if (ieee->iw_mode == IW_MODE_ADHOC) {
745			/* not From/To DS: Addr1 = DA, Addr2 = SA,
746			Addr3 = BSSID */
747			memcpy(&header.addr1, dest, ETH_ALEN);
748			memcpy(&header.addr2, src, ETH_ALEN);
749			memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
750		}
751
752                header.frame_ctl = cpu_to_le16(fc);
753
754		/* Determine fragmentation size based on destination (multicast
755		* and broadcast are not fragmented) */
756		if (is_multicast_ether_addr(header.addr1) ||
757		is_broadcast_ether_addr(header.addr1)) {
758			frag_size = MAX_FRAG_THRESHOLD;
759			qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
760		}
761		else {
762			frag_size = ieee->fts;//default:392
763			qos_ctl = 0;
764		}
765
766		//if (ieee->current_network.QoS_Enable)
767		if(qos_actived)
768		{
769			hdr_len = IEEE80211_3ADDR_LEN + 2;
770
771			skb->priority = ieee80211_classify(skb, &ieee->current_network);
772			qos_ctl |= skb->priority; //set in the ieee80211_classify
773			header.qos_ctl = cpu_to_le16(qos_ctl & IEEE80211_QOS_TID);
774		} else {
775			hdr_len = IEEE80211_3ADDR_LEN;
776		}
777		/* Determine amount of payload per fragment.  Regardless of if
778		* this stack is providing the full 802.11 header, one will
779		* eventually be affixed to this fragment -- so we must account for
780		* it when determining the amount of payload space. */
781		bytes_per_frag = frag_size - hdr_len;
782		if (ieee->config &
783		(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
784			bytes_per_frag -= IEEE80211_FCS_LEN;
785
786		/* Each fragment may need to have room for encryptiong pre/postfix */
787		if (encrypt)
788			bytes_per_frag -= crypt->ops->extra_prefix_len +
789				crypt->ops->extra_postfix_len;
790
791		/* Number of fragments is the total bytes_per_frag /
792		* payload_per_fragment */
793		nr_frags = bytes / bytes_per_frag;
794		bytes_last_frag = bytes % bytes_per_frag;
795		if (bytes_last_frag)
796			nr_frags++;
797		else
798			bytes_last_frag = bytes_per_frag;
799
800		/* When we allocate the TXB we allocate enough space for the reserve
801		* and full fragment bytes (bytes_per_frag doesn't include prefix,
802		* postfix, header, FCS, etc.) */
803		txb = ieee80211_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC);
804		if (unlikely(!txb)) {
805			printk(KERN_WARNING "%s: Could not allocate TXB\n",
806			ieee->dev->name);
807			goto failed;
808		}
809		txb->encrypted = encrypt;
810		txb->payload_size = bytes;
811
812		//if (ieee->current_network.QoS_Enable)
813		if(qos_actived)
814		{
815			txb->queue_index = UP2AC(skb->priority);
816		} else {
817			txb->queue_index = WME_AC_BK;;
818		}
819
820
821
822		for (i = 0; i < nr_frags; i++) {
823			skb_frag = txb->fragments[i];
824			tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE);
825			if(qos_actived){
826				skb_frag->priority = skb->priority;//UP2AC(skb->priority);
827				tcb_desc->queue_index =  UP2AC(skb->priority);
828			} else {
829				skb_frag->priority = WME_AC_BK;
830				tcb_desc->queue_index = WME_AC_BK;
831			}
832			skb_reserve(skb_frag, ieee->tx_headroom);
833
834			if (encrypt){
835				if (ieee->hwsec_active)
836					tcb_desc->bHwSec = 1;
837				else
838					tcb_desc->bHwSec = 0;
839				skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
840			}
841			else
842			{
843				tcb_desc->bHwSec = 0;
844			}
845			frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
846			memcpy(frag_hdr, &header, hdr_len);
847
848			/* If this is not the last fragment, then add the MOREFRAGS
849			* bit to the frame control */
850			if (i != nr_frags - 1) {
851				frag_hdr->frame_ctl = cpu_to_le16(
852					fc | IEEE80211_FCTL_MOREFRAGS);
853				bytes = bytes_per_frag;
854
855			} else {
856				/* The last fragment takes the remaining length */
857				bytes = bytes_last_frag;
858			}
859			//if(ieee->current_network.QoS_Enable)
860			if(qos_actived)
861			{
862				// add 1 only indicate to corresponding seq number control 2006/7/12
863				frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i);
864			} else {
865				frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
866			}
867
868			/* Put a SNAP header on the first fragment */
869			if (i == 0) {
870				ieee80211_put_snap(
871					skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
872					ether_type);
873				bytes -= SNAP_SIZE + sizeof(u16);
874			}
875
876			memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
877
878			/* Advance the SKB... */
879			skb_pull(skb, bytes);
880
881			/* Encryption routine will move the header forward in order
882			* to insert the IV between the header and the payload */
883			if (encrypt)
884				ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
885			if (ieee->config &
886			(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
887				skb_put(skb_frag, 4);
888		}
889
890		if(qos_actived)
891		{
892		  if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
893			ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
894		  else
895			ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
896		} else {
897  		  if (ieee->seq_ctrl[0] == 0xFFF)
898			ieee->seq_ctrl[0] = 0;
899		  else
900			ieee->seq_ctrl[0]++;
901		}
902	}else{
903		if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
904			printk(KERN_WARNING "%s: skb too small (%d).\n",
905			ieee->dev->name, skb->len);
906			goto success;
907		}
908
909		txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC);
910		if(!txb){
911			printk(KERN_WARNING "%s: Could not allocate TXB\n",
912			ieee->dev->name);
913			goto failed;
914		}
915
916		txb->encrypted = 0;
917		txb->payload_size = skb->len;
918		memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len);
919	}
920
921 success:
922//WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place.
923	if (txb)
924	{
925		cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
926		tcb_desc->bTxEnableFwCalcDur = 1;
927		if (is_multicast_ether_addr(header.addr1))
928			tcb_desc->bMulticast = 1;
929		if (is_broadcast_ether_addr(header.addr1))
930			tcb_desc->bBroadcast = 1;
931		ieee80211_txrate_selectmode(ieee, tcb_desc);
932		if ( tcb_desc->bMulticast ||  tcb_desc->bBroadcast)
933			tcb_desc->data_rate = ieee->basic_rate;
934		else
935			//tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate);
936			tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
937
938		if(bdhcp == true){
939			// Use low rate to send DHCP packet.
940			//if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) {
941			//	tcb_desc->data_rate = MGN_1M;//MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m
942			//	tcb_desc->bTxDisableRateFallBack = false;
943			//}
944			//else
945			{
946				tcb_desc->data_rate = MGN_1M;
947				tcb_desc->bTxDisableRateFallBack = 1;
948			}
949
950			tcb_desc->RATRIndex = 7;
951			tcb_desc->bTxUseDriverAssingedRate = 1;
952			tcb_desc->bdhcp = 1;
953		}
954
955
956		ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc);
957		ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
958		ieee80211_query_HTCapShortGI(ieee, tcb_desc);
959		ieee80211_query_BandwidthMode(ieee, tcb_desc);
960		ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]);
961		ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1);
962//		IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, txb->fragments[0]->data, txb->fragments[0]->len);
963		//IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, tcb_desc, sizeof(cb_desc));
964	}
965	spin_unlock_irqrestore(&ieee->lock, flags);
966	dev_kfree_skb_any(skb);
967	if (txb) {
968		if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){
969			ieee80211_softmac_xmit(txb, ieee);
970		}else{
971			if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
972				stats->tx_packets++;
973				stats->tx_bytes += txb->payload_size;
974				return 0;
975			}
976			ieee80211_txb_free(txb);
977		}
978	}
979
980	return 0;
981
982 failed:
983	spin_unlock_irqrestore(&ieee->lock, flags);
984	netif_stop_queue(dev);
985	stats->tx_errors++;
986	return 1;
987
988}
989
990//EXPORT_SYMBOL(ieee80211_txb_free);
991