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 + -
显示快捷键?