📄 txproc.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
/** @file txproc.c
* @This module has the implementation of TX functions
*
* Copyright (c) Marvell Semiconductor, Inc.
*/
#include "precomp.h"
// compilation error if this file is not included
#ifdef UNDER_CE
#include "pkfuncs.h"
#endif
/******************************************************************************
*
* Name: MrvDrvSend()
*
* Description: NDIS miniport serialized send packet routine
*
* Conditions for Use: Protocol driver will call this routine to pass Tx NDIS_PACKET
*
* Arguments:
* IN NDIS_HANDLE MiniportAdapterContext
* IN PPNDIS_PACKET Packet
* IN UINT Flags
*
* Return Value: NDIS_STATUS_RESOURCES or NDIS_STATUS_PENDING
*
* Notes:
*
*****************************************************************************/
NDIS_STATUS
MrvDrvSend(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet,
IN UINT Flags)
{
PMRVDRV_ADAPTER Adapter;
NDIS_STATUS Status;
PTX_PKT_T pTxPkt;
UINT BufferCount;
UINT TotalPacketLength = 0;
UINT Length;
PNDIS_BUFFER pBuffer;
PVOID pVirtualAddr;
PTxCtrlNode pTxNode;
PUCHAR pHeader = NULL;
#ifdef TX_PERFORMANCE_MEASUREMENT
static ULONG TxRdyEventCalled = 0;
static ULONG TxTickCount = 0;
ULONG ulCurTickCount = GetTickCount();
#endif
// return NDIS_STATUS_SUCCESS;
Status = NDIS_STATUS_SUCCESS;
Adapter = (PMRVDRV_ADAPTER)MiniportAdapterContext;
///RETAILMSG(1, (TEXT("+MrvSend() \r\n")));
if (Adapter->bIsFreeNow == TRUE)
{
///RETAILMSG(1, (TEXT("+MrvSend() NDIS_STATUS_FAILURE 0 \r\n")));
return NDIS_STATUS_FAILURE;
}
#ifdef DEEP_SLEEP
// In Deep Sleep Mode no packet can be sent out
if (Adapter->IsDeepSleepRequired || Adapter->IsDeepSleep)
{
///RETAILMSG(1, (TEXT("+MrvSend() NDIS_STATUS_NO_CABLE \r\n")));
Status = NDIS_STATUS_NO_CABLE;
}
#endif
// Check device removal status
if( Adapter->SurpriseRemoved == TRUE )
{
///RETAILMSG(1, (TEXT("+MrvSend() NDIS_STATUS_FAILURE 1 \r\n")));
return NDIS_STATUS_FAILURE;
}
if ( Adapter->bIsPendingReset == TRUE )
{
//return NDIS_STATUS_RESET_IN_PROGRESS;
///RETAILMSG(1, (TEXT("+MrvSend() NDIS_STATUS_FAILURE 2 \r\n")));
return NDIS_STATUS_FAILURE;
}
if ( Adapter->MediaConnectStatus == NdisMediaStateDisconnected )
{
return NDIS_STATUS_FAILURE;
}
if (Adapter->bIsScanInProgress == TRUE)
{
Adapter->bTXRESOURCES=TRUE;
return NDIS_STATUS_RESOURCES;
}
#ifdef WPA
pTxNode = &Adapter->TxNode;
NdisQueryPacket(
Packet,
NULL,
&BufferCount,
&pBuffer,
&TotalPacketLength );
if (!pBuffer || !BufferCount || !TotalPacketLength)
{
return NDIS_STATUS_FAILURE;
}
NdisQueryBuffer(pBuffer, &pVirtualAddr, &Length);
pHeader = (PUCHAR)pVirtualAddr;
if (( Adapter->EncryptionStatus == Ndis802_11Encryption2KeyAbsent ) ||
( Adapter->EncryptionStatus == Ndis802_11Encryption3KeyAbsent ) )
{
// no key yet, only allow 802.1x packets
if ( TotalPacketLength < 14 )
{
return NDIS_STATUS_FAILURE;
}
if ( (pHeader[12] != 0x88) || (pHeader[13] != 0x8E) )
{
return NDIS_STATUS_FAILURE;
}
}
#endif
EnterCriticalSection(&Adapter->TxCriticalSection);
if (Adapter->TxPacketCount < MAX_TX_PACKETS )
{
if (InsertNdisPacketToTXPkQ( Packet, &(Adapter->SendPackets[Adapter->TxPacketPut])))
{
Adapter->TxPacketCount++;
Adapter->TxPacketPut++;
Adapter->TxPacketPut %= MAX_TX_PACKETS;
Adapter->TxPacketSend++;
}
else
{
LeaveCriticalSection(&Adapter->TxCriticalSection);
return NDIS_STATUS_FAILURE;
}
}
else
{
LeaveCriticalSection(&Adapter->TxCriticalSection);
return NDIS_STATUS_FAILURE;
}
if ((Adapter->TxPacketGet != Adapter->TxPacketComplete) || (Adapter->CurCmd != NULL))
{
LeaveCriticalSection(&Adapter->TxCriticalSection);
return NDIS_STATUS_SUCCESS;
}
pTxPkt = &(Adapter->SendPackets[Adapter->TxPacketGet]);
Status = SendSinglePacket(Adapter,pTxPkt);
if (Status == NDIS_STATUS_SUCCESS)
{
Adapter->SendPackets[Adapter->TxPacketGet].PktLen = 0;
Status = NDIS_STATUS_SUCCESS;
Adapter->TxPacketGet++;
Adapter->TxPacketGet %= MAX_TX_PACKETS;
}
LeaveCriticalSection(&Adapter->TxCriticalSection);
//DBGPRINT(DBG_TXDATA, ("-MrvSend()\n"));
return NDIS_STATUS_SUCCESS;
}
BOOLEAN
InsertNdisPacketToTXPkQ(
IN PNDIS_PACKET Packet,
IN PTX_PKT_T pSendPacket
)
{
UINT BufferCount;
UINT TotalPacketLength = 0;
PNDIS_BUFFER pBuffer, pNextBuffer;
UINT Length, AccumLength;
ULONG coBufferLength = 0;
ULONG i;
PVOID pVirtualAddr;
PUCHAR pDest ;
PUCHAR pHeader ;
NdisQueryPacket(
Packet,
NULL,
&BufferCount,
&pBuffer,
&TotalPacketLength );
if (!pBuffer || !BufferCount || !TotalPacketLength)
{
goto end;
}
NdisQueryBuffer(pBuffer, &pVirtualAddr, &Length);
pDest = (PUCHAR)(pSendPacket->PktBuf);
pHeader = pDest;
AccumLength =0;
for (i=0; i<BufferCount; i++)
{
NdisQueryBuffer(pBuffer, &pVirtualAddr, &Length);
AccumLength += Length;
if ( AccumLength > MAX_TX_PKT_LEN )
goto end;
if ( Length )
{
NdisMoveMemory((PVOID)pDest, pVirtualAddr, Length);
pDest = (PUCHAR)(pDest + Length);
coBufferLength += Length;
}
NdisGetNextBuffer(pBuffer, &pNextBuffer);
if ( !pNextBuffer )
break;
pBuffer = pNextBuffer;
}
pSendPacket->PktLen = (USHORT)coBufferLength;
pSendPacket->Wcb.PktLen = (USHORT)coBufferLength;
pSendPacket->Wcb.Status = MRVDRV_WCB_STATUS_IDLE;
pSendPacket->Wcb.TxControl = 0;
pSendPacket->Wcb.PktPtr = sizeof(WCB);
// First buffer contains the MAC header
// Call NdisMoveMemory() to copy DEST MAC address to WCB
NdisMoveMemory(
(PVOID)(pSendPacket->Wcb.DestMACAdrHi),
pHeader,
MRVDRV_ETH_ADDR_LEN);
return TRUE;
end:
return FALSE;
}
/******************************************************************************
*
* Name: SendSinglePacket()
*
* Description: TX packet handler
*
* Arguments: PMRVDRV_ADAPTER Adapter
*
* Return Value:
*
* Notes:
*
*****************************************************************************/
NDIS_STATUS
SendSinglePacket(
IN PMRVDRV_ADAPTER Adapter,
IN PTX_PKT_T Packet
)
{
PCF_OBJECT pCf = (PCF_OBJECT)Adapter->hwIface; // get cf interface object.
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
IX_STATUS ixStatus = IX_STATUS_SUCCESS;
USHORT AccumLength;
PTxCtrlNode pTxNode;
NdisAcquireSpinLock(&Adapter->lCFInterfaceLock);
if ((Adapter->psState != PS_STATE_FULL_POWER) &&
(Adapter->psState != PS_STATE_WAKEUP))
{
NdisReleaseSpinLock(&Adapter->lCFInterfaceLock);
return NDIS_STATUS_FAILURE;
}
Adapter->bIsDoingTx = TRUE;
Status = NDIS_STATUS_SUCCESS;
pTxNode = &Adapter->TxNode;
pTxNode->NPTxPacket = Packet;
if ((Adapter->psState != PS_STATE_FULL_POWER) &&
(Adapter->psState != PS_STATE_WAKEUP))
{
DBGPRINT(DBG_TXDATA ,("Tx can not send in the power state_2 \n"));
Status = NDIS_STATUS_FAILURE;
goto end;
}
AccumLength = sizeof(WCB) + Packet->PktLen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -