SHOW:
|
|
- or go back to the newest paste.
1 | - | d3dkmthk.h got some updates: |
1 | + | C:\Program Files (x86)\Windows Kits\10\Include\10.0.10586.0\km\ndis.h got some updates: |
2 | ||
3 | - | D3DKMT_MAX_MULTIPLANE_OVERLAY_ALLOCATIONS_PER_PLANE increased from 32 to 265 compared to TH1 10240: |
3 | + | NDIS Version is now 6.51: |
4 | ||
5 | - | #define D3DKMT_MAX_MULTIPLANE_OVERLAY_ALLOCATIONS_PER_PLANE 256 |
5 | + | Definitions with NDIS version numbers may use any of the following: |
6 | ||
7 | - | /////// |
7 | + | Version First available in |
8 | ------------------------------------------------------------------ | |
9 | - | KMTQUERYADAPTERINFOTYPE has a new entry: |
9 | + | 651 Windows 10 |
10 | 650 Windows 10 | |
11 | - | typedef enum _KMTQUERYADAPTERINFOTYPE |
11 | + | |
12 | - | { |
12 | + | |
13 | - | KMTQAITYPE_QUERY_HW_PROTECTION_TEARDOWN_COUNT = 36, |
13 | + | #if (NDIS_SUPPORT_NDIS651) |
14 | - | #endif // DXGKDDI_INTERFACE_VERSION_WDDM2_0 |
14 | + | #define NDIS_STATUS_WWAN_PRESHUTDOWN_STATE ((NDIS_STATUS)0x40041033L) |
15 | - | } KMTQUERYADAPTERINFOTYPE; |
15 | + | #endif |
16 | ||
17 | - | //////// |
17 | + | |
18 | // | |
19 | - | D3DKMT_ESCAPETYPE has also new entries: |
19 | + | // status codes used in NDIS 6.51 |
20 | // | |
21 | - | typedef enum _D3DKMT_ESCAPETYPE |
21 | + | #if NDIS_SUPPORT_NDIS651 |
22 | - | { |
22 | + | #define NDIS_STATUS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE) |
23 | - | D3DKMT_ESCAPE_HMD_GET_EDID_BASE_BLOCK = 26, |
23 | + | #define NDIS_STATUS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE) |
24 | - | D3DKMT_ESCAPE_WIN32K_HMD_ENUM = 1032, |
24 | + | #define NDIS_STATUS_DOT11_AP_CHANNEL_NOT_ALLOWED ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED) |
25 | - | D3DKMT_ESCAPE_WIN32K_HMD_CONTROL = 1033 |
25 | + | #define NDIS_STATUS_DOT11_AP_BAND_NOT_ALLOWED ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED) |
26 | - | } D3DKMT_ESCAPETYPE; |
26 | + | #endif |
27 | ||
28 | - | //// |
28 | + | |
29 | #if (NDIS_SUPPORT_NDIS650) | |
30 | - | new structs: |
30 | + | |
31 | #pragma warning(push) | |
32 | - | typedef struct _D3DKMT_SETHWPROTECTIONTEARDOWNRECOVERY |
32 | + | #pragma warning(disable:4201) // (nonstandard extension used : nameless struct/union) |
33 | - | { |
33 | + | #pragma warning(disable:4214) // (extension used : bit field types other than int) |
34 | - | D3DKMT_HANDLE hAdapter; // in: adapter handle |
34 | + | |
35 | - | BOOL Recovered; // in: HW protection teardown recovery |
35 | + | typedef struct _NDIS_PD_QUEUE NDIS_PD_QUEUE; |
36 | - | } D3DKMT_SETHWPROTECTIONTEARDOWNRECOVERY; |
36 | + | DECLARE_HANDLE(NDIS_PD_COUNTER_HANDLE); |
37 | DECLARE_HANDLE(NDIS_PD_FILTER_HANDLE); | |
38 | - | typedef struct _D3DKMT_FLUSHHEAPTRANSITIONS |
38 | + | |
39 | - | { |
39 | + | typedef PHYSICAL_ADDRESS DMA_LOGICAL_ADDRESS; |
40 | - | D3DKMT_HANDLE hAdapter; |
40 | + | |
41 | - | } D3DKMT_FLUSHHEAPTRANSITIONS; |
41 | + | typedef struct _PD_BUFFER_8021Q_INFO { |
42 | UINT16 UserPriority:3; | |
43 | - | //// |
43 | + | UINT16 CanonicalFormatId:1; |
44 | UINT16 VlanId:12; | |
45 | - | D3DKMT_MIRACAST_DEVICE_STATUS has a new entry: |
45 | + | } PD_BUFFER_8021Q_INFO; |
46 | ||
47 | - | typedef enum |
47 | + | typedef struct _PD_BUFFER_VIRTUAL_SUBNET_INFO { |
48 | - | { |
48 | + | UINT32 VirtualSubnetId:24; |
49 | - | D3DKMT_MIRACAST_DEVICE_STATUS_CANCELLED = 0x8000000B, |
49 | + | UINT32 Reserved:8; |
50 | - | } D3DKMT_MIRACAST_DEVICE_STATUS; |
50 | + | } PD_BUFFER_VIRTUAL_SUBNET_INFO; |
51 | ||
52 | - | /// |
52 | + | // |
53 | // If an L2 packet is represented by multiple PD_BUFFERs, the first PD_BUFFER | |
54 | - | new functions: |
54 | + | // must have the PD_BUFFER_FLAG_PARTIAL_PACKET_HEAD flag set and the |
55 | // NextPartialPDBuffer field must point to the partial PD_BUFFERs that | |
56 | - | typedef _Check_return_ NTSTATUS (APIENTRY *PFND3DKMT_FLUSHHEAPTRANSITIONS)(_In_ D3DKMT_FLUSHHEAPTRANSITIONS*); |
56 | + | // constitute the whole packet. Each of the partial PD_BUFFERs must point to |
57 | - | typedef _Check_return_ NTSTATUS (APIENTRY *PFND3DKMT_SETHWPROTECTIONTEARDOWNRECOVERY)(_In_ D3DKMT_SETHWPROTECTIONTEARDOWNRECOVERY*); |
57 | + | // the next partial PD_BUFFER by using the NextPartialPDBuffer as opposed to |
58 | // the NextPDBuffer field which must be NULL in all partial PD_BUFFERs except | |
59 | - | EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTFlushHeapTransitions(_In_ D3DKMT_FLUSHHEAPTRANSITIONS*); |
59 | + | // for the head buffer. All partial PD_BUFFERs except for the head buffer must |
60 | - | EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTSetHwProtectionTeardownRecovery(_In_ D3DKMT_SETHWPROTECTIONTEARDOWNRECOVERY*); |
60 | + | // have the PD_BUFFER_FLAG_PARTIAL_PACKET_HEAD cleared. The last partial |
61 | // PD_BUFFER must have its NextPartialPDBuffer field set to NULL. The total | |
62 | // length of the L2 packet is the sum of DataLength fields from each partial | |
63 | // PD_BUFFER. The head PD_BUFFER must contain up to and including the IP | |
64 | // transport (TCP, UDP, SCTP, etc) header. In the case of encap or double-encap, | |
65 | // the innermost IP transport header must be contained in the head PD_BUFFER. | |
66 | // | |
67 | #define PD_BUFFER_FLAG_PARTIAL_PACKET_HEAD 0x00000001 | |
68 | ||
69 | // | |
70 | // A PD_BUFFER allocated with its own accompanying data buffer will have | |
71 | // this attribute set. PD_BUFFER attibutes must never be modified by PD clients | |
72 | // or PD providers. | |
73 | // | |
74 | #define PD_BUFFER_ATTR_BUILT_IN_DATA_BUFFER 0x00000001 | |
75 | ||
76 | // | |
77 | // All PD_BUFFERs posted to an RX queue will have the DataStart field | |
78 | // set a value >= PD_BUFFER_MIN_RX_DATA_START_VALUE by the PD client. | |
79 | // While a PD_BUFFER is pending in an RX queue, PD provider can use the | |
80 | // portion of the data buffer between DataBufferDmaLogicalAddress and | |
81 | // (DataBufferDmaLogicalAddress + DataStart) for its own purpose. As soon as | |
82 | // a PD_BUFFER is drained by the PD client from the RX queue, PD client can | |
83 | // use the same portion of data buffer for its own purpose. A corollary of | |
84 | // this is that neither the PD client nor the PD provider can expect the | |
85 | // contents of this portion of the data buffer to be preserved as soon | |
86 | // as the control of the PD_BUFFER is transferred. A PD_BUFFER is under | |
87 | // the control of a PD provider when the PD_BUFFER is sitting in | |
88 | // a queue owned by that PD provider (i.e., posted to the queue, and has not | |
89 | // yet been drained out from the queue by the PD client). Otherwise, the | |
90 | // PD_BUFFER is under the control of the PD client. | |
91 | // | |
92 | #define PD_BUFFER_MIN_RX_DATA_START_VALUE 32 | |
93 | ||
94 | // | |
95 | // All PD_BUFFERs posted to an RX queue will satisfy the following | |
96 | // alignment requirement: | |
97 | // | |
98 | // ((DataBufferDmaLogicalAddress + DataStart) | |
99 | // & (PD_BUFFER_MIN_RX_DATA_START_ALIGNMENT - 1)) == 0 | |
100 | // | |
101 | #define PD_BUFFER_MIN_RX_DATA_START_ALIGNMENT 2 | |
102 | ||
103 | // | |
104 | // All PD_BUFFERs posted to an TX queue will satisfy the following | |
105 | // alignment requirement: | |
106 | // | |
107 | // ((DataBufferDmaLogicalAddress + DataStart) | |
108 | // & (PD_BUFFER_MIN_TX_DATA_START_ALIGNMENT - 1)) == 0 | |
109 | // | |
110 | #define PD_BUFFER_MIN_TX_DATA_START_ALIGNMENT 2 | |
111 | ||
112 | // | |
113 | // PD_BUFFER structure represents a PD packet (or a portion of a PD packet). | |
114 | // The actual memory location which is used for storing the packet data is | |
115 | // indicated by the DataBufferDmaLogicalAdress and DataBufferVirtualAdress | |
116 | // fields. The former field represents the address which the PD provider | |
117 | // must use for DMA. The latter field represents the address which host | |
118 | // software can use to access/modify the packet contents. | |
119 | // The DataBufferDmaLogicalAdress is valid for *all* PD-capable NDIS miniport | |
120 | // adapters in the same IOMMU domain. | |
121 | // | |
122 | typedef struct _PD_BUFFER { | |
123 | ||
124 | struct _PD_BUFFER* NextPDBuffer; | |
125 | struct _PD_BUFFER* NextPartialPDBuffer; | |
126 | ||
127 | // | |
128 | // Reserved for PD client use. PD provider must never modify this field. | |
129 | // | |
130 | PVOID PDClientReserved; | |
131 | ||
132 | // | |
133 | // Neither PD client nor PD provider is allowed to modify this field. | |
134 | // If PD client has allocated the PD_BUFFER with a non-zero value for | |
135 | // ClientContextSize, PDClientContext refers to a buffer of size | |
136 | // ClientContextSize. Otherwise, this field is NULL. | |
137 | // | |
138 | _Field_size_bytes_(PDClientContextSize) PVOID PDClientContext; | |
139 | ||
140 | // | |
141 | // This field denotes the original virtual address of the allocated data | |
142 | // buffer. The actual packet data is always at | |
143 | // DataBufferVirtualAddress+DataStart. Neither the PD provider nor the | |
144 | // PD platform ever modify the value of this field after PD_BUFFER | |
145 | // initialization. | |
146 | // | |
147 | _Field_size_bytes_(DataBufferSize) | |
148 | PUCHAR DataBufferVirtualAddress; | |
149 | ||
150 | // | |
151 | // This field denotes the original DMA logical address of the allocated | |
152 | // data buffer. The actual packet data is always at | |
153 | // DataBufferDmaLogicalAddress+DataStart. Neither the PD provider nor the | |
154 | // PD platform ever modify the value of this field after PD_BUFFER | |
155 | // initialization. | |
156 | // | |
157 | _Field_size_bytes_(DataBufferSize) | |
158 | DMA_LOGICAL_ADDRESS DataBufferDmaLogicalAddress; | |
159 | ||
160 | // | |
161 | // This is the total size of the allocated data buffer. Neither the PD | |
162 | // provider nor the PD platform ever modify the value of this field | |
163 | // after PD_BUFFER initialization. This is a ULONG (as opposed to a | |
164 | // USHORT) mainly because of LSO. | |
165 | // | |
166 | ULONG DataBufferSize; | |
167 | ||
168 | // | |
169 | // If non-zero, this is the size of the buffer pointed by PDClientContext. | |
170 | // The value of this field must never be modified except by the PD platform. | |
171 | // The PD platform does NOT change the value of this field after PD_BUFFER | |
172 | // allocation/initialization. | |
173 | // | |
174 | USHORT PDClientContextSize; | |
175 | ||
176 | // | |
177 | // See PD_BUFFER_ATTR_XXX. Must never be modified by PD provider. | |
178 | // | |
179 | USHORT Attributes; | |
180 | ||
181 | // | |
182 | // See PD_BUFFER_FLAG_XXX | |
183 | // | |
184 | USHORT Flags; | |
185 | ||
186 | // | |
187 | // DataStart denotes where the packet starts relative to the original | |
188 | // starting address of the allocated data buffer. PD provider never | |
189 | // modifies this field. PD provider adds this value to the | |
190 | // DataBufferDmaLogicalAddress value in order to derive the actual | |
191 | // target DMA address for packet reception/transmission. I.e., the | |
192 | // target DMA address value in the hardware receive/transmit descriptor | |
193 | // must be set to DataBufferDmaLogicalAddress+DataStart when a PD_BUFFER | |
194 | // is posted to a receive/transmit queue. | |
195 | // | |
196 | USHORT DataStart; | |
197 | ||
198 | // | |
199 | // When posting PD_BUFFERs to receive queues, DataLength is ignored by | |
200 | // the PD provider (see ReceiveDataLength description in PD queue creation). | |
201 | // When draining completed PD_BUFFERs from receive queues, | |
202 | // the PD provider stores the length of the received packet in the | |
203 | // DataLength field. The length does not include FCS or any stripped 801Q | |
204 | // headers. | |
205 | // When posting PD_BUFFERs to transmit queues, DataLength denotes the length | |
206 | // of the packet to be sent. When draining completed PD_BUFFERs from | |
207 | // transmit queues, the PD provider leaves DataLength field unmodified. | |
208 | // | |
209 | ULONG DataLength; | |
210 | ||
211 | union { | |
212 | ||
213 | struct { | |
214 | union { | |
215 | // | |
216 | // PD provider sets this to the filter context value obtained | |
217 | // from the matched filter that steered the packet to the receive | |
218 | // queue. Filter context values are specified by the PD clients | |
219 | // when configuring filters. | |
220 | // | |
221 | ULONG64 RxFilterContext; | |
222 | ||
223 | // | |
224 | // If one of the RxGftxxx bits are set, RxFilterContext value may | |
225 | // be used for GFT flow entry Id value. | |
226 | // | |
227 | ULONG64 GftFlowEntryId; | |
228 | }; | |
229 | ||
230 | // | |
231 | // The hash value computed for the incoming packet | |
232 | // that is steered to the receve queue via RSS. | |
233 | // | |
234 | ULONG RxHashValue; | |
235 | ||
236 | // | |
237 | // Commonly used RX offload fields | |
238 | // | |
239 | union { | |
240 | struct { | |
241 | ULONG RxIPHeaderChecksumSucceeded:1; | |
242 | ULONG RxTCPChecksumSucceeded:1; | |
243 | ULONG RxUDPChecksumSucceeded:1; | |
244 | ULONG RxIPHeaderChecksumFailed:1; | |
245 | ULONG RxTCPChecksumFailed:1; | |
246 | ULONG RxUDPChecksumFailed:1; | |
247 | ULONG RxHashComputed:1; | |
248 | ULONG RxHashWithL4PortNumbers:1; | |
249 | ULONG RxGftDirectionIngress:1; | |
250 | ULONG RxGftExceptionPacket:1; | |
251 | ULONG RxGftCopyPacket:1; | |
252 | ULONG RxGftSamplePacket:1; | |
253 | ULONG RxReserved1:4; | |
254 | ULONG RxCoalescedSegCount:16; // RSC | |
255 | ULONG RxRscTcpTimestampDelta; // RSC | |
256 | }; | |
257 | ULONG RxOffloads[2]; | |
258 | }; | |
259 | ||
260 | // | |
261 | // Commonly used TX offload fields | |
262 | // | |
263 | union { | |
264 | struct { | |
265 | ULONG TxIsIPv4:1; // Checksum, LSO | |
266 | ULONG TxIsIPv6:1; // Checksum, LSO | |
267 | ULONG TxTransportHeaderOffset:10; // Checksum, LSO, NVGRE | |
268 | ULONG TxMSS:20; // LSO | |
269 | ULONG TxComputeIPHeaderChecksum:1; | |
270 | ULONG TxComputeTCPChecksum:1; | |
271 | ULONG TxComputeUDPChecksum:1; | |
272 | ULONG TxIsEncapsulatedPacket:1; | |
273 | ULONG TxInnerPacketOffsetsValid:1; | |
274 | ULONG TxReserved1:11; | |
275 | ULONG TxInnerFrameOffset:8; | |
276 | ULONG TxInnerIpHeaderRelativeOffset:6; | |
277 | ULONG TxInnerIsIPv6:1; | |
278 | ULONG TxInnerTcpOptionsPresent:1; | |
279 | }; | |
280 | ULONG TxOffloads[2]; | |
281 | }; | |
282 | ||
283 | // | |
284 | // Other Meta Data | |
285 | // | |
286 | PD_BUFFER_VIRTUAL_SUBNET_INFO VirtualSubnetInfo; | |
287 | PD_BUFFER_8021Q_INFO Ieee8021qInfo; | |
288 | USHORT GftSourceVPortId; | |
289 | ||
290 | ULONG Reserved; | |
291 | ||
292 | // | |
293 | // A scratch field which the PD provider can use for its own | |
294 | // purposes while the PD_BUFFER is sitting in the provider | |
295 | // queue (i.e., posted by the client but not yet drained back | |
296 | // by the client). Once the PD_BUFFER is drained by the | |
297 | // client, there's no guarantee that the contents of this field | |
298 | // is going to be preserved. | |
299 | // | |
300 | UINT64 ProviderScratch; | |
301 | } MetaDataV0; | |
302 | }; | |
303 | } PD_BUFFER; | |
304 | ||
305 | #pragma warning(pop) | |
306 | ||
307 | // | |
308 | // A NDIS_PD_QUEUE provides the following abstraction: | |
309 | // The queue is a circular array of N slots. | |
310 | // Overall state of the queue is tracked by 3 conceptual pointers: head (H), | |
311 | // tail (T), and completed (C). H points to the slot which contains the next | |
312 | // item that must be processed. T points to the slot which the next item | |
313 | // posted by the client must be placed into. If H == T, the queue is empty. | |
314 | // If H == (T+1)%N, the queue is full. Hence, the queue can hold at most N-1 | |
315 | // items. That is, NDIS_PD_QUEUE_PARAMETERS.QueueSize is N-1. | |
316 | // C points to the slot which contains the earliest completed item | |
317 | // which has not yet been drained by the client. If C == H, the queue has no | |
318 | // items in completed state. | |
319 | // All slots are initially empty, that is, H, T, and C all point to the same | |
320 | // slot. All items posted to the queue should typically be processed and | |
321 | // completed by the provider in the order they were posted but the PD client | |
322 | // must not take a dependency on completions being strictly ordered. As the | |
323 | // queue progresses, it will always have 0 or more empty slots followed by 0 | |
324 | // or more completed slots followed by 0 or more busy slots in a circular | |
325 | // fashion. A "completed slot" refers to a slot which contains a completed item. | |
326 | // Taking the simple case where no wrap-around has occured yet, C <= H <= T | |
327 | // will always hold. Factoring in wrap-around, the following formulas will | |
328 | // hold true at any point in time: | |
329 | // The number of busy slots : (T-H)%N | |
330 | // The number of completed slots : (H-C)%N | |
331 | // The number of empty slots : (C-T-1)%N | |
332 | // | |
333 | ||
334 | // | |
335 | // All of the NDIS_PD_QUEUE_DISPATCH routines are guaranteed to be invoked by | |
336 | // the caller in serialized fashion on the same PD queue. The implementation of | |
337 | // these routines MUST avoid acquiring any locks or performing interlocked | |
338 | // operations (since the caller is responsible for dealing with concurrency, | |
339 | // not the provider, hence the provider must not use any synchronization | |
340 | // routines/primitives; if there's any need for synchronization in the core | |
341 | // transmit/receive code path in the PD provider, we must know about it and | |
342 | // do whatever necessary to remove that need.) | |
343 | // | |
344 | ||
345 | // | |
346 | // PostAndDrain is the main data path function which allows posting PD_BUFFERs | |
347 | // to PD transmit/receive queues and draining any previously posted | |
348 | // PD buffers that have been completed. Provider removes buffers from the | |
349 | // PostBufferList and places them into the queue, starting with the head | |
350 | // buffer in the list and advancing to the next buffer until either the | |
351 | // PostBufferList gets empty or the queue is full (or near full). | |
352 | // Provider advances the PostListHead and returns the new list head to the | |
353 | // caller. Provider also removes any completed buffers from the queue and | |
354 | // inserts them to tail of the DrainBufferList and returns the new | |
355 | // DrainBufferList tail to the client. Note that the provider should drain | |
356 | // as many buffers as it can in order to open up room for the buffers being | |
357 | // posted. The PostBufferList and DrainBufferList are guaranteed to be disjoint | |
358 | // buffer lists (i.e., the PD client never provides the head of a buffer list | |
359 | // as the PostBufferListHead and the tail of that same list as | |
360 | // DrainBufferListTail). The provider must ensure that it never drains more than | |
361 | // MaxDrainCount packets (a set of partial PD_BUFFERs that make up a single | |
362 | // L2 packet count as 1). The PD client can pass an empty list via | |
363 | // PostBufferListHead in order to just drain completed buffers without posting | |
364 | // any new buffers. The PD client can pass 0 for MaxDrainCount in order to | |
365 | // just post new buffers without draining any completed buffers. In rare cases, | |
366 | // client may invoke the call with both an empty PostBufferList and 0 for | |
367 | // MaxDrainCount, so the provider must NOT assume otherwise, and handle such | |
368 | // a call properly (i.e., a no-op). | |
369 | // | |
370 | // An example code snippet illustrates the abundant pointer indirections | |
371 | // best: | |
372 | // | |
373 | // PD_BUFFER* PostHead = NULL; | |
374 | // PD_BUFFER** PostTail = &PostHead; | |
375 | // PD_BUFFER* DrainHead = NULL; | |
376 | // PD_BUFFER** DrainTail = &DrainHead; | |
377 | // | |
378 | // PD_BUFFER* bufX = <allocated PD_BUFFER>; | |
379 | // | |
380 | // bufX->NextPDBuffer = NULL; | |
381 | // *PostTail = bufX; | |
382 | // PostTail = &bufX->NextPDBuffer; | |
383 | // | |
384 | // // Assume 20 PD_BUFFERs are present in the Post list just like | |
385 | // // bufX. Assume bufY is the 10th buffer and bufZ is the last buffer | |
386 | // // in Post list. Assume there are many previously posted buffers in | |
387 | // // the Queue and 5 of them are currently completed: buf1, ..., buf5. | |
388 | // // Assume the provider is able to accept only 9 buffers from the Post | |
389 | // // list and drains all 5 of the completed buffers. With these | |
390 | // // assumptions, the state of the Post and Drain lists before and | |
391 | // // after the following call returns is: | |
392 | // | |
393 | // // BEFORE: | |
394 | // // PostHead == bufX | |
395 | // // PostTail == &bufZ->NextPDBuffer | |
396 | // // DrainHead == NULL | |
397 | // // DrainTail == &DrainHead | |
398 | // | |
399 | // NDIS_PD_POST_AND_DRAIN_BUFFER_LIST( | |
400 | // Queue, | |
401 | // &PostHead, | |
402 | // &DrainTail, | |
403 | // 32); | |
404 | // | |
405 | // // AFTER: | |
406 | // // PostHead == bufY | |
407 | // // PostTail == &bufZ->NextPDBuffer | |
408 | // // DrainHead == buf1 | |
409 | // // DrainTail == &buf5->NextPDBuffer | |
410 | // | |
411 | typedef | |
412 | _IRQL_requires_min_(PASSIVE_LEVEL) | |
413 | _IRQL_requires_max_(DISPATCH_LEVEL) | |
414 | _IRQL_requires_same_ | |
415 | _Function_class_(NDIS_PD_POST_AND_DRAIN_BUFFER_LIST) | |
416 | VOID | |
417 | (NDIS_PD_POST_AND_DRAIN_BUFFER_LIST)( | |
418 | _Inout_ NDIS_PD_QUEUE* Queue, | |
419 | _Inout_ PD_BUFFER** PostBufferListHead, | |
420 | _Inout_ PD_BUFFER*** DrainBufferListTail, | |
421 | _In_ ULONG MaxDrainCount | |
422 | ); | |
423 | ||
424 | typedef NDIS_PD_POST_AND_DRAIN_BUFFER_LIST | |
425 | *NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_HANDLER; | |
426 | ||
427 | // | |
428 | // PostandDrainEx is exactly the same as PostandDrain with a few additional | |
429 | // output parameters: | |
430 | // *QueueDepthThresholdReached is set to TRUE by the provider if the queue | |
431 | // depth (as explained in the NDIS_PD_QUERY_QUEUE_DEPTH function) is below | |
432 | // the threshold value set by the client for a receive queue or is above | |
433 | // the threshold value set by the client for a transmit queue; otherwise, | |
434 | // PD provider sets it to FALSE. | |
435 | // *DrainCount is set to the number of PD_BUFFERs that the provider has | |
436 | // appended to the DrainBufferList. A set of partial PD_BUFFERs that | |
437 | // make up a single L2 packet is counted as 1. | |
438 | // *DrainCount is always <= MaxDrainCount. | |
439 | // *PostCount is set to the number of PD_BUFFERs that the provider has | |
440 | // removed from the PostbufferList. A set of partial PD_BUFFERs that | |
441 | // make up a single L2 packet is counted as 1. | |
442 | // | |
443 | typedef struct _NDIS_PD_POST_AND_DRAIN_ARG { | |
444 | _Inout_ PD_BUFFER* PostBufferListHead; | |
445 | _Inout_ PD_BUFFER** DrainBufferListTail; | |
446 | _In_ ULONG MaxDrainCount; | |
447 | _Out_ ULONG DrainCount; | |
448 | _Out_ ULONG PostCount; | |
449 | _Out_ BOOLEAN QueueDepthThresholdReached; | |
450 | } NDIS_PD_POST_AND_DRAIN_ARG; | |
451 | ||
452 | typedef | |
453 | _IRQL_requires_min_(PASSIVE_LEVEL) | |
454 | _IRQL_requires_max_(DISPATCH_LEVEL) | |
455 | _IRQL_requires_same_ | |
456 | _Function_class_(NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_EX) | |
457 | VOID | |
458 | (NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_EX)( | |
459 | _Inout_ NDIS_PD_QUEUE* Queue, | |
460 | _Inout_ NDIS_PD_POST_AND_DRAIN_ARG* Arg | |
461 | ); | |
462 | ||
463 | typedef NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_EX | |
464 | *NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_EX_HANDLER; | |
465 | ||
466 | // | |
467 | // This routine ensures that any item that's not yet in completed state | |
468 | // in the queue will be completed imminently. The caller is responsible for | |
469 | // waiting for and draining all previously posted requests before closing | |
470 | // the queue. The caller must not post any further PD buffers to the queue | |
471 | // after this call (i.e., the queue is not usable for transmiting/receiving | |
472 | // packets any more via PD). The primary use case for this routine is flushing | |
473 | // the receive queues, i.e., if there's no incoming traffic, posted buffers | |
474 | // will sit in the receive queue indefinitely, but we need to drain the | |
475 | // queue before we can close it, hence we need to flush it first. The same | |
476 | // issue does not exist for transmit queues in practice since transmit requests | |
477 | // will not pend indefinitely, but providers must honor the flush call for | |
478 | // transmit queues as well anyway (which may be a no-op if the provider knows | |
479 | // that the pending transmit request will complete very soon anyway, which is | |
480 | // the typical case except for L2 flow control possibly). | |
481 | // | |
482 | typedef | |
483 | _IRQL_requires_min_(PASSIVE_LEVEL) | |
484 | _IRQL_requires_max_(DISPATCH_LEVEL) | |
485 | _IRQL_requires_same_ | |
486 | _Function_class_(NDIS_PD_FLUSH_QUEUE) | |
487 | VOID | |
488 | (NDIS_PD_FLUSH_QUEUE)( | |
489 | _Inout_ NDIS_PD_QUEUE* Queue | |
490 | ); | |
491 | ||
492 | typedef NDIS_PD_FLUSH_QUEUE *NDIS_PD_FLUSH_QUEUE_HANDLER; | |
493 | ||
494 | // | |
495 | // Queue depth query returns the number of PD_PACKETs that are posted | |
496 | // to a NDIS_PD_QUEUE but are not yet being processed by the provider. | |
497 | // On a receive queue, this is the number of PD_BUFFERs that are available | |
498 | // for placing incoming packets into. If 10 buffers were posted, and 3 of | |
499 | // them have already been fetched by the provider for DMA'ing incoming | |
500 | // packets into, the query should return 7 (not 10). On a transmit queue, | |
501 | // this is the number of PD_BUFFERs which the provider has not yet fetched | |
502 | // from the queue for transmitting. | |
503 | // Ability to monitor the queue depth is very important for | |
504 | // PD clients in order to assess congestion build-up and take precautionary | |
505 | // action. An increasing queue depth for a TX queue is a sign of increasing | |
506 | // congestion on the outbound link. A decreasing queue depth for a RX queue | |
507 | // is a sign of the PD client not being able to process incoming packets | |
508 | // fast enough on the inbound link. PD clients may need to monitor the | |
509 | // queue depth status in a very fine grain fashion (i.e., find out if the queue | |
510 | // depth has reached a certain level during each Post-And-Operation). Such PD | |
511 | // clients use the PostAndDrainEx call. PD clients may also need to query the | |
512 | // actual queue depth (in contrast to whether the queue depth is above or below | |
513 | // a certain level) as well, which the NDIS_PD_QUERY_QUEUE_DEPTH function is | |
514 | // for. Performance of PostAndDrainEx implementation is very critical for PD | |
515 | // clients. NDIS_PD_QUERY_QUEUE_DEPTH, while also very important, is not | |
516 | // expected to be used by the PD clients with the same frequency as the | |
517 | // PostAndDrain or PostAndDrainEx operations, hence it is acceptable for | |
518 | // NDIS_PD_QUERY_QUEUE_DEPTH to be more expensive in exchange for returning the | |
519 | // actual queue depth (in contrast to whether or not queue depth is above/below | |
520 | // a given threshold). Note that it is understood by PD clients that the | |
521 | // actual queue depth in the hw may have already changed and the returned queue | |
522 | // depth may not precisely reflect it. As long as there isn't a too large lag | |
523 | // between the real and returned queue depths and the lag itself is reasonably | |
524 | // stable (for a stable incoming traffic rate), this information is still useful | |
525 | // for the PD clients. | |
526 | // | |
527 | typedef | |
528 | _IRQL_requires_min_(PASSIVE_LEVEL) | |
529 | _IRQL_requires_max_(DISPATCH_LEVEL) | |
530 | _IRQL_requires_same_ | |
531 | _Function_class_(NDIS_PD_QUERY_QUEUE_DEPTH) | |
532 | VOID | |
533 | (NDIS_PD_QUERY_QUEUE_DEPTH)( | |
534 | _In_ CONST NDIS_PD_QUEUE* Queue, | |
535 | _Out_ ULONG64* Depth | |
536 | ); | |
537 | ||
538 | typedef NDIS_PD_QUERY_QUEUE_DEPTH *NDIS_PD_QUERY_QUEUE_DEPTH_HANDLER; | |
539 | ||
540 | typedef struct _NDIS_PD_QUEUE_DISPATCH { | |
541 | // | |
542 | // Header.Type = NDIS_OBJECT_TYPE_DEFAULT; | |
543 | // Header.Revision = NDIS_PD_QUEUE_DISPATCH_REVISION_1; | |
544 | // Header.Size >= NDIS_SIZEOF_PD_QUEUE_DISPATCH_REVISION_1; | |
545 | // | |
546 | NDIS_OBJECT_HEADER Header; | |
547 | ULONG Flags; // Reserved. Must be set to 0. | |
548 | NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_HANDLER PDPostAndDrainBufferList; | |
549 | NDIS_PD_QUERY_QUEUE_DEPTH_HANDLER PDQueryQueueDepth; | |
550 | NDIS_PD_FLUSH_QUEUE_HANDLER PDFlushQueue; | |
551 | NDIS_PD_POST_AND_DRAIN_BUFFER_LIST_EX_HANDLER PDPostAndDrainBufferListEx; | |
552 | } NDIS_PD_QUEUE_DISPATCH; | |
553 | ||
554 | #define NDIS_PD_QUEUE_DISPATCH_REVISION_1 1 | |
555 | #define NDIS_SIZEOF_PD_QUEUE_DISPATCH_REVISION_1 \ | |
556 | RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_QUEUE_DISPATCH, PDPostAndDrainBufferListEx) | |
557 | ||
558 | typedef struct _NDIS_PD_QUEUE { | |
559 | // | |
560 | // Header.Type = NDIS_OBJECT_TYPE_PD_TRANSMIT_QUEUE or NDIS_OBJECT_TYPE_PD_RECEIVE_QUEUE; | |
561 | // Header.Revision = NDIS_PD_QUEUE_REVISION_1; | |
562 | // Header.Size >= NDIS_SIZEOF_PD_QUEUE_REVISION_1; | |
563 | // | |
564 | NDIS_OBJECT_HEADER Header; | |
565 | ULONG Flags; // Reserved. Must be set to 0. | |
566 | CONST NDIS_PD_QUEUE_DISPATCH* Dispatch; | |
567 | PVOID PDPlatformReserved[2]; | |
568 | PVOID PDClientReserved[2]; | |
569 | } NDIS_PD_QUEUE; | |
570 | ||
571 | #define NDIS_PD_QUEUE_REVISION_1 1 | |
572 | #define NDIS_SIZEOF_PD_QUEUE_REVISION_1 \ | |
573 | RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_QUEUE, PDClientReserved) | |
574 | ||
575 | // | |
576 | // PD and NIC SWITCH COEXISTENCE: | |
577 | // Unless otherwise is explicitly noted for a specific PD OID, all | |
578 | // PD OID requests are VPort specific when there's a NIC switch. That is, | |
579 | // PD queues are created, PD filters are set, PD counters are created all | |
580 | // per Vport. When there's no NIC switch, PD client uses NDIS_DEFAULT_VPORT_ID, | |
581 | // which must be handled by the PD provider as if the scope of the | |
582 | // OID request is the whole miniport adapter. | |
583 | // | |
584 | ||
585 | typedef enum { | |
586 | PDQueueTypeUnknown, | |
587 | PDQueueTypeReceive, | |
588 | PDQueueTypeTransmit, | |
589 | PDQueueTypeMax | |
590 | } NDIS_PD_QUEUE_TYPE; | |
591 | ||
592 | // | |
593 | // QueueSize is the maximum number of PD_BUFFERs that can be posted to the | |
594 | // queue and it is always equal to a number of the form (2^K)-1 (e.g., 63, | |
595 | // 127, 255, 511, 1023, etc). This lends itself to efficient circular index | |
596 | // arithmetic (i.e., can use "&" as opposed to "%" for index wrap-around). | |
597 | // | |
598 | // For receive queues, ReceiveDataLength denotes the minimum length of | |
599 | // the data buffers that will be posted to the receive queue, i.e., | |
600 | // (PD_BUFFER.DataBufferSize - PD_BUFFER.DataStart) >= ReceiveDataLength for | |
601 | // all PD_BUFFERs posted to the receive queue. | |
602 | // | |
603 | // Affinity is a hint to PD provider for performance optimization. PD platform | |
604 | // will primarily be processing the queue on procs indicated by the Affinity | |
605 | // mask. But, note that this is NOT a strict requirement on the PD platform. | |
606 | // Hence the PD provider must NOT use the Affinity info for anything other | |
607 | // than performance optimization. For example, PD provider should use the | |
608 | // Affinity for direct access to the proper cache for packet DMA, if supported | |
609 | // by the underlying hardware platform. | |
610 | // | |
611 | ||
612 | // | |
613 | // If this flag is set in the NDIS_PD_QUEUE_PARAMETERS Flags field, the provider | |
614 | // must be prepared to handle drain notification requests from the PD client | |
615 | // on the particular queue being allocated. This flag is valid for both RX and | |
616 | // TX queues. After the PD client requests a drain notification, it must issue | |
617 | // another PDPostAndDrainBufferList before waiting for a notification. This | |
618 | // drain request right after the arm request ensures that any items that might | |
619 | // have been completed after the previous PDPostAndDrainBufferList request but | |
620 | // right before the arm request are drained back by the client before starting | |
621 | // to wait for a notification which may never come unless new items are | |
622 | // completed. This "poll/arm/poll" model removes the synchronization burden | |
623 | // from the provider and puts it in the PD client/platform. | |
624 | // | |
625 | #define NDIS_PD_QUEUE_FLAG_DRAIN_NOTIFICATION 0x00000001 | |
626 | ||
627 | // | |
628 | // A PD provider sets this value in the NDIS_PD_QUEUE_PARAMETERS TrafficClassId | |
629 | // field when returning a PD Rx queue via NdisPDAcquireReceiveQueues if the | |
630 | // PD provider can handle multiple traffic classes via a single Rx queue for | |
631 | // a given RSS target processor. | |
632 | // | |
633 | #define NDIS_PD_INVALID_TRAFFIC_CLASS_ID ((ULONG)-1) | |
634 | ||
635 | typedef struct DECLSPEC_ALIGN(8) _NDIS_PD_QUEUE_PARAMETERS { | |
636 | // | |
637 | // Header.Type = NDIS_OBJECT_TYPE_DEFAULT; | |
638 | // Header.Revision = NDIS_PD_QUEUE_PARAMETERS_REVISION_1; | |
639 | // Header.Size >= NDIS_SIZEOF_PD_QUEUE_PARAMETERS_REVISION_1; | |
640 | // | |
641 | NDIS_OBJECT_HEADER Header; | |
642 | ULONG Flags; | |
643 | NDIS_PD_QUEUE_TYPE QueueType; // transmit or receive | |
644 | ULONG QueueSize; // 2^K-1 | |
645 | ULONG ReceiveDataLength; // min PD_BUFFER data length | |
646 | GROUP_AFFINITY Affinity; | |
647 | // | |
648 | // TrafficClassId (as defined in NDIS_QOS_PARAMETERS) for the PD queue. | |
649 | // | |
650 | ULONG TrafficClassId; | |
651 | // | |
652 | // For transmit queues, this is the maximum number of partial PD_BUFFERs | |
653 | // that the client is allowed to chain together to form a single L2 packet. | |
654 | // This must be less than or equal to the MaximumTxPartialBufferCount value | |
655 | // in NDIS_PD_CAPABILITIES. | |
656 | // | |
657 | // For receive queues, this is the maximum number of partial PD_BUFFERs | |
658 | // that the provider is allowed to chain together to form a single | |
659 | // large L2 packet with RSC. This must be less than or equal to the | |
660 | // MaximumRxPartialBufferCount value in NDIS_PD_CAPABILITIES. | |
661 | // Note that PD client never posts PD_BUFFERs with the partial flag to the | |
662 | // receive queue. PD client is always required to post PD_BUFFERs with at | |
663 | // least MTU-size space (starting from the DataStart position). Provider | |
664 | // performs chaining only in the case of RSC. Some providers may not be | |
665 | // able to support RSC chaining. Such providers advertize a value of 1 | |
666 | // via MaximumRxPartialBufferCount in NDIS_PD_CAPABILITIES. | |
667 | // If a PD client wants to still use RSC over such a provider, PD client | |
668 | // must post large enough PD_BUFFERs. | |
669 | // | |
670 | ULONG MaximumPartialBufferCount; | |
671 | // | |
672 | // During PD queue creation, PD client can optionally provide a counter | |
673 | // handle. If a counter handle is provided, depending on the queue type, | |
674 | // PD provider must update the counter values as activity occurs on the | |
675 | // PD queue. This is a handle to a PD transmit queue counter for transmit | |
676 | // queues and PD receive queue counter for receive queues. PD client is | |
677 | // responsible for closing the counter handle only after the PD queue is | |
678 | // closed. | |
679 | // | |
680 | // For PD queues obtained via NDIS_PD_ACQUIRE_RECEIVE_QUEUES, | |
681 | // PD provider MUST return a dedicated PD receive queue counter | |
682 | // for each returned receive queue. | |
683 | // | |
684 | NDIS_PD_COUNTER_HANDLE CounterHandle; | |
685 | } NDIS_PD_QUEUE_PARAMETERS; | |
686 | ||
687 | #define NDIS_PD_QUEUE_PARAMETERS_REVISION_1 1 | |
688 | ||
689 | #define NDIS_SIZEOF_PD_QUEUE_PARAMETERS_REVISION_1 \ | |
690 | RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_QUEUE_PARAMETERS, CounterHandle) | |
691 | ||
692 | // | |
693 | // If this flag is set in the NDIS_PD_ACQUIRE_QUEUES_PARAMETERS Flags field, the | |
694 | // provider must be prepared to handle drain notification requests from the PD | |
695 | // client on each of the individual RX queues returned. | |
696 | // | |
697 | #define NDIS_PD_ACQUIRE_QUEUES_FLAG_DRAIN_NOTIFICATION 0x00000001 | |
698 | ||
699 | typedef struct DECLSPEC_ALIGN(8) _NDIS_PD_ACQUIRE_QUEUES_PARAMETERS { | |
700 | // | |
701 | // Header.Type = NDIS_OBJECT_TYPE_DEFAULT; | |
702 | // Header.Revision = NDIS_PD_ACQUIRE_QUEUES_PARAMETERS_REVISION_1; | |
703 | // Header.Size >= NDIS_SIZEOF_PD_ACQUIRE_QUEUES_PARAMETERS_REVISION_1; | |
704 | // | |
705 | NDIS_OBJECT_HEADER Header; | |
706 | ULONG Flags; | |
707 | } NDIS_PD_ACQUIRE_QUEUES_PARAMETERS; | |
708 | ||
709 | #define NDIS_PD_ACQUIRE_QUEUES_PARAMETERS_REVISION_1 1 | |
710 | #define NDIS_SIZEOF_PD_ACQUIRE_QUEUES_PARAMETERS_REVISION_1 \ | |
711 | RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_ACQUIRE_QUEUES_PARAMETERS, Flags) | |
712 | ||
713 | typedef enum { | |
714 | PDCounterTypeUnknown, | |
715 | PDCounterTypeReceiveQueue, | |
716 | PDCounterTypeTransmitQueue, | |
717 | PDCounterTypeReceiveFilter, | |
718 | PDCounterTypeMax | |
719 | } NDIS_PD_COUNTER_TYPE; | |
720 | ||
721 | typedef struct _NDIS_PD_RECEIVE_QUEUE_COUNTER { | |
722 | ULONG64 PacketsReceived; | |
723 | ULONG64 BytesReceived; | |
724 | ULONG64 PacketsDropped; | |
725 | } NDIS_PD_RECEIVE_QUEUE_COUNTER; | |
726 | ||
727 | typedef struct _NDIS_PD_TRANSMIT_QUEUE_COUNTER { | |
728 | ULONG64 PacketsTransmitted; | |
729 | ULONG64 BytesTransmitted; | |
730 | } NDIS_PD_TRANSMIT_QUEUE_COUNTER; | |
731 | ||
732 | typedef struct _NDIS_PD_FILTER_COUNTER { | |
733 | ULONG64 PacketsMatched; | |
734 | ULONG64 BytesMatched; | |
735 | } NDIS_PD_FILTER_COUNTER; | |
736 | ||
737 | typedef union _NDIS_PD_COUNTER_VALUE { | |
738 | NDIS_PD_RECEIVE_QUEUE_COUNTER ReceiveQueue; | |
739 | NDIS_PD_TRANSMIT_QUEUE_COUNTER TransmitQueue; | |
740 | NDIS_PD_FILTER_COUNTER Filter; | |
741 | } NDIS_PD_COUNTER_VALUE, *PNDIS_PD_COUNTER_VALUE; | |
742 | ||
743 | typedef struct _NDIS_PD_COUNTER_PARAMETERS { | |
744 | // | |
745 | // Header.Type = NDIS_OBJECT_TYPE_DEFAULT; | |
746 | // Header.Revision = NDIS_PD_COUNTER_PARAMETERS_REVISION_1; | |
747 | // Header.Size >= NDIS_SIZEOF_PD_COUNTER_PARAMETERS_REVISION_1; | |
748 | // | |
749 | NDIS_OBJECT_HEADER Header; | |
750 | ULONG Flags; // Reserved. Must be set to 0 by client, ignored by provider | |
751 | // | |
752 | // CounterName is ignored by the PD provider. It is used by the PD platform | |
753 | // for publishing the counter to Windows Performance Counter subsystem (so | |
754 | // that the counter can be viewed via PerfMon and accessed by system APIs | |
755 | // programmatically). | |
756 | // | |
757 | PCWSTR CounterName; | |
758 | NDIS_PD_COUNTER_TYPE Type; | |
759 | } NDIS_PD_COUNTER_PARAMETERS; | |
760 | ||
761 | #define NDIS_PD_COUNTER_PARAMETERS_REVISION_1 1 | |
762 | #define NDIS_SIZEOF_PD_COUNTER_PARAMETERS_REVISION_1 \ | |
763 | RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_COUNTER_PARAMETERS, Type) | |
764 | ||
765 | typedef struct DECLSPEC_ALIGN(8) _NDIS_PD_FILTER_PARAMETERS { | |
766 | // | |
767 | // Header.Type = NDIS_OBJECT_TYPE_DEFAULT; | |
768 | // Header.Revision = NDIS_PD_FILTER_PARAMETERS_REVISION_1; | |
769 | // Header.Size >= NDIS_SIZEOF_PD_FILTER_PARAMETERS_REVISION_1; | |
770 | // | |
771 | NDIS_OBJECT_HEADER Header; | |
772 | ULONG Flags; // Reserved. Must be set to 0 by client, ignored by provider | |
773 | NDIS_GFP_PROFILE_ID MatchProfileId; | |
774 | ULONG Priority; | |
775 | NDIS_PD_COUNTER_HANDLE CounterHandle; | |
776 | NDIS_PD_QUEUE* TargetReceiveQueue; | |
777 | ULONG64 RxFilterContext; | |
778 | // | |
779 | // The following fields are used to describe an array of either | |
780 | // NDIS_GFP_HEADER_GROUP_EXACT_MATCH or NDIS_GFP_HEADER_GROUP_WILDCARD_MATCH | |
781 | // structures (determined by the MatchProfileId) | |
782 | // | |
783 | _Field_size_bytes_(HeaderGroupMatchArrayTotalSize) | |
784 | PUCHAR HeaderGroupMatchArray; // must be 8-byte aligned | |
785 | _Field_range_(0, MAXULONG/HeaderGroupMatchArrayElementSize) | |
786 | ULONG HeaderGroupMatchArrayNumElements; | |
787 | ULONG HeaderGroupMatchArrayElementSize; | |
788 | _Field_range_((HeaderGroupMatchArrayNumElements*HeaderGroupMatchArrayElementSize), MAXULONG) | |
789 | ULONG HeaderGroupMatchArrayTotalSize; | |
790 | } NDIS_PD_FILTER_PARAMETERS; | |
791 | ||
792 | #define NDIS_PD_FILTER_PARAMETERS_REVISION_1 1 | |
793 | #define NDIS_SIZEOF_PD_FILTER_PARAMETERS_REVISION_1 \ | |
794 | RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_FILTER_PARAMETERS, HeaderGroupMatchArrayTotalSize) | |
795 | ||
796 | ||
797 | DECLARE_HANDLE(NDIS_PD_PROVIDER_HANDLE); | |
798 | ||
799 | typedef | |
800 | _IRQL_requires_(PASSIVE_LEVEL) | |
801 | _IRQL_requires_same_ | |
802 | _At_(*NdisPDQueue, __drv_allocatesMem(Mem)) | |
803 | _Function_class_(NDIS_PD_ALLOCATE_QUEUE) | |
804 | NTSTATUS | |
805 | (NDIS_PD_ALLOCATE_QUEUE)( | |
806 | _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle, | |
807 | _In_ CONST NDIS_PD_QUEUE_PARAMETERS* QueueParameters, | |
808 | _Outptr_ NDIS_PD_QUEUE** NdisPDQueue | |
809 | ); | |
810 | ||
811 | typedef NDIS_PD_ALLOCATE_QUEUE *NDIS_PD_ALLOCATE_QUEUE_HANDLER; | |
812 | ||
813 | // | |
814 | // Caller is responsible for ensuring that the PD queue is empty before | |
815 | // issuing this call. Caller is also responsible for clearing all filters | |
816 | // that target this queue before closing the queue. | |
817 | // | |
818 | typedef | |
819 | _IRQL_requires_(PASSIVE_LEVEL) | |
820 | _IRQL_requires_same_ | |
821 | _Function_class_(NDIS_PD_FREE_QUEUE) | |
822 | VOID | |
823 | (NDIS_PD_FREE_QUEUE)( | |
824 | _In_ __drv_freesMem(Mem) NDIS_PD_QUEUE* NdisPDQueue | |
825 | ); | |
826 | ||
827 | typedef NDIS_PD_FREE_QUEUE *NDIS_PD_FREE_QUEUE_HANDLER; | |
828 | ||
829 | // | |
830 | // This function allows a PD client to obtain | |
831 | // PD-mode access to the NDIS receive queues. While in PD-mode, | |
832 | // PD client uses the PD-post-and-drain API on the receive | |
833 | // queues, and the PD provider stops indicating receive NBLs via the existing | |
834 | // NDIS receive data path. | |
835 | // Once PD client gets the list of NDIS_PD_QUEUE objects representing the NDIS | |
836 | // receive queues, PD client typically decides which processor core to use | |
837 | // for draining each individual receive queue. PD client uses the | |
838 | // NDIS_PD_QUEUE_PARAMETERS.Affinity parameter returned by the provider for | |
839 | // this purpose. PD provider must set NDIS_PD_QUEUE_PARAMETERS.Affinity to the | |
840 | // processor core derived from the indirection table configured via | |
841 | // OID_GEN_RECEIVE_SCALE_PARAMETERS. | |
842 | // Note that the TX path is completely independent irrespective of whether | |
843 | // a PD client is using PD on the receive queues or not. I.e., Miniport | |
844 | // adapter must handle MiniportSendNetBufferLists/MiniportReturnNetBufferLists | |
845 | // as usual even when a PD client puts the NDIS receive queues into PD-mode. | |
846 | // PD client creates PD transmit queues for sending packets via PD. So, | |
847 | // while PD client is sending PD_BUFFERs over PD transmit queues, existing | |
848 | // NDIS protocol drivers or LWFs may also send packets via usual NDIS NBL APIs | |
849 | // on the same miniport adapter. | |
850 | // | |
851 | typedef | |
852 | _IRQL_requires_(PASSIVE_LEVEL) | |
853 | _IRQL_requires_same_ | |
854 | _Function_class_(NDIS_PD_ACQUIRE_RECEIVE_QUEUES) | |
855 | NTSTATUS | |
856 | (NDIS_PD_ACQUIRE_RECEIVE_QUEUES)( | |
857 | _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle, | |
858 | _In_ CONST NDIS_PD_ACQUIRE_QUEUES_PARAMETERS* Parameters, | |
859 | _Out_writes_to_(*QueueCount, *QueueCount) NDIS_PD_QUEUE** NdisPDQueueArray, | |
860 | _Inout_ ULONG* QueueCount, | |
861 | _Out_writes_bytes_to_(*QueueParametersArraySize, *QueueParametersArraySize) | |
862 | NDIS_PD_QUEUE_PARAMETERS* QueueParametersArray, | |
863 | _Inout_ ULONG* QueueParametersArraySize, | |
864 | _Out_ ULONG* QueueParametersArrayElementSize | |
865 | ); | |
866 | ||
867 | typedef NDIS_PD_ACQUIRE_RECEIVE_QUEUES *NDIS_PD_ACQUIRE_RECEIVE_QUEUES_HANDLER; | |
868 | ||
869 | // | |
870 | // This function allows a PD client to stop using PD over | |
871 | // NDIS receive queues previosuly acquired via NDIS_PD_ACQUIRE_RECEIVE_QUEUES, | |
872 | // and instruct the PD provider to go back to the NBL-based NDIS receive data | |
873 | // path operation. PD client will invoke this function only after all pending | |
874 | // PD buffers are completed and drained (i.e., the receive queue is empty). | |
875 | // PD client does this by issuing a PDFlush request and then drain all pending | |
876 | // PD buffers until no pending buffers are left. Note that the PD client may | |
877 | // invoke NDIS_PD_ACQUIRE_RECEIVE_QUEUES again in the future to acquire PD-mode | |
878 | // access to the NDIS receive queues again. | |
879 | // | |
880 | typedef | |
881 | _IRQL_requires_(PASSIVE_LEVEL) | |
882 | _IRQL_requires_same_ | |
883 | _Function_class_(NDIS_PD_RELEASE_RECEIVE_QUEUES) | |
884 | VOID | |
885 | (NDIS_PD_RELEASE_RECEIVE_QUEUES)( | |
886 | _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle | |
887 | ); | |
888 | ||
889 | typedef NDIS_PD_RELEASE_RECEIVE_QUEUES *NDIS_PD_RELEASE_RECEIVE_QUEUES_HANDLER; | |
890 | ||
891 | // | |
892 | // This function allows the PD client to allocate a counter object. | |
893 | // Receive queue counters are used for tracking receive queue activity. | |
894 | // Transmit queue counters are used for tracking transmit queue activity. | |
895 | // Filter counters are used for tracking filter match activity. | |
896 | // Same counter object (of a given type) can be associated with multiple | |
897 | // queue or filter objects. E.g., use receive counter RC1 for receive queues | |
898 | // RQ1, RQ2, RQ3, and receive counter RC2 for receive queues RQ4 and RQ5. | |
899 | // | |
900 | typedef | |
901 | _IRQL_requires_(PASSIVE_LEVEL) | |
902 | _IRQL_requires_same_ | |
903 | _At_(*CounterHandle, __drv_allocatesMem(Mem)) | |
904 | _Function_class_(NDIS_PD_ALLOCATE_COUNTER) | |
905 | NTSTATUS | |
906 | (NDIS_PD_ALLOCATE_COUNTER)( | |
907 | _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle, | |
908 | _In_ CONST NDIS_PD_COUNTER_PARAMETERS* CounterParameters, | |
909 | _Out_ NDIS_PD_COUNTER_HANDLE* CounterHandle | |
910 | ); | |
911 | ||
912 | typedef NDIS_PD_ALLOCATE_COUNTER *NDIS_PD_ALLOCATE_COUNTER_HANDLER; | |
913 | ||
914 | // | |
915 | // PD client frees a counter only after closing | |
916 | // the object it's associated with, i.e., first close all the queues which | |
917 | // counter C1 was associated with, and then free counter C1. | |
918 | // | |
919 | typedef | |
920 | _IRQL_requires_(PASSIVE_LEVEL) | |
921 | _IRQL_requires_same_ | |
922 | VOID | |
923 | _Function_class_(NDIS_PD_FREE_COUNTER) | |
924 | (NDIS_PD_FREE_COUNTER)( | |
925 | _In_ __drv_freesMem(Mem) NDIS_PD_COUNTER_HANDLE CounterHandle | |
926 | ); | |
927 | ||
928 | typedef NDIS_PD_FREE_COUNTER *NDIS_PD_FREE_COUNTER_HANDLER; | |
929 | ||
930 | typedef | |
931 | _IRQL_requires_(PASSIVE_LEVEL) | |
932 | _IRQL_requires_same_ | |
933 | _Function_class_(NDIS_PD_QUERY_COUNTER) | |
934 | VOID | |
935 | (NDIS_PD_QUERY_COUNTER)( | |
936 | _In_ NDIS_PD_COUNTER_HANDLE CounterHandle, | |
937 | _Out_ NDIS_PD_COUNTER_VALUE* CounterValue | |
938 | ); | |
939 | ||
940 | typedef NDIS_PD_QUERY_COUNTER *NDIS_PD_QUERY_COUNTER_HANDLER; | |
941 | ||
942 | // | |
943 | // This function is used for directing specific flows of packets | |
944 | // to a specific PD receive queue. PD filters are applied before any spreading | |
945 | // takes place. Hence, packet matching a PD filter can be placed into their | |
946 | // dedicated PD queue, and rest of the packets can be spread via RSS as usual. | |
947 | // The rules for plumbing filters is the same as GFT flows, i.e., the PD client | |
948 | // is responsible for plumbing non-overlapping disambiguous filters ultimately. | |
949 | // However, some PD providers may allow overlapping filters as long as the PD | |
950 | // client can pass a Priority value that indicates which filter must be applied | |
951 | // first. PD provider may fail filter set requests with | |
952 | // STATUS_NOT_SUPPORTED if the client attemtps to set filters with | |
953 | // conflicting profiles or overlapping match conditions. NDIS_PD_CAPABILITIES | |
954 | // structure does not allow the provider to advertise all valid combinations | |
955 | // of profiles that the PD client can use simultaneously. Hence, some of | |
956 | // the capabilities are discovered by the PD client at runtime when/if the PD | |
957 | // provider fails the filter set request with STATUS_NDIS_NOT_SUPPORTED. | |
958 | // | |
959 | typedef | |
960 | _IRQL_requires_(PASSIVE_LEVEL) | |
961 | _IRQL_requires_same_ | |
962 | _At_(*FilterHandle, __drv_allocatesMem(Mem)) | |
963 | _Function_class_(NDIS_PD_SET_RECEIVE_FILTER) | |
964 | NTSTATUS | |
965 | (NDIS_PD_SET_RECEIVE_FILTER)( | |
966 | _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle, | |
967 | _In_ CONST NDIS_PD_FILTER_PARAMETERS* FilterParameters, | |
968 | _Out_ NDIS_PD_FILTER_HANDLE* FilterHandle | |
969 | ); | |
970 | ||
971 | typedef NDIS_PD_SET_RECEIVE_FILTER *NDIS_PD_SET_RECEIVE_FILTER_HANDLER; | |
972 | ||
973 | // | |
974 | // After this function returns, it's | |
975 | // guaranteed that no more newly arriving packet will match this filter. | |
976 | // However, there may still be in-flight packets that have already matched this | |
977 | // filter and they are on their way to being placed into the target receive | |
978 | // queue (but they are not placed yet). | |
979 | // | |
980 | typedef | |
981 | _IRQL_requires_(PASSIVE_LEVEL) | |
982 | _IRQL_requires_same_ | |
983 | _Function_class_(NDIS_PD_CLEAR_RECEIVE_FILTER) | |
984 | VOID | |
985 | (NDIS_PD_CLEAR_RECEIVE_FILTER)( | |
986 | _In_ __drv_freesMem(Mem) NDIS_PD_FILTER_HANDLE FilterHandle | |
987 | ); | |
988 | ||
989 | typedef NDIS_PD_CLEAR_RECEIVE_FILTER *NDIS_PD_CLEAR_RECEIVE_FILTER_HANDLER; | |
990 | ||
991 | // | |
992 | // This function is used for arming a PD queue for getting a notification | |
993 | // upon PD_BUFFER completion. | |
994 | // | |
995 | typedef | |
996 | _IRQL_requires_(PASSIVE_LEVEL) | |
997 | _IRQL_requires_same_ | |
998 | _Function_class_(NDIS_PD_REQUEST_DRAIN_NOTIFICATION) | |
999 | VOID | |
1000 | (NDIS_PD_REQUEST_DRAIN_NOTIFICATION)( | |
1001 | _Inout_ NDIS_PD_QUEUE* NdisPDQueue | |
1002 | ); | |
1003 | ||
1004 | typedef NDIS_PD_REQUEST_DRAIN_NOTIFICATION *NDIS_PD_REQUEST_DRAIN_NOTIFICATION_HANDLER; | |
1005 | ||
1006 | // | |
1007 | // NDIS_PD_QUEUE_CONTROL is primarily used for setting and/or querying various | |
1008 | // queue properties. This is a synchronous routine called at PASSIVE_LEVEL, but | |
1009 | // PD provider must avoid blocking/waiting within this call since this call | |
1010 | // can be invoked by the PD clients from their primary packet processing loop | |
1011 | // and any stall/wait within this function can degrade performance. | |
1012 | // See the individual ControlCodes and the associated in/out buffer definitions | |
1013 | // for specific operations. | |
1014 | // PD platform/clients invoke this function always in serialized fashion over | |
1015 | // a given NDIS_PD_QUEUE. But serilization relative to data path operations | |
1016 | // is NOT guaranteed. For example, client may set a NdisPDQCTLModerationInterval | |
1017 | // request on one thread while another thread may be issuing post&drain | |
1018 | // and arm requests on the queue. | |
1019 | // PD provider must return STATUS_NOT_SUPPORTED for a ControlType/ControlCode | |
1020 | // combination that is not recognized/supported by the provider. | |
1021 | // STATUS_PENDING is an illegal return value from this function. | |
1022 | // PD platform validates the buffer sizes and the ControlTypes for all | |
1023 | // currently defined ControlCodes before passing the request to the provider. | |
1024 | // | |
1025 | ||
1026 | typedef enum { | |
1027 | // | |
1028 | // INPUT to the PD provider, No OUTPUT from the PD provider | |
1029 | // | |
1030 | NdisPDCTL_IN, | |
1031 | ||
1032 | // | |
1033 | // OUTPUT from the PD provider, no INPUT to the PD provider | |
1034 | // | |
1035 | NdisPDCTL_OUT, | |
1036 | ||
1037 | // | |
1038 | // INPUT to the PD provider and OUTPUT from the PD provider | |
1039 | // | |
1040 | NdisPDCTL_INOUT, | |
1041 | } NDIS_PD_CONTROL_TYPE; | |
1042 | ||
1043 | typedef enum { | |
1044 | ||
1045 | NdisPDQCTLUnknown, | |
1046 | ||
1047 | // | |
1048 | // Type: NdisPDCTL_IN | |
1049 | // InBuffer: ULONG (QueueDepthThreshold) | |
1050 | // InBufferSize: sizeof(ULONG) | |
1051 | // | |
1052 | // QueueDepthThreshold can be set by PD clients on PD queues at any | |
1053 | // point, but never concurrently with a PostAndDrainEx call on the same | |
1054 | // PD queue. As long as the queue depth of a receive queue is below the | |
1055 | // threshold value, PD provider must set *QueueDepthThresholdReached | |
1056 | // to TRUE before returning from PostAndDrainEx. As long as the queue | |
1057 | // depth of a transmit queue is above the threshold value, PD provider | |
1058 | // must set *QueueDepthThresholdReached to TRUE before returning from | |
1059 | // PostAndDrainEx. Otherwise, PD client must set *QueueDepthThresholdReached | |
1060 | // to FALSE before returning from PostAndDrainEx. | |
1061 | // The default value for QueueDepthThreshold is MAXULONG for a transmit | |
1062 | // queue, and 0 for a receive queue. That is, PD provider simply sets | |
1063 | // *QueueDepthThresholdReached to FALSE if NdisPDQCTLQueueDepthThreshold | |
1064 | // has never been issued on the queue. | |
1065 | // | |
1066 | NdisPDQCTLQueueDepthThreshold, | |
1067 | ||
1068 | // | |
1069 | // Type: NdisPDCTL_IN | |
1070 | // InBuffer: ULONG (ModerationInterval) | |
1071 | // InBufferSize: sizeof(ULONG) | |
1072 | // | |
1073 | // Used for setting a notification ModerationInterval value on a given PD | |
1074 | // queue. ModerationInterval is the maximum number of nanoseconds that a | |
1075 | // provider can defer interrupting the host CPU after an armed PD queue | |
1076 | // goes into drainable state. If ModerationInterval is zero (which is the | |
1077 | // default value for any arm-able PD queue), the provider performs no | |
1078 | // interrupt moderation on the PD queue. If ModerationInterval is larger | |
1079 | // than the maximum moderation interval that the PD provider supports or | |
1080 | // if the PD provider's timer granularity is larger, the PD provider can | |
1081 | // round down the interval value. PD provider advertises the minimum and | |
1082 | // the maximum values as well as the granularity of the intermediate values | |
1083 | // it can support for ModerationInterval via the NDIS_PD_CAPABILITIES | |
1084 | // structure. If NDIS_PD_CAPS_NOTIFICATION_MODERATION_INTERVAL_SUPPORTED is | |
1085 | // NOT advertised by the PD provider, PD client will not set any | |
1086 | // ModerationInterval value. | |
1087 | // | |
1088 | NdisPDQCTLModerationInterval, | |
1089 | ||
1090 | // | |
1091 | // Type: NdisPDCTL_IN | |
1092 | // InBuffer: ULONG (ModerationCount) | |
1093 | // InBufferSize: sizeof(ULONG) | |
1094 | // | |
1095 | // Used for setting a notification ModerationCount value on a given PD | |
1096 | // queue. ModerationCount is the maximum number of drainable PD_BUFFERs | |
1097 | // that a provider can accumulate in an armed PD queue before interrupting | |
1098 | // the host CPU to satisfy a drain notification request. If ModerationCount | |
1099 | // is zero or one, the provider performs no interrupt moderation on the PD | |
1100 | // queue regardless of the value of the ModerationInterval property. | |
1101 | // If ModerationCount is MAXULONG or larger than the size of the PD queue, | |
1102 | // ModerationInterval alone controls the interrupt moderation on the PD queue. | |
1103 | // If NDIS_PD_CAPS_NOTIFICATION_MODERATION_COUNT_SUPPORTED is NOT | |
1104 | // advertised by the PD provider, PD client will not set any ModerationCount | |
1105 | // value. The default value for ModerationCount is MAXULONG. | |
1106 | // | |
1107 | NdisPDQCTLModerationCount, | |
1108 | ||
1109 | // | |
1110 | // Type: NdisPDCTL_IN | |
1111 | // InBuffer: ULONG (NotificationGroupId) | |
1112 | // InBufferSize: sizeof(ULONG) | |
1113 | // | |
1114 | // Used for setting a notification group id on an arm-able PD queue. | |
1115 | // By default, each PD queue upon allocation (via NDIS_PD_ALLOCATE_QUEUE | |
1116 | // or NDIS_PD_ACQUIRE_RECEIVE_QUEUES) has NO notification group id. PD | |
1117 | // clients can set a notification group id on an arm-able PD queue | |
1118 | // before calling NDIS_PD_REQUEST_DRAIN_NOTIFICATION for the first | |
1119 | // time. Once NDIS_PD_REQUEST_DRAIN_NOTIFICATION is called, the | |
1120 | // notification group id for a PD queue cannot be changed. | |
1121 | // See NdisMTriggerPDDrainNotification for how PD providers can use | |
1122 | // notification group information for optimizing drain notifications. | |
1123 | // | |
1124 | NdisPDQCTLNotificationGroupId, | |
1125 | ||
1126 | // | |
1127 | // Type: NdisPDCTL_IN | |
1128 | // InBuffer: NDIS_QOS_SQ_ID | |
1129 | // InBufferSize: sizeof(NDIS_QOS_SQ_ID) | |
1130 | // | |
1131 | // Used for setting a QoS scheduler queue Id on a given PD queue. | |
1132 | // | |
1133 | NdisPDQCTLSchedulerQueueId, | |
1134 | ||
1135 | NdisPDQCTLMax | |
1136 | } NDIS_PD_QUEUE_CONTROL_CODE; | |
1137 | ||
1138 | // | |
1139 | // The default NotificationGroupId value for a given PD queue, which means | |
1140 | // that the PD queue is NOT part of any notification group. | |
1141 | // | |
1142 | #define NDIS_PD_NOTIFICATION_GROUP_ID_NONE ((ULONG)0) | |
1143 | ||
1144 | typedef | |
1145 | _IRQL_requires_(PASSIVE_LEVEL) | |
1146 | _IRQL_requires_same_ | |
1147 | _Function_class_(NDIS_PD_QUEUE_CONTROL) | |
1148 | NTSTATUS | |
1149 | (NDIS_PD_QUEUE_CONTROL)( | |
1150 | _Inout_ NDIS_PD_QUEUE* NdisPDQueue, | |
1151 | _In_ NDIS_PD_CONTROL_TYPE ControlType, | |
1152 | _In_ NDIS_PD_QUEUE_CONTROL_CODE ControlCode, | |
1153 | _In_reads_bytes_opt_(InBufferSize) PVOID InBuffer, | |
1154 | _In_ ULONG InBufferSize, | |
1155 | _Out_writes_bytes_to_opt_(OutBufferSize, *BytesReturned) PVOID OutBuffer, | |
1156 | _In_ ULONG OutBufferSize, | |
1157 | _Out_opt_ ULONG* BytesReturned | |
1158 | ); | |
1159 | ||
1160 | typedef NDIS_PD_QUEUE_CONTROL *NDIS_PD_QUEUE_CONTROL_HANDLER; | |
1161 | ||
1162 | typedef enum { | |
1163 | ||
1164 | NdisPDPCTLUnknown, | |
1165 | ||
1166 | // | |
1167 | // Type: NdisPDCTL_OUT | |
1168 | // OutBuffer: A variable length flat buffer which the provider stores a | |
1169 | // NDIS_PD_CAPABILITIES structure followed by a variable | |
1170 | // number of elements pointed by certain offset fields in the | |
1171 | // returned NDIS_PD_CAPABILITIES structure. | |
1172 | // OutBufferSize: length of the buffer passed via OutBuffer parameter | |
1173 | // *BytesReturned: Upon an NT_SUCCESS() return, this reflects the | |
1174 | // actual number of bytes written into OutBuffer. | |
1175 | // If OutBufferSize is not large enough to hold all the | |
1176 | // bytes that the PD provider needs to write, then the | |
1177 | // provider stores the actual size needed in *BytesReturned | |
1178 | // and returns STATUS_BUFFER_TOO_SMALL. | |
1179 | // | |
1180 | NdisPDPCTLCapabilities, | |
1181 | ||
1182 | NdisPDPCTLMax | |
1183 | } NDIS_PD_PROVIDER_CONTROL_CODE; | |
1184 | ||
1185 | // | |
1186 | // PD providers must return STATUS_NOT_SUPPORTED for provider control codes | |
1187 | // that they do not recognize or support. NdisPDPCTLCapabilities is the only | |
1188 | // defined control code currently, and support for it is optional. | |
1189 | // | |
1190 | typedef | |
1191 | _IRQL_requires_(PASSIVE_LEVEL) | |
1192 | _IRQL_requires_same_ | |
1193 | _Function_class_(NDIS_PD_PROVIDER_CONTROL) | |
1194 | NTSTATUS | |
1195 | (NDIS_PD_PROVIDER_CONTROL)( | |
1196 | _In_ NDIS_PD_PROVIDER_HANDLE ProviderHandle, | |
1197 | _In_ NDIS_PD_CONTROL_TYPE ControlType, | |
1198 | _In_ NDIS_PD_PROVIDER_CONTROL_CODE ControlCode, | |
1199 | _In_reads_bytes_opt_(InBufferSize) PVOID InBuffer, | |
1200 | _In_ ULONG InBufferSize, | |
1201 | _Out_writes_bytes_to_opt_(OutBufferSize, *BytesReturned) PVOID OutBuffer, | |
1202 | _In_ ULONG OutBufferSize, | |
1203 | _Out_opt_ ULONG* BytesReturned | |
1204 | ); | |
1205 | ||
1206 | typedef NDIS_PD_PROVIDER_CONTROL *NDIS_PD_PROVIDER_CONTROL_HANDLER; | |
1207 | ||
1208 | typedef struct _NDIS_PD_PROVIDER_DISPATCH { | |
1209 | // | |
1210 | // Header.Type = NDIS_OBJECT_TYPE_DEFAULT; | |
1211 | // Header.Revision = NDIS_PD_PROVIDER_DISPATCH_REVISION_1; | |
1212 | // Header.Size >= NDIS_SIZEOF_PD_PROVIDER_DISPATCH_REVISION_1; | |
1213 | // | |
1214 | NDIS_OBJECT_HEADER Header; | |
1215 | ULONG Flags; // Reserved. Set to 0 by PD provider and ignored by PD client. | |
1216 | NDIS_PD_ALLOCATE_QUEUE_HANDLER NdisPDAllocateQueue; | |
1217 | NDIS_PD_FREE_QUEUE_HANDLER NdisPDFreeQueue; | |
1218 | NDIS_PD_ACQUIRE_RECEIVE_QUEUES_HANDLER NdisPDAcquireReceiveQueues; | |
1219 | NDIS_PD_RELEASE_RECEIVE_QUEUES_HANDLER NdisPDReleaseReceiveQueues; | |
1220 | NDIS_PD_ALLOCATE_COUNTER_HANDLER NdisPDAllocateCounter; | |
1221 | NDIS_PD_FREE_COUNTER_HANDLER NdisPDFreeCounter; | |
1222 | NDIS_PD_QUERY_COUNTER_HANDLER NdisPDQueryCounter; | |
1223 | NDIS_PD_SET_RECEIVE_FILTER_HANDLER NdisPDSetReceiveFilter; | |
1224 | NDIS_PD_CLEAR_RECEIVE_FILTER_HANDLER NdisPDClearReceiveFilter; | |
1225 | NDIS_PD_REQUEST_DRAIN_NOTIFICATION_HANDLER NdisPDRequestDrainNotification; | |
1226 | NDIS_PD_QUEUE_CONTROL_HANDLER NdisPDQueueControl; | |
1227 | NDIS_PD_PROVIDER_CONTROL_HANDLER NdisPDProviderControl; | |
1228 | } NDIS_PD_PROVIDER_DISPATCH; | |
1229 | ||
1230 | #define NDIS_PD_PROVIDER_DISPATCH_REVISION_1 1 | |
1231 | #define NDIS_SIZEOF_PD_PROVIDER_DISPATCH_REVISION_1 \ | |
1232 | RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_PROVIDER_DISPATCH, NdisPDProviderControl) | |
1233 | ||
1234 | ||
1235 | // | |
1236 | // OID_PD_OPEN_PROVIDER | |
1237 | // | |
1238 | typedef struct DECLSPEC_ALIGN(8) _NDIS_PD_OPEN_PROVIDER_PARAMETERS { | |
1239 | // | |
1240 | // Header.Type = NDIS_OBJECT_TYPE_DEFAULT; | |
1241 | // Header.Revision = NDIS_PD_OPEN_PROVIDER_PARAMETERS_REVISION_1; | |
1242 | // Header.Size >= NDIS_SIZEOF_PD_OPEN_PROVIDER_PARAMETERS_REVISION_1; | |
1243 | // | |
1244 | NDIS_OBJECT_HEADER Header; | |
1245 | ULONG Flags; | |
1246 | _Out_ NDIS_PD_PROVIDER_HANDLE ProviderHandle; | |
1247 | _Out_ CONST NDIS_PD_PROVIDER_DISPATCH* ProviderDispatch; | |
1248 | } NDIS_PD_OPEN_PROVIDER_PARAMETERS; | |
1249 | ||
1250 | #define NDIS_PD_OPEN_PROVIDER_PARAMETERS_REVISION_1 1 | |
1251 | #define NDIS_SIZEOF_PD_OPEN_PROVIDER_PARAMETERS_REVISION_1 \ | |
1252 | RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_OPEN_PROVIDER_PARAMETERS, ProviderDispatch) | |
1253 | ||
1254 | // | |
1255 | // OID_PD_CLOSE_PROVIDER. An NDIS protocol or filter driver must call this | |
1256 | // OID whenever it receives an unbind/detach notification, a pause indication, | |
1257 | // a low-power event, or a PD config change event that indicates PD is disabled | |
1258 | // on the binding/attachment. Before calling this OID, NDIS protocol/filter | |
1259 | // driver must ensure that it closed/freed all PD objects such as queues, | |
1260 | // counters, filters that it had created over the PD provider instance that is | |
1261 | // being closed. NDIS protocol/filter driver must guarantee that there are no | |
1262 | // in-progress calls to any of the PD provider dispatch table functions before | |
1263 | // issung this OID. | |
1264 | // | |
1265 | typedef struct DECLSPEC_ALIGN(8) _NDIS_PD_CLOSE_PROVIDER_PARAMETERS { | |
1266 | // | |
1267 | // Header.Type = NDIS_OBJECT_TYPE_DEFAULT; | |
1268 | // Header.Revision = NDIS_PD_CLOSE_PROVIDER_PARAMETERS_REVISION_1; | |
1269 | // Header.Size >= NDIS_SIZEOF_PD_CLOSE_PROVIDER_PARAMETERS_REVISION_1; | |
1270 | // | |
1271 | NDIS_OBJECT_HEADER Header; | |
1272 | ULONG Flags; // Reserved. Must be set to 0 by client, ignored by provider | |
1273 | NDIS_PD_PROVIDER_HANDLE ProviderHandle; | |
1274 | } NDIS_PD_CLOSE_PROVIDER_PARAMETERS; | |
1275 | ||
1276 | #define NDIS_PD_CLOSE_PROVIDER_PARAMETERS_REVISION_1 1 | |
1277 | #define NDIS_SIZEOF_PD_CLOSE_PROVIDER_PARAMETERS_REVISION_1 \ | |
1278 | RTL_SIZEOF_THROUGH_FIELD(NDIS_PD_CLOSE_PROVIDER_PARAMETERS, ProviderHandle) | |
1279 | ||
1280 | #endif // (NDIS_SUPPORT_NDIS650) |