2870_main_dev.c

来自「ralink最新rt3070 usb wifi 无线网卡驱动程序」· C语言 代码 · 共 1,628 行 · 第 1/3 页

C
1,628
字号
		if (pNode)		{				if (pNode == pAd->TimerQ.pQHead)				pAd->TimerQ.pQHead = pNode->pNext;			if (pNode == pAd->TimerQ.pQTail)				pAd->TimerQ.pQTail = pPrev;			if (pPrev != NULL)				pPrev->pNext = pNode->pNext;						// return this queue entry to timerQFreeList.			pNode->pNext = pAd->TimerQ.pQPollFreeList;			pAd->TimerQ.pQPollFreeList = pNode;		}	}	RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);				return TRUE;}void RT2870_TimerQ_Exit(RTMP_ADAPTER *pAd){	RT2870_TIMER_ENTRY *pTimerQ;	unsigned long irqFlags;		RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);	while (pAd->TimerQ.pQHead)	{		pTimerQ = pAd->TimerQ.pQHead;		pAd->TimerQ.pQHead = pTimerQ->pNext;		// remove the timeQ	}	pAd->TimerQ.pQPollFreeList = NULL;	os_free_mem(pAd, pAd->TimerQ.pTimerQPoll);	pAd->TimerQ.pQTail = NULL;	pAd->TimerQ.pQHead = NULL;	pAd->TimerQ.status = RT2870_THREAD_STOPED;	RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);	}void RT2870_TimerQ_Init(RTMP_ADAPTER *pAd){	int 	i;	RT2870_TIMER_ENTRY *pQNode, *pEntry;	unsigned long irqFlags;		NdisAllocateSpinLock(&pAd->TimerQLock);	RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);	NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));	//InterlockedExchange(&pAd->TimerQ.count, 0);		/* Initialise the wait q head */	//init_waitqueue_head(&timerWaitQ);	os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RT2870_TIMER_ENTRY) * TIMER_QUEUE_SIZE_MAX);	if (pAd->TimerQ.pTimerQPoll)	{		pEntry = NULL;		pQNode = (RT2870_TIMER_ENTRY *)pAd->TimerQ.pTimerQPoll;		for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)		{			pQNode->pNext = pEntry;			pEntry = pQNode;			pQNode++;		}		pAd->TimerQ.pQPollFreeList = pEntry;		pAd->TimerQ.pQHead = NULL;		pAd->TimerQ.pQTail = NULL;		pAd->TimerQ.status = RT2870_THREAD_INITED;	}	RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);}VOID RT2870_WatchDog(IN RTMP_ADAPTER *pAd){	PHT_TX_CONTEXT		pHTTXContext;	int 					idx;	ULONG				irqFlags;	PURB		   		pUrb;	BOOLEAN				needDumpSeq = FALSE;	UINT32          	MACValue;	idx = 0;	RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);	if ((MACValue & 0xff) !=0 )	{		DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));		RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012);		while((MACValue &0xff) != 0 && (idx++ < 10))		{		        RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);		        NdisMSleep(1);		}		RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);	}//PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)#ifdef CONFIG_STA_SUPPORT	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)	{		idx = 0;		if ((MACValue & 0xff00) !=0 )		{			DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));			RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf4000a);			while((MACValue &0xff00) != 0 && (idx++ < 10))			{				RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);				NdisMSleep(1);			}			RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);		}	}#endif // CONFIG_STA_SUPPORT //		if (pAd->watchDogRxOverFlowCnt >= 2)	{		DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));		if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |									fRTMP_ADAPTER_BULKIN_RESET |									fRTMP_ADAPTER_HALT_IN_PROGRESS |									fRTMP_ADAPTER_NIC_NOT_EXIST))))		{			DBGPRINT(RT_DEBUG_TRACE, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));			RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);			RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0);			needDumpSeq = TRUE;		}		pAd->watchDogRxOverFlowCnt = 0;	}	for (idx = 0; idx < NUM_OF_TX_RING; idx++)	{		pUrb = NULL;				RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags);		if ((pAd->BulkOutPending[idx] == TRUE) && pAd->watchDogTxPendingCnt)		{			pAd->watchDogTxPendingCnt[idx]++;			if ((pAd->watchDogTxPendingCnt[idx] > 2) && 				 (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET)))				)			{				// FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!				pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[idx]);				if (pHTTXContext->IRPPending)				{	// Check TxContext.					pUrb = pHTTXContext->pUrb;				}				else if (idx == MGMTPIPEIDX)				{					PTX_CONTEXT pMLMEContext, pNULLContext, pPsPollContext;										//Check MgmtContext.					pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa);					pPsPollContext = (PTX_CONTEXT)(&pAd->PsPollContext);					pNULLContext = (PTX_CONTEXT)(&pAd->NullContext);										if (pMLMEContext->IRPPending)					{						ASSERT(pMLMEContext->IRPPending);						pUrb = pMLMEContext->pUrb;					}					else if (pNULLContext->IRPPending)					{							ASSERT(pNULLContext->IRPPending);						pUrb = pNULLContext->pUrb;					}					else if (pPsPollContext->IRPPending)					{							ASSERT(pPsPollContext->IRPPending);						pUrb = pPsPollContext->pUrb;					}				}								RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);								DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx));				if (pUrb)				{					DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n"));					// unlink it now					RTUSB_UNLINK_URB(pUrb);					// Sleep 200 microseconds to give cancellation time to work					RTMPusecDelay(200);					needDumpSeq = TRUE;				}				else				{					DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));				}			}			else			{				RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);			}		}		else		{			RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);		}	}#ifdef DOT11_N_SUPPORT	// For Sigma debug, dump the ba_reordering sequence.	if((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0))	{		USHORT				Idx;		PBA_REC_ENTRY		pBAEntry = NULL;		UCHAR				count = 0;		struct reordering_mpdu *mpdu_blk;							Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0];		pBAEntry = &pAd->BATable.BARecEntry[Idx];		if((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL))		{			DBGPRINT(RT_DEBUG_TRACE, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));			NdisAcquireSpinLock(&pBAEntry->RxReRingLock);			mpdu_blk = pBAEntry->list.next;			while (mpdu_blk)			{				DBGPRINT(RT_DEBUG_TRACE, ("\t%d:Seq-%d, bAMSDU-%d!\n", count, mpdu_blk->Sequence, mpdu_blk->bAMSDU));				mpdu_blk = mpdu_blk->next;				count++;			}			DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq));			NdisReleaseSpinLock(&pBAEntry->RxReRingLock);		}	}#endif // DOT11_N_SUPPORT //}/*========================================================================Routine Description:    Release allocated resources.Arguments:    *dev				Point to the PCI or USB device	pAd					driver control block pointerReturn Value:    NoneNote:========================================================================*/static void _rtusb_disconnect(struct usb_device *dev, PRTMP_ADAPTER pAd){	struct net_device	*net_dev = NULL;	DBGPRINT(RT_DEBUG_ERROR, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",				dev->bus->bus_name, dev->devpath));	if (!pAd)	{#ifdef MULTIPLE_CARD_SUPPORT		if ((pAd->MC_RowID >= 0) && (pAd->MC_RowID <= MAX_NUM_OF_MULTIPLE_CARD))			MC_CardUsed[pAd->MC_RowID] = 0; // not clear MAC address#endif // MULTIPLE_CARD_SUPPORT //#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	/* kernel 2.4 series */		while(MOD_IN_USE > 0)		{			MOD_DEC_USE_COUNT;		}#else		usb_put_dev(dev);#endif // LINUX_VERSION_CODE //		printk("rtusb_disconnect: pAd == NULL!\n");		return;	}	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);	// for debug, wait to show some messages to /proc system	udelay(1);		net_dev = pAd->net_dev;	if (pAd->net_dev != NULL)	{		printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev->name);		unregister_netdev (pAd->net_dev);	}	udelay(1);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	/* kernel 2.4 series */#else	flush_scheduled_work();#endif // LINUX_VERSION_CODE //	udelay(1);	// free net_device memory#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	/* kernel 2.4 series */	kfree(net_dev);#else	free_netdev(net_dev);#endif // LINUX_VERSION_CODE //	// free adapter memory	RTMPFreeAdapter(pAd);	// release a use of the usb device structure#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	/* kernel 2.4 series */	while(MOD_IN_USE > 0)	{		MOD_DEC_USE_COUNT;	}#else	usb_put_dev(dev);#endif // LINUX_VERSION_CODE //	udelay(1);	DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n"));}/*========================================================================Routine Description:    Probe RT28XX chipset.Arguments:    *dev				Point to the PCI or USB device	interface				*id_table			Point to the PCI or USB device IDReturn Value:    NoneNote:========================================================================*/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	/* kernel 2.4 series */static void *rtusb_probe(struct usb_device *dev, UINT interface,						const struct usb_device_id *id){	PRTMP_ADAPTER pAd;	rt28xx_probe((void *)dev, (void *)id, interface, &pAd);	return (void *)pAd;}//Disconnect function is called within exit routinestatic void rtusb_disconnect(struct usb_device *dev, void *ptr){	_rtusb_disconnect(dev, ((PRTMP_ADAPTER)ptr));}#else	/* kernel 2.6 series */static int rtusb_probe (struct usb_interface *intf,						const struct usb_device_id *id){		PRTMP_ADAPTER pAd;	return (int)rt28xx_probe((void *)intf, (void *)id, 0, &pAd);}static void rtusb_disconnect(struct usb_interface *intf){	struct usb_device   *dev = interface_to_usbdev(intf);	PRTMP_ADAPTER       pAd;	pAd = usb_get_intfdata(intf);	usb_set_intfdata(intf, NULL);		_rtusb_disconnect(dev, pAd);}#endif // LINUX_VERSION_CODE ///*========================================================================Routine Description:    Close kernel threads.Arguments:	*pAd				the raxx interface data pointerReturn Value:    NONENote:========================================================================*/VOID RT28xxThreadTerminate(	IN RTMP_ADAPTER *pAd){	POS_COOKIE	pObj = (POS_COOKIE) pAd->OS_Cookie;	INT			ret;	// Sleep 50 milliseconds so pending io might finish normally	RTMPusecDelay(50000);	// We want to wait until all pending receives and sends to the	// device object. We cancel any	// irps. Wait until sends and receives have stopped.	RTUSBCancelPendingIRPs(pAd);	// Terminate Threads	if (pObj->MLMEThr_pid >= 0) 	{		printk("Terminate the MLMEThr_pid=%d!\n", pObj->MLMEThr_pid);		mb();		pAd->mlme_kill = 1;		//RT28XX_MLME_HANDLER(pAd);		mb();		ret = kill_proc (pObj->MLMEThr_pid, SIGTERM, 1);		if (ret) 		{			printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n",					pAd->net_dev->name, pObj->MLMEThr_pid, ret);		} 		else		{			//wait_for_completion (&pAd->notify);			wait_for_completion (&pAd->mlmeComplete);			pObj->MLMEThr_pid = -1;		}	}	if (pObj->RTUSBCmdThr_pid >= 0) 	{		printk("Terminate the RTUSBCmdThr_pid=%d!\n", pObj->RTUSBCmdThr_pid);		mb();		NdisAcquireSpinLock(&pAd->CmdQLock);		pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;		NdisReleaseSpinLock(&pAd->CmdQLock);		mb();		//RTUSBCMDUp(pAd);		ret = kill_proc(pObj->RTUSBCmdThr_pid, SIGTERM, 1);		if (ret) 		{			printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",					pAd->net_dev->name, pObj->RTUSBCmdThr_pid, ret);		}		else		{			//wait_for_completion (&pAd->notify);			wait_for_completion (&pAd->CmdQComplete);			pObj->RTUSBCmdThr_pid = -1;		}	}	if (pObj->TimerQThr_pid >= 0) 	{		POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;		printk("Terminate the TimerQThr_pid=%d!\n", pObj->TimerQThr_pid);		mb();		pAd->TimerFunc_kill = 1;		mb();		ret = kill_proc(pObj->TimerQThr_pid, SIGTERM, 1);		if (ret)		{			printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n", 					pAd->net_dev->name, pObj->TimerQThr_pid, ret);		}		else 		{			printk("wait_for_completion TimerQThr\n");			wait_for_completion(&pAd->TimerQComplete);			pObj->TimerQThr_pid = -1;		}	}	// Kill tasklets	pAd->mlme_kill = 0;	pAd->CmdQ.CmdQState = RT2870_THREAD_UNKNOWN;	pAd->TimerFunc_kill = 0;}void kill_thread_task(IN PRTMP_ADAPTER pAd){	POS_COOKIE pObj;	pObj = (POS_COOKIE) pAd->OS_Cookie;	tasklet_kill(&pObj->rx_done_task);	tasklet_kill(&pObj->mgmt_dma_done_task);	tasklet_kill(&pObj->ac0_dma_done_task);	tasklet_kill(&pObj->ac1_dma_done_task);	tasklet_kill(&pObj->ac2_dma_done_task);	tasklet_kill(&pObj->ac3_dma_done_task);	tasklet_kill(&pObj->hcca_dma_done_task);	tasklet_kill(&pObj->tbtt_task);}/*========================================================================Routine Description:    Check the chipset vendor/product ID.Arguments:    _dev_p				Point to the PCI or USB deviceReturn Value:    TRUE				Check ok	FALSE				Check failNote:========================================================================*/BOOLEAN RT28XXChipsetCheck(	IN void *_dev_p){#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	/* kernel 2.4 series */	struct usb_device *dev_p = (struct usb_device *)_dev_p;#else	struct usb_interface *intf = (struct usb_interface *)_dev_p;	struct usb_device *dev_p = interface_to_usbdev(intf);#endif // LINUX_VERSION_CODE //	UINT32 i;	for(i=0; i<rtusb_usb_id_len; i++)	{		if (dev_p->descriptor.idVendor == rtusb_usb_id[i].idVendor &&			dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct)		{			printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",					dev_p->descriptor.idVendor, dev_p->descriptor.idProduct);			break;		}	}	if (i == rtusb_usb_id_len) 	{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?