📄 rt_usb.c
字号:
/* ************************************************************************* * 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: rtusb_bulk.c Abstract: Revision History: Who When What -------- ---------- ---------------------------------------------- Name Date Modification logs */#include "rt_config.h"#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) void dump_urb(struct urb* purb){ printk("urb :0x%08lx\n", (unsigned long)purb); printk("\tdev :0x%08lx\n", (unsigned long)purb->dev); printk("\t\tdev->state :0x%d\n", purb->dev->state); printk("\tpipe :0x%08x\n", purb->pipe); printk("\tstatus :%d\n", purb->status); printk("\ttransfer_flags :0x%08x\n", purb->transfer_flags); printk("\ttransfer_buffer :0x%08lx\n", (unsigned long)purb->transfer_buffer); printk("\ttransfer_buffer_length:%d\n", purb->transfer_buffer_length); printk("\tactual_length :%d\n", purb->actual_length); printk("\tsetup_packet :0x%08lx\n", (unsigned long)purb->setup_packet); printk("\tstart_frame :%d\n", purb->start_frame); printk("\tnumber_of_packets :%d\n", purb->number_of_packets); printk("\tinterval :%d\n", purb->interval); printk("\terror_count :%d\n", purb->error_count); printk("\tcontext :0x%08lx\n", (unsigned long)purb->context); printk("\tcomplete :0x%08lx\n\n", (unsigned long)purb->complete);}#elsevoid dump_urb(struct urb* purb){ return;}#endif/*========================================================================Routine Description: Create kernel threads & tasklets.Arguments: *net_dev Pointer to wireless net device interfaceReturn Value: NDIS_STATUS_SUCCESS NDIS_STATUS_FAILURENote:========================================================================*/NDIS_STATUS RtmpMgmtTaskInit( IN RTMP_ADAPTER *pAd){ RTMP_OS_TASK *pTask; NDIS_STATUS status; /* Creat TimerQ Thread, We need init timerQ related structure before create the timer thread. */ RtmpTimerQInit(pAd); pTask = &pAd->timerTask; RtmpOSTaskInit(pTask, "RtmpTimerTask", pAd); status = RtmpOSTaskAttach(pTask, RtmpTimerQThread, pTask); if (status == NDIS_STATUS_FAILURE) { printk (KERN_WARNING "%s: unable to start RtmpTimerQThread\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)); return NDIS_STATUS_FAILURE; } /* Creat MLME Thread */ pTask = &pAd->mlmeTask; RtmpOSTaskInit(pTask, "RtmpMlmeTask", pAd); status = RtmpOSTaskAttach(pTask, MlmeThread, pTask); if (status == NDIS_STATUS_FAILURE) { printk (KERN_WARNING "%s: unable to start MlmeThread\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)); return NDIS_STATUS_FAILURE; } /* Creat Command Thread */ pTask = &pAd->cmdQTask; RtmpOSTaskInit(pTask, "RtmpCmdQTask", pAd); status = RtmpOSTaskAttach(pTask, RTUSBCmdThread, pTask); if (status == NDIS_STATUS_FAILURE) { printk (KERN_WARNING "%s: unable to start RTUSBCmdThread\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)); return NDIS_STATUS_FAILURE; } return NDIS_STATUS_SUCCESS;}/*========================================================================Routine Description: Close kernel threads.Arguments: *pAd the raxx interface data pointerReturn Value: NONENote:========================================================================*/VOID RtmpMgmtTaskExit( IN RTMP_ADAPTER *pAd){ INT ret; RTMP_OS_TASK *pTask; // 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); // We need clear timerQ related structure before exits of the timer thread. RtmpTimerQExit(pAd); /* Terminate Mlme Thread */ pTask = &pAd->mlmeTask; ret = RtmpOSTaskKill(pTask); if (ret == NDIS_STATUS_FAILURE) { DBGPRINT(RT_DEBUG_ERROR, ("%s: kill task(%s) failed!\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev), pTask->taskName)); } /* Terminate cmdQ thread */ pTask = &pAd->cmdQTask;#ifdef KTHREAD_SUPPORT if (pTask->kthread_task)#else CHECK_PID_LEGALITY(pTask->taskPID)#endif { mb(); NdisAcquireSpinLock(&pAd->CmdQLock); pAd->CmdQ.CmdQState = RTMP_TASK_STAT_STOPED; NdisReleaseSpinLock(&pAd->CmdQLock); mb(); //RTUSBCMDUp(pAd); ret = RtmpOSTaskKill(pTask); if (ret == NDIS_STATUS_FAILURE) { DBGPRINT(RT_DEBUG_ERROR, ("%s: kill task(%s) failed!\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev), pTask->taskName)); } pAd->CmdQ.CmdQState = RTMP_TASK_STAT_UNKNOWN; } /* Terminate timer thread */ pTask = &pAd->timerTask; ret = RtmpOSTaskKill(pTask); if (ret == NDIS_STATUS_FAILURE) { DBGPRINT(RT_DEBUG_ERROR, ("%s: kill task(%s) failed!\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev), pTask->taskName)); }}static void rtusb_dataout_complete(unsigned long data){ PRTMP_ADAPTER pAd; purbb_t pUrb; POS_COOKIE pObj; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId; NTSTATUS Status; unsigned long IrqFlags; pUrb = (purbb_t)data; pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; pAd = pHTTXContext->pAd; pObj = (POS_COOKIE) pAd->OS_Cookie; Status = pUrb->status; // Store BulkOut PipeId BulkOutPipeId = pHTTXContext->BulkOutPipeId; pAd->BulkOutDataOneSecCount++; //DBGPRINT(RT_DEBUG_LOUD, ("Done-B(%d):I=0x%lx, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", BulkOutPipeId, in_interrupt(), pHTTXContext->CurWritePosition, // pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; pHTTXContext->IRPPending = FALSE; pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; if (Status == USB_ST_NOERROR) { pAd->BulkOutComplete++; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->Counters8023.GoodTransmits++; //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); FREE_HTTX_RING(pAd, BulkOutPipeId, pHTTXContext); //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); } else // STATUS_OTHER { PUCHAR pBuf; pAd->BulkOutCompleteOther++; pBuf = &pHTTXContext->TransferBuffer->field.WirelessPacket[pHTTXContext->NextBulkOutPosition]; if (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET))) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = BulkOutPipeId; pAd->bulkResetReq[BulkOutPipeId] = pAd->BulkOutReq; } RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkOutDataPacket failed: ReasonCode=%d!\n", Status)); DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>BulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>BulkOut Header:%x %x %x %x %x %x %x %x\n", pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5], pBuf[6], pBuf[7])); //DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOutCompleteCancel=0x%x, BulkOutCompleteOther=0x%x\n", pAd->BulkOutCompleteCancel, pAd->BulkOutCompleteOther)); } // // bInUse = TRUE, means some process are filling TX data, after that must turn on bWaitingBulkOut // bWaitingBulkOut = TRUE, means the TX data are waiting for bulk out. // //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); if ((pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition) && (pHTTXContext->ENextBulkOutPosition != (pHTTXContext->CurWritePosition+8)) && !RTUSB_TEST_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId))) { // Indicate There is data avaliable RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); } //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); // Always call Bulk routine, even reset bulk. // The protection of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd);}static void rtusb_null_frame_done_tasklet(unsigned long data){ PRTMP_ADAPTER pAd; PTX_CONTEXT pNullContext; purbb_t pUrb; NTSTATUS Status; unsigned long irqFlag; pUrb = (purbb_t)data; pNullContext = (PTX_CONTEXT)pUrb->context; pAd = pNullContext->pAd; Status = pUrb->status; // Reset Null frame context flags RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); pNullContext->IRPPending = FALSE; pNullContext->InUse = FALSE; pAd->BulkOutPending[0] = FALSE; pAd->watchDogTxPendingCnt[0] = 0; if (Status == USB_ST_NOERROR) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else // STATUS_OTHER { if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out Null Frame Failed, ReasonCode=%d!\n", Status)); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); } } // Always call Bulk routine, even reset bulk. // The protectioon of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd);}static void rtusb_rts_frame_done_tasklet(unsigned long data){ PRTMP_ADAPTER pAd; PTX_CONTEXT pRTSContext; purbb_t pUrb; NTSTATUS Status; unsigned long irqFlag; pUrb = (purbb_t)data; pRTSContext = (PTX_CONTEXT)pUrb->context; pAd = pRTSContext->pAd; Status = pUrb->status; // Reset RTS frame context flags RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); pRTSContext->IRPPending = FALSE; pRTSContext->InUse = FALSE; if (Status == USB_ST_NOERROR) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else // STATUS_OTHER { if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out RTS Frame Failed\n")); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); } } RTMP_SEM_LOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); pAd->BulkOutPending[pRTSContext->BulkOutPipeId] = FALSE; RTMP_SEM_UNLOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); // Always call Bulk routine, even reset bulk. // The protectioon of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd);}static void rtusb_pspoll_frame_done_tasklet(unsigned long data){ PRTMP_ADAPTER pAd; PTX_CONTEXT pPsPollContext; purbb_t pUrb; NTSTATUS Status; pUrb = (purbb_t)data; pPsPollContext = (PTX_CONTEXT)pUrb->context; pAd = pPsPollContext->pAd; Status = pUrb->status; // Reset PsPoll context flags pPsPollContext->IRPPending = FALSE; pPsPollContext->InUse = FALSE; pAd->watchDogTxPendingCnt[0] = 0; if (Status == USB_ST_NOERROR) { RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else // STATUS_OTHER { if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out PSPoll Failed\n")); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } } RTMP_SEM_LOCK(&pAd->BulkOutLock[0]); pAd->BulkOutPending[0] = FALSE; RTMP_SEM_UNLOCK(&pAd->BulkOutLock[0]); // Always call Bulk routine, even reset bulk. // The protectioon of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd);}/*========================================================================Routine Description:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -