summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Messer <jmesser@microsoft.com>2018-02-21 15:08:51 -0800
committerJason Messer <jmesser@microsoft.com>2018-02-21 15:08:51 -0800
commitb6aef1fa3437cb7a1d640a7dbe554a43193b7ddd (patch)
tree3027baf1592785ac19508fe048bfc558a514b155
parentffb752bd3b9e2d3f5535f289719c7f4aa0ee8e81 (diff)
downloaddpdk-draft-windows-b6aef1fa3437cb7a1d640a7dbe554a43193b7ddd.zip
dpdk-draft-windows-b6aef1fa3437cb7a1d640a7dbe554a43193b7ddd.tar.gz
dpdk-draft-windows-b6aef1fa3437cb7a1d640a7dbe554a43193b7ddd.tar.xz
Initial commit of UIO driver for Windows
-rw-r--r--lib/librte_eal/windows/netuio/netuio.apsbin0 -> 2920 bytes
-rw-r--r--lib/librte_eal/windows/netuio/netuio.inf112
-rw-r--r--lib/librte_eal/windows/netuio/netuio.rcbin0 -> 4772 bytes
-rw-r--r--lib/librte_eal/windows/netuio/netuio_dev.c332
-rw-r--r--lib/librte_eal/windows/netuio/netuio_dev.h92
-rw-r--r--lib/librte_eal/windows/netuio/netuio_drv.c168
-rw-r--r--lib/librte_eal/windows/netuio/netuio_drv.h59
-rw-r--r--lib/librte_eal/windows/netuio/netuio_interface.h88
-rw-r--r--lib/librte_eal/windows/netuio/netuio_queue.c294
-rw-r--r--lib/librte_eal/windows/netuio/netuio_queue.h56
-rw-r--r--lib/librte_eal/windows/netuio/resource.h14
-rw-r--r--mk/exec-env/windows/netuio/netuio.sln24
-rw-r--r--mk/exec-env/windows/netuio/netuio.vcxproj108
-rw-r--r--mk/exec-env/windows/netuio/netuio.vcxproj.filters59
-rw-r--r--mk/exec-env/windows/netuio/netuio.vcxproj.user11
15 files changed, 1417 insertions, 0 deletions
diff --git a/lib/librte_eal/windows/netuio/netuio.aps b/lib/librte_eal/windows/netuio/netuio.aps
new file mode 100644
index 0000000..09de915
--- /dev/null
+++ b/lib/librte_eal/windows/netuio/netuio.aps
Binary files differ
diff --git a/lib/librte_eal/windows/netuio/netuio.inf b/lib/librte_eal/windows/netuio/netuio.inf
new file mode 100644
index 0000000..6233265
--- /dev/null
+++ b/lib/librte_eal/windows/netuio/netuio.inf
@@ -0,0 +1,112 @@
+;
+; BSD LICENSE
+;
+; Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * 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.
+; * Neither the name of Intel Corporation nor the names of its
+; 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
+; OWNER 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.
+;
+;
+; netuio.inf
+;
+
+[Version]
+Signature="$WINDOWS NT$"
+Class=Net
+ClassGuid={4d36e972-e325-11ce-bfc1-08002be10318}
+Provider=%ManufacturerName%
+CatalogFile=netuio.cat
+DriverVer=
+
+;*****************************************
+; Install Section
+;*****************************************
+
+[Manufacturer]
+%ManufacturerName%=Standard,NT$ARCH$
+
+[Standard.NT$ARCH$]
+%F1583.netuio.Description%=netuio_Device, PCI\VEN_8086&DEV_1583
+%F37D0.netuio.Description%=netuio_Device, PCI\VEN_8086&DEV_37D0
+
+[netuio_Device.NT]
+CopyFiles=Drivers_Dir
+
+[Drivers_Dir]
+netuio.sys
+
+;-------------- Service installation
+[netuio_Device.NT.Services]
+AddService = netuio,%SPSVCINST_ASSOCSERVICE%, netuio_Service_Inst
+
+; -------------- netuio driver install sections
+[netuio_Service_Inst]
+DisplayName = %netuio.SVCDESC%
+ServiceType = 1 ; SERVICE_KERNEL_DRIVER
+StartType = 3 ; SERVICE_DEMAND_START
+ErrorControl = 1 ; SERVICE_ERROR_NORMAL
+ServiceBinary = %12%\netuio.sys
+
+;
+;--- netuio_Device Coinstaller installation ------
+;
+
+[DestinationDirs]
+DefaultDestDir = 12
+netuio_Device_CoInstaller_CopyFiles = 11
+
+[netuio_Device.NT.CoInstallers]
+AddReg=netuio_Device_CoInstaller_AddReg
+CopyFiles=netuio_Device_CoInstaller_CopyFiles
+
+[netuio_Device_CoInstaller_AddReg]
+HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
+
+[netuio_Device_CoInstaller_CopyFiles]
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
+
+[SourceDisksNames]
+1 = %DiskName%,,,""
+
+[SourceDisksFiles]
+netuio.sys = 1,,
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames
+
+[netuio_Device.NT.Wdf]
+KmdfService = netuio, netuio_wdfsect
+[netuio_wdfsect]
+KmdfLibraryVersion = $KMDFVERSION$
+
+[Strings]
+SPSVCINST_ASSOCSERVICE= 0x00000002
+ManufacturerName="Intel"
+ClassName = "Intel(R) DPDK netUIO Driver"
+DiskName = "DPDK netUIO Installation Disk"
+F1583.netuio.Description = "DPDK netUIO for Intel(R) Ethernet Converged Network Adapter XL710-Q2"
+F37D0.netuio.Description = "DPDK netUIO for Intel(R) Ethernet Connection X722"
+netuio.DeviceDesc = "netuio Device"
+netuio.SVCDESC = "netuio Service"
diff --git a/lib/librte_eal/windows/netuio/netuio.rc b/lib/librte_eal/windows/netuio/netuio.rc
new file mode 100644
index 0000000..ec8bf47
--- /dev/null
+++ b/lib/librte_eal/windows/netuio/netuio.rc
Binary files differ
diff --git a/lib/librte_eal/windows/netuio/netuio_dev.c b/lib/librte_eal/windows/netuio/netuio_dev.c
new file mode 100644
index 0000000..37971a9
--- /dev/null
+++ b/lib/librte_eal/windows/netuio/netuio_dev.c
@@ -0,0 +1,332 @@
+/*-
+* BSD LICENSE
+*
+* Copyright(c) 2017 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * 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.
+* * Neither the name of Intel Corporation nor the names of its
+* 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
+* OWNER 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.
+*/
+
+#include <stdio.h>
+#include "netuio_drv.h"
+
+#include <wdmguid.h>
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text (PAGE, netuio_create_device)
+#pragma alloc_text (PAGE, netuio_evt_device_context_cleanup)
+#pragma alloc_text (PAGE, netuio_map_hw_resources)
+#pragma alloc_text (PAGE, netuio_free_hw_resources)
+#endif
+
+/*
+Routine Description:
+ Worker routine called to create a device and its software resources.
+
+Return Value:
+ NTSTATUS
+ */
+NTSTATUS
+netuio_create_device(_Inout_ PWDFDEVICE_INIT DeviceInit)
+{
+ WDF_OBJECT_ATTRIBUTES deviceAttributes;
+ WDFDEVICE device;
+ NTSTATUS status;
+
+ PAGED_CODE();
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, NETUIO_CONTEXT_DATA);
+
+ // Set the device context cleanup callback.
+ // This function will be called when the WDF Device Object associated to the current device is destroyed
+ deviceAttributes.EvtCleanupCallback = netuio_evt_device_context_cleanup;
+
+ status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
+
+ if (NT_SUCCESS(status)) {
+ // Create a device interface so that applications can find and talk to us.
+ status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_netUIO, NULL);
+
+ if (NT_SUCCESS(status)) {
+ // Retrieve and store PCI information
+ status = get_pci_device_info(device);
+ }
+
+ if (NT_SUCCESS(status)) {
+ // Create a symbolic link name for user-space access
+ status = create_device_specific_symbolic_link(device);
+ }
+
+ if (NT_SUCCESS(status)) {
+ // Initialize the I/O Package and any Queues
+ status = netuio_queue_initialize(device);
+ }
+
+ if (NT_SUCCESS(status)) {
+ // Allocate physically contiguous memory for user process use. We'll map it later
+ status = allocate_usermemory_segment(device);
+ }
+ }
+
+ return status;
+}
+
+/*
+Routine Description:
+ Free all the resources allocated in AdfEvtDeviceAdd.
+
+Return Value:
+ None
+ */
+VOID
+netuio_evt_device_context_cleanup(_In_ WDFOBJECT Device)
+{
+ free_usermemory_segment(Device);
+ return;
+}
+
+NTSTATUS
+netuio_map_hw_resources(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST Resources, _In_ WDFCMRESLIST ResourcesTranslated)
+{
+ UNREFERENCED_PARAMETER(Resources);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PNETUIO_CONTEXT_DATA netuio_contextdata;
+ netuio_contextdata = netuio_get_context_data(Device);
+
+ if (!netuio_contextdata)
+ return STATUS_UNSUCCESSFUL;
+
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
+ UINT8 bar_index = 0;
+
+ // Collect device BAR resources from the ResourcesTranslated object
+ for (ULONG idx = 0; idx < WdfCmResourceListGetCount(ResourcesTranslated); idx++) {
+ descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, idx);
+ if (!descriptor) {
+ status = STATUS_DEVICE_CONFIGURATION_ERROR;
+ goto end;
+ }
+
+ switch (descriptor->Type) {
+ case CmResourceTypeMemory:
+ // Retrieve and map the BARs
+ netuio_contextdata->bar[bar_index].base_addr.QuadPart = descriptor->u.Memory.Start.QuadPart;
+ netuio_contextdata->bar[bar_index].size = descriptor->u.Memory.Length;
+ netuio_contextdata->bar[bar_index].virt_addr =
+ MmMapIoSpace(descriptor->u.Memory.Start, descriptor->u.Memory.Length, MmNonCached);
+
+ if (netuio_contextdata->bar[bar_index].virt_addr == NULL) {
+ status = STATUS_UNSUCCESSFUL;
+ goto end;
+ }
+
+ bar_index++;
+ break;
+
+ // Don't handle any other resource type
+ // This could be device-private type added by the PCI bus driver.
+ case CmResourceTypeInterrupt:
+ default:
+ break;
+ }
+ }
+
+ // Allocate an MDL for the device BAR, so that we can map it to the user's process context later...
+ if (status == STATUS_SUCCESS) {
+ // Bar 0 is typically the HW BAR
+ if (netuio_contextdata->bar[0].virt_addr) {
+ netuio_contextdata->dpdk_hw.mdl = IoAllocateMdl(netuio_contextdata->bar[0].virt_addr, (ULONG)netuio_contextdata->bar[0].size, FALSE, FALSE, NULL);
+ if (!netuio_contextdata->dpdk_hw.mdl) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto end;
+ }
+ netuio_contextdata->dpdk_hw.mem.size = netuio_contextdata->bar[0].size;
+ }
+ }
+
+end:
+ return status;
+}
+
+VOID
+netuio_free_hw_resources(_In_ WDFDEVICE Device)
+{
+ PNETUIO_CONTEXT_DATA netuio_contextdata;
+ netuio_contextdata = netuio_get_context_data(Device);
+
+ if (netuio_contextdata) {
+ // Free the allocated MDL
+ if (netuio_contextdata->dpdk_hw.mdl)
+ IoFreeMdl(netuio_contextdata->dpdk_hw.mdl);
+
+ // Unmap all the BAR regions previously mapped
+ for (UINT8 bar_index = 0; bar_index < PCI_MAX_BAR; bar_index++) {
+ if (netuio_contextdata->bar[bar_index].virt_addr)
+ MmUnmapIoSpace(netuio_contextdata->bar[bar_index].virt_addr, netuio_contextdata->bar[bar_index].size);
+ }
+ }
+}
+
+
+static NTSTATUS
+get_pci_device_info(_In_ WDFOBJECT device)
+{
+ NTSTATUS status = STATUS_UNSUCCESSFUL;
+
+ PNETUIO_CONTEXT_DATA netuio_contextdata;
+ netuio_contextdata = netuio_get_context_data(device);
+
+ if (!netuio_contextdata)
+ return status;
+
+ netuio_contextdata->wdf_device = device; // Store for later use
+
+ // Obtain the BUS_INTERFACE_STANDARD interface from the Bus Driver
+ status = WdfFdoQueryForInterface(device, &GUID_BUS_INTERFACE_STANDARD,
+ (PINTERFACE)&netuio_contextdata->bus_interface,
+ sizeof(BUS_INTERFACE_STANDARD), 1, NULL);
+ if (!NT_SUCCESS(status))
+ return status;
+
+ // Retrieve the B:D:F details of our device
+ PDEVICE_OBJECT pdo = NULL;
+ pdo = WdfDeviceWdmGetPhysicalDevice(device);
+ if (pdo) {
+ ULONG prop = 0, length = 0;
+ status = IoGetDeviceProperty(pdo, DevicePropertyBusNumber, sizeof(ULONG), (PVOID)&netuio_contextdata->addr.bus_num, &length);
+ status = IoGetDeviceProperty(pdo, DevicePropertyAddress, sizeof(ULONG), (PVOID)&prop, &length);
+
+ if (NT_SUCCESS(status)) {
+ netuio_contextdata->addr.func_num = prop & 0x0000FFFF;
+ netuio_contextdata->addr.dev_num = ((prop >> 16) & 0x0000FFFF);
+ }
+ // Also, retrieve the NUMA node of the device
+ USHORT numaNode;
+ status = IoGetDeviceNumaNode(pdo, &numaNode);
+ if (NT_SUCCESS(status)) {
+ netuio_contextdata->dev_numa_node = numaNode;
+ }
+ }
+
+ return status;
+}
+
+static NTSTATUS
+create_device_specific_symbolic_link(_In_ WDFOBJECT device)
+{
+ NTSTATUS status = STATUS_UNSUCCESSFUL;
+ UNICODE_STRING netuio_symbolic_link;
+
+ PNETUIO_CONTEXT_DATA netuio_contextdata;
+ netuio_contextdata = netuio_get_context_data(device);
+
+ if (!netuio_contextdata)
+ return status;
+
+ // Build symbolic link name as <netuio_symbolic_link>_BDF (bus/device/func)
+ CHAR symbolic_link[64] = { 0 };
+ sprintf_s(symbolic_link, sizeof(symbolic_link), "%s_%04d%02d%02d",
+ NETUIO_DEVICE_SYMBOLIC_LINK_ANSI, netuio_contextdata->addr.bus_num,
+ netuio_contextdata->addr.dev_num, netuio_contextdata->addr.func_num);
+
+ ANSI_STRING ansi_symbolic_link;
+ RtlInitAnsiString(&ansi_symbolic_link, symbolic_link);
+
+ status = RtlAnsiStringToUnicodeString(&netuio_symbolic_link, &ansi_symbolic_link, TRUE);
+ if (!NT_SUCCESS(status))
+ return status;
+
+ status = WdfDeviceCreateSymbolicLink(device, &netuio_symbolic_link);
+
+ RtlFreeUnicodeString(&netuio_symbolic_link);
+
+ return status;
+}
+
+static NTSTATUS
+allocate_usermemory_segment(_In_ WDFOBJECT device)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PNETUIO_CONTEXT_DATA netuio_contextdata;
+ netuio_contextdata = netuio_get_context_data(device);
+
+ if (!netuio_contextdata)
+ return STATUS_UNSUCCESSFUL;
+
+ PHYSICAL_ADDRESS lowest_acceptable_address;
+ PHYSICAL_ADDRESS highest_acceptable_address;
+ PHYSICAL_ADDRESS boundary_address_multiple;
+
+ lowest_acceptable_address.QuadPart = 0x0000000000800000;
+ highest_acceptable_address.QuadPart = 0xFFFFFFFFFFFFFFFF;
+ boundary_address_multiple.QuadPart = 0;
+
+ // Allocate physically contiguous memory for user process use
+ netuio_contextdata->dpdk_seg.mem.virt_addr =
+ MmAllocateContiguousMemorySpecifyCache(USER_MEMORY_SEGMENT_SIZE,
+ lowest_acceptable_address,
+ highest_acceptable_address,
+ boundary_address_multiple,
+ MmCached);
+
+ if (!netuio_contextdata->dpdk_seg.mem.virt_addr) {
+ status = STATUS_NO_MEMORY;
+ goto end;
+ }
+
+ netuio_contextdata->dpdk_seg.mem.size = USER_MEMORY_SEGMENT_SIZE;
+
+ // Allocate an MDL for this memory region - so that we can map it into the user's process context later
+ netuio_contextdata->dpdk_seg.mdl = IoAllocateMdl((PVOID)netuio_contextdata->dpdk_seg.mem.virt_addr, USER_MEMORY_SEGMENT_SIZE, FALSE, FALSE, NULL);
+ if (netuio_contextdata->dpdk_seg.mdl == NULL) {
+ status = STATUS_NO_MEMORY;
+ goto end;
+ }
+
+ // Store the region's physical address
+ netuio_contextdata->dpdk_seg.mem.phys_addr = MmGetPhysicalAddress(netuio_contextdata->dpdk_seg.mem.virt_addr);
+
+end:
+ return status;
+}
+
+static VOID
+free_usermemory_segment(_In_ WDFOBJECT device)
+{
+ PNETUIO_CONTEXT_DATA netuio_contextdata;
+ netuio_contextdata = netuio_get_context_data(device);
+
+ if (netuio_contextdata) {
+ if (netuio_contextdata->dpdk_seg.mdl)
+ IoFreeMdl(netuio_contextdata->dpdk_seg.mdl);
+
+ if (netuio_contextdata->dpdk_seg.mem.virt_addr)
+ MmFreeContiguousMemory(netuio_contextdata->dpdk_seg.mem.virt_addr);
+ }
+}
diff --git a/lib/librte_eal/windows/netuio/netuio_dev.h b/lib/librte_eal/windows/netuio/netuio_dev.h
new file mode 100644
index 0000000..843f476
--- /dev/null
+++ b/lib/librte_eal/windows/netuio/netuio_dev.h
@@ -0,0 +1,92 @@
+/*-
+* BSD LICENSE
+*
+* Copyright(c) 2017 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * 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.
+* * Neither the name of Intel Corporation nor the names of its
+* 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
+* OWNER 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 NETUIO_DEV_H
+#define NETUIO_DEV_H
+
+EXTERN_C_START
+
+#include "netuio_interface.h"
+
+// Constants
+#define PCI_MAX_BAR 3
+#define USER_MEMORY_SEGMENT_SIZE (256ULL * 1024ULL * 1024ULL) // 256MB
+
+struct pci_bar {
+ PHYSICAL_ADDRESS base_addr;
+ PVOID virt_addr;
+ UINT64 size;
+};
+
+struct mem_map_region {
+ PMDL mdl; // MDL describing the memory region
+ struct mem_region mem; // Memory region details
+};
+
+// The device context performs the same job as a WDM device extension in the driver frameworks
+typedef struct _NETUIO_CONTEXT_DATA
+{
+ WDFDEVICE wdf_device; // WDF device handle to the FDO
+ BUS_INTERFACE_STANDARD bus_interface; // Bus interface for config space access
+ struct pci_bar bar[PCI_MAX_BAR]; // device BARs
+ struct dev_addr addr; // B:D:F details of device
+ USHORT dev_numa_node; // The NUMA node of the device
+ struct mem_map_region dpdk_hw; // mapped region for the device's register space
+ struct mem_map_region dpdk_seg; // mapped region allocated for DPDK process use
+} NETUIO_CONTEXT_DATA, *PNETUIO_CONTEXT_DATA;
+
+
+// This macro will generate an inline function called DeviceGetContext
+// which will be used to get a pointer to the device context memory in a type safe manner.
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NETUIO_CONTEXT_DATA, netuio_get_context_data)
+
+
+// Function to initialize the device and its callbacks
+NTSTATUS netuio_create_device(_Inout_ PWDFDEVICE_INIT DeviceInit);
+NTSTATUS netuio_map_hw_resources(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST Resources, _In_ WDFCMRESLIST ResourcesTranslated);
+VOID netuio_free_hw_resources(_In_ WDFDEVICE Device);
+
+
+// Function called for cleanup when device object is being destroyed
+VOID netuio_evt_device_context_cleanup(_In_ WDFOBJECT Device);
+
+// Local function protoyypes
+static NTSTATUS get_pci_device_info(_In_ WDFOBJECT device);
+static NTSTATUS create_device_specific_symbolic_link(_In_ WDFOBJECT device);
+static NTSTATUS allocate_usermemory_segment(_In_ WDFOBJECT device);
+static VOID free_usermemory_segment(_In_ WDFOBJECT device);
+
+
+EXTERN_C_END
+
+#endif // NETUIO_DEV_H
diff --git a/lib/librte_eal/windows/netuio/netuio_drv.c b/lib/librte_eal/windows/netuio/netuio_drv.c
new file mode 100644
index 0000000..2f2d558
--- /dev/null
+++ b/lib/librte_eal/windows/netuio/netuio_drv.c
@@ -0,0 +1,168 @@
+/*-
+* BSD LICENSE
+*
+* Copyright(c) 2017 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * 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.
+* * Neither the name of Intel Corporation nor the names of its
+* 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
+* OWNER 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.
+*/
+
+#include "netuio_drv.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text (INIT, DriverEntry)
+#pragma alloc_text (PAGE, netuio_evt_device_add)
+#pragma alloc_text (PAGE, netuio_evt_driver_context_cleanup)
+#endif
+
+
+/*
+Routine Description:
+ DriverEntry initializes the driver and is the first routine called by the
+ system after the driver is loaded. DriverEntry specifies the other entry
+ points in the function driver, such as EvtDevice and DriverUnload.
+
+Return Value:
+ STATUS_SUCCESS if successful,
+ STATUS_UNSUCCESSFUL otherwise.
+ */
+NTSTATUS
+DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
+{
+ WDF_DRIVER_CONFIG config;
+ NTSTATUS status;
+ WDF_OBJECT_ATTRIBUTES attributes;
+
+ // Register a cleanup callback so that we can call WPP_CLEANUP when
+ // the framework driver object is deleted during driver unload.
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.EvtCleanupCallback = netuio_evt_driver_context_cleanup;
+
+ WDF_DRIVER_CONFIG_INIT(&config, netuio_evt_device_add);
+
+ status = WdfDriverCreate(DriverObject, RegistryPath,
+ &attributes, &config,
+ WDF_NO_HANDLE);
+
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ return status;
+}
+
+
+/*
+Routine Description:
+ netuio_evt_device_add is called by the framework in response to AddDevice
+ call from the PnP manager. We create and initialize a device object to
+ represent a new instance of the device.
+
+Return Value:
+ NTSTATUS
+ */
+NTSTATUS
+netuio_evt_device_add(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit)
+{
+ NTSTATUS status;
+ WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
+
+ UNREFERENCED_PARAMETER(Driver);
+
+ PAGED_CODE();
+
+ // Zero out the PnpPowerCallbacks structure
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
+
+ // Register Plug-aNd-Play and power management callbacks
+ pnpPowerCallbacks.EvtDevicePrepareHardware = netuio_evt_prepare_hw;
+ pnpPowerCallbacks.EvtDeviceReleaseHardware = netuio_evt_release_hw;
+
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
+
+ status = netuio_create_device(DeviceInit);
+
+ return status;
+}
+
+/*
+Routine Description :
+ Maps HW resources and retrieves the PCI BAR address(es) of the device
+
+Return Value :
+ STATUS_SUCCESS is successful.
+ STATUS_<ERROR> otherwise
+-*/
+NTSTATUS
+netuio_evt_prepare_hw(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST Resources, _In_ WDFCMRESLIST ResourcesTranslated)
+{
+ NTSTATUS status;
+
+ status = netuio_map_hw_resources(Device, Resources, ResourcesTranslated);
+
+ if (NT_SUCCESS(status)) {
+ PNETUIO_CONTEXT_DATA netuio_contextdata;
+ netuio_contextdata = netuio_get_context_data(Device);
+ if (netuio_contextdata) {
+ DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_NETUIO_INFO_LEVEL, "netUIO Driver loaded...on device (B:D:F) %04d:%02d:%02d\n",
+ netuio_contextdata->addr.bus_num, netuio_contextdata->addr.dev_num, netuio_contextdata->addr.func_num);
+ }
+ }
+ return status;
+}
+
+/*
+Routine Description :
+ Releases the resource mapped by netuio_evt_prepare_hw
+
+Return Value :
+ STATUS_SUCCESS always.
+-*/
+NTSTATUS
+netuio_evt_release_hw(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST ResourcesTranslated)
+{
+ UNREFERENCED_PARAMETER(ResourcesTranslated);
+
+ netuio_free_hw_resources(Device);
+
+ return STATUS_SUCCESS;
+}
+
+/*
+Routine Description:
+ Free all the resources allocated in DriverEntry.
+
+Return Value:
+ None
+-*/
+VOID
+netuio_evt_driver_context_cleanup(_In_ WDFOBJECT DriverObject)
+{
+ UNREFERENCED_PARAMETER(DriverObject);
+ DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_NETUIO_INFO_LEVEL, "netUIO Driver unloaded.\n");
+ PAGED_CODE();
+}
diff --git a/lib/librte_eal/windows/netuio/netuio_drv.h b/lib/librte_eal/windows/netuio/netuio_drv.h
new file mode 100644
index 0000000..1b34b32
--- /dev/null
+++ b/lib/librte_eal/windows/netuio/netuio_drv.h
@@ -0,0 +1,59 @@
+/*-
+* BSD LICENSE
+*
+* Copyright(c) 2017 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * 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.
+* * Neither the name of Intel Corporation nor the names of its
+* 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
+* OWNER 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 NETUIO_DRV_H
+#define NETUIO_DRV_H
+
+#define INITGUID
+
+#include <ntddk.h>
+#include <wdf.h>
+
+#include "netuio_dev.h"
+#include "netuio_queue.h"
+
+EXTERN_C_START
+
+// Print output constants
+#define DPFLTR_NETUIO_INFO_LEVEL 35
+
+// WDFDRIVER Events
+DRIVER_INITIALIZE DriverEntry;
+EVT_WDF_DRIVER_DEVICE_ADD netuio_evt_device_add;
+EVT_WDF_OBJECT_CONTEXT_CLEANUP netuio_evt_driver_context_cleanup;
+EVT_WDF_DEVICE_PREPARE_HARDWARE netuio_evt_prepare_hw;
+EVT_WDF_DEVICE_RELEASE_HARDWARE netuio_evt_release_hw;
+
+EXTERN_C_END
+
+#endif // NETUIO_DRV_H
diff --git a/lib/librte_eal/windows/netuio/netuio_interface.h b/lib/librte_eal/windows/netuio/netuio_interface.h
new file mode 100644
index 0000000..b07cf3e
--- /dev/null
+++ b/lib/librte_eal/windows/netuio/netuio_interface.h
@@ -0,0 +1,88 @@
+/*-
+* BSD LICENSE
+*
+* Copyright(c) 2017 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * 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.
+* * Neither the name of Intel Corporation nor the names of its
+* 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
+* OWNER 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 NETUIO_INTERFACE_H
+#define NETUIO_INTERFACE_H
+
+// Define an Interface Guid so that any app can find the device and talk to it.
+DEFINE_GUID (GUID_DEVINTERFACE_netUIO, 0x08336f60,0x0679,0x4c6c,0x85,0xd2,0xae,0x7c,0xed,0x65,0xff,0xf7); // {08336f60-0679-4c6c-85d2-ae7ced65fff7}
+
+// Device name definitions
+#define NETUIO_DEVICE_SYMBOLIC_LINK_ANSI "\\DosDevices\\netuio"
+
+// netUIO driver symbolic name (prefix)
+#define NETUIO_DRIVER_NAME _T("netuio")
+
+// IOCTL code definitions
+#define IOCTL_NETUIO_GET_HW_DATA CTL_CODE(FILE_DEVICE_NETWORK, 51, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_NETUIO_PCI_CONFIG_IO CTL_CODE(FILE_DEVICE_NETWORK, 52, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+struct mem_region {
+ UINT64 size; // memory region size
+ PHYSICAL_ADDRESS phys_addr; // physical address of the memory region
+ PVOID virt_addr; // virtual address of the memory region
+ PVOID user_mapped_virt_addr; // virtual address of the region mapped into user process context
+};
+
+struct dev_addr {
+ ULONG bus_num;
+ USHORT dev_num;
+ USHORT func_num;
+};
+
+enum pci_io {
+ PCI_IO_READ = 0,
+ PCI_IO_WRITE = 1
+};
+
+struct dpdk_private_info
+{
+ struct mem_region hw;
+ struct mem_region ms;
+ struct dev_addr dev_addr;
+ UINT16 dev_id;
+ UINT16 sub_dev_id;
+ USHORT dev_numa_node;
+ USHORT reserved;
+};
+
+struct dpdk_pci_config_io
+{
+ struct dev_addr dev_addr;
+ PVOID buf;
+ UINT32 offset;
+ enum pci_io op;
+};
+
+
+#endif // NETUIO_INTERFACE_H
diff --git a/lib/librte_eal/windows/netuio/netuio_queue.c b/lib/librte_eal/windows/netuio/netuio_queue.c
new file mode 100644
index 0000000..f02458b
--- /dev/null
+++ b/lib/librte_eal/windows/netuio/netuio_queue.c
@@ -0,0 +1,294 @@
+/*-
+* BSD LICENSE
+*
+* Copyright(c) 2017 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * 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.
+* * Neither the name of Intel Corporation nor the names of its
+* 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
+* OWNER 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.
+*/
+
+#include "netuio_drv.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text (PAGE, netuio_queue_initialize)
+#endif
+
+VOID netuio_read_PCI_config(PNETUIO_CONTEXT_DATA netuio_contextdata, ULONG offset, PVOID buffer)
+{
+ netuio_contextdata->bus_interface.GetBusData(netuio_contextdata->bus_interface.Context,
+ PCI_WHICHSPACE_CONFIG,
+ buffer,
+ offset,
+ sizeof(UINT32));
+}
+
+VOID netuio_write_PCI_config(PNETUIO_CONTEXT_DATA netuio_contextdata, ULONG offset, PVOID buffer)
+{
+ netuio_contextdata->bus_interface.GetBusData(netuio_contextdata->bus_interface.Context,
+ PCI_WHICHSPACE_CONFIG,
+ buffer,
+ offset,
+ sizeof(UINT32));
+}
+
+static NTSTATUS
+netuio_handle_get_hw_data_request(_In_ WDFREQUEST Request, _In_ PNETUIO_CONTEXT_DATA netuio_contextdata,
+ _In_ PVOID outputBuf, _In_ size_t outputBufSize)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ WDF_REQUEST_PARAMETERS params;
+ WDF_REQUEST_PARAMETERS_INIT(&params);
+ WdfRequestGetParameters(Request, &params);
+
+ if (!netuio_contextdata || (outputBufSize != sizeof(struct dpdk_private_info))) {
+ status = STATUS_INVALID_PARAMETER;
+ goto end;
+ }
+
+ struct dpdk_private_info *dpdk_pvt_info = (struct dpdk_private_info *)outputBuf;
+ RtlZeroMemory(dpdk_pvt_info, outputBufSize);
+
+ dpdk_pvt_info->hw.phys_addr.QuadPart = netuio_contextdata->bar[0].base_addr.QuadPart;
+ dpdk_pvt_info->hw.user_mapped_virt_addr = netuio_contextdata->dpdk_hw.mem.user_mapped_virt_addr;
+ dpdk_pvt_info->hw.size = netuio_contextdata->bar[0].size;
+
+ dpdk_pvt_info->ms.phys_addr.QuadPart = netuio_contextdata->dpdk_seg.mem.phys_addr.QuadPart;
+ dpdk_pvt_info->ms.user_mapped_virt_addr = netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr;
+ dpdk_pvt_info->ms.size = netuio_contextdata->dpdk_seg.mem.size;
+end:
+ return status;
+}
+
+/*
+Routine Description:
+ The I/O dispatch callbacks for the frameworks device object are configured here.
+ A single default I/O Queue is configured for parallel request processing, and a
+ driver context memory allocation is created to hold our structure QUEUE_CONTEXT.
+
+Return Value:
+ None
+ */
+NTSTATUS
+netuio_queue_initialize(_In_ WDFDEVICE Device)
+{
+ WDFQUEUE queue;
+ NTSTATUS status;
+ WDF_IO_QUEUE_CONFIG queueConfig;
+
+ PAGED_CODE();
+
+ // Configure a default queue so that requests that are not
+ // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
+ // other queues get dispatched here.
+ WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel);
+
+ queueConfig.EvtIoDeviceControl = netuio_evt_IO_device_control;
+ queueConfig.EvtIoStop = netuio_evt_IO_stop;
+
+ status = WdfIoQueueCreate(Device,
+ &queueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &queue);
+
+ if( !NT_SUCCESS(status) ) {
+ return status;
+ }
+
+ return status;
+}
+
+/*
+Routine Description:
+ This event is invoked when the framework receives IRP_MJ_DEVICE_CONTROL request.
+
+Return Value:
+ None
+ */
+VOID
+netuio_evt_IO_device_control(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request,
+ _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength,
+ _In_ ULONG IoControlCode)
+{
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+
+ NTSTATUS status = STATUS_SUCCESS;
+ PVOID input_buf = NULL, output_buf = NULL;
+ size_t input_buf_size, output_buf_size;
+ size_t bytes_returned = 0;
+
+ WDFDEVICE device = WdfIoQueueGetDevice(Queue);
+
+ PNETUIO_CONTEXT_DATA netuio_contextdata;
+ netuio_contextdata = netuio_get_context_data(device);
+
+ switch (IoControlCode) {
+ case IOCTL_NETUIO_GET_HW_DATA:
+ // First retrieve the input buffer and see if it matches our device
+ status = WdfRequestRetrieveInputBuffer(Request, sizeof(struct dpdk_private_info), &input_buf, &input_buf_size);
+ if (!NT_SUCCESS(status)) {
+ status = STATUS_INVALID_BUFFER_SIZE;
+ break;
+ }
+
+ struct dpdk_private_info *dpdk_pvt_info = (struct dpdk_private_info *)input_buf;
+ // Ensure that the B:D:F match - otherwise, fail the IOCTL
+ if ((netuio_contextdata->addr.bus_num != dpdk_pvt_info->dev_addr.bus_num) ||
+ (netuio_contextdata->addr.dev_num != dpdk_pvt_info->dev_addr.dev_num) ||
+ (netuio_contextdata->addr.func_num != dpdk_pvt_info->dev_addr.func_num)) {
+ status = STATUS_NOT_SAME_DEVICE;
+ break;
+ }
+
+ // Map the previously allocated/defined memory regions to the user's process context
+ MmBuildMdlForNonPagedPool(netuio_contextdata->dpdk_hw.mdl);
+ netuio_contextdata->dpdk_hw.mem.user_mapped_virt_addr =
+ MmMapLockedPagesSpecifyCache(netuio_contextdata->dpdk_hw.mdl, UserMode, MmCached,
+ NULL, FALSE, (NormalPagePriority | MdlMappingNoExecute));
+
+ MmBuildMdlForNonPagedPool(netuio_contextdata->dpdk_seg.mdl);
+ netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr =
+ MmMapLockedPagesSpecifyCache(netuio_contextdata->dpdk_seg.mdl, UserMode, MmCached,
+ NULL, FALSE, (NormalPagePriority | MdlMappingNoExecute));
+
+ if (!netuio_contextdata->dpdk_hw.mem.user_mapped_virt_addr && !netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ // Return relevant data to the caller
+ status = WdfRequestRetrieveOutputBuffer(Request, sizeof(struct dpdk_private_info), &output_buf, &output_buf_size);
+ if (!NT_SUCCESS(status)) {
+ status = STATUS_INVALID_BUFFER_SIZE;
+ break;
+ }
+ ASSERT(output_buf_size == OutputBufferLength);
+ status = netuio_handle_get_hw_data_request(Request, netuio_contextdata, output_buf, output_buf_size);
+ if (NT_SUCCESS(status))
+ bytes_returned = output_buf_size;
+
+ break;
+
+ case IOCTL_NETUIO_PCI_CONFIG_IO:
+ // First retrieve the input buffer and see if it matches our device
+ status = WdfRequestRetrieveInputBuffer(Request, sizeof(struct dpdk_pci_config_io), &input_buf, &input_buf_size);
+ if (!NT_SUCCESS(status)) {
+ status = STATUS_INVALID_BUFFER_SIZE;
+ break;
+ }
+
+ struct dpdk_pci_config_io *dpdk_pci_io_input = (struct dpdk_pci_config_io *)input_buf;
+ // Ensure that the B:D:F match - otherwise, fail the IOCTL
+ if ((netuio_contextdata->addr.bus_num != dpdk_pci_io_input->dev_addr.bus_num) ||
+ (netuio_contextdata->addr.dev_num != dpdk_pci_io_input->dev_addr.dev_num) ||
+ (netuio_contextdata->addr.func_num != dpdk_pci_io_input->dev_addr.func_num)) {
+ status = STATUS_NOT_SAME_DEVICE;
+ break;
+ }
+ // Retrieve output buffer
+ status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT32), &output_buf, &output_buf_size);
+ if (!NT_SUCCESS(status)) {
+ status = STATUS_INVALID_BUFFER_SIZE;
+ break;
+ }
+ ASSERT(output_buf_size == OutputBufferLength);
+
+ if (dpdk_pci_io_input->op == PCI_IO_READ) {
+ netuio_read_PCI_config(netuio_contextdata, dpdk_pci_io_input->offset, output_buf);
+ bytes_returned = output_buf_size;
+ }
+ else {
+ netuio_write_PCI_config(netuio_contextdata, dpdk_pci_io_input->offset, dpdk_pci_io_input->buf);
+ bytes_returned = 0;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ WdfRequestCompleteWithInformation(Request, status, bytes_returned);
+
+ return;
+}
+
+/*
+Routine Description:
+ This event is invoked for a power-managed queue before the device leaves the working state (D0).
+
+Return Value:
+ None
+ */
+VOID
+netuio_evt_IO_stop(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request,_In_ ULONG ActionFlags)
+{
+ //
+ // In most cases, the EvtIoStop callback function completes, cancels, or postpones
+ // further processing of the I/O request.
+ //
+ // Typically, the driver uses the following rules:
+ //
+ // - If the driver owns the I/O request, it calls WdfRequestUnmarkCancelable
+ // (if the request is cancelable) and either calls WdfRequestStopAcknowledge
+ // with a Requeue value of TRUE, or it calls WdfRequestComplete with a
+ // completion status value of STATUS_SUCCESS or STATUS_CANCELLED.
+ //
+ // Before it can call these methods safely, the driver must make sure that
+ // its implementation of EvtIoStop has exclusive access to the request.
+ //
+ // In order to do that, the driver must synchronize access to the request
+ // to prevent other threads from manipulating the request concurrently.
+ // The synchronization method you choose will depend on your driver's design.
+ //
+ // For example, if the request is held in a shared context, the EvtIoStop callback
+ // might acquire an internal driver lock, take the request from the shared context,
+ // and then release the lock. At this point, the EvtIoStop callback owns the request
+ // and can safely complete or requeue the request.
+ //
+ // - If the driver has forwarded the I/O request to an I/O target, it either calls
+ // WdfRequestCancelSentRequest to attempt to cancel the request, or it postpones
+ // further processing of the request and calls WdfRequestStopAcknowledge with
+ // a Requeue value of FALSE.
+ //
+ // A driver might choose to take no action in EvtIoStop for requests that are
+ // guaranteed to complete in a small amount of time.
+ //
+ // In this case, the framework waits until the specified request is complete
+ // before moving the device (or system) to a lower power state or removing the device.
+ // Potentially, this inaction can prevent a system from entering its hibernation state
+ // or another low system power state. In extreme cases, it can cause the system
+ // to crash with bugcheck code 9F.
+ //
+ UNREFERENCED_PARAMETER(Queue);
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(ActionFlags);
+
+ return;
+}
+
diff --git a/lib/librte_eal/windows/netuio/netuio_queue.h b/lib/librte_eal/windows/netuio/netuio_queue.h
new file mode 100644
index 0000000..c605411
--- /dev/null
+++ b/lib/librte_eal/windows/netuio/netuio_queue.h
@@ -0,0 +1,56 @@
+/*-
+* BSD LICENSE
+*
+* Copyright(c) 2017 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * 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.
+* * Neither the name of Intel Corporation nor the names of its
+* 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
+* OWNER 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 NETUIO_QUEUE_H
+#define NETUIO_QUEUE_H
+
+EXTERN_C_START
+
+// This is the context that can be placed per queue and would contain per queue information.
+typedef struct _QUEUE_CONTEXT {
+ ULONG PrivateDeviceData; // just a placeholder
+} QUEUE_CONTEXT, *PQUEUE_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, QueueGetContext)
+
+
+NTSTATUS
+netuio_queue_initialize(_In_ WDFDEVICE hDevice);
+
+// Events from the IoQueue object
+EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL netuio_evt_IO_device_control;
+EVT_WDF_IO_QUEUE_IO_STOP netuio_evt_IO_stop;
+
+EXTERN_C_END
+
+#endif // NETUIO_QUEUE_H
diff --git a/lib/librte_eal/windows/netuio/resource.h b/lib/librte_eal/windows/netuio/resource.h
new file mode 100644
index 0000000..9789ffd
--- /dev/null
+++ b/lib/librte_eal/windows/netuio/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by netuio.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/mk/exec-env/windows/netuio/netuio.sln b/mk/exec-env/windows/netuio/netuio.sln
new file mode 100644
index 0000000..15c26e6
--- /dev/null
+++ b/mk/exec-env/windows/netuio/netuio.sln
@@ -0,0 +1,24 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netuio", "netuio.vcxproj", "{66EC91EF-AC5B-4D1E-8314-9B3E2855CCF6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66EC91EF-AC5B-4D1E-8314-9B3E2855CCF6}.Debug|x64.ActiveCfg = Debug|x64
+ {66EC91EF-AC5B-4D1E-8314-9B3E2855CCF6}.Debug|x64.Build.0 = Debug|x64
+ {66EC91EF-AC5B-4D1E-8314-9B3E2855CCF6}.Debug|x64.Deploy.0 = Debug|x64
+ {66EC91EF-AC5B-4D1E-8314-9B3E2855CCF6}.Release|x64.ActiveCfg = Release|x64
+ {66EC91EF-AC5B-4D1E-8314-9B3E2855CCF6}.Release|x64.Build.0 = Release|x64
+ {66EC91EF-AC5B-4D1E-8314-9B3E2855CCF6}.Release|x64.Deploy.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/mk/exec-env/windows/netuio/netuio.vcxproj b/mk/exec-env/windows/netuio/netuio.vcxproj
new file mode 100644
index 0000000..251b8eb
--- /dev/null
+++ b/mk/exec-env/windows/netuio/netuio.vcxproj
@@ -0,0 +1,108 @@
+<?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|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{66EC91EF-AC5B-4D1E-8314-9B3E2855CCF6}</ProjectGuid>
+ <TemplateGuid>{497e31cb-056b-4f31-abb8-447fd55ee5a5}</TemplateGuid>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
+ <Configuration>Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <RootNamespace>netuio</RootNamespace>
+ <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <TargetVersion>
+ </TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <TargetVersion>
+ </TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ <OutDir>$(SolutionDir)..\..\..\..\$(Platform)\$(ConfigurationName)\$(MSBuildProjectName)\</OutDir>
+ <IntDir>$(SolutionDir)..\$(Platform)\$(ConfigurationName)\$(MSBuildProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ <OutDir>$(SolutionDir)..\..\..\..\$(Platform)\$(ConfigurationName)\$(MSBuildProjectName)\</OutDir>
+ <IntDir>$(SolutionDir)..\$(Platform)\$(ConfigurationName)\$(MSBuildProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WppEnabled>false</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <WppKernelMode>true</WppKernelMode>
+ <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking>
+ </ClCompile>
+ <Inf>
+ <TimeStamp>0.6.0.2</TimeStamp>
+ </Inf>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WppEnabled>false</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <WppKernelMode>true</WppKernelMode>
+ <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking>
+ </ClCompile>
+ <Inf>
+ <TimeStamp>0.6.0.2</TimeStamp>
+ </Inf>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <FilesToPackage Include="$(TargetPath)" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio.inf" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_dev.h" />
+ <ClInclude Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_drv.h" />
+ <ClInclude Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_interface.h" />
+ <ClInclude Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_queue.h" />
+ <ClInclude Include="..\..\..\..\lib\librte_eal\windows\netuio\resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_dev.c" />
+ <ClCompile Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_drv.c" />
+ <ClCompile Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_queue.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/mk/exec-env/windows/netuio/netuio.vcxproj.filters b/mk/exec-env/windows/netuio/netuio.vcxproj.filters
new file mode 100644
index 0000000..72a397d
--- /dev/null
+++ b/mk/exec-env/windows/netuio/netuio.vcxproj.filters
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Driver Files">
+ <UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio.inf">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_interface.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_dev.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_drv.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_queue.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\lib\librte_eal\windows\netuio\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_queue.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_dev.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\lib\librte_eal\windows\netuio\netuio_drv.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/mk/exec-env/windows/netuio/netuio.vcxproj.user b/mk/exec-env/windows/netuio/netuio.vcxproj.user
new file mode 100644
index 0000000..771ce86
--- /dev/null
+++ b/mk/exec-env/windows/netuio/netuio.vcxproj.user
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TestCertificate>
+ </TestCertificate>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TestCertificate>
+ </TestCertificate>
+ </PropertyGroup>
+</Project> \ No newline at end of file