📄 protocol.c
字号:
Arguments:
<see DDK ref page for ProtocolReceive>
Return Value:
NDIS_STATUS_SUCCESS if we processed the receive successfully,
NDIS_STATUS_XXX error code if we discarded it.
--*/
{
PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
PNDIS_PACKET MyPacket, Packet = NULL;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PUCHAR pPacketContent;
PUCHAR pBuf;
UINT BufLength;
MDL *pNext;
UINT i;
NTSTATUS ntStatus;
if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))
{
Status = NDIS_STATUS_FAILURE;
}
else do
{
//
// Get at the packet, if any, indicated up by the miniport below.
//
Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
if (Packet != NULL)
{
//
// The miniport below did indicate up a packet. Use information
// from that packet to construct a new packet to indicate up.
//
#ifdef NDIS51
//
// NDIS 5.1 NOTE: Do not reuse the original packet in indicating
// up a receive, even if there is sufficient packet stack space.
// If we had to do so, we would have had to overwrite the
// status field in the original packet to NDIS_STATUS_RESOURCES,
// and it is not allowed for protocols to overwrite this field
// in received packets.
//
#endif // NDIS51
//
// Get a packet off the pool and indicate that up
//
NdisDprAllocatePacket(&Status,
&MyPacket,
pAdapt->RecvPacketPoolHandle);
if (Status == NDIS_STATUS_SUCCESS)
{
//
// Make our packet point to data from the original
// packet. NOTE: this works only because we are
// indicating a receive directly from the context of
// our receive indication. If we need to queue this
// packet and indicate it from another thread context,
// we will also have to allocate a new buffer and copy
// over the packet contents, OOB data and per-packet
// information. This is because the packet data
// is available only for the duration of this
// receive indication call.
//
NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);
//
// Get the original packet (it could be the same packet as the
// one received or a different one based on the number of layered
// miniports below) and set it on the indicated packet so the OOB
// data is visible correctly at protocols above.
//
NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);
//
// Copy packet flags.
//
NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
//
// Force protocols above to make a copy if they want to hang
// on to data in this packet. This is because we are in our
// Receive handler (not ReceivePacket) and we can't return a
// ref count from here.
//
NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);
//
// By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim
// this packet as soon as the call to NdisMIndicateReceivePacket
// returns.
//
// NOTE: we queue the packet and indicate this packet immediately with
// the already queued packets together. We have to the queue the packet
// first because some versions of NDIS might call protocols'
// ReceiveHandler(not ReceivePacketHandler) if the packet indicate status
// is NDIS_STATUS_RESOURCES. If the miniport below indicates an array of
// packets, some of them with status NDIS_STATUS_SUCCESS, some of them
// with status NDIS_STATUS_RESOURCES, PtReceive might be called, by
// doing this way, we preserve the receive order of packets.
//
PtQueueReceivedPacket(pAdapt, MyPacket, TRUE);
//
// Reclaim the indicated packet. Since we had set its status
// to NDIS_STATUS_RESOURCES, we are guaranteed that protocols
// above are done with it.
//
if(Monitor_flag)
{
NdisQueryPacket(Packet,NULL,NULL,NULL,&PacketSize);
ntStatus = NdisAllocateMemory(&pPacketContent,2000,0,HighestAcceptableMax);
if(ntStatus != NDIS_STATUS_SUCCESS)
{
DbgPrint("PTReceive:NdisAllocateMemory Failed\n");
}
NdisZeroMemory(pPacketContent,2000);
NdisQueryBufferSafe(Packet->Private.Head,&pBuf,&BufLength,32);
NdisMoveMemory(pPacketContent,pBuf,BufLength);
i = BufLength;
pNext = Packet->Private.Head;
for(;;)
{
if(pNext == Packet->Private.Tail)
break;
pNext = pNext->Next;
if(pNext == NULL)
break;
NdisQueryBufferSafe(pNext,&pBuf,&BufLength,32);
NdisMoveMemory(pPacketContent+i,pBuf,BufLength);
i+=BufLength;
}
Check_Packet(pPacketContent);
}
NdisDprFreePacket(MyPacket);
break;
}
}
else
{
//
// The miniport below us uses the old-style (not packet)
// receive indication. Fall through.
//
}
//
// Fall through if the miniport below us has either not
// indicated a packet or we could not allocate one
//
if (Packet != NULL)
{
//
// We are here because we failed to allocate packet
//
PtFlushReceiveQueue(pAdapt);
}
//
// Here the driver checks if the miniport adapter is in lower power state, do not indicate the
// packets, but the check does not close the window, it only minimizes the window. To close
// the window completely, we need to add synchronization in the receive code path; because
// NDIS can handle the case that miniport drivers indicate packets in lower power state,
// we don't add the synchronization in the hot code path.
//
if ((pAdapt->MiniportHandle == NULL)
|| (pAdapt->MPDeviceState > NdisDeviceStateD0))
{
break;
}
pAdapt->IndicateRcvComplete = TRUE;
switch (pAdapt->Medium)
{
case NdisMedium802_3:
case NdisMediumWan:
NdisMEthIndicateReceive(pAdapt->MiniportHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
break;
case NdisMedium802_5:
NdisMTrIndicateReceive(pAdapt->MiniportHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
break;
case NdisMediumFddi:
NdisMFddiIndicateReceive(pAdapt->MiniportHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
break;
default:
ASSERT(FALSE);
break;
}
} while(FALSE);
return Status;
}
VOID
PtReceiveComplete(
IN NDIS_HANDLE ProtocolBindingContext
)
/*++
Routine Description:
Called by the adapter below us when it is done indicating a batch of
received packets.
Arguments:
ProtocolBindingContext Pointer to our adapter structure.
Return Value:
None
--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET PacketArray[MAX_RECEIVE_PACKET_ARRAY_SIZE];
ULONG NumberOfPackets = 0, i;
PtFlushReceiveQueue(pAdapt);
if ((pAdapt->MiniportHandle != NULL)
&& (pAdapt->MPDeviceState == NdisDeviceStateD0)
&& (pAdapt->IndicateRcvComplete == TRUE))
{
switch (pAdapt->Medium)
{
case NdisMedium802_3:
case NdisMediumWan:
NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle);
break;
case NdisMedium802_5:
NdisMTrIndicateReceiveComplete(pAdapt->MiniportHandle);
break;
case NdisMediumFddi:
NdisMFddiIndicateReceiveComplete(pAdapt->MiniportHandle);
break;
default:
ASSERT(FALSE);
break;
}
}
pAdapt->IndicateRcvComplete = FALSE;
}
INT
PtReceivePacket(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet
)
/*++
Routine Description:
ReceivePacket handler. Called by NDIS if the miniport below supports
NDIS 4.0 style receives. Re-package the buffer chain in a new packet
and indicate the new packet to protocols above us. Any context for
packets indicated up must be kept in the MiniportReserved field.
NDIS 5.1 - packet stacking - if there is sufficient "stack space" in
the packet passed to us, we can use the same packet in a receive
indication.
Arguments:
ProtocolBindingContext - Pointer to our adapter structure.
Packet - Pointer to the packet
Return Value:
== 0 -> We are done with the packet
!= 0 -> We will keep the packet and call NdisReturnPackets() this
many times when done.
--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
NDIS_STATUS Status;
PNDIS_PACKET MyPacket;
BOOLEAN Remaining;
PUCHAR pPacketContent;
PUCHAR pBuf;
UINT BufLength;
MDL *pNext;
UINT i;
int PacketSize;
//
// Drop the packet silently if the upper miniport edge isn't initialized or
// the miniport edge is in low power state
//
if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))
{
return 0;
}
#ifdef NDIS51
//
// Check if we can reuse the same packet for indicating up.
// See also: PtReceive().
//
(VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining);
if (Remaining)
{
//
// We can reuse "Packet". Indicate it up and be done with it.
//
Status = NDIS_GET_PACKET_STATUS(Packet);
if (Status == NDIS_STATUS_RESOURCES)
{
PtQueueReceivedPacket(pAdapt, Packet, TRUE);
}
else
{
PtQueueReceivedPacket(pAdapt, Packet, FALSE);
}
return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
}
#endif // NDIS51
//
// Get a packet off the pool and indicate that up
//
NdisDprAllocatePacket(&Status,
&MyPacket,
pAdapt->RecvPacketPoolHandle);
if (Status == NDIS_STATUS_SUCCESS)
{
PRECV_RSVD RecvRsvd;
RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved);
RecvRsvd->OriginalPkt = Packet;
NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);
//
// Get the original packet (it could be the same packet as the one
// received or a different one based on the number of layered miniports
// below) and set it on the indicated packet so the OOB data is visible
// correctly to protocols above us.
//
NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
//
// Set Packet Flags
//
NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
Status = NDIS_GET_PACKET_STATUS(Packet);
NDIS_SET_PACKET_STATUS(MyPacket, Status);
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));
if (Status == NDIS_STATUS_RESOURCES)
{
PtQueueReceivedPacket(pAdapt, MyPacket, TRUE);
}
else
{
PtQueueReceivedPacket(pAdapt, MyPacket, FALSE);
}
//
// Check if we had indicated up the packet with NDIS_STATUS_RESOURCES
// NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since
// it might have changed! Use the value saved in the local variable.
//
if (Status == NDIS_STATUS_RESOURCES)
{
//
// Our ReturnPackets handler will not be called for this packet.
// We should reclaim it right here.
//
NdisDprFreePacket(MyPacket);
}
return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
}
else
{
//
// We are out of packets. Silently drop it.
//
return(0);
}
}
NDIS_STATUS
PtPNPHandler(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNET_PNP_EVENT pNetPnPEvent
)
/*++
Routine Description:
This is called by NDIS to notify us of a PNP event related to a lower
binding. Based on the event, this dispatches to other helper routines.
NDIS 5.1: forward this event to the upper protocol(s) by calling
NdisIMNotifyPnPEvent.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -