2870_main_dev.c
来自「ralink最新rt3070 usb wifi 无线网卡驱动程序」· C语言 代码 · 共 1,628 行 · 第 1/3 页
C
1,628 行
/* ************************************************************************* * 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_SUPPORTMODULE_LICENSE("GPL");#ifdef MODULE_VERSIONMODULE_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 fileextern 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. *///static int mlme_kill = 0; // Mlme kernel thread//static int RTUSBCmd_kill = 0; // Command kernel thread//static int TimerFunc_kill = 0; // TimerQ kernel thread//static wait_queue_head_t timerWaitQ;//static wait_queue_t waitQ;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_PMstatic 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_PMVOID 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 moduleINT __init rtusb_init(void){ printk("rtusb init --->\n"); return usb_register(&rtusb_driver);}// Deinit driver moduleVOID __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 pointerReturn Value: 0 close the threadNote:========================================================================*/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 = -1; complete_and_exit (&pAd->mlmeComplete, 0); return 0;}/*========================================================================Routine Description: USB command kernel thread.Arguments: *Context the pAd, driver control block pointerReturn Value: 0 close the threadNote:========================================================================*/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 = -1; 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 = -1; 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 = pAd->TimerQ.pQTail; if (pAd->TimerQ.pQTail != NULL) pQTail->pNext = pQNode; pAd->TimerQ.pQTail = pQNode; if (pAd->TimerQ.pQHead == NULL) pAd->TimerQ.pQHead = pQNode; } RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); if (pQNode) up(&pAd->RTUSBTimer_semaphore); //wake_up(&timerWaitQ); } else { RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); } return pQNode;}BOOLEAN RT2870_TimerQ_Remove( IN RTMP_ADAPTER *pAd, IN RALINK_TIMER_STRUCT *pTimer){ RT2870_TIMER_ENTRY *pNode, *pPrev = NULL; unsigned long irqFlags; RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags); if (pAd->TimerQ.status >= RT2870_THREAD_INITED) { pNode = pAd->TimerQ.pQHead; while (pNode) { if (pNode->pRaTimer == pTimer) break; pPrev = pNode; pNode = pNode->pNext; } // Now move it to freeList queue.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?