linux/drivers/staging/rt2870/2870_main_dev.c
<<
>>
Prefs
   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    rtmp_main.c
  29
  30    Abstract:
  31    main initialization routines
  32
  33    Revision History:
  34    Who         When            What
  35    --------    ----------      ----------------------------------------------
  36    Name        Date            Modification logs
  37    Jan Lee             01-10-2005          modified
  38        Sample          Jun/01/07               Merge RT2870 and RT2860 drivers.
  39*/
  40
  41#include "rt_config.h"
  42
  43
  44// Following information will be show when you run 'modinfo'
  45// *** If you have a solution for the bug in current version of driver, please mail to me.
  46// Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. ***
  47MODULE_AUTHOR("Paul Lin <paul_lin@ralinktech.com>");
  48MODULE_DESCRIPTION(RT28xx_CHIP_NAME " Wireless LAN Linux Driver");
  49MODULE_LICENSE("GPL");
  50#ifdef MODULE_VERSION
  51MODULE_VERSION(STA_DRIVER_VERSION);
  52#endif
  53MODULE_ALIAS("rt3070sta");
  54
  55/* Kernel thread and vars, which handles packets that are completed. Only
  56 * packets that have a "complete" function are sent here. This way, the
  57 * completion is run out of kernel context, and doesn't block the rest of
  58 * the stack. */
  59
  60extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
  61                                                                        IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
  62
  63struct usb_device_id rtusb_usb_id[] = {
  64        { USB_DEVICE(0x148F, 0x2770) }, /* Ralink */
  65        { USB_DEVICE(0x1737, 0x0071) }, /* Linksys WUSB600N */
  66        { USB_DEVICE(0x1737, 0x0070) }, /* Linksys */
  67        { USB_DEVICE(0x148F, 0x2870) }, /* Ralink */
  68        { USB_DEVICE(0x148F, 0x3070) }, /* Ralink 3070 */
  69        { USB_DEVICE(0x148F, 0x3071) }, /* Ralink 3071 */
  70        { USB_DEVICE(0x148F, 0x3072) }, /* Ralink 3072 */
  71        { USB_DEVICE(0x0B05, 0x1731) }, /* Asus */
  72        { USB_DEVICE(0x0B05, 0x1732) }, /* Asus */
  73        { USB_DEVICE(0x0B05, 0x1742) }, /* Asus */
  74        { USB_DEVICE(0x0DF6, 0x0017) }, /* Sitecom */
  75        { USB_DEVICE(0x0DF6, 0x002B) }, /* Sitecom */
  76        { USB_DEVICE(0x0DF6, 0x002C) }, /* Sitecom */
  77        { USB_DEVICE(0x0DF6, 0x003E) }, /* Sitecom 3070 */
  78        { USB_DEVICE(0x0DF6, 0x002D) }, /* Sitecom */
  79        { USB_DEVICE(0x0DF6, 0x0039) }, /* Sitecom 2770 */
  80        { USB_DEVICE(0x0DF6, 0x003F) }, /* Sitecom WL-608 */
  81        { USB_DEVICE(0x14B2, 0x3C06) }, /* Conceptronic */
  82        { USB_DEVICE(0x14B2, 0x3C28) }, /* Conceptronic */
  83        { USB_DEVICE(0x2019, 0xED06) }, /* Planex Communications, Inc. */
  84        { USB_DEVICE(0x2019, 0xED14) }, /* Planex Communications, Inc. */
  85        { USB_DEVICE(0x2019, 0xAB25) }, /* Planex Communications, Inc. RT3070 */
  86        { USB_DEVICE(0x07D1, 0x3C09) }, /* D-Link */
  87        { USB_DEVICE(0x07D1, 0x3C11) }, /* D-Link */
  88        { USB_DEVICE(0x2001, 0x3C09) }, /* D-Link */
  89        { USB_DEVICE(0x2001, 0x3C0A) }, /* D-Link 3072*/
  90        { USB_DEVICE(0x14B2, 0x3C07) }, /* AL */
  91        { USB_DEVICE(0x14B2, 0x3C12) }, /* AL 3070 */
  92        { USB_DEVICE(0x050D, 0x8053) }, /* Belkin */
  93        { USB_DEVICE(0x050D, 0x815C) }, /* Belkin */
  94        { USB_DEVICE(0x050D, 0x825a) }, /* Belkin */
  95        { USB_DEVICE(0x14B2, 0x3C23) }, /* Airlink */
  96        { USB_DEVICE(0x14B2, 0x3C27) }, /* Airlink */
  97        { USB_DEVICE(0x07AA, 0x002F) }, /* Corega */
  98        { USB_DEVICE(0x07AA, 0x003C) }, /* Corega */
  99        { USB_DEVICE(0x07AA, 0x003F) }, /* Corega */
 100        { USB_DEVICE(0x18C5, 0x0012) }, /* Corega 3070 */
 101        { USB_DEVICE(0x1044, 0x800B) }, /* Gigabyte */
 102        { USB_DEVICE(0x1044, 0x800D) }, /* Gigabyte GN-WB32L 3070 */
 103        { USB_DEVICE(0x15A9, 0x0006) }, /* Sparklan */
 104        { USB_DEVICE(0x083A, 0xB522) }, /* SMC */
 105        { USB_DEVICE(0x083A, 0xA618) }, /* SMC */
 106        { USB_DEVICE(0x083A, 0x8522) }, /* Arcadyan */
 107        { USB_DEVICE(0x083A, 0x7512) }, /* Arcadyan 2770 */
 108        { USB_DEVICE(0x083A, 0x7522) }, /* Arcadyan */
 109        { USB_DEVICE(0x083A, 0x7511) }, /* Arcadyan 3070 */
 110        { USB_DEVICE(0x0CDE, 0x0022) }, /* ZCOM */
 111        { USB_DEVICE(0x0586, 0x3416) }, /* Zyxel */
 112        { USB_DEVICE(0x0CDE, 0x0025) }, /* Zyxel */
 113        { USB_DEVICE(0x1740, 0x9701) }, /* EnGenius */
 114        { USB_DEVICE(0x1740, 0x9702) }, /* EnGenius */
 115        { USB_DEVICE(0x1740, 0x9703) }, /* EnGenius 3070 */
 116        { USB_DEVICE(0x0471, 0x200f) }, /* Philips */
 117        { USB_DEVICE(0x14B2, 0x3C25) }, /* Draytek */
 118        { USB_DEVICE(0x13D3, 0x3247) }, /* AzureWave */
 119        { USB_DEVICE(0x13D3, 0x3273) }, /* AzureWave 3070*/
 120        { USB_DEVICE(0x083A, 0x6618) }, /* Accton */
 121        { USB_DEVICE(0x15c5, 0x0008) }, /* Amit */
 122        { USB_DEVICE(0x0E66, 0x0001) }, /* Hawking */
 123        { USB_DEVICE(0x0E66, 0x0003) }, /* Hawking */
 124        { USB_DEVICE(0x129B, 0x1828) }, /* Siemens */
 125        { USB_DEVICE(0x157E, 0x300E) }, /* U-Media */
 126        { USB_DEVICE(0x050d, 0x805c) },
 127        { USB_DEVICE(0x1482, 0x3C09) }, /* Abocom*/
 128        { USB_DEVICE(0x14B2, 0x3C09) }, /* Alpha */
 129        { USB_DEVICE(0x04E8, 0x2018) }, /* samsung */
 130        { USB_DEVICE(0x07B8, 0x3070) }, /* AboCom 3070 */
 131        { USB_DEVICE(0x07B8, 0x3071) }, /* AboCom 3071 */
 132        { USB_DEVICE(0x07B8, 0x2870) }, /* AboCom */
 133        { USB_DEVICE(0x07B8, 0x2770) }, /* AboCom */
 134        { USB_DEVICE(0x07B8, 0x3072) }, /* Abocom 3072 */
 135        { USB_DEVICE(0x7392, 0x7711) }, /* Edimax 3070 */
 136        { USB_DEVICE(0x5A57, 0x0280) }, /* Zinwell */
 137        { USB_DEVICE(0x5A57, 0x0282) }, /* Zinwell */
 138        { USB_DEVICE(0x1A32, 0x0304) }, /* Quanta 3070 */
 139        { USB_DEVICE(0x0789, 0x0162) }, /* Logitec 2870 */
 140        { USB_DEVICE(0x0789, 0x0163) }, /* Logitec 2870 */
 141        { USB_DEVICE(0x0789, 0x0164) }, /* Logitec 2870 */
 142        { USB_DEVICE(0x7392, 0x7717) }, /* Edimax */
 143        { USB_DEVICE(0x1EDA, 0x2310) }, /* AirTies 3070 */
 144        { USB_DEVICE(0x1737, 0x0077) }, /* Linksys WUSB54GC-EU v3 */
 145        { } /* Terminating entry */
 146};
 147
 148INT const               rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id);
 149MODULE_DEVICE_TABLE(usb, rtusb_usb_id);
 150
 151#ifndef PF_NOFREEZE
 152#define PF_NOFREEZE  0
 153#endif
 154
 155
 156#ifdef CONFIG_PM
 157static int rt2870_suspend(struct usb_interface *intf, pm_message_t state);
 158static int rt2870_resume(struct usb_interface *intf);
 159#endif // CONFIG_PM //
 160
 161/**************************************************************************/
 162/**************************************************************************/
 163//tested for kernel 2.6series
 164/**************************************************************************/
 165/**************************************************************************/
 166static int rtusb_probe (struct usb_interface *intf,
 167                                                const struct usb_device_id *id);
 168static void rtusb_disconnect(struct usb_interface *intf);
 169
 170struct usb_driver rtusb_driver = {
 171        .name="rt2870",
 172        .probe=rtusb_probe,
 173        .disconnect=rtusb_disconnect,
 174        .id_table=rtusb_usb_id,
 175
 176#ifdef CONFIG_PM
 177        suspend:        rt2870_suspend,
 178        resume:         rt2870_resume,
 179#endif
 180        };
 181
 182#ifdef CONFIG_PM
 183
 184VOID RT2860RejectPendingPackets(
 185        IN      PRTMP_ADAPTER   pAd)
 186{
 187        // clear PS packets
 188        // clear TxSw packets
 189}
 190
 191static int rt2870_suspend(
 192        struct usb_interface *intf,
 193        pm_message_t state)
 194{
 195        struct net_device *net_dev;
 196        PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
 197
 198
 199        DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n"));
 200        net_dev = pAd->net_dev;
 201        netif_device_detach (net_dev);
 202
 203        pAd->PM_FlgSuspend = 1;
 204        if (netif_running(net_dev)) {
 205                RTUSBCancelPendingBulkInIRP(pAd);
 206                RTUSBCancelPendingBulkOutIRP(pAd);
 207        }
 208        DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n"));
 209        return 0;
 210}
 211
 212static int rt2870_resume(
 213        struct usb_interface *intf)
 214{
 215        struct net_device *net_dev;
 216        PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
 217
 218
 219        DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n"));
 220
 221        pAd->PM_FlgSuspend = 0;
 222        net_dev = pAd->net_dev;
 223        netif_device_attach (net_dev);
 224        netif_start_queue(net_dev);
 225        netif_carrier_on(net_dev);
 226        netif_wake_queue(net_dev);
 227
 228        DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n"));
 229        return 0;
 230}
 231#endif // CONFIG_PM //
 232
 233
 234// Init driver module
 235INT __init rtusb_init(void)
 236{
 237        printk("rtusb init --->\n");
 238        return usb_register(&rtusb_driver);
 239}
 240
 241// Deinit driver module
 242VOID __exit rtusb_exit(void)
 243{
 244        usb_deregister(&rtusb_driver);
 245        printk("<--- rtusb exit\n");
 246}
 247
 248module_init(rtusb_init);
 249module_exit(rtusb_exit);
 250
 251
 252
 253
 254/*--------------------------------------------------------------------- */
 255/* function declarations                                                                                                */
 256/*--------------------------------------------------------------------- */
 257
 258/*
 259========================================================================
 260Routine Description:
 261    MLME kernel thread.
 262
 263Arguments:
 264        *Context                        the pAd, driver control block pointer
 265
 266Return Value:
 267    0                                   close the thread
 268
 269Note:
 270========================================================================
 271*/
 272INT MlmeThread(
 273        IN void *Context)
 274{
 275        PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER)Context;
 276        POS_COOKIE      pObj;
 277        int status;
 278
 279        pObj = (POS_COOKIE)pAd->OS_Cookie;
 280
 281        rtmp_os_thread_init("rt2870MlmeThread", (PVOID)&(pAd->mlmeComplete));
 282
 283        while (pAd->mlme_kill == 0)
 284        {
 285                /* lock the device pointers */
 286                //down(&(pAd->mlme_semaphore));
 287                status = down_interruptible(&(pAd->mlme_semaphore));
 288
 289                /* lock the device pointers , need to check if required*/
 290                //down(&(pAd->usbdev_semaphore));
 291
 292                if (!pAd->PM_FlgSuspend)
 293                MlmeHandler(pAd);
 294
 295                /* unlock the device pointers */
 296                //up(&(pAd->usbdev_semaphore));
 297                if (status != 0)
 298                {
 299                        RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
 300                        break;
 301                }
 302        }
 303
 304        /* notify the exit routine that we're actually exiting now
 305         *
 306         * complete()/wait_for_completion() is similar to up()/down(),
 307         * except that complete() is safe in the case where the structure
 308         * is getting deleted in a parallel mode of execution (i.e. just
 309         * after the down() -- that's necessary for the thread-shutdown
 310         * case.
 311         *
 312         * complete_and_exit() goes even further than this -- it is safe in
 313         * the case that the thread of the caller is going away (not just
 314         * the structure) -- this is necessary for the module-remove case.
 315         * This is important in preemption kernels, which transfer the flow
 316         * of execution immediately upon a complete().
 317         */
 318        DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
 319
 320        pObj->MLMEThr_pid = NULL;
 321
 322        complete_and_exit (&pAd->mlmeComplete, 0);
 323        return 0;
 324
 325}
 326
 327
 328/*
 329========================================================================
 330Routine Description:
 331    USB command kernel thread.
 332
 333Arguments:
 334        *Context                        the pAd, driver control block pointer
 335
 336Return Value:
 337    0                                   close the thread
 338
 339Note:
 340========================================================================
 341*/
 342INT RTUSBCmdThread(
 343        IN void * Context)
 344{
 345        PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER)Context;
 346        POS_COOKIE              pObj;
 347        int status;
 348
 349        pObj = (POS_COOKIE)pAd->OS_Cookie;
 350
 351        rtmp_os_thread_init("rt2870CmdThread", (PVOID)&(pAd->CmdQComplete));
 352
 353        NdisAcquireSpinLock(&pAd->CmdQLock);
 354        pAd->CmdQ.CmdQState = RT2870_THREAD_RUNNING;
 355        NdisReleaseSpinLock(&pAd->CmdQLock);
 356
 357        while (pAd->CmdQ.CmdQState == RT2870_THREAD_RUNNING)
 358        {
 359                /* lock the device pointers */
 360                //down(&(pAd->RTUSBCmd_semaphore));
 361                status = down_interruptible(&(pAd->RTUSBCmd_semaphore));
 362
 363                if (pAd->CmdQ.CmdQState == RT2870_THREAD_STOPED)
 364                        break;
 365
 366                if (status != 0)
 367                {
 368                        RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
 369                        break;
 370                }
 371                /* lock the device pointers , need to check if required*/
 372                //down(&(pAd->usbdev_semaphore));
 373
 374                if (!pAd->PM_FlgSuspend)
 375                CMDHandler(pAd);
 376
 377                /* unlock the device pointers */
 378                //up(&(pAd->usbdev_semaphore));
 379        }
 380
 381        if (!pAd->PM_FlgSuspend)
 382        {       // Clear the CmdQElements.
 383                CmdQElmt        *pCmdQElmt = NULL;
 384
 385                NdisAcquireSpinLock(&pAd->CmdQLock);
 386                pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
 387                while(pAd->CmdQ.size)
 388                {
 389                        RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt);
 390                        if (pCmdQElmt)
 391                        {
 392                                if (pCmdQElmt->CmdFromNdis == TRUE)
 393                                {
 394                                        if (pCmdQElmt->buffer != NULL)
 395                                                NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
 396
 397                                        NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
 398                                }
 399                                else
 400                                {
 401                                        if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0))
 402                                                NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
 403                            {
 404                                                NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
 405                                        }
 406                                }
 407                        }
 408                }
 409
 410                NdisReleaseSpinLock(&pAd->CmdQLock);
 411        }
 412        /* notify the exit routine that we're actually exiting now
 413         *
 414         * complete()/wait_for_completion() is similar to up()/down(),
 415         * except that complete() is safe in the case where the structure
 416         * is getting deleted in a parallel mode of execution (i.e. just
 417         * after the down() -- that's necessary for the thread-shutdown
 418         * case.
 419         *
 420         * complete_and_exit() goes even further than this -- it is safe in
 421         * the case that the thread of the caller is going away (not just
 422         * the structure) -- this is necessary for the module-remove case.
 423         * This is important in preemption kernels, which transfer the flow
 424         * of execution immediately upon a complete().
 425         */
 426        DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n"));
 427
 428        pObj->RTUSBCmdThr_pid = NULL;
 429
 430        complete_and_exit (&pAd->CmdQComplete, 0);
 431        return 0;
 432
 433}
 434
 435
 436static void RT2870_TimerQ_Handle(RTMP_ADAPTER *pAd)
 437{
 438        int status;
 439        RALINK_TIMER_STRUCT     *pTimer;
 440        RT2870_TIMER_ENTRY      *pEntry;
 441        unsigned long   irqFlag;
 442
 443        while(!pAd->TimerFunc_kill)
 444        {
 445//              printk("waiting for event!\n");
 446                pTimer = NULL;
 447
 448                status = down_interruptible(&(pAd->RTUSBTimer_semaphore));
 449
 450                if (pAd->TimerQ.status == RT2870_THREAD_STOPED)
 451                        break;
 452
 453                // event happened.
 454                while(pAd->TimerQ.pQHead)
 455                {
 456                        RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlag);
 457                        pEntry = pAd->TimerQ.pQHead;
 458                        if (pEntry)
 459                        {
 460                                pTimer = pEntry->pRaTimer;
 461
 462                                // update pQHead
 463                                pAd->TimerQ.pQHead = pEntry->pNext;
 464                                if (pEntry == pAd->TimerQ.pQTail)
 465                                        pAd->TimerQ.pQTail = NULL;
 466
 467                                // return this queue entry to timerQFreeList.
 468                                pEntry->pNext = pAd->TimerQ.pQPollFreeList;
 469                                pAd->TimerQ.pQPollFreeList = pEntry;
 470                        }
 471                        RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlag);
 472
 473                        if (pTimer)
 474                        {
 475                                if (pTimer->handle != NULL)
 476                                if (!pAd->PM_FlgSuspend)
 477                                        pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer);
 478                                if ((pTimer->Repeat) && (pTimer->State == FALSE))
 479                                        RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue);
 480                        }
 481                }
 482
 483                if (status != 0)
 484                {
 485                        pAd->TimerQ.status = RT2870_THREAD_STOPED;
 486                        RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
 487                        break;
 488                }
 489        }
 490}
 491
 492
 493INT TimerQThread(
 494        IN OUT PVOID Context)
 495{
 496        PRTMP_ADAPTER   pAd;
 497        POS_COOKIE      pObj;
 498
 499        pAd = (PRTMP_ADAPTER)Context;
 500        pObj = (POS_COOKIE) pAd->OS_Cookie;
 501
 502        rtmp_os_thread_init("rt2870TimerQHandle", (PVOID)&(pAd->TimerQComplete));
 503
 504        RT2870_TimerQ_Handle(pAd);
 505
 506        /* notify the exit routine that we're actually exiting now
 507         *
 508         * complete()/wait_for_completion() is similar to up()/down(),
 509         * except that complete() is safe in the case where the structure
 510         * is getting deleted in a parallel mode of execution (i.e. just
 511         * after the down() -- that's necessary for the thread-shutdown
 512         * case.
 513         *
 514         * complete_and_exit() goes even further than this -- it is safe in
 515         * the case that the thread of the caller is going away (not just
 516         * the structure) -- this is necessary for the module-remove case.
 517         * This is important in preemption kernels, which transfer the flow
 518         * of execution immediately upon a complete().
 519         */
 520        DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
 521
 522        pObj->TimerQThr_pid = NULL;
 523
 524        complete_and_exit(&pAd->TimerQComplete, 0);
 525        return 0;
 526
 527}
 528
 529
 530RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert(
 531        IN RTMP_ADAPTER *pAd,
 532        IN RALINK_TIMER_STRUCT *pTimer)
 533{
 534        RT2870_TIMER_ENTRY *pQNode = NULL, *pQTail;
 535        unsigned long irqFlags;
 536
 537
 538        RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
 539        if (pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT)
 540        {
 541                if(pAd->TimerQ.pQPollFreeList)
 542                {
 543                        pQNode = pAd->TimerQ.pQPollFreeList;
 544                        pAd->TimerQ.pQPollFreeList = pQNode->pNext;
 545
 546                        pQNode->pRaTimer = pTimer;
 547                        pQNode->pNext = NULL;
 548
 549                        pQTail = pAd->TimerQ.pQTail;
 550                        if (pAd->TimerQ.pQTail != NULL)
 551                                pQTail->pNext = pQNode;
 552                        pAd->TimerQ.pQTail = pQNode;
 553                        if (pAd->TimerQ.pQHead == NULL)
 554                                pAd->TimerQ.pQHead = pQNode;
 555                }
 556                RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
 557
 558                if (pQNode)
 559                        up(&pAd->RTUSBTimer_semaphore);
 560                        //wake_up(&timerWaitQ);
 561        }
 562        else
 563        {
 564                RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
 565        }
 566        return pQNode;
 567}
 568
 569
 570BOOLEAN RT2870_TimerQ_Remove(
 571        IN RTMP_ADAPTER *pAd,
 572        IN RALINK_TIMER_STRUCT *pTimer)
 573{
 574        RT2870_TIMER_ENTRY *pNode, *pPrev = NULL;
 575        unsigned long irqFlags;
 576
 577        RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
 578        if (pAd->TimerQ.status >= RT2870_THREAD_INITED)
 579        {
 580                pNode = pAd->TimerQ.pQHead;
 581                while (pNode)
 582                {
 583                        if (pNode->pRaTimer == pTimer)
 584                                break;
 585                        pPrev = pNode;
 586                        pNode = pNode->pNext;
 587                }
 588
 589                // Now move it to freeList queue.
 590                if (pNode)
 591                {
 592                        if (pNode == pAd->TimerQ.pQHead)
 593                                pAd->TimerQ.pQHead = pNode->pNext;
 594                        if (pNode == pAd->TimerQ.pQTail)
 595                                pAd->TimerQ.pQTail = pPrev;
 596                        if (pPrev != NULL)
 597                                pPrev->pNext = pNode->pNext;
 598
 599                        // return this queue entry to timerQFreeList.
 600                        pNode->pNext = pAd->TimerQ.pQPollFreeList;
 601                        pAd->TimerQ.pQPollFreeList = pNode;
 602                }
 603        }
 604        RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
 605
 606        return TRUE;
 607}
 608
 609
 610void RT2870_TimerQ_Exit(RTMP_ADAPTER *pAd)
 611{
 612        RT2870_TIMER_ENTRY *pTimerQ;
 613        unsigned long irqFlags;
 614
 615        RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
 616        while (pAd->TimerQ.pQHead)
 617        {
 618                pTimerQ = pAd->TimerQ.pQHead;
 619                pAd->TimerQ.pQHead = pTimerQ->pNext;
 620                // remove the timeQ
 621        }
 622        pAd->TimerQ.pQPollFreeList = NULL;
 623        os_free_mem(pAd, pAd->TimerQ.pTimerQPoll);
 624        pAd->TimerQ.pQTail = NULL;
 625        pAd->TimerQ.pQHead = NULL;
 626        pAd->TimerQ.status = RT2870_THREAD_STOPED;
 627        RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
 628
 629}
 630
 631
 632void RT2870_TimerQ_Init(RTMP_ADAPTER *pAd)
 633{
 634        int     i;
 635        RT2870_TIMER_ENTRY *pQNode, *pEntry;
 636        unsigned long irqFlags;
 637
 638        NdisAllocateSpinLock(&pAd->TimerQLock);
 639
 640        RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
 641        NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));
 642        //InterlockedExchange(&pAd->TimerQ.count, 0);
 643
 644        /* Initialise the wait q head */
 645        //init_waitqueue_head(&timerWaitQ);
 646
 647        os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RT2870_TIMER_ENTRY) * TIMER_QUEUE_SIZE_MAX);
 648        if (pAd->TimerQ.pTimerQPoll)
 649        {
 650                pEntry = NULL;
 651                pQNode = (RT2870_TIMER_ENTRY *)pAd->TimerQ.pTimerQPoll;
 652                for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)
 653                {
 654                        pQNode->pNext = pEntry;
 655                        pEntry = pQNode;
 656                        pQNode++;
 657                }
 658                pAd->TimerQ.pQPollFreeList = pEntry;
 659                pAd->TimerQ.pQHead = NULL;
 660                pAd->TimerQ.pQTail = NULL;
 661                pAd->TimerQ.status = RT2870_THREAD_INITED;
 662        }
 663        RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
 664}
 665
 666
 667VOID RT2870_WatchDog(IN RTMP_ADAPTER *pAd)
 668{
 669        PHT_TX_CONTEXT          pHTTXContext;
 670        int                                     idx;
 671        ULONG                           irqFlags;
 672        PURB                            pUrb;
 673        BOOLEAN                         needDumpSeq = FALSE;
 674        UINT32                  MACValue;
 675
 676
 677        idx = 0;
 678        RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
 679        if ((MACValue & 0xff) !=0 )
 680        {
 681                DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
 682                RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012);
 683                while((MACValue &0xff) != 0 && (idx++ < 10))
 684                {
 685                        RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
 686                        NdisMSleep(1);
 687                }
 688                RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
 689        }
 690
 691//PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
 692        idx = 0;
 693        if ((MACValue & 0xff00) !=0 )
 694        {
 695                DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
 696                RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf4000a);
 697                while((MACValue &0xff00) != 0 && (idx++ < 10))
 698                {
 699                        RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
 700                        NdisMSleep(1);
 701                }
 702                RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
 703        }
 704
 705        if (pAd->watchDogRxOverFlowCnt >= 2)
 706        {
 707                DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
 708                if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
 709                                                                        fRTMP_ADAPTER_BULKIN_RESET |
 710                                                                        fRTMP_ADAPTER_HALT_IN_PROGRESS |
 711                                                                        fRTMP_ADAPTER_NIC_NOT_EXIST))))
 712                {
 713                        DBGPRINT(RT_DEBUG_TRACE, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
 714                        RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
 715                        RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0);
 716                        needDumpSeq = TRUE;
 717                }
 718                pAd->watchDogRxOverFlowCnt = 0;
 719        }
 720
 721
 722        for (idx = 0; idx < NUM_OF_TX_RING; idx++)
 723        {
 724                pUrb = NULL;
 725
 726                RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags);
 727                if ((pAd->BulkOutPending[idx] == TRUE) && pAd->watchDogTxPendingCnt)
 728                {
 729                        pAd->watchDogTxPendingCnt[idx]++;
 730
 731                        if ((pAd->watchDogTxPendingCnt[idx] > 2) &&
 732                                 (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET)))
 733                                )
 734                        {
 735                                // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!
 736                                pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[idx]);
 737                                if (pHTTXContext->IRPPending)
 738                                {       // Check TxContext.
 739                                        pUrb = pHTTXContext->pUrb;
 740                                }
 741                                else if (idx == MGMTPIPEIDX)
 742                                {
 743                                        PTX_CONTEXT pMLMEContext, pNULLContext, pPsPollContext;
 744
 745                                        //Check MgmtContext.
 746                                        pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa);
 747                                        pPsPollContext = (PTX_CONTEXT)(&pAd->PsPollContext);
 748                                        pNULLContext = (PTX_CONTEXT)(&pAd->NullContext);
 749
 750                                        if (pMLMEContext->IRPPending)
 751                                        {
 752                                                ASSERT(pMLMEContext->IRPPending);
 753                                                pUrb = pMLMEContext->pUrb;
 754                                        }
 755                                        else if (pNULLContext->IRPPending)
 756                                        {
 757                                                ASSERT(pNULLContext->IRPPending);
 758                                                pUrb = pNULLContext->pUrb;
 759                                        }
 760                                        else if (pPsPollContext->IRPPending)
 761                                        {
 762                                                ASSERT(pPsPollContext->IRPPending);
 763                                                pUrb = pPsPollContext->pUrb;
 764                                        }
 765                                }
 766
 767                                RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
 768
 769                                DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx));
 770                                if (pUrb)
 771                                {
 772                                        DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n"));
 773                                        // unlink it now
 774                                        RTUSB_UNLINK_URB(pUrb);
 775                                        // Sleep 200 microseconds to give cancellation time to work
 776                                        RTMPusecDelay(200);
 777                                        needDumpSeq = TRUE;
 778                                }
 779                                else
 780                                {
 781                                        DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
 782                                }
 783                        }
 784                        else
 785                        {
 786                                RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
 787                        }
 788                }
 789                else
 790                {
 791                        RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
 792                }
 793        }
 794
 795        // For Sigma debug, dump the ba_reordering sequence.
 796        if((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0))
 797        {
 798                USHORT                          Idx;
 799                PBA_REC_ENTRY           pBAEntry = NULL;
 800                UCHAR                           count = 0;
 801                struct reordering_mpdu *mpdu_blk;
 802
 803                Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0];
 804
 805                pBAEntry = &pAd->BATable.BARecEntry[Idx];
 806                if((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL))
 807                {
 808                        DBGPRINT(RT_DEBUG_TRACE, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
 809                        NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
 810                        mpdu_blk = pBAEntry->list.next;
 811                        while (mpdu_blk)
 812                        {
 813                                DBGPRINT(RT_DEBUG_TRACE, ("\t%d:Seq-%d, bAMSDU-%d!\n", count, mpdu_blk->Sequence, mpdu_blk->bAMSDU));
 814                                mpdu_blk = mpdu_blk->next;
 815                                count++;
 816                        }
 817
 818                        DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq));
 819                        NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
 820                }
 821        }
 822}
 823
 824/*
 825========================================================================
 826Routine Description:
 827    Release allocated resources.
 828
 829Arguments:
 830    *dev                                Point to the PCI or USB device
 831        pAd                                     driver control block pointer
 832
 833Return Value:
 834    None
 835
 836Note:
 837========================================================================
 838*/
 839static void _rtusb_disconnect(struct usb_device *dev, PRTMP_ADAPTER pAd)
 840{
 841        struct net_device       *net_dev = NULL;
 842
 843
 844        DBGPRINT(RT_DEBUG_ERROR, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",
 845                                dev->bus->bus_name, dev->devpath));
 846        if (!pAd)
 847        {
 848                usb_put_dev(dev);
 849
 850                printk("rtusb_disconnect: pAd == NULL!\n");
 851                return;
 852        }
 853        RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
 854
 855
 856
 857        // for debug, wait to show some messages to /proc system
 858        udelay(1);
 859
 860
 861
 862
 863        net_dev = pAd->net_dev;
 864        if (pAd->net_dev != NULL)
 865        {
 866                printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev->name);
 867                unregister_netdev (pAd->net_dev);
 868        }
 869        udelay(1);
 870        flush_scheduled_work();
 871        udelay(1);
 872
 873        // free net_device memory
 874        free_netdev(net_dev);
 875
 876        // free adapter memory
 877        RTMPFreeAdapter(pAd);
 878
 879        // release a use of the usb device structure
 880        usb_put_dev(dev);
 881        udelay(1);
 882
 883        DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n"));
 884}
 885
 886
 887/*
 888========================================================================
 889Routine Description:
 890    Probe RT28XX chipset.
 891
 892Arguments:
 893    *dev                                Point to the PCI or USB device
 894        interface
 895        *id_table                       Point to the PCI or USB device ID
 896
 897Return Value:
 898    None
 899
 900Note:
 901========================================================================
 902*/
 903static int rtusb_probe (struct usb_interface *intf,
 904                                                const struct usb_device_id *id)
 905{
 906        PRTMP_ADAPTER pAd;
 907        return (int)rt28xx_probe((void *)intf, (void *)id, 0, &pAd);
 908}
 909
 910
 911static void rtusb_disconnect(struct usb_interface *intf)
 912{
 913        struct usb_device   *dev = interface_to_usbdev(intf);
 914        PRTMP_ADAPTER       pAd;
 915
 916
 917        pAd = usb_get_intfdata(intf);
 918        usb_set_intfdata(intf, NULL);
 919
 920        _rtusb_disconnect(dev, pAd);
 921}
 922
 923
 924/*
 925========================================================================
 926Routine Description:
 927    Close kernel threads.
 928
 929Arguments:
 930        *pAd                            the raxx interface data pointer
 931
 932Return Value:
 933    NONE
 934
 935Note:
 936========================================================================
 937*/
 938VOID RT28xxThreadTerminate(
 939        IN RTMP_ADAPTER *pAd)
 940{
 941        POS_COOKIE      pObj = (POS_COOKIE) pAd->OS_Cookie;
 942        INT                     ret;
 943
 944
 945        // Sleep 50 milliseconds so pending io might finish normally
 946        RTMPusecDelay(50000);
 947
 948        // We want to wait until all pending receives and sends to the
 949        // device object. We cancel any
 950        // irps. Wait until sends and receives have stopped.
 951        RTUSBCancelPendingIRPs(pAd);
 952
 953        // Terminate Threads
 954
 955        if (pid_nr(pObj->TimerQThr_pid) > 0)
 956        {
 957                POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
 958
 959                printk("Terminate the TimerQThr_pid=%d!\n", pid_nr(pObj->TimerQThr_pid));
 960                mb();
 961                pAd->TimerFunc_kill = 1;
 962                mb();
 963                ret = kill_pid(pObj->TimerQThr_pid, SIGTERM, 1);
 964                if (ret)
 965                {
 966                        printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
 967                                        pAd->net_dev->name, pid_nr(pObj->TimerQThr_pid), ret);
 968                }
 969                else
 970                {
 971                        wait_for_completion(&pAd->TimerQComplete);
 972                        pObj->TimerQThr_pid = NULL;
 973                }
 974        }
 975
 976        if (pid_nr(pObj->MLMEThr_pid) > 0)
 977        {
 978                printk("Terminate the MLMEThr_pid=%d!\n", pid_nr(pObj->MLMEThr_pid));
 979                mb();
 980                pAd->mlme_kill = 1;
 981                //RT28XX_MLME_HANDLER(pAd);
 982                mb();
 983                ret = kill_pid(pObj->MLMEThr_pid, SIGTERM, 1);
 984                if (ret)
 985                {
 986                        printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n",
 987                                        pAd->net_dev->name, pid_nr(pObj->MLMEThr_pid), ret);
 988                }
 989                else
 990                {
 991                        //wait_for_completion (&pAd->notify);
 992                        wait_for_completion (&pAd->mlmeComplete);
 993                        pObj->MLMEThr_pid = NULL;
 994                }
 995        }
 996
 997        if (pid_nr(pObj->RTUSBCmdThr_pid) > 0)
 998        {
 999                printk("Terminate the RTUSBCmdThr_pid=%d!\n", pid_nr(pObj->RTUSBCmdThr_pid));
1000                mb();
1001                NdisAcquireSpinLock(&pAd->CmdQLock);
1002                pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
1003                NdisReleaseSpinLock(&pAd->CmdQLock);
1004                mb();
1005                //RTUSBCMDUp(pAd);
1006                ret = kill_pid(pObj->RTUSBCmdThr_pid, SIGTERM, 1);
1007                if (ret)
1008                {
1009                        printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
1010                                        pAd->net_dev->name, pid_nr(pObj->RTUSBCmdThr_pid), ret);
1011                }
1012                else
1013                {
1014                        //wait_for_completion (&pAd->notify);
1015                        wait_for_completion (&pAd->CmdQComplete);
1016                        pObj->RTUSBCmdThr_pid = NULL;
1017                }
1018        }
1019
1020        // Kill tasklets
1021        pAd->mlme_kill = 0;
1022        pAd->CmdQ.CmdQState = RT2870_THREAD_UNKNOWN;
1023        pAd->TimerFunc_kill = 0;
1024}
1025
1026
1027void kill_thread_task(IN PRTMP_ADAPTER pAd)
1028{
1029        POS_COOKIE pObj;
1030
1031        pObj = (POS_COOKIE) pAd->OS_Cookie;
1032
1033        tasklet_kill(&pObj->rx_done_task);
1034        tasklet_kill(&pObj->mgmt_dma_done_task);
1035        tasklet_kill(&pObj->ac0_dma_done_task);
1036        tasklet_kill(&pObj->ac1_dma_done_task);
1037        tasklet_kill(&pObj->ac2_dma_done_task);
1038        tasklet_kill(&pObj->ac3_dma_done_task);
1039        tasklet_kill(&pObj->hcca_dma_done_task);
1040        tasklet_kill(&pObj->tbtt_task);
1041
1042}
1043
1044
1045/*
1046========================================================================
1047Routine Description:
1048    Check the chipset vendor/product ID.
1049
1050Arguments:
1051    _dev_p                              Point to the PCI or USB device
1052
1053Return Value:
1054    TRUE                                Check ok
1055        FALSE                           Check fail
1056
1057Note:
1058========================================================================
1059*/
1060BOOLEAN RT28XXChipsetCheck(
1061        IN void *_dev_p)
1062{
1063        struct usb_interface *intf = (struct usb_interface *)_dev_p;
1064        struct usb_device *dev_p = interface_to_usbdev(intf);
1065        UINT32 i;
1066
1067
1068        for(i=0; i<rtusb_usb_id_len; i++)
1069        {
1070                if (dev_p->descriptor.idVendor == rtusb_usb_id[i].idVendor &&
1071                        dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct)
1072                {
1073                        printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1074                                        dev_p->descriptor.idVendor, dev_p->descriptor.idProduct);
1075                        break;
1076                }
1077        }
1078
1079        if (i == rtusb_usb_id_len)
1080        {
1081                printk("rt2870: Error! Device Descriptor not matching!\n");
1082                return FALSE;
1083        }
1084
1085        return TRUE;
1086}
1087
1088
1089/*
1090========================================================================
1091Routine Description:
1092    Init net device structure.
1093
1094Arguments:
1095    _dev_p                              Point to the PCI or USB device
1096    *net_dev                    Point to the net device
1097        *pAd                            the raxx interface data pointer
1098
1099Return Value:
1100    TRUE                                Init ok
1101        FALSE                           Init fail
1102
1103Note:
1104========================================================================
1105*/
1106BOOLEAN RT28XXNetDevInit(
1107        IN void                                 *_dev_p,
1108        IN struct  net_device   *net_dev,
1109        IN RTMP_ADAPTER                 *pAd)
1110{
1111        struct usb_interface *intf = (struct usb_interface *)_dev_p;
1112        struct usb_device *dev_p = interface_to_usbdev(intf);
1113
1114
1115        pAd->config = &dev_p->config->desc;
1116        return TRUE;
1117}
1118
1119
1120/*
1121========================================================================
1122Routine Description:
1123    Init net device structure.
1124
1125Arguments:
1126    _dev_p                              Point to the PCI or USB device
1127        *pAd                            the raxx interface data pointer
1128
1129Return Value:
1130    TRUE                                Config ok
1131        FALSE                           Config fail
1132
1133Note:
1134========================================================================
1135*/
1136BOOLEAN RT28XXProbePostConfig(
1137        IN void                                 *_dev_p,
1138        IN RTMP_ADAPTER                 *pAd,
1139        IN INT32                                interface)
1140{
1141        struct usb_interface *intf = (struct usb_interface *)_dev_p;
1142        struct usb_host_interface *iface_desc;
1143        ULONG BulkOutIdx;
1144        UINT32 i;
1145
1146
1147        /* get the active interface descriptor */
1148        iface_desc = intf->cur_altsetting;
1149
1150        /* get # of enpoints  */
1151        pAd->NumberOfPipes = iface_desc->desc.bNumEndpoints;
1152        DBGPRINT(RT_DEBUG_TRACE,
1153                        ("NumEndpoints=%d\n", iface_desc->desc.bNumEndpoints));
1154
1155        /* Configure Pipes */
1156        BulkOutIdx = 0;
1157
1158        for(i=0; i<pAd->NumberOfPipes; i++)
1159        {
1160                if ((iface_desc->endpoint[i].desc.bmAttributes ==
1161                                USB_ENDPOINT_XFER_BULK) &&
1162                        ((iface_desc->endpoint[i].desc.bEndpointAddress &
1163                                USB_ENDPOINT_DIR_MASK) == USB_DIR_IN))
1164                {
1165                        pAd->BulkInEpAddr = iface_desc->endpoint[i].desc.bEndpointAddress;
1166                        pAd->BulkInMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1167
1168                        DBGPRINT_RAW(RT_DEBUG_TRACE,
1169                                ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize));
1170                        DBGPRINT_RAW(RT_DEBUG_TRACE,
1171                                ("EP address = 0x%2x\n", iface_desc->endpoint[i].desc.bEndpointAddress));
1172                }
1173                else if ((iface_desc->endpoint[i].desc.bmAttributes ==
1174                                        USB_ENDPOINT_XFER_BULK) &&
1175                                ((iface_desc->endpoint[i].desc.bEndpointAddress &
1176                                        USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT))
1177                {
1178                        // there are 6 bulk out EP. EP6 highest priority.
1179                        // EP1-4 is EDCA.  EP5 is HCCA.
1180                        pAd->BulkOutEpAddr[BulkOutIdx++] = iface_desc->endpoint[i].desc.bEndpointAddress;
1181                        pAd->BulkOutMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1182
1183                        DBGPRINT_RAW(RT_DEBUG_TRACE,
1184                                ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize));
1185                        DBGPRINT_RAW(RT_DEBUG_TRACE,
1186                                ("EP address = 0x%2x  \n", iface_desc->endpoint[i].desc.bEndpointAddress));
1187                }
1188        }
1189
1190        if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0]))
1191        {
1192                printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __func__);
1193                return FALSE;
1194        }
1195
1196        return TRUE;
1197}
1198
1199
1200/*
1201========================================================================
1202Routine Description:
1203    Disable DMA.
1204
1205Arguments:
1206        *pAd                            the raxx interface data pointer
1207
1208Return Value:
1209        None
1210
1211Note:
1212========================================================================
1213*/
1214VOID RT28XXDMADisable(
1215        IN RTMP_ADAPTER                 *pAd)
1216{
1217        // no use
1218}
1219
1220
1221
1222/*
1223========================================================================
1224Routine Description:
1225    Enable DMA.
1226
1227Arguments:
1228        *pAd                            the raxx interface data pointer
1229
1230Return Value:
1231        None
1232
1233Note:
1234========================================================================
1235*/
1236VOID RT28XXDMAEnable(
1237        IN RTMP_ADAPTER                 *pAd)
1238{
1239        WPDMA_GLO_CFG_STRUC     GloCfg;
1240        USB_DMA_CFG_STRUC       UsbCfg;
1241        int                                     i = 0;
1242
1243
1244        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
1245        do
1246        {
1247                RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1248                if ((GloCfg.field.TxDMABusy == 0)  && (GloCfg.field.RxDMABusy == 0))
1249                        break;
1250
1251                DBGPRINT(RT_DEBUG_TRACE, ("==>  DMABusy\n"));
1252                RTMPusecDelay(1000);
1253                i++;
1254        }while ( i <200);
1255
1256
1257        RTMPusecDelay(50);
1258        GloCfg.field.EnTXWriteBackDDONE = 1;
1259        GloCfg.field.EnableRxDMA = 1;
1260        GloCfg.field.EnableTxDMA = 1;
1261        DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
1262        RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
1263
1264        UsbCfg.word = 0;
1265        UsbCfg.field.phyclear = 0;
1266        /* usb version is 1.1,do not use bulk in aggregation */
1267        if (pAd->BulkInMaxPacketSize == 512)
1268                        UsbCfg.field.RxBulkAggEn = 1;
1269        /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
1270        UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE /1024)-3;
1271        UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */
1272        UsbCfg.field.RxBulkEn = 1;
1273        UsbCfg.field.TxBulkEn = 1;
1274
1275        RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word);
1276
1277}
1278
1279/*
1280========================================================================
1281Routine Description:
1282    Write Beacon buffer to Asic.
1283
1284Arguments:
1285        *pAd                            the raxx interface data pointer
1286
1287Return Value:
1288        None
1289
1290Note:
1291========================================================================
1292*/
1293VOID RT28xx_UpdateBeaconToAsic(
1294        IN RTMP_ADAPTER         *pAd,
1295        IN INT                          apidx,
1296        IN ULONG                        FrameLen,
1297        IN ULONG                        UpdatePos)
1298{
1299        PUCHAR          pBeaconFrame = NULL;
1300        UCHAR                   *ptr;
1301        UINT                    i, padding;
1302        BEACON_SYNC_STRUCT      *pBeaconSync = pAd->CommonCfg.pBeaconSync;
1303        UINT32                  longValue;
1304        BOOLEAN                 bBcnReq = FALSE;
1305        UCHAR                   bcn_idx = 0;
1306
1307
1308        if (pBeaconFrame == NULL)
1309        {
1310                DBGPRINT(RT_DEBUG_ERROR,("pBeaconFrame is NULL!\n"));
1311                return;
1312        }
1313
1314        if (pBeaconSync == NULL)
1315        {
1316                DBGPRINT(RT_DEBUG_ERROR,("pBeaconSync is NULL!\n"));
1317                return;
1318        }
1319
1320        //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) ||
1321        //      ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
1322        //      )
1323        if (bBcnReq == FALSE)
1324        {
1325                /* when the ra interface is down, do not send its beacon frame */
1326                /* clear all zero */
1327                for(i=0; i<TXWI_SIZE; i+=4) {
1328                        RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
1329                }
1330                pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1331                NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE);
1332        }
1333        else
1334        {
1335                ptr = (PUCHAR)&pAd->BeaconTxWI;
1336
1337                if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE)
1338                {       // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames.
1339                        pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1340                        NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE);
1341                }
1342
1343                if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != (1 << bcn_idx))
1344                {
1345                        for (i=0; i<TXWI_SIZE; i+=4)  // 16-byte TXWI field
1346                        {
1347                                longValue =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
1348                                RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longValue);
1349                                ptr += 4;
1350                        }
1351                }
1352
1353                ptr = pBeaconSync->BeaconBuf[bcn_idx];
1354                padding = (FrameLen & 0x01);
1355                NdisZeroMemory((PUCHAR)(pBeaconFrame + FrameLen), padding);
1356                FrameLen += padding;
1357                for (i = 0 ; i < FrameLen /*HW_BEACON_OFFSET*/; i += 2)
1358                {
1359                        if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE)
1360                        {
1361                                NdisMoveMemory(ptr, pBeaconFrame, 2);
1362                                //shortValue = *ptr + (*(ptr+1)<<8);
1363                                //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue);
1364                                RTUSBMultiWrite(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, ptr, 2);
1365                        }
1366                        ptr +=2;
1367                        pBeaconFrame += 2;
1368                }
1369
1370                pBeaconSync->BeaconBitMap |= (1 << bcn_idx);
1371
1372                // For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame.
1373        }
1374
1375}
1376
1377
1378VOID RT2870_BssBeaconStop(
1379        IN RTMP_ADAPTER *pAd)
1380{
1381        BEACON_SYNC_STRUCT      *pBeaconSync;
1382        int i, offset;
1383        BOOLEAN Cancelled = TRUE;
1384
1385        pBeaconSync = pAd->CommonCfg.pBeaconSync;
1386        if (pBeaconSync && pBeaconSync->EnableBeacon)
1387        {
1388                INT NumOfBcn;
1389
1390                NumOfBcn = MAX_MESH_NUM;
1391
1392                RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1393
1394                for(i=0; i<NumOfBcn; i++)
1395                {
1396                        NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1397                        NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1398
1399                        for (offset=0; offset<HW_BEACON_OFFSET; offset+=4)
1400                                RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[i] + offset, 0x00);
1401
1402                        pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1403                        pBeaconSync->TimIELocationInBeacon[i] = 0;
1404                }
1405                pBeaconSync->BeaconBitMap = 0;
1406                pBeaconSync->DtimBitOn = 0;
1407        }
1408}
1409
1410
1411VOID RT2870_BssBeaconStart(
1412        IN RTMP_ADAPTER *pAd)
1413{
1414        int apidx;
1415        BEACON_SYNC_STRUCT      *pBeaconSync;
1416//      LARGE_INTEGER   tsfTime, deltaTime;
1417
1418        pBeaconSync = pAd->CommonCfg.pBeaconSync;
1419        if (pBeaconSync && pBeaconSync->EnableBeacon)
1420        {
1421                INT NumOfBcn;
1422
1423                NumOfBcn = MAX_MESH_NUM;
1424
1425                for(apidx=0; apidx<NumOfBcn; apidx++)
1426                {
1427                        UCHAR CapabilityInfoLocationInBeacon = 0;
1428                        UCHAR TimIELocationInBeacon = 0;
1429
1430                        NdisZeroMemory(pBeaconSync->BeaconBuf[apidx], HW_BEACON_OFFSET);
1431                        pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = CapabilityInfoLocationInBeacon;
1432                        pBeaconSync->TimIELocationInBeacon[apidx] = TimIELocationInBeacon;
1433                        NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], TXWI_SIZE);
1434                }
1435                pBeaconSync->BeaconBitMap = 0;
1436                pBeaconSync->DtimBitOn = 0;
1437                pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE;
1438
1439                pAd->CommonCfg.BeaconAdjust = 0;
1440                pAd->CommonCfg.BeaconFactor = 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10);
1441                pAd->CommonCfg.BeaconRemain = (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1;
1442                printk(RT28xx_CHIP_NAME "_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd->CommonCfg.BeaconFactor, pAd->CommonCfg.BeaconRemain);
1443                RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, pAd->CommonCfg.BeaconPeriod);
1444
1445        }
1446}
1447
1448
1449VOID RT2870_BssBeaconInit(
1450        IN RTMP_ADAPTER *pAd)
1451{
1452        BEACON_SYNC_STRUCT      *pBeaconSync;
1453        int i;
1454
1455        NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(BEACON_SYNC_STRUCT), MEM_ALLOC_FLAG);
1456        if (pAd->CommonCfg.pBeaconSync)
1457        {
1458                pBeaconSync = pAd->CommonCfg.pBeaconSync;
1459                NdisZeroMemory(pBeaconSync, sizeof(BEACON_SYNC_STRUCT));
1460                for(i=0; i < HW_BEACON_MAX_COUNT; i++)
1461                {
1462                        NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1463                        pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1464                        pBeaconSync->TimIELocationInBeacon[i] = 0;
1465                        NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1466                }
1467                pBeaconSync->BeaconBitMap = 0;
1468
1469                //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE);
1470                pBeaconSync->EnableBeacon = TRUE;
1471        }
1472}
1473
1474
1475VOID RT2870_BssBeaconExit(
1476        IN RTMP_ADAPTER *pAd)
1477{
1478        BEACON_SYNC_STRUCT      *pBeaconSync;
1479        BOOLEAN Cancelled = TRUE;
1480        int i;
1481
1482        if (pAd->CommonCfg.pBeaconSync)
1483        {
1484                pBeaconSync = pAd->CommonCfg.pBeaconSync;
1485                pBeaconSync->EnableBeacon = FALSE;
1486                RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1487                pBeaconSync->BeaconBitMap = 0;
1488
1489                for(i=0; i<HW_BEACON_MAX_COUNT; i++)
1490                {
1491                        NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1492                        pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1493                        pBeaconSync->TimIELocationInBeacon[i] = 0;
1494                        NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1495                }
1496
1497                NdisFreeMemory(pAd->CommonCfg.pBeaconSync, HW_BEACON_OFFSET * HW_BEACON_MAX_COUNT, 0);
1498                pAd->CommonCfg.pBeaconSync = NULL;
1499        }
1500}
1501
1502VOID BeaconUpdateExec(
1503    IN PVOID SystemSpecific1,
1504    IN PVOID FunctionContext,
1505    IN PVOID SystemSpecific2,
1506    IN PVOID SystemSpecific3)
1507{
1508        PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER)FunctionContext;
1509        LARGE_INTEGER   tsfTime_a;//, tsfTime_b, deltaTime_exp, deltaTime_ab;
1510        UINT32                  delta, remain, remain_low, remain_high;
1511//      BOOLEAN                 positive;
1512
1513        ReSyncBeaconTime(pAd);
1514
1515
1516
1517        RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart);
1518        RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart);
1519
1520
1521        //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp);
1522        remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart;
1523        remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10);
1524        remain = (remain_high + remain_low)%(pAd->CommonCfg.BeaconPeriod << 10);
1525        delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain;
1526
1527        pAd->CommonCfg.BeaconUpdateTimer.TimerValue = (delta >> 10) + 10;
1528
1529}
1530
1531