summaryrefslogtreecommitdiff
path: root/network/wwan/cxwmbclass/rxqueue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'network/wwan/cxwmbclass/rxqueue.cpp')
-rw-r--r--network/wwan/cxwmbclass/rxqueue.cpp602
1 files changed, 602 insertions, 0 deletions
diff --git a/network/wwan/cxwmbclass/rxqueue.cpp b/network/wwan/cxwmbclass/rxqueue.cpp
new file mode 100644
index 00000000..836201a5
--- /dev/null
+++ b/network/wwan/cxwmbclass/rxqueue.cpp
@@ -0,0 +1,602 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#include "precomp.h"
+
+#include "device.h"
+#include "rxqueue.h"
+
+#define MBB_NTH_GET_FIRST_NDP_OFFSET(IS32BIT, NTH) \
+ ((IS32BIT) ? MBB_NTH32_GET_FIRST_NDP_OFFSET((PNCM_NTH32)NTH) : MBB_NTH16_GET_FIRST_NDP_OFFSET((PNCM_NTH16)NTH))
+
+void MbbNotifyRxReady(_In_ NETPACKETQUEUE RxQueue)
+{
+ PMBB_RXQUEUE_CONTEXT rxQueueContext = MbbGetRxQueueContext(RxQueue);
+ if (InterlockedExchange(&rxQueueContext->NotificationEnabled, FALSE) == TRUE)
+ {
+ NetRxQueueNotifyMoreReceivedPacketsAvailable(RxQueue);
+ }
+}
+
+VOID MbbRecvCleanup(_In_ PMBB_NDIS_RECEIVE_CONTEXT Receive)
+{
+ MbbBusReturnReceiveBuffer(Receive->BusHandle, Receive->BusContext, Receive->Mdl);
+
+ WdfObjectDelete(Receive->ReceiveLookasideBufferMemory);
+}
+
+VOID MbbRecvReturnNdp(_In_ PMBB_NDIS_RECEIVE_CONTEXT ReceiveContext, _In_opt_ PMBB_RECEIVE_NDP_CONTEXT ReceiveNdpContext)
+{
+ LONG newCompletedCount = InterlockedIncrement(&ReceiveContext->CompletedNdpCount);
+ if (newCompletedCount == ReceiveContext->TotalNdpCount)
+ {
+ MbbRecvCleanup(ReceiveContext);
+ }
+ if (ReceiveNdpContext != NULL)
+ {
+ WdfObjectDelete(ReceiveNdpContext->ReceiveNdpLookasideBufferMemory);
+ }
+}
+
+_Use_decl_annotations_ VOID MbbRecvCancelNdps(PWMBCLASS_DEVICE_CONTEXT DeviceContext, ULONG SessionId)
+{
+ LIST_ENTRY tempList;
+ PLIST_ENTRY listEntry;
+ PLIST_ENTRY nextEntry;
+ PMBB_RECEIVE_NDP_CONTEXT receiveNdpContext = NULL;
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = DeviceContext->Sessions[SessionId].NetAdapterContext;
+
+ InitializeListHead(&tempList);
+
+ WdfSpinLockAcquire(DeviceContext->Sessions[SessionId].WdfRecvSpinLock);
+ InsertHeadList(&netAdapterContext->ReceiveNdpList, &tempList);
+ RemoveEntryList(&netAdapterContext->ReceiveNdpList);
+ InitializeListHead(&netAdapterContext->ReceiveNdpList);
+ // Cannot cache the received Ndps anymore
+ netAdapterContext->AllowRxTraffic = FALSE;
+ WdfSpinLockRelease(DeviceContext->Sessions[SessionId].WdfRecvSpinLock);
+
+ for (listEntry = tempList.Flink; listEntry != &tempList; listEntry = nextEntry)
+ {
+ nextEntry = listEntry->Flink;
+ receiveNdpContext = CONTAINING_RECORD(listEntry, MBB_RECEIVE_NDP_CONTEXT, ReceiveNdpNode);
+ MbbRecvReturnNdp(receiveNdpContext->ReceiveContext, receiveNdpContext);
+ }
+}
+
+void MbbReceiveDssData(__in PWMBCLASS_DEVICE_CONTEXT DeviceContext, __in ULONG SessionId, __in_bcount_opt(InBufferSize) PUCHAR InBuffer, __in ULONG InBufferSize)
+{
+ NTSTATUS status;
+ WDFMEMORY data;
+
+ status = WdfMemoryCreatePreallocated(WDF_NO_OBJECT_ATTRIBUTES, InBuffer, InBufferSize, &data);
+
+ if (NT_SUCCESS(status))
+ {
+ DeviceContext->DSSPacketsReceivedCount++;
+
+ MbbDeviceReceiveDeviceServiceSessionData(DeviceContext->WdfDevice, SessionId, data);
+ WdfObjectDelete(data);
+ }
+}
+
+NTSTATUS
+MbbRecvNdpUnpackDss32(_In_ PMBB_NDIS_RECEIVE_CONTEXT ReceiveContext, _In_ PNCM_NTH32 Nth, _In_ PNCM_NDP32 Ndp)
+{
+ UNREFERENCED_PARAMETER(Nth);
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG datagramCount = MBB_NDP32_GET_DATAGRAM_COUNT(Ndp);
+ ULONG sessionId = MBB_NDP32_GET_SESSIONID(Ndp);
+ for (ULONG index = 0; index < datagramCount; index++)
+ {
+ if (MBB_NTB32_IS_END_DATAGRAM(Nth, Ndp, index))
+ break;
+
+ // Forward to the dss receive handler
+ MbbReceiveDssData(
+ ReceiveContext->WmbDeviceContext, sessionId, (PUCHAR)MBB_NDP32_GET_DATAGRAM(Nth, Ndp, index), MBB_NDP32_GET_DATAGRAM_LENGTH(Ndp, index));
+ }
+
+ MbbRecvReturnNdp(ReceiveContext, NULL);
+ return status;
+}
+
+NTSTATUS
+MbbRecvNdpUnpackDss16(_In_ PMBB_NDIS_RECEIVE_CONTEXT ReceiveContext, _In_ PNCM_NTH16 Nth, _In_ PNCM_NDP16 Ndp)
+{
+ UNREFERENCED_PARAMETER(Nth);
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG datagramCount = MBB_NDP16_GET_DATAGRAM_COUNT(Ndp);
+ ULONG sessionId = MBB_NDP16_GET_SESSIONID(Ndp);
+ for (ULONG index = 0; index < datagramCount; index++)
+ {
+ if (MBB_NTB16_IS_END_DATAGRAM(Nth, Ndp, index))
+ break;
+
+ // Forward to the dss receive handler
+ MbbReceiveDssData(
+ ReceiveContext->WmbDeviceContext, sessionId, (PUCHAR)MBB_NDP16_GET_DATAGRAM(Nth, Ndp, index), MBB_NDP16_GET_DATAGRAM_LENGTH(Ndp, index));
+ }
+ MbbRecvReturnNdp(ReceiveContext, NULL);
+ return status;
+}
+
+NTSTATUS
+MbbRecvAddNdp(_In_ PMBB_NDIS_RECEIVE_CONTEXT ReceiveContext, _In_ PVOID Nth, _In_ PVOID Ndp, _In_ ULONG SessionId)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = ReceiveContext->WmbDeviceContext;
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = NULL;
+ WDFMEMORY ndpContextMemory;
+ PMBB_RECEIVE_NDP_CONTEXT ndpContext = NULL;
+ size_t ndpContextSize;
+ BOOLEAN returnNdp = FALSE;
+
+ WdfSpinLockAcquire(deviceContext->Sessions[SessionId].WdfRecvSpinLock);
+ do
+ {
+ netAdapterContext = deviceContext->Sessions[SessionId].NetAdapterContext;
+ if (netAdapterContext == NULL)
+ {
+ returnNdp = TRUE;
+ break;
+ }
+
+ if (!NT_SUCCESS(status = WdfMemoryCreateFromLookaside(netAdapterContext->ReceiveNdpLookasideList, &ndpContextMemory)))
+ {
+ returnNdp = TRUE;
+ break;
+ }
+
+ ndpContext = (PMBB_RECEIVE_NDP_CONTEXT)WdfMemoryGetBuffer(ndpContextMemory, &ndpContextSize);
+ RtlZeroMemory(ndpContext, ndpContextSize);
+ ndpContext->Nth = Nth;
+ ndpContext->Ndp = Ndp;
+ ndpContext->ReceiveContext = ReceiveContext;
+ ndpContext->ReceiveNdpLookasideBufferMemory = ndpContextMemory;
+ ndpContext->NetAdapterContext = netAdapterContext;
+ if (netAdapterContext->AllowRxTraffic)
+ {
+ InsertTailList(&netAdapterContext->ReceiveNdpList, &ndpContext->ReceiveNdpNode);
+ }
+ else
+ {
+ returnNdp = TRUE;
+ break;
+ }
+
+ // If RxQueueCreate hasn't completed yet, we only queue the received Ndp and don't need notify RxReady
+ if (netAdapterContext->RxQueue)
+ {
+ MbbNotifyRxReady(netAdapterContext->RxQueue);
+ }
+ } while (FALSE);
+ WdfSpinLockRelease(deviceContext->Sessions[SessionId].WdfRecvSpinLock);
+
+ if (returnNdp)
+ {
+ MbbRecvReturnNdp(ReceiveContext, ndpContext);
+ }
+ return status;
+}
+
+VOID MbbRecvNtbParse(_In_ PMBB_NDIS_RECEIVE_CONTEXT ReceiveContext)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PNCM_NTH32 nth32;
+ PNCM_NTH16 nth16;
+ PNCM_NDP32 ndp32;
+ PNCM_NDP16 ndp16;
+ PVOID nth = ReceiveContext->ReceiveNtbBuffer;
+
+ if (MBB_NTB_IS_32BIT(nth))
+ {
+ nth32 = (PNCM_NTH32)nth;
+ for (ndp32 = MBB_NTH32_GET_FIRST_NDP(nth32); ndp32 != NULL; ndp32 = MBB_NDP32_GET_NEXT_NDP(nth32, ndp32))
+ {
+ if (MBB_NDP32_GET_SIGNATURE_TYPE(ndp32) == NCM_NDP32_VENDOR)
+ {
+ status = MbbRecvNdpUnpackDss32(ReceiveContext, nth32, ndp32);
+ if (!NT_SUCCESS(status))
+ {
+ }
+ }
+ else if (MBB_NDP32_GET_SIGNATURE_TYPE(ndp32) == NCM_NDP32_IPS)
+ {
+ status = MbbRecvAddNdp(ReceiveContext, nth32, ndp32, MBB_NDP32_GET_SESSIONID(ndp32));
+ if (!NT_SUCCESS(status))
+ {
+ }
+ }
+ else
+ {
+ MbbRecvReturnNdp(ReceiveContext, NULL);
+ }
+ }
+ }
+ else if (MBB_NTB_IS_16BIT(nth))
+ {
+ nth16 = (PNCM_NTH16)nth;
+ for (ndp16 = MBB_NTH16_GET_FIRST_NDP(nth16); ndp16 != NULL; ndp16 = MBB_NDP16_GET_NEXT_NDP(nth16, ndp16))
+ {
+ if (MBB_NDP16_GET_SIGNATURE_TYPE(ndp16) == NCM_NDP16_VENDOR)
+ {
+ status = MbbRecvNdpUnpackDss16(ReceiveContext, nth16, ndp16);
+ if (!NT_SUCCESS(status))
+ {
+ }
+ }
+ else if (MBB_NDP16_GET_SIGNATURE_TYPE(ndp16) == NCM_NDP16_IPS)
+ {
+ status = MbbRecvAddNdp(ReceiveContext, nth16, ndp16, MBB_NDP32_GET_SESSIONID(ndp16));
+ if (!NT_SUCCESS(status))
+ {
+ }
+ }
+ else
+ {
+ MbbRecvReturnNdp(ReceiveContext, NULL);
+ }
+ }
+ }
+}
+
+NTSTATUS
+MbbRecvNtbUnpackIpNdp32(_In_ PMBB_RECEIVE_NDP_CONTEXT ReceiveNdpContext, _In_ PNCM_NTH32 Nth32, _In_ PNCM_NDP32 Ndp32, _Inout_ ULONG* IncompletedDatagramIndex, _In_ PMBB_RXQUEUE_CONTEXT RxQueueContext)
+{
+ PCHAR incompletedDatagram;
+ ULONG incompletedDatagramLength;
+ NET_PACKET* packet;
+ NET_FRAGMENT* fragment;
+ NET_FRAGMENT_RETURN_CONTEXT* returnContext;
+ NET_FRAGMENT_VIRTUAL_ADDRESS* virtualAddress;
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG datagramCount = MBB_NDP32_GET_DATAGRAM_COUNT(Ndp32);
+
+ NET_RING * pr = NetRingCollectionGetPacketRing(RxQueueContext->DatapathDescriptor);
+ NET_RING * fr = NetRingCollectionGetFragmentRing(RxQueueContext->DatapathDescriptor);
+
+ while ((incompletedDatagram = MBB_NDP32_GET_DATAGRAM(Nth32, Ndp32, *IncompletedDatagramIndex)) != NULL)
+ {
+ if (*IncompletedDatagramIndex >= datagramCount)
+ {
+ break;
+ }
+
+ if (fr->BeginIndex == fr->EndIndex)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ break;
+ }
+
+ incompletedDatagramLength = MBB_NDP32_GET_DATAGRAM_LENGTH(Ndp32, *IncompletedDatagramIndex);
+
+ UINT32 const fragmentIndex = fr->BeginIndex;
+ fragment = NetRingGetFragmentAtIndex(fr, fragmentIndex);
+ fragment->Capacity = incompletedDatagramLength;
+ fragment->ValidLength = incompletedDatagramLength;
+ fragment->Offset = 0;
+
+ returnContext = NetExtensionGetFragmentReturnContext(&RxQueueContext->ReturnContextExtension, fragmentIndex);
+ virtualAddress =
+ NetExtensionGetFragmentVirtualAddress(&RxQueueContext->VirtualAddressExtension, fragmentIndex);
+
+
+ returnContext->Handle = (NET_FRAGMENT_RETURN_CONTEXT_HANDLE)ReceiveNdpContext;
+ virtualAddress->VirtualAddress = incompletedDatagram;
+
+ (ReceiveNdpContext->IndicatedPackets)++;
+ (*IncompletedDatagramIndex)++;
+
+ UINT32 const packetIndex = pr->BeginIndex;
+ packet = NetRingGetPacketAtIndex(pr, packetIndex);
+ packet->FragmentIndex = fragmentIndex;
+ packet->FragmentCount = 1;
+ packet->Layout = {};
+
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+ fr->BeginIndex = NetRingIncrementIndex(fr, fr->BeginIndex);
+ }
+ return status;
+}
+
+NTSTATUS
+MbbRecvNtbUnpackIpNdp16(_In_ PMBB_RECEIVE_NDP_CONTEXT ReceiveNdpContext, _In_ PNCM_NTH16 Nth16, _In_ PNCM_NDP16 Ndp16, _Inout_ ULONG* IncompletedDatagramIndex, _In_ PMBB_RXQUEUE_CONTEXT RxQueueContext)
+{
+ PCHAR incompletedDatagram;
+ ULONG incompletedDatagramLength;
+ NET_PACKET* packet;
+ NET_FRAGMENT* fragment;
+ NET_FRAGMENT_RETURN_CONTEXT* returnContext;
+ NET_FRAGMENT_VIRTUAL_ADDRESS* virtualAddress;
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG datagramCount = MBB_NDP16_GET_DATAGRAM_COUNT(Ndp16);
+
+ NET_RING * pr = NetRingCollectionGetPacketRing(RxQueueContext->DatapathDescriptor);
+ NET_RING * fr = NetRingCollectionGetFragmentRing(RxQueueContext->DatapathDescriptor);
+
+ while ((incompletedDatagram = MBB_NDP16_GET_DATAGRAM(Nth16, Ndp16, *IncompletedDatagramIndex)) != NULL)
+ {
+ if (*IncompletedDatagramIndex >= datagramCount)
+ {
+ break;
+ }
+
+ if (fr->BeginIndex == fr->EndIndex)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ break;
+ }
+
+ incompletedDatagramLength = MBB_NDP16_GET_DATAGRAM_LENGTH(Ndp16, *IncompletedDatagramIndex);
+
+ UINT32 const fragmentIndex = fr->BeginIndex;
+ fragment = NetRingGetFragmentAtIndex(fr, fragmentIndex);
+ fragment->Capacity = incompletedDatagramLength;
+ fragment->ValidLength = incompletedDatagramLength;
+ fragment->Offset = 0;
+
+ returnContext = NetExtensionGetFragmentReturnContext(&RxQueueContext->ReturnContextExtension, fragmentIndex);
+ virtualAddress =
+ NetExtensionGetFragmentVirtualAddress(&RxQueueContext->VirtualAddressExtension, fragmentIndex);
+
+ returnContext->Handle = (NET_FRAGMENT_RETURN_CONTEXT_HANDLE)ReceiveNdpContext;
+ virtualAddress->VirtualAddress = incompletedDatagram;
+
+ (ReceiveNdpContext->IndicatedPackets)++;
+ (*IncompletedDatagramIndex)++;
+
+ UINT32 const packetIndex = pr->BeginIndex;
+ packet = NetRingGetPacketAtIndex(pr, packetIndex);
+ packet->FragmentIndex = fragmentIndex;
+ packet->FragmentCount = 1;
+ packet->Layout = {};
+
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+ fr->BeginIndex = NetRingIncrementIndex(fr, fr->BeginIndex);
+ }
+
+ return status;
+}
+
+NTSTATUS
+MbbRecvNdpUnpackIps(_In_ PMBB_RECEIVE_NDP_CONTEXT ReceiveNdpContext, _In_ PMBB_RXQUEUE_CONTEXT RxQueueContext)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PNCM_NTH32 nth32;
+ PNCM_NTH16 nth16;
+ PNCM_NDP32 ndp32;
+ PNCM_NDP16 ndp16;
+ PMBB_NDIS_RECEIVE_CONTEXT receiveContext = ReceiveNdpContext->ReceiveContext;
+ PVOID nth = receiveContext->ReceiveNtbBuffer;
+
+ if (MBB_NTB_IS_32BIT(nth))
+ {
+ nth32 = (PNCM_NTH32)nth;
+ ndp32 = (PNCM_NDP32)ReceiveNdpContext->Ndp;
+ status = MbbRecvNtbUnpackIpNdp32(ReceiveNdpContext, nth32, ndp32, &ReceiveNdpContext->CurrentDatagramIndex, RxQueueContext);
+ }
+ else if (MBB_NTB_IS_16BIT(nth))
+ {
+ nth16 = (PNCM_NTH16)nth;
+ ndp16 = (PNCM_NDP16)ReceiveNdpContext->Ndp;
+ status = MbbRecvNtbUnpackIpNdp16(ReceiveNdpContext, nth16, ndp16, &ReceiveNdpContext->CurrentDatagramIndex, RxQueueContext);
+ }
+
+ return status;
+}
+
+PMBB_NDIS_RECEIVE_CONTEXT
+MbbRecvQQueueReceive(_In_ PWMBCLASS_DEVICE_CONTEXT DeviceContext, _In_ MBB_RECEIVE_CONTEXT BusContext, _In_ PMDL Mdl, _In_reads_(sizeof(NCM_NTH32)) PUCHAR ReceiveNtbBuffer)
+{
+ PMBB_NDIS_RECEIVE_CONTEXT receiveContext = NULL;
+ WDFMEMORY receiveContextMemory;
+ size_t receiveContextSize;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ do
+ {
+ if (!NT_SUCCESS(status = WdfMemoryCreateFromLookaside(DeviceContext->ReceiveLookasideList, &receiveContextMemory)))
+ {
+ break;
+ }
+
+ receiveContext = (PMBB_NDIS_RECEIVE_CONTEXT)WdfMemoryGetBuffer(receiveContextMemory, &receiveContextSize);
+ RtlZeroMemory(receiveContext, receiveContextSize);
+
+ receiveContext->Mdl = Mdl;
+ receiveContext->WmbDeviceContext = DeviceContext;
+ receiveContext->BusHandle = DeviceContext->BusHandle;
+ receiveContext->BusContext = BusContext;
+ receiveContext->ReceiveLookasideList = DeviceContext->ReceiveLookasideList;
+ receiveContext->ReceiveLookasideBufferMemory = receiveContextMemory;
+ receiveContext->ReceiveNtbBuffer = ReceiveNtbBuffer;
+ receiveContext->NtbSequence = MBB_NTB_GET_SEQUENCE(ReceiveNtbBuffer);
+ } while (FALSE);
+
+ return receiveContext;
+}
+
+VOID MbbNdisReceiveCallback(_In_ MBB_PROTOCOL_HANDLE ProtocolHandle, _In_ MBB_RECEIVE_CONTEXT ReceiveContext, _In_ PMDL Mdl)
+{
+ PUCHAR dataBuffer;
+ ULONG dataLength;
+ PVOID nth;
+ BOOLEAN returnBuffer = TRUE;
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = (PWMBCLASS_DEVICE_CONTEXT)ProtocolHandle;
+ PMBB_NDIS_RECEIVE_CONTEXT receive = NULL;
+ ULONG ndpCount = 1;
+ NTSTATUS status = STATUS_SUCCESS;
+ do
+ {
+ if ((dataBuffer = (PUCHAR)MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority | MdlMappingNoExecute)) == NULL)
+ {
+ status = STATUS_RESOURCE_DATA_NOT_FOUND;
+ break;
+ }
+ dataLength = MmGetMdlByteCount(Mdl);
+
+ nth = dataBuffer;
+
+ if (!NT_SUCCESS(status = MbbNtbValidate(nth, dataLength, deviceContext->BusParams.CurrentMode32Bit, &ndpCount)))
+ {
+ {
+ ULONG i;
+ ULONG j;
+
+ PUCHAR buffer = (PUCHAR)nth;
+
+ for (i = 0; i < dataLength; i += 16)
+ {
+ UCHAR numString[16 * 3 + 1];
+ UCHAR asciiBuffer[40];
+ UCHAR value = 0;
+ const char translateTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+ RtlZeroMemory(numString, sizeof(numString));
+ RtlZeroMemory(asciiBuffer, sizeof(asciiBuffer));
+
+ for (j = 0; j < 16; j++)
+ {
+ if (i + j >= dataLength)
+ {
+ //
+ // past the end, just put spaces
+ //
+ numString[j * 3] = ' ';
+ numString[j * 3 + 1] = ' ';
+ numString[j * 3 + 2] = ' ';
+ }
+ else
+ {
+ value = buffer[i + j];
+
+ numString[j * 3] = translateTable[value >> 4];
+ numString[j * 3 + 1] = translateTable[value & 0xf];
+ numString[j * 3 + 2] = ' ';
+
+ if ((buffer[i + j] >= 32) && (buffer[i + j] < 128))
+ {
+ asciiBuffer[j] = value;
+ }
+ else
+ {
+ asciiBuffer[j] = '.';
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ if ((receive = MbbRecvQQueueReceive(deviceContext, ReceiveContext, Mdl, (PUCHAR)nth)) == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ returnBuffer = FALSE;
+ receive->TotalNdpCount = ndpCount;
+
+ // Receive DSS, IPs will be received in EvtRxQueueAdvance
+ MbbRecvNtbParse(receive);
+ } while (FALSE);
+
+ if (returnBuffer)
+ {
+ if (receive != NULL)
+ {
+ MbbRecvCleanup(receive);
+ }
+ else
+ {
+ MbbBusReturnReceiveBuffer(deviceContext->BusHandle, ReceiveContext, Mdl);
+ }
+ }
+}
+
+void EvtRxQueueDestroy(_In_ WDFOBJECT RxQueue)
+{
+ PMBB_RXQUEUE_CONTEXT rxQueueContext = MbbGetRxQueueContext(RxQueue);
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = rxQueueContext->NetAdapterContext;
+ netAdapterContext->RxQueue = NULL;
+}
+
+VOID EvtRxQueueSetNotificationEnabled(_In_ NETPACKETQUEUE RxQueue, _In_ BOOLEAN NotificationEnabled)
+{
+ PMBB_RXQUEUE_CONTEXT txQueueContext = MbbGetRxQueueContext(RxQueue);
+ InterlockedExchange(&txQueueContext->NotificationEnabled, NotificationEnabled);
+}
+
+void EvtRxQueueAdvance(_In_ NETPACKETQUEUE RxQueue)
+{
+ PMBB_RXQUEUE_CONTEXT rxQueueContext = MbbGetRxQueueContext(RxQueue);
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = rxQueueContext->NetAdapterContext;
+ WDFSPINLOCK wdfRecvSpinLock = netAdapterContext->WmbDeviceContext->Sessions[netAdapterContext->SessionId].WdfRecvSpinLock;
+ PMBB_RECEIVE_NDP_CONTEXT receiveNdpContext;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ WdfSpinLockAcquire(wdfRecvSpinLock);
+ while (!IsListEmpty(&netAdapterContext->ReceiveNdpList))
+ {
+ receiveNdpContext = CONTAINING_RECORD(RemoveHeadList(&netAdapterContext->ReceiveNdpList), MBB_RECEIVE_NDP_CONTEXT, ReceiveNdpNode);
+ receiveNdpContext->ReceiveNdpNode.Flink = receiveNdpContext->ReceiveNdpNode.Blink = NULL;
+ WdfSpinLockRelease(wdfRecvSpinLock);
+
+ status = MbbRecvNdpUnpackIps(receiveNdpContext, rxQueueContext);
+ if (status == STATUS_BUFFER_OVERFLOW)
+ {
+ WdfSpinLockAcquire(wdfRecvSpinLock);
+ InsertHeadList(&netAdapterContext->ReceiveNdpList, &receiveNdpContext->ReceiveNdpNode);
+ break;
+ }
+ else
+ {
+ if (!NT_SUCCESS(status))
+ {
+ }
+ }
+
+ WdfSpinLockAcquire(wdfRecvSpinLock);
+ }
+ WdfSpinLockRelease(wdfRecvSpinLock);
+}
+
+void EvtRxQueueCancel(_In_ NETPACKETQUEUE RxQueue)
+{
+ PMBB_RXQUEUE_CONTEXT rxQueueContext = MbbGetRxQueueContext(RxQueue);
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = rxQueueContext->NetAdapterContext;
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = netAdapterContext->WmbDeviceContext;
+ NET_RING_COLLECTION const* rings = rxQueueContext->DatapathDescriptor;
+
+ NET_RING * pr = NetRingCollectionGetPacketRing(rings);
+
+ while (pr->BeginIndex != pr->EndIndex)
+ {
+ NET_PACKET * packet = NetRingGetPacketAtIndex(pr, pr->BeginIndex);
+ packet->Ignore = 1;
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+ }
+
+ NET_RING * fr = NetRingCollectionGetFragmentRing(rings);
+ fr->BeginIndex = fr->EndIndex;
+
+ // Cancel received Ndps which may be received after EvtRxQueueCancel started, these Ndps may never be processed by EvtRxQueueAdvance
+ MbbRecvCancelNdps(deviceContext, netAdapterContext->SessionId);
+}
+
+VOID EvtAdapterReturnRxBuffer(_In_ NETADAPTER Adapter, _In_ NET_FRAGMENT_RETURN_CONTEXT_HANDLE RxBufferReturnContext)
+{
+ PMBB_RECEIVE_NDP_CONTEXT receiveNdpContext = (PMBB_RECEIVE_NDP_CONTEXT)RxBufferReturnContext;
+ UNREFERENCED_PARAMETER(Adapter);
+ NT_ASSERT(receiveNdpContext->IndicatedPackets);
+
+ receiveNdpContext->IndicatedPackets--;
+ if ((receiveNdpContext->IndicatedPackets == 0) && (receiveNdpContext->ReceiveNdpNode.Blink == NULL) &&
+ (receiveNdpContext->ReceiveNdpNode.Flink == NULL))
+ {
+ MbbRecvReturnNdp(receiveNdpContext->ReceiveContext, receiveNdpContext);
+ }
+}