📄 recv.c
字号:
PNDIS_PACKET pRcvPacket;
PUCHAR pRcvData;
UINT BytesTransferred;
PNDIS_BUFFER pOriginalNdisBuffer, pPartialNdisBuffer;
pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
NUIO_STRUCT_ASSERT(pOpenContext, oc);
pRcvPacket = NULL;
pRcvData = NULL;
Status = NDIS_STATUS_SUCCESS;
do
{
if (HeaderBufferSize != sizeof(NDISUIO_ETH_HEADER))
{
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
pEthHeader = (PNDISUIO_ETH_HEADER)pHeaderBuffer;
//
// Check the EtherType. If the Ether type indicates presence of
// a tag, then the "real" Ether type is 4 bytes further down.
//
if (pEthHeader->EthType == NUIO_8021P_TAG_TYPE)
{
USHORT UNALIGNED *pEthType;
pEthType = (USHORT UNALIGNED *)((PUCHAR)&pEthHeader->EthType + 4);
if (*pEthType != Globals.EthType)
{
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
}
else if (pEthHeader->EthType != Globals.EthType)
{
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
//
// Allocate resources for queueing this up.
//
pRcvPacket = ndisuioAllocateReceivePacket(
pOpenContext,
PacketSize + HeaderBufferSize,
&pRcvData
);
if (pRcvPacket == NULL)
{
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
NdisMoveMappedMemory(pRcvData, pHeaderBuffer, HeaderBufferSize);
//
// Check if the entire packet is within the lookahead.
//
if (PacketSize == LookaheadBufferSize)
{
NdisCopyLookaheadData(pRcvData+HeaderBufferSize,
pLookaheadBuffer,
LookaheadBufferSize,
pOpenContext->MacOptions);
//
// Queue this up for receive processing, and
// try to complete some read IRPs.
//
ndisuioQueueReceivePacket(pOpenContext, pRcvPacket);
}
else
{
//
// Allocate an NDIS buffer to map the receive area
// at an offset "HeaderBufferSize" from the current
// start. This is so that NdisTransferData can copy
// in at the right point in the destination buffer.
//
NdisAllocateBuffer(
&Status,
&pPartialNdisBuffer,
pOpenContext->RecvBufferPool,
pRcvData + HeaderBufferSize,
PacketSize);
if (Status == NDIS_STATUS_SUCCESS)
{
//
// Unlink and save away the original NDIS Buffer
// that maps the full receive buffer.
//
NdisUnchainBufferAtFront(pRcvPacket, &pOriginalNdisBuffer);
NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pRcvPacket) = pOriginalNdisBuffer;
//
// Link in the partial buffer for NdisTransferData to
// operate on.
//
NdisChainBufferAtBack(pRcvPacket, pPartialNdisBuffer);
DEBUGP(DL_LOUD, ("Receive: setting up for TransferData:"
" Pkt %p, OriginalBuf %p, PartialBuf %p\n",
pRcvPacket, pOriginalNdisBuffer, pPartialNdisBuffer));
NdisTransferData(
&Status,
pOpenContext->BindingHandle,
MacReceiveContext,
0, // ByteOffset
PacketSize,
pRcvPacket,
&BytesTransferred);
}
else
{
//
// Failure handled below in TransferDataComplete.
//
BytesTransferred = 0;
}
if (Status != NDIS_STATUS_PENDING)
{
NdisuioTransferDataComplete(
(NDIS_HANDLE)pOpenContext,
pRcvPacket,
Status,
BytesTransferred);
}
}
break;
}
while (FALSE);
return Status;
DEBUGP(DL_LOUD, ("Receive: Open %p, Pkt %p, Size %d\n",
pOpenContext, pRcvPacket, PacketSize));
}
VOID
NdisuioTransferDataComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET pNdisPacket,
IN NDIS_STATUS TransferStatus,
IN UINT BytesTransferred
)
/*++
Routine Description:
NDIS entry point called to signal completion of a call to
NdisTransferData that had pended.
Arguments:
ProtocolBindingContext - pointer to open context
pNdisPacket - our receive packet into which data is transferred
TransferStatus - status of the transfer
BytesTransferred - bytes copied into the packet.
Return Value:
None
--*/
{
PNDISUIO_OPEN_CONTEXT pOpenContext;
PNDIS_BUFFER pOriginalBuffer, pPartialBuffer;
pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
NUIO_STRUCT_ASSERT(pOpenContext, oc);
//
// Check if an NDIS_BUFFER was created to map part of the receive buffer;
// if so, free it and link back the original NDIS_BUFFER that maps
// the full receive buffer to the packet.
//
pOriginalBuffer = NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pNdisPacket);
if (pOriginalBuffer != NULL)
{
//
// We had stashed off the NDIS_BUFFER for the full receive
// buffer in the packet reserved area. Unlink the partial
// buffer and link in the full buffer.
//
NdisUnchainBufferAtFront(pNdisPacket, &pPartialBuffer);
NdisChainBufferAtBack(pNdisPacket, pOriginalBuffer);
DEBUGP(DL_LOUD, ("TransferComp: Pkt %p, OrigBuf %p, PartialBuf %p\n",
pNdisPacket, pOriginalBuffer, pPartialBuffer));
//
// Free up the partial buffer.
//
NdisFreeBuffer(pPartialBuffer);
}
if (TransferStatus == NDIS_STATUS_SUCCESS)
{
//
// Queue this up for receive processing, and
// try to complete some read IRPs.
//
ndisuioQueueReceivePacket(pOpenContext, pNdisPacket);
}
else
{
ndisuioFreeReceivePacket(pOpenContext, pNdisPacket);
}
}
VOID
NdisuioReceiveComplete(
IN NDIS_HANDLE ProtocolBindingContext
)
/*++
Routine Description:
Protocol entry point called by NDIS when the miniport
has finished indicating up a batch of receives.
We ignore this.
Arguments:
ProtocolBindingContext - pointer to open context
Return Value:
None
--*/
{
PNDISUIO_OPEN_CONTEXT pOpenContext;
pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
NUIO_STRUCT_ASSERT(pOpenContext, oc);
return;
}
INT
NdisuioReceivePacket(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET pNdisPacket
)
/*++
Routine Description:
Protocol entry point called by NDIS if the driver below
uses NDIS 4 style receive packet indications.
If the miniport allows us to hold on to this packet, we
use it as is, otherwise we make a copy.
Arguments:
ProtocolBindingContext - pointer to open context
pNdisPacket - the packet being indicated up.
Return Value:
None
--*/
{
PNDISUIO_OPEN_CONTEXT pOpenContext;
PNDIS_BUFFER pNdisBuffer;
UINT BufferLength;
PNDISUIO_ETH_HEADER pEthHeader;
PNDIS_PACKET pCopyPacket;
PUCHAR pCopyBuf;
UINT TotalPacketLength;
UINT BytesCopied;
INT RefCount = 0;
NDIS_STATUS Status;
pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
NUIO_STRUCT_ASSERT(pOpenContext, oc);
#ifdef NDIS51
NdisGetFirstBufferFromPacketSafe(
pNdisPacket,
&pNdisBuffer,
&pEthHeader,
&BufferLength,
&TotalPacketLength,
NormalPagePriority);
if (pEthHeader == NULL)
{
//
// The system is low on resources. Set up to handle failure
// below.
//
BufferLength = 0;
}
#else
NdisGetFirstBufferFromPacket(
pNdisPacket,
&pNdisBuffer,
&pEthHeader,
&BufferLength,
&TotalPacketLength);
#endif
do
{
if (BufferLength < sizeof(NDISUIO_ETH_HEADER))
{
DEBUGP(DL_WARN,
("ReceivePacket: Open %p, runt pkt %p, first buffer length %d\n",
pOpenContext, pNdisPacket, BufferLength));
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
//
// Check the EtherType. If the Ether type indicates presence of
// a tag, then the "real" Ether type is 4 bytes further down.
//
if (pEthHeader->EthType == NUIO_8021P_TAG_TYPE)
{
USHORT UNALIGNED *pEthType;
pEthType = (USHORT UNALIGNED *)((PUCHAR)&pEthHeader->EthType + 4);
if (*pEthType != Globals.EthType)
{
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
}
else if (pEthHeader->EthType != Globals.EthType)
{
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
DEBUGP(DL_LOUD, ("ReceivePacket: Open %p, interesting pkt %p\n",
pOpenContext, pNdisPacket));
//
// If the miniport is out of resources, we can't queue
// this packet - make a copy if this is so.
//
if ((NDIS_GET_PACKET_STATUS(pNdisPacket) == NDIS_STATUS_RESOURCES) ||
pOpenContext->bRunningOnWin9x)
{
pCopyPacket = ndisuioAllocateReceivePacket(
pOpenContext,
TotalPacketLength,
&pCopyBuf
);
if (pCopyPacket == NULL)
{
DEBUGP(DL_FATAL, ("ReceivePacket: Open %p, failed to"
" alloc copy, %d bytes\n", pOpenContext, TotalPacketLength));
break;
}
NdisCopyFromPacketToPacket(
pCopyPacket,
0,
TotalPacketLength,
pNdisPacket,
0,
&BytesCopied);
NUIO_ASSERT(BytesCopied == TotalPacketLength);
pNdisPacket = pCopyPacket;
}
else
{
//
// We can queue the original packet - return
// a packet reference count indicating that
// we will call NdisReturnPackets when we are
// done with this packet.
//
RefCount = 1;
}
//
// Queue this up and service any pending Read IRPs.
//
ndisuioQueueReceivePacket(pOpenContext, pNdisPacket);
break;
}
while (FALSE);
return (RefCount);
}
VOID
ndisuioQueueReceivePacket(
IN PNDISUIO_OPEN_CONTEXT pOpenContext,
IN PNDIS_PACKET pRcvPacket
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -