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
VirtIODeviceGetHostFeature(PARANDIS_ADAPTER * pContext,unsigned uFeature)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
VirtIODeviceEnableGuestFeature(PARANDIS_ADAPTER * pContext,unsigned uFeature)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
IsTimeToReleaseTx(PARANDIS_ADAPTER * pContext)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
IsValidVlanId(PARANDIS_ADAPTER * pContext,ULONG VlanID)537 static BOOLEAN FORCEINLINE IsValidVlanId(PARANDIS_ADAPTER *pContext, ULONG VlanID)
538 {
539 return pContext->VlanId == 0 || pContext->VlanId == VlanID;
540 }
541
IsVlanSupported(PARANDIS_ADAPTER * pContext)542 static BOOLEAN FORCEINLINE IsVlanSupported(PARANDIS_ADAPTER *pContext)
543 {
544 return pContext->ulPriorityVlanSetting & 2;
545 }
546
IsPrioritySupported(PARANDIS_ADAPTER * pContext)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 *
ParaNdis_GetQueueForInterrupt(PARANDIS_ADAPTER * pContext,ULONG interruptSource)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
ParaNDIS_IsQueueInterruptEnabled(struct virtqueue * _vq)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
ParaNdis_DebugHistory(PARANDIS_ADAPTER * pContext,eHistoryLogOperation op,PVOID pParam1,ULONG lParam2,ULONG lParam3,ULONG lParam4)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