1 /*
2  * This file contains general definitions for VirtIO network adapter driver,
3  * common for both NDIS5 and NDIS6
4  *
5  * Copyright (c) 2008-2017 Red Hat, Inc.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met :
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and / or other materials provided with the distribution.
15  * 3. Neither the names of the copyright holders nor the names of their contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 #ifndef PARANDIS_56_COMMON_H
31 #define PARANDIS_56_COMMON_H
32 
33 //#define PARANDIS_TEST_TX_KICK_ALWAYS
34 
35 #if defined(OFFLOAD_UNIT_TEST)
36 #include <windows.h>
37 #include <stdio.h>
38 
39 #define ETH_LENGTH_OF_ADDRESS       6
40 #define DoPrint(fmt, ...) printf(fmt##"\n", __VA_ARGS__)
41 #define DPrintf(a,b) DoPrint b
42 #define RtlOffsetToPointer(B,O)  ((PCHAR)( ((PCHAR)(B)) + ((ULONG_PTR)(O))  ))
43 
44 #include "ethernetutils.h"
45 #endif //+OFFLOAD_UNIT_TEST
46 
47 #if !defined(OFFLOAD_UNIT_TEST)
48 
49 #if !defined(RtlOffsetToPointer)
50 #define RtlOffsetToPointer(Base,Offset)  ((PCHAR)(((PCHAR)(Base))+((ULONG_PTR)(Offset))))
51 #endif
52 
53 #if !defined(RtlPointerToOffset)
54 #define RtlPointerToOffset(Base,Pointer)  ((ULONG)(((PCHAR)(Pointer))-((PCHAR)(Base))))
55 #endif
56 
57 
58 #include <ndis.h>
59 #include "osdep.h"
60 #include "kdebugprint.h"
61 #include "ethernetutils.h"
62 #include "virtio_pci.h"
63 #include "VirtIO.h"
64 #include "virtio_ring.h"
65 #include "IONetDescriptor.h"
66 #include "DebugData.h"
67 
68 // those stuff defined in NDIS
69 //NDIS_MINIPORT_MAJOR_VERSION
70 //NDIS_MINIPORT_MINOR_VERSION
71 // those stuff defined in build environment
72 // PARANDIS_MAJOR_DRIVER_VERSION
73 // PARANDIS_MINOR_DRIVER_VERSION
74 
75 #if !defined(NDIS_MINIPORT_MAJOR_VERSION) || !defined(NDIS_MINIPORT_MINOR_VERSION)
76 #error "Something is wrong with NDIS environment"
77 #endif
78 
79 //define to see when the status register is unreadable(see ParaNdis_ResetVirtIONetDevice)
80 //#define VIRTIO_RESET_VERIFY
81 
82 //define to if hardware raise interrupt on error (see ParaNdis_DPCWorkBody)
83 //#define VIRTIO_SIGNAL_ERROR
84 
85 // define if qemu supports logging to static IO port for synchronization
86 // of driver output with qemu printouts; in this case define the port number
87 // #define VIRTIO_DBG_USE_IOPORT    0x99
88 
89 // to be set to real limit later
90 #define MAX_RX_LOOPS    1000
91 
92 // maximum number of virtio queues used by the driver
93 #define MAX_NUM_OF_QUEUES 3
94 
95 /* The feature bitmap for virtio net */
96 #define VIRTIO_NET_F_CSUM   0   /* Host handles pkts w/ partial csum */
97 #define VIRTIO_NET_F_GUEST_CSUM 1   /* Guest handles pkts w/ partial csum */
98 #define VIRTIO_NET_F_MAC    5   /* Host has given MAC address. */
99 #define VIRTIO_NET_F_GSO    6   /* Host handles pkts w/ any GSO type */
100 #define VIRTIO_NET_F_GUEST_TSO4 7   /* Guest can handle TSOv4 in. */
101 #define VIRTIO_NET_F_GUEST_TSO6 8   /* Guest can handle TSOv6 in. */
102 #define VIRTIO_NET_F_GUEST_ECN  9   /* Guest can handle TSO[6] w/ ECN in. */
103 #define VIRTIO_NET_F_GUEST_UFO  10  /* Guest can handle UFO in. */
104 #define VIRTIO_NET_F_HOST_TSO4  11  /* Host can handle TSOv4 in. */
105 #define VIRTIO_NET_F_HOST_TSO6  12  /* Host can handle TSOv6 in. */
106 #define VIRTIO_NET_F_HOST_ECN   13  /* Host can handle TSO[6] w/ ECN in. */
107 #define VIRTIO_NET_F_HOST_UFO   14  /* Host can handle UFO in. */
108 #define VIRTIO_NET_F_MRG_RXBUF  15  /* Host can handle merged Rx buffers and requires bigger header for that. */
109 #define VIRTIO_NET_F_STATUS     16
110 #define VIRTIO_NET_F_CTRL_VQ    17      /* Control channel available */
111 #define VIRTIO_NET_F_CTRL_RX    18      /* Control channel RX mode support */
112 #define VIRTIO_NET_F_CTRL_VLAN  19      /* Control channel VLAN filtering */
113 #define VIRTIO_NET_F_CTRL_RX_EXTRA 20   /* Extra RX mode control support */
114 
115 #define VIRTIO_NET_S_LINK_UP    1       /* Link is up */
116 
117 #define VIRTIO_NET_INVALID_INTERRUPT_STATUS     0xFF
118 
119 #define PARANDIS_MULTICAST_LIST_SIZE        32
120 #define PARANDIS_MEMORY_TAG                 '5muQ'
121 #define PARANDIS_FORMAL_LINK_SPEED          (pContext->ulFormalLinkSpeed)
122 #define PARANDIS_MAXIMUM_TRANSMIT_SPEED     PARANDIS_FORMAL_LINK_SPEED
123 #define PARANDIS_MAXIMUM_RECEIVE_SPEED      PARANDIS_FORMAL_LINK_SPEED
124 #define PARANDIS_MIN_LSO_SEGMENTS           2
125 // reported
126 #define PARANDIS_MAX_LSO_SIZE               0xF800
127 
128 #define PARANDIS_UNLIMITED_PACKETS_TO_INDICATE  (~0ul)
129 
130 extern VirtIOSystemOps ParaNdisSystemOps;
131 
132 typedef enum _tagInterruptSource
133 {
134     isControl  = VIRTIO_PCI_ISR_CONFIG,
135     isReceive  = 0x10,
136     isTransmit = 0x20,
137     isUnknown  = 0x40,
138     isBothTransmitReceive = isReceive | isTransmit,
139     isAny      = isReceive | isTransmit | isControl | isUnknown,
140     isDisable  = 0x80
141 }tInterruptSource;
142 
143 static const ULONG PARANDIS_PACKET_FILTERS =
144     NDIS_PACKET_TYPE_DIRECTED |
145     NDIS_PACKET_TYPE_MULTICAST |
146     NDIS_PACKET_TYPE_BROADCAST |
147     NDIS_PACKET_TYPE_PROMISCUOUS |
148     NDIS_PACKET_TYPE_ALL_MULTICAST;
149 
150 typedef VOID (*ONPAUSECOMPLETEPROC)(VOID *);
151 
152 
153 typedef enum _tagSendReceiveState
154 {
155     srsDisabled = 0,        // initial state
156     srsPausing,
157     srsEnabled
158 } tSendReceiveState;
159 
160 typedef struct _tagBusResource {
161     NDIS_PHYSICAL_ADDRESS BasePA;
162     ULONG                 uLength;
163     PVOID                 pBase;
164     BOOLEAN               bPortSpace;
165     BOOLEAN               bUsed;
166 } tBusResource;
167 
168 typedef struct _tagAdapterResources
169 {
170     tBusResource PciBars[PCI_TYPE0_ADDRESSES];
171     ULONG Vector;
172     ULONG Level;
173     KAFFINITY Affinity;
174     ULONG InterruptFlags;
175 } tAdapterResources;
176 
177 typedef enum _tagOffloadSettingsBit
178 {
179     osbT4IpChecksum = (1 << 0),
180     osbT4TcpChecksum = (1 << 1),
181     osbT4UdpChecksum = (1 << 2),
182     osbT4TcpOptionsChecksum = (1 << 3),
183     osbT4IpOptionsChecksum = (1 << 4),
184     osbT4Lso = (1 << 5),
185     osbT4LsoIp = (1 << 6),
186     osbT4LsoTcp = (1 << 7),
187     osbT4RxTCPChecksum = (1 << 8),
188     osbT4RxTCPOptionsChecksum = (1 << 9),
189     osbT4RxIPChecksum = (1 << 10),
190     osbT4RxIPOptionsChecksum = (1 << 11),
191     osbT4RxUDPChecksum = (1 << 12),
192     osbT6TcpChecksum = (1 << 13),
193     osbT6UdpChecksum = (1 << 14),
194     osbT6TcpOptionsChecksum = (1 << 15),
195     osbT6IpExtChecksum = (1 << 16),
196     osbT6Lso = (1 << 17),
197     osbT6LsoIpExt = (1 << 18),
198     osbT6LsoTcpOptions = (1 << 19),
199     osbT6RxTCPChecksum = (1 << 20),
200     osbT6RxTCPOptionsChecksum = (1 << 21),
201     osbT6RxUDPChecksum = (1 << 22),
202     osbT6RxIpExtChecksum = (1 << 23),
203 }tOffloadSettingsBit;
204 
205 typedef struct _tagOffloadSettingsFlags
206 {
207     ULONG fTxIPChecksum     : 1;
208     ULONG fTxTCPChecksum    : 1;
209     ULONG fTxUDPChecksum    : 1;
210     ULONG fTxTCPOptions     : 1;
211     ULONG fTxIPOptions      : 1;
212     ULONG fTxLso            : 1;
213     ULONG fTxLsoIP          : 1;
214     ULONG fTxLsoTCP         : 1;
215     ULONG fRxIPChecksum     : 1;
216     ULONG fRxTCPChecksum    : 1;
217     ULONG fRxUDPChecksum    : 1;
218     ULONG fRxTCPOptions     : 1;
219     ULONG fRxIPOptions      : 1;
220     ULONG fTxTCPv6Checksum  : 1;
221     ULONG fTxUDPv6Checksum  : 1;
222     ULONG fTxTCPv6Options   : 1;
223     ULONG fTxIPv6Ext        : 1;
224     ULONG fTxLsov6          : 1;
225     ULONG fTxLsov6IP        : 1;
226     ULONG fTxLsov6TCP       : 1;
227     ULONG fRxTCPv6Checksum  : 1;
228     ULONG fRxUDPv6Checksum  : 1;
229     ULONG fRxTCPv6Options   : 1;
230     ULONG fRxIPv6Ext        : 1;
231 }tOffloadSettingsFlags;
232 
233 
234 typedef struct _tagOffloadSettings
235 {
236     /* current value of enabled offload features */
237     tOffloadSettingsFlags flags;
238     /* load once, do not modify - bitmask of offload features, enabled in configuration */
239     ULONG flagsValue;
240     ULONG ipHeaderOffset;
241     ULONG maxPacketSize;
242 }tOffloadSettings;
243 
244 typedef struct _tagChecksumCheckResult
245 {
246     union
247     {
248         struct
249         {
250             ULONG   TcpFailed       :1;
251             ULONG   UdpFailed       :1;
252             ULONG   IpFailed        :1;
253             ULONG   TcpOK           :1;
254             ULONG   UdpOK           :1;
255             ULONG   IpOK            :1;
256         } flags;
257         ULONG value;
258     };
259 }tChecksumCheckResult;
260 
261 /*
262 for simplicity, we use for NDIS5 the same statistics as native NDIS6 uses
263 */
264 typedef struct _tagNdisStatistics
265 {
266     ULONG64                     ifHCInOctets;
267     ULONG64                     ifHCInUcastPkts;
268     ULONG64                     ifHCInUcastOctets;
269     ULONG64                     ifHCInMulticastPkts;
270     ULONG64                     ifHCInMulticastOctets;
271     ULONG64                     ifHCInBroadcastPkts;
272     ULONG64                     ifHCInBroadcastOctets;
273     ULONG64                     ifInDiscards;
274     ULONG64                     ifInErrors;
275     ULONG64                     ifHCOutOctets;
276     ULONG64                     ifHCOutUcastPkts;
277     ULONG64                     ifHCOutUcastOctets;
278     ULONG64                     ifHCOutMulticastPkts;
279     ULONG64                     ifHCOutMulticastOctets;
280     ULONG64                     ifHCOutBroadcastPkts;
281     ULONG64                     ifHCOutBroadcastOctets;
282     ULONG64                     ifOutDiscards;
283     ULONG64                     ifOutErrors;
284 }NDIS_STATISTICS_INFO;
285 
286 typedef PNDIS_PACKET tPacketType;
287 typedef PNDIS_PACKET tPacketHolderType;
288 typedef PNDIS_PACKET tPacketIndicationType;
289 
290 typedef struct _tagNdisOffloadParams
291 {
292     UCHAR   IPv4Checksum;
293     UCHAR   TCPIPv4Checksum;
294     UCHAR   UDPIPv4Checksum;
295     UCHAR   LsoV1;
296     UCHAR   LsoV2IPv4;
297     UCHAR   TCPIPv6Checksum;
298     UCHAR   UDPIPv6Checksum;
299     UCHAR   LsoV2IPv6;
300 }NDIS_OFFLOAD_PARAMETERS;
301 
302 //#define UNIFY_LOCKS
303 
304 typedef struct _tagOurCounters
305 {
306     UINT nReusedRxBuffers;
307     UINT nPrintDiagnostic;
308     ULONG64 prevIn;
309     UINT nRxInactivity;
310 }tOurCounters;
311 
312 typedef struct _tagMaxPacketSize
313 {
314     UINT nMaxDataSize;
315     UINT nMaxFullSizeOS;
316     UINT nMaxFullSizeHwTx;
317     UINT nMaxFullSizeHwRx;
318 }tMaxPacketSize;
319 
320 typedef struct _tagCompletePhysicalAddress
321 {
322     PHYSICAL_ADDRESS    Physical;
323     PVOID               Virtual;
324     ULONG               size;
325     ULONG               IsCached        : 1;
326     ULONG               IsTX            : 1;
327 } tCompletePhysicalAddress;
328 
329 typedef struct _tagMulticastData
330 {
331     ULONG                   nofMulticastEntries;
332     UCHAR                   MulticastList[ETH_LENGTH_OF_ADDRESS * PARANDIS_MULTICAST_LIST_SIZE];
333 }tMulticastData;
334 
335 typedef struct _tagIONetDescriptor {
336     LIST_ENTRY listEntry;
337     tCompletePhysicalAddress HeaderInfo;
338     tCompletePhysicalAddress DataInfo;
339     tPacketHolderType pHolder;
340     PVOID ReferenceValue;
341     UINT  nofUsedBuffers;
342 } IONetDescriptor, * pIONetDescriptor;
343 
344 typedef void (*tReuseReceiveBufferProc)(void *pContext, pIONetDescriptor pDescriptor);
345 
346 typedef struct _tagPARANDIS_ADAPTER
347 {
348     NDIS_HANDLE             DriverHandle;
349     NDIS_HANDLE             MiniportHandle;
350     NDIS_EVENT              ResetEvent;
351     tAdapterResources       AdapterResources;
352     tBusResource            SharedMemoryRanges[MAX_NUM_OF_QUEUES];
353 
354     VirtIODevice            IODevice;
355     BOOLEAN                 bIODeviceInitialized;
356     ULONGLONG               ullHostFeatures;
357     ULONGLONG               ullGuestFeatures;
358 
359     LARGE_INTEGER           LastTxCompletionTimeStamp;
360 #ifdef PARANDIS_DEBUG_INTERRUPTS
361     LARGE_INTEGER           LastInterruptTimeStamp;
362 #endif
363     BOOLEAN                 bConnected;
364     BOOLEAN                 bEnableInterruptHandlingDPC;
365     BOOLEAN                 bEnableInterruptChecking;
366     BOOLEAN                 bDoInterruptRecovery;
367     BOOLEAN                 bDoSupportPriority;
368     BOOLEAN                 bDoHwPacketFiltering;
369     BOOLEAN                 bUseScatterGather;
370     BOOLEAN                 bBatchReceive;
371     BOOLEAN                 bLinkDetectSupported;
372     BOOLEAN                 bDoHardwareChecksum;
373     BOOLEAN                 bDoGuestChecksumOnReceive;
374     BOOLEAN                 bDoIPCheckTx;
375     BOOLEAN                 bDoIPCheckRx;
376     BOOLEAN                 bUseMergedBuffers;
377     BOOLEAN                 bDoKickOnNoBuffer;
378     BOOLEAN                 bSurprizeRemoved;
379     BOOLEAN                 bUsingMSIX;
380     BOOLEAN                 bUseIndirect;
381     BOOLEAN                 bHasHardwareFilters;
382     BOOLEAN                 bHasControlQueue;
383     BOOLEAN                 bNoPauseOnSuspend;
384     BOOLEAN                 bFastSuspendInProcess;
385     BOOLEAN                 bResetInProgress;
386     ULONG                   ulCurrentVlansFilterSet;
387     tMulticastData          MulticastData;
388     UINT                    uNumberOfHandledRXPacketsInDPC;
389     NDIS_DEVICE_POWER_STATE powerState;
390     LONG                    dpcReceiveActive;
391     LONG                    counterDPCInside;
392     LONG                    bDPCInactive;
393     LONG                    InterruptStatus;
394     ULONG                   ulPriorityVlanSetting;
395     ULONG                   VlanId;
396     ULONGLONG               ulFormalLinkSpeed;
397     ULONG                   ulEnableWakeup;
398     tMaxPacketSize          MaxPacketSize;
399     ULONG                   nEnableDPCChecker;
400     ULONG                   ulUniqueID;
401     UCHAR                   PermanentMacAddress[ETH_LENGTH_OF_ADDRESS];
402     UCHAR                   CurrentMacAddress[ETH_LENGTH_OF_ADDRESS];
403     ULONG                   PacketFilter;
404     ULONG                   DummyLookAhead;
405     ULONG                   ulMilliesToConnect;
406     ULONG                   nDetectedStoppedTx;
407     ULONG                   nDetectedInactivity;
408     ULONG                   nVirtioHeaderSize;
409     /* send part */
410 #if !defined(UNIFY_LOCKS)
411     NDIS_SPIN_LOCK          SendLock;
412     NDIS_SPIN_LOCK          ReceiveLock;
413 #else
414     union
415     {
416     NDIS_SPIN_LOCK          SendLock;
417     NDIS_SPIN_LOCK          ReceiveLock;
418     };
419 #endif
420     NDIS_STATISTICS_INFO    Statistics;
421     struct
422     {
423         ULONG framesCSOffload;
424         ULONG framesLSO;
425         ULONG framesIndirect;
426         ULONG framesRxPriority;
427         ULONG framesRxCSHwOK;
428         ULONG framesRxCSHwMissedBad;
429         ULONG framesRxCSHwMissedGood;
430         ULONG framesFilteredOut;
431     } extraStatistics;
432     tOurCounters            Counters;
433     tOurCounters            Limits;
434     tSendReceiveState       SendState;
435     tSendReceiveState       ReceiveState;
436     ONPAUSECOMPLETEPROC     SendPauseCompletionProc;
437     ONPAUSECOMPLETEPROC     ReceivePauseCompletionProc;
438     tReuseReceiveBufferProc ReuseBufferProc;
439     /* Net part - management of buffers and queues of QEMU */
440     struct virtqueue *      NetControlQueue;
441     tCompletePhysicalAddress ControlData;
442     struct virtqueue *      NetReceiveQueue;
443     struct virtqueue *      NetSendQueue;
444     /* list of Rx buffers available for data (under VIRTIO management) */
445     LIST_ENTRY              NetReceiveBuffers;
446     UINT                    NetNofReceiveBuffers;
447     /* list of Rx buffers waiting for return (under NDIS management) */
448     LIST_ENTRY              NetReceiveBuffersWaiting;
449     /* list of Tx buffers in process (under VIRTIO management) */
450     LIST_ENTRY              NetSendBuffersInUse;
451     /* list of Tx buffers ready for data (under MINIPORT management) */
452     LIST_ENTRY              NetFreeSendBuffers;
453     /* current number of free Tx descriptors */
454     UINT                    nofFreeTxDescriptors;
455     /* initial number of free Tx descriptor(from cfg) - max number of available Tx descriptors */
456     UINT                    maxFreeTxDescriptors;
457     /* current number of free Tx buffers, which can be submitted */
458     UINT                    nofFreeHardwareBuffers;
459     /* maximal number of free Tx buffers, which can be used by SG */
460     UINT                    maxFreeHardwareBuffers;
461     /* minimal number of free Tx buffers */
462     UINT                    minFreeHardwareBuffers;
463     /* current number of Tx packets (or lists) to return */
464     LONG                    NetTxPacketsToReturn;
465     /* total of Rx buffer in turnaround */
466     UINT                    NetMaxReceiveBuffers;
467     struct VirtIOBufferDescriptor *sgTxGatherTable;
468     UINT                    nPnpEventIndex;
469     NDIS_DEVICE_PNP_EVENT   PnpEvents[16];
470     tOffloadSettings        Offload;
471     NDIS_OFFLOAD_PARAMETERS InitialOffloadParameters;
472     // we keep these members common for XP and Vista
473     // for XP and non-MSI case of Vista they are set to zero
474     ULONG                       ulRxMessage;
475     ULONG                       ulTxMessage;
476     ULONG                       ulControlMessage;
477 
478     NDIS_MINIPORT_INTERRUPT     Interrupt;
479     NDIS_HANDLE                 PacketPool;
480     NDIS_HANDLE                 BuffersPool;
481     NDIS_HANDLE                 WrapperConfigurationHandle;
482     LIST_ENTRY                  SendQueue;
483     LIST_ENTRY                  TxWaitingList;
484     NDIS_EVENT                  HaltEvent;
485     NDIS_TIMER                  ConnectTimer;
486     NDIS_TIMER                  DPCPostProcessTimer;
487     BOOLEAN                     bDmaInitialized;
488 }PARANDIS_ADAPTER, *PPARANDIS_ADAPTER;
489 
490 typedef enum { cpeOK, cpeNoBuffer, cpeInternalError, cpeTooLarge, cpeNoIndirect } tCopyPacketError;
491 typedef struct _tagCopyPacketResult
492 {
493     ULONG       size;
494     tCopyPacketError error;
495 }tCopyPacketResult;
496 
497 typedef struct _tagSynchronizedContext
498 {
499     PARANDIS_ADAPTER    *pContext;
500     PVOID               Parameter;
501 }tSynchronizedContext;
502 
503 typedef BOOLEAN (NTAPI *tSynchronizedProcedure)(tSynchronizedContext *context);
504 
505 /**********************************************************
506 LAZY release procedure returns buffers to VirtIO
507 only where there are no free buffers available
508 
509 NON-LAZY release releases transmit buffers from VirtIO
510 library every time there is something to release
511 ***********************************************************/
512 //#define LAZY_TX_RELEASE
513 
514 static inline bool VirtIODeviceGetHostFeature(PARANDIS_ADAPTER *pContext, unsigned uFeature)
515 {
516    DPrintf(4, ("%s\n", __FUNCTION__));
517 
518    return virtio_is_feature_enabled(pContext->ullHostFeatures, uFeature);
519 }
520 
521 static inline void VirtIODeviceEnableGuestFeature(PARANDIS_ADAPTER *pContext, unsigned uFeature)
522 {
523    DPrintf(4, ("%s\n", __FUNCTION__));
524 
525    virtio_feature_enable(pContext->ullGuestFeatures, uFeature);
526 }
527 
528 static BOOLEAN FORCEINLINE IsTimeToReleaseTx(PARANDIS_ADAPTER *pContext)
529 {
530 #ifndef LAZY_TX_RELEASE
531     return pContext->nofFreeTxDescriptors < pContext->maxFreeTxDescriptors;
532 #else
533     return pContext->nofFreeTxDescriptors == 0;
534 #endif
535 }
536 
537 static BOOLEAN FORCEINLINE IsValidVlanId(PARANDIS_ADAPTER *pContext, ULONG VlanID)
538 {
539     return pContext->VlanId == 0 || pContext->VlanId == VlanID;
540 }
541 
542 static BOOLEAN FORCEINLINE IsVlanSupported(PARANDIS_ADAPTER *pContext)
543 {
544     return pContext->ulPriorityVlanSetting & 2;
545 }
546 
547 static BOOLEAN FORCEINLINE IsPrioritySupported(PARANDIS_ADAPTER *pContext)
548 {
549     return pContext->ulPriorityVlanSetting & 1;
550 }
551 
552 BOOLEAN ParaNdis_ValidateMacAddress(
553     PUCHAR pcMacAddress,
554     BOOLEAN bLocal);
555 
556 NDIS_STATUS ParaNdis_InitializeContext(
557     PARANDIS_ADAPTER *pContext,
558     PNDIS_RESOURCE_LIST ResourceList);
559 
560 NDIS_STATUS ParaNdis_FinishInitialization(
561     PARANDIS_ADAPTER *pContext);
562 
563 VOID ParaNdis_CleanupContext(
564     PARANDIS_ADAPTER *pContext);
565 
566 
567 UINT ParaNdis_VirtIONetReleaseTransmitBuffers(
568     PARANDIS_ADAPTER *pContext);
569 
570 ULONG ParaNdis_DPCWorkBody(
571   PARANDIS_ADAPTER *pContext,
572   ULONG ulMaxPacketsToIndicate);
573 
574 NDIS_STATUS ParaNdis_SetMulticastList(
575     PARANDIS_ADAPTER *pContext,
576     PVOID Buffer,
577     ULONG BufferSize,
578     PUINT pBytesRead,
579     PUINT pBytesNeeded);
580 
581 VOID ParaNdis_VirtIOEnableIrqSynchronized(
582     PARANDIS_ADAPTER *pContext,
583     ULONG interruptSource);
584 
585 VOID ParaNdis_VirtIODisableIrqSynchronized(
586     PARANDIS_ADAPTER *pContext,
587     ULONG interruptSource);
588 
589 static __inline struct virtqueue *
590 ParaNdis_GetQueueForInterrupt(PARANDIS_ADAPTER *pContext, ULONG interruptSource)
591 {
592     if (interruptSource & isTransmit)
593         return pContext->NetSendQueue;
594     if (interruptSource & isReceive)
595         return pContext->NetReceiveQueue;
596 
597     return NULL;
598 }
599 
600 static __inline BOOLEAN
601 ParaNDIS_IsQueueInterruptEnabled(struct virtqueue * _vq)
602 {
603     return virtqueue_is_interrupt_enabled(_vq);
604 }
605 
606 VOID ParaNdis_OnPnPEvent(
607     PARANDIS_ADAPTER *pContext,
608     NDIS_DEVICE_PNP_EVENT pEvent,
609     PVOID   pInfo,
610     ULONG   ulSize);
611 
612 BOOLEAN ParaNdis_OnLegacyInterrupt(
613     PARANDIS_ADAPTER *pContext,
614     BOOLEAN *pRunDpc);
615 
616 BOOLEAN ParaNdis_OnQueuedInterrupt(
617     PARANDIS_ADAPTER *pContext,
618     BOOLEAN *pRunDpc,
619     ULONG knownInterruptSources);
620 
621 VOID ParaNdis_OnShutdown(
622     PARANDIS_ADAPTER *pContext);
623 
624 BOOLEAN ParaNdis_CheckForHang(
625     PARANDIS_ADAPTER *pContext);
626 
627 VOID ParaNdis_ReportLinkStatus(
628     PARANDIS_ADAPTER *pContext,
629     BOOLEAN bForce);
630 
631 NDIS_STATUS ParaNdis_PowerOn(
632     PARANDIS_ADAPTER *pContext
633 );
634 
635 VOID ParaNdis_PowerOff(
636     PARANDIS_ADAPTER *pContext
637 );
638 
639 void ParaNdis_DebugInitialize(PVOID DriverObject,PVOID RegistryPath);
640 void ParaNdis_DebugCleanup(PDRIVER_OBJECT  pDriverObject);
641 void ParaNdis_DebugRegisterMiniport(PARANDIS_ADAPTER *pContext, BOOLEAN bRegister);
642 
643 
644 //#define ENABLE_HISTORY_LOG
645 #if !defined(ENABLE_HISTORY_LOG)
646 
647 static void FORCEINLINE ParaNdis_DebugHistory(
648     PARANDIS_ADAPTER *pContext,
649     eHistoryLogOperation op,
650     PVOID pParam1,
651     ULONG lParam2,
652     ULONG lParam3,
653     ULONG lParam4)
654 {
655 
656 }
657 
658 #else
659 
660 void ParaNdis_DebugHistory(
661     PARANDIS_ADAPTER *pContext,
662     eHistoryLogOperation op,
663     PVOID pParam1,
664     ULONG lParam2,
665     ULONG lParam3,
666     ULONG lParam4);
667 
668 #endif
669 
670 typedef struct _tagTxOperationParameters
671 {
672     tPacketType     packet;
673     PVOID           ReferenceValue;
674     UINT            nofSGFragments;
675     ULONG           ulDataSize;
676     ULONG           offloadMss;
677     ULONG           tcpHeaderOffset;
678     ULONG           flags;      //see tPacketOffloadRequest
679 }tTxOperationParameters;
680 
681 tCopyPacketResult ParaNdis_DoCopyPacketData(
682     PARANDIS_ADAPTER *pContext,
683     tTxOperationParameters *pParams);
684 
685 typedef struct _tagMapperResult
686 {
687     USHORT  usBuffersMapped;
688     USHORT  usBufferSpaceUsed;
689     ULONG   ulDataSize;
690 }tMapperResult;
691 
692 
693 tCopyPacketResult ParaNdis_DoSubmitPacket(PARANDIS_ADAPTER *pContext, tTxOperationParameters *Params);
694 
695 void ParaNdis_ResetOffloadSettings(PARANDIS_ADAPTER *pContext, tOffloadSettingsFlags *pDest, PULONG from);
696 
697 tChecksumCheckResult ParaNdis_CheckRxChecksum(PARANDIS_ADAPTER *pContext, ULONG virtioFlags, PVOID pRxPacket, ULONG len);
698 
699 void ParaNdis_CallOnBugCheck(PARANDIS_ADAPTER *pContext);
700 
701 /*****************************************************
702 Procedures to implement for NDIS specific implementation
703 ******************************************************/
704 
705 PVOID ParaNdis_AllocateMemory(
706     PARANDIS_ADAPTER *pContext,
707     ULONG ulRequiredSize);
708 
709 NDIS_STATUS NTAPI ParaNdis_FinishSpecificInitialization(
710     PARANDIS_ADAPTER *pContext);
711 
712 VOID ParaNdis_FinalizeCleanup(
713     PARANDIS_ADAPTER *pContext);
714 
715 NDIS_HANDLE ParaNdis_OpenNICConfiguration(
716     PARANDIS_ADAPTER *pContext);
717 
718 tPacketIndicationType ParaNdis_IndicateReceivedPacket(
719     PARANDIS_ADAPTER *pContext,
720     PVOID dataBuffer,
721     PULONG pLength,
722     BOOLEAN bPrepareOnly,
723     pIONetDescriptor pBufferDesc);
724 
725 VOID ParaNdis_IndicateReceivedBatch(
726     PARANDIS_ADAPTER *pContext,
727     tPacketIndicationType *pBatch,
728     ULONG nofPackets);
729 
730 VOID ParaNdis_PacketMapper(
731     PARANDIS_ADAPTER *pContext,
732     tPacketType packet,
733     PVOID Reference,
734     struct VirtIOBufferDescriptor *buffers,
735     pIONetDescriptor pDesc,
736     tMapperResult *pMapperResult
737     );
738 
739 tCopyPacketResult ParaNdis_PacketCopier(
740     tPacketType packet,
741     PVOID dest,
742     ULONG maxSize,
743     PVOID refValue,
744     BOOLEAN bPreview);
745 
746 BOOLEAN ParaNdis_ProcessTx(
747     PARANDIS_ADAPTER *pContext,
748     BOOLEAN IsDpc,
749     BOOLEAN IsInterrupt);
750 
751 BOOLEAN ParaNdis_SetTimer(
752     NDIS_HANDLE timer,
753     LONG millies);
754 
755 BOOLEAN ParaNdis_SynchronizeWithInterrupt(
756     PARANDIS_ADAPTER *pContext,
757     ULONG messageId,
758     tSynchronizedProcedure procedure,
759     PVOID parameter);
760 
761 VOID ParaNdis_Suspend(
762     PARANDIS_ADAPTER *pContext);
763 
764 VOID ParaNdis_Resume(
765     PARANDIS_ADAPTER *pContext);
766 
767 VOID ParaNdis_OnTransmitBufferReleased(
768     PARANDIS_ADAPTER *pContext,
769     IONetDescriptor *pDesc);
770 
771 
772 typedef VOID (*tOnAdditionalPhysicalMemoryAllocated)(
773     PARANDIS_ADAPTER *pContext,
774     tCompletePhysicalAddress *pAddresses);
775 
776 
777 typedef struct _tagPhysicalAddressAllocationContext
778 {
779     tCompletePhysicalAddress address;
780     PARANDIS_ADAPTER *pContext;
781     tOnAdditionalPhysicalMemoryAllocated Callback;
782 } tPhysicalAddressAllocationContext;
783 
784 
785 BOOLEAN ParaNdis_InitialAllocatePhysicalMemory(
786     PARANDIS_ADAPTER *pContext,
787     tCompletePhysicalAddress *pAddresses);
788 
789 VOID ParaNdis_FreePhysicalMemory(
790     PARANDIS_ADAPTER *pContext,
791     tCompletePhysicalAddress *pAddresses);
792 
793 BOOLEAN ParaNdis_BindBufferToPacket(
794     PARANDIS_ADAPTER *pContext,
795     pIONetDescriptor pBufferDesc);
796 
797 void ParaNdis_UnbindBufferFromPacket(
798     PARANDIS_ADAPTER *pContext,
799     pIONetDescriptor pBufferDesc);
800 
801 void ParaNdis_IndicateConnect(
802     PARANDIS_ADAPTER *pContext,
803     BOOLEAN bConnected,
804     BOOLEAN bForce);
805 
806 void ParaNdis_RestoreDeviceConfigurationAfterReset(
807     PARANDIS_ADAPTER *pContext);
808 
809 VOID ParaNdis_UpdateDeviceFilters(
810     PARANDIS_ADAPTER *pContext);
811 
812 VOID ParaNdis_DeviceFiltersUpdateVlanId(
813     PARANDIS_ADAPTER *pContext);
814 
815 VOID ParaNdis_SetPowerState(
816     PARANDIS_ADAPTER *pContext,
817     NDIS_DEVICE_POWER_STATE newState);
818 
819 
820 #endif //-OFFLOAD_UNIT_TEST
821 
822 typedef enum _tagppResult
823 {
824     ppresNotTested = 0,
825     ppresNotIP     = 1,
826     ppresIPV4      = 2,
827     ppresIPV6      = 3,
828     ppresIPTooShort  = 1,
829     ppresPCSOK       = 1,
830     ppresCSOK        = 2,
831     ppresCSBad       = 3,
832     ppresXxpOther    = 1,
833     ppresXxpKnown    = 2,
834     ppresXxpIncomplete = 3,
835     ppresIsTCP         = 0,
836     ppresIsUDP         = 1,
837 }ppResult;
838 
839 typedef union _tagTcpIpPacketParsingResult
840 {
841     struct {
842         /* 0 - not tested, 1 - not IP, 2 - IPV4, 3 - IPV6 */
843         ULONG ipStatus          : 2;
844         /* 0 - not tested, 1 - n/a, 2 - CS, 3 - bad */
845         ULONG ipCheckSum        : 2;
846         /* 0 - not tested, 1 - PCS, 2 - CS, 3 - bad */
847         ULONG xxpCheckSum       : 2;
848         /* 0 - not tested, 1 - other, 2 - known(contains basic TCP or UDP header), 3 - known incomplete */
849         ULONG xxpStatus         : 2;
850         /* 1 - contains complete payload */
851         ULONG xxpFull           : 1;
852         ULONG TcpUdp            : 1;
853         ULONG fixedIpCS         : 1;
854         ULONG fixedXxpCS        : 1;
855         ULONG IsFragment        : 1;
856         ULONG reserved          : 3;
857         ULONG ipHeaderSize      : 8;
858         ULONG XxpIpHeaderSize   : 8;
859     };
860     ULONG value;
861 }tTcpIpPacketParsingResult;
862 
863 typedef enum _tagPacketOffloadRequest
864 {
865     pcrIpChecksum  = (1 << 0),
866     pcrTcpV4Checksum = (1 << 1),
867     pcrUdpV4Checksum = (1 << 2),
868     pcrTcpV6Checksum = (1 << 3),
869     pcrUdpV6Checksum = (1 << 4),
870     pcrTcpChecksum = (pcrTcpV4Checksum | pcrTcpV6Checksum),
871     pcrUdpChecksum = (pcrUdpV4Checksum | pcrUdpV6Checksum),
872     pcrAnyChecksum = (pcrIpChecksum | pcrTcpV4Checksum | pcrUdpV4Checksum | pcrTcpV6Checksum | pcrUdpV6Checksum),
873     pcrLSO   = (1 << 5),
874     pcrIsIP  = (1 << 6),
875     pcrFixIPChecksum = (1 << 7),
876     pcrFixPHChecksum = (1 << 8),
877     pcrFixTcpV4Checksum = (1 << 9),
878     pcrFixUdpV4Checksum = (1 << 10),
879     pcrFixTcpV6Checksum = (1 << 11),
880     pcrFixUdpV6Checksum = (1 << 12),
881     pcrFixXxpChecksum = (pcrFixTcpV4Checksum | pcrFixUdpV4Checksum | pcrFixTcpV6Checksum | pcrFixUdpV6Checksum),
882     pcrPriorityTag = (1 << 13),
883     pcrNoIndirect  = (1 << 14)
884 }tPacketOffloadRequest;
885 
886 // sw offload
887 tTcpIpPacketParsingResult ParaNdis_CheckSumVerify(PVOID buffer, ULONG size, ULONG flags, LPCSTR caller);
888 tTcpIpPacketParsingResult ParaNdis_ReviewIPPacket(PVOID buffer, ULONG size, LPCSTR caller);
889 
890 void ParaNdis_PadPacketReceived(PVOID pDataBuffer, PULONG pLength);
891 
892 #endif
893