summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--network/ndis/netvmini/6x/680/netvmini680.infbin0 -> 15762 bytes
-rw-r--r--network/ndis/netvmini/6x/680/netvmini680.rc50
-rw-r--r--network/ndis/netvmini/6x/680/netvmini680.vcxproj217
-rw-r--r--network/ndis/netvmini/6x/680/netvmini680.vcxproj.Filters58
-rw-r--r--network/ndis/netvmini/6x/adapter.c11
-rw-r--r--network/ndis/netvmini/6x/adapter.h9
-rw-r--r--network/ndis/netvmini/6x/ctrlpath.c208
-rw-r--r--network/ndis/netvmini/6x/ctrlpath.h4
-rw-r--r--network/ndis/netvmini/6x/miniport.c9
-rw-r--r--network/ndis/netvmini/6x/miniport.h3
-rw-r--r--network/ndis/netvmini/6x/netvmin6.h1
-rw-r--r--network/ndis/netvmini/6x/netvmini.sln13
-rw-r--r--network/ndis/netvmini/6x/rssv2.c1283
-rw-r--r--network/ndis/netvmini/6x/rssv2.h136
-rw-r--r--network/ndis/netvmini/6x/rssv2lib.c657
-rw-r--r--network/ndis/netvmini/6x/rssv2lib.h205
16 files changed, 2863 insertions, 1 deletions
diff --git a/network/ndis/netvmini/6x/680/netvmini680.inf b/network/ndis/netvmini/6x/680/netvmini680.inf
new file mode 100644
index 00000000..876441f2
--- /dev/null
+++ b/network/ndis/netvmini/6x/680/netvmini680.inf
Binary files differ
diff --git a/network/ndis/netvmini/6x/680/netvmini680.rc b/network/ndis/netvmini/6x/680/netvmini680.rc
new file mode 100644
index 00000000..a30405d1
--- /dev/null
+++ b/network/ndis/netvmini/6x/680/netvmini680.rc
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ netvmini680.rc
+
+Abstract:
+
+ Internal resource file for driver.
+
+--*/
+
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR "Microsoft Virtual Miniport Driver"
+#define VER_INTERNALNAME_STR "netvmini680.sys"
+#define VER_ORIGINALFILENAME_STR "netvmini680.sys"
+
+
+#define VER_FILEVERSION 4,30,00,0000
+#define VER_FILEVERSION_STR "4.30.00.0000"
+
+#undef VER_PRODUCTVERSION
+#define VER_PRODUCTVERSION VER_FILEVERSION
+
+#undef VER_PRODUCTVERSION_STR
+#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR
+
+#define VER_LEGALCOPYRIGHT_STR "Copyright (C) 2009 Microsoft Corporation"
+#ifdef VER_COMPANYNAME_STR
+#undef VER_COMPANYNAME_STR
+#define VER_COMPANYNAME_STR "Microsoft Corporation"
+#endif
+
+#undef VER_PRODUCTNAME_STR
+#define VER_PRODUCTNAME_STR "Microsoft Virtual Network Adapter (NDIS 6.80 Miniport)"
+#define VER_LANGNEUTRAL
+
+#include "common.ver"
+
diff --git a/network/ndis/netvmini/6x/680/netvmini680.vcxproj b/network/ndis/netvmini/6x/680/netvmini680.vcxproj
new file mode 100644
index 00000000..503b040b
--- /dev/null
+++ b/network/ndis/netvmini/6x/680/netvmini680.vcxproj
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{7B9C33BA-F817-42B9-A355-9E54854CE9D6}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{173BE266-31F2-4D74-A9C1-35B20D4DD5EA}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>WDM</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>WDM</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>WDM</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>WDM</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems">
+ <ClCompile Include="..\miniport.c; ..\adapter.c; ..\ctrlpath.c; ..\datapath.c; ..\tcbrcb.c; ..\mphal.c; ..\vmq.c; ..\qos.c; ..\rssv2.c; ..\rssv2lib.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>DEBUGP(LEVEL,MSG,...)</WppTraceFunction>
+ </ClCompile>
+ <OtherWpp Include="netvmini680.rc">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>DEBUGP(LEVEL,MSG,...)</WppTraceFunction>
+ </OtherWpp>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>netvmini680</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>netvmini680</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>netvmini680</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>netvmini680</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201;4214;4127</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ndis.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201;4214;4127</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ndis.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201;4214;4127</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ndis.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201;4214;4127</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS680_MINIPORT=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_MINIPORT_DRIVER=1</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ndis.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ResourceCompile Include="netvmini680.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/network/ndis/netvmini/6x/680/netvmini680.vcxproj.Filters b/network/ndis/netvmini/6x/680/netvmini680.vcxproj.Filters
new file mode 100644
index 00000000..f7c43737
--- /dev/null
+++ b/network/ndis/netvmini/6x/680/netvmini680.vcxproj.Filters
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{1FEAFB34-8DD3-4B56-A9A1-F6572B7E94F0}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{4E98F484-F310-4E1A-A097-D7ADBAE1351F}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{D8093E47-6AB1-4358-AC7C-7ACE55606993}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{7E4706EB-3B87-4AB9-BA5C-93CC3E3B78CA}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\adapter.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\ctrlpath.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\datapath.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\miniport.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\mphal.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\qos.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\tcbrcb.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\vmq.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\rssv2.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\rssv2lib.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="netvmini680.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/network/ndis/netvmini/6x/adapter.c b/network/ndis/netvmini/6x/adapter.c
index 0cea21d4..f1beefc8 100644
--- a/network/ndis/netvmini/6x/adapter.c
+++ b/network/ndis/netvmini/6x/adapter.c
@@ -480,6 +480,17 @@ Arguments:
break;
}
+#if (NDIS_SUPPORT_NDIS680)
+ //
+ // Set miniport attributes for supported and enabled NDIS RSS features.
+ //
+ Status = InitializeRSSConfig(Adapter);
+ if (NDIS_STATUS_SUCCESS != Status)
+ {
+ DEBUGP(MP_ERROR, "[%p] InitializeRSSConfig Status 0x%08x\n", Adapter, Status);
+ break;
+ }
+#endif
//
// For hardware devices, you should register your interrupt handlers
// here, using NdisMRegisterInterruptEx.
diff --git a/network/ndis/netvmini/6x/adapter.h b/network/ndis/netvmini/6x/adapter.h
index 7162fc02..cfc540d3 100644
--- a/network/ndis/netvmini/6x/adapter.h
+++ b/network/ndis/netvmini/6x/adapter.h
@@ -299,6 +299,15 @@ typedef struct _MP_ADAPTER
#endif
+#if (NDIS_SUPPORT_NDIS680)
+
+ //
+ // NDIS RSSv2-related data
+ //
+ MP_ADAPTER_RSS_DATA RSSData;
+
+#endif
+
} MP_ADAPTER, *PMP_ADAPTER;
#define MP_ADAPTER_FROM_CONTEXT(_ctx_) ((PMP_ADAPTER)(_ctx_))
diff --git a/network/ndis/netvmini/6x/ctrlpath.c b/network/ndis/netvmini/6x/ctrlpath.c
index 01969705..6a745a36 100644
--- a/network/ndis/netvmini/6x/ctrlpath.c
+++ b/network/ndis/netvmini/6x/ctrlpath.c
@@ -31,6 +31,12 @@ MPMethodRequest(
static
NDIS_STATUS
+MPSynchronousMethodRequest(
+ _In_ PMP_ADAPTER Adapter,
+ _In_ PNDIS_OID_REQUEST NdisRequest);
+
+static
+NDIS_STATUS
MPSetInformation(
_In_ PMP_ADAPTER Adapter,
_In_ PNDIS_OID_REQUEST NdisSetRequest);
@@ -108,6 +114,20 @@ NICSetQOSParameters(
#endif
+#if (NDIS_SUPPORT_NDIS680)
+static
+NDIS_STATUS
+MPSetRSSv2Parameters(
+ _In_ PMP_ADAPTER Adapter,
+ _In_ PNDIS_OID_REQUEST NdisSetRequest);
+
+static
+NDIS_STATUS
+MPSetRSSv2IndirectionTableEntries(
+ _In_ PMP_ADAPTER Adapter,
+ _In_ PNDIS_OID_REQUEST NdisSetRequest);
+#endif
+
static
NDIS_STATUS
MPSetPower(
@@ -194,6 +214,52 @@ Return Value:
return Status;
}
+#if (NDIS_SUPPORT_NDIS680)
+NDIS_STATUS
+MPSynchronousOidRequest(
+ _In_ NDIS_HANDLE MiniportAdapterContext,
+ _In_ PNDIS_OID_REQUEST NdisRequest)
+/*++
+
+Routine Description:
+
+ Entry point called by NDIS to get or set the value of a specified
+ synchronous OID.
+
+Arguments:
+
+ MiniportAdapterContext - Our adapter handle
+ NdisRequest - The OID request to handle
+
+Return Value:
+
+ Return code from the NdisRequest below.
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PMP_ADAPTER Adapter = MP_ADAPTER_FROM_CONTEXT(MiniportAdapterContext);
+
+ DEBUGP(MP_LOUD, "[%p] ---> MPSynchronousOidRequest\n", Adapter);
+
+ switch (NdisRequest->RequestType)
+ {
+ case NdisRequestMethod:
+ Status = MPSynchronousMethodRequest(Adapter, NdisRequest);
+ break;
+ default:
+ //
+ // The entry point may by used by other requests
+ //
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+
+ DEBUGP(MP_LOUD, "[%p] <--- MPSynchronousOidRequest Status = 0x%08x\n", Adapter, Status);
+ return Status;
+}
+#endif
VOID
MPCancelOidRequest(
@@ -875,6 +941,15 @@ Return Value:
NdisSetRequest);
break;
+#if (NDIS_SUPPORT_NDIS680)
+ case OID_GEN_RECEIVE_SCALE_PARAMETERS_V2:
+ //
+ // Update RSSv2 parameters
+ //
+ Status = MPSetRSSv2Parameters(Adapter, NdisSetRequest);
+ break;
+#endif
+
#if (NDIS_SUPPORT_NDIS620)
case OID_PM_ADD_WOL_PATTERN:
case OID_PM_REMOVE_WOL_PATTERN:
@@ -996,6 +1071,55 @@ Return Value:
}
+#if (NDIS_SUPPORT_NDIS680)
+NDIS_STATUS
+MPSynchronousMethodRequest(
+ _In_ PMP_ADAPTER Adapter,
+ _In_ PNDIS_OID_REQUEST NdisRequest)
+/*++
+Routine Description:
+
+ Helper function to perform a synchronous method OID request
+
+Arguments:
+
+ Adapter -
+ NdisRequest - THe synchronous method OID request
+
+Return Value:
+
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_NOT_SUPPORTED
+
+--*/
+{
+ NDIS_STATUS Status;
+ NDIS_OID Oid;
+
+ DEBUGP(MP_LOUD, "[%p] ---> MPSynchronousMethodRequest ", Adapter);
+
+ Oid = NdisRequest->DATA.METHOD_INFORMATION.Oid;
+ DbgPrintOidName(Oid);
+
+ switch (Oid)
+ {
+ case OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES:
+ //
+ // Handle RSSv2 traffic steering OID.
+ //
+ Status = MPSetRSSv2IndirectionTableEntries(Adapter, NdisRequest);
+ break;
+
+ default:
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+
+ DEBUGP(MP_LOUD, "[%p] <--- MPSynchronousMethodRequest Status = 0x%08x\n", Adapter, Status);
+ return Status;
+}
+#endif
NDIS_STATUS
@@ -1753,3 +1877,87 @@ Return Value:
return Status;
}
+
+
+#if (NDIS_SUPPORT_NDIS680)
+static
+NDIS_STATUS
+MPSetRSSv2Parameters(
+ _In_ PMP_ADAPTER Adapter,
+ _In_ PNDIS_OID_REQUEST NdisSetRequest)
+/*++
+Routine Description:
+
+ This routine handles OID_GEN_RECEIVE_SCALE_PARAMETERS_V2 set request.
+
+Arguments:
+
+ Adapter - Pointer to adapter block
+ NdisSetRequest - The OID data for the request
+
+Return Value:
+
+ NDIS_STATUS
+
+--*/
+{
+ struct _SET *Set;
+
+ Set = &NdisSetRequest->DATA.SET_INFORMATION;
+
+ //
+ // Validate the request
+ //
+ if (Set->InformationBufferLength <
+ NDIS_SIZEOF_RECEIVE_SCALE_PARAMETERS_V2_REVISION_1)
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid InformationBufferLength\n");
+
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+
+ return NICSetRSSv2Parameters(Adapter, NdisSetRequest);
+}
+
+
+static
+NDIS_STATUS
+MPSetRSSv2IndirectionTableEntries(
+ _In_ PMP_ADAPTER Adapter,
+ _In_ PNDIS_OID_REQUEST NdisMethodRequest)
+/*++
+Routine Description:
+
+ This routine handles OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES method request.
+
+Arguments:
+
+ Adapter - Pointer to adapter block
+ NdisSetRequest - The OID data for the request
+
+Return Value:
+
+ NDIS_STATUS
+
+--*/
+{
+ struct _METHOD *Method;
+
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ Method = &NdisMethodRequest->DATA.METHOD_INFORMATION;
+
+ //
+ // Validate the request
+ //
+ if (Method->InputBufferLength <
+ NDIS_SIZEOF_RSS_SET_INDIRECTION_ENTRIES_REVISION_1)
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid InformationBufferLength\n");
+
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+
+ return NICSetRSSv2IndirectionTableEntries(Adapter, NdisMethodRequest);
+}
+#endif \ No newline at end of file
diff --git a/network/ndis/netvmini/6x/ctrlpath.h b/network/ndis/netvmini/6x/ctrlpath.h
index 99fd791e..e37f4a95 100644
--- a/network/ndis/netvmini/6x/ctrlpath.h
+++ b/network/ndis/netvmini/6x/ctrlpath.h
@@ -22,7 +22,9 @@ Abstract:
MINIPORT_OID_REQUEST MPOidRequest;
-
+#if (NDIS_SUPPORT_NDIS680)
+MINIPORT_SYNCHRONOUS_OID_REQUEST MPSynchronousOidRequest;
+#endif
#endif // _CTRLPATH_H
diff --git a/network/ndis/netvmini/6x/miniport.c b/network/ndis/netvmini/6x/miniport.c
index 08d8cc3b..317f8c54 100644
--- a/network/ndis/netvmini/6x/miniport.c
+++ b/network/ndis/netvmini/6x/miniport.c
@@ -157,6 +157,9 @@ Arguments:
MPChar.DevicePnPEventNotifyHandler = MPDevicePnpEventNotify;
MPChar.ShutdownHandlerEx = MPShutdownEx;
MPChar.CancelOidRequestHandler = MPCancelOidRequest;
+#if (NDIS_SUPPORT_NDIS680)
+ MPChar.SynchronousOidRequestHandler = MPSynchronousOidRequest;
+#endif
//
// Associate the miniport driver with NDIS by calling the
@@ -592,6 +595,12 @@ DbgPrintOidName(
/* NDIS QoS OIDs for NDIS 6.30 */
MAKECASE(OID_QOS_PARAMETERS)
#endif
+
+#if (NDIS_SUPPORT_NDIS680)
+ /* RSSv2 OIDS*/
+ MAKECASE(OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES)
+ MAKECASE(OID_GEN_RECEIVE_SCALE_PARAMETERS_V2)
+#endif
}
if (oidName)
diff --git a/network/ndis/netvmini/6x/miniport.h b/network/ndis/netvmini/6x/miniport.h
index 9b922b1a..364ad704 100644
--- a/network/ndis/netvmini/6x/miniport.h
+++ b/network/ndis/netvmini/6x/miniport.h
@@ -53,6 +53,9 @@ Abstract:
#elif defined(NDIS630_MINIPORT)
# define MP_NDIS_MAJOR_VERSION 6
# define MP_NDIS_MINOR_VERSION 30
+#elif defined(NDIS680_MINIPORT)
+# define MP_NDIS_MAJOR_VERSION 6
+# define MP_NDIS_MINOR_VERSION 80
#else
# error Unsupported NDIS version
#endif
diff --git a/network/ndis/netvmini/6x/netvmin6.h b/network/ndis/netvmini/6x/netvmin6.h
index 33419487..b7331fc8 100644
--- a/network/ndis/netvmini/6x/netvmin6.h
+++ b/network/ndis/netvmini/6x/netvmin6.h
@@ -33,6 +33,7 @@ _Analysis_mode_(_Analysis_code_type_kernel_driver_);
#include "miniport.h"
#include "vmq.h"
#include "qos.h"
+#include "rssv2.h"
#include "adapter.h"
#include "mphal.h"
#include "tcbrcb.h"
diff --git a/network/ndis/netvmini/6x/netvmini.sln b/network/ndis/netvmini/6x/netvmini.sln
index d42e00a0..e5eaca43 100644
--- a/network/ndis/netvmini/6x/netvmini.sln
+++ b/network/ndis/netvmini/6x/netvmini.sln
@@ -9,12 +9,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "620", "620", "{60E2C616-EC5
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "630", "630", "{C6046890-63CF-4299-B25C-6C97B4ED890A}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "680", "680", "{BB8C555B-1DE0-4C5E-B2FD-12B2B0C7C8B4}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netvmini60", "60\netvmini60.vcxproj", "{50458BE9-A423-44C1-AF44-21D4B5233063}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netvmini620", "620\netvmini620.vcxproj", "{062B87F8-6021-4BE2-B677-3AEF2456CBA0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netvmini630", "630\netvmini630.vcxproj", "{7B9C33BA-F817-42B9-A355-9E54854CE9D6}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netvmini680", "680\netvmini680.vcxproj", "{B08F62D4-7A4C-4789-A0F7-862E622839A7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -47,6 +51,14 @@ Global
{7B9C33BA-F817-42B9-A355-9E54854CE9D6}.Debug|x64.Build.0 = Debug|x64
{7B9C33BA-F817-42B9-A355-9E54854CE9D6}.Release|x64.ActiveCfg = Release|x64
{7B9C33BA-F817-42B9-A355-9E54854CE9D6}.Release|x64.Build.0 = Release|x64
+ {B08F62D4-7A4C-4789-A0F7-862E622839A7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B08F62D4-7A4C-4789-A0F7-862E622839A7}.Debug|Win32.Build.0 = Debug|Win32
+ {B08F62D4-7A4C-4789-A0F7-862E622839A7}.Release|Win32.ActiveCfg = Release|Win32
+ {B08F62D4-7A4C-4789-A0F7-862E622839A7}.Release|Win32.Build.0 = Release|Win32
+ {B08F62D4-7A4C-4789-A0F7-862E622839A7}.Debug|x64.ActiveCfg = Debug|x64
+ {B08F62D4-7A4C-4789-A0F7-862E622839A7}.Debug|x64.Build.0 = Debug|x64
+ {B08F62D4-7A4C-4789-A0F7-862E622839A7}.Release|x64.ActiveCfg = Release|x64
+ {B08F62D4-7A4C-4789-A0F7-862E622839A7}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -55,5 +67,6 @@ Global
{50458BE9-A423-44C1-AF44-21D4B5233063} = {0D16B31B-2170-40BA-8850-F16E85EE02F0}
{062B87F8-6021-4BE2-B677-3AEF2456CBA0} = {60E2C616-EC5B-4B24-ADDD-1BE70657EDEC}
{7B9C33BA-F817-42B9-A355-9E54854CE9D6} = {C6046890-63CF-4299-B25C-6C97B4ED890A}
+ {B08F62D4-7A4C-4789-A0F7-862E622839A7} = {BB8C555B-1DE0-4C5E-B2FD-12B2B0C7C8B4}
EndGlobalSection
EndGlobal
diff --git a/network/ndis/netvmini/6x/rssv2.c b/network/ndis/netvmini/6x/rssv2.c
new file mode 100644
index 00000000..f1785ef4
--- /dev/null
+++ b/network/ndis/netvmini/6x/rssv2.c
@@ -0,0 +1,1283 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ RSSv2.c
+
+Abstract:
+
+ This module implements the NDIS RSSv2-related functionality for the adapter.
+
+--*/
+
+#include "netvmin6.h"
+#include "rssv2.tmh"
+
+//
+// Constant defines the maximum number of processors in the RSS processor set
+// the hardware can support.
+//
+#define RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE 64
+#include "rssv2lib.h"
+
+VOID
+MiniportApplyMoveITECommandToHW(
+ _Inout_ PMP_ADAPTER Adapter,
+ _Inout_ PMP_ADAPTER_VPORT VPort,
+ _In_ PNDIS_RSS_SET_INDIRECTION_ENTRY Command,
+ _In_ UINT8 NewLocalCpuIndex
+ )
+/*++
+Routine Description:
+
+ This routine propagates changes as specified by the move command to the HW.
+
+ NOTE: This routine cannot fail. All failures should have been handled and
+ reported before calling this function.
+
+ If there is an underlying transient condition (for example in FIRWMARE),
+ it is miniport's responsibility to retry to clear transient error.
+
+Arguments:
+
+ Adapter - Pointer to our adapter
+
+ Vport - Pointer to the VPort
+
+ Command - Move command which identifies the steering
+ parameter and the target processor.
+
+ NewLocalCpuIndex - Local index of the target processor the steering
+ parameter is being pointed to.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(Adapter);
+ UNREFERENCED_PARAMETER(VPort);
+ UNREFERENCED_PARAMETER(Command);
+ UNREFERENCED_PARAMETER(NewLocalCpuIndex);
+}
+
+VOID
+MiniportApplyConfigurationToHW(
+ _Inout_ PMP_ADAPTER Adapter,
+ _Inout_ PMP_ADAPTER_VPORT VPort,
+ _In_ BOOLEAN IsRssEnabled,
+ _In_ USHORT NewITCount,
+ _In_ ULONG NewNumberOfQueues
+ )
+/*++
+Routine Description:
+
+ This routine propagates changes as specified by the configuration OID to
+ the HW.
+
+ All failures cases are already handled and before calling this function.
+
+Arguments:
+
+ Adapter - Pointer to our adapter
+
+ Vport - Pointer to the VPort
+
+ IsRssEnabled - New RSS state
+
+ NewITCount - New size of the indirection table
+
+ NewNumberOfQueues - New number of HW queues allocated to the VPort
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(Adapter);
+ UNREFERENCED_PARAMETER(VPort);
+ UNREFERENCED_PARAMETER(IsRssEnabled);
+ UNREFERENCED_PARAMETER(NewITCount);
+ UNREFERENCED_PARAMETER(NewNumberOfQueues);
+}
+
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NDIS_STATUS
+InitializeRSSConfig(
+ _Inout_ PMP_ADAPTER Adapter
+ )
+/*++
+Routine Description:
+
+ This routine will initialize RSS for the miniport.
+
+Arguments:
+
+ Adapter - Pointer to our adapter
+
+Return Value:
+
+ NDIS_STATUS
+
+--*/
+{
+ SIZE_T RssInfoSize;
+ NDIS_STATUS Status;
+
+ DEBUGP(MP_TRACE, "[%p] ---> InitializeRSSConfig\n", Adapter);
+
+ PAGED_CODE();
+
+ RssInfoSize = 0;
+ Status = NdisGetRssProcessorInformation(Adapter->AdapterHandle,
+ NULL,
+ &RssInfoSize);
+
+ if (Status != NDIS_STATUS_BUFFER_TOO_SHORT)
+ {
+ DEBUGP(MP_ERROR, "%s: Unabled to get rss information size\n", __FUNCTION__);
+ goto Cleanup;
+ }
+
+ //
+ // Allocate the neccessary memory for reading the available processors
+ //
+ Adapter->RSSData.RssProcessorInfo =
+ (PNDIS_RSS_PROCESSOR_INFO)ExAllocatePoolWithTag(NonPagedPoolNx,
+ RssInfoSize,
+ 'IRMT');
+ if (Adapter->RSSData.RssProcessorInfo == NULL)
+ {
+ DEBUGP(MP_ERROR, "%s: Failed to allocate memory for rss information\n", __FUNCTION__);
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Cleanup;
+ }
+
+ Status = NdisGetRssProcessorInformation(Adapter->AdapterHandle,
+ Adapter->RSSData.RssProcessorInfo,
+ &RssInfoSize);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DEBUGP(MP_ERROR, "%s: Unabled to get rss information\n", __FUNCTION__);
+ goto Cleanup;
+ }
+
+ Adapter->RSSData.RssProcessorArray = (PNDIS_RSS_PROCESSOR)
+ ((PUCHAR)Adapter->RSSData.RssProcessorInfo +
+ Adapter->RSSData.RssProcessorInfo->RssProcessorArrayOffset);
+
+ Status = NDIS_STATUS_SUCCESS;
+
+Cleanup:
+
+ DEBUGP(MP_TRACE, "<--- [%p] InitializeRSSSConfig Status 0x%08x\n", Adapter, Status);
+
+ return Status;
+}
+
+
+UINT8
+NICSetRSSv2FindProcessorInRssSet(
+ _In_ PMP_ADAPTER Adapter,
+ _In_ PROCESSOR_NUMBER ProcessorNumber
+ )
+/*++
+Routine Description:
+
+ This routine finds processor in RSS table and returns its local index
+ (relative to RSS table).
+
+Arguments:
+
+ Adapter - Pointer to our adapter
+
+ ProcessorNumber - Processor number to lookup
+
+Return Value:
+
+ Local index
+
+--*/
+{
+ UINT8 index;
+ PNDIS_RSS_PROCESSOR processor;
+
+ for (index = 0;
+ index < Adapter->RSSData.RssProcessorInfo->RssProcessorCount;
+ index++)
+ {
+ processor = &Adapter->RSSData.RssProcessorArray[index];
+
+ if ((processor->ProcNum.Group == ProcessorNumber.Group) &&
+ (processor->ProcNum.Number == ProcessorNumber.Number))
+ {
+ return index;
+ }
+ }
+
+ return 0xFF;
+}
+
+
+PROCESSOR_NUMBER
+NICSetRSSv2RssGetBaseProcessor(
+ _In_ PMP_ADAPTER Adapter
+ )
+/*++
+Routine Description:
+
+ This routine returns base RSS processor for the miniport.
+
+Arguments:
+
+ Adapter - Pointer to our adapter
+
+Return Value:
+
+ Processor Number.
+
+--*/
+{
+ PROCESSOR_NUMBER baseProcessor;
+
+ //
+ // Mark processor as invalid.
+ //
+ baseProcessor.Reserved = 1;
+
+ if (Adapter->RSSData.RssProcessorInfo != NULL)
+ {
+ baseProcessor = Adapter->RSSData.RssProcessorInfo->RssBaseProcessor;
+ }
+
+ return baseProcessor;
+}
+
+
+BOOLEAN
+NICSetRSSv2ValidateRssProcessor(
+ _In_ PMP_ADAPTER Adapter,
+ _In_ PROCESSOR_NUMBER ProcessorNumber,
+ _Out_ UINT8* LocalCpuIndex
+ )
+/*++
+Routine Description:
+
+ This routine validates processor against minport's RSS settings, and if it
+ is valid, returns local index.
+
+Arguments:
+
+ Adapter - Pointer to our adapter
+
+ ProcessorNumber - Processor number to validate
+
+ LocalCpuIndex - Poitner to local index if processor is valid
+
+Return Value:
+
+ TRUE if processor is valid, FALSE otherwise.
+
+--*/
+{
+ UINT8 CpuIndex;
+ PNDIS_RSS_PROCESSOR_INFO RssProcessorInfo;
+
+ *LocalCpuIndex = (UINT8)(-1);
+ RssProcessorInfo = Adapter->RSSData.RssProcessorInfo;
+
+ if (ProcessorNumber.Group < (USHORT)RssProcessorInfo->RssBaseProcessor.Group)
+ {
+ DEBUGP(MP_ERROR, "RssValidateProcessor: Invalid Proc Group %d:%d, below RssBaseProcGroup\n",
+ ProcessorNumber.Group, ProcessorNumber.Number);
+ return FALSE;
+ }
+
+ if ((ProcessorNumber.Group == (USHORT)RssProcessorInfo->RssBaseProcessor.Group) &&
+ (ProcessorNumber.Number < (UCHAR)RssProcessorInfo->RssBaseProcessor.Number))
+ {
+ DEBUGP(MP_ERROR, "RssValidateProcessor: Invalid Proc Number %d:%d, below RssBaseProcNumber\n",
+ ProcessorNumber.Group, ProcessorNumber.Number);
+ return FALSE;
+ }
+
+ if (ProcessorNumber.Group > (USHORT)RssProcessorInfo->RssMaxProcessor.Group)
+ {
+ DEBUGP(MP_ERROR, "RssValidateProcessor: Invalid Proc Group %d:%d, above RssMaxProcGroup\n",
+ ProcessorNumber.Group, ProcessorNumber.Number);
+ return FALSE;
+ }
+
+ if ((ProcessorNumber.Group == (USHORT)RssProcessorInfo->RssMaxProcessor.Group) &&
+ (ProcessorNumber.Number > (UCHAR)RssProcessorInfo->RssMaxProcessor.Number))
+ {
+ DEBUGP(MP_ERROR, "RssValidateProcessor: Invalid Proc Number %d:%d, above RssMaxProcNumber\n",
+ ProcessorNumber.Group, ProcessorNumber.Number);
+ return FALSE;
+ }
+
+ CpuIndex = NICSetRSSv2FindProcessorInRssSet(Adapter, ProcessorNumber);
+ if (CpuIndex == 0xFF)
+ {
+ DEBUGP(MP_ERROR, "RssValidateProcessor: Invalid Proc Number %d:%d, outside of RSS table\n",
+ ProcessorNumber.Group, ProcessorNumber.Number);
+ return FALSE;
+ }
+
+ *LocalCpuIndex = CpuIndex;
+
+ return TRUE;
+}
+
+
+NDIS_STATUS
+NICSetRSSv2InitializeVPortRSS (
+ _In_ PMP_ADAPTER Adapter,
+ _Inout_ PMP_ADAPTER_VPORT VPort,
+ _In_ PROCESSOR_NUMBER PrimaryProcessor
+ )
+/*++
+Routine Description:
+
+ This routine initializes RSS state for a given VPort.
+
+Arguments:
+
+ Adapter - Pointer to our adapter
+
+ VPort - Pointer to the VPort which contains RSS state
+
+ PrimaryProcessor - Primary processor to use
+
+Return Value:
+
+ NDIS_STATUS
+
+--*/
+{
+ SIZE_T Size;
+ NDIS_STATUS Status;
+ UINT8 PrimaryProcessorIndex;
+
+ VPort->RssEnabled = FALSE;
+
+ if (!NICSetRSSv2ValidateRssProcessor(Adapter,
+ PrimaryProcessor,
+ &PrimaryProcessorIndex))
+ {
+ DEBUGP(MP_TRACE, "Primary is not a valid RSS processor.\n");
+ Status = NDIS_STATUS_INVALID_DATA;
+ goto Cleanup;
+ }
+
+ Size = RssV2NQEnforcerGetQueueMapSize(RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE);
+
+ VPort->QueueMap = (PRSSV2_QUEUE_MAP)ExAllocatePoolWithTag(NonPagedPoolNx,
+ Size,
+ 'QNMT');
+ if (VPort->QueueMap == NULL)
+ {
+ DEBUGP(MP_TRACE, "Inisufficient memory for QueueMap processor.\n");
+ Status = NDIS_STATUS_RESOURCES;
+ goto Cleanup;
+ }
+
+ RssV2NQEnforcerInitialize(VPort->QueueMap,
+ RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE);
+
+ RtlFillMemory(&VPort->RssV2IndexTable, sizeof(VPort->RssV2IndexTable), 0xFF);
+
+ VPort->DefaultProcessorNumber = PrimaryProcessor;
+ VPort->PrimaryProcessorNumber = PrimaryProcessor;
+ VPort->DefaultProcessorIndex = PrimaryProcessorIndex;
+ VPort->PrimaryProcessorIndex = PrimaryProcessorIndex;
+
+ VPort->RssV2Params.NumberOfIndirectionTableEntries = 1;
+ VPort->RssV2Table[0] = PrimaryProcessor;
+ VPort->RssV2IndexTable[0] = PrimaryProcessorIndex;
+
+ //
+ // When RSS is OFF, only the primary is active and holds a queue reference.
+ //
+ RssV2NQEnforcerReference(VPort->QueueMap, VPort->PrimaryProcessorIndex);
+
+ Status = NDIS_STATUS_SUCCESS;
+
+Cleanup:
+
+ return Status;
+}
+
+
+VOID
+NICSetRSSv2SetCurrentProcessor(
+ _Inout_ PMP_ADAPTER_VPORT VPort,
+ _In_ PNDIS_RSS_SET_INDIRECTION_ENTRY Command,
+ _In_ PROCESSOR_NUMBER NewProcessor,
+ _In_ UINT8 NewCpuIndex
+ )
+/*++
+Routine Description:
+
+ This routine updates tracking information for the steering parameter
+ (Primary, Default or ITE[n]), as selected by the Command.
+
+ Routine is called after the "move command" has fully succeeded.
+
+Arguments:
+
+ VPort - Pointer to the VPort
+
+ Command - Move command used to update steering parameter
+
+ NewProcessor - New processor number
+
+ NewCpuIndex - Corresponding local index
+
+Return Value:
+
+ None.
+
+--*/
+{
+ if ((Command->Flags & NDIS_RSS_SET_INDIRECTION_ENTRY_FLAG_DEFAULT_PROCESSOR) != 0)
+ {
+ VPort->DefaultProcessorIndex = NewCpuIndex;
+ VPort->DefaultProcessorNumber = NewProcessor;
+
+ DEBUGP(MP_TRACE, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: OK: DEFAULT_PROCESSOR: VPortId %d, RssEnabled %d, TargetProc %d:%d \n",
+ Command->VPortId, VPort->RssEnabled, NewProcessor.Group, NewProcessor.Number);
+ }
+ else if ((Command->Flags & NDIS_RSS_SET_INDIRECTION_ENTRY_FLAG_PRIMARY_PROCESSOR) != 0)
+ {
+ VPort->PrimaryProcessorIndex = NewCpuIndex;
+ VPort->PrimaryProcessorNumber = NewProcessor;
+
+ DEBUGP(MP_TRACE, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: OK: PRIMARY_PROCESSOR: VPortId %d, RssEnabled %d, TargetProc %d:%d \n",
+ Command->VPortId, VPort->RssEnabled, NewProcessor.Group, NewProcessor.Number);
+
+ }
+ else if (Command->Flags == 0)
+ {
+ VPort->RssV2IndexTable[Command->IndirectionTableIndex] = NewCpuIndex;
+ VPort->RssV2Table[Command->IndirectionTableIndex] = NewProcessor;
+
+ DEBUGP(MP_TRACE, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: OK: ITE[%d] VPortId %d, RssEnabled %d, TargetProc %d:%d\n",
+ Command->IndirectionTableIndex,
+ Command->VPortId,
+ VPort->RssEnabled,
+ NewProcessor.Group,
+ NewProcessor.Number);
+ }
+}
+
+
+_Success_(return != FALSE)
+BOOLEAN
+NICSetRSSv2ValidateCommandAndGetProcessor (
+ _In_ PMP_ADAPTER_VPORT VPort,
+ _In_ PNDIS_RSS_SET_INDIRECTION_ENTRY Command,
+ _Out_ PPROCESSOR_NUMBER CurrentProcessor,
+ _Out_ UINT8* CurrentCpuIndex,
+ _Out_ BOOLEAN* IsActiveSteeringParameter
+ )
+/*++
+Routine Description:
+
+ This routine validates the move command, and returns information about
+ specified steering parameter (Primary, Default or ITE[n] if command is valid.
+
+Arguments:
+
+ VPort - Pointer to the VPort
+
+ Command - Move command used to update steering parameter
+
+ CurrentProcessor - Pointer which receives processor where steering
+ parameter currenty points to.
+
+ CurrentCpuIndex - Corresponding local index
+
+ IsActiveSteeringParameter - Pointer to the boolean which say if steering
+ parameter is currently ACTIVE or not.
+
+Return Value:
+
+ TRUE if move command is valid, FALSE - otherwise.
+
+--*/
+{
+ BOOLEAN isSucceeded;
+
+ isSucceeded = FALSE;
+ *CurrentCpuIndex = 0xFF;
+ *IsActiveSteeringParameter = FALSE;
+
+ if ((Command->Flags & NDIS_RSS_SET_INDIRECTION_ENTRY_FLAG_DEFAULT_PROCESSOR) != 0)
+ {
+ *CurrentProcessor = VPort->DefaultProcessorNumber;
+ *CurrentCpuIndex = VPort->DefaultProcessorIndex;
+ *IsActiveSteeringParameter = VPort->RssEnabled;
+ isSucceeded = TRUE;
+ }
+ else if ((Command->Flags & NDIS_RSS_SET_INDIRECTION_ENTRY_FLAG_PRIMARY_PROCESSOR) != 0)
+ {
+ *CurrentProcessor = VPort->PrimaryProcessorNumber;
+ *CurrentCpuIndex = VPort->PrimaryProcessorIndex;
+ *IsActiveSteeringParameter = (BOOLEAN)(VPort->RssEnabled == FALSE);
+ isSucceeded = TRUE;
+ }
+ else if (Command->Flags == 0)
+ {
+ if (Command->IndirectionTableIndex <
+ VPort->RssV2Params.NumberOfIndirectionTableEntries)
+ {
+ *CurrentProcessor = VPort->RssV2Table[Command->IndirectionTableIndex];
+ *CurrentCpuIndex = VPort->RssV2IndexTable[Command->IndirectionTableIndex];
+ *IsActiveSteeringParameter = VPort->RssEnabled;
+ isSucceeded = TRUE;
+ }
+ else
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid IndirectionTableIndex(%d) >= %d\n",
+ Command->IndirectionTableIndex,
+ VPort->RssV2Params.NumberOfIndirectionTableEntries);
+ }
+ }
+ else
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid flags=0x%x\n", Command->Flags);
+ }
+
+ return isSucceeded;
+}
+
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NDIS_STATUS
+NICSetRSSv2Parameters(
+ _In_ PMP_ADAPTER Adapter,
+ _In_ PNDIS_OID_REQUEST NdisRequest)
+/*++
+Routine Description:
+
+ This routine handles OID_GEN_RECEIVE_SCALE_PARAMETERS_V2 set request.
+
+Arguments:
+
+ Adapter - Pointer to adapter block
+ NdisRequest - The OID data for the request
+
+Return Value:
+
+ NDIS_STATUS
+
+--*/
+{
+ USHORT EntryIndex;
+ BOOLEAN IsHashInfoChanged;
+ BOOLEAN IsHashKeyChanged;
+ BOOLEAN IsNumITEsChanged;
+ BOOLEAN IsNumQueuesChanged;
+ BOOLEAN IsRssEnabled;
+ UINT8 LocalCpuIndex;
+ USHORT NewITCount;
+ ULONG NewNumberOfQueues;
+ ULONG NumProcs;
+ USHORT OldITCount;
+ PROCESSOR_NUMBER PrimaryProcessorNumber;
+ PROCESSOR_NUMBER ProcessorNumber;
+ PNDIS_RECEIVE_SCALE_PARAMETERS_V2 RssParams;
+ struct _SET *Set;
+ NDIS_STATUS Status;
+ ULONG VPortId;
+ PMP_ADAPTER_VPORT VPort;
+
+ PAGED_CODE();
+
+ DEBUGP(MP_TRACE, "[%p] ---> NICSetRSSv2Parameters\n", Adapter);
+
+ Set = &NdisRequest->DATA.SET_INFORMATION;
+ RssParams = (PNDIS_RECEIVE_SCALE_PARAMETERS_V2)Set->InformationBuffer;
+
+ //
+ // Validate the request
+ //
+ if (RssParams->HashSecretKeySize !=
+ NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2)
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid HashSecretKeySize\n");
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+
+ if ((Set->InformationBufferLength <
+ (RssParams->HashSecretKeyOffset + RssParams->HashSecretKeySize))
+ ||
+ (RssParams->HashSecretKeyOffset <
+ NDIS_SIZEOF_RECEIVE_SCALE_PARAMETERS_V2_REVISION_1))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid HashSecretKeyOffset\n");
+ return NDIS_STATUS_INVALID_LENGTH;
+ }
+
+ if ((NdisRequest->Flags & NDIS_OID_REQUEST_FLAGS_VPORT_ID_VALID) != 0)
+ {
+ DEBUGP(MP_TRACE, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Issued for VPortId=%d, Flags=0x%x \n",
+ NdisRequest->VPortId, RssParams->Flags);
+ VPortId = NdisRequest->VPortId;
+ }
+ else
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Issued for miniport (NativeRSS), Flags=0x%x\n", RssParams->Flags);
+ VPortId = NDIS_INVALID_VPORT_ID;
+ }
+
+ if ((VPortId != NDIS_INVALID_VPORT_ID) &&
+ (VPortId >= MAX_NIC_SWITCH_VPORTS))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid VPortId\n");
+ return NDIS_STATUS_INVALID_PORT;
+ }
+
+ if (VPortId != NDIS_INVALID_VPORT_ID)
+ {
+ VPort = &Adapter->RSSData.VPort[VPortId];
+ }
+ else
+ {
+ VPort = &Adapter->RSSData.NativeVPort;
+ }
+
+ IsNumQueuesChanged =
+ ((RssParams->Flags & NDIS_RECEIVE_SCALE_PARAM_NUMBER_OF_QUEUES_CHANGED) != 0) &&
+ (RssParams->NumberOfQueues != VPort->RssV2Params.NumberOfQueues);
+
+ IsRssEnabled =
+ ((RssParams->Flags & NDIS_RECEIVE_SCALE_PARAM_ENABLE_RSS) != 0);
+
+ IsNumITEsChanged =
+ ((RssParams->Flags & NDIS_RECEIVE_SCALE_PARAM_NUMBER_OF_ENTRIES_CHANGED) != 0) &&
+ (RssParams->NumberOfIndirectionTableEntries !=
+ VPort->RssV2Params.NumberOfIndirectionTableEntries);
+
+ IsHashInfoChanged =
+ ((RssParams->Flags & NDIS_RECEIVE_SCALE_PARAM_HASH_INFO_CHANGED) != 0) &&
+ (VPort->RssV2Params.HashInformation != RssParams->HashInformation);
+
+ IsHashKeyChanged =
+ ((RssParams->Flags & NDIS_RECEIVE_SCALE_PARAM_HASH_KEY_CHANGED) != 0) &&
+ !RtlEqualMemory(&VPort->RssV2Key,
+ (PUCHAR)RssParams + RssParams->HashSecretKeyOffset,
+ RssParams->HashSecretKeySize);
+
+ NewNumberOfQueues = VPort->RssV2Params.NumberOfQueues;
+ if (IsNumQueuesChanged)
+ {
+ NewNumberOfQueues = RssParams->NumberOfQueues;
+ if (VPort->RssEnabled)
+ {
+ //
+ // Check for NQ-violation during queue change.
+ //
+ // Since RSS is enabled, the VPort->QueueMap reflects up-to-date
+ // queue-to-processor mapping.
+ //
+ // Get the number of current referenced processors.
+ //
+ NumProcs = RssV2NQEnforcerGetNumberOfProcs(VPort->QueueMap);
+ if (NumProcs > NewNumberOfQueues)
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId=%d, NQ-Violation (queue change): NQueues=%d < NProcs=%d\n",
+ NdisRequest->VPortId,
+ NewNumberOfQueues,
+ NumProcs);
+ Status = NDIS_STATUS_NO_QUEUES;
+ goto Cleanup;
+ }
+ }
+ }
+
+ OldITCount = (USHORT)VPort->RssV2Params.NumberOfIndirectionTableEntries;
+ NewITCount = OldITCount;
+
+ //
+ // IT size change: check for non-repeat violation during shrinking.
+ //
+ if (IsNumITEsChanged)
+ {
+ NewITCount = (USHORT)RssParams->NumberOfIndirectionTableEntries;
+ if (OldITCount > NewITCount)
+ {
+ ASSERT((OldITCount % NewITCount) == 0);
+
+ //
+ // IT shrinking should fail if pattern is non-repeat.
+ //
+ for (EntryIndex = NewITCount; EntryIndex < OldITCount; EntryIndex++)
+ {
+ ProcessorNumber = VPort->RssV2Table[EntryIndex % NewITCount];
+ if ((ProcessorNumber.Group != VPort->RssV2Table[EntryIndex].Group) ||
+ (ProcessorNumber.Number != VPort->RssV2Table[EntryIndex].Number))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId %d, Cannot shrink IT size from %d to %d, mismatch at ITE[%d]\n",
+ NdisRequest->VPortId,
+ OldITCount,
+ NewITCount,
+ EntryIndex);
+ Status = NDIS_STATUS_INVALID_DATA;
+ goto Cleanup;
+ }
+ }
+ }
+ }
+
+ if (VPort->RssEnabled == FALSE && IsRssEnabled)
+ {
+ RssV2NQEnforcerReset(VPort->QueueMap);
+
+ //
+ // Check for processor numbers sanity in the default processor
+ // and the indirection table.
+ //
+ if (!NICSetRSSv2ValidateRssProcessor(Adapter,
+ VPort->DefaultProcessorNumber,
+ &LocalCpuIndex))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid DedfaultProcessorNumebr: %d:%d \n",
+ VPort->DefaultProcessorNumber.Group,
+ VPort->DefaultProcessorNumber.Number);
+
+ Status = NDIS_STATUS_INVALID_DATA;
+ goto Cleanup;
+ }
+
+ VPort->DefaultProcessorIndex = LocalCpuIndex;
+ RssV2NQEnforcerReference(VPort->QueueMap, LocalCpuIndex);
+
+ OldITCount = (USHORT)VPort->RssV2Params.NumberOfIndirectionTableEntries;
+
+ for (EntryIndex = 0; EntryIndex < OldITCount; EntryIndex++)
+ {
+ ProcessorNumber = VPort->RssV2Table[EntryIndex];
+
+ if (!NICSetRSSv2ValidateRssProcessor(Adapter,
+ ProcessorNumber,
+ &LocalCpuIndex))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid ITE[%d]: %d:%d \n",
+ EntryIndex,
+ ProcessorNumber.Group,
+ ProcessorNumber.Number);
+
+ Status = NDIS_STATUS_INVALID_DATA;
+ goto Cleanup;
+ }
+
+ VPort->RssV2IndexTable[EntryIndex] = LocalCpuIndex;
+ RssV2NQEnforcerReference(VPort->QueueMap, LocalCpuIndex);
+ }
+
+ //
+ // After VPort->QueueMap is built, check for NQ-violation during
+ // RSS enablement.
+ //
+ // Get number of queues after RSS enablement.
+ //
+ NumProcs = RssV2NQEnforcerGetNumberOfProcs(VPort->QueueMap);
+ if (NumProcs > NewNumberOfQueues)
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: NQ-Violation: NQueues=%d < NProcs=%d\n",
+ NewNumberOfQueues,
+ NumProcs);
+ Status = NDIS_STATUS_NO_QUEUES;
+ goto Cleanup;
+ }
+ }
+
+ if (VPort->RssEnabled && (IsRssEnabled == FALSE))
+ {
+ //
+ // Check for primary processor number sanity during RSS=OFF
+ //
+ PrimaryProcessorNumber = VPort->PrimaryProcessorNumber;
+
+ if (!NICSetRSSv2ValidateRssProcessor(Adapter,
+ PrimaryProcessorNumber,
+ &LocalCpuIndex))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid PrimaryProcessorNumebr: %d:%d \n",
+ PrimaryProcessorNumber.Group,
+ PrimaryProcessorNumber.Number);
+
+ Status = NDIS_STATUS_INVALID_DATA;
+ goto Cleanup;
+ }
+
+ RssV2NQEnforcerReset(VPort->QueueMap);
+ VPort->PrimaryProcessorIndex = LocalCpuIndex;
+ RssV2NQEnforcerReference(VPort->QueueMap, LocalCpuIndex);
+ }
+
+ //
+ // COMMIT PASS: NO FAILURES AFTER THIS POINT!
+ //
+ if (IsHashKeyChanged)
+ {
+ VPort->RssV2Params.HashSecretKeySize =
+ RssParams->HashSecretKeySize;
+
+ NdisMoveMemory(&VPort->RssV2Key,
+ (PUCHAR)RssParams + RssParams->HashSecretKeyOffset,
+ RssParams->HashSecretKeySize);
+ }
+
+ if (IsHashInfoChanged)
+ {
+ VPort->RssV2Params.HashInformation = RssParams->HashInformation;
+ }
+
+ //
+ // IT size change: actual application (cannot fail)
+ //
+ if (IsNumITEsChanged)
+ {
+ if (OldITCount < NewITCount)
+ {
+ //
+ // IT expansion
+ //
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId %d, Expand IT size from %d to %d\n",
+ NdisRequest->VPortId, OldITCount, NewITCount);
+
+ ASSERT((NewITCount % OldITCount) == 0);
+ for (EntryIndex = OldITCount; EntryIndex < NewITCount; EntryIndex++)
+ {
+ ProcessorNumber = VPort->RssV2Table[EntryIndex % OldITCount];
+ VPort->RssV2Table[EntryIndex] = ProcessorNumber;
+
+ LocalCpuIndex = VPort->RssV2IndexTable[EntryIndex % OldITCount];
+ VPort->RssV2IndexTable[EntryIndex] = LocalCpuIndex;
+ RssV2NQEnforcerReference(VPort->QueueMap, LocalCpuIndex);
+ }
+ }
+ else if (OldITCount > NewITCount)
+ {
+ //
+ // IT contraction
+ //
+ DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId %d, Shrink IT size from %d to %d\n",
+ NdisRequest->VPortId, OldITCount, NewITCount);
+ ASSERT((OldITCount % NewITCount) == 0);
+
+ for (EntryIndex = NewITCount; EntryIndex < OldITCount; EntryIndex++)
+ {
+ ProcessorNumber = VPort->RssV2Table[EntryIndex % NewITCount];
+ ASSERT(ProcessorNumber.Group == VPort->RssV2Table[EntryIndex].Group);
+ ASSERT(ProcessorNumber.Number == VPort->RssV2Table[EntryIndex].Number);
+ LocalCpuIndex = VPort->RssV2IndexTable[EntryIndex];
+ VPort->RssV2IndexTable[EntryIndex] = 0xFF;
+ RssV2NQEnforcerDereference(VPort->QueueMap, LocalCpuIndex);
+ }
+ }
+ }
+
+ //
+ // Apply new configuration to HW (hash key and information is already in
+ // the VPort object).
+ //
+ MiniportApplyConfigurationToHW(Adapter,
+ VPort,
+ IsRssEnabled,
+ NewITCount,
+ NewNumberOfQueues);
+
+ VPort->RssV2Params.NumberOfIndirectionTableEntries = NewITCount;
+ VPort->RssV2Params.NumberOfQueues = NewNumberOfQueues;
+ VPort->RssEnabled = IsRssEnabled;
+
+ DEBUGP(MP_TRACE, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId=%d, RssEnabled=%d, IT.size=%d\n",
+ NdisRequest->VPortId, IsRssEnabled, VPort->RssV2Params.NumberOfIndirectionTableEntries);
+
+ Set->BytesNeeded = Set->InformationBufferLength;
+ Status = NDIS_STATUS_SUCCESS;
+
+Cleanup:
+
+ DEBUGP(MP_TRACE, "<--- [%p] NICSetRSSv2Parameters Status 0x%08x\n", Adapter, Status);
+
+ return Status;
+}
+
+
+_IRQL_requires_(DISPATCH_LEVEL)
+NDIS_STATUS
+NICSetRSSv2IndirectionTableEntries(
+ _In_ PMP_ADAPTER Adapter,
+ _In_ PNDIS_OID_REQUEST NdisRequest)
+/*++
+Routine Description:
+
+ This routine handles OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES method request.
+
+Arguments:
+
+ Adapter - Pointer to adapter block
+ NdisRequest - The OID data for the request
+
+Return Value:
+
+ NDIS_STATUS
+
+--*/
+{
+ PROCESSOR_NUMBER ActorProcessorNumber;
+ PNDIS_RSS_SET_INDIRECTION_ENTRY Command;
+ RSSV2_PARSING_CONTEXT Context;
+ PROCESSOR_NUMBER CurrentProcessorNumber;
+ PNDIS_RSS_SET_INDIRECTION_ENTRY EntryArray;
+ BOOLEAN IsActive;
+ BOOLEAN IsNativeRss;
+ BOOLEAN IsValid;
+ ULONG InputBufferLength;
+ struct _METHOD *Method;
+ UINT8 NewCpuIndex;
+ ULONG NumCommandsToExecute;
+ UINT8 OldCpuIndex;
+ PNDIS_RSS_SET_INDIRECTION_ENTRIES RssEntries;
+ NDIS_STATUS Status;
+ ULONG SwitchId;
+ PROCESSOR_NUMBER TargetProcessorNumber;
+ ULONG VPortId;
+ PMP_ADAPTER_VPORT VPort;
+
+ //
+ // Allocate a local queue map on stack, to hold temporary results during
+ // handling of each "move all" group.
+ //
+ DECLARE_RSSV2_QUEUE_MAP_ON_STACK(LocalQueueMap,
+ RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE);
+
+ DEBUGP(MP_TRACE, "[%p] ---> NICSetRSSv2IndirectionTableEntries\n", Adapter);
+
+ Method = &NdisRequest->DATA.METHOD_INFORMATION;
+ RssEntries = (PNDIS_RSS_SET_INDIRECTION_ENTRIES)Method->InformationBuffer;
+ InputBufferLength = Method->InputBufferLength;
+
+ Method->BytesRead = 0;
+ Method->BytesNeeded = 0;
+ Method->BytesWritten = 0;
+
+ //
+ // Validate the request
+ //
+ if (InputBufferLength <
+ (NDIS_SIZEOF_RSS_SET_INDIRECTION_ENTRIES_REVISION_1 +
+ RssEntries->NumberOfRssEntries * RssEntries->RssEntrySize))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid InformationBufferLength \n");
+ Status = NDIS_STATUS_INVALID_LENGTH;
+ goto Cleanup;
+ }
+
+ //
+ // RSSv2 spec requires up to 130 entries to be handled in a single batch.
+ //
+ if (RssEntries->NumberOfRssEntries >
+ (2 + MAX_NUMBER_OF_INDIRECTION_TABLE_ENTRIES))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid NumberOfRssEntries \n");
+ Status = NDIS_STATUS_INVALID_DATA;
+ goto Cleanup;
+ }
+
+ KeGetCurrentProcessorNumberEx(&ActorProcessorNumber);
+
+ IsNativeRss = (BOOLEAN)(Adapter->RSSData.IsNicSwitchCreated == FALSE);
+
+ RssV2InitializeParsingContext(&Context, RssEntries, IsNativeRss);
+
+ EntryArray = (PNDIS_RSS_SET_INDIRECTION_ENTRY)
+ ((PUCHAR)RssEntries + RssEntries->RssEntryTableOffset);
+
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Actor %d:%d, NumberOfRssEntries %d \n",
+ ActorProcessorNumber.Group,
+ ActorProcessorNumber.Number,
+ RssEntries->NumberOfRssEntries);
+
+ NumCommandsToExecute = 0;
+
+ //
+ // PASS 1: validation
+ //
+ while (RssV2GetNextCommandRange(&Context, &SwitchId, &VPortId))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: 1ST PASS FOR VPortId=%d\n",
+ VPortId);
+ if (IsNativeRss)
+ {
+ ASSERT(VPortId == NDIS_INVALID_SWITCH_ID);
+ ASSERT(VPortId == NDIS_INVALID_VPORT_ID);
+ VPort = &Adapter->RSSData.NativeVPort;
+ }
+ else
+ {
+ if (SwitchId != NDIS_DEFAULT_SWITCH_ID)
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid SwitchId (%d)\n",
+ SwitchId);
+ RssV2SetCommandRangeStatus(&Context,
+ NDIS_STATUS_INVALID_PARAMETER);
+ continue; // while (RssV2FindNextCommandRange())
+ }
+
+ if (VPortId > MAX_NIC_SWITCH_VPORTS)
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid VPortId (%d)\n",
+ VPortId);
+ RssV2SetCommandRangeStatus(&Context,
+ NDIS_STATUS_INVALID_PARAMETER);
+ continue; // while (RssV2FindNextCommandRange())
+ }
+
+ VPort = &Adapter->RSSData.VPort[VPortId];
+
+ if (VPort->Created == FALSE)
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: VPort %d is not created\n",
+ VPortId);
+ RssV2SetCommandRangeStatus(&Context,
+ NDIS_STATUS_INVALID_PARAMETER);
+ continue; // while (RssV2FindNextCommandRange())
+ }
+
+ if (VPort->Active == FALSE)
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: VPort %d is not active\n",
+ VPortId);
+ RssV2SetCommandRangeStatus(&Context,
+ NDIS_STATUS_INVALID_PORT_STATE);
+ continue; // while (RssV2FindNextCommandRange())
+ }
+ }
+
+ ASSERT(VPort != NULL);
+
+ //
+ // Once valid VPort for the Command range is acquired, perform
+ // validation of individual "move entry" commands.
+ //
+ while ((Command = RssV2GetNextCommand(&Context, FALSE)) != NULL)
+ {
+ if (!NICSetRSSv2ValidateCommandAndGetProcessor(
+ VPort,
+ Command,
+ &CurrentProcessorNumber,
+ &OldCpuIndex,
+ &IsActive))
+ {
+ Command->EntryStatus = NDIS_STATUS_INVALID_PARAMETER;
+ continue; // while (Command = RssV2GetNextCommand())
+ }
+
+ if ((ActorProcessorNumber.Group != CurrentProcessorNumber.Group) ||
+ (ActorProcessorNumber.Number != CurrentProcessorNumber.Number))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: VPortId=%d, Flags=0x%x, EntryIndex=%d: Invalid Actor %d:%d, expected %d:%d\n",
+ Command->VPortId,
+ Command->Flags,
+ Command->IndirectionTableIndex,
+ ActorProcessorNumber.Group,
+ ActorProcessorNumber.Number,
+ CurrentProcessorNumber.Group,
+ CurrentProcessorNumber.Number);
+
+ Command->EntryStatus = NDIS_STATUS_NOT_ACCEPTED;
+ __debugbreak();
+ continue; // while (Command = RssV2GetNextCommand())
+ }
+
+ TargetProcessorNumber = Command->TargetProcessorNumber;
+
+ //
+ // Treat no-op commands as "succeded".
+ //
+ if ((TargetProcessorNumber.Group == CurrentProcessorNumber.Group) &&
+ (TargetProcessorNumber.Number == CurrentProcessorNumber.Number))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: OK1: VPortId=%d, Flags=0x%x, EntryIndex=%d: TargetProc=%d:%d\n",
+ Command->VPortId,
+ Command->Flags,
+ Command->IndirectionTableIndex,
+ TargetProcessorNumber.Group,
+ TargetProcessorNumber.Number);
+
+ Command->EntryStatus = NDIS_STATUS_SUCCESS;
+ continue; // while (Command = RssV2GetNextCommand())
+ }
+
+ if (IsActive == FALSE)
+ {
+ //
+ // INACTIVE steering entities are only tracked and will be
+ // enforced during RSS transition to ON/OFF.
+ //
+ NICSetRSSv2SetCurrentProcessor(VPort,
+ Command,
+ TargetProcessorNumber,
+ 0xFF);
+
+ DEBUGP(MP_ERROR, "NDIS_SET_INDIRECTION_TABLE_ENTRY: OK2: VPortId=%d, Flags=0x%x, EntryIndex=%d, TargetProc=%d:%d\n",
+ Command->VPortId,
+ Command->Flags,
+ Command->IndirectionTableIndex,
+ TargetProcessorNumber.Group,
+ TargetProcessorNumber.Number);
+
+ Command->EntryStatus = NDIS_STATUS_SUCCESS;
+ continue; // while (Command = RssV2GetNextCommand())
+ }
+
+ if (!NICSetRSSv2ValidateRssProcessor(Adapter,
+ TargetProcessorNumber,
+ &NewCpuIndex))
+ {
+ Command->EntryStatus = NDIS_STATUS_INVALID_DATA;
+ continue; // while (Command = RssV2GetNextCommand())
+ }
+
+ //
+ // Marked commands as candidates for NQ-check and HW execution
+ // if they:
+ //
+ // - refer to ACTIVE steering entities
+ // - contain a validated target processor
+ // - target processor actualy changes
+ //
+ ASSERT(Command->EntryStatus == NDIS_STATUS_PENDING);
+ NumCommandsToExecute++;
+ }
+ }
+
+ if (NumCommandsToExecute == 0)
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: 2ND PASS EMPTY FOR VPortId=%d\n",
+ VPortId);
+ Status = NDIS_STATUS_SUCCESS;
+ goto Cleanup;
+ }
+
+ RssV2RestartRangeIterator(&Context);
+
+ //
+ // PASS 2: NQ-enforcement and execution for ACTIVE steering parameters only.
+ //
+ while (RssV2GetNextCommandRange(&Context, &SwitchId, &VPortId))
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: 2ND PASS FOR VPortId=%d\n",
+ VPortId);
+ //
+ // VPorts are already validated
+ //
+ VPort = IsNativeRss ? &Adapter->RSSData.NativeVPort :
+ &Adapter->RSSData.VPort[VPortId];
+
+ RssV2NQEnforcerEnter(VPort->QueueMap, LocalQueueMap);
+
+ //
+ // Iterate over non-processed commands and update LocalQueueMap
+ //
+ while ((Command = RssV2GetNextCommand(&Context, TRUE)) != NULL)
+ {
+ TargetProcessorNumber = Command->TargetProcessorNumber;
+ IsValid = NICSetRSSv2ValidateRssProcessor(Adapter,
+ TargetProcessorNumber,
+ &NewCpuIndex);
+ ASSERT(IsValid);
+
+ IsValid = NICSetRSSv2ValidateCommandAndGetProcessor(
+ VPort,
+ Command,
+ &CurrentProcessorNumber,
+ &OldCpuIndex,
+ &IsActive);
+ ASSERT(IsValid && IsActive);
+ RssV2NQEnforcerUpdate(LocalQueueMap, OldCpuIndex, NewCpuIndex);
+ }
+
+ Status = RssV2NQEnforcerLeave(VPort->QueueMap,
+ LocalQueueMap,
+ VPort->RssV2Params.NumberOfQueues);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: VPortId=%d: NQ-violation: NQueues=%d < NProcs=%d\n",
+ VPortId,
+ VPort->RssV2Params.NumberOfQueues,
+ RssV2NQEnforcerGetNumberOfProcs(LocalQueueMap));
+ RssV2SetCommandRangeStatus(&Context, Status);
+ continue; // while (RssV2GetNextCommandRange())
+ }
+
+ //
+ // NO FAILURES AFTER THIS POINT (INCLUDING IN HW !!!)
+ //
+
+ //
+ // Iterate over the same Command range to actually update the
+ // processor numbers/indices.
+ //
+ RssV2RestartCommandIterator(&Context);
+
+ while ((Command = RssV2GetNextCommand(&Context, TRUE)) != NULL)
+ {
+ TargetProcessorNumber = Command->TargetProcessorNumber;
+ IsValid = NICSetRSSv2ValidateRssProcessor(Adapter,
+ TargetProcessorNumber,
+ &NewCpuIndex);
+ ASSERT(IsValid);
+
+ //
+ // Apply "move ITE" command to hardware
+ //
+ MiniportApplyMoveITECommandToHW(Adapter, VPort, Command, NewCpuIndex);
+
+ //
+ // Reflect the change in software structure.
+ //
+ NICSetRSSv2SetCurrentProcessor(VPort,
+ Command,
+ TargetProcessorNumber,
+ NewCpuIndex);
+
+ DEBUGP(MP_ERROR, "NDIS_SET_INDIRECTION_TABLE_ENTRY: OK3: VPortId=%d, Flags=0x%x, EntryIndex=%d, TargetProc=%d:%d\n",
+ Command->VPortId,
+ Command->Flags,
+ Command->IndirectionTableIndex,
+ TargetProcessorNumber.Group,
+ TargetProcessorNumber.Number);
+
+ Command->EntryStatus = NDIS_STATUS_SUCCESS;
+ }
+ }
+
+
+ Method->BytesRead = InputBufferLength;
+ Method->BytesWritten = InputBufferLength;
+ Status = NDIS_STATUS_SUCCESS;
+
+Cleanup:
+
+ DEBUGP(MP_TRACE, "<--- [%p] NICSetRSSv2IndirectionTableEntries Status 0x%08x\n", Adapter, Status);
+
+ return Status;
+}
diff --git a/network/ndis/netvmini/6x/rssv2.h b/network/ndis/netvmini/6x/rssv2.h
new file mode 100644
index 00000000..7795dfcc
--- /dev/null
+++ b/network/ndis/netvmini/6x/rssv2.h
@@ -0,0 +1,136 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ RSSv2.h
+
+Abstract:
+
+ This module declares the NDIS-RSSv2 related data types, flags, macros, and functions.
+
+Revision History:
+
+--*/
+
+#pragma once
+
+#if (NDIS_SUPPORT_NDIS680)
+
+#define MAX_NIC_SWITCH_VPORTS 64
+
+#define MAX_NUMBER_OF_INDIRECTION_TABLE_ENTRIES \
+ (NDIS_RSS_INDIRECTION_TABLE_MAX_SIZE_REVISION_3 / \
+ sizeof(PROCESSOR_NUMBER))
+
+//
+// This define controls if QueueMap's functionality of the rssv2lib will
+// be compiled-in.
+//
+#define RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE 64
+
+typedef struct _RSSV2_QUEUE_MAP* PRSSV2_QUEUE_MAP;
+typedef struct _MP_ADAPTER_VPORT
+{
+ //
+ // CREATE_VPORT OID was issues for this VPort
+ //
+ BOOLEAN Created;
+
+ //
+ // VPort is activated
+ //
+ BOOLEAN Active;
+
+ //
+ // If HwRSS (VMMQ) is enabled for this VPort
+ //
+ BOOLEAN RssEnabled;
+
+ //
+ // RSSv2 parameters
+ //
+ NDIS_RECEIVE_SCALE_PARAMETERS_V2 RssV2Params;
+
+ //
+ // Hashing key
+ //
+ UCHAR RssV2Key[NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2];
+
+ //
+ // Processor numbers for steering parameters
+ //
+ PROCESSOR_NUMBER PrimaryProcessorNumber;
+ PROCESSOR_NUMBER DefaultProcessorNumber;
+ PROCESSOR_NUMBER RssV2Table[MAX_NUMBER_OF_INDIRECTION_TABLE_ENTRIES];
+
+ //
+ // Local indexes (relative to RSS table) for steering parameters
+ //
+ UINT8 PrimaryProcessorIndex;
+ UINT8 DefaultProcessorIndex;
+ UINT8 RssV2IndexTable[MAX_NUMBER_OF_INDIRECTION_TABLE_ENTRIES];
+
+ //
+ // NQ ("number of queues") enforcement helper object.
+ // Tracks how many entries reference each RSS processor
+ //
+ PRSSV2_QUEUE_MAP QueueMap;
+
+} MP_ADAPTER_VPORT, *PMP_ADAPTER_VPORT;
+
+//
+// The MP_ADAPTER_RSS_DATA structure is used to track RSS state
+//
+typedef struct _MP_ADAPTER_RSS_DATA
+{
+ //
+ // Flag determines if miniport is in Native RSS or NicSwitch mode
+ //
+ BOOLEAN IsNicSwitchCreated;
+
+ //
+ // RSS processor information from NDIS
+ //
+ PNDIS_RSS_PROCESSOR_INFO RssProcessorInfo;
+ PNDIS_RSS_PROCESSOR RssProcessorArray;
+
+ //
+ // RSS state for a single "VPort" in NativeRSS mode
+ //
+ MP_ADAPTER_VPORT NativeVPort;
+
+ //
+ // RSS state for VPorts in NicSwitch mode
+ //
+ MP_ADAPTER_VPORT VPort[MAX_NIC_SWITCH_VPORTS];
+
+} MP_ADAPTER_RSS_DATA, *PMP_ADAPTER_RSS_DATA;
+
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NDIS_STATUS
+InitializeRSSConfig(
+ _Inout_ struct _MP_ADAPTER* Adapter
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NDIS_STATUS
+NICSetRSSv2Parameters(
+ _In_ struct _MP_ADAPTER* Adapter,
+ _In_ PNDIS_OID_REQUEST NdisRequest);
+
+_IRQL_requires_(DISPATCH_LEVEL)
+NDIS_STATUS
+NICSetRSSv2IndirectionTableEntries(
+ _In_ struct _MP_ADAPTER* Adapter,
+ _In_ PNDIS_OID_REQUEST NdisRequest);
+
+
+#endif // NDIS_SUPPORT_NDIS680
diff --git a/network/ndis/netvmini/6x/rssv2lib.c b/network/ndis/netvmini/6x/rssv2lib.c
new file mode 100644
index 00000000..a2bc5550
--- /dev/null
+++ b/network/ndis/netvmini/6x/rssv2lib.c
@@ -0,0 +1,657 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ RSSv2Lib.c
+
+Abstract:
+
+ This module implements RSSv2 helper library.
+
+--*/
+#pragma warning(push)
+#define PRAGMA_ZERO_SIZED_ARRAY 4200
+#define PRAGMA_NAMELESS_STRUCT_UNION 4201
+#define PRAGMA_BIT_FIELD_NOT_INT 4214
+#define PRAGMA_STRUCTURE_PADDED 4324
+#define PRAGMA_NO_RETTYPE_FOR_FUNC 4508
+#pragma warning(disable: PRAGMA_NO_RETTYPE_FOR_FUNC)
+#pragma warning(disable: PRAGMA_ZERO_SIZED_ARRAY)
+#pragma warning(disable: PRAGMA_NAMELESS_STRUCT_UNION)
+#pragma warning(disable: PRAGMA_STRUCTURE_PADDED)
+#include <ndis.h>
+#pragma warning(pop)
+
+#define RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE 64
+#include "rssv2lib.h"
+
+extern
+FORCEINLINE
+VOID
+RssV2InitializeParsingContext (
+ _Out_ PRSSV2_PARSING_CONTEXT Context,
+ _In_ PNDIS_RSS_SET_INDIRECTION_ENTRIES RssV2Oid,
+ _In_ BOOLEAN IsNativeRss
+ )
+/*++
+Routine Description:
+
+ This routine initializes RSSv2 command parsing context from the OID.
+
+Arguments:
+
+ Context - parsing context
+
+ RssV2Oid - OID that needs parsing
+
+ IsNativeRSS - Boolean which tells if the miniport is in NativeRSS mode
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RtlZeroMemory(Context, sizeof(*Context));
+ Context->IsNativeRss = IsNativeRss;
+ Context->RssV2Oid = RssV2Oid;
+ Context->MaxIndex = RssV2Oid->NumberOfRssEntries;
+ Context->LimitIndex = 0;
+ Context->StartIndex = 0;
+ Context->LastStartIndex = 0;
+}
+
+
+_Success_(return != FALSE)
+BOOLEAN
+RssV2GetNextCommandRange (
+ _Inout_ PRSSV2_PARSING_CONTEXT Context,
+ _Out_ ULONG* SwitchId,
+ _Out_ ULONG* VPortId
+ )
+/*++
+Routine Description:
+
+ This routine finds a group of move commands in the OID, which target the
+ same SwitchID & VPortID. It updates the Context to facilitate iteration
+ over the group later.
+
+Arguments:
+
+ Context - parsing context
+
+ SwitchId - pointer to the variable which receives SwitchId
+
+ VPortId - pointer to the variable which receives VPortId
+
+Return Value:
+
+ TRUE if a new group of commands is found, FALSE otherwise.
+
+--*/
+{
+ PNDIS_RSS_SET_INDIRECTION_ENTRY command;
+ ULONG currIndex;
+ BOOLEAN isRangePresent;
+ ULONG switchId;
+ ULONG vPortId;
+
+ isRangePresent = (BOOLEAN)(Context->LimitIndex < Context->MaxIndex);
+
+ if (isRangePresent)
+ {
+ Context->StartIndex = Context->LimitIndex;
+ Context->LastStartIndex = Context->StartIndex;
+
+ if (Context->IsNativeRss)
+ {
+ switchId = NDIS_INVALID_SWITCH_ID;
+ vPortId = NDIS_INVALID_VPORT_ID;
+ currIndex = Context->MaxIndex;
+ }
+ else
+ {
+ currIndex = Context->LimitIndex;
+ command = RSSV2_GET_COMMAND(Context->RssV2Oid, currIndex);
+ switchId = command->SwitchId;
+ vPortId = command->VPortId;
+
+ for (; currIndex < Context->MaxIndex; currIndex++)
+ {
+ command = RSSV2_GET_COMMAND(Context->RssV2Oid, currIndex);
+
+ if ((command->SwitchId != switchId) ||
+ (command->VPortId != vPortId))
+ {
+ break;
+ }
+ }
+ }
+
+ Context->LimitIndex = currIndex;
+ *SwitchId = switchId;
+ *VPortId = vPortId;
+ }
+
+ return isRangePresent;
+}
+
+
+VOID
+RssV2RestartRangeIterator (
+ _Inout_ PRSSV2_PARSING_CONTEXT Context
+ )
+/*++
+Routine Description:
+
+ This routine allows to reset the context with respect to iterations
+ over the command groups.
+
+ This is used by multi-pass OID handlers.
+
+Arguments:
+
+ Context - parsing context
+
+Return Value:
+
+ None.
+
+--*/
+{
+ Context->LimitIndex = 0;
+ Context->StartIndex = 0;
+ Context->LastStartIndex = 0;
+}
+
+
+
+
+PNDIS_RSS_SET_INDIRECTION_ENTRY
+RssV2GetNextCommand (
+ _Inout_ PRSSV2_PARSING_CONTEXT Context,
+ _In_ BOOLEAN SkipProcessedCommands
+ )
+/*++
+Routine Description:
+
+ This routine returns next command from the current command group (which
+ target the same SwitchId & VPortId).
+
+Arguments:
+
+ Context - parsing context
+
+ SkipProcessedCommands - TRUE, if user wants to commands which already
+ have EntryStatus changed from NDIS_STATUS_PENDING.
+ FALSE, if user wants to iterate over all commands.
+
+Return Value:
+
+ Pointer to the next command, NULL - if there are no more commands left.
+
+--*/
+{
+ PNDIS_RSS_SET_INDIRECTION_ENTRY command;
+
+ do
+ {
+ if (Context->StartIndex < Context->LimitIndex)
+ {
+ command = RSSV2_GET_COMMAND(Context->RssV2Oid,
+ Context->StartIndex++);
+ }
+ else
+ {
+ command = NULL;
+ }
+ } while (SkipProcessedCommands &&
+ (command != NULL) &&
+ (command->EntryStatus != NDIS_STATUS_PENDING));
+
+ return command;
+}
+
+
+
+VOID
+RssV2RestartCommandIterator (
+ _Inout_ PRSSV2_PARSING_CONTEXT Context
+ )
+/*++
+Routine Description:
+
+ This routine allows to reset the context with respect to iterations
+ over the commands inside the same command group.
+
+ This is used by multi-pass OID handlers.
+
+Arguments:
+
+ Context - parsing context
+
+Return Value:
+
+ None.
+
+--*/
+{
+ Context->StartIndex = Context->LastStartIndex;
+}
+
+
+VOID
+RssV2SetCommandRangeStatus (
+ _Inout_ PRSSV2_PARSING_CONTEXT Context,
+ _In_ NDIS_STATUS Status
+ )
+/*++
+Routine Description:
+
+ This routine sets EntryStatus for all commands of the current command group
+
+Arguments:
+
+ Context - parsing context
+
+ Status - NDIS_STATUS to set
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG index;
+ PNDIS_RSS_SET_INDIRECTION_ENTRY command;
+
+ for (index = Context->LastStartIndex; index < Context->LimitIndex; index++)
+ {
+ command = RSSV2_GET_COMMAND(Context->RssV2Oid, index);
+ command->EntryStatus = Status;
+ }
+}
+
+
+FORCEINLINE
+PULONG_PTR
+RssV2NQEnforcerGetBitfield (
+ _In_ PRSSV2_QUEUE_MAP QueueMap,
+ _In_ ULONG LocalCpuIndex
+ )
+/*++
+Routine Description:
+
+ Routine finds a pointer to the bitfield for specified
+ (RSS-)local processor index.
+
+Arguments:
+
+ QueueMap - Pointer to the queue map
+
+ LocalCpuIndex - Local index of the processor
+
+Return Value:
+
+ Pointer to the bitfield.
+
+--*/
+{
+ ASSERT(LocalCpuIndex < QueueMap->MaxProcessors);
+
+ return (PULONG_PTR)((PUINT8)QueueMap +
+ sizeof(RSSV2_QUEUE_MAP) +
+ RSSV2_BITFIELD_OFFSET(LocalCpuIndex));
+}
+
+FORCEINLINE
+PUINT8
+RssV2NQEnforceGetReference (
+ _In_ PRSSV2_QUEUE_MAP QueueMap,
+ _In_ ULONG LocalCpuIndex
+ )
+/*++
+Routine Description:
+
+ Routine finds a pointer to the reference counter for the specified
+ (RSS-)local processor index.
+
+Arguments:
+
+ QueueMap - Pointer to the queue map
+
+ LocalCpuIndex - Local index of the processor
+
+Return Value:
+
+ Pointer to the reference coutner.
+
+--*/
+{
+ ASSERT(LocalCpuIndex < QueueMap->MaxProcessors);
+
+ return (PUINT8)((PUINT8)QueueMap +
+ sizeof(RSSV2_QUEUE_MAP) +
+ RSSV2_BITFIELD_SIZE(QueueMap->MaxProcessors) +
+ RSSV2_REFERENCE_OFFSET(LocalCpuIndex));
+}
+
+
+VOID
+RssV2NQEnforcerReset (
+ _Inout_ PRSSV2_QUEUE_MAP QueueMap
+ )
+/*++
+Routine Description:
+
+ Routine resets the already initialized QueueMap.
+
+ Queue Map has zero references by any processors.
+
+Arguments:
+
+ QueueMap - Pointer to the queue map
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RtlZeroMemory(RssV2NQEnforcerGetBitfield(QueueMap, 0),
+ RSSV2_BITFIELD_SIZE(QueueMap->MaxProcessors));
+
+ RtlZeroMemory(RssV2NQEnforceGetReference(QueueMap, 0),
+ RSSV2_REFERENCE_SIZE(QueueMap->MaxProcessors));
+}
+
+
+VOID
+RssV2NQEnforcerInitialize (
+ _Inout_ PRSSV2_QUEUE_MAP QueueMap,
+ _In_ ULONG MaxNumberOfProcessorsInRssTable
+ )
+/*++
+Routine Description:
+
+ Routine initializes the QueueMap.
+
+Arguments:
+
+ QueueMap - Pointer to the queue map
+
+ MaxNumberOfProcessorsInRssTable - Maximum number of processors which
+ RSS table can ever contain.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ QueueMap->MaxProcessors = MaxNumberOfProcessorsInRssTable;
+ KeInitializeSpinLock(&QueueMap->SpinLock);
+ RssV2NQEnforcerReset(QueueMap);
+}
+
+
+VOID
+RssV2NQEnforcerReference (
+ _Inout_ PRSSV2_QUEUE_MAP QueueMap,
+ _In_ ULONG LocalCpuIndex
+ )
+/*++
+Routine Description:
+
+ Routine marks processor as holding a reference. Corresponding bit in
+ the bitfiled is set to 1, and reference count is incremented.
+
+Arguments:
+
+ QueueMap - Pointer to the queue map
+
+ LocalCpuIndex - Local index of the processor
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PUINT8 reference;
+ PULONG_PTR bitfield;
+
+ if (LocalCpuIndex < QueueMap->MaxProcessors)
+ {
+ reference = RssV2NQEnforceGetReference(QueueMap, LocalCpuIndex);
+ *reference += 1;
+
+ bitfield = RssV2NQEnforcerGetBitfield(QueueMap, LocalCpuIndex);
+ *bitfield |= 1UI64 << (LocalCpuIndex % BITS_PER_WORD);
+ }
+}
+
+
+VOID
+RssV2NQEnforcerDereference (
+ _Inout_ PRSSV2_QUEUE_MAP QueueMap,
+ _In_ ULONG LocalCpuIndex
+ )
+/*++
+Routine Description:
+
+ Routine removes one reference cause by the processor. Reference count
+ is decremented, and if it becomes zero, a corresponding bit in
+ the bitfiled is cleared to 0.
+
+Arguments:
+
+ QueueMap - Pointer to the queue map
+
+ LocalCpuIndex - Local index of the processor
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PUINT8 reference;
+ PULONG_PTR bitfield;
+
+ if (LocalCpuIndex < QueueMap->MaxProcessors)
+ {
+ reference = RssV2NQEnforceGetReference(QueueMap, LocalCpuIndex);
+ *reference -= 1;
+ if (*reference == 0)
+ {
+ bitfield = RssV2NQEnforcerGetBitfield(QueueMap, LocalCpuIndex);
+ *bitfield &= ~(1UI64 << (LocalCpuIndex % BITS_PER_WORD));
+ }
+ }
+}
+
+
+VOID
+RssV2NQEnforcerUpdate (
+ _Inout_ PRSSV2_QUEUE_MAP QueueMap,
+ _In_ UINT8 OldCpuIndex,
+ _In_ UINT8 NewCpuIndex
+ )
+/*++
+Routine Description:
+
+ Routine updates references for steering parameter (when it is re-points
+ from one processor to another).
+
+Arguments:
+
+ QueueMap - Pointer to the queue map
+
+ OldCpuIndex - Old local index of the processor used by steering parameter
+
+ NewCpuIndex - New Local index of the processor for the steering parameter
+
+Return Value:
+
+ None.
+
+--*/
+{
+ if (OldCpuIndex != NewCpuIndex)
+ {
+ RssV2NQEnforcerReference(QueueMap, NewCpuIndex);
+ RssV2NQEnforcerDereference(QueueMap, OldCpuIndex);
+ }
+}
+
+
+ULONG
+RssV2NQEnforcerGetNumberOfProcs (
+ _In_ PRSSV2_QUEUE_MAP QueueMap
+ )
+/*++
+Routine Description:
+
+ Routine counts number of bits set to "1" in the bitfield, this telling
+ how many processors are used.
+
+Arguments:
+
+ QueueMap - Pointer to the queue map
+
+
+Return Value:
+
+ Number of processors used.
+
+--*/
+{
+ ULONG localCpuIndex;
+ ULONG numberOfProcessors;
+ PULONG_PTR bitfield;
+
+ numberOfProcessors = 0;
+
+ for (localCpuIndex = 0;
+ localCpuIndex < QueueMap->MaxProcessors;
+ localCpuIndex += BITS_PER_WORD)
+ {
+ bitfield = RssV2NQEnforcerGetBitfield(QueueMap, localCpuIndex);
+ numberOfProcessors += RtlNumberOfSetBitsUlongPtr(*bitfield);
+ }
+
+ return numberOfProcessors;
+}
+
+
+VOID
+RssV2NQEnforcerEnter(
+ _Inout_ PRSSV2_QUEUE_MAP GlobalQueueMap,
+ _Inout_ PRSSV2_QUEUE_MAP LocalQueueMap
+ )
+/*++
+Routine Description:
+
+ Routine takes a spinlock and copies Queue Map locally.
+
+Arguments:
+
+ GlobalQueueMap - Pointer to the global queue map (e.g. VPort's) visible by
+ many processors.
+
+ LocalQueueMap - Pointer to the queue map on stack.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ KeAcquireSpinLockAtDpcLevel(&GlobalQueueMap->SpinLock);
+
+ RtlMoveMemory(LocalQueueMap,
+ GlobalQueueMap,
+ RssV2NQEnforcerGetQueueMapSize(GlobalQueueMap->MaxProcessors));
+}
+
+
+NDIS_STATUS
+RssV2NQEnforcerLeave (
+ _Inout_ PRSSV2_QUEUE_MAP GlobalQueueMap,
+ _In_ PRSSV2_QUEUE_MAP LocalQueueMap,
+ _In_ ULONG QueueLimit
+ )
+/*++
+Routine Description:
+
+ Routine performs "Number of Queues" (NQ-)violation check.
+
+ Usage pattern:
+
+ RssV2NQEnforcerEnter(qm);
+
+ for_all_commands_in_the_current_group()
+ {
+ RssV2NQEnforcerUpdate(qm, oldCpuIndex, newCpuIndex);
+ }
+
+ status = RssV2NQEnforcerLeave(qm);
+ if (FAILED(status)
+ {
+ RssV2SetCommandRangeStatus(&context, status);
+ }
+
+ //
+ // Proceed to apply to HW.
+ //
+
+Arguments:
+
+ GlobalQueueMap - Pointer to the global queue map (e.g. VPort's) visible by
+ many processors.
+
+ LocalQueueMap - Pointer to the queue map on stack. If NQ-check succeeds,
+ the global queue map will be updated from the local copy.
+ If NQ-check fails, local copy will be discarded and global
+ copy is unchanged.
+
+ QueueLimit - Configured maximum number of queues for scaling entity (VPort).
+
+Return Value:
+
+ NDIS_STATUS_SUCCESS - if the accumulated local changes lead to valid
+ configuration.
+
+ NDIS_STATUS_NO_QUEUES - if the accumulated local configuration exceeds
+ QueueLimit.
+
+--*/
+{
+ NDIS_STATUS status;
+
+ if (RssV2NQEnforcerGetNumberOfProcs(LocalQueueMap) <= QueueLimit)
+ {
+ RtlMoveMemory(GlobalQueueMap,
+ LocalQueueMap,
+ RssV2NQEnforcerGetQueueMapSize(GlobalQueueMap->MaxProcessors));
+
+ status = NDIS_STATUS_SUCCESS;
+ }
+ else
+ {
+ status = NDIS_STATUS_NO_QUEUES;
+ }
+
+ KeReleaseSpinLockFromDpcLevel(&GlobalQueueMap->SpinLock);
+
+ return status;
+}
+
diff --git a/network/ndis/netvmini/6x/rssv2lib.h b/network/ndis/netvmini/6x/rssv2lib.h
new file mode 100644
index 00000000..619624ec
--- /dev/null
+++ b/network/ndis/netvmini/6x/rssv2lib.h
@@ -0,0 +1,205 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ RSSv2Lib.h
+
+Abstract:
+
+ This module declares the NDIS RSSv2 helper data types, flags, macros, and functions.
+
+Revision History:
+
+--*/
+
+#pragma once
+
+//
+// Temporary workaround until new definition reaches WDK.
+//
+#if !defined(NDIS_STATUS_NO_QUEUES)
+#define NDIS_STATUS_NO_QUEUES 0xC0230031L
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct _RSSV2_PARSING_CONTEXT
+{
+ PNDIS_RSS_SET_INDIRECTION_ENTRIES RssV2Oid;
+ ULONG MaxIndex;
+ ULONG StartIndex;
+ ULONG LimitIndex;
+ ULONG LastStartIndex;
+ BOOLEAN IsNativeRss;
+
+} RSSV2_PARSING_CONTEXT, *PRSSV2_PARSING_CONTEXT;
+
+
+#define RSSV2_GET_COMMAND(_RssV2Oid_,_Index_) \
+ (PNDIS_RSS_SET_INDIRECTION_ENTRY) \
+ ((PUCHAR)(_RssV2Oid_) + (_RssV2Oid_)->RssEntryTableOffset + \
+ (_Index_) * (_RssV2Oid_)->RssEntrySize)
+
+extern
+FORCEINLINE
+VOID
+RssV2InitializeParsingContext (
+ _Out_ PRSSV2_PARSING_CONTEXT Context,
+ _In_ PNDIS_RSS_SET_INDIRECTION_ENTRIES RssV2Oid,
+ _In_ BOOLEAN IsNativeRss
+ );
+
+_Success_(return != FALSE)
+BOOLEAN
+RssV2GetNextCommandRange (
+ _Inout_ PRSSV2_PARSING_CONTEXT Context,
+ _Out_ ULONG* SwitchId,
+ _Out_ ULONG* VPortId
+ );
+
+VOID
+RssV2RestartRangeIterator (
+ _Inout_ PRSSV2_PARSING_CONTEXT Context
+ );
+
+PNDIS_RSS_SET_INDIRECTION_ENTRY
+RssV2GetNextCommand (
+ _Inout_ PRSSV2_PARSING_CONTEXT Context,
+ _In_ BOOLEAN SkipProcessedCommands
+ );
+
+VOID
+RssV2RestartCommandIterator (
+ _Inout_ PRSSV2_PARSING_CONTEXT Context
+ );
+
+VOID
+RssV2SetCommandRangeStatus (
+ _Inout_ PRSSV2_PARSING_CONTEXT Context,
+ _In_ NDIS_STATUS Status
+ );
+
+//
+// Conditionally include support for example RSSV2_QUEUE_MAP implementation.
+// Miniports don't have to use this implementation (as they may have different
+// locking schema)
+//
+#if defined(RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE) && (RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE != 0)
+
+//
+// Queue map for VPort (or for adapter's in NativeRSS mode)
+//
+#define BITS_PER_WORD (sizeof(ULONG_PTR) * 8)
+#define RSSV2_BITFIELD_OFFSET(_PROC_INDEX_) ((_PROC_INDEX_) / BITS_PER_WORD)
+#define RSSV2_BITFIELD_SIZE(_MAX_PROC_) \
+ sizeof(ULONG_PTR) * (1 + RSSV2_BITFIELD_OFFSET((_MAX_PROC_) - 1))
+
+#define RSSV2_REFERENCE_OFFSET(_PROC_INDEX_) ((_PROC_INDEX_) * sizeof(UINT8))
+#define RSSV2_REFERENCE_SIZE(_MAX_PROC_) ((_MAX_PROC_) * sizeof(UINT8))
+
+typedef struct _RSSV2_QUEUE_MAP
+{
+ //
+ // Members to help enforce "NQ-violation" (per-VPort limit on number of queues)
+ //
+ KSPIN_LOCK SpinLock;
+
+ //
+ // Maximum number of processors in adapter's RSS table.
+ //
+ ULONG MaxProcessors;
+ ULONG ReservedField;
+
+ //
+ // Two variable-size fields follow this structure:
+ //
+ // - Bitmask of referenced processors
+ // - Array with reference counts for each RSS processor
+ // (indexed by a local CPU index, which is relative to RSS table).
+ //
+ //
+ // ULONG_PTR ReferenceBitmask[];
+ // UINT8 ReferenceCount[];
+
+} RSSV2_QUEUE_MAP, *PRSSV2_QUEUE_MAP;
+
+
+#define DECLARE_RSSV2_QUEUE_MAP_ON_STACK(_LOCAL_NAME_, _MAX_PROCS_) \
+ __pragma(warning(suppress: 6255)) \
+ PRSSV2_QUEUE_MAP _LOCAL_NAME_ = \
+ (PRSSV2_QUEUE_MAP)_alloca(RssV2NQEnforcerGetQueueMapSize(_MAX_PROCS_))
+
+FORCEINLINE
+ULONG
+RssV2NQEnforcerGetQueueMapSize (
+ _In_ ULONG MaxNumberOfProcessorsInRssTable
+ )
+{
+ return sizeof(RSSV2_QUEUE_MAP) +
+ RSSV2_BITFIELD_SIZE(MaxNumberOfProcessorsInRssTable) +
+ RSSV2_REFERENCE_SIZE(MaxNumberOfProcessorsInRssTable);
+}
+
+VOID
+RssV2NQEnforcerReset (
+ _Inout_ PRSSV2_QUEUE_MAP QueueMap
+ );
+
+VOID
+RssV2NQEnforcerInitialize (
+ _Inout_ PRSSV2_QUEUE_MAP QueueMap,
+ _In_ ULONG MaxNumberOfProcessorsInRssTable
+ );
+
+VOID
+RssV2NQEnforcerReference (
+ _Inout_ PRSSV2_QUEUE_MAP QueueMap,
+ _In_ ULONG LocalCpuIndex
+ );
+
+VOID
+RssV2NQEnforcerDereference (
+ _Inout_ PRSSV2_QUEUE_MAP QueueMap,
+ _In_ ULONG LocalCpuIndex
+ );
+
+VOID
+RssV2NQEnforcerUpdate (
+ _Inout_ PRSSV2_QUEUE_MAP QueueMap,
+ _In_ UINT8 OldCpuIndex,
+ _In_ UINT8 NewCpuIndex
+ );
+
+ULONG
+RssV2NQEnforcerGetNumberOfProcs (
+ _In_ PRSSV2_QUEUE_MAP QueueMap
+ );
+
+VOID
+RssV2NQEnforcerEnter(
+ _Inout_ PRSSV2_QUEUE_MAP GlobalQueueMap,
+ _Inout_ PRSSV2_QUEUE_MAP LocalQueueMap
+ );
+
+NDIS_STATUS
+RssV2NQEnforcerLeave (
+ _Inout_ PRSSV2_QUEUE_MAP GlobalQueueMap,
+ _In_ PRSSV2_QUEUE_MAP LocalQueueMap,
+ _In_ ULONG QueueLimit
+ );
+
+#endif // defined(RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE) && (RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE != 0)
+
+#ifdef __cplusplus
+}
+#endif