get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/75533/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 75533,
    "url": "https://patches.dpdk.org/api/patches/75533/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1597360905-74106-7-git-send-email-navasile@linux.microsoft.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1597360905-74106-7-git-send-email-navasile@linux.microsoft.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1597360905-74106-7-git-send-email-navasile@linux.microsoft.com",
    "date": "2020-08-13T23:21:29",
    "name": "[06/22] Windows DPDK libraries and applications have now been updated to the latest public release v18.08, of the main DPDK source.",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "240ceaf20068b6fec2568b132f98273fc56819be",
    "submitter": {
        "id": 1668,
        "url": "https://patches.dpdk.org/api/people/1668/?format=api",
        "name": "Narcisa Ana Maria Vasile",
        "email": "navasile@linux.microsoft.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1597360905-74106-7-git-send-email-navasile@linux.microsoft.com/mbox/",
    "series": [
        {
            "id": 11644,
            "url": "https://patches.dpdk.org/api/series/11644/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=11644",
            "date": "2020-08-13T23:21:23",
            "name": "windows/netuio: add netuio driver for Windows",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/11644/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/75533/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/75533/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 3901DA04B1;\n\tFri, 14 Aug 2020 01:24:57 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id B02221C1B4;\n\tFri, 14 Aug 2020 01:23:03 +0200 (CEST)",
            "from linux.microsoft.com (linux.microsoft.com [13.77.154.182])\n by dpdk.org (Postfix) with ESMTP id DBCD21C0CF\n for <dev@dpdk.org>; Fri, 14 Aug 2020 01:22:44 +0200 (CEST)",
            "by linux.microsoft.com (Postfix, from userid 1059)\n id B3F4120B4916; Thu, 13 Aug 2020 16:22:43 -0700 (PDT)"
        ],
        "DKIM-Filter": "OpenDKIM Filter v2.11.0 linux.microsoft.com B3F4120B4916",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com;\n s=default; t=1597360963;\n bh=SLZXc7axZJl04uKHnM5I4NTHS4bojddh/qwBYadFnRw=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n b=M8GOYlw8FR+VxV5YFp04rlD5FT3x9XLvGEsqeuwP759FHbekPexcp+45zPqlpF+Rc\n Ugf+oKMOrv57fQAq8/hZFsVYMbBecQGaPVhxON5xW7LLwVfbJXktpT6j4QRmo+vdCK\n 7Q6Bg9mb9Wcc91QY6oMjxi2sX20NlQTfliSwEvjg=",
        "From": "Narcisa Ana Maria Vasile <navasile@linux.microsoft.com>",
        "To": "dev@dpdk.org, thomas@monjalon.net, haramakr@linux.microsoft.com,\n ocardona@microsoft.com, pallavi.kadam@intel.com, dmitry.kozliuk@gmail.com",
        "Cc": "ranjit.menon@intel.com, dmitrym@microsoft.com,\n Harini Ramakrishnan <haramakr@microsoft.com>",
        "Date": "Thu, 13 Aug 2020 16:21:29 -0700",
        "Message-Id": "<1597360905-74106-7-git-send-email-navasile@linux.microsoft.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1597360905-74106-1-git-send-email-navasile@linux.microsoft.com>",
        "References": "<1597360905-74106-1-git-send-email-navasile@linux.microsoft.com>",
        "Subject": "[dpdk-dev] [PATCH 06/22] Windows DPDK libraries and applications\n\thave now been updated to the latest public release v18.08,\n\tof the main DPDK source.",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Harini Ramakrishnan <haramakr@microsoft.com>\n\n---\n kernel/windows/netuio/netuio.inf         | 118 +++++++++\n kernel/windows/netuio/netuio.rc          | Bin 0 -> 4772 bytes\n kernel/windows/netuio/netuio_dev.c       | 306 +++++++++++++++++++++++\n kernel/windows/netuio/netuio_dev.h       |  65 +++++\n kernel/windows/netuio/netuio_drv.c       | 142 +++++++++++\n kernel/windows/netuio/netuio_drv.h       |  33 +++\n kernel/windows/netuio/netuio_interface.h |  69 +++++\n kernel/windows/netuio/netuio_queue.c     | 271 ++++++++++++++++++++\n kernel/windows/netuio/netuio_queue.h     |  30 +++\n kernel/windows/netuio/resource.h         |  14 ++\n 10 files changed, 1048 insertions(+)\n create mode 100644 kernel/windows/netuio/netuio.inf\n create mode 100644 kernel/windows/netuio/netuio.rc\n create mode 100644 kernel/windows/netuio/netuio_dev.c\n create mode 100644 kernel/windows/netuio/netuio_dev.h\n create mode 100644 kernel/windows/netuio/netuio_drv.c\n create mode 100644 kernel/windows/netuio/netuio_drv.h\n create mode 100644 kernel/windows/netuio/netuio_interface.h\n create mode 100644 kernel/windows/netuio/netuio_queue.c\n create mode 100644 kernel/windows/netuio/netuio_queue.h\n create mode 100644 kernel/windows/netuio/resource.h",
    "diff": "diff --git a/kernel/windows/netuio/netuio.inf b/kernel/windows/netuio/netuio.inf\nnew file mode 100644\nindex 000000000..0453b371a\n--- /dev/null\n+++ b/kernel/windows/netuio/netuio.inf\n@@ -0,0 +1,118 @@\n+;\n+;   BSD LICENSE\n+;\n+;   Copyright(c) 2010-2018 Intel Corporation. All rights reserved.\n+;   All rights reserved.\n+;\n+;   Redistribution and use in source and binary forms, with or without\n+;   modification, are permitted provided that the following conditions\n+;   are met:\n+;\n+;     * Redistributions of source code must retain the above copyright\n+;       notice, this list of conditions and the following disclaimer.\n+;     * Redistributions in binary form must reproduce the above copyright\n+;       notice, this list of conditions and the following disclaimer in\n+;       the documentation and/or other materials provided with the\n+;       distribution.\n+;     * Neither the name of Intel Corporation nor the names of its\n+;       contributors may be used to endorse or promote products derived\n+;       from this software without specific prior written permission.\n+;\n+;   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+;   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+;   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+;   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+;   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+;   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+;   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+;   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+;   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+;   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+;   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+;\n+;\n+; netuio.inf\n+;\n+\n+[Version]\n+Signature=\"$WINDOWS NT$\"\n+Class=Net\n+ClassGuid={4d36e972-e325-11ce-bfc1-08002be10318}\n+Provider=%ManufacturerName%\n+CatalogFile=netuio.cat\n+DriverVer=\n+\n+;*****************************************\n+; Install Section\n+;*****************************************\n+\n+[Manufacturer]\n+%ManufacturerName%=Standard,NT$ARCH$\n+\n+[Standard.NT$ARCH$]\n+%F1583.netuio.Description%=netuio_Device, PCI\\VEN_8086&DEV_1583\n+%F158A.netuio.Description%=netuio_Device, PCI\\VEN_8086&DEV_158A   ; I40E_DEV_ID_25G_B\n+%F158B.netuio.Description%=netuio_Device, PCI\\VEN_8086&DEV_158B   ; I40E_DEV_ID_25G_SFP28\n+%F37D0.netuio.Description%=netuio_Device, PCI\\VEN_8086&DEV_37D0\n+%F153B.netuio.Description%=netuio_Device, PCI\\VEN_8086&DEV_153B\n+\n+[netuio_Device.NT]\n+CopyFiles=Drivers_Dir\n+\n+[Drivers_Dir]\n+netuio.sys\n+\n+;-------------- Service installation\n+[netuio_Device.NT.Services]\n+AddService = netuio,%SPSVCINST_ASSOCSERVICE%, netuio_Service_Inst\n+\n+; -------------- netuio driver install sections\n+[netuio_Service_Inst]\n+DisplayName    = %netuio.SVCDESC%\n+ServiceType    = 1               ; SERVICE_KERNEL_DRIVER\n+StartType      = 3               ; SERVICE_DEMAND_START\n+ErrorControl   = 1               ; SERVICE_ERROR_NORMAL\n+ServiceBinary  = %12%\\netuio.sys\n+\n+;\n+;--- netuio_Device Coinstaller installation ------\n+;\n+\n+[DestinationDirs]\n+DefaultDestDir = 12\n+netuio_Device_CoInstaller_CopyFiles = 11\n+\n+[netuio_Device.NT.CoInstallers]\n+AddReg=netuio_Device_CoInstaller_AddReg\n+CopyFiles=netuio_Device_CoInstaller_CopyFiles\n+\n+[netuio_Device_CoInstaller_AddReg]\n+HKR,,CoInstallers32,0x00010000, \"WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller\"\n+\n+[netuio_Device_CoInstaller_CopyFiles]\n+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll\n+\n+[SourceDisksNames]\n+1 = %DiskName%,,,\"\"\n+\n+[SourceDisksFiles]\n+netuio.sys  = 1,,\n+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames\n+\n+[netuio_Device.NT.Wdf]\n+KmdfService =  netuio, netuio_wdfsect\n+[netuio_wdfsect]\n+KmdfLibraryVersion = $KMDFVERSION$\n+\n+[Strings]\n+SPSVCINST_ASSOCSERVICE= 0x00000002\n+ManufacturerName=\"Intel\"\n+ClassName = \"Intel(R) DPDK netUIO Driver\"\n+DiskName = \"DPDK netUIO Installation Disk\"\n+F1583.netuio.Description = \"DPDK netUIO for Intel(R) Ethernet Converged Network Adapter XL710-Q2\"\n+F158A.netuio.Description = \"DPDK netUIO for Intel(R) Ethernet Network Adapter XXV710 for 25GbE backplane\"\n+F158B.netuio.Description = \"DPDK netUIO for Intel(R) Ethernet Network Adapter XXV710-DA1\"\n+F37D0.netuio.Description = \"DPDK netUIO for Intel(R) Ethernet Connection X722\"\n+F153B.netuio.Description = \"DPDK netUIO for Intel(R) Ethernet Connection I217-V\"\n+netuio.DeviceDesc = \"netuio Device\"\n+netuio.SVCDESC = \"netuio Service\"\ndiff --git a/kernel/windows/netuio/netuio.rc b/kernel/windows/netuio/netuio.rc\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..4b0b176e6284fcfa65662f7ea6b3b1b36fb85a6d\nGIT binary patch\nliteral 4772\nzcmdUy+iuf95QgU(iFYvR4G7dGEg-mTlQdMM2Q_H`sZs<aEtNuC#R&(AX9vE2H(T4W\nzQ<TC*kY%rTJu^G=&tb>Ees0;8MRsUc_R%I5Tf%)|Q`UN{B{sA7Heyz{$6S$J+R(<_\nz6V|7U1J)*t;+ygIk@tw1q+QuHG@Ewc?y<|38#h=T^K}IEz|mF;{G0a4Dvny58;<V6\nz@k#csomj`Zc4iGbuw(1nsWn+`@P1@%d&f$L=b`Pf(&jzvFCEtJ3fhG+vKF{3VtfHg\nzv3<t=Dd-4?E>^$gd4Sb*>=YhN*0;GAJ@RKCe0BJGzC8Zxhgi_aN5>4T6iFA@eYe;M\nz$OpOWH3sb>ygMfUMtCYA1|oZi&&SL{9(H*1S((_Qk|;<rId$dmdXUSl0TOp@pQ!RV\nz)ggb*$gVm&_ld4Hm*oE7ik5PAk#R~4_u)E%|B>6Z&FT@WXN)Zur(wm@wUB*4uD-G-\nz$nHS5$BO4!r0Db2XSI(2*|IzWlpj4TdCjhk|E?C4XL*PTjk;@KR!$kY?|azZa+N~V\nz(flf}yysS(S6}(hBPK4@mAmXwR`DxVtTz=qr*54S(Z2SlS}xOQ=Z+e!y3dBI#{)7=\nzHO6165oPtJ7;V8v>s3{<+DJpq!>F@gCwzj%G5!ea!IB=?*N3J_o_E|Ce8gOq?~`ZZ\nz&VC8&;*Ov=Ag`MXG!ZfP#GZ3&eCBqHIOk81*C5;LL|$HMM9h0?aa89VLHfR{9WAsw\nzq=t0JeeLkgcJN@^(JCs_s-f!Eq~e^BC3!tlNnS$jhJQ#UPQdAQ`f7$==ahEMa~z|e\nzm;DqSbv>Q)q-b^NXHL-2({0;_0)?-bdAhK7dG@Qm9)ql~si4CYkE=Jk#79@yHpEk7\nzw2c??v0Pfni@a3XQni=PrVl*xnVs^KRj2SZj6FQ5E=MR-&|BTmHRs*fz7u)xnGIRj\nz=}~c->s0ieYm8;r(EFa%$8@<S<$DD@8c57`wn38Lvw?>i4o&rLQ#4g~s&i7feqn9G\nzOn7Q+LZLoxg8rgbhpk+b7h?1l{>s3+=$X&nfJv23{5iMAXDi8790*P6s=t9nw7ms0\nztc;PJ;E&bxZX^5BNfrjz@C&g^@R{CtwD?8+Pu=w++t^gI7tZ%V*X5qy1nXUga729x\nz`y{NMqK7hi;=DD$mQ~O{o@=cf5=tRzG|R^3-=cNGJ~2@><1cDj@I`~&)CH<~ju^FD\nzL|hJ?O(Tb|w2?<6qE+2v8kKLDt4hV3&#U<`uT^;j*5=Wt2wYYR(w-yaVsRy3V|rLQ\nzxj|e0U$tiCD@zw?!Yy(5O+iF?>9a^@h_7hM`5HZu>b0-uUf)#P^iAKF_YnW4tIwY2\nz>-8?{v$sEaZ~JE}_E76(QC1sSrg<3u_U~Oi?d^Z>0n4lw>-8=Tm&f~<d{WIR{;L=L\nHE=j)u5l}&X\n\nliteral 0\nHcmV?d00001\n\ndiff --git a/kernel/windows/netuio/netuio_dev.c b/kernel/windows/netuio/netuio_dev.c\nnew file mode 100644\nindex 000000000..10ff5f903\n--- /dev/null\n+++ b/kernel/windows/netuio/netuio_dev.c\n@@ -0,0 +1,306 @@\n+/*-\n+*\n+*   Copyright(c) 2017 Intel Corporation. All rights reserved.\n+*\n+*/\n+\n+\n+#include <stdio.h>\n+#include \"netuio_drv.h\"\n+\n+#include <wdmguid.h>\n+\n+#ifdef ALLOC_PRAGMA\n+#pragma alloc_text (PAGE, netuio_create_device)\n+#pragma alloc_text (PAGE, netuio_evt_device_context_cleanup)\n+#pragma alloc_text (PAGE, netuio_map_hw_resources)\n+#pragma alloc_text (PAGE, netuio_free_hw_resources)\n+#endif\n+\n+/*\n+Routine Description:\n+    Worker routine called to create a device and its software resources.\n+\n+Return Value:\n+    NTSTATUS\n+ */\n+NTSTATUS\n+netuio_create_device(_Inout_ PWDFDEVICE_INIT DeviceInit)\n+{\n+    WDF_OBJECT_ATTRIBUTES deviceAttributes;\n+    WDFDEVICE device;\n+    NTSTATUS status;\n+\n+    PAGED_CODE();\n+    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, NETUIO_CONTEXT_DATA);\n+\n+    // Set the device context cleanup callback.\n+    // This function will be called when the WDF Device Object associated to the current device is destroyed\n+    deviceAttributes.EvtCleanupCallback = netuio_evt_device_context_cleanup;\n+\n+    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);\n+\n+    if (NT_SUCCESS(status)) {\n+        // Create a device interface so that applications can find and talk to us.\n+        status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_netUIO, NULL);\n+\n+        if (NT_SUCCESS(status)) {\n+            // Retrieve and store PCI information\n+            status = get_pci_device_info(device);\n+        }\n+\n+        if (NT_SUCCESS(status)) {\n+            // Create a symbolic link name for user-space access\n+            status = create_device_specific_symbolic_link(device);\n+        }\n+\n+        if (NT_SUCCESS(status)) {\n+            // Initialize the I/O Package and any Queues\n+            status = netuio_queue_initialize(device);\n+        }\n+\n+        if (NT_SUCCESS(status)) {\n+            // Allocate physically contiguous memory for user process use. We'll map it later\n+            status = allocate_usermemory_segment(device);\n+        }\n+    }\n+\n+    return status;\n+}\n+\n+/*\n+Routine Description:\n+    Free all the resources allocated in AdfEvtDeviceAdd.\n+\n+Return Value:\n+    None\n+ */\n+VOID\n+netuio_evt_device_context_cleanup(_In_ WDFOBJECT Device)\n+{\n+    free_usermemory_segment(Device);\n+    return;\n+}\n+\n+NTSTATUS\n+netuio_map_hw_resources(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST Resources, _In_ WDFCMRESLIST ResourcesTranslated)\n+{\n+    UNREFERENCED_PARAMETER(Resources);\n+\n+    NTSTATUS status = STATUS_SUCCESS;\n+\n+    PNETUIO_CONTEXT_DATA  netuio_contextdata;\n+    netuio_contextdata = netuio_get_context_data(Device);\n+\n+    if (!netuio_contextdata)\n+        return STATUS_UNSUCCESSFUL;\n+\n+    PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;\n+    UINT8 bar_index = 0;\n+\n+    // Collect device BAR resources from the ResourcesTranslated object\n+    for (ULONG idx = 0; idx < WdfCmResourceListGetCount(ResourcesTranslated); idx++) {\n+        descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, idx);\n+        if (!descriptor) {\n+            status = STATUS_DEVICE_CONFIGURATION_ERROR;\n+            goto end;\n+        }\n+\n+        switch (descriptor->Type) {\n+        case CmResourceTypeMemory:\n+            // Retrieve and map the BARs\n+            netuio_contextdata->bar[bar_index].base_addr.QuadPart = descriptor->u.Memory.Start.QuadPart;\n+            netuio_contextdata->bar[bar_index].size = descriptor->u.Memory.Length;\n+            netuio_contextdata->bar[bar_index].virt_addr =\n+                MmMapIoSpace(descriptor->u.Memory.Start, descriptor->u.Memory.Length, MmNonCached);\n+\n+            if (netuio_contextdata->bar[bar_index].virt_addr == NULL) {\n+                status = STATUS_UNSUCCESSFUL;\n+                goto end;\n+            }\n+\n+            bar_index++;\n+            break;\n+\n+            // Don't handle any other resource type\n+            // This could be device-private type added by the PCI bus driver.\n+        case CmResourceTypeInterrupt:\n+        default:\n+            break;\n+        }\n+    }\n+\n+    // Allocate an MDL for the device BAR, so that we can map it to the user's process context later...\n+    if (status == STATUS_SUCCESS) {\n+        // Bar 0 is typically the HW BAR\n+        if (netuio_contextdata->bar[0].virt_addr) {\n+            netuio_contextdata->dpdk_hw.mdl = IoAllocateMdl(netuio_contextdata->bar[0].virt_addr, (ULONG)netuio_contextdata->bar[0].size, FALSE, FALSE, NULL);\n+            if (!netuio_contextdata->dpdk_hw.mdl) {\n+                status = STATUS_INSUFFICIENT_RESOURCES;\n+                goto end;\n+            }\n+            netuio_contextdata->dpdk_hw.mem.size = netuio_contextdata->bar[0].size;\n+        }\n+    }\n+\n+end:\n+    return status;\n+}\n+\n+VOID\n+netuio_free_hw_resources(_In_ WDFDEVICE Device)\n+{\n+    PNETUIO_CONTEXT_DATA  netuio_contextdata;\n+    netuio_contextdata = netuio_get_context_data(Device);\n+\n+    if (netuio_contextdata) {\n+        // Free the allocated MDL\n+        if (netuio_contextdata->dpdk_hw.mdl)\n+            IoFreeMdl(netuio_contextdata->dpdk_hw.mdl);\n+\n+        // Unmap all the BAR regions previously mapped\n+        for (UINT8 bar_index = 0; bar_index < PCI_MAX_BAR; bar_index++) {\n+            if (netuio_contextdata->bar[bar_index].virt_addr)\n+                MmUnmapIoSpace(netuio_contextdata->bar[bar_index].virt_addr, netuio_contextdata->bar[bar_index].size);\n+        }\n+    }\n+}\n+\n+\n+static NTSTATUS\n+get_pci_device_info(_In_ WDFOBJECT device)\n+{\n+    NTSTATUS status = STATUS_UNSUCCESSFUL;\n+\n+    PNETUIO_CONTEXT_DATA  netuio_contextdata;\n+    netuio_contextdata = netuio_get_context_data(device);\n+\n+    if (!netuio_contextdata)\n+        return status;\n+\n+    netuio_contextdata->wdf_device = device;  // Store for later use\n+\n+    // Obtain the BUS_INTERFACE_STANDARD interface from the Bus Driver\n+    status = WdfFdoQueryForInterface(device, &GUID_BUS_INTERFACE_STANDARD,\n+                                    (PINTERFACE)&netuio_contextdata->bus_interface,\n+                                    sizeof(BUS_INTERFACE_STANDARD), 1, NULL);\n+    if (!NT_SUCCESS(status))\n+        return status;\n+\n+    // Retrieve the B:D:F details of our device\n+    PDEVICE_OBJECT pdo = NULL;\n+    pdo = WdfDeviceWdmGetPhysicalDevice(device);\n+    if (pdo) {\n+        ULONG prop = 0, length = 0;\n+        status = IoGetDeviceProperty(pdo, DevicePropertyBusNumber, sizeof(ULONG), (PVOID)&netuio_contextdata->addr.bus_num, &length);\n+        status = IoGetDeviceProperty(pdo, DevicePropertyAddress, sizeof(ULONG), (PVOID)&prop, &length);\n+\n+        if (NT_SUCCESS(status)) {\n+            netuio_contextdata->addr.func_num = prop & 0x0000FFFF;\n+            netuio_contextdata->addr.dev_num = ((prop >> 16) & 0x0000FFFF);\n+        }\n+        // Also, retrieve the NUMA node of the device\n+        USHORT numaNode;\n+        status = IoGetDeviceNumaNode(pdo, &numaNode);\n+        if (NT_SUCCESS(status)) {\n+            netuio_contextdata->dev_numa_node = numaNode;\n+        }\n+    }\n+\n+    return status;\n+}\n+\n+static NTSTATUS\n+create_device_specific_symbolic_link(_In_ WDFOBJECT device)\n+{\n+    NTSTATUS status = STATUS_UNSUCCESSFUL;\n+    UNICODE_STRING netuio_symbolic_link;\n+\n+    PNETUIO_CONTEXT_DATA  netuio_contextdata;\n+    netuio_contextdata = netuio_get_context_data(device);\n+\n+    if (!netuio_contextdata)\n+        return status;\n+\n+    // Build symbolic link name as <netuio_symbolic_link>_BDF  (bus/device/func)\n+    CHAR  symbolic_link[64] = { 0 };\n+    sprintf_s(symbolic_link, sizeof(symbolic_link), \"%s_%04d%02d%02d\",\n+                            NETUIO_DEVICE_SYMBOLIC_LINK_ANSI, netuio_contextdata->addr.bus_num,\n+                            netuio_contextdata->addr.dev_num, netuio_contextdata->addr.func_num);\n+\n+    ANSI_STRING ansi_symbolic_link;\n+    RtlInitAnsiString(&ansi_symbolic_link, symbolic_link);\n+\n+    status = RtlAnsiStringToUnicodeString(&netuio_symbolic_link, &ansi_symbolic_link, TRUE);\n+    if (!NT_SUCCESS(status))\n+        return status;\n+\n+    status = WdfDeviceCreateSymbolicLink(device, &netuio_symbolic_link);\n+\n+    RtlFreeUnicodeString(&netuio_symbolic_link);\n+\n+    return status;\n+}\n+\n+static NTSTATUS\n+allocate_usermemory_segment(_In_ WDFOBJECT device)\n+{\n+    NTSTATUS status = STATUS_SUCCESS;\n+\n+    PNETUIO_CONTEXT_DATA  netuio_contextdata;\n+    netuio_contextdata = netuio_get_context_data(device);\n+\n+    if (!netuio_contextdata)\n+        return STATUS_UNSUCCESSFUL;\n+\n+    PHYSICAL_ADDRESS lowest_acceptable_address;\n+    PHYSICAL_ADDRESS highest_acceptable_address;\n+    PHYSICAL_ADDRESS boundary_address_multiple;\n+\n+    lowest_acceptable_address.QuadPart = 0x0000000000800000;\n+    highest_acceptable_address.QuadPart = 0xFFFFFFFFFFFFFFFF;\n+    boundary_address_multiple.QuadPart = 0;\n+\n+    // Allocate physically contiguous memory for user process use\n+    netuio_contextdata->dpdk_seg.mem.virt_addr =\n+                MmAllocateContiguousMemorySpecifyCache(USER_MEMORY_SEGMENT_SIZE,\n+                                                       lowest_acceptable_address,\n+                                                       highest_acceptable_address,\n+                                                       boundary_address_multiple,\n+                                                       MmCached);\n+\n+    if (!netuio_contextdata->dpdk_seg.mem.virt_addr) {\n+        status = STATUS_NO_MEMORY;\n+        goto end;\n+    }\n+\n+    netuio_contextdata->dpdk_seg.mem.size = USER_MEMORY_SEGMENT_SIZE;\n+\n+    // Allocate an MDL for this memory region - so that we can map it into the user's process context later\n+    netuio_contextdata->dpdk_seg.mdl = IoAllocateMdl((PVOID)netuio_contextdata->dpdk_seg.mem.virt_addr, USER_MEMORY_SEGMENT_SIZE, FALSE, FALSE, NULL);\n+    if (netuio_contextdata->dpdk_seg.mdl == NULL) {\n+        status = STATUS_NO_MEMORY;\n+        goto end;\n+    }\n+\n+    // Store the region's physical address\n+    netuio_contextdata->dpdk_seg.mem.phys_addr = MmGetPhysicalAddress(netuio_contextdata->dpdk_seg.mem.virt_addr);\n+\n+end:\n+    return status;\n+}\n+\n+static VOID\n+free_usermemory_segment(_In_ WDFOBJECT device)\n+{\n+    PNETUIO_CONTEXT_DATA  netuio_contextdata;\n+    netuio_contextdata = netuio_get_context_data(device);\n+\n+    if (netuio_contextdata) {\n+        if (netuio_contextdata->dpdk_seg.mdl)\n+            IoFreeMdl(netuio_contextdata->dpdk_seg.mdl);\n+\n+        if (netuio_contextdata->dpdk_seg.mem.virt_addr)\n+            MmFreeContiguousMemory(netuio_contextdata->dpdk_seg.mem.virt_addr);\n+    }\n+}\ndiff --git a/kernel/windows/netuio/netuio_dev.h b/kernel/windows/netuio/netuio_dev.h\nnew file mode 100644\nindex 000000000..a19a4fb42\n--- /dev/null\n+++ b/kernel/windows/netuio/netuio_dev.h\n@@ -0,0 +1,65 @@\n+/*-\n+*\n+*   Copyright(c) 2017 Intel Corporation. All rights reserved.\n+*\n+*/\n+\n+#ifndef NETUIO_DEV_H\n+#define NETUIO_DEV_H\n+\n+EXTERN_C_START\n+\n+#include \"netuio_interface.h\"\n+\n+// Constants\n+#define PCI_MAX_BAR              3\n+#define USER_MEMORY_SEGMENT_SIZE (256ULL * 1024ULL * 1024ULL)   // 256MB\n+\n+struct pci_bar {\n+    PHYSICAL_ADDRESS base_addr;\n+    PVOID            virt_addr;\n+    UINT64           size;\n+};\n+\n+struct mem_map_region {\n+    PMDL               mdl;    // MDL describing the memory region\n+    struct mem_region  mem;    // Memory region details\n+};\n+\n+// The device context performs the same job as a WDM device extension in the driver frameworks\n+typedef struct _NETUIO_CONTEXT_DATA\n+{\n+    WDFDEVICE               wdf_device;        // WDF device handle to the FDO\n+    BUS_INTERFACE_STANDARD  bus_interface;     // Bus interface for config space access\n+    struct pci_bar          bar[PCI_MAX_BAR];  // device BARs\n+    struct dev_addr         addr;              // B:D:F details of device\n+    USHORT                  dev_numa_node;     // The NUMA node of the device\n+    struct mem_map_region   dpdk_hw;           // mapped region for the device's register space\n+    struct mem_map_region   dpdk_seg;          // mapped region allocated for DPDK process use\n+} NETUIO_CONTEXT_DATA, *PNETUIO_CONTEXT_DATA;\n+\n+\n+// This macro will generate an inline function called DeviceGetContext\n+// which will be used to get a pointer to the device context memory in a type safe manner.\n+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NETUIO_CONTEXT_DATA, netuio_get_context_data)\n+\n+\n+// Function to initialize the device and its callbacks\n+NTSTATUS netuio_create_device(_Inout_ PWDFDEVICE_INIT DeviceInit);\n+NTSTATUS netuio_map_hw_resources(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST Resources, _In_ WDFCMRESLIST ResourcesTranslated);\n+VOID netuio_free_hw_resources(_In_ WDFDEVICE Device);\n+\n+\n+// Function called for cleanup when device object is being destroyed\n+VOID netuio_evt_device_context_cleanup(_In_ WDFOBJECT Device);\n+\n+// Local function protoyypes\n+static NTSTATUS get_pci_device_info(_In_ WDFOBJECT device);\n+static NTSTATUS create_device_specific_symbolic_link(_In_ WDFOBJECT device);\n+static NTSTATUS allocate_usermemory_segment(_In_ WDFOBJECT device);\n+static VOID free_usermemory_segment(_In_ WDFOBJECT device);\n+\n+\n+EXTERN_C_END\n+\n+#endif // NETUIO_DEV_H\ndiff --git a/kernel/windows/netuio/netuio_drv.c b/kernel/windows/netuio/netuio_drv.c\nnew file mode 100644\nindex 000000000..d45a9ec4f\n--- /dev/null\n+++ b/kernel/windows/netuio/netuio_drv.c\n@@ -0,0 +1,142 @@\n+/*-\n+*\n+*   Copyright(c) 2017 Intel Corporation. All rights reserved.\n+*\n+*/\n+\n+\n+#include \"netuio_drv.h\"\n+\n+#ifdef ALLOC_PRAGMA\n+#pragma alloc_text (INIT, DriverEntry)\n+#pragma alloc_text (PAGE, netuio_evt_device_add)\n+#pragma alloc_text (PAGE, netuio_evt_driver_context_cleanup)\n+#endif\n+\n+\n+/*\n+Routine Description:\n+    DriverEntry initializes the driver and is the first routine called by the\n+    system after the driver is loaded. DriverEntry specifies the other entry\n+    points in the function driver, such as EvtDevice and DriverUnload.\n+\n+Return Value:\n+    STATUS_SUCCESS if successful,\n+    STATUS_UNSUCCESSFUL otherwise.\n+ */\n+NTSTATUS\n+DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)\n+{\n+    WDF_DRIVER_CONFIG config;\n+    NTSTATUS status;\n+    WDF_OBJECT_ATTRIBUTES attributes;\n+\n+    // Register a cleanup callback so that we can call WPP_CLEANUP when\n+    // the framework driver object is deleted during driver unload.\n+    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);\n+    attributes.EvtCleanupCallback = netuio_evt_driver_context_cleanup;\n+\n+    WDF_DRIVER_CONFIG_INIT(&config, netuio_evt_device_add);\n+\n+    status = WdfDriverCreate(DriverObject, RegistryPath,\n+                             &attributes, &config,\n+                             WDF_NO_HANDLE);\n+\n+    if (!NT_SUCCESS(status)) {\n+        return status;\n+    }\n+\n+    return status;\n+}\n+\n+\n+/*\n+Routine Description:\n+    netuio_evt_device_add is called by the framework in response to AddDevice\n+    call from the PnP manager. We create and initialize a device object to\n+    represent a new instance of the device.\n+\n+Return Value:\n+    NTSTATUS\n+ */\n+NTSTATUS\n+netuio_evt_device_add(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit)\n+{\n+    NTSTATUS status;\n+    WDF_PNPPOWER_EVENT_CALLBACKS    pnpPowerCallbacks;\n+\n+    UNREFERENCED_PARAMETER(Driver);\n+\n+    PAGED_CODE();\n+\n+    // Zero out the PnpPowerCallbacks structure\n+    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);\n+\n+    // Register Plug-aNd-Play and power management callbacks\n+    pnpPowerCallbacks.EvtDevicePrepareHardware = netuio_evt_prepare_hw;\n+    pnpPowerCallbacks.EvtDeviceReleaseHardware = netuio_evt_release_hw;\n+\n+    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);\n+\n+    status = netuio_create_device(DeviceInit);\n+\n+    return status;\n+}\n+\n+/*\n+Routine Description :\n+    Maps HW resources and retrieves the PCI BAR address(es) of the device\n+\n+Return Value :\n+    STATUS_SUCCESS is successful.\n+    STATUS_<ERROR> otherwise\n+-*/\n+NTSTATUS\n+netuio_evt_prepare_hw(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST Resources, _In_ WDFCMRESLIST ResourcesTranslated)\n+{\n+    NTSTATUS status;\n+\n+    status = netuio_map_hw_resources(Device, Resources, ResourcesTranslated);\n+\n+    if (NT_SUCCESS(status)) {\n+        PNETUIO_CONTEXT_DATA  netuio_contextdata;\n+        netuio_contextdata = netuio_get_context_data(Device);\n+        if (netuio_contextdata) {\n+            DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_NETUIO_INFO_LEVEL, \"netUIO Driver loaded...on device (B:D:F) %04d:%02d:%02d\\n\",\n+                                             netuio_contextdata->addr.bus_num, netuio_contextdata->addr.dev_num, netuio_contextdata->addr.func_num);\n+        }\n+    }\n+    return status;\n+}\n+\n+/*\n+Routine Description :\n+    Releases the resource mapped by netuio_evt_prepare_hw\n+\n+Return Value :\n+    STATUS_SUCCESS always.\n+-*/\n+NTSTATUS\n+netuio_evt_release_hw(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST ResourcesTranslated)\n+{\n+    UNREFERENCED_PARAMETER(ResourcesTranslated);\n+\n+    netuio_free_hw_resources(Device);\n+\n+    return STATUS_SUCCESS;\n+}\n+\n+/*\n+Routine Description:\n+    Free all the resources allocated in DriverEntry.\n+\n+Return Value:\n+    None\n+-*/\n+VOID\n+netuio_evt_driver_context_cleanup(_In_ WDFOBJECT DriverObject)\n+{\n+    UNREFERENCED_PARAMETER(DriverObject);\n+    DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_NETUIO_INFO_LEVEL, \"netUIO Driver unloaded.\\n\");\n+    PAGED_CODE();\n+}\ndiff --git a/kernel/windows/netuio/netuio_drv.h b/kernel/windows/netuio/netuio_drv.h\nnew file mode 100644\nindex 000000000..39d7f301e\n--- /dev/null\n+++ b/kernel/windows/netuio/netuio_drv.h\n@@ -0,0 +1,33 @@\n+/*-\n+*\n+*   Copyright(c) 2017 Intel Corporation. All rights reserved.\n+*\n+*/\n+\n+\n+#ifndef NETUIO_DRV_H\n+#define NETUIO_DRV_H\n+\n+#define INITGUID\n+\n+#include <ntddk.h>\n+#include <wdf.h>\n+\n+#include \"netuio_dev.h\"\n+#include \"netuio_queue.h\"\n+\n+EXTERN_C_START\n+\n+// Print output constants\n+#define DPFLTR_NETUIO_INFO_LEVEL   35\n+\n+// WDFDRIVER Events\n+DRIVER_INITIALIZE DriverEntry;\n+EVT_WDF_DRIVER_DEVICE_ADD       netuio_evt_device_add;\n+EVT_WDF_OBJECT_CONTEXT_CLEANUP  netuio_evt_driver_context_cleanup;\n+EVT_WDF_DEVICE_PREPARE_HARDWARE netuio_evt_prepare_hw;\n+EVT_WDF_DEVICE_RELEASE_HARDWARE netuio_evt_release_hw;\n+\n+EXTERN_C_END\n+\n+#endif // NETUIO_DRV_H\ndiff --git a/kernel/windows/netuio/netuio_interface.h b/kernel/windows/netuio/netuio_interface.h\nnew file mode 100644\nindex 000000000..b86bf5d3f\n--- /dev/null\n+++ b/kernel/windows/netuio/netuio_interface.h\n@@ -0,0 +1,69 @@\n+/*-\n+*\n+*   Copyright(c) 2017 Intel Corporation. All rights reserved.\n+*\n+*/\n+\n+\n+#ifndef NETUIO_INTERFACE_H\n+#define NETUIO_INTERFACE_H\n+\n+// All structures in this file are packed on an 8B boundary. \n+#pragma pack(push)\n+#pragma pack(8)\n+\n+// Define an Interface Guid so that any app can find the device and talk to it.\n+DEFINE_GUID (GUID_DEVINTERFACE_netUIO, 0x08336f60,0x0679,0x4c6c,0x85,0xd2,0xae,0x7c,0xed,0x65,0xff,0xf7); // {08336f60-0679-4c6c-85d2-ae7ced65fff7}\n+\n+// Device name definitions\n+#define NETUIO_DEVICE_SYMBOLIC_LINK_ANSI    \"\\\\DosDevices\\\\netuio\"\n+\n+// netUIO driver symbolic name (prefix)\n+#define NETUIO_DRIVER_NAME  _T(\"netuio\")\n+\n+// IOCTL code definitions\n+#define IOCTL_NETUIO_GET_HW_DATA      CTL_CODE(FILE_DEVICE_NETWORK, 51, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n+#define IOCTL_NETUIO_PCI_CONFIG_IO    CTL_CODE(FILE_DEVICE_NETWORK, 52, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n+\n+struct mem_region {\n+    UINT64           size;       // memory region size\n+    PHYSICAL_ADDRESS phys_addr;  // physical address of the memory region\n+    PVOID            virt_addr;  // virtual address of the memory region\n+    PVOID            user_mapped_virt_addr;  // virtual address of the region mapped into user process context\n+};\n+\n+struct dev_addr {\n+    ULONG   bus_num;\n+    USHORT  dev_num;\n+    USHORT  func_num;\n+};\n+\n+enum pci_io {\n+    PCI_IO_READ = 0,\n+    PCI_IO_WRITE = 1\n+};\n+\n+struct dpdk_private_info\n+{\n+    struct mem_region   hw;\n+    struct mem_region   ms;\n+    struct dev_addr     dev_addr;\n+    struct mem_region\tbar1;\n+//  struct mem_region\tbar2;\n+    UINT16              dev_id;\n+    UINT16              sub_dev_id;\n+    USHORT              dev_numa_node;\n+    USHORT              reserved;\n+};\n+\n+struct dpdk_pci_config_io\n+{\n+    struct dev_addr     dev_addr;\n+    PVOID               buf;\n+    UINT32              offset;\n+    enum pci_io         op;\n+};\n+\n+#pragma pack(pop)\n+\n+#endif // NETUIO_INTERFACE_H\ndiff --git a/kernel/windows/netuio/netuio_queue.c b/kernel/windows/netuio/netuio_queue.c\nnew file mode 100644\nindex 000000000..312d4b682\n--- /dev/null\n+++ b/kernel/windows/netuio/netuio_queue.c\n@@ -0,0 +1,271 @@\n+/*-\n+*\n+*   Copyright(c) 2017 Intel Corporation. All rights reserved.\n+*\n+*/\n+\n+\n+#include \"netuio_drv.h\"\n+\n+#ifdef ALLOC_PRAGMA\n+#pragma alloc_text (PAGE, netuio_queue_initialize)\n+#endif\n+\n+VOID netuio_read_PCI_config(PNETUIO_CONTEXT_DATA netuio_contextdata, ULONG offset, PVOID buffer)\n+{\n+    netuio_contextdata->bus_interface.GetBusData(netuio_contextdata->bus_interface.Context,\n+                                                 PCI_WHICHSPACE_CONFIG,\n+                                                 buffer,\n+                                                 offset,\n+                                                 sizeof(UINT32));\n+}\n+\n+VOID netuio_write_PCI_config(PNETUIO_CONTEXT_DATA netuio_contextdata, ULONG offset, PVOID buffer)\n+{\n+    netuio_contextdata->bus_interface.SetBusData(netuio_contextdata->bus_interface.Context,\n+                                                 PCI_WHICHSPACE_CONFIG,\n+                                                 buffer,\n+                                                 offset,\n+                                                 sizeof(UINT32));\n+}\n+\n+static NTSTATUS\n+netuio_handle_get_hw_data_request(_In_ WDFREQUEST Request, _In_ PNETUIO_CONTEXT_DATA netuio_contextdata,\n+                                   _In_ PVOID outputBuf, _In_ size_t outputBufSize)\n+{\n+    NTSTATUS status = STATUS_SUCCESS;\n+\n+    WDF_REQUEST_PARAMETERS params;\n+    WDF_REQUEST_PARAMETERS_INIT(&params);\n+    WdfRequestGetParameters(Request, &params);\n+\n+    if (!netuio_contextdata || (outputBufSize != sizeof(struct dpdk_private_info))) {\n+        status = STATUS_INVALID_PARAMETER;\n+        goto end;\n+    }\n+\n+    struct dpdk_private_info *dpdk_pvt_info = (struct dpdk_private_info *)outputBuf;\n+    RtlZeroMemory(dpdk_pvt_info, outputBufSize);\n+\n+    dpdk_pvt_info->hw.phys_addr.QuadPart = netuio_contextdata->bar[0].base_addr.QuadPart;\n+    dpdk_pvt_info->hw.user_mapped_virt_addr = netuio_contextdata->dpdk_hw.mem.user_mapped_virt_addr;\n+    dpdk_pvt_info->hw.size = netuio_contextdata->bar[0].size;\n+\n+    dpdk_pvt_info->ms.phys_addr.QuadPart = netuio_contextdata->dpdk_seg.mem.phys_addr.QuadPart;\n+    dpdk_pvt_info->ms.user_mapped_virt_addr = netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr;\n+    dpdk_pvt_info->ms.size = netuio_contextdata->dpdk_seg.mem.size;\n+end:\n+    return status;\n+}\n+\n+/*\n+Routine Description:\n+    The I/O dispatch callbacks for the frameworks device object are configured here.\n+    A single default I/O Queue is configured for parallel request processing, and a\n+    driver context memory allocation is created to hold our structure QUEUE_CONTEXT.\n+\n+Return Value:\n+    None\n+ */\n+NTSTATUS\n+netuio_queue_initialize(_In_ WDFDEVICE Device)\n+{\n+    WDFQUEUE queue;\n+    NTSTATUS status;\n+    WDF_IO_QUEUE_CONFIG    queueConfig;\n+\n+    PAGED_CODE();\n+\n+    // Configure a default queue so that requests that are not\n+    // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto\n+    // other queues get dispatched here.\n+    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel);\n+\n+    queueConfig.EvtIoDeviceControl = netuio_evt_IO_device_control;\n+    queueConfig.EvtIoStop = netuio_evt_IO_stop;\n+\n+    status = WdfIoQueueCreate(Device,\n+                              &queueConfig,\n+                              WDF_NO_OBJECT_ATTRIBUTES,\n+                              &queue);\n+\n+    if( !NT_SUCCESS(status) ) {\n+        return status;\n+    }\n+\n+    return status;\n+}\n+\n+/*\n+Routine Description:\n+    This event is invoked when the framework receives IRP_MJ_DEVICE_CONTROL request.\n+\n+Return Value:\n+    None\n+ */\n+VOID\n+netuio_evt_IO_device_control(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request,\n+                              _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength,\n+                              _In_ ULONG IoControlCode)\n+{\n+    UNREFERENCED_PARAMETER(OutputBufferLength);\n+    UNREFERENCED_PARAMETER(InputBufferLength);\n+\n+    NTSTATUS status = STATUS_SUCCESS;\n+    PVOID    input_buf = NULL, output_buf = NULL;\n+    size_t   input_buf_size, output_buf_size;\n+    size_t  bytes_returned = 0;\n+\n+    WDFDEVICE device = WdfIoQueueGetDevice(Queue);\n+\n+    PNETUIO_CONTEXT_DATA  netuio_contextdata;\n+    netuio_contextdata = netuio_get_context_data(device);\n+\n+    switch (IoControlCode) {\n+    case IOCTL_NETUIO_GET_HW_DATA:\n+        // First retrieve the input buffer and see if it matches our device\n+        status = WdfRequestRetrieveInputBuffer(Request, sizeof(struct dpdk_private_info), &input_buf, &input_buf_size);\n+        if (!NT_SUCCESS(status)) {\n+            status = STATUS_INVALID_BUFFER_SIZE;\n+            break;\n+        }\n+\n+        struct dpdk_private_info *dpdk_pvt_info = (struct dpdk_private_info *)input_buf;\n+        // Ensure that the B:D:F match - otherwise, fail the IOCTL\n+        if ((netuio_contextdata->addr.bus_num != dpdk_pvt_info->dev_addr.bus_num) ||\n+            (netuio_contextdata->addr.dev_num != dpdk_pvt_info->dev_addr.dev_num) ||\n+            (netuio_contextdata->addr.func_num != dpdk_pvt_info->dev_addr.func_num)) {\n+            status = STATUS_NOT_SAME_DEVICE;\n+            break;\n+        }\n+\n+        // Map the previously allocated/defined memory regions to the user's process context\n+        MmBuildMdlForNonPagedPool(netuio_contextdata->dpdk_hw.mdl);\n+        netuio_contextdata->dpdk_hw.mem.user_mapped_virt_addr =\n+                            MmMapLockedPagesSpecifyCache(netuio_contextdata->dpdk_hw.mdl, UserMode, MmCached,\n+        NULL, FALSE, (NormalPagePriority | MdlMappingNoExecute));\n+\n+        MmBuildMdlForNonPagedPool(netuio_contextdata->dpdk_seg.mdl);\n+        netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr =\n+                            MmMapLockedPagesSpecifyCache(netuio_contextdata->dpdk_seg.mdl, UserMode, MmCached,\n+        NULL, FALSE, (NormalPagePriority | MdlMappingNoExecute));\n+\n+        if (!netuio_contextdata->dpdk_hw.mem.user_mapped_virt_addr && !netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr) {\n+            status = STATUS_INSUFFICIENT_RESOURCES;\n+            break;\n+        }\n+\n+        // Zero out the physically contiguous block\n+        RtlZeroMemory(netuio_contextdata->dpdk_seg.mem.virt_addr, netuio_contextdata->dpdk_seg.mem.size);\n+\n+        // Return relevant data to the caller\n+        status = WdfRequestRetrieveOutputBuffer(Request, sizeof(struct dpdk_private_info), &output_buf, &output_buf_size);\n+        if (!NT_SUCCESS(status)) {\n+            status = STATUS_INVALID_BUFFER_SIZE;\n+            break;\n+        }\n+        ASSERT(output_buf_size == OutputBufferLength);\n+        status = netuio_handle_get_hw_data_request(Request, netuio_contextdata, output_buf, output_buf_size);\n+        if (NT_SUCCESS(status))\n+            bytes_returned = output_buf_size;\n+\n+        break;\n+\n+    case IOCTL_NETUIO_PCI_CONFIG_IO:\n+        // First retrieve the input buffer and see if it matches our device\n+        status = WdfRequestRetrieveInputBuffer(Request, sizeof(struct dpdk_pci_config_io), &input_buf, &input_buf_size);\n+        if (!NT_SUCCESS(status)) {\n+            status = STATUS_INVALID_BUFFER_SIZE;\n+            break;\n+        }\n+\n+        struct dpdk_pci_config_io *dpdk_pci_io_input = (struct dpdk_pci_config_io *)input_buf;\n+        // Ensure that the B:D:F match - otherwise, fail the IOCTL\n+        if ((netuio_contextdata->addr.bus_num != dpdk_pci_io_input->dev_addr.bus_num) ||\n+            (netuio_contextdata->addr.dev_num != dpdk_pci_io_input->dev_addr.dev_num) ||\n+            (netuio_contextdata->addr.func_num != dpdk_pci_io_input->dev_addr.func_num)) {\n+            status = STATUS_NOT_SAME_DEVICE;\n+            break;\n+        }\n+        // Retrieve output buffer\n+        status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT32), &output_buf, &output_buf_size);\n+        if (!NT_SUCCESS(status)) {\n+            status = STATUS_INVALID_BUFFER_SIZE;\n+            break;\n+        }\n+        ASSERT(output_buf_size == OutputBufferLength);\n+\n+        if (dpdk_pci_io_input->op == PCI_IO_READ) {\n+            netuio_read_PCI_config(netuio_contextdata, dpdk_pci_io_input->offset, output_buf);\n+            bytes_returned = output_buf_size;\n+        }\n+        else {\n+            netuio_write_PCI_config(netuio_contextdata, dpdk_pci_io_input->offset, dpdk_pci_io_input->buf);\n+            bytes_returned = 0;\n+        }\n+\n+        break;\n+\n+    default:\n+        break;\n+    }\n+\n+    WdfRequestCompleteWithInformation(Request, status, bytes_returned);\n+\n+    return;\n+}\n+\n+/*\n+Routine Description:\n+    This event is invoked for a power-managed queue before the device leaves the working state (D0).\n+\n+Return Value:\n+    None\n+ */\n+VOID\n+netuio_evt_IO_stop(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request,_In_ ULONG ActionFlags)\n+{\n+    //\n+    // In most cases, the EvtIoStop callback function completes, cancels, or postpones\n+    // further processing of the I/O request.\n+    //\n+    // Typically, the driver uses the following rules:\n+    //\n+    // - If the driver owns the I/O request, it calls WdfRequestUnmarkCancelable\n+    //   (if the request is cancelable) and either calls WdfRequestStopAcknowledge\n+    //   with a Requeue value of TRUE, or it calls WdfRequestComplete with a\n+    //   completion status value of STATUS_SUCCESS or STATUS_CANCELLED.\n+    //\n+    //   Before it can call these methods safely, the driver must make sure that\n+    //   its implementation of EvtIoStop has exclusive access to the request.\n+    //\n+    //   In order to do that, the driver must synchronize access to the request\n+    //   to prevent other threads from manipulating the request concurrently.\n+    //   The synchronization method you choose will depend on your driver's design.\n+    //\n+    //   For example, if the request is held in a shared context, the EvtIoStop callback\n+    //   might acquire an internal driver lock, take the request from the shared context,\n+    //   and then release the lock. At this point, the EvtIoStop callback owns the request\n+    //   and can safely complete or requeue the request.\n+    //\n+    // - If the driver has forwarded the I/O request to an I/O target, it either calls\n+    //   WdfRequestCancelSentRequest to attempt to cancel the request, or it postpones\n+    //   further processing of the request and calls WdfRequestStopAcknowledge with\n+    //   a Requeue value of FALSE.\n+    //\n+    // A driver might choose to take no action in EvtIoStop for requests that are\n+    // guaranteed to complete in a small amount of time.\n+    //\n+    // In this case, the framework waits until the specified request is complete\n+    // before moving the device (or system) to a lower power state or removing the device.\n+    // Potentially, this inaction can prevent a system from entering its hibernation state\n+    // or another low system power state. In extreme cases, it can cause the system\n+    // to crash with bugcheck code 9F.\n+    //\n+    UNREFERENCED_PARAMETER(Queue);\n+    UNREFERENCED_PARAMETER(Request);\n+    UNREFERENCED_PARAMETER(ActionFlags);\n+\n+    return;\n+}\n+\ndiff --git a/kernel/windows/netuio/netuio_queue.h b/kernel/windows/netuio/netuio_queue.h\nnew file mode 100644\nindex 000000000..6a0306516\n--- /dev/null\n+++ b/kernel/windows/netuio/netuio_queue.h\n@@ -0,0 +1,30 @@\n+/*-\n+*\n+*   Copyright(c) 2017 Intel Corporation. All rights reserved.\n+*\n+*/\n+\n+\n+#ifndef NETUIO_QUEUE_H\n+#define NETUIO_QUEUE_H\n+\n+EXTERN_C_START\n+\n+// This is the context that can be placed per queue and would contain per queue information.\n+typedef struct _QUEUE_CONTEXT {\n+    ULONG PrivateDeviceData;  // just a placeholder\n+} QUEUE_CONTEXT, *PQUEUE_CONTEXT;\n+\n+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, QueueGetContext)\n+\n+\n+NTSTATUS\n+netuio_queue_initialize(_In_ WDFDEVICE hDevice);\n+\n+// Events from the IoQueue object\n+EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL netuio_evt_IO_device_control;\n+EVT_WDF_IO_QUEUE_IO_STOP netuio_evt_IO_stop;\n+\n+EXTERN_C_END\n+\n+#endif // NETUIO_QUEUE_H\ndiff --git a/kernel/windows/netuio/resource.h b/kernel/windows/netuio/resource.h\nnew file mode 100644\nindex 000000000..9789ffdf3\n--- /dev/null\n+++ b/kernel/windows/netuio/resource.h\n@@ -0,0 +1,14 @@\n+//{{NO_DEPENDENCIES}}\n+// Microsoft Visual C++ generated include file.\n+// Used by netuio.rc\n+\n+// Next default values for new objects\n+// \n+#ifdef APSTUDIO_INVOKED\n+#ifndef APSTUDIO_READONLY_SYMBOLS\n+#define _APS_NEXT_RESOURCE_VALUE        101\n+#define _APS_NEXT_COMMAND_VALUE         40001\n+#define _APS_NEXT_CONTROL_VALUE         1001\n+#define _APS_NEXT_SYMED_VALUE           101\n+#endif\n+#endif\n",
    "prefixes": [
        "06/22"
    ]
}