📄 ndissend.c
字号:
UINT uiPacketLength
Length of the packet.
UINT uiBufferCount
Number of buffers.
Return (NDIS_STATUS):
NDIS_STATUS_PENDING if successful; otherwise, an error code indicating
failure.
*/
NDIS_STATUS SendBuffers (
PNDIS_ADAPTER pAdapter,
PNDIS_PACKET pPacket,
PNDIS_BUFFER pndisBuffer,
UINT uiPacketLength,
UINT uiBufferCount )
{
PTDesc pDesc;
PTDesc pLastDesc;
PTDesc pFirstDesc;
PDMA_BUFFER pDma;
PHARDWARE pHardware = &pAdapter->m_Hardware;
PTDescInfo pInfo = &pHardware->m_TxDescInfo;
NDIS_STATUS nsStatus = NDIS_STATUS_FAILURE;
TDesc BufDesc;
NDIS_PHYSICAL_ADDRESS_UNIT PhySegArray[ DRV_PACKET_ARRAY_SIZE ];
UINT uiPhySegCount;
UINT uiBuf;
UINT uiSeg;
#if 0
UINT uiLength;
BOOLEAN bBroadcast;
#endif
int port = MAIN_PORT;
/* Remember the very first descriptor. */
pFirstDesc = pInfo->pCurrent;
pDesc = pFirstDesc;
pLastDesc = pFirstDesc;
#if 0
{
UINT uiBufferLength;
PUCHAR pBuffer = GetFirstBuffer( &pndisBuffer, &uiBufferLength );
if ( pBuffer && ( pBuffer[ 0 ] & 0x01 ) )
{
bBroadcast = TRUE;
}
else
{
bBroadcast = FALSE;
}
}
#endif
for ( uiBuf = 0; uiBuf < uiBufferCount; uiBuf++ )
{
#if 0
// want length only
NdisQueryBuffer( pndisBuffer, NULL, &uiLength );
if ( 0 == uiLength )
{
continue;
}
#endif
pDma = Alloc_DMA_Buffer( &pAdapter->m_TxBufInfo, &BufDesc );
/* Get free map register. */
pDma->pMapReg = AllocMapReg( pAdapter );
pDma->pMapReg->pNdisBuffer = pndisBuffer;
/* Get the mapping of the physical segments. */
NdisMStartBufferPhysicalMapping(
pAdapter->m_hAdapter,
pndisBuffer, // Buffer
pDma->pMapReg->uiRegister, // PhysicalMapRegister
TRUE, // WriteToDevice
PhySegArray, // PhysicalAddressArray
&uiPhySegCount // ArraySize
);
#ifdef DBG
if ( uiPhySegCount )
#endif
{
for ( uiSeg = 0; uiSeg < uiPhySegCount; uiSeg++ )
{
#ifdef DBG
if ( PhySegArray[ uiSeg ].Length )
#endif
{
/* Release this descriptor to hardware if not the very
first one, not wanting the hardware to start
transmitting this packet when descriptors are being set.
*/
if ( pLastDesc != pFirstDesc )
ReleasePacket( pLastDesc );
SetTransmitBuffer( pDesc,
( ULONG ) NdisGetPhysicalAddressLow(
PhySegArray[ uiSeg ].PhysicalAddress ));
SetTransmitLength( pDesc,
PhySegArray[ uiSeg ].Length );
/* Remember the last descriptor. */
pLastDesc = pDesc;
/* Allocate more descriptor. */
GetTxPacket( pInfo, pDesc );
}
}
/* If more than one descriptor is used for this buffer, move the
buffer so that the mapping is freed only after all descriptors
are transmitted.
*/
pLastDesc->pReserved = BufDesc.pReserved;
}
#ifdef DBG
else
{
NdisMCompleteBufferPhysicalMapping(
pAdapter->m_hAdapter, pndisBuffer, pDma->pMapReg->uiRegister );
/* Recycle this map register. */
FreeMapReg( pAdapter, pDma->pMapReg );
pDma->pMapReg = NULL;
Free_DMA_Buffer( &pAdapter->m_TxBufInfo, pDma );
do
{
HardwareFreeTxPacket( pInfo );
pDesc = &pInfo->pRing[ pInfo->iNext ];
ReleaseDescriptor( pDesc, pDesc->sw.Control );
} while ( pDesc != pFirstDesc );
goto SendBuffersDone;
}
#endif
/* Flush buffer. */
NdisFlushBuffer( pndisBuffer, TRUE );
/* Get next buffer. */
NdisGetNextBuffer( pndisBuffer, &pndisBuffer );
}
/* One more descriptor is allocated. */
HardwareFreeTxPacket( pInfo );
/* The last descriptor holds the packet so that it can be returned to
network subsystem after all descriptors are transmitted.
*/
pDma->pNdisPacket = pPacket;
/* pCurrent points to the last descriptor. */
pInfo->pCurrent = pLastDesc;
/* Release the first descriptor. */
ReleasePacket( pFirstDesc );
if ( HardwareSendPacket( pHardware ) )
{
nsStatus = NDIS_STATUS_PENDING;
pHardware->m_cnCounter[ port ][ OID_COUNTER_XMIT_OK ]++;
#ifndef NO_STATS
if ( bBroadcast )
{
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_BROADCAST_FRAME_XMIT ]++;
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_BROADCAST_BYTES_XMIT ] += uiPacketLength;
}
else
{
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_DIRECTED_FRAMES_XMIT ]++;
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_DIRECTED_BYTES_XMIT ] += uiPacketLength;
}
#endif
}
#ifdef DBG
SendBuffersDone:
#endif
return( nsStatus );
} // SendBuffers
/* -------------------------------------------------------------------------- */
/*
TransmitDone
Description:
This routine cleans up the descriptors after transmission.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
Return (None):
*/
VOID TransmitDone (
PNDIS_ADAPTER pAdapter )
{
int iLast;
TDescStat status;
PHARDWARE pHardware = &pAdapter->m_Hardware;
PTDescInfo pInfo = &pHardware->m_TxDescInfo;
PTDesc pDesc;
PDMA_BUFFER pDma;
iLast = pInfo->iLast;
while ( pInfo->cnAvail < pInfo->cnAlloc )
{
/* Get next descriptor which is not hardware owned. */
GetTransmittedPacket( pInfo, iLast, pDesc, status.ulData );
if ( status.tx.fHWOwned )
break;
pDma = DMA_BUFFER( pDesc );
/* This descriptor contains a buffer. */
if ( pDma )
{
/* It is a mapped buffer. */
if ( pDma->pMapReg )
{
/* Ask network subsystem to free the mapping. */
NdisMCompleteBufferPhysicalMapping(
pAdapter->m_hAdapter,
pDma->pMapReg->pNdisBuffer,
pDma->pMapReg->uiRegister );
/* Free the map register. */
FreeMapReg( pAdapter, pDma->pMapReg );
pDma->pMapReg = NULL;
}
/* This descriptor contains the last buffer in the packet. */
if ( pDma->pNdisPacket )
{
/* Notify the network subsystem that the packet has been sent.
*/
NdisMSendComplete( pAdapter->m_hAdapter, pDma->pNdisPacket,
NDIS_STATUS_SUCCESS );
/* Release the packet back to network subsystem. */
pDma->pNdisPacket = NULL;
}
/* Free the transmitted buffer. */
Free_DMA_Buffer( &pAdapter->m_TxBufInfo, pDma );
pDesc->pReserved = NULL;
}
/* Free the transmitted descriptor. */
FreeTransmittedPacket( pInfo, iLast );
}
pInfo->iLast = iLast;
#ifdef SEND_QUEUE
if ( pHardware->m_TxDescInfo.cnAvail >
pHardware->m_TxDescInfo.cnAlloc / 4 )
SendNextPacket( pAdapter );
#endif
} // TransmitDone
/*
TransmitReset
Description:
This routine resets the descriptors to starting state after a software
reset.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
Return (None):
*/
VOID TransmitReset (
PNDIS_ADAPTER pAdapter )
{
PHARDWARE pHardware = &pAdapter->m_Hardware;
PTDescInfo pInfo = &pHardware->m_TxDescInfo;
int iLast;
PTDesc pDesc;
PDMA_BUFFER pDma;
TDescStat status;
iLast = pInfo->iLast;
while ( pInfo->cnAvail < pInfo->cnAlloc )
{
/* Get next descriptor which is hardware owned. */
GetTransmittedPacket( pInfo, iLast, pDesc, status.ulData );
if ( status.tx.fHWOwned )
{
ReleaseDescriptor( pDesc, status );
}
pDma = DMA_BUFFER( pDesc );
/* This descriptor contains a buffer. */
if ( pDma )
{
/* It is a mapped buffer. */
if ( pDma->pMapReg )
{
/* Ask network subsystem to free the mapping. */
NdisMCompleteBufferPhysicalMapping(
pAdapter->m_hAdapter,
pDma->pMapReg->pNdisBuffer,
pDma->pMapReg->uiRegister );
/* Free the map register. */
FreeMapReg( pAdapter, pDma->pMapReg );
pDma->pMapReg = NULL;
}
/* This descriptor contains the last buffer in the packet. */
if ( pDma->pNdisPacket )
{
/* Notify the network subsystem that the packet has not been
sent.
*/
NdisMSendComplete( pAdapter->m_hAdapter, pDma->pNdisPacket,
NDIS_STATUS_FAILURE );
/* Release the packet back to network subsystem. */
pDma->pNdisPacket = NULL;
}
/* Free the buffer. */
Free_DMA_Buffer( &pAdapter->m_TxBufInfo, pDma );
pDesc->pReserved = NULL;
}
/* Free the descriptor. */
FreeTransmittedPacket( pInfo, iLast );
}
pInfo->iLast = iLast;
} // TransmitReset
/* -------------------------------------------------------------------------- */
/*
MiniportSend
Description:
This function sends one packet in NDIS 3.0.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
PNDIS_PACKET pPacket
Pointer to NDIS packet.
UINT uiFlags
Send flags.
Return (NDIS_STATUS):
NDIS_STATUS_PENDING if successful; otherwise, an error code indicating
failure.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -