summaryrefslogblamecommitdiffstats
path: root/drivers/staging/vt6655/rxtx.c
blob: a1a594fa10d5dda7a0be4b0ef4a51d1cb0f00aa7 (plain) (tree)
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702


























                                                                          
                                                                    
                                                             
                                                        




                                                          
                                                           


                                                      
                                                         









                                                        
                   
                 
                   
                 
                  
                
                     
                    
                 
                 
                 
                   
                   
               





                                                                       
 





                                                                                 
                                                          


                                                                               
 
                                              


                                                                             
                                              


                                                                             
 
















                                                                       
      
    
             
                                    






                                   
 
      
    
               
                                    




                                      
                                  


                                    

      
    
                       
                                    







                                    
                          

                                   
 
                   





                                                                               
 
      
      
                
                                    










                                        
 

                                                                       
      
    
             
                                    






                                   
 
                                                                    

                                                                                  



                                                               

























                                                                                                   
                                                       
                                                 
 

                                                                 
                                                
                                                   
 








                                                                                                     
                                                                        


                                                                 
                                                
                                                   
 








                                                                                                     


                                         
                                                                          











                                                                           
                                         
                                                        
                    
                                                        
 

                                                                      

                             
                                                                      




                                                                            
                                                                              
         

 
      
    
                
                                    



                                         
 





























                                                                                                   

 





                                                                           
                               


                   

      
            
                
                                    




                                   
 
                                         
 
                                                                                              
                                                    
                                                                                                                               
                                                    
                                                                                                                                
 
                     
                                                             
            
                                 

 






                                                                               

                               
      
                    
                                    




                                   
 



                                                                         



                                                                                                                          
                                                                         


                                                                                                                
                                                         

                                                                                                                           
                                                                         


                                                                                                                
                                                  



                                                                                 
                                          



                              
            
                   
                                    









                                        
 


                                                    
                                        
                              
 
                            
                                      
                                                                               

                                                                                                                               
                                                                 


                                         
                                                
                                                        
                                                                                                                        
                            
                                                                                                                   
 

                                                                                                                               
                                                                                
                                
                                                                     




                                      
                                                                               

                                                                                                                                
                                                                 


                                         
                                                
                                                        
                                                                                                                        
                            
                                                                                                                   
 

                                                                                                                                
                                                                                
                                
                                                                     




                                            
                                                                               

                                                                                                                                
                                                                 


                                         
                                                 





                                                          
                                                                
                                                                                                                                                             
                                    
                                                                                                                                                        
 





                                                             
                                                                
                                                                                                                                                             
                                    
                                                                                                                                                        
 



                                                                                                                                
                                                                                
                                
                                                                     




                                            
                                                                               

                                                                                                                                
                                                                 


                                         
                                                 





                                                          
                                                                
                                                                                                                                                             
                                    
                                                                                                                                                        






                                                             
                                                                
                                                                                                                                                             
                                    
                                                                                                                                                        


                                                                                                                                
                                                                                
                                
                                                                     






                         
 
                      


                 

                               
      
                     
                                    






                                   
 

                                                
                            




















                                                                                                                             
                                                                                            
                                                                                                                                                                    
                                                                                                 
                                                                                                                                                                    
 



                                                                                                                
                                                                                            
                                                                                                                                                                  
                                                                                                 
                                                                                                                                                                  
 



                                                                                                               
                                                                                            
                                                                                                                                                                  
                                                                                                 
                                                                                                                                                                  
 



                                                                                                                
                                                                                            
                                                                                                                                                                  
                                                                                                 
                                                                                                                                                                  
 


                                              
                                                                                            
                                                                                                                                                     
                                                                                                 
                                                                                                                                                     
 


                                              
                                                                                            
                                                                                                                                                     
                                                                                                 
                                                                                                                                                     
 





                      
                                          

 
      
      
                
                                    










                                        
 
 
                                
                         
 


                                                                     
                                                                    

                                                                               
                                                              


                                                                     















                                                                                                                          
                        

                                                                       

                                                                               
                                                              


                                                                     














                                                                                                                                                                             
                                                   
                                              
                                                   

                                                                       

                                                                               
                                                              
 








                                                                                                                                                                
                        
                                                                     

                                                                               
                                                               
 




                                                                                                                         
 

                                                                                        
                 
                
                                                             

                                                                       







                                                                                                                 

                 

 
      
    
               
                                    




                                   
                                  


                                    
 
                                       













                                                                                                                
                                                      


                                                                     
                                                                


                                                                      


                                                              



                                                                                
                                          



                                                                              
                                          



                                                                              

                                                              
                                                
                                                 


                                                                         

                                                                  
                        
                                                         


                                                                     
                                                                


                                                                      


                                                              



                                                                                
                                          



                                                                              
                                          



                                                                              
                                                 



                                                                              
                                                 



                                                                              
                                                 



                                                                              
                                                 



                                                                              
                                                              
                                                
                                                 


                                                                         

                                                                  
                                                    
                                              
                                                 
                                                       


                                                                      


                                                               



                                                                              
                                                           
                                                
                                                 


                                                                         

                                                                  
                        
                                                         


                                                                      


                                                              



                                                                              
                                              



                                                                              
                                              



                                                                              
                                                           
                                                
                                                 


                                                                         

                                                                  
                 
                                              
                                               


                                                             


                                                         



                                                                               
                                                   
                                        
                                         
                                                                               
 

                                                          
         


      
    
               
                                    








                                    
 
                                       
 
                          
                       









                                                                                                         
                                                       


                                                                     

                                                                




                                                                              
 












                                                                              
 
                                                
                                                              
 
                                                 


                                                                 
                                             
 

                                                                    
                                                                                                                  
                                                    


                                                                     
                                                                
 

                                                



                                                                              
 

                                                              
 
                                                 


                                                                 
                                             

                                                                    

                 

 






                                                           
                                            












                                                                
    
                                             
      
    
                       
                                    







                                 
                          

                                   
 



                                                          
 
                                                        
 


                                            
                                      
                               
 
                                         
                                       
                                              
                                       



                                                    


                       
                                                                     
                                               








                                                                                                                                         
                                                                                                                                         
                                                
                                                                 
 


                                                                                                                                         
 


                                                                                                                                     
                                              
                                                            



                                                                                                                       
 

                                                                                                                                         
                                                                       
                                                                
 
                                                                                                                         
                 
                                              
                                                              



                                                                                                                         
 

                                                                                                                                         
                                                     
                                                                
 
                                                                                                                         

                 
 
 
                   




                                                                               
                                                                     
 






                                                                      
                                 
                         
                                 
                                 
                                  


                                     

                                                           
                               

                                        
                                    



                                                   
                                                
 

                                                                
                                   
 


                                                       
                                                              

                              
                 


                                                             

                                                                         
                                                                                



                                      


                                 
                                         
                                       
                                              
                                       







                                                                                     

                                                                                                                                 
                                                                                                                            
                                             

                                                                                                                      
                                                                                               

                                                                                             
                                               

                                                                                                                                  
                                             


                                                                                                                             
                                                                                               
                                                                                                                             



                                                     

                                                                                                                                  
                                                                                                                             
                                             

                                                                                                                      
                                                                                               
                                                                                                                     
                                               

                                                                                                                                  
                                             


                                                                                                                            
                                                                                               
                                                                                                                   

                                   
                                  


                                                 

                                                                                                                                 
                                                                                                                           
                                             
                                                                                    
                                                                                                               
                                                                                              
                                                                                                                 
                                                            

                                                                                                                                 

                                             


                                                                                                                                



                                                     

                                                                                                                                 
                                                                                                                           
                                             

                                                                                                                 
                                                                                              
                                                                                                                     
                                               

                                                                                                                                

                                             


                                                                                                                                


                                   
 
                                   
 
                                                                                         
 





                                                                                                   
 
                                     
 


                                                                 
 

                                                                
 
                                    
 






                                                                                
 
                                    
 
                              

 
    


                                                                         


                                                                                                
 










                                                                   

                                                         


                                                                                         
                        



                                                                
                





                                                        










                                                                             
                            
                                   
                                                       

                              
                                 
                                                    
            
                                                
 


                                                                                
                                                           
                 
                                                                
                                                    
                                                                 
                                                     
                                                                 
                                                     
 
                                  
                                                                 
                                                       


                                                
                                                       
                                                                  
                                                            
                                                                  









                                                                              
                                                                                                  

                                                                                   
                                                                                        



                                                                    
 
                                                                          
 
                                                  
 


                                                                                                

 






                                        
                                            








                                                                                   
    
 
    
                   
                                    
                                     
                         





                                     
 

                                                                   
                                                       
 
                                    
                                                         
            
                                                         
 
                                                    





                                                               
                                                   
                
                                                               





                                                                       
                        





                                                                       






                                                                                           
                                                         


                                                                                    
 













                                                                                 
                                                                                                    
                                                     

 
                                                                           
 



                                       
                             






















                                               
                                                
                                            



















                                                                                                    
                                                           
                                                                         
            
                                                                        
 











                                                                                                
                                                                   
                                                    
                                                                    
                                                     
                                                                    





                                                                            




                                                                               
         


                                                       
                                                       























                                                                                            
                                                                                        




                                                                           
                                                                                        












                                                                                              
                                                                 
                                                       
 



                                                                                              
                                                                    

                               
                                                                        
                                                                         
                                                                    
                                                                                          
                                                                             
                                                                                          
                                    
                                                                   


                               



                                                                            



                                                                                       



                                                                   




                                                                





























                                                                                                                     
                    
                                                                           





                                                                                                                               
                                                                      


                                                      
                                                              






                                                                                                                
                                                                      
                                                           
                                
                                                      








                                                                                                       
                















                                                                                                              

                                                                                                                                   
                        
                                                                                                                                  


                 



















                                                                                
                                                
                                                  

                                                       
 
                                                                                    
 

                                           
 
                                  

 
                                                                             
 



                                                                            

                                                                          

                                    
 
                                                   











                                                       

                                                            
 
                                            
                                                            



                                                                                
                                                                   





                                                                                

         
                                               
                                                                    
 
                              
                                                                               
                                                            






















                                                                                

 
            
               
                                    



                                      
 











                                                                      

                                                         



                                                                           
                








                                                      
                                                 

































                                                                                                  
                                               
                                                                  
                    
                                      

                           

 


                                                                     





















                                       

                                 

                      
















                                               
 

                                                                
                                            
                                    
            
                                                                 
 

                                               

















                                                                                                      
                                                           
                                                                         
            
                                                                        
 









                                                                                       

                                                                      



                                                            
                                                                   
                                                    
                                                                    
                                                     
                                                                    





                                                                            





                                                                        
                





                                                                                                                            
         


                                                       
                                                       












                                                                                       
                                                                             
                                                                                                              
 
                                                                                
                                                                                                                 
 
                                      
                                                                        

         







                                                                              




                                                                                 
                                                                                        




                                                                           
                                                                                        

                                                
                                                              










                                                                                                              
                                                                 
                                                       
 

                                                                                              

                                                                                     


                                                                               
                             
                                                                         
                                                                            
                                                                    
                                                                                             
                                                                             
                                                                                                     
 
                                  
 


                                                                             

                             
                                                       

                                                                                
                                                                             



                                                                                       



                                                          




                                                                








































                                                                                                                                                 













                                                                                                    

                                                                        





                                                                                      

                                                                  




                                                                                  

                                                                                            









                                                            



                                                                                


                 







                                                                                                       
                                                             
                                                                                                                             






                                                                     






                                                                                                           

                                                                                                                          
                        
                                                                                                                         


                 





















                                                                            
                                                
                                                  
 
                                                       
 

                                           
 






















































































































































































































































































































                                                                                
/*
 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * File: rxtx.c
 *
 * Purpose: handle WMAC/802.3/802.11 rx & tx functions
 *
 * Author: Lyndon Chen
 *
 * Date: May 20, 2003
 *
 * Functions:
 *      s_vGenerateTxParameter - Generate tx dma required parameter.
 *      vGenerateMACHeader - Translate 802.3 to 802.11 header
 *      cbGetFragCount - Calculate fragment number count
 *      csBeacon_xmit - beacon tx function
 *      csMgmt_xmit - management tx function
 *      s_cbFillTxBufHead - fulfill tx dma buffer header
 *      s_uGetDataDuration - get tx data required duration
 *      s_uFillDataHead- fulfill tx data duration header
 *      s_uGetRTSCTSDuration- get rtx/cts required duration
 *      s_uGetRTSCTSRsvTime- get rts/cts reserved time
 *      s_uGetTxRsvTime- get frame reserved time
 *      s_vFillCTSHead- fulfill CTS ctl header
 *      s_vFillFragParameter- Set fragment ctl parameter.
 *      s_vFillRTSHead- fulfill RTS ctl header
 *      s_vFillTxKey- fulfill tx encrypt key
 *      s_vSWencryption- Software encrypt header
 *      vDMA0_tx_80211- tx 802.11 frame via dma0
 *      vGenerateFIFOHeader- Generate tx FIFO ctl header
 *
 * Revision History:
 *
 */

#include "device.h"
#include "rxtx.h"
#include "tether.h"
#include "card.h"
#include "bssdb.h"
#include "mac.h"
#include "baseband.h"
#include "michael.h"
#include "tkip.h"
#include "tcrc.h"
#include "wctl.h"
#include "wroute.h"
#include "hostap.h"
#include "rf.h"

/*---------------------  Static Definitions -------------------------*/

/*---------------------  Static Classes  ----------------------------*/

/*---------------------  Static Variables  --------------------------*/

/*---------------------  Static Functions  --------------------------*/

/*---------------------  Static Definitions -------------------------*/
#define CRITICAL_PACKET_LEN      256    // if packet size < 256 -> in-direct send
                                        //    packet size >= 256 -> direct send

static const unsigned short wTimeStampOff[2][MAX_RATE] = {
	{384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble
	{384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, // Short Preamble
};

static const unsigned short wFB_Opt0[2][5] = {
	{RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0
	{RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1
};
static const unsigned short wFB_Opt1[2][5] = {
	{RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0
	{RATE_6M , RATE_6M,  RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1
};

#define RTSDUR_BB       0
#define RTSDUR_BA       1
#define RTSDUR_AA       2
#define CTSDUR_BA       3
#define RTSDUR_BA_F0    4
#define RTSDUR_AA_F0    5
#define RTSDUR_BA_F1    6
#define RTSDUR_AA_F1    7
#define CTSDUR_BA_F0    8
#define CTSDUR_BA_F1    9
#define DATADUR_B       10
#define DATADUR_A       11
#define DATADUR_A_F0    12
#define DATADUR_A_F1    13

/*---------------------  Static Functions  --------------------------*/

static
void
s_vFillTxKey(
	struct vnt_private *pDevice,
	unsigned char *pbyBuf,
	unsigned char *pbyIVHead,
	PSKeyItem  pTransmitKey,
	unsigned char *pbyHdrBuf,
	unsigned short wPayloadLen,
	unsigned char *pMICHDR
);

static
void
s_vFillRTSHead(
	struct vnt_private *pDevice,
	unsigned char byPktType,
	void *pvRTS,
	unsigned int	cbFrameLength,
	bool bNeedAck,
	bool bDisCRC,
	struct ieee80211_hdr *hdr,
	unsigned short wCurrentRate,
	unsigned char byFBOption
);

static
void
s_vGenerateTxParameter(
	struct vnt_private *pDevice,
	unsigned char byPktType,
	void *pTxBufHead,
	void *pvRrvTime,
	void *pvRTS,
	void *pvCTS,
	unsigned int	cbFrameSize,
	bool bNeedACK,
	unsigned int	uDMAIdx,
	void *psEthHeader,
	unsigned short wCurrentRate
);

static unsigned int
s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
		  unsigned char *pbyTxBufferAddr, unsigned int cbFrameBodySize,
		  unsigned int uDMAIdx, PSTxDesc pHeadTD,
		  PSEthernetHeader psEthHeader, unsigned char *pPacket,
		  bool bNeedEncrypt, PSKeyItem pTransmitKey,
		  unsigned int uNodeIndex, unsigned int *puMACfragNum);

static
__le16
s_uFillDataHead(
	struct vnt_private *pDevice,
	unsigned char byPktType,
	void *pTxDataHead,
	unsigned int cbFrameLength,
	unsigned int uDMAIdx,
	bool bNeedAck,
	unsigned int uFragIdx,
	unsigned int cbLastFragmentSize,
	unsigned int uMACfragNum,
	unsigned char byFBOption,
	unsigned short wCurrentRate
);

/*---------------------  Export Variables  --------------------------*/

static
void
s_vFillTxKey(
	struct vnt_private *pDevice,
	unsigned char *pbyBuf,
	unsigned char *pbyIVHead,
	PSKeyItem  pTransmitKey,
	unsigned char *pbyHdrBuf,
	unsigned short wPayloadLen,
	unsigned char *pMICHDR
)
{
	struct vnt_mic_hdr *mic_hdr = (struct vnt_mic_hdr *)pMICHDR;
	unsigned long *pdwIV = (unsigned long *)pbyIVHead;
	unsigned long *pdwExtIV = (unsigned long *)((unsigned char *)pbyIVHead+4);
	PS802_11Header  pMACHeader = (PS802_11Header)pbyHdrBuf;
	unsigned long dwRevIVCounter;
	unsigned char byKeyIndex = 0;

	//Fill TXKEY
	if (pTransmitKey == NULL)
		return;

	dwRevIVCounter = cpu_to_le32(pDevice->dwIVCounter);
	*pdwIV = pDevice->dwIVCounter;
	byKeyIndex = pTransmitKey->dwKeyIndex & 0xf;

	if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
		if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN) {
			memcpy(pDevice->abyPRNG, (unsigned char *)&(dwRevIVCounter), 3);
			memcpy(pDevice->abyPRNG+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
		} else {
			memcpy(pbyBuf, (unsigned char *)&(dwRevIVCounter), 3);
			memcpy(pbyBuf+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
			if (pTransmitKey->uKeyLength == WLAN_WEP40_KEYLEN) {
				memcpy(pbyBuf+8, (unsigned char *)&(dwRevIVCounter), 3);
				memcpy(pbyBuf+11, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
			}
			memcpy(pDevice->abyPRNG, pbyBuf, 16);
		}
		// Append IV after Mac Header
		*pdwIV &= WEP_IV_MASK;//00000000 11111111 11111111 11111111
		*pdwIV |= (unsigned long)byKeyIndex << 30;
		*pdwIV = cpu_to_le32(*pdwIV);
		pDevice->dwIVCounter++;
		if (pDevice->dwIVCounter > WEP_IV_MASK)
			pDevice->dwIVCounter = 0;

	} else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
		pTransmitKey->wTSC15_0++;
		if (pTransmitKey->wTSC15_0 == 0)
			pTransmitKey->dwTSC47_16++;

		TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr,
			    pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG);
		memcpy(pbyBuf, pDevice->abyPRNG, 16);
		// Make IV
		memcpy(pdwIV, pDevice->abyPRNG, 3);

		*(pbyIVHead+3) = (unsigned char)(((byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV
		// Append IV&ExtIV after Mac Header
		*pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16);
		pr_debug("vFillTxKey()---- pdwExtIV: %lx\n", *pdwExtIV);

	} else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) {
		pTransmitKey->wTSC15_0++;
		if (pTransmitKey->wTSC15_0 == 0)
			pTransmitKey->dwTSC47_16++;

		memcpy(pbyBuf, pTransmitKey->abyKey, 16);

		// Make IV
		*pdwIV = 0;
		*(pbyIVHead+3) = (unsigned char)(((byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV
		*pdwIV |= cpu_to_le16((unsigned short)(pTransmitKey->wTSC15_0));
		//Append IV&ExtIV after Mac Header
		*pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16);

		/* MICHDR0 */
		mic_hdr->id = 0x59;
		mic_hdr->tx_priority = 0;
		ether_addr_copy(mic_hdr->mic_addr2, pMACHeader->abyAddr2);

		/* ccmp pn big endian order */
		mic_hdr->ccmp_pn[0] = (u8)(pTransmitKey->dwTSC47_16 >> 24);
		mic_hdr->ccmp_pn[1] = (u8)(pTransmitKey->dwTSC47_16 >> 16);
		mic_hdr->ccmp_pn[2] = (u8)(pTransmitKey->dwTSC47_16 >> 8);
		mic_hdr->ccmp_pn[3] = (u8)pTransmitKey->dwTSC47_16;
		mic_hdr->ccmp_pn[4] = (u8)(pTransmitKey->wTSC15_0 >> 8);
		mic_hdr->ccmp_pn[5] = (u8)pTransmitKey->wTSC15_0;

		/* MICHDR1 */
		mic_hdr->payload_len = cpu_to_be16(wPayloadLen);

		if (pDevice->bLongHeader)
			mic_hdr->hlen = cpu_to_be16(28);
		else
			mic_hdr->hlen = cpu_to_be16(22);

		ether_addr_copy(mic_hdr->addr1, pMACHeader->abyAddr1);
		ether_addr_copy(mic_hdr->addr2, pMACHeader->abyAddr2);

		/* MICHDR2 */
		ether_addr_copy(mic_hdr->addr3, pMACHeader->abyAddr3);
		mic_hdr->frame_control =
				cpu_to_le16(pMACHeader->wFrameCtl & 0xc78f);
		mic_hdr->seq_ctrl = cpu_to_le16(pMACHeader->wSeqCtl & 0xf);

		if (pDevice->bLongHeader)
			ether_addr_copy(mic_hdr->addr4, pMACHeader->abyAddr4);
	}
}

static
void
s_vSWencryption(
	struct vnt_private *pDevice,
	PSKeyItem           pTransmitKey,
	unsigned char *pbyPayloadHead,
	unsigned short wPayloadSize
)
{
	unsigned int cbICVlen = 4;
	unsigned long dwICV = 0xFFFFFFFFL;
	unsigned long *pdwICV;

	if (pTransmitKey == NULL)
		return;

	if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
		//=======================================================================
		// Append ICV after payload
		dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload)
		pdwICV = (unsigned long *)(pbyPayloadHead + wPayloadSize);
		// finally, we must invert dwCRC to get the correct answer
		*pdwICV = cpu_to_le32(~dwICV);
		// RC4 encryption
		rc4_init(&pDevice->SBox, pDevice->abyPRNG, pTransmitKey->uKeyLength + 3);
		rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen);
		//=======================================================================
	} else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
		//=======================================================================
		//Append ICV after payload
		dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload)
		pdwICV = (unsigned long *)(pbyPayloadHead + wPayloadSize);
		// finally, we must invert dwCRC to get the correct answer
		*pdwICV = cpu_to_le32(~dwICV);
		// RC4 encryption
		rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN);
		rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen);
		//=======================================================================
	}
}

static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate)
{
	return cpu_to_le16(wTimeStampOff[priv->byPreambleType % 2]
							[rate % MAX_RATE]);
}

/*byPktType : PK_TYPE_11A     0
  PK_TYPE_11B     1
  PK_TYPE_11GB    2
  PK_TYPE_11GA    3
*/
static
unsigned int
s_uGetTxRsvTime(
	struct vnt_private *pDevice,
	unsigned char byPktType,
	unsigned int cbFrameLength,
	unsigned short wRate,
	bool bNeedAck
)
{
	unsigned int uDataTime, uAckTime;

	uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wRate);
	if (byPktType == PK_TYPE_11B) //llb,CCK mode
		uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopCCKBasicRate);
	else //11g 2.4G OFDM mode & 11a 5G OFDM mode
		uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopOFDMBasicRate);

	if (bNeedAck)
		return uDataTime + pDevice->uSIFS + uAckTime;
	else
		return uDataTime;
}

static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type,
				    u32 frame_length, u16 rate, bool need_ack)
{
	return cpu_to_le16((u16)s_uGetTxRsvTime(priv, pkt_type,
						frame_length, rate, need_ack));
}

//byFreqType: 0=>5GHZ 1=>2.4GHZ
static
__le16
s_uGetRTSCTSRsvTime(
	struct vnt_private *pDevice,
	unsigned char byRTSRsvType,
	unsigned char byPktType,
	unsigned int cbFrameLength,
	unsigned short wCurrentRate
)
{
	unsigned int uRrvTime  , uRTSTime, uCTSTime, uAckTime, uDataTime;

	uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0;

	uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wCurrentRate);
	if (byRTSRsvType == 0) { //RTSTxRrvTime_bb
		uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate);
		uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
	} else if (byRTSRsvType == 1) { //RTSTxRrvTime_ba, only in 2.4GHZ
		uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate);
		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
		uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
	} else if (byRTSRsvType == 2) { //RTSTxRrvTime_aa
		uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopOFDMBasicRate);
		uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
	} else if (byRTSRsvType == 3) { //CTSTxRrvTime_ba, only in 2.4GHZ
		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
		uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
		uRrvTime = uCTSTime + uAckTime + uDataTime + 2*pDevice->uSIFS;
		return cpu_to_le16((u16)uRrvTime);
	}

	//RTSRrvTime
	uRrvTime = uRTSTime + uCTSTime + uAckTime + uDataTime + 3*pDevice->uSIFS;
	return cpu_to_le16((u16)uRrvTime);
}

//byFreqType 0: 5GHz, 1:2.4Ghz
static
unsigned int
s_uGetDataDuration(
	struct vnt_private *pDevice,
	unsigned char byDurType,
	unsigned int cbFrameLength,
	unsigned char byPktType,
	unsigned short wRate,
	bool bNeedAck,
	unsigned int uFragIdx,
	unsigned int cbLastFragmentSize,
	unsigned int uMACfragNum,
	unsigned char byFBOption
)
{
	bool bLastFrag = 0;
	unsigned int uAckTime = 0, uNextPktTime = 0;

	if (uFragIdx == (uMACfragNum-1))
		bLastFrag = 1;

	switch (byDurType) {
	case DATADUR_B:    //DATADUR_B
		if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
			if (bNeedAck) {
				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
				return pDevice->uSIFS + uAckTime;
			} else {
				return 0;
			}
		} else {//First Frag or Mid Frag
			if (uFragIdx == (uMACfragNum-2))
				uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck);
			else
				uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);

			if (bNeedAck) {
				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
				return pDevice->uSIFS + uAckTime + uNextPktTime;
			} else {
				return pDevice->uSIFS + uNextPktTime;
			}
		}
		break;

	case DATADUR_A:    //DATADUR_A
		if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
			if (bNeedAck) {
				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
				return pDevice->uSIFS + uAckTime;
			} else {
				return 0;
			}
		} else {//First Frag or Mid Frag
			if (uFragIdx == (uMACfragNum-2))
				uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck);
			else
				uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);

			if (bNeedAck) {
				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
				return pDevice->uSIFS + uAckTime + uNextPktTime;
			} else {
				return pDevice->uSIFS + uNextPktTime;
			}
		}
		break;

	case DATADUR_A_F0:    //DATADUR_A_F0
		if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
			if (bNeedAck) {
				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
				return pDevice->uSIFS + uAckTime;
			} else {
				return 0;
			}
		} else { //First Frag or Mid Frag
			if (byFBOption == AUTO_FB_0) {
				if (wRate < RATE_18M)
					wRate = RATE_18M;
				else if (wRate > RATE_54M)
					wRate = RATE_54M;

				if (uFragIdx == (uMACfragNum-2))
					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
				else
					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);

			} else { // (byFBOption == AUTO_FB_1)
				if (wRate < RATE_18M)
					wRate = RATE_18M;
				else if (wRate > RATE_54M)
					wRate = RATE_54M;

				if (uFragIdx == (uMACfragNum-2))
					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
				else
					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);

			}

			if (bNeedAck) {
				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
				return pDevice->uSIFS + uAckTime + uNextPktTime;
			} else {
				return pDevice->uSIFS + uNextPktTime;
			}
		}
		break;

	case DATADUR_A_F1:    //DATADUR_A_F1
		if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
			if (bNeedAck) {
				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
				return pDevice->uSIFS + uAckTime;
			} else {
				return 0;
			}
		} else { //First Frag or Mid Frag
			if (byFBOption == AUTO_FB_0) {
				if (wRate < RATE_18M)
					wRate = RATE_18M;
				else if (wRate > RATE_54M)
					wRate = RATE_54M;

				if (uFragIdx == (uMACfragNum-2))
					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
				else
					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);

			} else { // (byFBOption == AUTO_FB_1)
				if (wRate < RATE_18M)
					wRate = RATE_18M;
				else if (wRate > RATE_54M)
					wRate = RATE_54M;

				if (uFragIdx == (uMACfragNum-2))
					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
				else
					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
			}
			if (bNeedAck) {
				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
				return pDevice->uSIFS + uAckTime + uNextPktTime;
			} else {
				return pDevice->uSIFS + uNextPktTime;
			}
		}
		break;

	default:
		break;
	}

	ASSERT(false);
	return 0;
}

//byFreqType: 0=>5GHZ 1=>2.4GHZ
static
__le16
s_uGetRTSCTSDuration(
	struct vnt_private *pDevice,
	unsigned char byDurType,
	unsigned int cbFrameLength,
	unsigned char byPktType,
	unsigned short wRate,
	bool bNeedAck,
	unsigned char byFBOption
)
{
	unsigned int uCTSTime = 0, uDurTime = 0;

	switch (byDurType) {
	case RTSDUR_BB:    //RTSDuration_bb
		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
		uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
		break;

	case RTSDUR_BA:    //RTSDuration_ba
		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
		uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
		break;

	case RTSDUR_AA:    //RTSDuration_aa
		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
		uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
		break;

	case CTSDUR_BA:    //CTSDuration_ba
		uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
		break;

	case RTSDUR_BA_F0: //RTSDuration_ba_f0
		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
		else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);

		break;

	case RTSDUR_AA_F0: //RTSDuration_aa_f0
		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
		else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);

		break;

	case RTSDUR_BA_F1: //RTSDuration_ba_f1
		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
		else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);

		break;

	case RTSDUR_AA_F1: //RTSDuration_aa_f1
		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
		else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);

		break;

	case CTSDUR_BA_F0: //CTSDuration_ba_f0
		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
		else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);

		break;

	case CTSDUR_BA_F1: //CTSDuration_ba_f1
		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
		else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
			uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);

		break;

	default:
		break;
	}

	return cpu_to_le16((u16)uDurTime);
}

static
__le16
s_uFillDataHead(
	struct vnt_private *pDevice,
	unsigned char byPktType,
	void *pTxDataHead,
	unsigned int cbFrameLength,
	unsigned int uDMAIdx,
	bool bNeedAck,
	unsigned int uFragIdx,
	unsigned int cbLastFragmentSize,
	unsigned int uMACfragNum,
	unsigned char byFBOption,
	unsigned short wCurrentRate
)
{

	if (pTxDataHead == NULL)
		return 0;


	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
		if (byFBOption == AUTO_FB_NONE) {
			struct vnt_tx_datahead_g *buf = pTxDataHead;
			/* Get SignalField, ServiceField & Length */
			vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
					  byPktType, &buf->a);

			vnt_get_phy_field(pDevice, cbFrameLength,
					  pDevice->byTopCCKBasicRate,
					  PK_TYPE_11B, &buf->b);

			/* Get Duration and TimeStamp */
			buf->duration_a = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength,
									      byPktType, wCurrentRate, bNeedAck, uFragIdx,
									      cbLastFragmentSize, uMACfragNum,
									      byFBOption));
			buf->duration_b = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength,
									      PK_TYPE_11B, pDevice->byTopCCKBasicRate,
									      bNeedAck, uFragIdx, cbLastFragmentSize,
									      uMACfragNum, byFBOption));

			buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate);
			buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate);

			return buf->duration_a;
		} else {
			/* Auto Fallback */
			struct vnt_tx_datahead_g_fb *buf = pTxDataHead;
			/* Get SignalField, ServiceField & Length */
			vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
					  byPktType, &buf->a);

			vnt_get_phy_field(pDevice, cbFrameLength,
					  pDevice->byTopCCKBasicRate,
					  PK_TYPE_11B, &buf->b);
			/* Get Duration and TimeStamp */
			buf->duration_a = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
									      wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
			buf->duration_b = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B,
									       pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
			buf->duration_a_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
										  wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
			buf->duration_a_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
										 wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));

			buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate);
			buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate);

			return buf->duration_a;
		} //if (byFBOption == AUTO_FB_NONE)
	} else if (byPktType == PK_TYPE_11A) {
		if ((byFBOption != AUTO_FB_NONE)) {
			/* Auto Fallback */
			struct vnt_tx_datahead_a_fb *buf = pTxDataHead;
			/* Get SignalField, ServiceField & Length */
			vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
					  byPktType, &buf->a);

			/* Get Duration and TimeStampOff */
			buf->duration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
									    wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
			buf->duration_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
									       wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
			buf->duration_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
										wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
			buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
			return buf->duration;
		} else {
			struct vnt_tx_datahead_ab *buf = pTxDataHead;
			/* Get SignalField, ServiceField & Length */
			vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
					  byPktType, &buf->ab);

			/* Get Duration and TimeStampOff */
			buf->duration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
									    wCurrentRate, bNeedAck, uFragIdx,
									    cbLastFragmentSize, uMACfragNum,
									    byFBOption));

			buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
			return buf->duration;
		}
	} else {
		struct vnt_tx_datahead_ab *buf = pTxDataHead;
		/* Get SignalField, ServiceField & Length */
		vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
				  byPktType, &buf->ab);
		/* Get Duration and TimeStampOff */
		buf->duration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType,
								    wCurrentRate, bNeedAck, uFragIdx,
								    cbLastFragmentSize, uMACfragNum,
								    byFBOption));
		buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
		return buf->duration;
	}
	return 0;
}

static
void
s_vFillRTSHead(
	struct vnt_private *pDevice,
	unsigned char byPktType,
	void *pvRTS,
	unsigned int cbFrameLength,
	bool bNeedAck,
	bool bDisCRC,
	struct ieee80211_hdr *hdr,
	unsigned short wCurrentRate,
	unsigned char byFBOption
)
{
	unsigned int uRTSFrameLen = 20;

	if (pvRTS == NULL)
		return;

	if (bDisCRC) {
		// When CRCDIS bit is on, H/W forgot to generate FCS for RTS frame,
		// in this case we need to decrease its length by 4.
		uRTSFrameLen -= 4;
	}

	// Note: So far RTSHead dosen't appear in ATIM & Beacom DMA, so we don't need to take them into account.
	//       Otherwise, we need to modify codes for them.
	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
		if (byFBOption == AUTO_FB_NONE) {
			struct vnt_rts_g *buf = pvRTS;
			/* Get SignalField, ServiceField & Length */
			vnt_get_phy_field(pDevice, uRTSFrameLen,
					  pDevice->byTopCCKBasicRate,
					  PK_TYPE_11B, &buf->b);

			vnt_get_phy_field(pDevice, uRTSFrameLen,
					  pDevice->byTopOFDMBasicRate,
					  byPktType, &buf->a);
			/* Get Duration */
			buf->duration_bb =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
						     cbFrameLength, PK_TYPE_11B,
						     pDevice->byTopCCKBasicRate,
						     bNeedAck, byFBOption);
			buf->duration_aa =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);
			buf->duration_ba =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_BA,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);

			buf->data.duration = buf->duration_aa;
			/* Get RTS Frame body */
			buf->data.frame_control =
					cpu_to_le16(IEEE80211_FTYPE_CTL |
						    IEEE80211_STYPE_RTS);

			ether_addr_copy(buf->data.ra, hdr->addr1);
			ether_addr_copy(buf->data.ta, hdr->addr2);
		} else {
			struct vnt_rts_g_fb *buf = pvRTS;
			/* Get SignalField, ServiceField & Length */
			vnt_get_phy_field(pDevice, uRTSFrameLen,
					  pDevice->byTopCCKBasicRate,
					  PK_TYPE_11B, &buf->b);

			vnt_get_phy_field(pDevice, uRTSFrameLen,
					  pDevice->byTopOFDMBasicRate,
					  byPktType, &buf->a);
			/* Get Duration */
			buf->duration_bb =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
						     cbFrameLength, PK_TYPE_11B,
						     pDevice->byTopCCKBasicRate,
						     bNeedAck, byFBOption);
			buf->duration_aa =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);
			buf->duration_ba =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_BA,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);
			buf->rts_duration_ba_f0 =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);
			buf->rts_duration_aa_f0 =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);
			buf->rts_duration_ba_f1 =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);
			buf->rts_duration_aa_f1 =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);
			buf->data.duration = buf->duration_aa;
			/* Get RTS Frame body */
			buf->data.frame_control =
					cpu_to_le16(IEEE80211_FTYPE_CTL |
						    IEEE80211_STYPE_RTS);

			ether_addr_copy(buf->data.ra, hdr->addr1);
			ether_addr_copy(buf->data.ta, hdr->addr2);
		} // if (byFBOption == AUTO_FB_NONE)
	} else if (byPktType == PK_TYPE_11A) {
		if (byFBOption == AUTO_FB_NONE) {
			struct vnt_rts_ab *buf = pvRTS;
			/* Get SignalField, ServiceField & Length */
			vnt_get_phy_field(pDevice, uRTSFrameLen,
					  pDevice->byTopOFDMBasicRate,
					  byPktType, &buf->ab);
			/* Get Duration */
			buf->duration =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);
			buf->data.duration = buf->duration;
			/* Get RTS Frame body */
			buf->data.frame_control =
					cpu_to_le16(IEEE80211_FTYPE_CTL |
						    IEEE80211_STYPE_RTS);

			ether_addr_copy(buf->data.ra, hdr->addr1);
			ether_addr_copy(buf->data.ta, hdr->addr2);
		} else {
			struct vnt_rts_a_fb *buf = pvRTS;
			/* Get SignalField, ServiceField & Length */
			vnt_get_phy_field(pDevice, uRTSFrameLen,
					  pDevice->byTopOFDMBasicRate,
					  byPktType, &buf->a);
			/* Get Duration */
			buf->duration =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);
			buf->rts_duration_f0 =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);
			buf->rts_duration_f1 =
				s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);
			buf->data.duration = buf->duration;
			/* Get RTS Frame body */
			buf->data.frame_control =
					cpu_to_le16(IEEE80211_FTYPE_CTL |
						    IEEE80211_STYPE_RTS);

			ether_addr_copy(buf->data.ra, hdr->addr1);
			ether_addr_copy(buf->data.ta, hdr->addr2);
		}
	} else if (byPktType == PK_TYPE_11B) {
		struct vnt_rts_ab *buf = pvRTS;
		/* Get SignalField, ServiceField & Length */
		vnt_get_phy_field(pDevice, uRTSFrameLen,
				  pDevice->byTopCCKBasicRate,
				  PK_TYPE_11B, &buf->ab);
		/* Get Duration */
		buf->duration =
			s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength,
					     byPktType, wCurrentRate, bNeedAck,
					     byFBOption);

		buf->data.duration = buf->duration;
		/* Get RTS Frame body */
		buf->data.frame_control =
			cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);

		ether_addr_copy(buf->data.ra, hdr->addr1);
		ether_addr_copy(buf->data.ta, hdr->addr2);
	}
}

static
void
s_vFillCTSHead(
	struct vnt_private *pDevice,
	unsigned int uDMAIdx,
	unsigned char byPktType,
	void *pvCTS,
	unsigned int cbFrameLength,
	bool bNeedAck,
	bool bDisCRC,
	unsigned short wCurrentRate,
	unsigned char byFBOption
)
{
	unsigned int uCTSFrameLen = 14;

	if (pvCTS == NULL)
		return;

	if (bDisCRC) {
		// When CRCDIS bit is on, H/W forgot to generate FCS for CTS frame,
		// in this case we need to decrease its length by 4.
		uCTSFrameLen -= 4;
	}

	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
		if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) {
			// Auto Fall back
			struct vnt_cts_fb *buf = pvCTS;
			/* Get SignalField, ServiceField & Length */
			vnt_get_phy_field(pDevice, uCTSFrameLen,
					  pDevice->byTopCCKBasicRate,
					  PK_TYPE_11B, &buf->b);

			buf->duration_ba =
				s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);

			/* Get CTSDuration_ba_f0 */
			buf->cts_duration_ba_f0 =
				s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);

			/* Get CTSDuration_ba_f1 */
			buf->cts_duration_ba_f1 =
				s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);

			/* Get CTS Frame body */
			buf->data.duration = buf->duration_ba;

			buf->data.frame_control =
				cpu_to_le16(IEEE80211_FTYPE_CTL |
					    IEEE80211_STYPE_CTS);

			buf->reserved2 = 0x0;

			ether_addr_copy(buf->data.ra,
					pDevice->abyCurrentNetAddr);
		} else { //if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA)
			struct vnt_cts *buf = pvCTS;
			/* Get SignalField, ServiceField & Length */
			vnt_get_phy_field(pDevice, uCTSFrameLen,
					  pDevice->byTopCCKBasicRate,
					  PK_TYPE_11B, &buf->b);

			/* Get CTSDuration_ba */
			buf->duration_ba =
				s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
						     cbFrameLength, byPktType,
						     wCurrentRate, bNeedAck,
						     byFBOption);

			/* Get CTS Frame body */
			buf->data.duration = buf->duration_ba;

			buf->data.frame_control =
				cpu_to_le16(IEEE80211_FTYPE_CTL |
					    IEEE80211_STYPE_CTS);

			buf->reserved2 = 0x0;
			ether_addr_copy(buf->data.ra,
					pDevice->abyCurrentNetAddr);
		}
	}
}

/*+
 *
 * Description:
 *      Generate FIFO control for MAC & Baseband controller
 *
 * Parameters:
 *  In:
 *      pDevice         - Pointer to adapter
 *      pTxDataHead     - Transmit Data Buffer
 *      pTxBufHead      - pTxBufHead
 *      pvRrvTime        - pvRrvTime
 *      pvRTS            - RTS Buffer
 *      pCTS            - CTS Buffer
 *      cbFrameSize     - Transmit Data Length (Hdr+Payload+FCS)
 *      bNeedACK        - If need ACK
 *      uDescIdx        - Desc Index
 *  Out:
 *      none
 *
 * Return Value: none
 *
 -*/
// unsigned int cbFrameSize,//Hdr+Payload+FCS
static
void
s_vGenerateTxParameter(
	struct vnt_private *pDevice,
	unsigned char byPktType,
	void *pTxBufHead,
	void *pvRrvTime,
	void *pvRTS,
	void *pvCTS,
	unsigned int cbFrameSize,
	bool bNeedACK,
	unsigned int uDMAIdx,
	void *psEthHeader,
	unsigned short wCurrentRate
)
{
	unsigned int cbMACHdLen = WLAN_HDR_ADDR3_LEN; //24
	unsigned short wFifoCtl;
	bool bDisCRC = false;
	unsigned char byFBOption = AUTO_FB_NONE;

	PSTxBufHead pFifoHead = (PSTxBufHead)pTxBufHead;

	pFifoHead->wReserved = wCurrentRate;
	wFifoCtl = pFifoHead->wFIFOCtl;

	if (wFifoCtl & FIFOCTL_CRCDIS)
		bDisCRC = true;

	if (wFifoCtl & FIFOCTL_AUTO_FB_0)
		byFBOption = AUTO_FB_0;
	else if (wFifoCtl & FIFOCTL_AUTO_FB_1)
		byFBOption = AUTO_FB_1;

	if (pDevice->bLongHeader)
		cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;

	if (!pvRrvTime)
		return;

	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
		if (pvRTS != NULL) { //RTS_need
			/* Fill RsvTime */
			struct vnt_rrv_time_rts *buf = pvRrvTime;

			buf->rts_rrv_time_aa = s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate);
			buf->rts_rrv_time_ba = s_uGetRTSCTSRsvTime(pDevice, 1, byPktType, cbFrameSize, wCurrentRate);
			buf->rts_rrv_time_bb = s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate);
			buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
			buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK);

			s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
		} else {//RTS_needless, PCF mode
			struct vnt_rrv_time_cts *buf = pvRrvTime;

			buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
			buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK);
			buf->cts_rrv_time_ba = s_uGetRTSCTSRsvTime(pDevice, 3, byPktType, cbFrameSize, wCurrentRate);

			//Fill CTS
			s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption);
		}
	} else if (byPktType == PK_TYPE_11A) {
		if (pvRTS != NULL) {//RTS_need, non PCF mode
			struct vnt_rrv_time_ab *buf = pvRrvTime;

			buf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate);
			buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);

			//Fill RTS
			s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
		} else if (pvRTS == NULL) {//RTS_needless, non PCF mode
			struct vnt_rrv_time_ab *buf = pvRrvTime;

			buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK);
		}
	} else if (byPktType == PK_TYPE_11B) {
		if ((pvRTS != NULL)) {//RTS_need, non PCF mode
			struct vnt_rrv_time_ab *buf = pvRrvTime;

			buf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate);
			buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK);

			//Fill RTS
			s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
		} else { //RTS_needless, non PCF mode
			struct vnt_rrv_time_ab *buf = pvRrvTime;

			buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK);
		}
	}
}

static unsigned int
s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
		  unsigned char *pbyTxBufferAddr, unsigned int cbFrameBodySize,
		  unsigned int uDMAIdx, PSTxDesc pHeadTD,
		  PSEthernetHeader psEthHeader, unsigned char *pPacket,
		  bool bNeedEncrypt, PSKeyItem pTransmitKey,
		  unsigned int is_pspoll, unsigned int *puMACfragNum)
{
	PDEVICE_TD_INFO td_info = pHeadTD->pTDInfo;
	struct sk_buff *skb = td_info->skb;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	struct vnt_tx_fifo_head *tx_buffer_head =
			(struct vnt_tx_fifo_head *)td_info->buf;
	u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl);
	unsigned int cbFrameSize;
	__le16 uDuration;
	unsigned char *pbyBuffer;
	unsigned int uLength = 0;
	unsigned int cbMICHDR = 0;
	unsigned int uMACfragNum = 1;
	unsigned int uPadding = 0;
	unsigned int cbReqCount = 0;
	bool bNeedACK = (bool)(fifo_ctl & FIFOCTL_NEEDACK);
	bool bRTS = (bool)(fifo_ctl & FIFOCTL_RTS);
	PSTxDesc       ptdCurr;
	unsigned int cbHeaderLength = 0;
	void *pvRrvTime;
	struct vnt_mic_hdr *pMICHDR;
	void *pvRTS;
	void *pvCTS;
	void *pvTxDataHd;
	unsigned short wTxBufSize;   // FFinfo size
	unsigned char byFBOption = AUTO_FB_NONE;

	pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL;

	cbFrameSize = skb->len + 4;

	if (info->control.hw_key) {
		switch (info->control.hw_key->cipher) {
		case WLAN_CIPHER_SUITE_CCMP:
			cbMICHDR = sizeof(struct vnt_mic_hdr);
		default:
			break;
		}

		cbFrameSize += info->control.hw_key->icv_len;

		if (pDevice->byLocalID > REV_ID_VT3253_A1) {
			//MAC Header should be padding 0 to DW alignment.
			uPadding = 4 - (ieee80211_get_hdrlen_from_skb(skb) % 4);
			uPadding %= 4;
		}
	}

	//
	// Use for AUTO FALL BACK
	//
	if (fifo_ctl & FIFOCTL_AUTO_FB_0)
		byFBOption = AUTO_FB_0;
	else if (fifo_ctl & FIFOCTL_AUTO_FB_1)
		byFBOption = AUTO_FB_1;

	//////////////////////////////////////////////////////
	//Set RrvTime/RTS/CTS Buffer
	wTxBufSize = sizeof(STxBufHead);
	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet

		if (byFBOption == AUTO_FB_NONE) {
			if (bRTS == true) {//RTS_need
				pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
				pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts));
				pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
				pvCTS = NULL;
				pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
							cbMICHDR + sizeof(struct vnt_rts_g));
				cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
							cbMICHDR + sizeof(struct vnt_rts_g) +
							sizeof(struct vnt_tx_datahead_g);
			} else { //RTS_needless
				pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
				pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts));
				pvRTS = NULL;
				pvCTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
				pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
						sizeof(struct vnt_rrv_time_cts) + cbMICHDR + sizeof(struct vnt_cts));
				cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
							cbMICHDR + sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
			}
		} else {
			// Auto Fall Back
			if (bRTS == true) {//RTS_need
				pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
				pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts));
				pvRTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
				pvCTS = NULL;
				pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
					cbMICHDR + sizeof(struct vnt_rts_g_fb));
				cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
					cbMICHDR + sizeof(struct vnt_rts_g_fb) + sizeof(struct vnt_tx_datahead_g_fb);
			} else { //RTS_needless
				pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
				pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts));
				pvRTS = NULL;
				pvCTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
				pvTxDataHd = (void  *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
					cbMICHDR + sizeof(struct vnt_cts_fb));
				cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
					cbMICHDR + sizeof(struct vnt_cts_fb) + sizeof(struct vnt_tx_datahead_g_fb);
			}
		} // Auto Fall Back
	} else {//802.11a/b packet

		if (byFBOption == AUTO_FB_NONE) {
			if (bRTS == true) {
				pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
				pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
				pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
				pvCTS = NULL;
				pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
					sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_ab));
				cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
					cbMICHDR + sizeof(struct vnt_rts_ab) + sizeof(struct vnt_tx_datahead_ab);
			} else { //RTS_needless, need MICHDR
				pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
				pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
				pvRTS = NULL;
				pvCTS = NULL;
				pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
				cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
					cbMICHDR + sizeof(struct vnt_tx_datahead_ab);
			}
		} else {
			// Auto Fall Back
			if (bRTS == true) {//RTS_need
				pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
				pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
				pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
				pvCTS = NULL;
				pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
					sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_a_fb));
				cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
					cbMICHDR + sizeof(struct vnt_rts_a_fb) + sizeof(struct vnt_tx_datahead_a_fb);
			} else { //RTS_needless
				pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
				pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
				pvRTS = NULL;
				pvCTS = NULL;
				pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
				cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
					cbMICHDR + sizeof(struct vnt_tx_datahead_a_fb);
			}
		} // Auto Fall Back
	}

	td_info->mic_hdr = pMICHDR;

	memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderLength - wTxBufSize));

	/* Fill FIFO,RrvTime,RTS,and CTS */
	s_vGenerateTxParameter(pDevice, byPktType, tx_buffer_head, pvRrvTime, pvRTS, pvCTS,
			       cbFrameSize, bNeedACK, uDMAIdx, hdr, pDevice->wCurrentRate);
	/* Fill DataHead */
	uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
				    0, 0, uMACfragNum, byFBOption, pDevice->wCurrentRate);

	hdr->duration_id = uDuration;

	cbReqCount = cbHeaderLength + uPadding + cbFrameBodySize;
	pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
	uLength = cbHeaderLength + uPadding;

	/* Copy the Packet into a tx Buffer */
	memcpy((pbyBuffer + uLength), pPacket, cbFrameBodySize);

	ptdCurr = (PSTxDesc)pHeadTD;

	ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding;
	ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
	ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
	ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma);
	/* Set TSR1 & ReqCount in TxDescHead */
	ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU);
	ptdCurr->m_td1TD1.wReqCount = cpu_to_le16((unsigned short)(cbReqCount));

	*puMACfragNum = uMACfragNum;

	return cbHeaderLength;
}

void
vGenerateFIFOHeader(struct vnt_private *pDevice, unsigned char byPktType,
		    unsigned char *pbyTxBufferAddr, bool bNeedEncrypt,
		    unsigned int cbPayloadSize, unsigned int uDMAIdx,
		    PSTxDesc pHeadTD, PSEthernetHeader psEthHeader, unsigned char *pPacket,
		    PSKeyItem pTransmitKey, unsigned int uNodeIndex, unsigned int *puMACfragNum,
		    unsigned int *pcbHeaderSize)
{
	unsigned int wTxBufSize;       // FFinfo size
	bool bNeedACK;
	bool bIsAdhoc;
	unsigned short cbMacHdLen;
	PSTxBufHead     pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;

	wTxBufSize = sizeof(STxBufHead);

	memset(pTxBufHead, 0, wTxBufSize);
	//Set FIFOCTL_NEEDACK

	if ((pDevice->op_mode == NL80211_IFTYPE_ADHOC) ||
	    (pDevice->op_mode == NL80211_IFTYPE_AP)) {
		if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0]))) {
			bNeedACK = false;
			pTxBufHead->wFIFOCtl = pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK);
		} else {
			bNeedACK = true;
			pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
		}
		bIsAdhoc = true;
	} else {
		// MSDUs in Infra mode always need ACK
		bNeedACK = true;
		pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
		bIsAdhoc = false;
	}

	pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN;
	pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);

	//Set FIFOCTL_LHEAD
	if (pDevice->bLongHeader)
		pTxBufHead->wFIFOCtl |= FIFOCTL_LHEAD;

	//Set FIFOCTL_GENINT

	pTxBufHead->wFIFOCtl |= FIFOCTL_GENINT;

	//Set FIFOCTL_ISDMA0
	if (TYPE_TXDMA0 == uDMAIdx)
		pTxBufHead->wFIFOCtl |= FIFOCTL_ISDMA0;

	//Set FRAGCTL_MACHDCNT
	if (pDevice->bLongHeader)
		cbMacHdLen = WLAN_HDR_ADDR3_LEN + 6;
	else
		cbMacHdLen = WLAN_HDR_ADDR3_LEN;

	pTxBufHead->wFragCtl |= cpu_to_le16((unsigned short)(cbMacHdLen << 10));

	//Set packet type
	if (byPktType == PK_TYPE_11A) //0000 0000 0000 0000
		;
	else if (byPktType == PK_TYPE_11B) //0000 0001 0000 0000
		pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
	else if (byPktType == PK_TYPE_11GB) //0000 0010 0000 0000
		pTxBufHead->wFIFOCtl |= FIFOCTL_11GB;
	else if (byPktType == PK_TYPE_11GA) //0000 0011 0000 0000
		pTxBufHead->wFIFOCtl |= FIFOCTL_11GA;

	//Set FIFOCTL_GrpAckPolicy
	if (pDevice->bGrpAckPolicy == true) //0000 0100 0000 0000
		pTxBufHead->wFIFOCtl |=	FIFOCTL_GRPACK;

	//Set Auto Fallback Ctl
	if (pDevice->wCurrentRate >= RATE_18M) {
		if (pDevice->byAutoFBCtrl == AUTO_FB_0)
			pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0;
		else if (pDevice->byAutoFBCtrl == AUTO_FB_1)
			pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1;
	}

	//Set FRAGCTL_WEPTYP
	pDevice->bAES = false;

	//Set FRAGCTL_WEPTYP
	if (pDevice->byLocalID > REV_ID_VT3253_A1) {
		if ((bNeedEncrypt) && (pTransmitKey != NULL))  { //WEP enabled
			if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
				pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
			} else if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { //WEP40 or WEP104
				if (pTransmitKey->uKeyLength != WLAN_WEP232_KEYLEN)
					pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
			} else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { //CCMP
				pTxBufHead->wFragCtl |= FRAGCTL_AES;
			}
		}
	}

	RFbSetPower(pDevice, pDevice->wCurrentRate, pDevice->byCurrentCh);

	pTxBufHead->byTxPower = pDevice->byCurPwr;

	*pcbHeaderSize = s_cbFillTxBufHead(pDevice, byPktType, pbyTxBufferAddr, cbPayloadSize,
					   uDMAIdx, pHeadTD, psEthHeader, pPacket, bNeedEncrypt,
					   pTransmitKey, uNodeIndex, puMACfragNum);
}

/*+
 *
 * Description:
 *      Translate 802.3 to 802.11 header
 *
 * Parameters:
 *  In:
 *      pDevice         - Pointer to adapter
 *      dwTxBufferAddr  - Transmit Buffer
 *      pPacket         - Packet from upper layer
 *      cbPacketSize    - Transmit Data Length
 *  Out:
 *      pcbHeadSize         - Header size of MAC&Baseband control and 802.11 Header
 *      pcbAppendPayload    - size of append payload for 802.1H translation
 *
 * Return Value: none
 *
 -*/

void
vGenerateMACHeader(
	struct vnt_private *pDevice,
	unsigned char *pbyBufferAddr,
	__le16 wDuration,
	PSEthernetHeader psEthHeader,
	bool bNeedEncrypt,
	unsigned short wFragType,
	unsigned int uDMAIdx,
	unsigned int uFragIdx
)
{
	PS802_11Header  pMACHeader = (PS802_11Header)pbyBufferAddr;

	memset(pMACHeader, 0, (sizeof(S802_11Header)));

	if (uDMAIdx == TYPE_ATIMDMA)
		pMACHeader->wFrameCtl = TYPE_802_11_ATIM;
	else
		pMACHeader->wFrameCtl = TYPE_802_11_DATA;

	if (pDevice->op_mode == NL80211_IFTYPE_AP) {
		ether_addr_copy(&(pMACHeader->abyAddr1[0]),
				&(psEthHeader->abyDstAddr[0]));
		ether_addr_copy(&(pMACHeader->abyAddr2[0]),
				&(pDevice->abyBSSID[0]));
		ether_addr_copy(&(pMACHeader->abyAddr3[0]),
				&(psEthHeader->abySrcAddr[0]));
		pMACHeader->wFrameCtl |= FC_FROMDS;
	} else {
		if (pDevice->op_mode == NL80211_IFTYPE_ADHOC) {
			ether_addr_copy(&(pMACHeader->abyAddr1[0]),
					&(psEthHeader->abyDstAddr[0]));
			ether_addr_copy(&(pMACHeader->abyAddr2[0]),
					&(psEthHeader->abySrcAddr[0]));
			ether_addr_copy(&(pMACHeader->abyAddr3[0]),
					&(pDevice->abyBSSID[0]));
		} else {
			ether_addr_copy(&(pMACHeader->abyAddr3[0]),
					&(psEthHeader->abyDstAddr[0]));
			ether_addr_copy(&(pMACHeader->abyAddr2[0]),
					&(psEthHeader->abySrcAddr[0]));
			ether_addr_copy(&(pMACHeader->abyAddr1[0]),
					&(pDevice->abyBSSID[0]));
			pMACHeader->wFrameCtl |= FC_TODS;
		}
	}

	if (bNeedEncrypt)
		pMACHeader->wFrameCtl |= cpu_to_le16((unsigned short)WLAN_SET_FC_ISWEP(1));

	pMACHeader->wDurationID = le16_to_cpu(wDuration);

	if (pDevice->bLongHeader) {
		PWLAN_80211HDR_A4 pMACA4Header  = (PWLAN_80211HDR_A4) pbyBufferAddr;

		pMACHeader->wFrameCtl |= (FC_TODS | FC_FROMDS);
		memcpy(pMACA4Header->abyAddr4, pDevice->abyBSSID, WLAN_ADDR_LEN);
	}
	pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);

	//Set FragNumber in Sequence Control
	pMACHeader->wSeqCtl |= cpu_to_le16((unsigned short)uFragIdx);

	if ((wFragType == FRAGCTL_ENDFRAG) || (wFragType == FRAGCTL_NONFRAG)) {
		pDevice->wSeqCounter++;
		if (pDevice->wSeqCounter > 0x0fff)
			pDevice->wSeqCounter = 0;
	}

	if ((wFragType == FRAGCTL_STAFRAG) || (wFragType == FRAGCTL_MIDFRAG)) //StartFrag or MidFrag
		pMACHeader->wFrameCtl |= FC_MOREFRAG;
}

CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice, PSTxMgmtPacket pPacket)
{
	PSTxDesc        pFrstTD;
	unsigned char byPktType;
	unsigned char *pbyTxBufferAddr;
	void *pvRTS;
	struct vnt_cts *pCTS;
	void *pvTxDataHd;
	unsigned int uDuration;
	unsigned int cbReqCount;
	PS802_11Header  pMACHeader;
	unsigned int cbHeaderSize;
	unsigned int cbFrameBodySize;
	bool bNeedACK;
	bool bIsPSPOLL = false;
	PSTxBufHead     pTxBufHead;
	unsigned int cbFrameSize;
	unsigned int cbIVlen = 0;
	unsigned int cbICVlen = 0;
	unsigned int cbMIClen = 0;
	unsigned int cbFCSlen = 4;
	unsigned int uPadding = 0;
	unsigned short wTxBufSize;
	unsigned int cbMacHdLen;
	SEthernetHeader sEthHeader;
	void *pvRrvTime;
	void *pMICHDR;
	PSMgmtObject    pMgmt = pDevice->pMgmt;
	unsigned short wCurrentRate = RATE_1M;

	if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0)
		return CMD_STATUS_RESOURCES;

	pFrstTD = pDevice->apCurrTD[TYPE_TXDMA0];
	pbyTxBufferAddr = (unsigned char *)pFrstTD->pTDInfo->buf;
	cbFrameBodySize = pPacket->cbPayloadLen;
	pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
	wTxBufSize = sizeof(STxBufHead);
	memset(pTxBufHead, 0, wTxBufSize);

	if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
		wCurrentRate = RATE_6M;
		byPktType = PK_TYPE_11A;
	} else {
		wCurrentRate = RATE_1M;
		byPktType = PK_TYPE_11B;
	}

	// SetPower will cause error power TX state for OFDM Date packet in TX buffer.
	// 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability.
	//                    And cmd timer will wait data pkt TX finish before scanning so it's OK
	//                    to set power here.
	if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING)
		RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh);
	else
		RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel);

	pTxBufHead->byTxPower = pDevice->byCurPwr;
	//+++++++++++++++++++++ Patch VT3253 A1 performance +++++++++++++++++++++++++++
	if (pDevice->byFOETuning) {
		if ((pPacket->p80211Header->sA3.wFrameCtl & TYPE_DATE_NULL) == TYPE_DATE_NULL) {
			wCurrentRate = RATE_24M;
			byPktType = PK_TYPE_11GA;
		}
	}

	//Set packet type
	if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
		pTxBufHead->wFIFOCtl = 0;
	} else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
		pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
	} else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000
		pTxBufHead->wFIFOCtl |= FIFOCTL_11GB;
	} else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000
		pTxBufHead->wFIFOCtl |= FIFOCTL_11GA;
	}

	pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN;
	pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);

	if (is_multicast_ether_addr(&(pPacket->p80211Header->sA3.abyAddr1[0])))
		bNeedACK = false;
	else {
		bNeedACK = true;
		pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
	}

	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) ||
	    (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
		pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY;
	}

	pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0);

	if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) {
		bIsPSPOLL = true;
		cbMacHdLen = WLAN_HDR_ADDR2_LEN;
	} else {
		cbMacHdLen = WLAN_HDR_ADDR3_LEN;
	}

	//Set FRAGCTL_MACHDCNT
	pTxBufHead->wFragCtl |= cpu_to_le16((unsigned short)(cbMacHdLen << 10));

	// Notes:
	// Although spec says MMPDU can be fragmented; In most cases,
	// no one will send a MMPDU under fragmentation. With RTS may occur.
	pDevice->bAES = false;  //Set FRAGCTL_WEPTYP

	if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) {
		if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) {
			cbIVlen = 4;
			cbICVlen = 4;
			pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
		} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
			cbIVlen = 8;//IV+ExtIV
			cbMIClen = 8;
			cbICVlen = 4;
			pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
			//We need to get seed here for filling TxKey entry.
		} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
			cbIVlen = 8;//RSN Header
			cbICVlen = 8;//MIC
			pTxBufHead->wFragCtl |= FRAGCTL_AES;
			pDevice->bAES = true;
		}
		//MAC Header should be padding 0 to DW alignment.
		uPadding = 4 - (cbMacHdLen%4);
		uPadding %= 4;
	}

	cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen;

	//Set FIFOCTL_GrpAckPolicy
	if (pDevice->bGrpAckPolicy == true) //0000 0100 0000 0000
		pTxBufHead->wFIFOCtl |=	FIFOCTL_GRPACK;

	//the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()

	//Set RrvTime/RTS/CTS Buffer
	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
		pvRrvTime = (void *) (pbyTxBufferAddr + wTxBufSize);
		pMICHDR = NULL;
		pvRTS = NULL;
		pCTS = (struct vnt_cts *)(pbyTxBufferAddr + wTxBufSize +
					sizeof(struct vnt_rrv_time_cts));
		pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
				sizeof(struct vnt_rrv_time_cts) + sizeof(struct vnt_cts));
		cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
				sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
	} else { // 802.11a/b packet
		pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
		pMICHDR = NULL;
		pvRTS = NULL;
		pCTS = NULL;
		pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
			sizeof(struct vnt_rrv_time_ab));
		cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
			sizeof(struct vnt_tx_datahead_ab);
	}

	memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderSize - wTxBufSize));

	ether_addr_copy(&(sEthHeader.abyDstAddr[0]),
			&(pPacket->p80211Header->sA3.abyAddr1[0]));
	ether_addr_copy(&(sEthHeader.abySrcAddr[0]),
			&(pPacket->p80211Header->sA3.abyAddr2[0]));
	//=========================
	//    No Fragmentation
	//=========================
	pTxBufHead->wFragCtl |= (unsigned short)FRAGCTL_NONFRAG;

	//Fill FIFO,RrvTime,RTS,and CTS
	s_vGenerateTxParameter(pDevice, byPktType, pbyTxBufferAddr, pvRrvTime, pvRTS, pCTS,
			       cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, wCurrentRate);

	//Fill DataHead
	uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
				    0, 0, 1, AUTO_FB_NONE, wCurrentRate);

	pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize);

	cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize;

	if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) {
		unsigned char *pbyIVHead;
		unsigned char *pbyPayloadHead;
		unsigned char *pbyBSSID;
		PSKeyItem       pTransmitKey = NULL;

		pbyIVHead = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding);
		pbyPayloadHead = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen);

		//Fill TXKEY
		//Kyle: Need fix: TKIP and AES did't encrypt Mnt Packet.
		//s_vFillTxKey(pDevice, (unsigned char *)pTxBufHead->adwTxKey, NULL);

		//Fill IV(ExtIV,RSNHDR)
		//s_vFillPrePayload(pDevice, pbyIVHead, NULL);
		//---------------------------
		// S/W or H/W Encryption
		//---------------------------
		do {
			if ((pDevice->op_mode == NL80211_IFTYPE_STATION) &&
			    (pDevice->bLinkPass == true)) {
				pbyBSSID = pDevice->abyBSSID;
				// get pairwise key
				if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
					// get group key
					if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) {
						pr_debug("Get GTK\n");
						break;
					}
				} else {
					pr_debug("Get PTK\n");
					break;
				}
			}
			// get group key
			pbyBSSID = pDevice->abyBroadcastAddr;
			if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
				pTransmitKey = NULL;
				pr_debug("KEY is NULL. OP Mode[%d]\n",
					 pDevice->op_mode);
			} else {
				pr_debug("Get GTK\n");
			}
		} while (false);
		//Fill TXKEY
		s_vFillTxKey(pDevice, (unsigned char *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
			     (unsigned char *)pMACHeader, (unsigned short)cbFrameBodySize, NULL);

		memcpy(pMACHeader, pPacket->p80211Header, cbMacHdLen);
		memcpy(pbyPayloadHead, ((unsigned char *)(pPacket->p80211Header) + cbMacHdLen),
		       cbFrameBodySize);
	} else {
		// Copy the Packet into a tx Buffer
		memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen);
	}

	pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
	pDevice->wSeqCounter++;
	if (pDevice->wSeqCounter > 0x0fff)
		pDevice->wSeqCounter = 0;

	if (bIsPSPOLL) {
		// The MAC will automatically replace the Duration-field of MAC header by Duration-field
		// of  FIFO control header.
		// This will cause AID-field of PS-POLL packet to be incorrect (Because PS-POLL's AID field is
		// in the same place of other packet's Duration-field).
		// And it will cause Cisco-AP to issue Disassociation-packet
		if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
			((struct vnt_tx_datahead_g *)pvTxDataHd)->duration_a = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
			((struct vnt_tx_datahead_g *)pvTxDataHd)->duration_b = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
		} else {
			((struct vnt_tx_datahead_ab *)pvTxDataHd)->duration = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
		}
	}

	// first TD is the only TD
	//Set TSR1 & ReqCount in TxDescHead
	pFrstTD->m_td1TD1.byTCR = (TCR_STP | TCR_EDP | EDMSDU);
	pFrstTD->pTDInfo->skb_dma = pFrstTD->pTDInfo->buf_dma;
	pFrstTD->m_td1TD1.wReqCount = cpu_to_le16((unsigned short)(cbReqCount));
	pFrstTD->buff_addr = cpu_to_le32(pFrstTD->pTDInfo->skb_dma);
	pFrstTD->pTDInfo->byFlags = 0;

	if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
		// Disable PS
		MACbPSWakeup(pDevice->PortOffset);
	}
	pDevice->bPWBitOn = false;

	wmb();
	pFrstTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
	wmb();

	pDevice->iTDUsed[TYPE_TXDMA0]++;

	if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 1)
		pr_debug(" available td0 <= 1\n");

	pDevice->apCurrTD[TYPE_TXDMA0] = pFrstTD->next;

	pDevice->nTxDataTimeCout = 0; //2008-8-21 chester <add> for send null packet

	// Poll Transmit the adapter
	MACvTransmit0(pDevice->PortOffset);

	return CMD_STATUS_PENDING;
}

CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice, PSTxMgmtPacket pPacket)
{
	unsigned char byPktType;
	unsigned char *pbyBuffer = (unsigned char *)pDevice->tx_beacon_bufs;
	unsigned int cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN;
	unsigned int cbHeaderSize = 0;
	struct vnt_tx_short_buf_head *short_head =
				(struct vnt_tx_short_buf_head *)pbyBuffer;
	PS802_11Header   pMACHeader;
	unsigned short wCurrentRate;

	memset(short_head, 0, sizeof(*short_head));

	if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
		wCurrentRate = RATE_6M;
		byPktType = PK_TYPE_11A;
	} else {
		wCurrentRate = RATE_2M;
		byPktType = PK_TYPE_11B;
	}

	//Set Preamble type always long
	pDevice->byPreambleType = PREAMBLE_LONG;

	/* Set FIFOCTL_GENINT */
	short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT);

	/* Set packet type & Get Duration */
	if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
		short_head->duration =
			cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A,
				    cbFrameSize, byPktType, wCurrentRate, false,
				    0, 0, 1, AUTO_FB_NONE));
	} else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
		short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_11B);

		short_head->duration =
			cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B,
				    cbFrameSize, byPktType, wCurrentRate, false,
				    0, 0, 1, AUTO_FB_NONE));
	}

	vnt_get_phy_field(pDevice, cbFrameSize,
			  wCurrentRate, byPktType, &short_head->ab);

	/* Get TimeStampOff */
	short_head->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
	cbHeaderSize = sizeof(struct vnt_tx_short_buf_head);

	//Generate Beacon Header
	pMACHeader = (PS802_11Header)(pbyBuffer + cbHeaderSize);
	memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen);

	pMACHeader->wDurationID = 0;
	pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
	pDevice->wSeqCounter++;
	if (pDevice->wSeqCounter > 0x0fff)
		pDevice->wSeqCounter = 0;

	// Set Beacon buffer length
	pDevice->wBCNBufLen = pPacket->cbMPDULen + cbHeaderSize;

	MACvSetCurrBCNTxDescAddr(pDevice->PortOffset, (pDevice->tx_beacon_dma));

	MACvSetCurrBCNLength(pDevice->PortOffset, pDevice->wBCNBufLen);
	// Set auto Transmit on
	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
	// Poll Transmit the adapter
	MACvTransmitBCN(pDevice->PortOffset);

	return CMD_STATUS_PENDING;
}

unsigned int
cbGetFragCount(
	struct vnt_private *pDevice,
	PSKeyItem        pTransmitKey,
	unsigned int cbFrameBodySize,
	PSEthernetHeader psEthHeader
)
{
	unsigned int cbMACHdLen;
	unsigned int cbFrameSize;
	unsigned int cbFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS
	unsigned int cbFragPayloadSize;
	unsigned int cbLastFragPayloadSize;
	unsigned int cbIVlen = 0;
	unsigned int cbICVlen = 0;
	unsigned int cbMIClen = 0;
	unsigned int cbFCSlen = 4;
	unsigned int uMACfragNum = 1;
	bool bNeedACK;

	if ((pDevice->op_mode == NL80211_IFTYPE_ADHOC) ||
	    (pDevice->op_mode == NL80211_IFTYPE_AP)) {
		if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0])))
			bNeedACK = false;
		else
			bNeedACK = true;
	} else {
		// MSDUs in Infra mode always need ACK
		bNeedACK = true;
	}

	if (pDevice->bLongHeader)
		cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;
	else
		cbMACHdLen = WLAN_HDR_ADDR3_LEN;

	if (pDevice->bEncryptionEnable == true) {
		if (pTransmitKey == NULL) {
			if ((pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) ||
			    (pDevice->pMgmt->eAuthenMode < WMAC_AUTH_WPA)) {
				cbIVlen = 4;
				cbICVlen = 4;
			} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
				cbIVlen = 8;//IV+ExtIV
				cbMIClen = 8;
				cbICVlen = 4;
			} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
				cbIVlen = 8;//RSN Header
				cbICVlen = 8;//MIC
			}
		} else if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
			cbIVlen = 4;
			cbICVlen = 4;
		} else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
			cbIVlen = 8;//IV+ExtIV
			cbMIClen = 8;
			cbICVlen = 4;
		} else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) {
			cbIVlen = 8;//RSN Header
			cbICVlen = 8;//MIC
		}
	}

	cbFrameSize = cbMACHdLen + cbIVlen + (cbFrameBodySize + cbMIClen) + cbICVlen + cbFCSlen;

	if ((cbFrameSize > pDevice->wFragmentationThreshold) && (bNeedACK == true)) {
		// Fragmentation
		cbFragmentSize = pDevice->wFragmentationThreshold;
		cbFragPayloadSize = cbFragmentSize - cbMACHdLen - cbIVlen - cbICVlen - cbFCSlen;
		uMACfragNum = (unsigned short) ((cbFrameBodySize + cbMIClen) / cbFragPayloadSize);
		cbLastFragPayloadSize = (cbFrameBodySize + cbMIClen) % cbFragPayloadSize;
		if (cbLastFragPayloadSize == 0)
			cbLastFragPayloadSize = cbFragPayloadSize;
		else
			uMACfragNum++;
	}
	return uMACfragNum;
}

void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb,
		    unsigned char *pbMPDU, unsigned int cbMPDULen)
{
	PSTxDesc        pFrstTD;
	unsigned char byPktType;
	unsigned char *pbyTxBufferAddr;
	void *pvRTS;
	void *pvCTS;
	void *pvTxDataHd;
	unsigned int uDuration;
	unsigned int cbReqCount;
	PS802_11Header  pMACHeader;
	unsigned int cbHeaderSize;
	unsigned int cbFrameBodySize;
	bool bNeedACK;
	bool bIsPSPOLL = false;
	PSTxBufHead     pTxBufHead;
	unsigned int cbFrameSize;
	unsigned int cbIVlen = 0;
	unsigned int cbICVlen = 0;
	unsigned int cbMIClen = 0;
	unsigned int cbFCSlen = 4;
	unsigned int uPadding = 0;
	unsigned int cbMICHDR = 0;
	unsigned int uLength = 0;
	u32 dwMICKey0, dwMICKey1;
	u32 dwMIC_Priority;
	u32 *pdwMIC_L;
	u32 *pdwMIC_R;
	unsigned short wTxBufSize;
	unsigned int cbMacHdLen;
	SEthernetHeader sEthHeader;
	void *pvRrvTime;
	void *pMICHDR;
	PSMgmtObject    pMgmt = pDevice->pMgmt;
	unsigned short wCurrentRate = RATE_1M;
	PUWLAN_80211HDR  p80211Header;
	unsigned int uNodeIndex = 0;
	bool bNodeExist = false;
	SKeyItem        STempKey;
	PSKeyItem       pTransmitKey = NULL;
	unsigned char *pbyIVHead;
	unsigned char *pbyPayloadHead;
	unsigned char *pbyMacHdr;

	unsigned int cbExtSuppRate = 0;

	pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL;

	if (cbMPDULen <= WLAN_HDR_ADDR3_LEN)
		cbFrameBodySize = 0;
	else
		cbFrameBodySize = cbMPDULen - WLAN_HDR_ADDR3_LEN;

	p80211Header = (PUWLAN_80211HDR)pbMPDU;

	pFrstTD = pDevice->apCurrTD[TYPE_TXDMA0];
	pbyTxBufferAddr = (unsigned char *)pFrstTD->pTDInfo->buf;
	pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
	wTxBufSize = sizeof(STxBufHead);
	memset(pTxBufHead, 0, wTxBufSize);

	if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
		wCurrentRate = RATE_6M;
		byPktType = PK_TYPE_11A;
	} else {
		wCurrentRate = RATE_1M;
		byPktType = PK_TYPE_11B;
	}

	// SetPower will cause error power TX state for OFDM Date packet in TX buffer.
	// 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability.
	//                    And cmd timer will wait data pkt TX to finish before scanning so it's OK
	//                    to set power here.
	if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING)
		RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh);
	else
		RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel);

	pTxBufHead->byTxPower = pDevice->byCurPwr;

	//+++++++++++++++++++++ Patch VT3253 A1 performance +++++++++++++++++++++++++++
	if (pDevice->byFOETuning) {
		if ((p80211Header->sA3.wFrameCtl & TYPE_DATE_NULL) == TYPE_DATE_NULL) {
			wCurrentRate = RATE_24M;
			byPktType = PK_TYPE_11GA;
		}
	}

	pr_debug("vDMA0_tx_80211: p80211Header->sA3.wFrameCtl = %x\n",
		 p80211Header->sA3.wFrameCtl);

	//Set packet type
	if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
		pTxBufHead->wFIFOCtl = 0;
	} else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
		pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
	} else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000
		pTxBufHead->wFIFOCtl |= FIFOCTL_11GB;
	} else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000
		pTxBufHead->wFIFOCtl |= FIFOCTL_11GA;
	}

	pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN;
	pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);

	if (is_multicast_ether_addr(&(p80211Header->sA3.abyAddr1[0]))) {
		bNeedACK = false;
		if (pDevice->bEnableHostWEP) {
			uNodeIndex = 0;
			bNodeExist = true;
		}
	} else {
		if (pDevice->bEnableHostWEP) {
			if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, (unsigned char *)(p80211Header->sA3.abyAddr1), &uNodeIndex))
				bNodeExist = true;
		}
		bNeedACK = true;
		pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
	}

	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) ||
	    (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
		pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY;
	}

	pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0);

	if ((p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) {
		bIsPSPOLL = true;
		cbMacHdLen = WLAN_HDR_ADDR2_LEN;
	} else {
		cbMacHdLen = WLAN_HDR_ADDR3_LEN;
	}

	// hostapd deamon ext support rate patch
	if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) {
		if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0)
			cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN;

		if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0)
			cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN;

		if (cbExtSuppRate > 0)
			cbFrameBodySize = WLAN_ASSOCRESP_OFF_SUPP_RATES;
	}

	//Set FRAGCTL_MACHDCNT
	pTxBufHead->wFragCtl |= cpu_to_le16((unsigned short)cbMacHdLen << 10);

	// Notes:
	// Although spec says MMPDU can be fragmented; In most cases,
	// no one will send a MMPDU under fragmentation. With RTS may occur.
	pDevice->bAES = false;  //Set FRAGCTL_WEPTYP

	if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) {
		if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) {
			cbIVlen = 4;
			cbICVlen = 4;
			pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
		} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
			cbIVlen = 8;//IV+ExtIV
			cbMIClen = 8;
			cbICVlen = 4;
			pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
			//We need to get seed here for filling TxKey entry.
		} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
			cbIVlen = 8;//RSN Header
			cbICVlen = 8;//MIC
			cbMICHDR = sizeof(struct vnt_mic_hdr);
			pTxBufHead->wFragCtl |= FRAGCTL_AES;
			pDevice->bAES = true;
		}
		//MAC Header should be padding 0 to DW alignment.
		uPadding = 4 - (cbMacHdLen%4);
		uPadding %= 4;
	}

	cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen + cbExtSuppRate;

	//Set FIFOCTL_GrpAckPolicy
	if (pDevice->bGrpAckPolicy == true) //0000 0100 0000 0000
		pTxBufHead->wFIFOCtl |=	FIFOCTL_GRPACK;

	//the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()

	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet

		pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
		pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize +
					sizeof(struct vnt_rrv_time_cts));
		pvRTS = NULL;
		pvCTS = (struct vnt_cts *)(pbyTxBufferAddr + wTxBufSize +
				sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
		pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
			sizeof(struct vnt_rrv_time_cts) + cbMICHDR + sizeof(struct vnt_cts));
		cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
				cbMICHDR + sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);

	} else {//802.11a/b packet

		pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
		pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr +
				wTxBufSize + sizeof(struct vnt_rrv_time_ab));
		pvRTS = NULL;
		pvCTS = NULL;
		pvTxDataHd = (void *)(pbyTxBufferAddr +
			wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
		cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
				cbMICHDR + sizeof(struct vnt_tx_datahead_ab);

	}

	memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderSize - wTxBufSize));
	ether_addr_copy(&(sEthHeader.abyDstAddr[0]),
			&(p80211Header->sA3.abyAddr1[0]));
	ether_addr_copy(&(sEthHeader.abySrcAddr[0]),
			&(p80211Header->sA3.abyAddr2[0]));
	//=========================
	//    No Fragmentation
	//=========================
	pTxBufHead->wFragCtl |= (unsigned short)FRAGCTL_NONFRAG;

	//Fill FIFO,RrvTime,RTS,and CTS
	s_vGenerateTxParameter(pDevice, byPktType, pbyTxBufferAddr, pvRrvTime, pvRTS, pvCTS,
			       cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, wCurrentRate);

	//Fill DataHead
	uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
				    0, 0, 1, AUTO_FB_NONE, wCurrentRate);

	pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize);

	cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen) + cbExtSuppRate;

	pbyMacHdr = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize);
	pbyPayloadHead = (unsigned char *)(pbyMacHdr + cbMacHdLen + uPadding + cbIVlen);
	pbyIVHead = (unsigned char *)(pbyMacHdr + cbMacHdLen + uPadding);

	// Copy the Packet into a tx Buffer
	memcpy(pbyMacHdr, pbMPDU, cbMacHdLen);

	// version set to 0, patch for hostapd deamon
	pMACHeader->wFrameCtl &= cpu_to_le16(0xfffc);
	memcpy(pbyPayloadHead, (pbMPDU + cbMacHdLen), cbFrameBodySize);

	// replace support rate, patch for hostapd deamon(only support 11M)
	if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) {
		if (cbExtSuppRate != 0) {
			if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0)
				memcpy((pbyPayloadHead + cbFrameBodySize),
				       pMgmt->abyCurrSuppRates,
				       ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN
);
			if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0)
				memcpy((pbyPayloadHead + cbFrameBodySize) + ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN,
				       pMgmt->abyCurrExtSuppRates,
				       ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN
);
		}
	}

	// Set wep
	if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) {
		if (pDevice->bEnableHostWEP) {
			pTransmitKey = &STempKey;
			pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
			pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
			pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
			pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
			pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
			memcpy(pTransmitKey->abyKey,
			       &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
			       pTransmitKey->uKeyLength
);
		}

		if ((pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
			dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[16]);
			dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[20]);

			// DO Software Michael
			MIC_vInit(dwMICKey0, dwMICKey1);
			MIC_vAppend((unsigned char *)&(sEthHeader.abyDstAddr[0]), 12);
			dwMIC_Priority = 0;
			MIC_vAppend((unsigned char *)&dwMIC_Priority, 4);
			pr_debug("DMA0_tx_8021:MIC KEY: %X, %X\n",
				 dwMICKey0, dwMICKey1);

			uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen;

			MIC_vAppend((pbyTxBufferAddr + uLength), cbFrameBodySize);

			pdwMIC_L = (u32 *)(pbyTxBufferAddr + uLength + cbFrameBodySize);
			pdwMIC_R = (u32 *)(pbyTxBufferAddr + uLength + cbFrameBodySize + 4);

			MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
			MIC_vUnInit();

			if (pDevice->bTxMICFail == true) {
				*pdwMIC_L = 0;
				*pdwMIC_R = 0;
				pDevice->bTxMICFail = false;
			}

			pr_debug("uLength: %d, %d\n", uLength, cbFrameBodySize);
			pr_debug("cbReqCount:%d, %d, %d, %d\n",
				 cbReqCount, cbHeaderSize, uPadding, cbIVlen);
			pr_debug("MIC:%x, %x\n", *pdwMIC_L, *pdwMIC_R);

		}

		s_vFillTxKey(pDevice, (unsigned char *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
			     pbyMacHdr, (unsigned short)cbFrameBodySize, (unsigned char *)pMICHDR);

		if (pDevice->bEnableHostWEP) {
			pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
			pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0;
		}

		if ((pDevice->byLocalID <= REV_ID_VT3253_A1))
			s_vSWencryption(pDevice, pTransmitKey, pbyPayloadHead, (unsigned short)(cbFrameBodySize + cbMIClen));
	}

	pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
	pDevice->wSeqCounter++;
	if (pDevice->wSeqCounter > 0x0fff)
		pDevice->wSeqCounter = 0;

	if (bIsPSPOLL) {
		// The MAC will automatically replace the Duration-field of MAC header by Duration-field
		// of  FIFO control header.
		// This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is
		// in the same place of other packet's Duration-field).
		// And it will cause Cisco-AP to issue Disassociation-packet
		if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
			((struct vnt_tx_datahead_g *)pvTxDataHd)->duration_a = cpu_to_le16(p80211Header->sA2.wDurationID);
			((struct vnt_tx_datahead_g *)pvTxDataHd)->duration_b = cpu_to_le16(p80211Header->sA2.wDurationID);
		} else {
			((struct vnt_tx_datahead_ab *)pvTxDataHd)->duration = cpu_to_le16(p80211Header->sA2.wDurationID);
		}
	}

	// first TD is the only TD
	//Set TSR1 & ReqCount in TxDescHead
	pFrstTD->pTDInfo->skb = skb;
	pFrstTD->m_td1TD1.byTCR = (TCR_STP | TCR_EDP | EDMSDU);
	pFrstTD->pTDInfo->skb_dma = pFrstTD->pTDInfo->buf_dma;
	pFrstTD->m_td1TD1.wReqCount = cpu_to_le16(cbReqCount);
	pFrstTD->buff_addr = cpu_to_le32(pFrstTD->pTDInfo->skb_dma);
	pFrstTD->pTDInfo->byFlags = 0;
	pFrstTD->pTDInfo->byFlags |= TD_FLAGS_PRIV_SKB;

	if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
		// Disable PS
		MACbPSWakeup(pDevice->PortOffset);
	}
	pDevice->bPWBitOn = false;

	wmb();
	pFrstTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
	wmb();

	pDevice->iTDUsed[TYPE_TXDMA0]++;

	if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 1)
		pr_debug(" available td0 <= 1\n");

	pDevice->apCurrTD[TYPE_TXDMA0] = pFrstTD->next;

	// Poll Transmit the adapter
	MACvTransmit0(pDevice->PortOffset);
}

static void vnt_fill_txkey(struct ieee80211_hdr *hdr, u8 *key_buffer,
			   struct ieee80211_key_conf *tx_key,
			   struct sk_buff *skb,	u16 payload_len,
			   struct vnt_mic_hdr *mic_hdr)
{
	struct ieee80211_key_seq seq;
	u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb));

	/* strip header and icv len from payload */
	payload_len -= ieee80211_get_hdrlen_from_skb(skb);
	payload_len -= tx_key->icv_len;

	switch (tx_key->cipher) {
	case WLAN_CIPHER_SUITE_WEP40:
	case WLAN_CIPHER_SUITE_WEP104:
		memcpy(key_buffer, iv, 3);
		memcpy(key_buffer + 3, tx_key->key, tx_key->keylen);

		if (tx_key->keylen == WLAN_KEY_LEN_WEP40) {
			memcpy(key_buffer + 8, iv, 3);
			memcpy(key_buffer + 11,
			       tx_key->key, WLAN_KEY_LEN_WEP40);
		}

		break;
	case WLAN_CIPHER_SUITE_TKIP:
		ieee80211_get_tkip_p2k(tx_key, skb, key_buffer);

		break;
	case WLAN_CIPHER_SUITE_CCMP:

		if (!mic_hdr)
			return;

		mic_hdr->id = 0x59;
		mic_hdr->payload_len = cpu_to_be16(payload_len);
		ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2);

		ieee80211_get_key_tx_seq(tx_key, &seq);

		memcpy(mic_hdr->ccmp_pn, seq.ccmp.pn, IEEE80211_CCMP_PN_LEN);

		if (ieee80211_has_a4(hdr->frame_control))
			mic_hdr->hlen = cpu_to_be16(28);
		else
			mic_hdr->hlen = cpu_to_be16(22);

		ether_addr_copy(mic_hdr->addr1, hdr->addr1);
		ether_addr_copy(mic_hdr->addr2, hdr->addr2);
		ether_addr_copy(mic_hdr->addr3, hdr->addr3);

		mic_hdr->frame_control = cpu_to_le16(
			le16_to_cpu(hdr->frame_control) & 0xc78f);
		mic_hdr->seq_ctrl = cpu_to_le16(
				le16_to_cpu(hdr->seq_ctrl) & 0xf);

		if (ieee80211_has_a4(hdr->frame_control))
			ether_addr_copy(mic_hdr->addr4, hdr->addr4);

		memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP);

		break;
	default:
		break;
	}
}

int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx,
			     PSTxDesc head_td, struct sk_buff *skb)
{
	PDEVICE_TD_INFO td_info = head_td->pTDInfo;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_tx_rate *tx_rate = &info->control.rates[0];
	struct ieee80211_rate *rate;
	struct ieee80211_key_conf *tx_key;
	struct ieee80211_hdr *hdr;
	struct vnt_tx_fifo_head *tx_buffer_head =
			(struct vnt_tx_fifo_head *)td_info->buf;
	u32 frag;
	u16 tx_body_size = skb->len, current_rate;
	u8 pkt_type;
	bool is_pspoll = false;

	memset(tx_buffer_head, 0, sizeof(*tx_buffer_head));

	hdr = (struct ieee80211_hdr *)(skb->data);

	rate = ieee80211_get_tx_rate(priv->hw, info);

	current_rate = rate->hw_value;
	if (priv->wCurrentRate != current_rate &&
			!(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
		priv->wCurrentRate = current_rate;

		RFbSetPower(priv, priv->wCurrentRate,
			    priv->hw->conf.chandef.chan->hw_value);
	}

	if (current_rate > RATE_11M)
		pkt_type = (u8)priv->byPacketType;
	else
		pkt_type = PK_TYPE_11B;

	/*Set fifo controls */
	if (pkt_type == PK_TYPE_11A)
		tx_buffer_head->fifo_ctl = 0;
	else if (pkt_type == PK_TYPE_11B)
		tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11B);
	else if (pkt_type == PK_TYPE_11GB)
		tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GB);
	else if (pkt_type == PK_TYPE_11GA)
		tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GA);

	/* generate interrupt */
	tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT);

	if (!ieee80211_is_data(hdr->frame_control)) {
		tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_TMOEN);
		tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_ISDMA0);
		tx_buffer_head->time_stamp =
			cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
	} else {
		tx_buffer_head->time_stamp =
			cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
	}

	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
		tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_NEEDACK);

	if (ieee80211_has_retry(hdr->frame_control))
		tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LRETRY);

	if (tx_rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
		priv->byPreambleType = PREAMBLE_SHORT;
	else
		priv->byPreambleType = PREAMBLE_LONG;

	if (tx_rate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
		tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_RTS);

	if (ieee80211_has_a4(hdr->frame_control)) {
		tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LHEAD);
		priv->bLongHeader = true;
	}

	if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER)
		is_pspoll = true;

	tx_buffer_head->frag_ctl =
			cpu_to_le16(ieee80211_get_hdrlen_from_skb(skb) << 10);

	if (info->control.hw_key) {
		tx_key = info->control.hw_key;

		switch (info->control.hw_key->cipher) {
		case WLAN_CIPHER_SUITE_WEP40:
		case WLAN_CIPHER_SUITE_WEP104:
			tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY);
			break;
		case WLAN_CIPHER_SUITE_TKIP:
			tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP);
			break;
		case WLAN_CIPHER_SUITE_CCMP:
			tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_AES);
		default:
			break;
		}
	}

	tx_buffer_head->current_rate = cpu_to_le16(current_rate);

	/* legacy rates TODO use ieee80211_tx_rate */
	if (current_rate >= RATE_18M && ieee80211_is_data(hdr->frame_control)) {
		if (priv->byAutoFBCtrl == AUTO_FB_0)
			tx_buffer_head->fifo_ctl |=
						cpu_to_le16(FIFOCTL_AUTO_FB_0);
		else if (priv->byAutoFBCtrl == AUTO_FB_1)
			tx_buffer_head->fifo_ctl |=
						cpu_to_le16(FIFOCTL_AUTO_FB_1);

	}

	tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG);

	s_cbFillTxBufHead(priv, pkt_type, (u8 *)tx_buffer_head, skb->len,
			  dma_idx, head_td, NULL, (u8 *)skb->data,
			  false, NULL, is_pspoll, &frag);

	if (info->control.hw_key) {
		tx_key = info->control.hw_key;
		if (tx_key->keylen > 0)
			vnt_fill_txkey(hdr, tx_buffer_head->tx_key,
				tx_key, skb, tx_body_size, td_info->mic_hdr);
	}

	return 0;
}

static int vnt_beacon_xmit(struct vnt_private *priv,
			   struct sk_buff *skb)
{
	struct vnt_tx_short_buf_head *short_head =
		(struct vnt_tx_short_buf_head *)priv->tx_beacon_bufs;
	struct ieee80211_mgmt *mgmt_hdr = (struct ieee80211_mgmt *)
				(priv->tx_beacon_bufs + sizeof(*short_head));
	struct ieee80211_tx_info *info;
	u32 frame_size = skb->len + 4;
	u16 current_rate;

	memset(priv->tx_beacon_bufs, 0, sizeof(*short_head));

	if (priv->byBBType == BB_TYPE_11A) {
		current_rate = RATE_6M;

		/* Get SignalField,ServiceField,Length */
		vnt_get_phy_field(priv, frame_size, current_rate,
				  PK_TYPE_11A, &short_head->ab);

		/* Get Duration and TimeStampOff */
		short_head->duration =
			cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B,
				    frame_size, PK_TYPE_11A, current_rate,
				    false, 0, 0, 1, AUTO_FB_NONE));

		short_head->time_stamp_off =
				vnt_time_stamp_off(priv, current_rate);
	} else {
		current_rate = RATE_1M;
		short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_11B);

		/* Get SignalField,ServiceField,Length */
		vnt_get_phy_field(priv, frame_size, current_rate,
				  PK_TYPE_11B, &short_head->ab);

		/* Get Duration and TimeStampOff */
		short_head->duration =
			cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B,
				    frame_size, PK_TYPE_11B, current_rate,
				    false, 0, 0, 1, AUTO_FB_NONE));

		short_head->time_stamp_off =
			vnt_time_stamp_off(priv, current_rate);
	}

	short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT);

	/* Copy Beacon */
	memcpy(mgmt_hdr, skb->data, skb->len);

	/* time stamp always 0 */
	mgmt_hdr->u.beacon.timestamp = 0;

	info = IEEE80211_SKB_CB(skb);
	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr;

		hdr->duration_id = 0;
		hdr->seq_ctrl = cpu_to_le16(priv->wSeqCounter << 4);
	}

	priv->wSeqCounter++;
	if (priv->wSeqCounter > 0x0fff)
		priv->wSeqCounter = 0;

	priv->wBCNBufLen = sizeof(*short_head) + skb->len;

	MACvSetCurrBCNTxDescAddr(priv->PortOffset, priv->tx_beacon_dma);

	MACvSetCurrBCNLength(priv->PortOffset, priv->wBCNBufLen);
	/* Set auto Transmit on */
	MACvRegBitsOn(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
	/* Poll Transmit the adapter */
	MACvTransmitBCN(priv->PortOffset);

	return 0;
}

int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif)
{
	struct sk_buff *beacon;

	beacon = ieee80211_beacon_get(priv->hw, vif);
	if (!beacon)
		return -ENOMEM;

	if (vnt_beacon_xmit(priv, beacon)) {
		ieee80211_free_txskb(priv->hw, beacon);
		return -ENODEV;
	}

	return 0;
}

int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
		      struct ieee80211_bss_conf *conf)
{
	int ret;

	VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);

	VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);

	CARDvSetFirstNextTBTT(priv->PortOffset, conf->beacon_int);

	CARDbSetBeaconPeriod(priv, conf->beacon_int);

	ret = vnt_beacon_make(priv, vif);

	return ret;
}