mirror of
https://github.com/reactos/reactos.git
synced 2024-09-10 21:04:26 +00:00
893 lines
28 KiB
C
893 lines
28 KiB
C
/*
|
|
* This file contains general definitions for VirtIO network adapter driver,
|
|
* common for both NDIS5 and NDIS6
|
|
*
|
|
* Copyright (c) 2008-2017 Red Hat, Inc.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met :
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and / or other materials provided with the distribution.
|
|
* 3. Neither the names of the copyright holders nor the names of their contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
#ifndef PARANDIS_56_COMMON_H
|
|
#define PARANDIS_56_COMMON_H
|
|
|
|
//#define PARANDIS_TEST_TX_KICK_ALWAYS
|
|
|
|
#if defined(OFFLOAD_UNIT_TEST)
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
|
|
#define ETH_LENGTH_OF_ADDRESS 6
|
|
#define DoPrint(fmt, ...) printf(fmt##"\n", __VA_ARGS__)
|
|
#define DPrintf(a,b) DoPrint b
|
|
#define RtlOffsetToPointer(B,O) ((PCHAR)( ((PCHAR)(B)) + ((ULONG_PTR)(O)) ))
|
|
|
|
#include "ethernetutils.h"
|
|
#endif //+OFFLOAD_UNIT_TEST
|
|
|
|
#if !defined(OFFLOAD_UNIT_TEST)
|
|
|
|
#if !defined(RtlOffsetToPointer)
|
|
#define RtlOffsetToPointer(Base,Offset) ((PCHAR)(((PCHAR)(Base))+((ULONG_PTR)(Offset))))
|
|
#endif
|
|
|
|
#if !defined(RtlPointerToOffset)
|
|
#define RtlPointerToOffset(Base,Pointer) ((ULONG)(((PCHAR)(Pointer))-((PCHAR)(Base))))
|
|
#endif
|
|
|
|
|
|
#include <ndis.h>
|
|
#include "osdep.h"
|
|
#include "kdebugprint.h"
|
|
#include "ethernetutils.h"
|
|
#include "virtio_pci.h"
|
|
#include "VirtIO.h"
|
|
#include "virtio_ring.h"
|
|
#include "IONetDescriptor.h"
|
|
#include "DebugData.h"
|
|
|
|
// those stuff defined in NDIS
|
|
//NDIS_MINIPORT_MAJOR_VERSION
|
|
//NDIS_MINIPORT_MINOR_VERSION
|
|
// those stuff defined in build environment
|
|
// PARANDIS_MAJOR_DRIVER_VERSION
|
|
// PARANDIS_MINOR_DRIVER_VERSION
|
|
|
|
#if !defined(NDIS_MINIPORT_MAJOR_VERSION) || !defined(NDIS_MINIPORT_MINOR_VERSION)
|
|
#error "Something is wrong with NDIS environment"
|
|
#endif
|
|
|
|
//define to see when the status register is unreadable(see ParaNdis_ResetVirtIONetDevice)
|
|
//#define VIRTIO_RESET_VERIFY
|
|
|
|
//define to if hardware raise interrupt on error (see ParaNdis_DPCWorkBody)
|
|
//#define VIRTIO_SIGNAL_ERROR
|
|
|
|
// define if qemu supports logging to static IO port for synchronization
|
|
// of driver output with qemu printouts; in this case define the port number
|
|
// #define VIRTIO_DBG_USE_IOPORT 0x99
|
|
|
|
// to be set to real limit later
|
|
#define MAX_RX_LOOPS 1000
|
|
|
|
// maximum number of virtio queues used by the driver
|
|
#define MAX_NUM_OF_QUEUES 3
|
|
|
|
/* The feature bitmap for virtio net */
|
|
#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
|
|
#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
|
|
#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
|
|
#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
|
|
#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
|
|
#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */
|
|
#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */
|
|
#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */
|
|
#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */
|
|
#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */
|
|
#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */
|
|
#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */
|
|
#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can handle merged Rx buffers and requires bigger header for that. */
|
|
#define VIRTIO_NET_F_STATUS 16
|
|
#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */
|
|
#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */
|
|
#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */
|
|
#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */
|
|
|
|
#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
|
|
|
|
#define VIRTIO_NET_INVALID_INTERRUPT_STATUS 0xFF
|
|
|
|
#define PARANDIS_MULTICAST_LIST_SIZE 32
|
|
#define PARANDIS_MEMORY_TAG '5muQ'
|
|
#define PARANDIS_FORMAL_LINK_SPEED (pContext->ulFormalLinkSpeed)
|
|
#define PARANDIS_MAXIMUM_TRANSMIT_SPEED PARANDIS_FORMAL_LINK_SPEED
|
|
#define PARANDIS_MAXIMUM_RECEIVE_SPEED PARANDIS_FORMAL_LINK_SPEED
|
|
#define PARANDIS_MIN_LSO_SEGMENTS 2
|
|
// reported
|
|
#define PARANDIS_MAX_LSO_SIZE 0xF800
|
|
|
|
#define PARANDIS_UNLIMITED_PACKETS_TO_INDICATE (~0ul)
|
|
|
|
extern VirtIOSystemOps ParaNdisSystemOps;
|
|
|
|
typedef enum _tagInterruptSource
|
|
{
|
|
isControl = VIRTIO_PCI_ISR_CONFIG,
|
|
isReceive = 0x10,
|
|
isTransmit = 0x20,
|
|
isUnknown = 0x40,
|
|
isBothTransmitReceive = isReceive | isTransmit,
|
|
isAny = isReceive | isTransmit | isControl | isUnknown,
|
|
isDisable = 0x80
|
|
}tInterruptSource;
|
|
|
|
static const ULONG PARANDIS_PACKET_FILTERS =
|
|
NDIS_PACKET_TYPE_DIRECTED |
|
|
NDIS_PACKET_TYPE_MULTICAST |
|
|
NDIS_PACKET_TYPE_BROADCAST |
|
|
NDIS_PACKET_TYPE_PROMISCUOUS |
|
|
NDIS_PACKET_TYPE_ALL_MULTICAST;
|
|
|
|
typedef VOID (*ONPAUSECOMPLETEPROC)(VOID *);
|
|
|
|
|
|
typedef enum _tagSendReceiveState
|
|
{
|
|
srsDisabled = 0, // initial state
|
|
srsPausing,
|
|
srsEnabled
|
|
} tSendReceiveState;
|
|
|
|
typedef struct _tagBusResource {
|
|
NDIS_PHYSICAL_ADDRESS BasePA;
|
|
ULONG uLength;
|
|
PVOID pBase;
|
|
BOOLEAN bPortSpace;
|
|
BOOLEAN bUsed;
|
|
} tBusResource;
|
|
|
|
typedef struct _tagAdapterResources
|
|
{
|
|
tBusResource PciBars[PCI_TYPE0_ADDRESSES];
|
|
ULONG Vector;
|
|
ULONG Level;
|
|
KAFFINITY Affinity;
|
|
ULONG InterruptFlags;
|
|
} tAdapterResources;
|
|
|
|
typedef enum _tagOffloadSettingsBit
|
|
{
|
|
osbT4IpChecksum = (1 << 0),
|
|
osbT4TcpChecksum = (1 << 1),
|
|
osbT4UdpChecksum = (1 << 2),
|
|
osbT4TcpOptionsChecksum = (1 << 3),
|
|
osbT4IpOptionsChecksum = (1 << 4),
|
|
osbT4Lso = (1 << 5),
|
|
osbT4LsoIp = (1 << 6),
|
|
osbT4LsoTcp = (1 << 7),
|
|
osbT4RxTCPChecksum = (1 << 8),
|
|
osbT4RxTCPOptionsChecksum = (1 << 9),
|
|
osbT4RxIPChecksum = (1 << 10),
|
|
osbT4RxIPOptionsChecksum = (1 << 11),
|
|
osbT4RxUDPChecksum = (1 << 12),
|
|
osbT6TcpChecksum = (1 << 13),
|
|
osbT6UdpChecksum = (1 << 14),
|
|
osbT6TcpOptionsChecksum = (1 << 15),
|
|
osbT6IpExtChecksum = (1 << 16),
|
|
osbT6Lso = (1 << 17),
|
|
osbT6LsoIpExt = (1 << 18),
|
|
osbT6LsoTcpOptions = (1 << 19),
|
|
osbT6RxTCPChecksum = (1 << 20),
|
|
osbT6RxTCPOptionsChecksum = (1 << 21),
|
|
osbT6RxUDPChecksum = (1 << 22),
|
|
osbT6RxIpExtChecksum = (1 << 23),
|
|
}tOffloadSettingsBit;
|
|
|
|
typedef struct _tagOffloadSettingsFlags
|
|
{
|
|
ULONG fTxIPChecksum : 1;
|
|
ULONG fTxTCPChecksum : 1;
|
|
ULONG fTxUDPChecksum : 1;
|
|
ULONG fTxTCPOptions : 1;
|
|
ULONG fTxIPOptions : 1;
|
|
ULONG fTxLso : 1;
|
|
ULONG fTxLsoIP : 1;
|
|
ULONG fTxLsoTCP : 1;
|
|
ULONG fRxIPChecksum : 1;
|
|
ULONG fRxTCPChecksum : 1;
|
|
ULONG fRxUDPChecksum : 1;
|
|
ULONG fRxTCPOptions : 1;
|
|
ULONG fRxIPOptions : 1;
|
|
ULONG fTxTCPv6Checksum : 1;
|
|
ULONG fTxUDPv6Checksum : 1;
|
|
ULONG fTxTCPv6Options : 1;
|
|
ULONG fTxIPv6Ext : 1;
|
|
ULONG fTxLsov6 : 1;
|
|
ULONG fTxLsov6IP : 1;
|
|
ULONG fTxLsov6TCP : 1;
|
|
ULONG fRxTCPv6Checksum : 1;
|
|
ULONG fRxUDPv6Checksum : 1;
|
|
ULONG fRxTCPv6Options : 1;
|
|
ULONG fRxIPv6Ext : 1;
|
|
}tOffloadSettingsFlags;
|
|
|
|
|
|
typedef struct _tagOffloadSettings
|
|
{
|
|
/* current value of enabled offload features */
|
|
tOffloadSettingsFlags flags;
|
|
/* load once, do not modify - bitmask of offload features, enabled in configuration */
|
|
ULONG flagsValue;
|
|
ULONG ipHeaderOffset;
|
|
ULONG maxPacketSize;
|
|
}tOffloadSettings;
|
|
|
|
typedef struct _tagChecksumCheckResult
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
ULONG TcpFailed :1;
|
|
ULONG UdpFailed :1;
|
|
ULONG IpFailed :1;
|
|
ULONG TcpOK :1;
|
|
ULONG UdpOK :1;
|
|
ULONG IpOK :1;
|
|
} flags;
|
|
ULONG value;
|
|
};
|
|
}tChecksumCheckResult;
|
|
|
|
/*
|
|
for simplicity, we use for NDIS5 the same statistics as native NDIS6 uses
|
|
*/
|
|
typedef struct _tagNdisStatistics
|
|
{
|
|
ULONG64 ifHCInOctets;
|
|
ULONG64 ifHCInUcastPkts;
|
|
ULONG64 ifHCInUcastOctets;
|
|
ULONG64 ifHCInMulticastPkts;
|
|
ULONG64 ifHCInMulticastOctets;
|
|
ULONG64 ifHCInBroadcastPkts;
|
|
ULONG64 ifHCInBroadcastOctets;
|
|
ULONG64 ifInDiscards;
|
|
ULONG64 ifInErrors;
|
|
ULONG64 ifHCOutOctets;
|
|
ULONG64 ifHCOutUcastPkts;
|
|
ULONG64 ifHCOutUcastOctets;
|
|
ULONG64 ifHCOutMulticastPkts;
|
|
ULONG64 ifHCOutMulticastOctets;
|
|
ULONG64 ifHCOutBroadcastPkts;
|
|
ULONG64 ifHCOutBroadcastOctets;
|
|
ULONG64 ifOutDiscards;
|
|
ULONG64 ifOutErrors;
|
|
}NDIS_STATISTICS_INFO;
|
|
|
|
typedef PNDIS_PACKET tPacketType;
|
|
typedef PNDIS_PACKET tPacketHolderType;
|
|
typedef PNDIS_PACKET tPacketIndicationType;
|
|
|
|
typedef struct _tagNdisOffloadParams
|
|
{
|
|
UCHAR IPv4Checksum;
|
|
UCHAR TCPIPv4Checksum;
|
|
UCHAR UDPIPv4Checksum;
|
|
UCHAR LsoV1;
|
|
UCHAR LsoV2IPv4;
|
|
UCHAR TCPIPv6Checksum;
|
|
UCHAR UDPIPv6Checksum;
|
|
UCHAR LsoV2IPv6;
|
|
}NDIS_OFFLOAD_PARAMETERS;
|
|
|
|
//#define UNIFY_LOCKS
|
|
|
|
typedef struct _tagOurCounters
|
|
{
|
|
UINT nReusedRxBuffers;
|
|
UINT nPrintDiagnostic;
|
|
ULONG64 prevIn;
|
|
UINT nRxInactivity;
|
|
}tOurCounters;
|
|
|
|
typedef struct _tagMaxPacketSize
|
|
{
|
|
UINT nMaxDataSize;
|
|
UINT nMaxFullSizeOS;
|
|
UINT nMaxFullSizeHwTx;
|
|
UINT nMaxFullSizeHwRx;
|
|
}tMaxPacketSize;
|
|
|
|
typedef struct _tagCompletePhysicalAddress
|
|
{
|
|
PHYSICAL_ADDRESS Physical;
|
|
PVOID Virtual;
|
|
ULONG size;
|
|
ULONG IsCached : 1;
|
|
ULONG IsTX : 1;
|
|
} tCompletePhysicalAddress;
|
|
|
|
typedef struct _tagMulticastData
|
|
{
|
|
ULONG nofMulticastEntries;
|
|
UCHAR MulticastList[ETH_LENGTH_OF_ADDRESS * PARANDIS_MULTICAST_LIST_SIZE];
|
|
}tMulticastData;
|
|
|
|
typedef struct _tagIONetDescriptor {
|
|
LIST_ENTRY listEntry;
|
|
tCompletePhysicalAddress HeaderInfo;
|
|
tCompletePhysicalAddress DataInfo;
|
|
tPacketHolderType pHolder;
|
|
PVOID ReferenceValue;
|
|
UINT nofUsedBuffers;
|
|
} IONetDescriptor, * pIONetDescriptor;
|
|
|
|
typedef void (*tReuseReceiveBufferProc)(void *pContext, pIONetDescriptor pDescriptor);
|
|
|
|
typedef struct _tagPARANDIS_ADAPTER
|
|
{
|
|
NDIS_HANDLE DriverHandle;
|
|
NDIS_HANDLE MiniportHandle;
|
|
NDIS_EVENT ResetEvent;
|
|
tAdapterResources AdapterResources;
|
|
tBusResource SharedMemoryRanges[MAX_NUM_OF_QUEUES];
|
|
|
|
VirtIODevice IODevice;
|
|
BOOLEAN bIODeviceInitialized;
|
|
ULONGLONG ullHostFeatures;
|
|
ULONGLONG ullGuestFeatures;
|
|
|
|
LARGE_INTEGER LastTxCompletionTimeStamp;
|
|
#ifdef PARANDIS_DEBUG_INTERRUPTS
|
|
LARGE_INTEGER LastInterruptTimeStamp;
|
|
#endif
|
|
BOOLEAN bConnected;
|
|
BOOLEAN bEnableInterruptHandlingDPC;
|
|
BOOLEAN bEnableInterruptChecking;
|
|
BOOLEAN bDoInterruptRecovery;
|
|
BOOLEAN bDoSupportPriority;
|
|
BOOLEAN bDoHwPacketFiltering;
|
|
BOOLEAN bUseScatterGather;
|
|
BOOLEAN bBatchReceive;
|
|
BOOLEAN bLinkDetectSupported;
|
|
BOOLEAN bDoHardwareChecksum;
|
|
BOOLEAN bDoGuestChecksumOnReceive;
|
|
BOOLEAN bDoIPCheckTx;
|
|
BOOLEAN bDoIPCheckRx;
|
|
BOOLEAN bUseMergedBuffers;
|
|
BOOLEAN bDoKickOnNoBuffer;
|
|
BOOLEAN bSurprizeRemoved;
|
|
BOOLEAN bUsingMSIX;
|
|
BOOLEAN bUseIndirect;
|
|
BOOLEAN bHasHardwareFilters;
|
|
BOOLEAN bHasControlQueue;
|
|
BOOLEAN bNoPauseOnSuspend;
|
|
BOOLEAN bFastSuspendInProcess;
|
|
BOOLEAN bResetInProgress;
|
|
ULONG ulCurrentVlansFilterSet;
|
|
tMulticastData MulticastData;
|
|
UINT uNumberOfHandledRXPacketsInDPC;
|
|
NDIS_DEVICE_POWER_STATE powerState;
|
|
LONG dpcReceiveActive;
|
|
LONG counterDPCInside;
|
|
LONG bDPCInactive;
|
|
LONG InterruptStatus;
|
|
ULONG ulPriorityVlanSetting;
|
|
ULONG VlanId;
|
|
ULONGLONG ulFormalLinkSpeed;
|
|
ULONG ulEnableWakeup;
|
|
tMaxPacketSize MaxPacketSize;
|
|
ULONG nEnableDPCChecker;
|
|
ULONG ulUniqueID;
|
|
UCHAR PermanentMacAddress[ETH_LENGTH_OF_ADDRESS];
|
|
UCHAR CurrentMacAddress[ETH_LENGTH_OF_ADDRESS];
|
|
ULONG PacketFilter;
|
|
ULONG DummyLookAhead;
|
|
ULONG ulMilliesToConnect;
|
|
ULONG nDetectedStoppedTx;
|
|
ULONG nDetectedInactivity;
|
|
ULONG nVirtioHeaderSize;
|
|
/* send part */
|
|
#if !defined(UNIFY_LOCKS)
|
|
NDIS_SPIN_LOCK SendLock;
|
|
NDIS_SPIN_LOCK ReceiveLock;
|
|
#else
|
|
union
|
|
{
|
|
NDIS_SPIN_LOCK SendLock;
|
|
NDIS_SPIN_LOCK ReceiveLock;
|
|
};
|
|
#endif
|
|
NDIS_STATISTICS_INFO Statistics;
|
|
struct
|
|
{
|
|
ULONG framesCSOffload;
|
|
ULONG framesLSO;
|
|
ULONG framesIndirect;
|
|
ULONG framesRxPriority;
|
|
ULONG framesRxCSHwOK;
|
|
ULONG framesRxCSHwMissedBad;
|
|
ULONG framesRxCSHwMissedGood;
|
|
ULONG framesFilteredOut;
|
|
} extraStatistics;
|
|
tOurCounters Counters;
|
|
tOurCounters Limits;
|
|
tSendReceiveState SendState;
|
|
tSendReceiveState ReceiveState;
|
|
ONPAUSECOMPLETEPROC SendPauseCompletionProc;
|
|
ONPAUSECOMPLETEPROC ReceivePauseCompletionProc;
|
|
tReuseReceiveBufferProc ReuseBufferProc;
|
|
/* Net part - management of buffers and queues of QEMU */
|
|
struct virtqueue * NetControlQueue;
|
|
tCompletePhysicalAddress ControlData;
|
|
struct virtqueue * NetReceiveQueue;
|
|
struct virtqueue * NetSendQueue;
|
|
/* list of Rx buffers available for data (under VIRTIO management) */
|
|
LIST_ENTRY NetReceiveBuffers;
|
|
UINT NetNofReceiveBuffers;
|
|
/* list of Rx buffers waiting for return (under NDIS management) */
|
|
LIST_ENTRY NetReceiveBuffersWaiting;
|
|
/* list of Tx buffers in process (under VIRTIO management) */
|
|
LIST_ENTRY NetSendBuffersInUse;
|
|
/* list of Tx buffers ready for data (under MINIPORT management) */
|
|
LIST_ENTRY NetFreeSendBuffers;
|
|
/* current number of free Tx descriptors */
|
|
UINT nofFreeTxDescriptors;
|
|
/* initial number of free Tx descriptor(from cfg) - max number of available Tx descriptors */
|
|
UINT maxFreeTxDescriptors;
|
|
/* current number of free Tx buffers, which can be submitted */
|
|
UINT nofFreeHardwareBuffers;
|
|
/* maximal number of free Tx buffers, which can be used by SG */
|
|
UINT maxFreeHardwareBuffers;
|
|
/* minimal number of free Tx buffers */
|
|
UINT minFreeHardwareBuffers;
|
|
/* current number of Tx packets (or lists) to return */
|
|
LONG NetTxPacketsToReturn;
|
|
/* total of Rx buffer in turnaround */
|
|
UINT NetMaxReceiveBuffers;
|
|
struct VirtIOBufferDescriptor *sgTxGatherTable;
|
|
UINT nPnpEventIndex;
|
|
NDIS_DEVICE_PNP_EVENT PnpEvents[16];
|
|
tOffloadSettings Offload;
|
|
NDIS_OFFLOAD_PARAMETERS InitialOffloadParameters;
|
|
// we keep these members common for XP and Vista
|
|
// for XP and non-MSI case of Vista they are set to zero
|
|
ULONG ulRxMessage;
|
|
ULONG ulTxMessage;
|
|
ULONG ulControlMessage;
|
|
|
|
NDIS_MINIPORT_INTERRUPT Interrupt;
|
|
NDIS_HANDLE PacketPool;
|
|
NDIS_HANDLE BuffersPool;
|
|
NDIS_HANDLE WrapperConfigurationHandle;
|
|
LIST_ENTRY SendQueue;
|
|
LIST_ENTRY TxWaitingList;
|
|
NDIS_EVENT HaltEvent;
|
|
NDIS_TIMER ConnectTimer;
|
|
NDIS_TIMER DPCPostProcessTimer;
|
|
BOOLEAN bDmaInitialized;
|
|
}PARANDIS_ADAPTER, *PPARANDIS_ADAPTER;
|
|
|
|
typedef enum { cpeOK, cpeNoBuffer, cpeInternalError, cpeTooLarge, cpeNoIndirect } tCopyPacketError;
|
|
typedef struct _tagCopyPacketResult
|
|
{
|
|
ULONG size;
|
|
tCopyPacketError error;
|
|
}tCopyPacketResult;
|
|
|
|
typedef struct _tagSynchronizedContext
|
|
{
|
|
PARANDIS_ADAPTER *pContext;
|
|
PVOID Parameter;
|
|
}tSynchronizedContext;
|
|
|
|
typedef BOOLEAN (NTAPI *tSynchronizedProcedure)(tSynchronizedContext *context);
|
|
|
|
/**********************************************************
|
|
LAZY release procedure returns buffers to VirtIO
|
|
only where there are no free buffers available
|
|
|
|
NON-LAZY release releases transmit buffers from VirtIO
|
|
library every time there is something to release
|
|
***********************************************************/
|
|
//#define LAZY_TX_RELEASE
|
|
|
|
static inline bool VirtIODeviceGetHostFeature(PARANDIS_ADAPTER *pContext, unsigned uFeature)
|
|
{
|
|
DPrintf(4, ("%s\n", __FUNCTION__));
|
|
|
|
return virtio_is_feature_enabled(pContext->ullHostFeatures, uFeature);
|
|
}
|
|
|
|
static inline void VirtIODeviceEnableGuestFeature(PARANDIS_ADAPTER *pContext, unsigned uFeature)
|
|
{
|
|
DPrintf(4, ("%s\n", __FUNCTION__));
|
|
|
|
virtio_feature_enable(pContext->ullGuestFeatures, uFeature);
|
|
}
|
|
|
|
static BOOLEAN FORCEINLINE IsTimeToReleaseTx(PARANDIS_ADAPTER *pContext)
|
|
{
|
|
#ifndef LAZY_TX_RELEASE
|
|
return pContext->nofFreeTxDescriptors < pContext->maxFreeTxDescriptors;
|
|
#else
|
|
return pContext->nofFreeTxDescriptors == 0;
|
|
#endif
|
|
}
|
|
|
|
static BOOLEAN FORCEINLINE IsValidVlanId(PARANDIS_ADAPTER *pContext, ULONG VlanID)
|
|
{
|
|
return pContext->VlanId == 0 || pContext->VlanId == VlanID;
|
|
}
|
|
|
|
static BOOLEAN FORCEINLINE IsVlanSupported(PARANDIS_ADAPTER *pContext)
|
|
{
|
|
return pContext->ulPriorityVlanSetting & 2;
|
|
}
|
|
|
|
static BOOLEAN FORCEINLINE IsPrioritySupported(PARANDIS_ADAPTER *pContext)
|
|
{
|
|
return pContext->ulPriorityVlanSetting & 1;
|
|
}
|
|
|
|
BOOLEAN ParaNdis_ValidateMacAddress(
|
|
PUCHAR pcMacAddress,
|
|
BOOLEAN bLocal);
|
|
|
|
NDIS_STATUS ParaNdis_InitializeContext(
|
|
PARANDIS_ADAPTER *pContext,
|
|
PNDIS_RESOURCE_LIST ResourceList);
|
|
|
|
NDIS_STATUS ParaNdis_FinishInitialization(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
VOID ParaNdis_CleanupContext(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
|
|
UINT ParaNdis_VirtIONetReleaseTransmitBuffers(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
ULONG ParaNdis_DPCWorkBody(
|
|
PARANDIS_ADAPTER *pContext,
|
|
ULONG ulMaxPacketsToIndicate);
|
|
|
|
NDIS_STATUS ParaNdis_SetMulticastList(
|
|
PARANDIS_ADAPTER *pContext,
|
|
PVOID Buffer,
|
|
ULONG BufferSize,
|
|
PUINT pBytesRead,
|
|
PUINT pBytesNeeded);
|
|
|
|
VOID ParaNdis_VirtIOEnableIrqSynchronized(
|
|
PARANDIS_ADAPTER *pContext,
|
|
ULONG interruptSource);
|
|
|
|
VOID ParaNdis_VirtIODisableIrqSynchronized(
|
|
PARANDIS_ADAPTER *pContext,
|
|
ULONG interruptSource);
|
|
|
|
static __inline struct virtqueue *
|
|
ParaNdis_GetQueueForInterrupt(PARANDIS_ADAPTER *pContext, ULONG interruptSource)
|
|
{
|
|
if (interruptSource & isTransmit)
|
|
return pContext->NetSendQueue;
|
|
if (interruptSource & isReceive)
|
|
return pContext->NetReceiveQueue;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static __inline BOOLEAN
|
|
ParaNDIS_IsQueueInterruptEnabled(struct virtqueue * _vq)
|
|
{
|
|
return virtqueue_is_interrupt_enabled(_vq);
|
|
}
|
|
|
|
VOID ParaNdis_OnPnPEvent(
|
|
PARANDIS_ADAPTER *pContext,
|
|
NDIS_DEVICE_PNP_EVENT pEvent,
|
|
PVOID pInfo,
|
|
ULONG ulSize);
|
|
|
|
BOOLEAN ParaNdis_OnLegacyInterrupt(
|
|
PARANDIS_ADAPTER *pContext,
|
|
BOOLEAN *pRunDpc);
|
|
|
|
BOOLEAN ParaNdis_OnQueuedInterrupt(
|
|
PARANDIS_ADAPTER *pContext,
|
|
BOOLEAN *pRunDpc,
|
|
ULONG knownInterruptSources);
|
|
|
|
VOID ParaNdis_OnShutdown(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
BOOLEAN ParaNdis_CheckForHang(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
VOID ParaNdis_ReportLinkStatus(
|
|
PARANDIS_ADAPTER *pContext,
|
|
BOOLEAN bForce);
|
|
|
|
NDIS_STATUS ParaNdis_PowerOn(
|
|
PARANDIS_ADAPTER *pContext
|
|
);
|
|
|
|
VOID ParaNdis_PowerOff(
|
|
PARANDIS_ADAPTER *pContext
|
|
);
|
|
|
|
void ParaNdis_DebugInitialize(PVOID DriverObject,PVOID RegistryPath);
|
|
void ParaNdis_DebugCleanup(PDRIVER_OBJECT pDriverObject);
|
|
void ParaNdis_DebugRegisterMiniport(PARANDIS_ADAPTER *pContext, BOOLEAN bRegister);
|
|
|
|
|
|
//#define ENABLE_HISTORY_LOG
|
|
#if !defined(ENABLE_HISTORY_LOG)
|
|
|
|
static void FORCEINLINE ParaNdis_DebugHistory(
|
|
PARANDIS_ADAPTER *pContext,
|
|
eHistoryLogOperation op,
|
|
PVOID pParam1,
|
|
ULONG lParam2,
|
|
ULONG lParam3,
|
|
ULONG lParam4)
|
|
{
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void ParaNdis_DebugHistory(
|
|
PARANDIS_ADAPTER *pContext,
|
|
eHistoryLogOperation op,
|
|
PVOID pParam1,
|
|
ULONG lParam2,
|
|
ULONG lParam3,
|
|
ULONG lParam4);
|
|
|
|
#endif
|
|
|
|
typedef struct _tagTxOperationParameters
|
|
{
|
|
tPacketType packet;
|
|
PVOID ReferenceValue;
|
|
UINT nofSGFragments;
|
|
ULONG ulDataSize;
|
|
ULONG offloadMss;
|
|
ULONG tcpHeaderOffset;
|
|
ULONG flags; //see tPacketOffloadRequest
|
|
}tTxOperationParameters;
|
|
|
|
tCopyPacketResult ParaNdis_DoCopyPacketData(
|
|
PARANDIS_ADAPTER *pContext,
|
|
tTxOperationParameters *pParams);
|
|
|
|
typedef struct _tagMapperResult
|
|
{
|
|
USHORT usBuffersMapped;
|
|
USHORT usBufferSpaceUsed;
|
|
ULONG ulDataSize;
|
|
}tMapperResult;
|
|
|
|
|
|
tCopyPacketResult ParaNdis_DoSubmitPacket(PARANDIS_ADAPTER *pContext, tTxOperationParameters *Params);
|
|
|
|
void ParaNdis_ResetOffloadSettings(PARANDIS_ADAPTER *pContext, tOffloadSettingsFlags *pDest, PULONG from);
|
|
|
|
tChecksumCheckResult ParaNdis_CheckRxChecksum(PARANDIS_ADAPTER *pContext, ULONG virtioFlags, PVOID pRxPacket, ULONG len);
|
|
|
|
void ParaNdis_CallOnBugCheck(PARANDIS_ADAPTER *pContext);
|
|
|
|
/*****************************************************
|
|
Procedures to implement for NDIS specific implementation
|
|
******************************************************/
|
|
|
|
PVOID ParaNdis_AllocateMemory(
|
|
PARANDIS_ADAPTER *pContext,
|
|
ULONG ulRequiredSize);
|
|
|
|
NDIS_STATUS NTAPI ParaNdis_FinishSpecificInitialization(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
VOID ParaNdis_FinalizeCleanup(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
NDIS_HANDLE ParaNdis_OpenNICConfiguration(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
tPacketIndicationType ParaNdis_IndicateReceivedPacket(
|
|
PARANDIS_ADAPTER *pContext,
|
|
PVOID dataBuffer,
|
|
PULONG pLength,
|
|
BOOLEAN bPrepareOnly,
|
|
pIONetDescriptor pBufferDesc);
|
|
|
|
VOID ParaNdis_IndicateReceivedBatch(
|
|
PARANDIS_ADAPTER *pContext,
|
|
tPacketIndicationType *pBatch,
|
|
ULONG nofPackets);
|
|
|
|
VOID ParaNdis_PacketMapper(
|
|
PARANDIS_ADAPTER *pContext,
|
|
tPacketType packet,
|
|
PVOID Reference,
|
|
struct VirtIOBufferDescriptor *buffers,
|
|
pIONetDescriptor pDesc,
|
|
tMapperResult *pMapperResult
|
|
);
|
|
|
|
tCopyPacketResult ParaNdis_PacketCopier(
|
|
tPacketType packet,
|
|
PVOID dest,
|
|
ULONG maxSize,
|
|
PVOID refValue,
|
|
BOOLEAN bPreview);
|
|
|
|
BOOLEAN ParaNdis_ProcessTx(
|
|
PARANDIS_ADAPTER *pContext,
|
|
BOOLEAN IsDpc,
|
|
BOOLEAN IsInterrupt);
|
|
|
|
BOOLEAN ParaNdis_SetTimer(
|
|
NDIS_HANDLE timer,
|
|
LONG millies);
|
|
|
|
BOOLEAN ParaNdis_SynchronizeWithInterrupt(
|
|
PARANDIS_ADAPTER *pContext,
|
|
ULONG messageId,
|
|
tSynchronizedProcedure procedure,
|
|
PVOID parameter);
|
|
|
|
VOID ParaNdis_Suspend(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
VOID ParaNdis_Resume(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
VOID ParaNdis_OnTransmitBufferReleased(
|
|
PARANDIS_ADAPTER *pContext,
|
|
IONetDescriptor *pDesc);
|
|
|
|
|
|
typedef VOID (*tOnAdditionalPhysicalMemoryAllocated)(
|
|
PARANDIS_ADAPTER *pContext,
|
|
tCompletePhysicalAddress *pAddresses);
|
|
|
|
|
|
typedef struct _tagPhysicalAddressAllocationContext
|
|
{
|
|
tCompletePhysicalAddress address;
|
|
PARANDIS_ADAPTER *pContext;
|
|
tOnAdditionalPhysicalMemoryAllocated Callback;
|
|
} tPhysicalAddressAllocationContext;
|
|
|
|
|
|
BOOLEAN ParaNdis_InitialAllocatePhysicalMemory(
|
|
PARANDIS_ADAPTER *pContext,
|
|
tCompletePhysicalAddress *pAddresses);
|
|
|
|
VOID ParaNdis_FreePhysicalMemory(
|
|
PARANDIS_ADAPTER *pContext,
|
|
tCompletePhysicalAddress *pAddresses);
|
|
|
|
BOOLEAN ParaNdis_BindBufferToPacket(
|
|
PARANDIS_ADAPTER *pContext,
|
|
pIONetDescriptor pBufferDesc);
|
|
|
|
void ParaNdis_UnbindBufferFromPacket(
|
|
PARANDIS_ADAPTER *pContext,
|
|
pIONetDescriptor pBufferDesc);
|
|
|
|
void ParaNdis_IndicateConnect(
|
|
PARANDIS_ADAPTER *pContext,
|
|
BOOLEAN bConnected,
|
|
BOOLEAN bForce);
|
|
|
|
void ParaNdis_RestoreDeviceConfigurationAfterReset(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
VOID ParaNdis_UpdateDeviceFilters(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
VOID ParaNdis_DeviceFiltersUpdateVlanId(
|
|
PARANDIS_ADAPTER *pContext);
|
|
|
|
VOID ParaNdis_SetPowerState(
|
|
PARANDIS_ADAPTER *pContext,
|
|
NDIS_DEVICE_POWER_STATE newState);
|
|
|
|
|
|
#endif //-OFFLOAD_UNIT_TEST
|
|
|
|
typedef enum _tagppResult
|
|
{
|
|
ppresNotTested = 0,
|
|
ppresNotIP = 1,
|
|
ppresIPV4 = 2,
|
|
ppresIPV6 = 3,
|
|
ppresIPTooShort = 1,
|
|
ppresPCSOK = 1,
|
|
ppresCSOK = 2,
|
|
ppresCSBad = 3,
|
|
ppresXxpOther = 1,
|
|
ppresXxpKnown = 2,
|
|
ppresXxpIncomplete = 3,
|
|
ppresIsTCP = 0,
|
|
ppresIsUDP = 1,
|
|
}ppResult;
|
|
|
|
typedef union _tagTcpIpPacketParsingResult
|
|
{
|
|
struct {
|
|
/* 0 - not tested, 1 - not IP, 2 - IPV4, 3 - IPV6 */
|
|
ULONG ipStatus : 2;
|
|
/* 0 - not tested, 1 - n/a, 2 - CS, 3 - bad */
|
|
ULONG ipCheckSum : 2;
|
|
/* 0 - not tested, 1 - PCS, 2 - CS, 3 - bad */
|
|
ULONG xxpCheckSum : 2;
|
|
/* 0 - not tested, 1 - other, 2 - known(contains basic TCP or UDP header), 3 - known incomplete */
|
|
ULONG xxpStatus : 2;
|
|
/* 1 - contains complete payload */
|
|
ULONG xxpFull : 1;
|
|
ULONG TcpUdp : 1;
|
|
ULONG fixedIpCS : 1;
|
|
ULONG fixedXxpCS : 1;
|
|
ULONG IsFragment : 1;
|
|
ULONG reserved : 3;
|
|
ULONG ipHeaderSize : 8;
|
|
ULONG XxpIpHeaderSize : 8;
|
|
};
|
|
ULONG value;
|
|
}tTcpIpPacketParsingResult;
|
|
|
|
typedef enum _tagPacketOffloadRequest
|
|
{
|
|
pcrIpChecksum = (1 << 0),
|
|
pcrTcpV4Checksum = (1 << 1),
|
|
pcrUdpV4Checksum = (1 << 2),
|
|
pcrTcpV6Checksum = (1 << 3),
|
|
pcrUdpV6Checksum = (1 << 4),
|
|
pcrTcpChecksum = (pcrTcpV4Checksum | pcrTcpV6Checksum),
|
|
pcrUdpChecksum = (pcrUdpV4Checksum | pcrUdpV6Checksum),
|
|
pcrAnyChecksum = (pcrIpChecksum | pcrTcpV4Checksum | pcrUdpV4Checksum | pcrTcpV6Checksum | pcrUdpV6Checksum),
|
|
pcrLSO = (1 << 5),
|
|
pcrIsIP = (1 << 6),
|
|
pcrFixIPChecksum = (1 << 7),
|
|
pcrFixPHChecksum = (1 << 8),
|
|
pcrFixTcpV4Checksum = (1 << 9),
|
|
pcrFixUdpV4Checksum = (1 << 10),
|
|
pcrFixTcpV6Checksum = (1 << 11),
|
|
pcrFixUdpV6Checksum = (1 << 12),
|
|
pcrFixXxpChecksum = (pcrFixTcpV4Checksum | pcrFixUdpV4Checksum | pcrFixTcpV6Checksum | pcrFixUdpV6Checksum),
|
|
pcrPriorityTag = (1 << 13),
|
|
pcrNoIndirect = (1 << 14)
|
|
}tPacketOffloadRequest;
|
|
|
|
// sw offload
|
|
tTcpIpPacketParsingResult ParaNdis_CheckSumVerify(PVOID buffer, ULONG size, ULONG flags, LPCSTR caller);
|
|
tTcpIpPacketParsingResult ParaNdis_ReviewIPPacket(PVOID buffer, ULONG size, LPCSTR caller);
|
|
|
|
void ParaNdis_PadPacketReceived(PVOID pDataBuffer, PULONG pLength);
|
|
|
|
#endif
|