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 (*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