aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2008-12-17 17:04:23 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2009-01-06 13:52:35 -0800
commitc55519ff75224222f4668c92ae3733059269f575 (patch)
treecf7871a28ee226e274763608f215c171d54cd33e /drivers/staging
parent6e16aee60c815dac2d6c3b875769a79d09df6f91 (diff)
Staging: add rt2870 wireless driver
This is the Ralink RT2870 driver from the company that does horrible things like reading a config file from /etc. However, the driver that is currently under development from the wireless development community is not working at all yet, so distros and users are using this version instead (quite common hardware on a lot of netbook machines). So here is this driver, for now, until the wireless developers get a "clean" version into the main tree, or until this version is cleaned up sufficiently to move out of the staging tree. Ported to the Linux build system and cleaned up a bit already by me. Cc: Linux wireless <linux-wireless@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/rt2870/2870_main_dev.c1612
-rw-r--r--drivers/staging/rt2870/Kconfig6
-rw-r--r--drivers/staging/rt2870/Makefile47
-rw-r--r--drivers/staging/rt2870/TODO10
-rw-r--r--drivers/staging/rt2870/aironet.h210
-rw-r--r--drivers/staging/rt2870/ap.h562
-rw-r--r--drivers/staging/rt2870/chlist.h1296
-rw-r--r--drivers/staging/rt2870/common/2870_rtmp_init.c1778
-rw-r--r--drivers/staging/rt2870/common/action.c1046
-rw-r--r--drivers/staging/rt2870/common/action.h68
-rw-r--r--drivers/staging/rt2870/common/ba_action.c1798
-rw-r--r--drivers/staging/rt2870/common/cmm_data.c2734
-rw-r--r--drivers/staging/rt2870/common/cmm_data_2870.c963
-rw-r--r--drivers/staging/rt2870/common/cmm_info.c3712
-rw-r--r--drivers/staging/rt2870/common/cmm_sanity.c1663
-rw-r--r--drivers/staging/rt2870/common/cmm_sync.c711
-rw-r--r--drivers/staging/rt2870/common/cmm_wpa.c1654
-rw-r--r--drivers/staging/rt2870/common/dfs.c453
-rw-r--r--drivers/staging/rt2870/common/eeprom.c254
-rw-r--r--drivers/staging/rt2870/common/firmware.h558
-rw-r--r--drivers/staging/rt2870/common/md5.c1427
-rw-r--r--drivers/staging/rt2870/common/mlme.c8609
-rw-r--r--drivers/staging/rt2870/common/netif_block.c144
-rw-r--r--drivers/staging/rt2870/common/rtmp_init.c4132
-rw-r--r--drivers/staging/rt2870/common/rtmp_tkip.c1613
-rw-r--r--drivers/staging/rt2870/common/rtmp_wep.c508
-rw-r--r--drivers/staging/rt2870/common/rtusb_bulk.c1981
-rw-r--r--drivers/staging/rt2870/common/rtusb_data.c229
-rw-r--r--drivers/staging/rt2870/common/rtusb_io.c2006
-rw-r--r--drivers/staging/rt2870/common/spectrum.c1876
-rw-r--r--drivers/staging/rt2870/dfs.h100
-rw-r--r--drivers/staging/rt2870/leap.h215
-rw-r--r--drivers/staging/rt2870/link_list.h134
-rw-r--r--drivers/staging/rt2870/md4.h42
-rw-r--r--drivers/staging/rt2870/md5.h107
-rw-r--r--drivers/staging/rt2870/mlme.h1471
-rw-r--r--drivers/staging/rt2870/netif_block.h58
-rw-r--r--drivers/staging/rt2870/oid.h1091
-rw-r--r--drivers/staging/rt2870/rt2870.h761
-rw-r--r--drivers/staging/rt2870/rt28xx.h2689
-rw-r--r--drivers/staging/rt2870/rt_ate.c6452
-rw-r--r--drivers/staging/rt2870/rt_ate.h315
-rw-r--r--drivers/staging/rt2870/rt_config.h104
-rw-r--r--drivers/staging/rt2870/rt_linux.c1095
-rw-r--r--drivers/staging/rt2870/rt_linux.h908
-rw-r--r--drivers/staging/rt2870/rt_main_dev.c1863
-rw-r--r--drivers/staging/rt2870/rt_profile.c2016
-rw-r--r--drivers/staging/rt2870/rtmp.h7586
-rw-r--r--drivers/staging/rt2870/rtmp_ckipmic.h113
-rw-r--r--drivers/staging/rt2870/rtmp_def.h1622
-rw-r--r--drivers/staging/rt2870/rtmp_type.h94
-rw-r--r--drivers/staging/rt2870/spectrum.h322
-rw-r--r--drivers/staging/rt2870/spectrum_def.h95
-rw-r--r--drivers/staging/rt2870/sta/aironet.c1312
-rw-r--r--drivers/staging/rt2870/sta/assoc.c2039
-rw-r--r--drivers/staging/rt2870/sta/auth.c474
-rw-r--r--drivers/staging/rt2870/sta/auth_rsp.c166
-rw-r--r--drivers/staging/rt2870/sta/connect.c2822
-rw-r--r--drivers/staging/rt2870/sta/dls.c2210
-rw-r--r--drivers/staging/rt2870/sta/rtmp_data.c2619
-rw-r--r--drivers/staging/rt2870/sta/sanity.c420
-rw-r--r--drivers/staging/rt2870/sta/sync.c1753
-rw-r--r--drivers/staging/rt2870/sta/wpa.c2107
-rw-r--r--drivers/staging/rt2870/sta_ioctl.c7068
-rw-r--r--drivers/staging/rt2870/sta_ioctl.c.patch18
-rw-r--r--drivers/staging/rt2870/tmp607037
-rw-r--r--drivers/staging/rt2870/tmp617037
-rw-r--r--drivers/staging/rt2870/wpa.h357
70 files changed, 110355 insertions, 0 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 9845eab9ebf..e2f57e9b694 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -71,6 +71,8 @@ source "drivers/staging/otus/Kconfig"
source "drivers/staging/rt2860/Kconfig"
+source "drivers/staging/rt2870/Kconfig"
+
source "drivers/staging/benet/Kconfig"
source "drivers/staging/comedi/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 968f333a659..94efc9df5a8 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_POCH) += poch/
obj-$(CONFIG_AGNX) += agnx/
obj-$(CONFIG_OTUS) += otus/
obj-$(CONFIG_RT2860) += rt2860/
+obj-$(CONFIG_RT2870) += rt2870/
obj-$(CONFIG_BENET) += benet/
obj-$(CONFIG_COMEDI) += comedi/
obj-$(CONFIG_ASUS_OLED) += asus_oled/
diff --git a/drivers/staging/rt2870/2870_main_dev.c b/drivers/staging/rt2870/2870_main_dev.c
new file mode 100644
index 00000000000..91da4e2298a
--- /dev/null
+++ b/drivers/staging/rt2870/2870_main_dev.c
@@ -0,0 +1,1612 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rtmp_main.c
+
+ Abstract:
+ main initialization routines
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+ Jan Lee 01-10-2005 modified
+ Sample Jun/01/07 Merge RT2870 and RT2860 drivers.
+*/
+
+#include "rt_config.h"
+
+
+// Following information will be show when you run 'modinfo'
+// *** If you have a solution for the bug in current version of driver, please mail to me.
+// Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. ***
+MODULE_AUTHOR("Paul Lin <paul_lin@ralinktech.com>");
+MODULE_DESCRIPTION("RT2870 Wireless Lan Linux Driver");
+#ifdef CONFIG_STA_SUPPORT
+MODULE_LICENSE("GPL");
+#ifdef MODULE_VERSION
+MODULE_VERSION(STA_DRIVER_VERSION);
+#endif
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef MULTIPLE_CARD_SUPPORT
+// record whether the card in the card list is used in the card file
+extern UINT8 MC_CardUsed[];
+#endif // MULTIPLE_CARD_SUPPORT //
+
+/* Kernel thread and vars, which handles packets that are completed. Only
+ * packets that have a "complete" function are sent here. This way, the
+ * completion is run out of kernel context, and doesn't block the rest of
+ * the stack. */
+
+extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
+ IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
+
+
+/* module table */
+struct usb_device_id rtusb_usb_id[] = RT2870_USB_DEVICES;
+INT const rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id);
+MODULE_DEVICE_TABLE(usb, rtusb_usb_id);
+
+#ifndef PF_NOFREEZE
+#define PF_NOFREEZE 0
+#endif
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+
+/**************************************************************************/
+/**************************************************************************/
+//tested for kernel 2.4 series
+/**************************************************************************/
+/**************************************************************************/
+static void *rtusb_probe(struct usb_device *dev, UINT interface,
+ const struct usb_device_id *id_table);
+static void rtusb_disconnect(struct usb_device *dev, void *ptr);
+
+struct usb_driver rtusb_driver = {
+ name:"rt2870",
+ probe:rtusb_probe,
+ disconnect:rtusb_disconnect,
+ id_table:rtusb_usb_id,
+ };
+
+#else
+
+#ifdef CONFIG_PM
+static int rt2870_suspend(struct usb_interface *intf, pm_message_t state);
+static int rt2870_resume(struct usb_interface *intf);
+#endif // CONFIG_PM //
+
+/**************************************************************************/
+/**************************************************************************/
+//tested for kernel 2.6series
+/**************************************************************************/
+/**************************************************************************/
+static int rtusb_probe (struct usb_interface *intf,
+ const struct usb_device_id *id);
+static void rtusb_disconnect(struct usb_interface *intf);
+
+struct usb_driver rtusb_driver = {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+ .owner = THIS_MODULE,
+#endif
+ .name="rt2870",
+ .probe=rtusb_probe,
+ .disconnect=rtusb_disconnect,
+ .id_table=rtusb_usb_id,
+
+#ifdef CONFIG_PM
+ suspend: rt2870_suspend,
+ resume: rt2870_resume,
+#endif
+ };
+
+#ifdef CONFIG_PM
+
+VOID RT2860RejectPendingPackets(
+ IN PRTMP_ADAPTER pAd)
+{
+ // clear PS packets
+ // clear TxSw packets
+}
+
+static int rt2870_suspend(
+ struct usb_interface *intf,
+ pm_message_t state)
+{
+ struct net_device *net_dev;
+ PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n"));
+ net_dev = pAd->net_dev;
+ netif_device_detach (net_dev);
+
+ pAd->PM_FlgSuspend = 1;
+ if (netif_running(net_dev)) {
+ RTUSBCancelPendingBulkInIRP(pAd);
+ RTUSBCancelPendingBulkOutIRP(pAd);
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n"));
+ return 0;
+}
+
+static int rt2870_resume(
+ struct usb_interface *intf)
+{
+ struct net_device *net_dev;
+ PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n"));
+
+ pAd->PM_FlgSuspend = 0;
+ net_dev = pAd->net_dev;
+ netif_device_attach (net_dev);
+ netif_start_queue(net_dev);
+ netif_carrier_on(net_dev);
+ netif_wake_queue(net_dev);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n"));
+ return 0;
+}
+#endif // CONFIG_PM //
+#endif // LINUX_VERSION_CODE //
+
+
+// Init driver module
+INT __init rtusb_init(void)
+{
+ printk("rtusb init --->\n");
+ return usb_register(&rtusb_driver);
+}
+
+// Deinit driver module
+VOID __exit rtusb_exit(void)
+{
+ usb_deregister(&rtusb_driver);
+ printk("<--- rtusb exit\n");
+}
+
+module_init(rtusb_init);
+module_exit(rtusb_exit);
+
+
+
+
+/*--------------------------------------------------------------------- */
+/* function declarations */
+/*--------------------------------------------------------------------- */
+
+/*
+========================================================================
+Routine Description:
+ MLME kernel thread.
+
+Arguments:
+ *Context the pAd, driver control block pointer
+
+Return Value:
+ 0 close the thread
+
+Note:
+========================================================================
+*/
+INT MlmeThread(
+ IN void *Context)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
+ POS_COOKIE pObj;
+ int status;
+
+ pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ rtmp_os_thread_init("rt2870MlmeThread", (PVOID)&(pAd->mlmeComplete));
+
+ while (pAd->mlme_kill == 0)
+ {
+ /* lock the device pointers */
+ //down(&(pAd->mlme_semaphore));
+ status = down_interruptible(&(pAd->mlme_semaphore));
+
+ /* lock the device pointers , need to check if required*/
+ //down(&(pAd->usbdev_semaphore));
+
+ if (!pAd->PM_FlgSuspend)
+ MlmeHandler(pAd);
+
+ /* unlock the device pointers */
+ //up(&(pAd->usbdev_semaphore));
+ if (status != 0)
+ {
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+ break;
+ }
+ }
+
+ /* notify the exit routine that we're actually exiting now
+ *
+ * complete()/wait_for_completion() is similar to up()/down(),
+ * except that complete() is safe in the case where the structure
+ * is getting deleted in a parallel mode of execution (i.e. just
+ * after the down() -- that's necessary for the thread-shutdown
+ * case.
+ *
+ * complete_and_exit() goes even further than this -- it is safe in
+ * the case that the thread of the caller is going away (not just
+ * the structure) -- this is necessary for the module-remove case.
+ * This is important in preemption kernels, which transfer the flow
+ * of execution immediately upon a complete().
+ */
+ DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__));
+
+ pObj->MLMEThr_pid = THREAD_PID_INIT_VALUE;
+
+ complete_and_exit (&pAd->mlmeComplete, 0);
+ return 0;
+
+}
+
+
+/*
+========================================================================
+Routine Description:
+ USB command kernel thread.
+
+Arguments:
+ *Context the pAd, driver control block pointer
+
+Return Value:
+ 0 close the thread
+
+Note:
+========================================================================
+*/
+INT RTUSBCmdThread(
+ IN void * Context)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
+ POS_COOKIE pObj;
+ int status;
+
+ pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ rtmp_os_thread_init("rt2870CmdThread", (PVOID)&(pAd->CmdQComplete));
+
+ NdisAcquireSpinLock(&pAd->CmdQLock);
+ pAd->CmdQ.CmdQState = RT2870_THREAD_RUNNING;
+ NdisReleaseSpinLock(&pAd->CmdQLock);
+
+ while (pAd->CmdQ.CmdQState == RT2870_THREAD_RUNNING)
+ {
+ /* lock the device pointers */
+ //down(&(pAd->RTUSBCmd_semaphore));
+ status = down_interruptible(&(pAd->RTUSBCmd_semaphore));
+
+ if (pAd->CmdQ.CmdQState == RT2870_THREAD_STOPED)
+ break;
+
+ if (status != 0)
+ {
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+ break;
+ }
+ /* lock the device pointers , need to check if required*/
+ //down(&(pAd->usbdev_semaphore));
+
+ if (!pAd->PM_FlgSuspend)
+ CMDHandler(pAd);
+
+ /* unlock the device pointers */
+ //up(&(pAd->usbdev_semaphore));
+ }
+
+ if (!pAd->PM_FlgSuspend)
+ { // Clear the CmdQElements.
+ CmdQElmt *pCmdQElmt = NULL;
+
+ NdisAcquireSpinLock(&pAd->CmdQLock);
+ pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
+ while(pAd->CmdQ.size)
+ {
+ RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt);
+ if (pCmdQElmt)
+ {
+ if (pCmdQElmt->CmdFromNdis == TRUE)
+ {
+ if (pCmdQElmt->buffer != NULL)
+ NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
+
+ NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
+ }
+ else
+ {
+ if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0))
+ NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
+ {
+ NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
+ }
+ }
+ }
+ }
+
+ NdisReleaseSpinLock(&pAd->CmdQLock);
+ }
+ /* notify the exit routine that we're actually exiting now
+ *
+ * complete()/wait_for_completion() is similar to up()/down(),
+ * except that complete() is safe in the case where the structure
+ * is getting deleted in a parallel mode of execution (i.e. just
+ * after the down() -- that's necessary for the thread-shutdown
+ * case.
+ *
+ * complete_and_exit() goes even further than this -- it is safe in
+ * the case that the thread of the caller is going away (not just
+ * the structure) -- this is necessary for the module-remove case.
+ * This is important in preemption kernels, which transfer the flow
+ * of execution immediately upon a complete().
+ */
+ DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n"));
+
+ pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE;
+
+ complete_and_exit (&pAd->CmdQComplete, 0);
+ return 0;
+
+}
+
+
+static void RT2870_TimerQ_Handle(RTMP_ADAPTER *pAd)
+{
+ int status;
+ RALINK_TIMER_STRUCT *pTimer;
+ RT2870_TIMER_ENTRY *pEntry;
+ unsigned long irqFlag;
+
+ while(!pAd->TimerFunc_kill)
+ {
+// printk("waiting for event!\n");
+ pTimer = NULL;
+
+ status = down_interruptible(&(pAd->RTUSBTimer_semaphore));
+
+ if (pAd->TimerQ.status == RT2870_THREAD_STOPED)
+ break;
+
+ // event happened.
+ while(pAd->TimerQ.pQHead)
+ {
+ RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlag);
+ pEntry = pAd->TimerQ.pQHead;
+ if (pEntry)
+ {
+ pTimer = pEntry->pRaTimer;
+
+ // update pQHead
+ pAd->TimerQ.pQHead = pEntry->pNext;
+ if (pEntry == pAd->TimerQ.pQTail)
+ pAd->TimerQ.pQTail = NULL;
+
+ // return this queue entry to timerQFreeList.
+ pEntry->pNext = pAd->TimerQ.pQPollFreeList;
+ pAd->TimerQ.pQPollFreeList = pEntry;
+ }
+ RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlag);
+
+ if (pTimer)
+ {
+ if (pTimer->handle != NULL)
+ if (!pAd->PM_FlgSuspend)
+ pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer);
+ if ((pTimer->Repeat) && (pTimer->State == FALSE))
+ RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue);
+ }
+ }
+
+ if (status != 0)
+ {
+ pAd->TimerQ.status = RT2870_THREAD_STOPED;
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+ break;
+ }
+ }
+}
+
+
+INT TimerQThread(
+ IN OUT PVOID Context)
+{
+ PRTMP_ADAPTER pAd;
+ POS_COOKIE pObj;
+
+ pAd = (PRTMP_ADAPTER)Context;
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ rtmp_os_thread_init("rt2870TimerQHandle", (PVOID)&(pAd->TimerQComplete));
+
+ RT2870_TimerQ_Handle(pAd);
+
+ /* notify the exit routine that we're actually exiting now
+ *
+ * complete()/wait_for_completion() is similar to up()/down(),
+ * except that complete() is safe in the case where the structure
+ * is getting deleted in a parallel mode of execution (i.e. just
+ * after the down() -- that's necessary for the thread-shutdown
+ * case.
+ *
+ * complete_and_exit() goes even further than this -- it is safe in
+ * the case that the thread of the caller is going away (not just
+ * the structure) -- this is necessary for the module-remove case.
+ * This is important in preemption kernels, which transfer the flow
+ * of execution immediately upon a complete().
+ */
+ DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__));
+
+ pObj->TimerQThr_pid = THREAD_PID_INIT_VALUE;
+
+ complete_and_exit(&pAd->TimerQComplete, 0);
+ return 0;
+
+}
+
+
+RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert(
+ IN RTMP_ADAPTER *pAd,
+ IN RALINK_TIMER_STRUCT *pTimer)
+{
+ RT2870_TIMER_ENTRY *pQNode = NULL, *pQTail;
+ unsigned long irqFlags;
+
+
+ RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
+ if (pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT)
+ {
+ if(pAd->TimerQ.pQPollFreeList)
+ {
+ pQNode = pAd->TimerQ.pQPollFreeList;
+ pAd->TimerQ.pQPollFreeList = pQNode->pNext;
+
+ pQNode->pRaTimer = pTimer;
+ pQNode->pNext = NULL;
+
+ pQTail =