Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- C:\Program Files (x86)\Windows Kits\10\Include\10.0.10586.0\km\ndis.h got some updates:
- NDIS Version is now 6.51:
- Definitions with NDIS version numbers may use any of the following:
- Version First available in
- ------------------------------------------------------------------
- 651 Windows 10
- 650 Windows 10
- #if (NDIS_SUPPORT_NDIS651)
- #define NDIS_STATUS_WWAN_PRESHUTDOWN_STATE ((NDIS_STATUS)0x40041033L)
- #endif
- //
- // status codes used in NDIS 6.51
- //
- #if NDIS_SUPPORT_NDIS651
- #define NDIS_STATUS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE)
- #define NDIS_STATUS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE)
- #define NDIS_STATUS_DOT11_AP_CHANNEL_NOT_ALLOWED ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED)
- #define NDIS_STATUS_DOT11_AP_BAND_NOT_ALLOWED ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED)
- #endif
- #if (NDIS_SUPPORT_NDIS650)
- #pragma warning(push)
- #pragma warning(disable:4201) // (nonstandard extension used : nameless struct/union)
- #pragma warning(disable:4214) // (extension used : bit field types other than int)
- typedef struct _NDIS_PD_QUEUE NDIS_PD_QUEUE;
- DECLARE_HANDLE(NDIS_PD_COUNTER_HANDLE);
- DECLARE_HANDLE(NDIS_PD_FILTER_HANDLE);
- typedef PHYSICAL_ADDRESS DMA_LOGICAL_ADDRESS;
- typedef struct _PD_BUFFER_8021Q_INFO {
- UINT16 UserPriority:3;
- UINT16 CanonicalFormatId:1;
- UINT16 VlanId:12;
- } PD_BUFFER_8021Q_INFO;
- typedef struct _PD_BUFFER_VIRTUAL_SUBNET_INFO {
- UINT32 VirtualSubnetId:24;
- UINT32 Reserved:8;
- } PD_BUFFER_VIRTUAL_SUBNET_INFO;
- //
- // If an L2 packet is represented by multiple PD_BUFFERs, the first PD_BUFFER
- // must have the PD_BUFFER_FLAG_PARTIAL_PACKET_HEAD flag set and the
- // NextPartialPDBuffer field must point to the partial PD_BUFFERs that
- // constitute the whole packet. Each of the partial PD_BUFFERs must point to
- // the next partial PD_BUFFER by using the NextPartialPDBuffer as opposed to
- // the NextPDBuffer field which must be NULL in all partial PD_BUFFERs except
- // for the head buffer. All partial PD_BUFFERs except for the head buffer must
- // have the PD_BUFFER_FLAG_PARTIAL_PACKET_HEAD cleared. The last partial
- // PD_BUFFER must have its NextPartialPDBuffer field set to NULL. The total
- // length of the L2 packet is the sum of DataLength fields from each partial
- // PD_BUFFER. The head PD_BUFFER must contain up to and including the IP
- // transport (TCP, UDP, SCTP, etc) header. In the case of encap or double-encap,
- // the innermost IP transport header must be contained in the head PD_BUFFER.
- //
- #define PD_BUFFER_FLAG_PARTIAL_PACKET_HEAD 0x00000001
- //
- // A PD_BUFFER allocated with its own accompanying data buffer will have
- // this attribute set. PD_BUFFER attibutes must never be modified by PD clients
- // or PD providers.
- //
- #define PD_BUFFER_ATTR_BUILT_IN_DATA_BUFFER 0x00000001
- //
- // All PD_BUFFERs posted to an RX queue will have the DataStart field
- // set a value >= PD_BUFFER_MIN_RX_DATA_START_VALUE by the PD client.
- // While a PD_BUFFER is pending in an RX queue, PD provider can use the
- // portion of the data buffer between DataBufferDmaLogicalAddress and
- // (DataBufferDmaLogicalAddress + DataStart) for its own purpose. As soon as
- // a PD_BUFFER is drained by the PD client from the RX queue, PD client can
- // use the same portion of data buffer for its own purpose. A corollary of
- // this is that neither the PD client nor the PD provider can expect the
- // contents of this portion of the data buffer to be preserved as soon
- // as the control of the PD_BUFFER is transferred. A PD_BUFFER is under
- // the control of a PD provider when the PD_BUFFER is sitting in
- // a queue owned by that PD provider (i.e., posted to the queue, and has not
- // yet been drained out from the queue by the PD client). Otherwise, the
- // PD_BUFFER is under the control of the PD client.
- //
- #define PD_BUFFER_MIN_RX_DATA_START_VALUE 32
- //
- // All PD_BUFFERs posted to an RX queue will satisfy the following
- // alignment requirement:
- //
- // ((DataBufferDmaLogicalAddress + DataStart)
- // & (PD_BUFFER_MIN_RX_DATA_START_ALIGNMENT - 1)) == 0
- //
- #define PD_BUFFER_MIN_RX_DATA_START_ALIGNMENT 2
- //
- // All PD_BUFFERs posted to an TX queue will satisfy the following
- // alignment requirement:
- //
- // ((DataBufferDmaLogicalAddress + DataStart)
- // & (PD_BUFFER_MIN_TX_DATA_START_ALIGNMENT - 1)) == 0
- //
- #define PD_BUFFER_MIN_TX_DATA_START_ALIGNMENT 2
- //
- // PD_BUFFER structure represents a PD packet (or a portion of a PD packet).
- // The actual memory location which is used for storing the packet data is
- // indicated by the DataBufferDmaLogicalAdress and DataBufferVirtualAdress
- // fields. The former field represents the address which the PD provider
- // must use for DMA. The latter field represents the address which host
- // software can use to access/modify the packet contents.
- // The DataBufferDmaLogicalAdress is valid for *all* PD-capable NDIS miniport
- // adapters in the same IOMMU domain.
- //
- typedef struct _PD_BUFFER {
- struct _PD_BUFFER* NextPDBuffer;
- struct _PD_BUFFER* NextPartialPDBuffer;
- //
- // Reserved for PD client use. PD provider must never modify this field.
- //
- PVOID PDClientReserved;
- //
- // Neither PD client nor PD provider is allowed to modify this field.
- // If PD client has allocated the PD_BUFFER with a non-zero value for
- // ClientContextSize, PDClientContext refers to a buffer of size
- // ClientContextSize. Otherwise, this field is NULL.
- //
- _Field_size_bytes_(PDClientContextSize) PVOID PDClientContext;
- //
- // This field denotes the original virtual address of the allocated data
- // buffer. The actual packet data is always at
- // DataBufferVirtualAddress+DataStart. Neither the PD provider nor the
- // PD platform ever modify the value of this field after PD_BUFFER
- // initialization.
- //
- _Field_size_bytes_(DataBufferSize)
- PUCHAR DataBufferVirtualAddress;
- //
- // This field denotes the original DMA logical address of the allocated
- // data buffer. The actual packet data is always at
- // DataBufferDmaLogicalAddress+DataStart. Neither the PD provider nor the
- // PD platform ever modify the value of this field after PD_BUFFER
- // initialization.
- //
- _Field_size_bytes_(DataBufferSize)
- DMA_LOGICAL_ADDRESS DataBufferDmaLogicalAddress;
- //
- // This is the total size of the allocated data buffer. Neither the PD
- // provider nor the PD platform ever modify the value of this field
- // after PD_BUFFER initialization. This is a ULONG (as opposed to a
- // USHORT) mainly because of LSO.
- //
- ULONG DataBufferSize;
- //
- // If non-zero, this is the size of the buffer pointed by PDClientContext.
- // The value of this field must never be modified except by the PD platform.
- // The PD platform does NOT change the value of this field after PD_BUFFER
- // allocation/initialization.
- //
- USHORT PDClientContextSize;
- //
- // See PD_BUFFER_ATTR_XXX. Must never be modified by PD provider.
- //
- USHORT Attributes;
- //
- // See PD_BUFFER_FLAG_XXX
- //
- USHORT Flags;
- //
- // DataStart denotes where the packet starts relative to the original
- // starting address of the allocated data buffer. PD provider never
- // modifies this field. PD provider adds this value to the
- // DataBufferDmaLogicalAddress value in order to derive the actual
- // target DMA address for packet reception/transmission. I.e., the
- // target DMA address value in the hardware receive/transmit descriptor
- // must be set to DataBufferDmaLogicalAddress+DataStart when a PD_BUFFER
- // is posted to a receive/transmit queue.
- //
- USHORT DataStart;
- //
- // When posting PD_BUFFERs to receive queues, DataLength is ignored by
- // the PD provider (see ReceiveDataLength description in PD queue creation).
- // When draining completed PD_BUFFERs from receive queues,
- // the PD provider stores the length of the received packet in the
- // DataLength field. The length does not include FCS or any stripped 801Q
- // headers.
- // When posting PD_BUFFERs to transmit queues, DataLength denotes the length
- // of the packet to be sent. When draining completed PD_BUFFERs from
- // transmit queues, the PD provider leaves DataLength field unmodified.
- //
- ULONG DataLength;
- union {
- struct {
- union {
- //
- // PD provider sets this to the filter context value obtained
- // from the matched filter that steered the packet to the receive
- // queue. Filter context values are specified by the PD clients
- // when configuring filters.
- //
- ULONG64 RxFilterContext;
- //
- // If one of the RxGftxxx bits are set, RxFilterContext value may
- // be used for GFT flow entry Id value.
- //
- ULONG64 GftFlowEntryId;
- };
- //
- // The hash value computed for the incoming packet
- // that is steered to the receve queue via RSS.
- //
- ULONG RxHashValue;
- //
- // Commonly used RX offload fields
- //
- union {
- struct {
- ULONG RxIPHeaderChecksumSucceeded:1;
- ULONG RxTCPChecksumSucceeded:1;
- ULONG RxUDPChecksumSucceeded:1;
- ULONG RxIPHeaderChecksumFailed:1;
- ULONG RxTCPChecksumFailed:1;
- ULONG RxUDPChecksumFailed:1;
- ULONG RxHashComputed:1;
- ULONG RxHashWithL4PortNumbers:1;
- ULONG RxGftDirectionIngress:1;
- ULONG RxGftExceptionPacket:1;
- ULONG RxGftCopyPacket:1;
- ULONG RxGftSamplePacket:1;
- ULONG RxReserved1:4;
- ULONG RxCoalescedSegCount:16; // RSC
- ULONG RxRscTcpTimestampDelta; // RSC
- };
- ULONG RxOffloads[2];
- };
- //
- // Commonly used TX offload fields
- //
- union {
- struct {
- ULONG TxIsIPv4:1; // Checksum, LSO
- ULONG TxIsIPv6:1; // Checksum, LSO
- ULONG TxTransportHeaderOffset:10; // Checksum, LSO, NVGRE
- ULONG TxMSS:20; // LSO
- ULONG TxComputeIPHeaderChecksum:1;
- ULONG TxComputeTCPChecksum:1;
- ULONG TxComputeUDPChecksum:1;
- ULONG TxIsEncapsulatedPacket:1;
- ULONG TxInnerPacketOffsetsValid:1;
- ULONG TxReserved1:11;
- ULONG TxInnerFrameOffset:8;
- ULONG TxInnerIpHeaderRelativeOffset:6;
- ULONG TxInnerIsIPv6:1;
- ULONG TxInnerTcpOptionsPresent:1;
- };
- ULONG TxOffloads[2];
- };
- //
- // Other Meta Data
- //
- PD_BUFFER_VIRTUAL_SUBNET_INFO VirtualSubnetInfo;
- PD_BUFFER_8021Q_INFO Ieee8021qInfo;
- USHORT GftSourceVPortId;
- ULONG Reserved;
- //
- // A scratch field which the PD provider can use for its own
- // purposes while the PD_BUFFER is sitting in the provider
- // queue (i.e., posted by the client but not yet drained back
- // by the client). Once the PD_BUFFER is drained by the
- // client, there's no guarantee that the contents of this field
- // is going to be preserved.
- //
- UINT64 ProviderScratch;
- } MetaDataV0;
- };
- } PD_BUFFER;
- #pragma warning(pop)
- //
- // A NDIS_PD_QUEUE provides the following abstraction:
- // The queue is a circular array of N slots.
- // Overall state of the queue is tracked by 3 conceptual pointers: head (H),
- // tail (T), and completed (C). H points to the slot which contains the next
- // item that must be processed. T points to the slot which the next item
- // posted by the client must be placed into. If H == T, the queue is empty.
- // If H == (T+1)%N, the queue is full. Hence, the queue can hold at most N-1
- // items. That is, NDIS_PD_QUEUE_PARAMETERS.QueueSize is N-1.
- // C points to the slot which contains the earliest completed item
- // which has not yet been drained by the client. If C == H, the queue has no
- // items in completed state.
- // All slots are initially empty, that is, H, T, and C all point to the same
- // slot. All items posted to the queue should typically be processed and
- // completed by the provider in the order they were posted but the PD client
- // must not take a dependency on completions being strictly ordered. As the
- // queue progresses, it will always have 0 or more empty slots followed by 0
- // or more completed slots followed by 0 or more busy slots in a circular
- // fashion. A "completed slot" refers to a slot which contains a completed item.
- // Taking the simple case where no wrap-around has occured yet, C <= H <= T
- // will always hold. Factoring in wrap-around, the following formulas will
- // hold true at any point in time:
- // The number of busy slots : (T-H)%N
- // The number of completed slots : (H-C)%N
- // The number of empty slots : (C-T-1)%N
- //
- //
- // All of the NDIS_PD_QUEUE_DISPATCH routines are guaranteed to be invoked by
- // the caller in serialized fashion on the same PD queue. The implementation of
- // these routines MUST avoid acquiring any locks or performing interlocked
- // operations (since the caller is responsible for dealing with concurrency,
- // not the provider, hence the provider must not use any synchronization
- // routines/primitives; if there's any need for synchronization in the core
- // transmit/receive code path in the PD provider, we must know about it and
- // do whatever necessary to remove that need.)
- //
- //
- // PostAndDrain is the main data path function which allows posting PD_BUFFERs
- // to PD transmit/receive queues and draining any previously posted
- // PD buffers that have been completed. Provider removes buffers from the
- // PostBufferList and places them into the queue, starting with the head
- // buffer in the list and advancing to the next buffer until either the
- // PostBufferList gets empty or the queue is full (or near full).
- // Provider advances the PostListHead and returns the new list head to the
- // caller. Provider also removes any completed buffers from the queue and
- // inserts them to tail of the DrainBufferList and returns the new
- // DrainBufferList tail to the client. Note that the provider should drain
- // as many buffers as it can in order to open up room for the buffers being
- // posted. The PostBufferList and DrainBufferList are guaranteed to be disjoint
- // buffer lists (i.e., the PD client never provides the head of a buffer list
- // as the PostBufferListHead and the tail of that same list as
- // DrainBufferListTail). The provider must ensure that it never drains more than
- // MaxDrainCount packets (a set of partial PD_BUFFERs that make up a single
- // L2 packet count as 1). The PD client can pass an empty list via
- // PostBufferListHead in order to just drain completed buffers without posting
- // any new buffers. The PD client can pass 0 for MaxDrainCount in order to
- // just post new buffers without draining any completed buffers. In rare cases,
- // client may invoke the call with both an empty PostBufferList and 0 for
- // MaxDrainCount, so the provider must NOT assume otherwise, and handle such
- // a call properly (i.e., a no-op).
- //
- // An example code snippet illustrates the abundant pointer indirections
- // best:
- //
- // PD_BUFFER* PostHead = NULL;
- // PD_BUFFER** PostTail = &PostHead;
- // PD_BUFFER* DrainHead = NULL;
- // PD_BUFFER** DrainTail = &DrainHead;
- //
- // PD_BUFFER* bufX = <allocated PD_BUFFER>;
- //
- // bufX->NextPDBuffer = NULL;
- // *PostTail = bufX;
- // PostTail = &bufX->NextPDBuffer;
- //
- // // Assume 20 PD_BUFFERs are present in the Post list just like
- // // bufX. Assume bufY is the 10th buffer and bufZ is the last buffer
- // // in Post list. Assume there are many previously posted buffers in
- // // the Queue and 5 of them are currently completed: buf1, ..., buf5.
- // // Assume the provider is able to accept only 9 buffers from the Post
- // // list and drains all 5 of the completed buffers. With these
- // // assumptions, the state of the Post and Drain lists before and
- // // after the following call returns is:
- //
- // // BEFORE:
- // // PostHead == bufX
- // // PostTail == &bufZ->NextPDBuffer
- // // DrainHead == NULL
- // // DrainTail == &DrainHead
- //
- // NDIS_PD_POST_AND_DRAIN_BUFFER_LIST(
- // Queue,
- // &PostHead,
- // &DrainTail,
- // 32);
- //
- // // AFTER:
- // // PostHead == bufY
- // // PostTail == &bufZ->NextPDBuffer
- // // DrainHead == buf1
- // // DrainTail == &buf5->NextPDBuffer
- //
- typedef
- _IRQL_requires_min_(PASSIVE_LEVEL)
- _IRQL_requires_max_(DISPATCH_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_POST_AND_DRAIN_BUFFER_LIST)
- VOID
- (NDIS_PD_POST_AND_DRAIN_BUFFER_LIST)(
- _Inout_ NDIS_PD_QUEUE* Queue,
- _Inout_ PD_BUFFER** PostBufferListHead,
- _Inout_ PD_BUFFER*** DrainBufferListTail,
- _In_ ULONG MaxDrainCount
- );
- typedef NDIS_PD_POST_AND_DRAIN_BUFFER_LIST
- *NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_HANDLER;
- //
- // PostandDrainEx is exactly the same as PostandDrain with a few additional
- // output parameters:
- // *QueueDepthThresholdReached is set to TRUE by the provider if the queue
- // depth (as explained in the NDIS_PD_QUERY_QUEUE_DEPTH function) is below
- // the threshold value set by the client for a receive queue or is above
- // the threshold value set by the client for a transmit queue; otherwise,
- // PD provider sets it to FALSE.
- // *DrainCount is set to the number of PD_BUFFERs that the provider has
- // appended to the DrainBufferList. A set of partial PD_BUFFERs that
- // make up a single L2 packet is counted as 1.
- // *DrainCount is always <= MaxDrainCount.
- // *PostCount is set to the number of PD_BUFFERs that the provider has
- // removed from the PostbufferList. A set of partial PD_BUFFERs that
- // make up a single L2 packet is counted as 1.
- //
- typedef struct _NDIS_PD_POST_AND_DRAIN_ARG {
- _Inout_ PD_BUFFER* PostBufferListHead;
- _Inout_ PD_BUFFER** DrainBufferListTail;
- _In_ ULONG MaxDrainCount;
- _Out_ ULONG DrainCount;
- _Out_ ULONG PostCount;
- _Out_ BOOLEAN QueueDepthThresholdReached;
- } NDIS_PD_POST_AND_DRAIN_ARG;
- typedef
- _IRQL_requires_min_(PASSIVE_LEVEL)
- _IRQL_requires_max_(DISPATCH_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_EX)
- VOID
- (NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_EX)(
- _Inout_ NDIS_PD_QUEUE* Queue,
- _Inout_ NDIS_PD_POST_AND_DRAIN_ARG* Arg
- );
- typedef NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_EX
- *NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_EX_HANDLER;
- //
- // This routine ensures that any item that's not yet in completed state
- // in the queue will be completed imminently. The caller is responsible for
- // waiting for and draining all previously posted requests before closing
- // the queue. The caller must not post any further PD buffers to the queue
- // after this call (i.e., the queue is not usable for transmiting/receiving
- // packets any more via PD). The primary use case for this routine is flushing
- // the receive queues, i.e., if there's no incoming traffic, posted buffers
- // will sit in the receive queue indefinitely, but we need to drain the
- // queue before we can close it, hence we need to flush it first. The same
- // issue does not exist for transmit queues in practice since transmit requests
- // will not pend indefinitely, but providers must honor the flush call for
- // transmit queues as well anyway (which may be a no-op if the provider knows
- // that the pending transmit request will complete very soon anyway, which is
- // the typical case except for L2 flow control possibly).
- //
- typedef
- _IRQL_requires_min_(PASSIVE_LEVEL)
- _IRQL_requires_max_(DISPATCH_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_FLUSH_QUEUE)
- VOID
- (NDIS_PD_FLUSH_QUEUE)(
- _Inout_ NDIS_PD_QUEUE* Queue
- );
- typedef NDIS_PD_FLUSH_QUEUE *NDIS_PD_FLUSH_QUEUE_HANDLER;
- //
- // Queue depth query returns the number of PD_PACKETs that are posted
- // to a NDIS_PD_QUEUE but are not yet being processed by the provider.
- // On a receive queue, this is the number of PD_BUFFERs that are available
- // for placing incoming packets into. If 10 buffers were posted, and 3 of
- // them have already been fetched by the provider for DMA'ing incoming
- // packets into, the query should return 7 (not 10). On a transmit queue,
- // this is the number of PD_BUFFERs which the provider has not yet fetched
- // from the queue for transmitting.
- // Ability to monitor the queue depth is very important for
- // PD clients in order to assess congestion build-up and take precautionary
- // action. An increasing queue depth for a TX queue is a sign of increasing
- // congestion on the outbound link. A decreasing queue depth for a RX queue
- // is a sign of the PD client not being able to process incoming packets
- // fast enough on the inbound link. PD clients may need to monitor the
- // queue depth status in a very fine grain fashion (i.e., find out if the queue
- // depth has reached a certain level during each Post-And-Operation). Such PD
- // clients use the PostAndDrainEx call. PD clients may also need to query the
- // actual queue depth (in contrast to whether the queue depth is above or below
- // a certain level) as well, which the NDIS_PD_QUERY_QUEUE_DEPTH function is
- // for. Performance of PostAndDrainEx implementation is very critical for PD
- // clients. NDIS_PD_QUERY_QUEUE_DEPTH, while also very important, is not
- // expected to be used by the PD clients with the same frequency as the
- // PostAndDrain or PostAndDrainEx operations, hence it is acceptable for
- // NDIS_PD_QUERY_QUEUE_DEPTH to be more expensive in exchange for returning the
- // actual queue depth (in contrast to whether or not queue depth is above/below
- // a given threshold). Note that it is understood by PD clients that the
- // actual queue depth in the hw may have already changed and the returned queue
- // depth may not precisely reflect it. As long as there isn't a too large lag
- // between the real and returned queue depths and the lag itself is reasonably
- // stable (for a stable incoming traffic rate), this information is still useful
- // for the PD clients.
- //
- typedef
- _IRQL_requires_min_(PASSIVE_LEVEL)
- _IRQL_requires_max_(DISPATCH_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_QUERY_QUEUE_DEPTH)
- VOID
- (NDIS_PD_QUERY_QUEUE_DEPTH)(
- _In_ CONST NDIS_PD_QUEUE* Queue,
- _Out_ ULONG64* Depth
- );
- typedef NDIS_PD_QUERY_QUEUE_DEPTH *NDIS_PD_QUERY_QUEUE_DEPTH_HANDLER;
- typedef struct _NDIS_PD_QUEUE_DISPATCH {
- //
- // Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
- // Header.Revision = NDIS_PD_QUEUE_DISPATCH_REVISION_1;
- // Header.Size >= NDIS_SIZEOF_PD_QUEUE_DISPATCH_REVISION_1;
- //
- NDIS_OBJECT_HEADER Header;
- ULONG Flags; // Reserved. Must be set to 0.
- NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_HANDLER PDPostAndDrainBufferList;
- NDIS_PD_QUERY_QUEUE_DEPTH_HANDLER PDQueryQueueDepth;
- NDIS_PD_FLUSH_QUEUE_HANDLER PDFlushQueue;
- NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_EX_HANDLER PDPostAndDrainBufferListEx;
- } NDIS_PD_QUEUE_DISPATCH;
- #define NDIS_PD_QUEUE_DISPATCH_REVISION_1 1
- #define NDIS_SIZEOF_PD_QUEUE_DISPATCH_REVISION_1 \
- RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_QUEUE_DISPATCH, PDPostAndDrainBufferListEx)
- typedef struct _NDIS_PD_QUEUE {
- //
- // Header.Type = NDIS_OBJECT_TYPE_PD_TRANSMIT_QUEUE or NDIS_OBJECT_TYPE_PD_RECEIVE_QUEUE;
- // Header.Revision = NDIS_PD_QUEUE_REVISION_1;
- // Header.Size >= NDIS_SIZEOF_PD_QUEUE_REVISION_1;
- //
- NDIS_OBJECT_HEADER Header;
- ULONG Flags; // Reserved. Must be set to 0.
- CONST NDIS_PD_QUEUE_DISPATCH* Dispatch;
- PVOID PDPlatformReserved[2];
- PVOID PDClientReserved[2];
- } NDIS_PD_QUEUE;
- #define NDIS_PD_QUEUE_REVISION_1 1
- #define NDIS_SIZEOF_PD_QUEUE_REVISION_1 \
- RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_QUEUE, PDClientReserved)
- //
- // PD and NIC SWITCH COEXISTENCE:
- // Unless otherwise is explicitly noted for a specific PD OID, all
- // PD OID requests are VPort specific when there's a NIC switch. That is,
- // PD queues are created, PD filters are set, PD counters are created all
- // per Vport. When there's no NIC switch, PD client uses NDIS_DEFAULT_VPORT_ID,
- // which must be handled by the PD provider as if the scope of the
- // OID request is the whole miniport adapter.
- //
- typedef enum {
- PDQueueTypeUnknown,
- PDQueueTypeReceive,
- PDQueueTypeTransmit,
- PDQueueTypeMax
- } NDIS_PD_QUEUE_TYPE;
- //
- // QueueSize is the maximum number of PD_BUFFERs that can be posted to the
- // queue and it is always equal to a number of the form (2^K)-1 (e.g., 63,
- // 127, 255, 511, 1023, etc). This lends itself to efficient circular index
- // arithmetic (i.e., can use "&" as opposed to "%" for index wrap-around).
- //
- // For receive queues, ReceiveDataLength denotes the minimum length of
- // the data buffers that will be posted to the receive queue, i.e.,
- // (PD_BUFFER.DataBufferSize - PD_BUFFER.DataStart) >= ReceiveDataLength for
- // all PD_BUFFERs posted to the receive queue.
- //
- // Affinity is a hint to PD provider for performance optimization. PD platform
- // will primarily be processing the queue on procs indicated by the Affinity
- // mask. But, note that this is NOT a strict requirement on the PD platform.
- // Hence the PD provider must NOT use the Affinity info for anything other
- // than performance optimization. For example, PD provider should use the
- // Affinity for direct access to the proper cache for packet DMA, if supported
- // by the underlying hardware platform.
- //
- //
- // If this flag is set in the NDIS_PD_QUEUE_PARAMETERS Flags field, the provider
- // must be prepared to handle drain notification requests from the PD client
- // on the particular queue being allocated. This flag is valid for both RX and
- // TX queues. After the PD client requests a drain notification, it must issue
- // another PDPostAndDrainBufferList before waiting for a notification. This
- // drain request right after the arm request ensures that any items that might
- // have been completed after the previous PDPostAndDrainBufferList request but
- // right before the arm request are drained back by the client before starting
- // to wait for a notification which may never come unless new items are
- // completed. This "poll/arm/poll" model removes the synchronization burden
- // from the provider and puts it in the PD client/platform.
- //
- #define NDIS_PD_QUEUE_FLAG_DRAIN_NOTIFICATION 0x00000001
- //
- // A PD provider sets this value in the NDIS_PD_QUEUE_PARAMETERS TrafficClassId
- // field when returning a PD Rx queue via NdisPDAcquireReceiveQueues if the
- // PD provider can handle multiple traffic classes via a single Rx queue for
- // a given RSS target processor.
- //
- #define NDIS_PD_INVALID_TRAFFIC_CLASS_ID ((ULONG)-1)
- typedef struct DECLSPEC_ALIGN(8) _NDIS_PD_QUEUE_PARAMETERS {
- //
- // Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
- // Header.Revision = NDIS_PD_QUEUE_PARAMETERS_REVISION_1;
- // Header.Size >= NDIS_SIZEOF_PD_QUEUE_PARAMETERS_REVISION_1;
- //
- NDIS_OBJECT_HEADER Header;
- ULONG Flags;
- NDIS_PD_QUEUE_TYPE QueueType; // transmit or receive
- ULONG QueueSize; // 2^K-1
- ULONG ReceiveDataLength; // min PD_BUFFER data length
- GROUP_AFFINITY Affinity;
- //
- // TrafficClassId (as defined in NDIS_QOS_PARAMETERS) for the PD queue.
- //
- ULONG TrafficClassId;
- //
- // For transmit queues, this is the maximum number of partial PD_BUFFERs
- // that the client is allowed to chain together to form a single L2 packet.
- // This must be less than or equal to the MaximumTxPartialBufferCount value
- // in NDIS_PD_CAPABILITIES.
- //
- // For receive queues, this is the maximum number of partial PD_BUFFERs
- // that the provider is allowed to chain together to form a single
- // large L2 packet with RSC. This must be less than or equal to the
- // MaximumRxPartialBufferCount value in NDIS_PD_CAPABILITIES.
- // Note that PD client never posts PD_BUFFERs with the partial flag to the
- // receive queue. PD client is always required to post PD_BUFFERs with at
- // least MTU-size space (starting from the DataStart position). Provider
- // performs chaining only in the case of RSC. Some providers may not be
- // able to support RSC chaining. Such providers advertize a value of 1
- // via MaximumRxPartialBufferCount in NDIS_PD_CAPABILITIES.
- // If a PD client wants to still use RSC over such a provider, PD client
- // must post large enough PD_BUFFERs.
- //
- ULONG MaximumPartialBufferCount;
- //
- // During PD queue creation, PD client can optionally provide a counter
- // handle. If a counter handle is provided, depending on the queue type,
- // PD provider must update the counter values as activity occurs on the
- // PD queue. This is a handle to a PD transmit queue counter for transmit
- // queues and PD receive queue counter for receive queues. PD client is
- // responsible for closing the counter handle only after the PD queue is
- // closed.
- //
- // For PD queues obtained via NDIS_PD_ACQUIRE_RECEIVE_QUEUES,
- // PD provider MUST return a dedicated PD receive queue counter
- // for each returned receive queue.
- //
- NDIS_PD_COUNTER_HANDLE CounterHandle;
- } NDIS_PD_QUEUE_PARAMETERS;
- #define NDIS_PD_QUEUE_PARAMETERS_REVISION_1 1
- #define NDIS_SIZEOF_PD_QUEUE_PARAMETERS_REVISION_1 \
- RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_QUEUE_PARAMETERS, CounterHandle)
- //
- // If this flag is set in the NDIS_PD_ACQUIRE_QUEUES_PARAMETERS Flags field, the
- // provider must be prepared to handle drain notification requests from the PD
- // client on each of the individual RX queues returned.
- //
- #define NDIS_PD_ACQUIRE_QUEUES_FLAG_DRAIN_NOTIFICATION 0x00000001
- typedef struct DECLSPEC_ALIGN(8) _NDIS_PD_ACQUIRE_QUEUES_PARAMETERS {
- //
- // Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
- // Header.Revision = NDIS_PD_ACQUIRE_QUEUES_PARAMETERS_REVISION_1;
- // Header.Size >= NDIS_SIZEOF_PD_ACQUIRE_QUEUES_PARAMETERS_REVISION_1;
- //
- NDIS_OBJECT_HEADER Header;
- ULONG Flags;
- } NDIS_PD_ACQUIRE_QUEUES_PARAMETERS;
- #define NDIS_PD_ACQUIRE_QUEUES_PARAMETERS_REVISION_1 1
- #define NDIS_SIZEOF_PD_ACQUIRE_QUEUES_PARAMETERS_REVISION_1 \
- RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_ACQUIRE_QUEUES_PARAMETERS, Flags)
- typedef enum {
- PDCounterTypeUnknown,
- PDCounterTypeReceiveQueue,
- PDCounterTypeTransmitQueue,
- PDCounterTypeReceiveFilter,
- PDCounterTypeMax
- } NDIS_PD_COUNTER_TYPE;
- typedef struct _NDIS_PD_RECEIVE_QUEUE_COUNTER {
- ULONG64 PacketsReceived;
- ULONG64 BytesReceived;
- ULONG64 PacketsDropped;
- } NDIS_PD_RECEIVE_QUEUE_COUNTER;
- typedef struct _NDIS_PD_TRANSMIT_QUEUE_COUNTER {
- ULONG64 PacketsTransmitted;
- ULONG64 BytesTransmitted;
- } NDIS_PD_TRANSMIT_QUEUE_COUNTER;
- typedef struct _NDIS_PD_FILTER_COUNTER {
- ULONG64 PacketsMatched;
- ULONG64 BytesMatched;
- } NDIS_PD_FILTER_COUNTER;
- typedef union _NDIS_PD_COUNTER_VALUE {
- NDIS_PD_RECEIVE_QUEUE_COUNTER ReceiveQueue;
- NDIS_PD_TRANSMIT_QUEUE_COUNTER TransmitQueue;
- NDIS_PD_FILTER_COUNTER Filter;
- } NDIS_PD_COUNTER_VALUE, *PNDIS_PD_COUNTER_VALUE;
- typedef struct _NDIS_PD_COUNTER_PARAMETERS {
- //
- // Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
- // Header.Revision = NDIS_PD_COUNTER_PARAMETERS_REVISION_1;
- // Header.Size >= NDIS_SIZEOF_PD_COUNTER_PARAMETERS_REVISION_1;
- //
- NDIS_OBJECT_HEADER Header;
- ULONG Flags; // Reserved. Must be set to 0 by client, ignored by provider
- //
- // CounterName is ignored by the PD provider. It is used by the PD platform
- // for publishing the counter to Windows Performance Counter subsystem (so
- // that the counter can be viewed via PerfMon and accessed by system APIs
- // programmatically).
- //
- PCWSTR CounterName;
- NDIS_PD_COUNTER_TYPE Type;
- } NDIS_PD_COUNTER_PARAMETERS;
- #define NDIS_PD_COUNTER_PARAMETERS_REVISION_1 1
- #define NDIS_SIZEOF_PD_COUNTER_PARAMETERS_REVISION_1 \
- RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_COUNTER_PARAMETERS, Type)
- typedef struct DECLSPEC_ALIGN(8) _NDIS_PD_FILTER_PARAMETERS {
- //
- // Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
- // Header.Revision = NDIS_PD_FILTER_PARAMETERS_REVISION_1;
- // Header.Size >= NDIS_SIZEOF_PD_FILTER_PARAMETERS_REVISION_1;
- //
- NDIS_OBJECT_HEADER Header;
- ULONG Flags; // Reserved. Must be set to 0 by client, ignored by provider
- NDIS_GFP_PROFILE_ID MatchProfileId;
- ULONG Priority;
- NDIS_PD_COUNTER_HANDLE CounterHandle;
- NDIS_PD_QUEUE* TargetReceiveQueue;
- ULONG64 RxFilterContext;
- //
- // The following fields are used to describe an array of either
- // NDIS_GFP_HEADER_GROUP_EXACT_MATCH or NDIS_GFP_HEADER_GROUP_WILDCARD_MATCH
- // structures (determined by the MatchProfileId)
- //
- _Field_size_bytes_(HeaderGroupMatchArrayTotalSize)
- PUCHAR HeaderGroupMatchArray; // must be 8-byte aligned
- _Field_range_(0, MAXULONG/HeaderGroupMatchArrayElementSize)
- ULONG HeaderGroupMatchArrayNumElements;
- ULONG HeaderGroupMatchArrayElementSize;
- _Field_range_((HeaderGroupMatchArrayNumElements*HeaderGroupMatchArrayElementSize), MAXULONG)
- ULONG HeaderGroupMatchArrayTotalSize;
- } NDIS_PD_FILTER_PARAMETERS;
- #define NDIS_PD_FILTER_PARAMETERS_REVISION_1 1
- #define NDIS_SIZEOF_PD_FILTER_PARAMETERS_REVISION_1 \
- RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_FILTER_PARAMETERS, HeaderGroupMatchArrayTotalSize)
- DECLARE_HANDLE(NDIS_PD_PROVIDER_HANDLE);
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- _At_(*NdisPDQueue, __drv_allocatesMem(Mem))
- _Function_class_(NDIS_PD_ALLOCATE_QUEUE)
- NTSTATUS
- (NDIS_PD_ALLOCATE_QUEUE)(
- _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle,
- _In_ CONST NDIS_PD_QUEUE_PARAMETERS* QueueParameters,
- _Outptr_ NDIS_PD_QUEUE** NdisPDQueue
- );
- typedef NDIS_PD_ALLOCATE_QUEUE *NDIS_PD_ALLOCATE_QUEUE_HANDLER;
- //
- // Caller is responsible for ensuring that the PD queue is empty before
- // issuing this call. Caller is also responsible for clearing all filters
- // that target this queue before closing the queue.
- //
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_FREE_QUEUE)
- VOID
- (NDIS_PD_FREE_QUEUE)(
- _In_ __drv_freesMem(Mem) NDIS_PD_QUEUE* NdisPDQueue
- );
- typedef NDIS_PD_FREE_QUEUE *NDIS_PD_FREE_QUEUE_HANDLER;
- //
- // This function allows a PD client to obtain
- // PD-mode access to the NDIS receive queues. While in PD-mode,
- // PD client uses the PD-post-and-drain API on the receive
- // queues, and the PD provider stops indicating receive NBLs via the existing
- // NDIS receive data path.
- // Once PD client gets the list of NDIS_PD_QUEUE objects representing the NDIS
- // receive queues, PD client typically decides which processor core to use
- // for draining each individual receive queue. PD client uses the
- // NDIS_PD_QUEUE_PARAMETERS.Affinity parameter returned by the provider for
- // this purpose. PD provider must set NDIS_PD_QUEUE_PARAMETERS.Affinity to the
- // processor core derived from the indirection table configured via
- // OID_GEN_RECEIVE_SCALE_PARAMETERS.
- // Note that the TX path is completely independent irrespective of whether
- // a PD client is using PD on the receive queues or not. I.e., Miniport
- // adapter must handle MiniportSendNetBufferLists/MiniportReturnNetBufferLists
- // as usual even when a PD client puts the NDIS receive queues into PD-mode.
- // PD client creates PD transmit queues for sending packets via PD. So,
- // while PD client is sending PD_BUFFERs over PD transmit queues, existing
- // NDIS protocol drivers or LWFs may also send packets via usual NDIS NBL APIs
- // on the same miniport adapter.
- //
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_ACQUIRE_RECEIVE_QUEUES)
- NTSTATUS
- (NDIS_PD_ACQUIRE_RECEIVE_QUEUES)(
- _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle,
- _In_ CONST NDIS_PD_ACQUIRE_QUEUES_PARAMETERS* Parameters,
- _Out_writes_to_(*QueueCount, *QueueCount) NDIS_PD_QUEUE** NdisPDQueueArray,
- _Inout_ ULONG* QueueCount,
- _Out_writes_bytes_to_(*QueueParametersArraySize, *QueueParametersArraySize)
- NDIS_PD_QUEUE_PARAMETERS* QueueParametersArray,
- _Inout_ ULONG* QueueParametersArraySize,
- _Out_ ULONG* QueueParametersArrayElementSize
- );
- typedef NDIS_PD_ACQUIRE_RECEIVE_QUEUES *NDIS_PD_ACQUIRE_RECEIVE_QUEUES_HANDLER;
- //
- // This function allows a PD client to stop using PD over
- // NDIS receive queues previosuly acquired via NDIS_PD_ACQUIRE_RECEIVE_QUEUES,
- // and instruct the PD provider to go back to the NBL-based NDIS receive data
- // path operation. PD client will invoke this function only after all pending
- // PD buffers are completed and drained (i.e., the receive queue is empty).
- // PD client does this by issuing a PDFlush request and then drain all pending
- // PD buffers until no pending buffers are left. Note that the PD client may
- // invoke NDIS_PD_ACQUIRE_RECEIVE_QUEUES again in the future to acquire PD-mode
- // access to the NDIS receive queues again.
- //
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_RELEASE_RECEIVE_QUEUES)
- VOID
- (NDIS_PD_RELEASE_RECEIVE_QUEUES)(
- _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle
- );
- typedef NDIS_PD_RELEASE_RECEIVE_QUEUES *NDIS_PD_RELEASE_RECEIVE_QUEUES_HANDLER;
- //
- // This function allows the PD client to allocate a counter object.
- // Receive queue counters are used for tracking receive queue activity.
- // Transmit queue counters are used for tracking transmit queue activity.
- // Filter counters are used for tracking filter match activity.
- // Same counter object (of a given type) can be associated with multiple
- // queue or filter objects. E.g., use receive counter RC1 for receive queues
- // RQ1, RQ2, RQ3, and receive counter RC2 for receive queues RQ4 and RQ5.
- //
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- _At_(*CounterHandle, __drv_allocatesMem(Mem))
- _Function_class_(NDIS_PD_ALLOCATE_COUNTER)
- NTSTATUS
- (NDIS_PD_ALLOCATE_COUNTER)(
- _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle,
- _In_ CONST NDIS_PD_COUNTER_PARAMETERS* CounterParameters,
- _Out_ NDIS_PD_COUNTER_HANDLE* CounterHandle
- );
- typedef NDIS_PD_ALLOCATE_COUNTER *NDIS_PD_ALLOCATE_COUNTER_HANDLER;
- //
- // PD client frees a counter only after closing
- // the object it's associated with, i.e., first close all the queues which
- // counter C1 was associated with, and then free counter C1.
- //
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- VOID
- _Function_class_(NDIS_PD_FREE_COUNTER)
- (NDIS_PD_FREE_COUNTER)(
- _In_ __drv_freesMem(Mem) NDIS_PD_COUNTER_HANDLE CounterHandle
- );
- typedef NDIS_PD_FREE_COUNTER *NDIS_PD_FREE_COUNTER_HANDLER;
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_QUERY_COUNTER)
- VOID
- (NDIS_PD_QUERY_COUNTER)(
- _In_ NDIS_PD_COUNTER_HANDLE CounterHandle,
- _Out_ NDIS_PD_COUNTER_VALUE* CounterValue
- );
- typedef NDIS_PD_QUERY_COUNTER *NDIS_PD_QUERY_COUNTER_HANDLER;
- //
- // This function is used for directing specific flows of packets
- // to a specific PD receive queue. PD filters are applied before any spreading
- // takes place. Hence, packet matching a PD filter can be placed into their
- // dedicated PD queue, and rest of the packets can be spread via RSS as usual.
- // The rules for plumbing filters is the same as GFT flows, i.e., the PD client
- // is responsible for plumbing non-overlapping disambiguous filters ultimately.
- // However, some PD providers may allow overlapping filters as long as the PD
- // client can pass a Priority value that indicates which filter must be applied
- // first. PD provider may fail filter set requests with
- // STATUS_NOT_SUPPORTED if the client attemtps to set filters with
- // conflicting profiles or overlapping match conditions. NDIS_PD_CAPABILITIES
- // structure does not allow the provider to advertise all valid combinations
- // of profiles that the PD client can use simultaneously. Hence, some of
- // the capabilities are discovered by the PD client at runtime when/if the PD
- // provider fails the filter set request with STATUS_NDIS_NOT_SUPPORTED.
- //
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- _At_(*FilterHandle, __drv_allocatesMem(Mem))
- _Function_class_(NDIS_PD_SET_RECEIVE_FILTER)
- NTSTATUS
- (NDIS_PD_SET_RECEIVE_FILTER)(
- _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle,
- _In_ CONST NDIS_PD_FILTER_PARAMETERS* FilterParameters,
- _Out_ NDIS_PD_FILTER_HANDLE* FilterHandle
- );
- typedef NDIS_PD_SET_RECEIVE_FILTER *NDIS_PD_SET_RECEIVE_FILTER_HANDLER;
- //
- // After this function returns, it's
- // guaranteed that no more newly arriving packet will match this filter.
- // However, there may still be in-flight packets that have already matched this
- // filter and they are on their way to being placed into the target receive
- // queue (but they are not placed yet).
- //
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_CLEAR_RECEIVE_FILTER)
- VOID
- (NDIS_PD_CLEAR_RECEIVE_FILTER)(
- _In_ __drv_freesMem(Mem) NDIS_PD_FILTER_HANDLE FilterHandle
- );
- typedef NDIS_PD_CLEAR_RECEIVE_FILTER *NDIS_PD_CLEAR_RECEIVE_FILTER_HANDLER;
- //
- // This function is used for arming a PD queue for getting a notification
- // upon PD_BUFFER completion.
- //
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_REQUEST_DRAIN_NOTIFICATION)
- VOID
- (NDIS_PD_REQUEST_DRAIN_NOTIFICATION)(
- _Inout_ NDIS_PD_QUEUE* NdisPDQueue
- );
- typedef NDIS_PD_REQUEST_DRAIN_NOTIFICATION *NDIS_PD_REQUEST_DRAIN_NOTIFICATION_HANDLER;
- //
- // NDIS_PD_QUEUE_CONTROL is primarily used for setting and/or querying various
- // queue properties. This is a synchronous routine called at PASSIVE_LEVEL, but
- // PD provider must avoid blocking/waiting within this call since this call
- // can be invoked by the PD clients from their primary packet processing loop
- // and any stall/wait within this function can degrade performance.
- // See the individual ControlCodes and the associated in/out buffer definitions
- // for specific operations.
- // PD platform/clients invoke this function always in serialized fashion over
- // a given NDIS_PD_QUEUE. But serilization relative to data path operations
- // is NOT guaranteed. For example, client may set a NdisPDQCTLModerationInterval
- // request on one thread while another thread may be issuing post&drain
- // and arm requests on the queue.
- // PD provider must return STATUS_NOT_SUPPORTED for a ControlType/ControlCode
- // combination that is not recognized/supported by the provider.
- // STATUS_PENDING is an illegal return value from this function.
- // PD platform validates the buffer sizes and the ControlTypes for all
- // currently defined ControlCodes before passing the request to the provider.
- //
- typedef enum {
- //
- // INPUT to the PD provider, No OUTPUT from the PD provider
- //
- NdisPDCTL_IN,
- //
- // OUTPUT from the PD provider, no INPUT to the PD provider
- //
- NdisPDCTL_OUT,
- //
- // INPUT to the PD provider and OUTPUT from the PD provider
- //
- NdisPDCTL_INOUT,
- } NDIS_PD_CONTROL_TYPE;
- typedef enum {
- NdisPDQCTLUnknown,
- //
- // Type: NdisPDCTL_IN
- // InBuffer: ULONG (QueueDepthThreshold)
- // InBufferSize: sizeof(ULONG)
- //
- // QueueDepthThreshold can be set by PD clients on PD queues at any
- // point, but never concurrently with a PostAndDrainEx call on the same
- // PD queue. As long as the queue depth of a receive queue is below the
- // threshold value, PD provider must set *QueueDepthThresholdReached
- // to TRUE before returning from PostAndDrainEx. As long as the queue
- // depth of a transmit queue is above the threshold value, PD provider
- // must set *QueueDepthThresholdReached to TRUE before returning from
- // PostAndDrainEx. Otherwise, PD client must set *QueueDepthThresholdReached
- // to FALSE before returning from PostAndDrainEx.
- // The default value for QueueDepthThreshold is MAXULONG for a transmit
- // queue, and 0 for a receive queue. That is, PD provider simply sets
- // *QueueDepthThresholdReached to FALSE if NdisPDQCTLQueueDepthThreshold
- // has never been issued on the queue.
- //
- NdisPDQCTLQueueDepthThreshold,
- //
- // Type: NdisPDCTL_IN
- // InBuffer: ULONG (ModerationInterval)
- // InBufferSize: sizeof(ULONG)
- //
- // Used for setting a notification ModerationInterval value on a given PD
- // queue. ModerationInterval is the maximum number of nanoseconds that a
- // provider can defer interrupting the host CPU after an armed PD queue
- // goes into drainable state. If ModerationInterval is zero (which is the
- // default value for any arm-able PD queue), the provider performs no
- // interrupt moderation on the PD queue. If ModerationInterval is larger
- // than the maximum moderation interval that the PD provider supports or
- // if the PD provider's timer granularity is larger, the PD provider can
- // round down the interval value. PD provider advertises the minimum and
- // the maximum values as well as the granularity of the intermediate values
- // it can support for ModerationInterval via the NDIS_PD_CAPABILITIES
- // structure. If NDIS_PD_CAPS_NOTIFICATION_MODERATION_INTERVAL_SUPPORTED is
- // NOT advertised by the PD provider, PD client will not set any
- // ModerationInterval value.
- //
- NdisPDQCTLModerationInterval,
- //
- // Type: NdisPDCTL_IN
- // InBuffer: ULONG (ModerationCount)
- // InBufferSize: sizeof(ULONG)
- //
- // Used for setting a notification ModerationCount value on a given PD
- // queue. ModerationCount is the maximum number of drainable PD_BUFFERs
- // that a provider can accumulate in an armed PD queue before interrupting
- // the host CPU to satisfy a drain notification request. If ModerationCount
- // is zero or one, the provider performs no interrupt moderation on the PD
- // queue regardless of the value of the ModerationInterval property.
- // If ModerationCount is MAXULONG or larger than the size of the PD queue,
- // ModerationInterval alone controls the interrupt moderation on the PD queue.
- // If NDIS_PD_CAPS_NOTIFICATION_MODERATION_COUNT_SUPPORTED is NOT
- // advertised by the PD provider, PD client will not set any ModerationCount
- // value. The default value for ModerationCount is MAXULONG.
- //
- NdisPDQCTLModerationCount,
- //
- // Type: NdisPDCTL_IN
- // InBuffer: ULONG (NotificationGroupId)
- // InBufferSize: sizeof(ULONG)
- //
- // Used for setting a notification group id on an arm-able PD queue.
- // By default, each PD queue upon allocation (via NDIS_PD_ALLOCATE_QUEUE
- // or NDIS_PD_ACQUIRE_RECEIVE_QUEUES) has NO notification group id. PD
- // clients can set a notification group id on an arm-able PD queue
- // before calling NDIS_PD_REQUEST_DRAIN_NOTIFICATION for the first
- // time. Once NDIS_PD_REQUEST_DRAIN_NOTIFICATION is called, the
- // notification group id for a PD queue cannot be changed.
- // See NdisMTriggerPDDrainNotification for how PD providers can use
- // notification group information for optimizing drain notifications.
- //
- NdisPDQCTLNotificationGroupId,
- //
- // Type: NdisPDCTL_IN
- // InBuffer: NDIS_QOS_SQ_ID
- // InBufferSize: sizeof(NDIS_QOS_SQ_ID)
- //
- // Used for setting a QoS scheduler queue Id on a given PD queue.
- //
- NdisPDQCTLSchedulerQueueId,
- NdisPDQCTLMax
- } NDIS_PD_QUEUE_CONTROL_CODE;
- //
- // The default NotificationGroupId value for a given PD queue, which means
- // that the PD queue is NOT part of any notification group.
- //
- #define NDIS_PD_NOTIFICATION_GROUP_ID_NONE ((ULONG)0)
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_QUEUE_CONTROL)
- NTSTATUS
- (NDIS_PD_QUEUE_CONTROL)(
- _Inout_ NDIS_PD_QUEUE* NdisPDQueue,
- _In_ NDIS_PD_CONTROL_TYPE ControlType,
- _In_ NDIS_PD_QUEUE_CONTROL_CODE ControlCode,
- _In_reads_bytes_opt_(InBufferSize) PVOID InBuffer,
- _In_ ULONG InBufferSize,
- _Out_writes_bytes_to_opt_(OutBufferSize, *BytesReturned) PVOID OutBuffer,
- _In_ ULONG OutBufferSize,
- _Out_opt_ ULONG* BytesReturned
- );
- typedef NDIS_PD_QUEUE_CONTROL *NDIS_PD_QUEUE_CONTROL_HANDLER;
- typedef enum {
- NdisPDPCTLUnknown,
- //
- // Type: NdisPDCTL_OUT
- // OutBuffer: A variable length flat buffer which the provider stores a
- // NDIS_PD_CAPABILITIES structure followed by a variable
- // number of elements pointed by certain offset fields in the
- // returned NDIS_PD_CAPABILITIES structure.
- // OutBufferSize: length of the buffer passed via OutBuffer parameter
- // *BytesReturned: Upon an NT_SUCCESS() return, this reflects the
- // actual number of bytes written into OutBuffer.
- // If OutBufferSize is not large enough to hold all the
- // bytes that the PD provider needs to write, then the
- // provider stores the actual size needed in *BytesReturned
- // and returns STATUS_BUFFER_TOO_SMALL.
- //
- NdisPDPCTLCapabilities,
- NdisPDPCTLMax
- } NDIS_PD_PROVIDER_CONTROL_CODE;
- //
- // PD providers must return STATUS_NOT_SUPPORTED for provider control codes
- // that they do not recognize or support. NdisPDPCTLCapabilities is the only
- // defined control code currently, and support for it is optional.
- //
- typedef
- _IRQL_requires_(PASSIVE_LEVEL)
- _IRQL_requires_same_
- _Function_class_(NDIS_PD_PROVIDER_CONTROL)
- NTSTATUS
- (NDIS_PD_PROVIDER_CONTROL)(
- _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle,
- _In_ NDIS_PD_CONTROL_TYPE ControlType,
- _In_ NDIS_PD_PROVIDER_CONTROL_CODE ControlCode,
- _In_reads_bytes_opt_(InBufferSize) PVOID InBuffer,
- _In_ ULONG InBufferSize,
- _Out_writes_bytes_to_opt_(OutBufferSize, *BytesReturned) PVOID OutBuffer,
- _In_ ULONG OutBufferSize,
- _Out_opt_ ULONG* BytesReturned
- );
- typedef NDIS_PD_PROVIDER_CONTROL *NDIS_PD_PROVIDER_CONTROL_HANDLER;
- typedef struct _NDIS_PD_PROVIDER_DISPATCH {
- //
- // Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
- // Header.Revision = NDIS_PD_PROVIDER_DISPATCH_REVISION_1;
- // Header.Size >= NDIS_SIZEOF_PD_PROVIDER_DISPATCH_REVISION_1;
- //
- NDIS_OBJECT_HEADER Header;
- ULONG Flags; // Reserved. Set to 0 by PD provider and ignored by PD client.
- NDIS_PD_ALLOCATE_QUEUE_HANDLER NdisPDAllocateQueue;
- NDIS_PD_FREE_QUEUE_HANDLER NdisPDFreeQueue;
- NDIS_PD_ACQUIRE_RECEIVE_QUEUES_HANDLER NdisPDAcquireReceiveQueues;
- NDIS_PD_RELEASE_RECEIVE_QUEUES_HANDLER NdisPDReleaseReceiveQueues;
- NDIS_PD_ALLOCATE_COUNTER_HANDLER NdisPDAllocateCounter;
- NDIS_PD_FREE_COUNTER_HANDLER NdisPDFreeCounter;
- NDIS_PD_QUERY_COUNTER_HANDLER NdisPDQueryCounter;
- NDIS_PD_SET_RECEIVE_FILTER_HANDLER NdisPDSetReceiveFilter;
- NDIS_PD_CLEAR_RECEIVE_FILTER_HANDLER NdisPDClearReceiveFilter;
- NDIS_PD_REQUEST_DRAIN_NOTIFICATION_HANDLER NdisPDRequestDrainNotification;
- NDIS_PD_QUEUE_CONTROL_HANDLER NdisPDQueueControl;
- NDIS_PD_PROVIDER_CONTROL_HANDLER NdisPDProviderControl;
- } NDIS_PD_PROVIDER_DISPATCH;
- #define NDIS_PD_PROVIDER_DISPATCH_REVISION_1 1
- #define NDIS_SIZEOF_PD_PROVIDER_DISPATCH_REVISION_1 \
- RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_PROVIDER_DISPATCH, NdisPDProviderControl)
- //
- // OID_PD_OPEN_PROVIDER
- //
- typedef struct DECLSPEC_ALIGN(8) _NDIS_PD_OPEN_PROVIDER_PARAMETERS {
- //
- // Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
- // Header.Revision = NDIS_PD_OPEN_PROVIDER_PARAMETERS_REVISION_1;
- // Header.Size >= NDIS_SIZEOF_PD_OPEN_PROVIDER_PARAMETERS_REVISION_1;
- //
- NDIS_OBJECT_HEADER Header;
- ULONG Flags;
- _Out_ NDIS_PD_PROVIDER_HANDLE ProviderHandle;
- _Out_ CONST NDIS_PD_PROVIDER_DISPATCH* ProviderDispatch;
- } NDIS_PD_OPEN_PROVIDER_PARAMETERS;
- #define NDIS_PD_OPEN_PROVIDER_PARAMETERS_REVISION_1 1
- #define NDIS_SIZEOF_PD_OPEN_PROVIDER_PARAMETERS_REVISION_1 \
- RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_OPEN_PROVIDER_PARAMETERS, ProviderDispatch)
- //
- // OID_PD_CLOSE_PROVIDER. An NDIS protocol or filter driver must call this
- // OID whenever it receives an unbind/detach notification, a pause indication,
- // a low-power event, or a PD config change event that indicates PD is disabled
- // on the binding/attachment. Before calling this OID, NDIS protocol/filter
- // driver must ensure that it closed/freed all PD objects such as queues,
- // counters, filters that it had created over the PD provider instance that is
- // being closed. NDIS protocol/filter driver must guarantee that there are no
- // in-progress calls to any of the PD provider dispatch table functions before
- // issung this OID.
- //
- typedef struct DECLSPEC_ALIGN(8) _NDIS_PD_CLOSE_PROVIDER_PARAMETERS {
- //
- // Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
- // Header.Revision = NDIS_PD_CLOSE_PROVIDER_PARAMETERS_REVISION_1;
- // Header.Size >= NDIS_SIZEOF_PD_CLOSE_PROVIDER_PARAMETERS_REVISION_1;
- //
- NDIS_OBJECT_HEADER Header;
- ULONG Flags; // Reserved. Must be set to 0 by client, ignored by provider
- NDIS_PD_PROVIDER_HANDLE ProviderHandle;
- } NDIS_PD_CLOSE_PROVIDER_PARAMETERS;
- #define NDIS_PD_CLOSE_PROVIDER_PARAMETERS_REVISION_1 1
- #define NDIS_SIZEOF_PD_CLOSE_PROVIDER_PARAMETERS_REVISION_1 \
- RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_CLOSE_PROVIDER_PARAMETERS, ProviderHandle)
- #endif // (NDIS_SUPPORT_NDIS650)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement