📄 rtusb_bulk.c
字号:
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2006, 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
Paul Lin 06-25-2004 created
*/
#include "rt_config.h"
void RTusb_fill_bulk_urb (struct urb *pUrb,
struct usb_device *pUsb_Dev,
unsigned int bulkpipe,
void *pTransferBuf,
int BufSize,
usb_complete_t Complete,
void *pContext)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
usb_fill_bulk_urb(pUrb, pUsb_Dev, bulkpipe, pTransferBuf, BufSize, Complete, pContext);
#else
FILL_BULK_URB(pUrb, pUsb_Dev, bulkpipe, pTransferBuf, BufSize, Complete, pContext);
#endif
}
// ************************ Completion Func ************************ //
VOID RTUSBBulkOutDataPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs)
{
PTX_CONTEXT pTxContext;
PRTMP_ADAPTER pAd;
NTSTATUS status;
UCHAR BulkOutPipeId;
ULONG IrqFlags;
DBGPRINT_RAW(RT_DEBUG_INFO, "--->RTUSBBulkOutDataPacketComplete\n");
pTxContext= (PTX_CONTEXT)pUrb->context;
pAd = pTxContext->pAd;
status = pUrb->status;
// Store BulkOut PipeId
BulkOutPipeId = pTxContext->BulkOutPipeId;
pAd->BulkOutDataOneSecCount++;
if (status == USB_ST_NOERROR)
{
DBGPRINT_RAW(RT_DEBUG_INFO, "BulkOutDataPacketComplete %d (STATUS_SUCCESS)\n", BulkOutPipeId);
if (pTxContext->LastOne == TRUE)
{
pAd->Counters.GoodTransmits++;
FREE_TX_RING(pAd, BulkOutPipeId, pTxContext);
pAd->TxRingTotalNumber[BulkOutPipeId]--; // sync. to TxCount
if (pAd->SendTxWaitQueue[BulkOutPipeId].Number > 0)
{
RTMPDeQueuePacket(pAd, BulkOutPipeId);
}
}
else
{
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)))
{
FREE_TX_RING(pAd, BulkOutPipeId, pTxContext);
pAd->TxRingTotalNumber[BulkOutPipeId]--; // sync. to TxCount
// Indicate next one is frag data which has highest priority
RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId));
}
else
{
while (pTxContext->LastOne != TRUE)
{
FREE_TX_RING(pAd, BulkOutPipeId, pTxContext);
pAd->TxRingTotalNumber[BulkOutPipeId]--; // sync. to TxCount
pTxContext = &(pAd->TxContext[BulkOutPipeId][pAd->NextBulkOutIndex[BulkOutPipeId]]);
}
FREE_TX_RING(pAd, BulkOutPipeId, pTxContext);
pAd->TxRingTotalNumber[BulkOutPipeId]--; // sync. to TxCount
}
}
}
#if 1 // STATUS_OTHER
else
{
DBGPRINT_RAW(RT_DEBUG_ERROR, "BulkOutDataPacketComplete %d (STATUS_OTHER)\n", BulkOutPipeId);
while (pTxContext->LastOne != TRUE)
{
FREE_TX_RING(pAd, BulkOutPipeId, pTxContext);
pAd->TxRingTotalNumber[BulkOutPipeId]--; // sync. to TxCount
pTxContext = &(pAd->TxContext[BulkOutPipeId][pAd->NextBulkOutIndex[BulkOutPipeId]]);
}
FREE_TX_RING(pAd, BulkOutPipeId, pTxContext);
pAd->TxRingTotalNumber[BulkOutPipeId]--; // sync. to TxCount
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)))
{
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
RTUSBEnqueueInternalCmd(pAd, RT_OID_USB_RESET_BULK_OUT);
}
}
#endif
pTxContext = &(pAd->TxContext[BulkOutPipeId][pAd->NextBulkOutIndex[BulkOutPipeId]]);
//
// 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.
//
if ((pTxContext->bWaitingBulkOut == TRUE) && !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));
}
NdisAcquireSpinLock(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
pAd->BulkOutPending[BulkOutPipeId] = FALSE;
NdisReleaseSpinLock(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
// Always call Bulk routine, even reset bulk.
// The protectioon of rest bulk should be in BulkOut routine
RTUSBKickBulkOut(pAd);
}
// NULL frame use BulkOutPipeId = 0
VOID RTUSBBulkOutNullFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs)
{
PRTMP_ADAPTER pAd;
PTX_CONTEXT pNullContext;
NTSTATUS status;
ULONG IrqFlags;
pNullContext= (PTX_CONTEXT)pUrb->context;
pAd = pNullContext->pAd;
DBGPRINT_RAW(RT_DEBUG_INFO, "--->RTUSBBulkOutNullFrameComplete\n");
// Reset Null frame context flags
pNullContext->IRPPending = FALSE;
pNullContext->InUse = FALSE;
status = pUrb->status;
if (status == USB_ST_NOERROR)
{
// Don't worry about the queue is empty or not, this function will check itself
RTMPDeQueuePacket(pAd, 0);
}
#if 1 // STATUS_OTHER
else
{
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\n");
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
RTUSBEnqueueInternalCmd(pAd, RT_OID_USB_RESET_BULK_OUT);
}
}
#endif
NdisAcquireSpinLock(&pAd->BulkOutLock[0], IrqFlags);
pAd->BulkOutPending[0] = FALSE;
NdisReleaseSpinLock(&pAd->BulkOutLock[0], IrqFlags);
// Always call Bulk routine, even reset bulk.
// The protectioon of rest bulk should be in BulkOut routine
RTUSBKickBulkOut(pAd);
DBGPRINT_RAW(RT_DEBUG_INFO, "<---RTUSBBulkOutNullFrameComplete\n");
}
// RTS frame use BulkOutPipeId = PipeID
VOID RTUSBBulkOutRTSFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs)
{
PRTMP_ADAPTER pAd;
PTX_CONTEXT pRTSContext;
NTSTATUS status;
ULONG IrqFlags;
pRTSContext= (PTX_CONTEXT)pUrb->context;
pAd = pRTSContext->pAd;
DBGPRINT_RAW(RT_DEBUG_INFO, "--->RTUSBBulkOutRTSFrameComplete\n");
// Reset RTS frame context flags
pRTSContext->IRPPending = FALSE;
pRTSContext->InUse = FALSE;
status = pUrb->status;
if (status == USB_ST_NOERROR)
{
// Don't worry about the queue is empty or not, this function will check itself
RTMPDeQueuePacket(pAd, pRTSContext->BulkOutPipeId);
}
#if 1 // STATUS_OTHER
else
{
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);
RTUSBEnqueueInternalCmd(pAd, RT_OID_USB_RESET_BULK_OUT);
}
}
#endif
NdisAcquireSpinLock(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId], IrqFlags);
pAd->BulkOutPending[pRTSContext->BulkOutPipeId] = FALSE;
NdisReleaseSpinLock(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId], IrqFlags);
// Always call Bulk routine, even reset bulk.
// The protectioon of rest bulk should be in BulkOut routine
RTUSBKickBulkOut(pAd);
DBGPRINT_RAW(RT_DEBUG_INFO, "<---RTUSBBulkOutRTSFrameComplete\n");
}
// MLME use BulkOutPipeId = 0
VOID RTUSBBulkOutMLMEPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs)
{
PTX_CONTEXT pMLMEContext;
PRTMP_ADAPTER pAd;
NTSTATUS status;
ULONG IrqFlags;
pMLMEContext= (PTX_CONTEXT)pUrb->context;
pAd = pMLMEContext->pAd;
status = pUrb->status;
pAd->PrioRingTxCnt--;
if (pAd->PrioRingTxCnt < 0)
pAd->PrioRingTxCnt = 0;
pAd->PrioRingFirstIndex++;
if (pAd->PrioRingFirstIndex >= PRIO_RING_SIZE)
{
pAd->PrioRingFirstIndex = 0;
}
DBGPRINT(RT_DEBUG_INFO, "RTUSBBulkOutMLMEPacketComplete::PrioRingFirstIndex = %d, PrioRingTxCnt = %d, PopMgmtIndex = %d, PushMgmtIndex = %d, NextMLMEIndex = %d\n",
pAd->PrioRingFirstIndex,
pAd->PrioRingTxCnt, pAd->PopMgmtIndex, pAd->PushMgmtIndex, pAd->NextMLMEIndex);
DBGPRINT_RAW(RT_DEBUG_INFO, "--->RTUSBBulkOutMLMEPacketComplete\n");
// Reset MLME context flags
pMLMEContext->IRPPending = FALSE;
pMLMEContext->InUse = FALSE;
if (status == USB_ST_NOERROR)
{
// Don't worry about the queue is empty or not, this function will check itself
RTUSBDequeueMLMEPacket(pAd);
}
#if 1 // STATUS_OTHER
else
{
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 MLME Failed\n");
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
RTUSBEnqueueInternalCmd(pAd, RT_OID_USB_RESET_BULK_OUT);
}
}
#endif
NdisAcquireSpinLock(&pAd->BulkOutLock[0], IrqFlags);
pAd->BulkOutPending[0] = FALSE;
NdisReleaseSpinLock(&pAd->BulkOutLock[0], IrqFlags);
// Always call Bulk routine, even reset bulk.
// The protectioon of rest bulk should be in BulkOut routine
RTUSBKickBulkOut(pAd);
DBGPRINT_RAW(RT_DEBUG_INFO, "<---RTUSBBulkOutMLMEPacketComplete\n");
}
// PS-Poll frame use BulkOutPipeId = 0
VOID RTUSBBulkOutPsPollComplete(purbb_t pUrb,struct pt_regs *pt_regs)
{
PRTMP_ADAPTER pAd;
PTX_CONTEXT pPsPollContext;
NTSTATUS status;
ULONG IrqFlags;
pPsPollContext= (PTX_CONTEXT)pUrb->context;
pAd = pPsPollContext->pAd;
DBGPRINT_RAW(RT_DEBUG_INFO, "--->RTUSBBulkOutPsPollComplete\n");
// Reset PsPoll context flags
pPsPollContext->IRPPending = FALSE;
pPsPollContext->InUse = FALSE;
status = pUrb->status;
if (status == USB_ST_NOERROR)
{
// Don't worry about the queue is empty or not, this function will check itself
RTMPDeQueuePacket(pAd, 0);
}
#if 1 // STATUS_OTHER
else
{
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);
RTUSBEnqueueInternalCmd(pAd, RT_OID_USB_RESET_BULK_OUT);
}
}
#endif
NdisAcquireSpinLock(&pAd->BulkOutLock[0], IrqFlags);
pAd->BulkOutPending[0] = FALSE;
NdisReleaseSpinLock(&pAd->BulkOutLock[0], IrqFlags);
// Always call Bulk routine, even reset bulk.
// The protectioon of rest bulk should be in BulkOut routine
RTUSBKickBulkOut(pAd);
DBGPRINT_RAW(RT_DEBUG_INFO, "<---RTUSBBulkOutPsPollComplete\n");
}
/*
========================================================================
Routine Description:
This routine process Rx Irp and call rx complete function.
Arguments:
DeviceObject Pointer to the device object for next lower
device. DeviceObject passed in here belongs to
the next lower driver in the stack because we
were invoked via IoCallDriver in USB_RxPacket
AND it is not OUR device object
Irp Ptr to completed IRP
Context Ptr to our Adapter object (context specified
in IoSetCompletionRoutine
Return Value:
Always returns STATUS_MORE_PROCESSING_REQUIRED
Note:
Always returns STATUS_MORE_PROCESSING_REQUIRED
========================================================================
*/
VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs)
{
PRX_CONTEXT pRxContext;
PRTMP_ADAPTER pAd;
NTSTATUS status;
pRxContext= (PRX_CONTEXT)pUrb->context;
pAd = pRxContext->pAd;
//
// We have a number of cases:
// 1) The USB read timed out and we received no data.
// 2) The USB read timed out and we received some data.
// 3) The USB read was successful and fully filled our irp buffer.
// 4) The irp was cancelled.
// 5) Some other failure from the USB device object.
//
//
// Free the IRP and its mdl because they were alloced by us
//
#if 0
if ( (atomread = (atomic_read(&pRxContext->IrpLock))) == IRPLOCK_CANCE_START)
{
atomic_dec(&pAd->PendingRx);
atomic_set(&pRxContext->IrpLock, IRPLOCK_CANCE_COMPLETE);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -