Staging: rt2870: remove dead QOS_DLS_SUPPORT code
[linux-2.6] / drivers / staging / rt2870 / rt_main_dev.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26
27     Module Name:
28     rt_main_dev.c
29
30     Abstract:
31     Create and register network interface.
32
33     Revision History:
34     Who         When            What
35     --------    ----------      ----------------------------------------------
36         Sample          Mar/21/07               Merge RT2870 and RT2860 drivers.
37 */
38
39 #include "rt_config.h"
40
41 #define FORTY_MHZ_INTOLERANT_INTERVAL   (60*1000) // 1 min
42
43 /*---------------------------------------------------------------------*/
44 /* Private Variables Used                                              */
45 /*---------------------------------------------------------------------*/
46 //static RALINK_TIMER_STRUCT     PeriodicTimer;
47
48 char *mac = "";            // default 00:00:00:00:00:00
49 char *hostname = "";
50 module_param (mac, charp, 0);
51 MODULE_PARM_DESC (mac, "rt28xx: wireless mac addr");
52
53
54 /*---------------------------------------------------------------------*/
55 /* Prototypes of Functions Used                                        */
56 /*---------------------------------------------------------------------*/
57 #ifdef DOT11_N_SUPPORT
58 extern BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num);
59 extern void ba_reordering_resource_release(PRTMP_ADAPTER pAd);
60 #endif // DOT11_N_SUPPORT //
61 extern NDIS_STATUS NICLoadRateSwitchingParams(IN PRTMP_ADAPTER pAd);
62
63
64 // public function prototype
65 INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
66                                                         IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
67
68 // private function prototype
69 static int rt28xx_init(IN struct net_device *net_dev);
70 INT rt28xx_send_packets(IN struct sk_buff *skb_p, IN struct net_device *net_dev);
71
72 static void CfgInitHook(PRTMP_ADAPTER pAd);
73 //static BOOLEAN RT28XXAvailRANameAssign(IN CHAR *name_p);
74
75 #ifdef CONFIG_STA_SUPPORT
76 extern  const struct iw_handler_def rt28xx_iw_handler_def;
77 #endif // CONFIG_STA_SUPPORT //
78
79 #if WIRELESS_EXT >= 12
80 // This function will be called when query /proc
81 struct iw_statistics *rt28xx_get_wireless_stats(
82     IN struct net_device *net_dev);
83 #endif
84
85 struct net_device_stats *RT28xx_get_ether_stats(
86     IN  struct net_device *net_dev);
87
88 /*
89 ========================================================================
90 Routine Description:
91     Close raxx interface.
92
93 Arguments:
94         *net_dev                        the raxx interface pointer
95
96 Return Value:
97     0                                   Open OK
98         otherwise                       Open Fail
99
100 Note:
101         1. if open fail, kernel will not call the close function.
102         2. Free memory for
103                 (1) Mlme Memory Handler:                MlmeHalt()
104                 (2) TX & RX:                                    RTMPFreeTxRxRingMemory()
105                 (3) BA Reordering:                              ba_reordering_resource_release()
106 ========================================================================
107 */
108 int MainVirtualIF_close(IN struct net_device *net_dev)
109 {
110     RTMP_ADAPTER *pAd = net_dev->ml_priv;
111
112         // Sanity check for pAd
113         if (pAd == NULL)
114                 return 0; // close ok
115
116         netif_carrier_off(pAd->net_dev);
117         netif_stop_queue(pAd->net_dev);
118
119
120
121         VIRTUAL_IF_DOWN(pAd);
122
123         RT_MOD_DEC_USE_COUNT();
124
125         return 0; // close ok
126 }
127
128 /*
129 ========================================================================
130 Routine Description:
131     Open raxx interface.
132
133 Arguments:
134         *net_dev                        the raxx interface pointer
135
136 Return Value:
137     0                                   Open OK
138         otherwise                       Open Fail
139
140 Note:
141         1. if open fail, kernel will not call the close function.
142         2. Free memory for
143                 (1) Mlme Memory Handler:                MlmeHalt()
144                 (2) TX & RX:                                    RTMPFreeTxRxRingMemory()
145                 (3) BA Reordering:                              ba_reordering_resource_release()
146 ========================================================================
147 */
148 int MainVirtualIF_open(IN struct net_device *net_dev)
149 {
150     RTMP_ADAPTER *pAd = net_dev->ml_priv;
151
152         // Sanity check for pAd
153         if (pAd == NULL)
154                 return 0; // close ok
155
156         if (VIRTUAL_IF_UP(pAd) != 0)
157                 return -1;
158
159         // increase MODULE use count
160         RT_MOD_INC_USE_COUNT();
161
162         netif_start_queue(net_dev);
163         netif_carrier_on(net_dev);
164         netif_wake_queue(net_dev);
165
166         return 0;
167 }
168
169 /*
170 ========================================================================
171 Routine Description:
172     Close raxx interface.
173
174 Arguments:
175         *net_dev                        the raxx interface pointer
176
177 Return Value:
178     0                                   Open OK
179         otherwise                       Open Fail
180
181 Note:
182         1. if open fail, kernel will not call the close function.
183         2. Free memory for
184                 (1) Mlme Memory Handler:                MlmeHalt()
185                 (2) TX & RX:                                    RTMPFreeTxRxRingMemory()
186                 (3) BA Reordering:                              ba_reordering_resource_release()
187 ========================================================================
188 */
189 int rt28xx_close(IN PNET_DEV dev)
190 {
191         struct net_device * net_dev = (struct net_device *)dev;
192     RTMP_ADAPTER        *pAd = net_dev->ml_priv;
193         BOOLEAN                 Cancelled = FALSE;
194         UINT32                  i = 0;
195 #ifdef RT2870
196         DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup);
197         DECLARE_WAITQUEUE(wait, current);
198
199         //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
200 #endif // RT2870 //
201
202
203     DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n"));
204
205         // Sanity check for pAd
206         if (pAd == NULL)
207                 return 0; // close ok
208
209
210 #ifdef CONFIG_STA_SUPPORT
211         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
212         {
213
214                 // If dirver doesn't wake up firmware here,
215                 // NICLoadFirmware will hang forever when interface is up again.
216                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
217         {
218                     AsicForceWakeup(pAd, TRUE);
219         }
220
221                 if (INFRA_ON(pAd) &&
222                         (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
223                 {
224                         MLME_DISASSOC_REQ_STRUCT        DisReq;
225                         MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
226
227                         COPY_MAC_ADDR(DisReq.Addr, pAd->CommonCfg.Bssid);
228                         DisReq.Reason =  REASON_DEAUTH_STA_LEAVING;
229
230                         MsgElem->Machine = ASSOC_STATE_MACHINE;
231                         MsgElem->MsgType = MT2_MLME_DISASSOC_REQ;
232                         MsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT);
233                         NdisMoveMemory(MsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT));
234
235                         // Prevent to connect AP again in STAMlmePeriodicExec
236                         pAd->MlmeAux.AutoReconnectSsidLen= 32;
237                         NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
238
239                         pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC;
240                         MlmeDisassocReqAction(pAd, MsgElem);
241                         kfree(MsgElem);
242
243                         RTMPusecDelay(1000);
244                 }
245
246 #ifdef RT2870
247         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
248 #endif // RT2870 //
249
250 #ifdef CCX_SUPPORT
251                 RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &Cancelled);
252 #endif
253
254                 RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled);
255                 RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled);
256
257 #ifdef WPA_SUPPLICANT_SUPPORT
258 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
259                 {
260                         union iwreq_data    wrqu;
261                         // send wireless event to wpa_supplicant for infroming interface down.
262                         memset(&wrqu, 0, sizeof(wrqu));
263                         wrqu.data.flags = RT_INTERFACE_DOWN;
264                         wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
265                 }
266 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
267 #endif // WPA_SUPPLICANT_SUPPORT //
268
269                 MlmeRadioOff(pAd);
270         }
271 #endif // CONFIG_STA_SUPPORT //
272
273         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
274
275         for (i = 0 ; i < NUM_OF_TX_RING; i++)
276         {
277                 while (pAd->DeQueueRunning[i] == TRUE)
278                 {
279                         printk("Waiting for TxQueue[%d] done..........\n", i);
280                         RTMPusecDelay(1000);
281                 }
282         }
283
284 #ifdef RT2870
285         // ensure there are no more active urbs.
286         add_wait_queue (&unlink_wakeup, &wait);
287         pAd->wait = &unlink_wakeup;
288
289         // maybe wait for deletions to finish.
290         i = 0;
291         //while((i < 25) && atomic_read(&pAd->PendingRx) > 0)
292         while(i < 25)
293         {
294                 unsigned long IrqFlags;
295
296                 RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
297                 if (pAd->PendingRx == 0)
298                 {
299                         RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
300                         break;
301                 }
302                 RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
303
304                 msleep(UNLINK_TIMEOUT_MS);      //Time in millisecond
305                 i++;
306         }
307         pAd->wait = NULL;
308         remove_wait_queue (&unlink_wakeup, &wait);
309 #endif // RT2870 //
310
311         //RTUSBCleanUpMLMEWaitQueue(pAd);       /*not used in RT28xx*/
312
313
314 #ifdef RT2870
315         // We need clear timerQ related structure before exits of the timer thread.
316         RT2870_TimerQ_Exit(pAd);
317         // Close kernel threads or tasklets
318         RT28xxThreadTerminate(pAd);
319 #endif // RT2870 //
320
321         // Stop Mlme state machine
322         MlmeHalt(pAd);
323
324         // Close kernel threads or tasklets
325         kill_thread_task(pAd);
326
327
328 #ifdef CONFIG_STA_SUPPORT
329         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
330         {
331                 MacTableReset(pAd);
332         }
333 #endif // CONFIG_STA_SUPPORT //
334
335
336         MeasureReqTabExit(pAd);
337         TpcReqTabExit(pAd);
338
339
340
341
342         // Free Ring or USB buffers
343         RTMPFreeTxRxRingMemory(pAd);
344
345         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
346
347 #ifdef DOT11_N_SUPPORT
348         // Free BA reorder resource
349         ba_reordering_resource_release(pAd);
350 #endif // DOT11_N_SUPPORT //
351
352 #ifdef RT2870
353 #ifdef INF_AMAZON_SE
354         if (pAd->UsbVendorReqBuf)
355                 os_free_mem(pAd, pAd->UsbVendorReqBuf);
356 #endif // INF_AMAZON_SE //
357 #endif // RT2870 //
358
359         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP);
360
361         return 0; // close ok
362 } /* End of rt28xx_close */
363
364 static int rt28xx_init(IN struct net_device *net_dev)
365 {
366         PRTMP_ADAPTER                   pAd = net_dev->ml_priv;
367         UINT                                    index;
368         UCHAR                                   TmpPhy;
369         NDIS_STATUS                             Status;
370         UINT32          MacCsr0 = 0;
371
372 #ifdef RT2870
373 #ifdef INF_AMAZON_SE
374         init_MUTEX(&(pAd->UsbVendorReq_semaphore));
375         os_alloc_mem(pAd, (PUCHAR)&pAd->UsbVendorReqBuf, MAX_PARAM_BUFFER_SIZE - 1);
376         if (pAd->UsbVendorReqBuf == NULL)
377         {
378                 DBGPRINT(RT_DEBUG_ERROR, ("Allocate vendor request temp buffer failed!\n"));
379                 goto err0;
380         }
381 #endif // INF_AMAZON_SE //
382 #endif // RT2870 //
383
384 #ifdef DOT11_N_SUPPORT
385         // Allocate BA Reordering memory
386         ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM);
387 #endif // DOT11_N_SUPPORT //
388
389         // Make sure MAC gets ready.
390         index = 0;
391         do
392         {
393                 RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0);
394                 pAd->MACVersion = MacCsr0;
395
396                 if ((pAd->MACVersion != 0x00) && (pAd->MACVersion != 0xFFFFFFFF))
397                         break;
398
399                 RTMPusecDelay(10);
400         } while (index++ < 100);
401
402         DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0  [ Ver:Rev=0x%08x]\n", pAd->MACVersion));
403
404         // Disable DMA
405         RT28XXDMADisable(pAd);
406
407
408         // Load 8051 firmware
409         Status = NICLoadFirmware(pAd);
410         if (Status != NDIS_STATUS_SUCCESS)
411         {
412                 DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status));
413                 goto err1;
414         }
415
416         NICLoadRateSwitchingParams(pAd);
417
418         // Disable interrupts here which is as soon as possible
419         // This statement should never be true. We might consider to remove it later
420
421         Status = RTMPAllocTxRxRingMemory(pAd);
422         if (Status != NDIS_STATUS_SUCCESS)
423         {
424                 DBGPRINT_ERR(("RTMPAllocDMAMemory failed, Status[=0x%08x]\n", Status));
425                 goto err1;
426         }
427
428         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
429
430         // initialize MLME
431         //
432
433         Status = MlmeInit(pAd);
434         if (Status != NDIS_STATUS_SUCCESS)
435         {
436                 DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status));
437                 goto err2;
438         }
439
440         // Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default
441         //
442         UserCfgInit(pAd);
443
444 #ifdef RT2870
445         // We need init timerQ related structure before create the timer thread.
446         RT2870_TimerQ_Init(pAd);
447 #endif // RT2870 //
448
449         RT28XX_TASK_THREAD_INIT(pAd, Status);
450         if (Status != NDIS_STATUS_SUCCESS)
451                 goto err1;
452
453 //      COPY_MAC_ADDR(pAd->ApCfg.MBSSID[apidx].Bssid, netif->hwaddr);
454 //      pAd->bForcePrintTX = TRUE;
455
456         CfgInitHook(pAd);
457
458 #ifdef CONFIG_STA_SUPPORT
459         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
460                 NdisAllocateSpinLock(&pAd->MacTabLock);
461 #endif // CONFIG_STA_SUPPORT //
462
463         MeasureReqTabInit(pAd);
464         TpcReqTabInit(pAd);
465
466         //
467         // Init the hardware, we need to init asic before read registry, otherwise mac register will be reset
468         //
469         Status = NICInitializeAdapter(pAd, TRUE);
470         if (Status != NDIS_STATUS_SUCCESS)
471         {
472                 DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", Status));
473                 if (Status != NDIS_STATUS_SUCCESS)
474                 goto err3;
475         }
476
477         // Read parameters from Config File
478         Status = RTMPReadParametersHook(pAd);
479
480         printk("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode);
481         if (Status != NDIS_STATUS_SUCCESS)
482         {
483                 DBGPRINT_ERR(("NICReadRegParameters failed, Status[=0x%08x]\n",Status));
484                 goto err4;
485         }
486
487 #ifdef RT2870
488         pAd->CommonCfg.bMultipleIRP = FALSE;
489
490         if (pAd->CommonCfg.bMultipleIRP)
491                 pAd->CommonCfg.NumOfBulkInIRP = RX_RING_SIZE;
492         else
493                 pAd->CommonCfg.NumOfBulkInIRP = 1;
494 #endif // RT2870 //
495
496
497         //Init Ba Capability parameters.
498 //      RT28XX_BA_INIT(pAd);
499 #ifdef DOT11_N_SUPPORT
500         pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
501         pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable;
502         pAd->CommonCfg.DesiredHtPhy.AmsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize;
503         pAd->CommonCfg.DesiredHtPhy.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode;
504         // UPdata to HT IE
505         pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode;
506         pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize;
507         pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
508 #endif // DOT11_N_SUPPORT //
509
510         // after reading Registry, we now know if in AP mode or STA mode
511
512         // Load 8051 firmware; crash when FW image not existent
513         // Status = NICLoadFirmware(pAd);
514         // if (Status != NDIS_STATUS_SUCCESS)
515         //    break;
516
517         printk("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode);
518
519         // We should read EEPROM for all cases.  rt2860b
520         NICReadEEPROMParameters(pAd, mac);
521 #ifdef CONFIG_STA_SUPPORT
522 #endif // CONFIG_STA_SUPPORT //
523
524         printk("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode);
525
526         NICInitAsicFromEEPROM(pAd); //rt2860b
527
528         // Set PHY to appropriate mode
529         TmpPhy = pAd->CommonCfg.PhyMode;
530         pAd->CommonCfg.PhyMode = 0xff;
531         RTMPSetPhyMode(pAd, TmpPhy);
532 #ifdef DOT11_N_SUPPORT
533         SetCommonHT(pAd);
534 #endif // DOT11_N_SUPPORT //
535
536         // No valid channels.
537         if (pAd->ChannelListNum == 0)
538         {
539                 printk("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n");
540                 goto err4;
541         }
542
543 #ifdef DOT11_N_SUPPORT
544         printk("MCS Set = %02x %02x %02x %02x %02x\n", pAd->CommonCfg.HtCapability.MCSSet[0],
545            pAd->CommonCfg.HtCapability.MCSSet[1], pAd->CommonCfg.HtCapability.MCSSet[2],
546            pAd->CommonCfg.HtCapability.MCSSet[3], pAd->CommonCfg.HtCapability.MCSSet[4]);
547 #endif // DOT11_N_SUPPORT //
548
549 #ifdef RT2870
550     //Init RT30xx RFRegisters after read RFIC type from EEPROM
551         NICInitRT30xxRFRegisters(pAd);
552 #endif // RT2870 //
553
554 #if 0
555         // Patch cardbus controller if EEPROM said so.
556         if (pAd->bTest1 == FALSE)
557                 RTMPPatchCardBus(pAd);
558 #endif
559
560
561 //              APInitialize(pAd);
562
563 #ifdef IKANOS_VX_1X0
564         VR_IKANOS_FP_Init(pAd->ApCfg.BssidNum, pAd->PermanentAddress);
565 #endif // IKANOS_VX_1X0 //
566
567                 //
568         // Initialize RF register to default value
569         //
570         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
571         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
572
573         // 8051 firmware require the signal during booting time.
574         AsicSendCommandToMcu(pAd, 0x72, 0xFF, 0x00, 0x00);
575
576         if (pAd && (Status != NDIS_STATUS_SUCCESS))
577         {
578                 //
579                 // Undo everything if it failed
580                 //
581                 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
582                 {
583 //                      NdisMDeregisterInterrupt(&pAd->Interrupt);
584                         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
585                 }
586 //              RTMPFreeAdapter(pAd); // we will free it in disconnect()
587         }
588         else if (pAd)
589         {
590                 // Microsoft HCT require driver send a disconnect event after driver initialization.
591                 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
592 //              pAd->IndicateMediaState = NdisMediaStateDisconnected;
593                 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
594
595                 DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n"));
596
597
598 #ifdef RT2870
599                 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS);
600                 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
601
602                 //
603                 // Support multiple BulkIn IRP,
604                 // the value on pAd->CommonCfg.NumOfBulkInIRP may be large than 1.
605                 //
606                 for(index=0; index<pAd->CommonCfg.NumOfBulkInIRP; index++)
607                 {
608                         RTUSBBulkReceive(pAd);
609                         DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkReceive!\n" ));
610                 }
611 #endif // RT2870 //
612         }// end of else
613
614
615         DBGPRINT_S(Status, ("<==== RTMPInitialize, Status=%x\n", Status));
616
617         return TRUE;
618
619
620 err4:
621 err3:
622         MlmeHalt(pAd);
623 err2:
624         RTMPFreeTxRxRingMemory(pAd);
625 //      RTMPFreeAdapter(pAd);
626 err1:
627
628 #ifdef DOT11_N_SUPPORT
629         os_free_mem(pAd, pAd->mpdu_blk_pool.mem); // free BA pool
630 #endif // DOT11_N_SUPPORT //
631         RT28XX_IRQ_RELEASE(net_dev);
632
633         // shall not set ml_priv to NULL here because the ml_priv didn't been free yet.
634         //net_dev->ml_priv = 0;
635 #ifdef INF_AMAZON_SE
636 err0:
637 #endif // INF_AMAZON_SE //
638         printk("!!! %s Initialized fail !!!\n", RT28xx_CHIP_NAME);
639         return FALSE;
640 } /* End of rt28xx_init */
641
642
643 /*
644 ========================================================================
645 Routine Description:
646     Open raxx interface.
647
648 Arguments:
649         *net_dev                        the raxx interface pointer
650
651 Return Value:
652     0                                   Open OK
653         otherwise                       Open Fail
654
655 Note:
656 ========================================================================
657 */
658 int rt28xx_open(IN PNET_DEV dev)
659 {
660         struct net_device * net_dev = (struct net_device *)dev;
661         PRTMP_ADAPTER pAd = net_dev->ml_priv;
662         int retval = 0;
663         POS_COOKIE pObj;
664
665
666         // Sanity check for pAd
667         if (pAd == NULL)
668         {
669                 /* if 1st open fail, pAd will be free;
670                    So the net_dev->ml_priv will be NULL in 2rd open */
671                 return -1;
672         }
673
674 #ifdef CONFIG_STA_SUPPORT
675 #endif // CONFIG_STA_SUPPORT //
676
677         // Init
678         pObj = (POS_COOKIE)pAd->OS_Cookie;
679
680         // reset Adapter flags
681         RTMP_CLEAR_FLAGS(pAd);
682
683         // Request interrupt service routine for PCI device
684         // register the interrupt routine with the os
685         RT28XX_IRQ_REQUEST(net_dev);
686
687
688         // Init BssTab & ChannelInfo tabbles for auto channel select.
689
690
691         // Chip & other init
692         if (rt28xx_init(net_dev) == FALSE)
693                 goto err;
694
695 #ifdef CONFIG_STA_SUPPORT
696         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
697         {
698                 NdisZeroMemory(pAd->StaCfg.dev_name, 16);
699                 NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name));
700         }
701 #endif // CONFIG_STA_SUPPORT //
702
703         // Set up the Mac address
704         NdisMoveMemory(net_dev->dev_addr, (void *) pAd->CurrentAddress, 6);
705
706         // Init IRQ parameters
707         RT28XX_IRQ_INIT(pAd);
708
709         // Various AP function init
710
711 #ifdef CONFIG_STA_SUPPORT
712         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
713         {
714 #ifdef WPA_SUPPLICANT_SUPPORT
715 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
716                 {
717                         union iwreq_data    wrqu;
718                         // send wireless event to wpa_supplicant for infroming interface down.
719                         memset(&wrqu, 0, sizeof(wrqu));
720                         wrqu.data.flags = RT_INTERFACE_UP;
721                         wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
722                 }
723 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
724 #endif // WPA_SUPPLICANT_SUPPORT //
725
726         }
727 #endif // CONFIG_STA_SUPPORT //
728
729         // Enable Interrupt
730         RT28XX_IRQ_ENABLE(pAd);
731
732         // Now Enable RxTx
733         RTMPEnableRxTx(pAd);
734         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP);
735
736         {
737         UINT32 reg = 0;
738         RTMP_IO_READ32(pAd, 0x1300, &reg);  // clear garbage interrupts
739         printk("0x1300 = %08x\n", reg);
740         }
741
742         {
743 //      u32 reg;
744 //      u8  byte;
745 //      u16 tmp;
746
747 //      RTMP_IO_READ32(pAd, XIFS_TIME_CFG, &reg);
748
749 //      tmp = 0x0805;
750 //      reg  = (reg & 0xffff0000) | tmp;
751 //      RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, reg);
752
753         }
754
755 #if 0
756         /*
757          * debugging helper
758          *              show the size of main table in Adapter structure
759          *              MacTab  -- 185K
760          *              BATable -- 137K
761          *              Total   -- 385K  !!!!! (5/26/2006)
762          */
763         printk("sizeof(pAd->MacTab) = %ld\n", sizeof(pAd->MacTab));
764         printk("sizeof(pAd->AccessControlList) = %ld\n", sizeof(pAd->AccessControlList));
765         printk("sizeof(pAd->ApCfg) = %ld\n", sizeof(pAd->ApCfg));
766         printk("sizeof(pAd->BATable) = %ld\n", sizeof(pAd->BATable));
767         BUG();
768 #endif
769
770 #ifdef CONFIG_STA_SUPPORT
771 #endif // CONFIG_STA_SUPPORT //
772
773         return (retval);
774
775 err:
776         return (-1);
777 } /* End of rt28xx_open */
778
779 static const struct net_device_ops rt2870_netdev_ops = {
780         .ndo_open               = MainVirtualIF_open,
781         .ndo_stop               = MainVirtualIF_close,
782         .ndo_do_ioctl           = rt28xx_ioctl,
783         .ndo_get_stats          = RT28xx_get_ether_stats,
784         .ndo_validate_addr      = NULL,
785         .ndo_set_mac_address    = eth_mac_addr,
786         .ndo_change_mtu         = eth_change_mtu,
787 #ifdef IKANOS_VX_1X0
788         .ndo_start_xmit         = IKANOS_DataFramesTx,
789 #else
790         .ndo_start_xmit         = rt28xx_send_packets,
791 #endif
792 };
793
794 /* Must not be called for mdev and apdev */
795 static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER pAd)
796 {
797         NDIS_STATUS Status;
798         INT     i=0;
799         CHAR    slot_name[IFNAMSIZ];
800         struct net_device   *device;
801
802
803         //ether_setup(dev);
804 //      dev->set_multicast_list = ieee80211_set_multicast_list;
805 //      dev->change_mtu = ieee80211_change_mtu;
806 #ifdef CONFIG_STA_SUPPORT
807 #if WIRELESS_EXT >= 12
808         if (pAd->OpMode == OPMODE_STA)
809         {
810                 dev->wireless_handlers = &rt28xx_iw_handler_def;
811         }
812 #endif //WIRELESS_EXT >= 12
813 #endif // CONFIG_STA_SUPPORT //
814
815 #if WIRELESS_EXT < 21
816                 dev->get_wireless_stats = rt28xx_get_wireless_stats;
817 #endif
818 //      dev->uninit = ieee80211_if_reinit;
819 //      dev->destructor = ieee80211_if_free;
820         dev->priv_flags = INT_MAIN;
821         dev->netdev_ops = &rt2870_netdev_ops;
822         // find available device name
823         for (i = 0; i < 8; i++)
824         {
825                 sprintf(slot_name, "ra%d", i);
826
827                 device = dev_get_by_name(dev_net(dev), slot_name);
828                 if (device != NULL)
829                         dev_put(device);
830
831                 if (device == NULL)
832                         break;
833         }
834
835         if(i == 8)
836         {
837                 DBGPRINT(RT_DEBUG_ERROR, ("No available slot name\n"));
838                 Status = NDIS_STATUS_FAILURE;
839         }
840         else
841         {
842                 sprintf(dev->name, "ra%d", i);
843                 Status = NDIS_STATUS_SUCCESS;
844         }
845
846         return Status;
847
848 }
849
850 /*
851 ========================================================================
852 Routine Description:
853     Probe RT28XX chipset.
854
855 Arguments:
856     _dev_p                              Point to the PCI or USB device
857         _dev_id_p                       Point to the PCI or USB device ID
858
859 Return Value:
860     0                                   Probe OK
861         -ENODEV                         Probe Fail
862
863 Note:
864 ========================================================================
865 */
866 INT __devinit   rt28xx_probe(
867     IN  void *_dev_p,
868     IN  void *_dev_id_p,
869         IN  UINT argc,
870         OUT PRTMP_ADAPTER *ppAd)
871 {
872     struct  net_device  *net_dev;
873     PRTMP_ADAPTER       pAd = (PRTMP_ADAPTER) NULL;
874     INT                 status;
875         PVOID                           handle;
876 #ifdef RT2870
877         struct usb_interface *intf = (struct usb_interface *)_dev_p;
878         struct usb_device *dev_p = interface_to_usbdev(intf);
879
880         dev_p = usb_get_dev(dev_p);
881 #endif // RT2870 //
882
883
884 #ifdef CONFIG_STA_SUPPORT
885     DBGPRINT(RT_DEBUG_TRACE, ("STA Driver version-%s\n", STA_DRIVER_VERSION));
886 #endif // CONFIG_STA_SUPPORT //
887
888         // Check chipset vendor/product ID
889 //      if (RT28XXChipsetCheck(_dev_p) == FALSE)
890 //              goto err_out;
891
892     net_dev = alloc_etherdev(sizeof(PRTMP_ADAPTER));
893     if (net_dev == NULL)
894     {
895         printk("alloc_netdev failed\n");
896
897         goto err_out;
898     }
899
900 // sample
901 //      if (rt_ieee80211_if_setup(net_dev) != NDIS_STATUS_SUCCESS)
902 //              goto err_out;
903
904         netif_stop_queue(net_dev);
905 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
906 /* for supporting Network Manager */
907 /* Set the sysfs physical device reference for the network logical device
908  * if set prior to registration will cause a symlink during initialization.
909  */
910     SET_NETDEV_DEV(net_dev, &(dev_p->dev));
911 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
912
913         // Allocate RTMP_ADAPTER miniport adapter structure
914         handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL);
915         RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p);
916
917         status = RTMPAllocAdapterBlock(handle, &pAd);
918         if (status != NDIS_STATUS_SUCCESS)
919                 goto err_out_free_netdev;
920
921         net_dev->ml_priv = (PVOID)pAd;
922     pAd->net_dev = net_dev; // must be before RT28XXNetDevInit()
923
924         RT28XXNetDevInit(_dev_p, net_dev, pAd);
925
926 #ifdef CONFIG_STA_SUPPORT
927     pAd->StaCfg.OriDevType = net_dev->type;
928 #endif // CONFIG_STA_SUPPORT //
929
930         // Find and assign a free interface name, raxx
931 //      RT28XXAvailRANameAssign(net_dev->name);
932
933         // Post config
934         if (RT28XXProbePostConfig(_dev_p, pAd, 0) == FALSE)
935                 goto err_out_unmap;
936
937 #ifdef CONFIG_STA_SUPPORT
938         pAd->OpMode = OPMODE_STA;
939 #endif // CONFIG_STA_SUPPORT //
940
941         // sample move
942         if (rt_ieee80211_if_setup(net_dev, pAd) != NDIS_STATUS_SUCCESS)
943                 goto err_out_unmap;
944
945     // Register this device
946     status = register_netdev(net_dev);
947     if (status)
948         goto err_out_unmap;
949
950     // Set driver data
951         RT28XX_DRVDATA_SET(_dev_p);
952
953
954
955         *ppAd = pAd;
956     return 0; // probe ok
957
958
959         /* --------------------------- ERROR HANDLE --------------------------- */
960 err_out_unmap:
961         RTMPFreeAdapter(pAd);
962         RT28XX_UNMAP();
963
964 err_out_free_netdev:
965         free_netdev(net_dev);
966
967 err_out:
968         RT28XX_PUT_DEVICE(dev_p);
969
970         return -ENODEV; /* probe fail */
971 } /* End of rt28xx_probe */
972
973
974 /*
975 ========================================================================
976 Routine Description:
977     The entry point for Linux kernel sent packet to our driver.
978
979 Arguments:
980     sk_buff *skb                the pointer refer to a sk_buffer.
981
982 Return Value:
983     0
984
985 Note:
986         This function is the entry point of Tx Path for Os delivery packet to
987         our driver. You only can put OS-depened & STA/AP common handle procedures
988         in here.
989 ========================================================================
990 */
991 int rt28xx_packet_xmit(struct sk_buff *skb)
992 {
993         struct net_device *net_dev = skb->dev;
994         PRTMP_ADAPTER pAd = net_dev->ml_priv;
995         int status = 0;
996         PNDIS_PACKET pPacket = (PNDIS_PACKET) skb;
997
998 #ifdef CONFIG_STA_SUPPORT
999         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1000         {
1001                 // Drop send request since we are in monitor mode
1002                 if (MONITOR_ON(pAd))
1003                 {
1004                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1005                         goto done;
1006                 }
1007         }
1008 #endif // CONFIG_STA_SUPPORT //
1009
1010         // EapolStart size is 18
1011         if (skb->len < 14)
1012         {
1013                 //printk("bad packet size: %d\n", pkt->len);
1014                 hex_dump("bad packet", skb->data, skb->len);
1015                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1016                 goto done;
1017         }
1018
1019 #if 0
1020 //      if ((pkt->data[0] & 0x1) == 0)
1021         {
1022                 //hex_dump(__func__, pkt->data, pkt->len);
1023                 printk("pPacket = %x\n", pPacket);
1024         }
1025 #endif
1026
1027         RTMP_SET_PACKET_5VT(pPacket, 0);
1028 //      MiniportMMRequest(pAd, pkt->data, pkt->len);
1029 #ifdef CONFIG_5VT_ENHANCE
1030     if (*(int*)(skb->cb) == BRIDGE_TAG) {
1031                 RTMP_SET_PACKET_5VT(pPacket, 1);
1032     }
1033 #endif
1034
1035
1036
1037 #ifdef CONFIG_STA_SUPPORT
1038         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1039         {
1040
1041                 STASendPackets((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1);
1042         }
1043
1044 #endif // CONFIG_STA_SUPPORT //
1045
1046         status = 0;
1047 done:
1048
1049         return status;
1050 }
1051
1052
1053 /*
1054 ========================================================================
1055 Routine Description:
1056     Send a packet to WLAN.
1057
1058 Arguments:
1059     skb_p           points to our adapter
1060     dev_p           which WLAN network interface
1061
1062 Return Value:
1063     0: transmit successfully
1064     otherwise: transmit fail
1065
1066 Note:
1067 ========================================================================
1068 */
1069 INT rt28xx_send_packets(
1070         IN struct sk_buff               *skb_p,
1071         IN struct net_device    *net_dev)
1072 {
1073     RTMP_ADAPTER *pAd = net_dev->ml_priv;
1074
1075         if (!(net_dev->flags & IFF_UP))
1076         {
1077                 RELEASE_NDIS_PACKET(pAd, (PNDIS_PACKET)skb_p, NDIS_STATUS_FAILURE);
1078                 return 0;
1079         }
1080
1081         NdisZeroMemory((PUCHAR)&skb_p->cb[CB_OFF], 15);
1082         RTMP_SET_PACKET_NET_DEVICE_MBSSID(skb_p, MAIN_MBSSID);
1083
1084         return rt28xx_packet_xmit(skb_p);
1085 } /* End of MBSS_VirtualIF_PacketSend */
1086
1087
1088
1089
1090 void CfgInitHook(PRTMP_ADAPTER pAd)
1091 {
1092         pAd->bBroadComHT = TRUE;
1093 } /* End of CfgInitHook */
1094
1095
1096 #if 0   // Not used now, should keep it in our source tree??
1097 /*
1098 ========================================================================
1099 Routine Description:
1100     Find and assign a free interface name (raxx).
1101
1102 Arguments:
1103     *name_p                             the interface name pointer
1104
1105 Return Value:
1106         TRUE                            OK
1107         FALSE                           FAIL
1108
1109 Note:
1110 ========================================================================
1111 */
1112 static BOOLEAN RT28XXAvailRANameAssign(
1113         IN CHAR                 *name_p)
1114 {
1115     CHAR                                slot_name[IFNAMSIZ];
1116     struct net_device   *device;
1117         UINT32                          if_id;
1118
1119
1120     for(if_id=0; if_id<8; if_id++)
1121     {
1122         sprintf(slot_name, "ra%d", if_id);
1123
1124         for(device=dev_base; device!=NULL; device=device->next)
1125         {
1126             if (strncmp(device->name, slot_name, 4) == 0)
1127                 break;
1128         }
1129
1130         if (device == NULL)
1131                         break;
1132     }
1133
1134     if (if_id == 8)
1135     {
1136         DBGPRINT(RT_DEBUG_ERROR, ("No available slot name\n"));
1137         return FALSE;
1138     }
1139
1140     sprintf(name_p, "ra%d", if_id);
1141         return TRUE;
1142 } /* End of RT28XXAvailRANameAssign */
1143 #endif
1144
1145 #if WIRELESS_EXT >= 12
1146 // This function will be called when query /proc
1147 struct iw_statistics *rt28xx_get_wireless_stats(
1148     IN struct net_device *net_dev)
1149 {
1150         PRTMP_ADAPTER pAd = net_dev->ml_priv;
1151
1152
1153         DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_get_wireless_stats --->\n"));
1154
1155         pAd->iw_stats.status = 0; // Status - device dependent for now
1156
1157         // link quality
1158         pAd->iw_stats.qual.qual = ((pAd->Mlme.ChannelQuality * 12)/10 + 10);
1159         if(pAd->iw_stats.qual.qual > 100)
1160                 pAd->iw_stats.qual.qual = 100;
1161
1162 #ifdef CONFIG_STA_SUPPORT
1163         if (pAd->OpMode == OPMODE_STA)
1164                 pAd->iw_stats.qual.level = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1165 #endif // CONFIG_STA_SUPPORT //
1166
1167         pAd->iw_stats.qual.noise = pAd->BbpWriteLatch[66]; // noise level (dBm)
1168
1169         pAd->iw_stats.qual.noise += 256 - 143;
1170         pAd->iw_stats.qual.updated = 1;     // Flags to know if updated
1171 #ifdef IW_QUAL_DBM
1172         pAd->iw_stats.qual.updated |= IW_QUAL_DBM;      // Level + Noise are dBm
1173 #endif // IW_QUAL_DBM //
1174
1175         pAd->iw_stats.discard.nwid = 0;     // Rx : Wrong nwid/essid
1176         pAd->iw_stats.miss.beacon = 0;      // Missed beacons/superframe
1177
1178         DBGPRINT(RT_DEBUG_TRACE, ("<--- rt28xx_get_wireless_stats\n"));
1179         return &pAd->iw_stats;
1180 } /* End of rt28xx_get_wireless_stats */
1181 #endif // WIRELESS_EXT //
1182
1183
1184
1185 void tbtt_tasklet(unsigned long data)
1186 {
1187 #define MAX_TX_IN_TBTT          (16)
1188
1189 }
1190
1191 INT rt28xx_ioctl(
1192         IN      struct net_device       *net_dev,
1193         IN      OUT     struct ifreq    *rq,
1194         IN      INT                                     cmd)
1195 {
1196         VIRTUAL_ADAPTER *pVirtualAd = NULL;
1197         RTMP_ADAPTER    *pAd = NULL;
1198         INT                             ret = 0;
1199
1200         if (net_dev->priv_flags == INT_MAIN)
1201         {
1202                 pAd = net_dev->ml_priv;
1203         }
1204         else
1205         {
1206                 pVirtualAd = net_dev->ml_priv;
1207                 pAd = pVirtualAd->RtmpDev->ml_priv;
1208         }
1209
1210         if (pAd == NULL)
1211         {
1212                 /* if 1st open fail, pAd will be free;
1213                    So the net_dev->ml_priv will be NULL in 2rd open */
1214                 return -ENETDOWN;
1215         }
1216
1217
1218 #ifdef CONFIG_STA_SUPPORT
1219         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1220         {
1221                 ret = rt28xx_sta_ioctl(net_dev, rq, cmd);
1222         }
1223 #endif // CONFIG_STA_SUPPORT //
1224
1225         return ret;
1226 }
1227
1228 /*
1229     ========================================================================
1230
1231     Routine Description:
1232         return ethernet statistics counter
1233
1234     Arguments:
1235         net_dev                     Pointer to net_device
1236
1237     Return Value:
1238         net_device_stats*
1239
1240     Note:
1241
1242     ========================================================================
1243 */
1244 struct net_device_stats *RT28xx_get_ether_stats(
1245     IN  struct net_device *net_dev)
1246 {
1247     RTMP_ADAPTER *pAd = NULL;
1248
1249         if (net_dev)
1250                 pAd = net_dev->ml_priv;
1251
1252         if (pAd)
1253         {
1254
1255                 pAd->stats.rx_packets = pAd->WlanCounters.ReceivedFragmentCount.QuadPart;
1256                 pAd->stats.tx_packets = pAd->WlanCounters.TransmittedFragmentCount.QuadPart;
1257
1258                 pAd->stats.rx_bytes = pAd->RalinkCounters.ReceivedByteCount;
1259                 pAd->stats.tx_bytes = pAd->RalinkCounters.TransmittedByteCount;
1260
1261                 pAd->stats.rx_errors = pAd->Counters8023.RxErrors;
1262                 pAd->stats.tx_errors = pAd->Counters8023.TxErrors;
1263
1264                 pAd->stats.rx_dropped = 0;
1265                 pAd->stats.tx_dropped = 0;
1266
1267             pAd->stats.multicast = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart;   // multicast packets received
1268             pAd->stats.collisions = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions;  // Collision packets
1269
1270             pAd->stats.rx_length_errors = 0;
1271             pAd->stats.rx_over_errors = pAd->Counters8023.RxNoBuffer;                   // receiver ring buff overflow
1272             pAd->stats.rx_crc_errors = 0;//pAd->WlanCounters.FCSErrorCount;     // recved pkt with crc error
1273             pAd->stats.rx_frame_errors = pAd->Counters8023.RcvAlignmentErrors;          // recv'd frame alignment error
1274             pAd->stats.rx_fifo_errors = pAd->Counters8023.RxNoBuffer;                   // recv'r fifo overrun
1275             pAd->stats.rx_missed_errors = 0;                                            // receiver missed packet
1276
1277             // detailed tx_errors
1278             pAd->stats.tx_aborted_errors = 0;
1279             pAd->stats.tx_carrier_errors = 0;
1280             pAd->stats.tx_fifo_errors = 0;
1281             pAd->stats.tx_heartbeat_errors = 0;
1282             pAd->stats.tx_window_errors = 0;
1283
1284             // for cslip etc
1285             pAd->stats.rx_compressed = 0;
1286             pAd->stats.tx_compressed = 0;
1287
1288                 return &pAd->stats;
1289         }
1290         else
1291         return NULL;
1292 }
1293