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