Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/75533/?format=api
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(¶ms);\n+ WdfRequestGetParameters(Request, ¶ms);\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" ] }{ "id": 75533, "url": "