📄 txproc.c
字号:
/******************* ?Marvell Semiconductor, Inc., 2001-2004 *****************
*
* Purpose: This module has the implementation of TX functions
*
* $Author: schiu $
*
* $Date: 2004/11/03 $
*
* $Revision: #7 $
*
*****************************************************************************/
#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;
//Plus++
PNDIS_PACKET pPacket;
//Plus--
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;
}
DBGPRINT(DBG_TXDATA, ("+MrvSend()\n"));
#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 )
{
DBGPRINT(DBG_WARNING, ("WARNING: OS attempted to send packet while disconnected!\n"));
return NDIS_STATUS_FAILURE;
}
#ifdef WPA
pTxNode = &Adapter->TxNode;
NdisQueryPacket(
Packet,
NULL,
&BufferCount,
&pBuffer,
&TotalPacketLength );
if (!pBuffer || !BufferCount || !TotalPacketLength)
{
Status = NDIS_STATUS_FAILURE;
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 )
{
DBGPRINT(DBG_TXDATA | DBG_MACEVENT , ("Got packet with length less than 14, invalid!\n"));
///RETAILMSG(1, (TEXT("Got packet with length less than 14, invalid! \r\n")));
Status = NDIS_STATUS_FAILURE;
return NDIS_STATUS_FAILURE;
}
if ( (pHeader[12] != 0x88) || (pHeader[13] != 0x8E) )
{
DBGPRINT(DBG_TXDATA | DBG_MACEVENT , ("Still no key and packet type(0x%x 0x%x) is "
"not 802.1x, drop!\n",
pHeader[12], pHeader[13]));
///RETAILMSG(1, (TEXT("Still no key and packet type \r\n")));
Status = NDIS_STATUS_FAILURE;
return NDIS_STATUS_FAILURE;
}
}
#endif
EnterCriticalSection(&Adapter->TxCriticalSection);
if (Adapter->TxPacketCount < MAX_TX_PACKETS )
{
Adapter->SendPackets[Adapter->TxPacketPut] = Packet;
Adapter->TxPacketCount++;
Adapter->TxPacketPut++;
Adapter->TxPacketPut %= MAX_TX_PACKETS;
Adapter->TxPacketSend++;
}
else
{
DBGPRINT(DBG_DRALEE,("***TxPacketCount: %x \n\r",Adapter->TxPacketCount));
LeaveCriticalSection(&Adapter->TxCriticalSection);
///RETAILMSG(1, (TEXT("+MrvSend() NDIS_STATUS_RESOURCES\r\n")));
return NDIS_STATUS_RESOURCES;
}
if ((Adapter->TxPacketGet != Adapter->TxPacketComplete) || (Adapter->CurCmd != NULL))
{
//NKDbgPrintfW( L"Get Complete count %d %d \r\n", Adapter->TxPacketGet, Adapter->TxPacketComplete );
//DBGPRINT(1,("TxPacketCount: %x \n\r",Adapter->TxPacketCount));
LeaveCriticalSection(&Adapter->TxCriticalSection);
///RETAILMSG(1, (TEXT("+MrvSend() NDIS_STATUS_PENDING 1 \r\n")));
return NDIS_STATUS_PENDING;
}
pPacket = Adapter->SendPackets[Adapter->TxPacketGet];
Status = SendSinglePacket(Adapter,pPacket);
if(Status == NDIS_STATUS_SUCCESS)
{
//RETAILMSG(1,(TEXT("txproc: Packet is Sent \r\n")));
if (pPacket == Packet)
{
Adapter->SendPackets[Adapter->TxPacketGet] = NULL;
Status = NDIS_STATUS_SUCCESS;
///RETAILMSG(1, (TEXT("+MrvSend() NDIS_STATUS_SUCCESS \r\n")));
}
else
{
Status = NDIS_STATUS_PENDING;
///RETAILMSG(1, (TEXT("+MrvSend() NDIS_STATUS_PENDING 2 \r\n")));
}
//InterlockedIncrement(&Adapter->TxPacketGet);
Adapter->TxPacketGet++;
Adapter->TxPacketGet %= MAX_TX_PACKETS;
}
else
{
DBGPRINT(DBG_DRALEE,("###TxPacketCount: %x \n\r",Adapter->TxPacketCount));
LeaveCriticalSection(&Adapter->TxCriticalSection);
///RETAILMSG(1, (TEXT("+MrvSend() NDIS_STATUS_PENDING 3 \r\n")));
return NDIS_STATUS_PENDING;
}
LeaveCriticalSection(&Adapter->TxCriticalSection);
//DBGPRINT(DBG_ERROR,("Status %x TxSend %x \n", Status, Adapter->TxPacketSend));
#ifdef TX_PERFORMANCE_MEASUREMENT
TxRdyEventCalled++;
TxTickCount += GetTickCount() - ulCurTickCount;
// average for 8000 pkts
if ( TxRdyEventCalled == 8000 )
{
wchar_t buf[100];
swprintf(buf, TEXT("time in ms per TX pkt: %d"), TxTickCount / TxRdyEventCalled);
MessageBox(NULL, buf, TEXT("CF-25"), MB_OK);
TxRdyEventCalled = 0;
TxTickCount = 0;
}
#endif
//DBGPRINT(DBG_TXDATA, ("-MrvSend()\n"));
return Status;
}
/******************************************************************************
*
* Name: SendSinglePacket()
*
* Description: TX packet handler
*
* Arguments: PMRVDRV_ADAPTER Adapter
*
* Return Value:
*
* Notes:
*
*****************************************************************************/
NDIS_STATUS
SendSinglePacket(
IN PMRVDRV_ADAPTER Adapter,
IN PNDIS_PACKET Packet
)
{
PCF_OBJECT pCf = (PCF_OBJECT)Adapter->hwIface; // get cf interface object.
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
IX_STATUS ixStatus = IX_STATUS_SUCCESS;
UINT BufferCount;
UINT TotalPacketLength = 0;
UINT BytesCopied = 0;
UINT Length, AccumLength;
PNDIS_BUFFER pBuffer, pNextBuffer;
ULONG i;
PVOID pVirtualAddr;
PTxCtrlNode pTxNode;
UCHAR Buffer[MRVDRV_ETH_TX_PACKET_BUFFER_SIZE];
PUCHAR pDest = Buffer;
PUCHAR pHeader = NULL;
ULONG coBufferLength = 0;
//USHORT framlen;
UCHAR llc_snap[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
//DBGPRINT(DBG_TXDATA ,("+SendSinglePacket()\n"));
NdisAcquireSpinLock(&Adapter->lCFInterfaceLock);
if ((Adapter->psState != PS_STATE_FULL_POWER) &&
(Adapter->psState != PS_STATE_WAKEUP))
{
//DBGPRINT(DBG_TXDATA | DBG_MACEVENT |DBG_SP,("Tx can not send in the power state_1 \n"));
NdisReleaseSpinLock(&Adapter->lCFInterfaceLock);
return NDIS_STATUS_FAILURE;
}
Adapter->bIsDoingTx = TRUE;
Status = NDIS_STATUS_SUCCESS;
pTxNode = &Adapter->TxNode;
NdisQueryPacket(
Packet,
NULL,
&BufferCount,
&pBuffer,
&TotalPacketLength );
if (!pBuffer || !BufferCount || !TotalPacketLength)
{
DBGPRINT(DBG_TXDATA | DBG_MACEVENT ,("TX - NDIS buffer is not valid, return FAILURE \n"));
Status = NDIS_STATUS_FAILURE;
goto end;
}
NdisQueryBuffer(pBuffer, &pVirtualAddr, &Length);
pHeader = (PUCHAR)pVirtualAddr;
/// RETAILMSG(1, (TEXT("First Ndis Buffer Length = %d \r\n"), Length));
#ifdef WPA
if ((Adapter->EncryptionStatus == Ndis802_11Encryption2KeyAbsent ) ||
(Adapter->EncryptionStatus == Ndis802_11Encryption3KeyAbsent ))
{
// no key yet, only allow 802.1x packets
if ( TotalPacketLength < 14 )
{
DBGPRINT(DBG_TXDATA | DBG_MACEVENT , ("Got packet with length less than 14, invalid!\n"));
Status = NDIS_STATUS_FAILURE;
goto end;
}
if ( (pHeader[12] != 0x88) || (pHeader[13] != 0x8E) )
{
DBGPRINT(DBG_TXDATA | DBG_MACEVENT , ("Still no key and packet type(0x%x 0x%x) is "
"not 802.1x, drop!\n",
pHeader[12], pHeader[13]));
Status = NDIS_STATUS_FAILURE;
goto end;
}
}
#endif
DBGPRINT(DBG_TXDATA ,("SendSinglePacket: buffers %d, packet len %d\n",BufferCount, TotalPacketLength));
pTxNode->NPTxPacket = Packet;
NdisZeroMemory(pTxNode->LocalWCB, sizeof(WCB));
pTxNode->LocalWCB->Status = MRVDRV_WCB_STATUS_IDLE;
#ifdef INTERFACE20
DBGPRINT(DBG_DATARATE | DBG_MACEVENT ,("DataRate = %x\n", (ULONG)Adapter->DataRate));
// number of retry is 3
// pTxNode->LocalWCB->TxControl = (( 3 << 12 ) | Adapter->DataRate);
pTxNode->LocalWCB->TxControl = 0;
pTxNode->LocalWCB->PktPtr = sizeof(WCB);
#endif
// First buffer contains the MAC header
// Call NdisMoveMemory() to copy DEST MAC address to WCB
NdisMoveMemory(
(PVOID)pTxNode->LocalWCB->DestMACAdrHi,
pVirtualAddr,
MRVDRV_ETH_ADDR_LEN);
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;
}
// DBGPRINT(DBG_TXDATA |DBG_SP,(" Realy start Tx \n"));
// Query each buffer for the packet and move data to SQ
AccumLength = sizeof(WCB);
DBGPRINT(DBG_TXDATADUMP,("TX Buffer (Packet):\n"));
for (i=0; i<BufferCount; i++)
{
NdisQueryBuffer(pBuffer, &pVirtualAddr, &Length);
AccumLength += Length;
if ( AccumLength > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE ) // PJG: accum length already counts the header... need to compare to entire buffer size
break;
if ( Length )
{
NdisMoveMemory((PVOID)pDest, pVirtualAddr, Length);
pDest = (PUCHAR)(pDest + Length);
coBufferLength += Length;
/// HexDump(DBG_TXDATADUMP, NULL, pVirtualAddr, Length);
}
NdisGetNextBuffer(pBuffer, &pNextBuffer);
if ( !pNextBuffer )
break;
pBuffer = pNextBuffer;
}
/*
// workarround -> add for two card test
framlen = (*((PUCHAR)Buffer+12) << 8) | (*((PUCHAR)Buffer+13));
if (framlen <= 1500)
{
NdisMoveMemory((PCHAR)Buffer+12, (PCHAR)Buffer+14, coBufferLength-14);
coBufferLength -= 2;
AccumLength -=2;
}
// workarround -> add for two card test
{
if (NdisEqualMemory(llc_snap, (PCHAR)Buffer+12, 6) == 1)
{
if( ((Buffer[18] == 0x80) && (Buffer[19] == 0xf3)) ||
((Buffer[18] == 0x81) && (Buffer[19] == 0x37)) )
{
NdisMoveMemory((PCHAR)Buffer+12, (PCHAR)Buffer+18, coBufferLength-18);
coBufferLength -= 6;
AccumLength -=6;
}
}
}
*/
/*
{
if (NdisEqualMemory(llc_snap, (PCHAR)Buffer+14, 6) == 1)
{
if( ((Buffer[20] == 0x80) && (Buffer[21] == 0xf3)) ||
((Buffer[20] == 0x81) && (Buffer[21] == 0x37)) )
{
NdisMoveMemory((PCHAR)Buffer+12, (PCHAR)Buffer+20, coBufferLength-20);
coBufferLength -= 8;
AccumLength -=8;
}
}
}
*/
pTxNode->LocalWCB->PktLen = (USHORT)coBufferLength;
AccumLength = sizeof(WCB) + coBufferLength;
///HexDump(DBG_TXDATA, "The Context of Tx data \n", Buffer, coBufferLength);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -