Advertisement
MagicAndre1981

ndis.h updates in Windows 10 WDK (Build 10586)

Nov 8th, 2015
474
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. C:\Program Files (x86)\Windows Kits\10\Include\10.0.10586.0\km\ndis.h got some updates:
  2.  
  3. NDIS Version is now 6.51:
  4.  
  5. Definitions with NDIS version numbers may use any of the following:
  6.  
  7.         Version     First available in
  8.         ------------------------------------------------------------------
  9.         651         Windows 10
  10.         650         Windows 10
  11.  
  12.  
  13. #if (NDIS_SUPPORT_NDIS651)
  14. #define NDIS_STATUS_WWAN_PRESHUTDOWN_STATE                  ((NDIS_STATUS)0x40041033L)
  15. #endif
  16.  
  17.  
  18. //
  19. // status codes used in NDIS 6.51
  20. //
  21. #if NDIS_SUPPORT_NDIS651
  22. #define NDIS_STATUS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE  ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE)
  23. #define NDIS_STATUS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE     ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE)
  24. #define NDIS_STATUS_DOT11_AP_CHANNEL_NOT_ALLOWED              ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED)
  25. #define NDIS_STATUS_DOT11_AP_BAND_NOT_ALLOWED                 ((NDIS_STATUS)STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED)
  26. #endif
  27.  
  28.  
  29. #if (NDIS_SUPPORT_NDIS650)
  30.  
  31. #pragma warning(push)
  32. #pragma warning(disable:4201) // (nonstandard extension used : nameless struct/union)
  33. #pragma warning(disable:4214) // (extension used : bit field types other than int)
  34.  
  35. typedef struct _NDIS_PD_QUEUE NDIS_PD_QUEUE;
  36. DECLARE_HANDLE(NDIS_PD_COUNTER_HANDLE);
  37. DECLARE_HANDLE(NDIS_PD_FILTER_HANDLE);
  38.  
  39. typedef PHYSICAL_ADDRESS DMA_LOGICAL_ADDRESS;
  40.  
  41. typedef struct _PD_BUFFER_8021Q_INFO {
  42.     UINT16 UserPriority:3;
  43.     UINT16 CanonicalFormatId:1;
  44.     UINT16 VlanId:12;
  45. } PD_BUFFER_8021Q_INFO;
  46.  
  47. typedef struct _PD_BUFFER_VIRTUAL_SUBNET_INFO {
  48.     UINT32 VirtualSubnetId:24;
  49.     UINT32 Reserved:8;
  50. } PD_BUFFER_VIRTUAL_SUBNET_INFO;
  51.  
  52. //
  53. // If an L2 packet is represented by multiple PD_BUFFERs, the first PD_BUFFER
  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. // constitute the whole packet. Each of the partial PD_BUFFERs must point to
  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. // for the head buffer. All partial PD_BUFFERs except for the head buffer must
  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)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement