winverbs: add new windows based verbs library and driver
authorshefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Fri, 25 Jul 2008 00:53:30 +0000 (00:53 +0000)
committershefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Fri, 25 Jul 2008 00:53:30 +0000 (00:53 +0000)
Include port of libibverbs, example programs, and perftest programs to test winverbs.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@1446 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

122 files changed:
core/dirs
core/winverbs/dirs [new file with mode: 0644]
core/winverbs/kernel/SOURCES [new file with mode: 0644]
core/winverbs/kernel/makefile [new file with mode: 0644]
core/winverbs/kernel/makefile.inc [new file with mode: 0644]
core/winverbs/kernel/winverbs.inx [new file with mode: 0644]
core/winverbs/kernel/winverbs.rc [new file with mode: 0644]
core/winverbs/kernel/wv_cq.c [new file with mode: 0644]
core/winverbs/kernel/wv_cq.h [new file with mode: 0644]
core/winverbs/kernel/wv_device.c [new file with mode: 0644]
core/winverbs/kernel/wv_device.h [new file with mode: 0644]
core/winverbs/kernel/wv_driver.c [new file with mode: 0644]
core/winverbs/kernel/wv_driver.h [new file with mode: 0644]
core/winverbs/kernel/wv_ep.h [new file with mode: 0644]
core/winverbs/kernel/wv_listen.h [new file with mode: 0644]
core/winverbs/kernel/wv_pd.c [new file with mode: 0644]
core/winverbs/kernel/wv_pd.h [new file with mode: 0644]
core/winverbs/kernel/wv_provider.c [new file with mode: 0644]
core/winverbs/kernel/wv_provider.h [new file with mode: 0644]
core/winverbs/kernel/wv_qp.c [new file with mode: 0644]
core/winverbs/kernel/wv_qp.h [new file with mode: 0644]
core/winverbs/kernel/wv_srq.c [new file with mode: 0644]
core/winverbs/kernel/wv_srq.h [new file with mode: 0644]
core/winverbs/user/SOURCES [new file with mode: 0644]
core/winverbs/user/makefile [new file with mode: 0644]
core/winverbs/user/winverbs.rc [new file with mode: 0644]
core/winverbs/user/wv_base.cpp [new file with mode: 0644]
core/winverbs/user/wv_base.h [new file with mode: 0644]
core/winverbs/user/wv_cq.cpp [new file with mode: 0644]
core/winverbs/user/wv_cq.h [new file with mode: 0644]
core/winverbs/user/wv_device.cpp [new file with mode: 0644]
core/winverbs/user/wv_device.h [new file with mode: 0644]
core/winverbs/user/wv_ep.cpp [new file with mode: 0644]
core/winverbs/user/wv_ep.h [new file with mode: 0644]
core/winverbs/user/wv_exports.src [new file with mode: 0644]
core/winverbs/user/wv_listen.cpp [new file with mode: 0644]
core/winverbs/user/wv_listen.h [new file with mode: 0644]
core/winverbs/user/wv_main.cpp [new file with mode: 0644]
core/winverbs/user/wv_memory.h [new file with mode: 0644]
core/winverbs/user/wv_pd.cpp [new file with mode: 0644]
core/winverbs/user/wv_pd.h [new file with mode: 0644]
core/winverbs/user/wv_provider.cpp [new file with mode: 0644]
core/winverbs/user/wv_provider.h [new file with mode: 0644]
core/winverbs/user/wv_qp.cpp [new file with mode: 0644]
core/winverbs/user/wv_qp.h [new file with mode: 0644]
core/winverbs/user/wv_srq.cpp [new file with mode: 0644]
core/winverbs/user/wv_srq.h [new file with mode: 0644]
core/winverbs/user/wv_uverbs.cpp [new file with mode: 0644]
core/winverbs/wv_ioctl.h [new file with mode: 0644]
core/winverbs/wv_public.h [new file with mode: 0644]
etc/kernel/index_list.c [new file with mode: 0644]
etc/user/getopt.c [new file with mode: 0644]
inc/kernel/index_list.h [new file with mode: 0644]
inc/user/getopt.h [new file with mode: 0644]
inc/user/rdma/winverbs.h [new file with mode: 0644]
inc/user/rdma/wvstatus.h [new file with mode: 0644]
tests/dirs
tests/perftest/dirs [new file with mode: 0644]
tests/perftest/rdma_bw/SOURCES [new file with mode: 0644]
tests/perftest/rdma_bw/makefile [new file with mode: 0644]
tests/perftest/rdma_bw/rdma_bw.c [new file with mode: 0644]
tests/perftest/rdma_lat/SOURCES [new file with mode: 0644]
tests/perftest/rdma_lat/makefile [new file with mode: 0644]
tests/perftest/rdma_lat/rdma_lat.c [new file with mode: 0644]
tests/perftest/read_bw/SOURCES [new file with mode: 0644]
tests/perftest/read_bw/makefile [new file with mode: 0644]
tests/perftest/read_bw/read_bw.c [new file with mode: 0644]
tests/perftest/read_lat/SOURCES [new file with mode: 0644]
tests/perftest/read_lat/makefile [new file with mode: 0644]
tests/perftest/read_lat/read_lat.c [new file with mode: 0644]
tests/perftest/send_bw/SOURCES [new file with mode: 0644]
tests/perftest/send_bw/makefile [new file with mode: 0644]
tests/perftest/send_bw/send_bw.c [new file with mode: 0644]
tests/perftest/send_lat/SOURCES [new file with mode: 0644]
tests/perftest/send_lat/makefile [new file with mode: 0644]
tests/perftest/send_lat/send_lat.c [new file with mode: 0644]
tests/perftest/write_bw/SOURCES [new file with mode: 0644]
tests/perftest/write_bw/makefile [new file with mode: 0644]
tests/perftest/write_bw/write_bw.c [new file with mode: 0644]
tests/perftest/write_bw_postlist/SOURCES [new file with mode: 0644]
tests/perftest/write_bw_postlist/makefile [new file with mode: 0644]
tests/perftest/write_bw_postlist/write_bw_postlist.c [new file with mode: 0644]
tests/perftest/write_lat/SOURCES [new file with mode: 0644]
tests/perftest/write_lat/makefile [new file with mode: 0644]
tests/perftest/write_lat/write_lat.c [new file with mode: 0644]
ulp/dirs
ulp/libibverbs/AUTHORS [new file with mode: 0644]
ulp/libibverbs/COPYING [new file with mode: 0644]
ulp/libibverbs/dirs [new file with mode: 0644]
ulp/libibverbs/examples/asyncwatch/SOURCES [new file with mode: 0644]
ulp/libibverbs/examples/asyncwatch/asyncwatch.c [new file with mode: 0644]
ulp/libibverbs/examples/asyncwatch/makefile [new file with mode: 0644]
ulp/libibverbs/examples/device_list.c [new file with mode: 0644]
ulp/libibverbs/examples/devinfo/SOURCES [new file with mode: 0644]
ulp/libibverbs/examples/devinfo/devinfo.c [new file with mode: 0644]
ulp/libibverbs/examples/devinfo/makefile [new file with mode: 0644]
ulp/libibverbs/examples/dirs [new file with mode: 0644]
ulp/libibverbs/examples/pingpong.c [new file with mode: 0644]
ulp/libibverbs/examples/pingpong.h [new file with mode: 0644]
ulp/libibverbs/examples/rc_pingpong/SOURCES [new file with mode: 0644]
ulp/libibverbs/examples/rc_pingpong/makefile [new file with mode: 0644]
ulp/libibverbs/examples/rc_pingpong/rc_pingpong.c [new file with mode: 0644]
ulp/libibverbs/examples/srq_pingpong/SOURCES [new file with mode: 0644]
ulp/libibverbs/examples/srq_pingpong/makefile [new file with mode: 0644]
ulp/libibverbs/examples/srq_pingpong/srq_pingpong.c [new file with mode: 0644]
ulp/libibverbs/examples/uc_pingpong/SOURCES [new file with mode: 0644]
ulp/libibverbs/examples/uc_pingpong/makefile [new file with mode: 0644]
ulp/libibverbs/examples/uc_pingpong/uc_pingpong.c [new file with mode: 0644]
ulp/libibverbs/examples/ud_pingpong/SOURCES [new file with mode: 0644]
ulp/libibverbs/examples/ud_pingpong/makefile [new file with mode: 0644]
ulp/libibverbs/examples/ud_pingpong/ud_pingpong.c [new file with mode: 0644]
ulp/libibverbs/include/infiniband/verbs.h [new file with mode: 0644]
ulp/libibverbs/src/Sources [new file with mode: 0644]
ulp/libibverbs/src/device.cpp [new file with mode: 0644]
ulp/libibverbs/src/enum_strs.cpp [new file with mode: 0644]
ulp/libibverbs/src/ibv_export.def [new file with mode: 0644]
ulp/libibverbs/src/ibv_exports.src [new file with mode: 0644]
ulp/libibverbs/src/ibv_main.cpp [new file with mode: 0644]
ulp/libibverbs/src/ibverbs.h [new file with mode: 0644]
ulp/libibverbs/src/ibverbs.rc [new file with mode: 0644]
ulp/libibverbs/src/makefile [new file with mode: 0644]
ulp/libibverbs/src/verbs.cpp [new file with mode: 0644]

index 2dc3235..0162fac 100644 (file)
--- a/core/dirs
+++ b/core/dirs
@@ -1,6 +1,7 @@
 DIRS=\\r
-       complib \\r
-       al              \\r
-       bus             \\r
-       iou             \\r
-       ibat\r
+       complib         \\r
+       al                      \\r
+       bus                     \\r
+       iou                     \\r
+       ibat            \\r
+       winverbs\r
diff --git a/core/winverbs/dirs b/core/winverbs/dirs
new file mode 100644 (file)
index 0000000..a5a581d
--- /dev/null
@@ -0,0 +1,3 @@
+DIRS=\\r
+       kernel \\r
+       user\r
diff --git a/core/winverbs/kernel/SOURCES b/core/winverbs/kernel/SOURCES
new file mode 100644 (file)
index 0000000..bf47175
--- /dev/null
@@ -0,0 +1,26 @@
+TARGETNAME = winverbs\r
+TARGETPATH = ..\..\..\bin\kernel\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = DRIVER\r
+\r
+KMDF_VERSION_MAJOR = 1\r
+INF_NAME = winverbs\r
+NTTARGETFILES = $(OBJ_PATH)\$(O)\$(INF_NAME).inf\r
+MISCFILES = $(NTTARGETFILES)\r
+TARGETLIBS = $(TARGETLIBS) \\r
+                        $(DDK_LIB_PATH)\wdmsec.lib             \\r
+                        $(TARGETPATH)\*\complib.lib\r
+\r
+SOURCES = \\r
+       winverbs.rc             \\r
+       wv_driver.c             \\r
+       wv_provider.c   \\r
+       wv_device.c             \\r
+       wv_cq.c                 \\r
+       wv_pd.c                 \\r
+       wv_srq.c                \\r
+       wv_qp.c\r
+\r
+INCLUDES = ..;..\..\..\inc;..\..\..\inc\kernel;..\..\..\inc\user;..\..\..\etc\kernel;\r
+\r
+C_DEFINES = $(C_DEFINES) -DIOCTL_INTERFACE=1\r
+\r
diff --git a/core/winverbs/kernel/makefile b/core/winverbs/kernel/makefile
new file mode 100644 (file)
index 0000000..128ed37
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the Windows NT DDK\r
+#\r
+\r
+!INCLUDE ..\..\..\inc\openib.def\r
diff --git a/core/winverbs/kernel/makefile.inc b/core/winverbs/kernel/makefile.inc
new file mode 100644 (file)
index 0000000..4986bef
--- /dev/null
@@ -0,0 +1,7 @@
+_LNG=$(LANGUAGE)\r
+_INX=.\r
+STAMP=stampinf -f $@ -a $(_BUILDARCH) -k $(KMDF_VERSION_MAJOR).$(KMDF_VERSION_MINOR)\r
+\r
+$(OBJ_PATH)\$(O)\$(INF_NAME).inf: $(_INX)\$(INF_NAME).inx \r
+    copy $(_INX)\$(@B).inx $@\r
+    $(STAMP)\r
diff --git a/core/winverbs/kernel/winverbs.inx b/core/winverbs/kernel/winverbs.inx
new file mode 100644 (file)
index 0000000..b9d8c0e
--- /dev/null
@@ -0,0 +1,108 @@
+;\r
+; Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+;\r
+; This software is available to you under the OpenIB.org BSD license\r
+; below:\r
+;\r
+;     Redistribution and use in source and binary forms, with or\r
+;     without modification, are permitted provided that the following\r
+;     conditions are met:\r
+;\r
+;      - Redistributions of source code must retain the above\r
+;        copyright notice, this list of conditions and the following\r
+;        disclaimer.\r
+;\r
+;      - Redistributions in binary form must reproduce the above\r
+;        copyright notice, this list of conditions and the following\r
+;        disclaimer in the documentation and/or other materials\r
+;        provided with the distribution.\r
+;\r
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+; BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+; ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+; SOFTWARE.\r
+;\r
+\r
+[Version]\r
+Signature = "$WINDOWS NT$"\r
+Class = InfiniBandHca\r
+ClassGUID = {58517E00-D3CF-40c9-A679-CEE5752F4491}\r
+Provider = %OFA%\r
+DriverVer = 05/20/2008\r
+CatalogFile = winverbs.cat\r
+\r
+[SourceDisksNames]\r
+1 = %DiskId%\r
+\r
+[SourceDisksFiles]\r
+winverbs.sys = 1\r
+winverbs.dll = 1\r
+winverbsd.dll = 1\r
+\r
+[DefaultInstall]\r
+AddReg = WvClassAddReg\r
+CopyFiles = WvClassCopySysFiles, WvClassCopyDllFiles\r
+\r
+[WvClassAddReg]\r
+HKLM, System\CurrentControlSet\Control\Class\{58517E00-D3CF-40c9-A679-CEE5752F4491}, UpperFilters, 0x00010008, WinVerbs\r
+\r
+[DestinationDirs]\r
+WvClassCopySysFiles = 12\r
+WvClassCopyDllFiles = 11\r
+\r
+[WvClassCopySysFiles]\r
+winverbs.sys\r
+\r
+[WvClassCopyDllFiles]\r
+winverbs.dll\r
+winverbsd.dll\r
+\r
+[Manufacturer]\r
+%OFA% = WvModel, NT$ARCH$\r
+\r
+[WvModel]\r
+%WinVerbs.DeviceDesc% = WvDevice, root\WinVerbs\r
+\r
+[DefaultInstall.Services]\r
+AddService = WinVerbs,, WvClassService\r
+\r
+[WvClassService]\r
+DisplayName = %WinVerbs.ServiceDesc%\r
+ServiceType = 1\r
+StartType = 3\r
+ErrorControl = 1\r
+ServiceBinary  = %12%\winverbs.sys\r
+LoadOrderGroup = PNP Filter\r
+\r
+[WvDevice.CoInstallers]\r
+AddReg = WvDeviceCoInstAddReg\r
+CopyFiles = WvDeviceCoInstCopyFiles\r
+\r
+[DestinationDirs]\r
+WvDeviceCoInstCopyFiles = 11\r
+\r
+[WvDeviceCoInstAddReg]\r
+HKR,, CoInstallers32, 0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll, WdfCoInstaller"\r
+\r
+[WvDeviceCoInstCopyFiles]\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll\r
+\r
+[SourceDisksFiles]\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1\r
+\r
+[WvDevice.Wdf]\r
+KmdfService = WinVerbs, WvWdfSect\r
+\r
+[WvWdfSect]\r
+KmdfLibraryVersion = $KMDFVERSION$\r
+\r
+[Strings]\r
+OFA = "OpenFabrics"\r
+DiskId = "OpenFabrics WinVerbs Installation"\r
+WinVerbs.DeviceDesc = "WinVerbs Driver"\r
+WinVerbs.ServiceDesc = "WinVerbs Service"\r
+ClassName = "WinVerbs Device"\r
diff --git a/core/winverbs/kernel/winverbs.rc b/core/winverbs/kernel/winverbs.rc
new file mode 100644 (file)
index 0000000..50b5759
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include <oib_ver.h>\r
+\r
+#define VER_FILETYPE                           VFT_DRV\r
+#define VER_FILESUBTYPE                                VFT2_DRV_SYSTEM\r
+\r
+#ifdef _DEBUG_\r
+#define VER_FILEDESCRIPTION_STR                "Kernel WinVerbs (Debug)"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR                "Kernel WinVerbs"\r
+#endif\r
+\r
+#define VER_INTERNALNAME_STR           "winverbs.sys"\r
+#define VER_ORIGINALFILENAME_STR       "winverbs.sys"\r
+\r
+#include <common.ver>\r
diff --git a/core/winverbs/kernel/wv_cq.c b/core/winverbs/kernel/wv_cq.c
new file mode 100644 (file)
index 0000000..3c15333
--- /dev/null
@@ -0,0 +1,350 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include "wv_driver.h"\r
+#include "wv_cq.h"\r
+#include "wv_ioctl.h"\r
+\r
+void WvCqGet(WV_COMPLETION_QUEUE *pCq)\r
+{\r
+       InterlockedIncrement(&pCq->Ref);\r
+}\r
+\r
+void WvCqPut(WV_COMPLETION_QUEUE *pCq)\r
+{\r
+       if (InterlockedDecrement(&pCq->Ref) == 0) {\r
+               KeSetEvent(&pCq->Event, 0, FALSE);\r
+       }\r
+}\r
+\r
+WV_COMPLETION_QUEUE *WvCqAcquire(WV_PROVIDER *pProvider, UINT64 Id)\r
+{\r
+       WV_COMPLETION_QUEUE *cq;\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       cq = IndexListAt(&pProvider->CqIndex, (SIZE_T) Id);\r
+       if (cq != NULL && cq->hVerbsCq != NULL) {\r
+               WvCqGet(cq);\r
+       } else {\r
+               cq = NULL;\r
+               WvProviderEnableRemove(pProvider);\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       return cq;\r
+}\r
+\r
+void WvCqRelease(WV_COMPLETION_QUEUE *pCq)\r
+{\r
+       WvProviderEnableRemove(pCq->pDevice->pProvider);\r
+       WvCqPut(pCq);\r
+}\r
+\r
+static void WvCqCompleteRequests(WDFQUEUE Queue, NTSTATUS ReqStatus)\r
+{\r
+       WDFREQUEST      request;\r
+       NTSTATUS        status;\r
+\r
+       WdfObjectAcquireLock(Queue);\r
+       status = WdfIoQueueRetrieveNextRequest(Queue, &request);\r
+\r
+       while (NT_SUCCESS(status)) {\r
+               WdfRequestComplete(request, ReqStatus);\r
+               status = WdfIoQueueRetrieveNextRequest(Queue, &request);\r
+       }\r
+       WdfObjectReleaseLock(Queue);\r
+}\r
+\r
+static void WvCqEventHandler(ib_event_rec_t *pEvent)\r
+{\r
+       WV_COMPLETION_QUEUE     *cq = pEvent->context;\r
+       WvCqCompleteRequests(cq->Queue, STATUS_UNEXPECTED_IO_ERROR);\r
+       WvCqCompleteRequests(cq->ErrorQueue, STATUS_UNEXPECTED_IO_ERROR);\r
+}\r
+\r
+static void WvCqHandler(void *Context)\r
+{\r
+       WV_COMPLETION_QUEUE     *cq = Context;\r
+\r
+       WvCqCompleteRequests(cq->Queue, STATUS_SUCCESS);\r
+}\r
+\r
+static NTSTATUS WvCqAlloc(WV_DEVICE *pDevice, UINT32 *pSize,\r
+                                                 WV_COMPLETION_QUEUE **ppCq, ci_umv_buf_t *pVerbsData)\r
+{\r
+       ib_api_status_t         ib_status;\r
+       WV_COMPLETION_QUEUE     *cq;\r
+       WDF_IO_QUEUE_CONFIG     config;\r
+       NTSTATUS                        status;\r
+\r
+       cq = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_COMPLETION_QUEUE), 'qcvw');\r
+       if (cq == NULL) {\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       cq->Ref = 1;\r
+       KeInitializeEvent(&cq->Event, NotificationEvent, FALSE);\r
+\r
+       WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);\r
+       status = WdfIoQueueCreate(ControlDevice, &config,\r
+                                                         WDF_NO_OBJECT_ATTRIBUTES, &cq->Queue);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       status = WdfIoQueueCreate(ControlDevice, &config,\r
+                                                         WDF_NO_OBJECT_ATTRIBUTES, &cq->ErrorQueue);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err2;\r
+       }\r
+\r
+       ib_status = pDevice->pVerbs->create_cq(pDevice->hVerbsDevice, cq,\r
+                                                                                  WvCqEventHandler, WvCqHandler,\r
+                                                                                  pSize, &cq->hVerbsCq, pVerbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+               goto err3;\r
+       }\r
+\r
+       cq->pDevice = pDevice;\r
+       cq->pVerbs = pDevice->pVerbs;\r
+       *ppCq = cq;\r
+       return STATUS_SUCCESS;\r
+\r
+err3:\r
+       WdfObjectDelete(cq->ErrorQueue);\r
+err2:\r
+       WdfObjectDelete(cq->Queue);\r
+err1:\r
+       ExFreePool(cq);\r
+       return status;\r
+}\r
+\r
+void WvCqCreate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                                *inid, *outid;\r
+       size_t                                  inlen, outlen;\r
+       WV_DEVICE                               *dev;\r
+       WV_COMPLETION_QUEUE             *cq;\r
+       NTSTATUS                                status;\r
+       ci_umv_buf_t                    verbsData;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &inid, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_ID), &outid, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       dev = WvDeviceAcquire(pProvider, inid->Id);\r
+       if (dev == NULL) {\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+               goto err1;\r
+       }\r
+\r
+       WvInitVerbsData(&verbsData, inid->VerbInfo, inlen - sizeof(WV_IO_ID),\r
+                                       outlen - sizeof(WV_IO_ID), inid + 1);\r
+       status = WvCqAlloc(dev, &inid->Data, &cq, &verbsData);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err2;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       outid->Id = IndexListInsertHead(&pProvider->CqIndex, cq);\r
+       if (outid->Id == 0) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err3;\r
+       }\r
+       InsertHeadList(&dev->CqList, &cq->Entry);\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       WvProviderEnableRemove(pProvider);\r
+       outid->Data = inid->Data;\r
+       outid->VerbInfo = verbsData.status;\r
+       WdfRequestCompleteWithInformation(Request, status, outlen);\r
+       return;\r
+\r
+err3:\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+       WvCqFree(cq);\r
+err2:\r
+       WvDeviceRelease(dev);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvCqDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_COMPLETION_QUEUE             *cq;\r
+       UINT64                                  *id;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       cq = IndexListAt(&pProvider->CqIndex, (SIZE_T) *id);\r
+       if (cq == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+       } else if (cq->Ref > 1) {\r
+               status = STATUS_ACCESS_DENIED;\r
+       } else {\r
+               IndexListRemove(&pProvider->CqIndex, (SIZE_T) *id);\r
+               RemoveEntryList(&cq->Entry);\r
+               status = STATUS_SUCCESS;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       if (NT_SUCCESS(status)) {\r
+               WvCqFree(cq);\r
+       }\r
+       WvProviderEnableRemove(pProvider);\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvCqFree(WV_COMPLETION_QUEUE *pCq)\r
+{\r
+       if (InterlockedDecrement(&pCq->Ref) > 0) {\r
+               KeWaitForSingleObject(&pCq->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
+\r
+       if (pCq->hVerbsCq != NULL) {\r
+               pCq->pVerbs->destroy_cq(pCq->hVerbsCq);\r
+       }\r
+\r
+       WdfIoQueuePurgeSynchronously(pCq->Queue);\r
+       WdfIoQueuePurgeSynchronously(pCq->ErrorQueue);\r
+       WdfObjectDelete(pCq->Queue);\r
+       WdfObjectDelete(pCq->ErrorQueue);\r
+       WvDevicePut(pCq->pDevice);\r
+       ExFreePool(pCq);\r
+}\r
+\r
+void WvCqResize(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                                *inid, *outid;\r
+       size_t                                  inlen, outlen, len = 0;\r
+       WV_COMPLETION_QUEUE             *cq;\r
+       NTSTATUS                                status;\r
+       ib_api_status_t                 ib_status;\r
+       ci_umv_buf_t                    verbsData;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &inid, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_ID), &outid, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       cq = WvCqAcquire(pProvider, inid->Id);\r
+       if (cq == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WvInitVerbsData(&verbsData, inid->VerbInfo, inlen - sizeof(WV_IO_ID),\r
+                                       outlen - sizeof(WV_IO_ID), inid + 1);\r
+       ib_status = cq->pVerbs->resize_cq(cq->hVerbsCq, &inid->Data, &verbsData);\r
+       WvCqRelease(cq);\r
+\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       len = outlen;\r
+       outid->Data = inid->Data;\r
+       outid->VerbInfo = verbsData.status;\r
+\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+void WvCqNotify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                                *id;\r
+       WV_COMPLETION_QUEUE             *cq;\r
+       NTSTATUS                                status;\r
+       WDFQUEUE                                queue;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       cq = WvCqAcquire(pProvider, id->Id);\r
+       if (cq == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto out;\r
+       }\r
+\r
+       queue = (id->Data == WV_CQ_ERROR) ? cq->ErrorQueue : cq->Queue;\r
+       WdfObjectAcquireLock(queue);\r
+       status = WdfRequestForwardToIoQueue(Request, queue);\r
+       WdfObjectReleaseLock(queue);\r
+       WvCqRelease(cq);\r
+\r
+out:\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
+}\r
+\r
+void WvCqCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                                  *id;\r
+       WV_COMPLETION_QUEUE             *cq;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       cq = WvCqAcquire(pProvider, *id);\r
+       if (cq == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto out;\r
+       }\r
+\r
+       WvCqCompleteRequests(cq->Queue, STATUS_CANCELLED);\r
+       WvCqCompleteRequests(cq->ErrorQueue, STATUS_CANCELLED);\r
+       WvCqRelease(cq);\r
+\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
diff --git a/core/winverbs/kernel/wv_cq.h b/core/winverbs/kernel/wv_cq.h
new file mode 100644 (file)
index 0000000..d0e20ae
--- /dev/null
@@ -0,0 +1,72 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_CQ_H_\r
+#define _WV_CQ_H_\r
+\r
+#include <ntddk.h>\r
+#include <wdm.h>\r
+#include <iba\ib_types.h>\r
+#include <iba\ib_ci.h>\r
+\r
+#include "wv_device.h"\r
+#include "wv_provider.h"\r
+\r
+typedef struct _WV_COMPLETION_QUEUE\r
+{\r
+       WV_DEVICE                       *pDevice;\r
+       ci_interface_t          *pVerbs;\r
+       ib_cq_handle_t          hVerbsCq;\r
+       LIST_ENTRY                      Entry;\r
+\r
+       KEVENT                          Event;\r
+       LONG                            Ref;\r
+       WDFQUEUE                        Queue;\r
+       WDFQUEUE                        ErrorQueue;\r
+\r
+}      WV_COMPLETION_QUEUE;\r
+\r
+\r
+void WvCqCreate(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvCqDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvCqFree(WV_COMPLETION_QUEUE *pCq);\r
+\r
+WV_COMPLETION_QUEUE *WvCqAcquire(WV_PROVIDER *pProvider, UINT64 Id);\r
+void WvCqRelease(WV_COMPLETION_QUEUE *pCq);\r
+void WvCqGet(WV_COMPLETION_QUEUE *pCq);\r
+void WvCqPut(WV_COMPLETION_QUEUE *pCq);\r
+\r
+void WvCqResize(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvCqNotify(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvCqBatchNotify(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvCqCancel(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+\r
+#endif //_WV_CQ_H_\r
diff --git a/core/winverbs/kernel/wv_device.c b/core/winverbs/kernel/wv_device.c
new file mode 100644 (file)
index 0000000..0620d85
--- /dev/null
@@ -0,0 +1,810 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include "wv_device.h"\r
+#include "wv_pd.h"\r
+#include "wv_cq.h"\r
+#include "wv_ioctl.h"\r
+\r
+void WvDeviceGet(WV_DEVICE *pDevice)\r
+{\r
+       InterlockedIncrement(&pDevice->Ref);\r
+}\r
+\r
+void WvDevicePut(WV_DEVICE *pDevice)\r
+{\r
+       if (InterlockedDecrement(&pDevice->Ref) == 0) {\r
+               KeSetEvent(&pDevice->Event, 0, FALSE);\r
+       }\r
+}\r
+\r
+WV_DEVICE *WvDeviceAcquire(WV_PROVIDER *pProvider, UINT64 Id)\r
+{\r
+       WV_DEVICE *dev;\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       dev = IndexListAt(&pProvider->DevIndex, (SIZE_T) Id);\r
+       if (dev != NULL && dev->hVerbsDevice != NULL) {\r
+               WvDeviceGet(dev);\r
+       } else {\r
+               dev = NULL;\r
+               WvProviderEnableRemove(pProvider);\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       return dev;\r
+}\r
+\r
+void WvDeviceRelease(WV_DEVICE *pDevice)\r
+{\r
+       WvProviderEnableRemove(pDevice->pProvider);\r
+       WvDevicePut(pDevice);\r
+}\r
+\r
+static UINT32 WvDeviceConvertEvent(ib_async_event_t event)\r
+{\r
+       switch (event) {\r
+       case IB_AE_LOCAL_FATAL:\r
+               return WV_IO_EVENT_ERROR;\r
+       case IB_AE_PORT_ACTIVE:\r
+       case IB_AE_PORT_DOWN:\r
+               return WV_IO_EVENT_STATE;\r
+       case IB_AE_CLIENT_REREGISTER:\r
+               return WV_IO_EVENT_MANAGEMENT;\r
+       // TODO: report LID / GID / SM / PKey changes\r
+       default:\r
+               return 0;\r
+       }\r
+}\r
+\r
+static void WvDeviceCompleteRequests(WV_PORT *pPort, NTSTATUS ReqStatus, UINT32 Event)\r
+{\r
+       WDFREQUEST      request;\r
+       NTSTATUS        status;\r
+       UINT32          *flags;\r
+\r
+       WdfObjectAcquireLock(pPort->Queue);\r
+       pPort->Flags |= Event;\r
+       Event = pPort->Flags;\r
+\r
+       status = WdfIoQueueRetrieveNextRequest(pPort->Queue, &request);\r
+       while (NT_SUCCESS(status)) {\r
+               pPort->Flags = 0;\r
+\r
+               status = WdfRequestRetrieveOutputBuffer(request, sizeof(UINT32), &flags, NULL);\r
+               if (NT_SUCCESS(status)) {\r
+                       *flags = Event;\r
+                       WdfRequestCompleteWithInformation(request, ReqStatus, sizeof(UINT32));\r
+               } else {\r
+                       WdfRequestComplete(request, status);\r
+               }\r
+               status = WdfIoQueueRetrieveNextRequest(pPort->Queue, &request);\r
+       }\r
+\r
+       WdfObjectReleaseLock(pPort->Queue);\r
+}\r
+\r
+static void WvDeviceEventHandler(ib_event_rec_t *pEvent)\r
+{\r
+       WV_DEVICE       *dev;\r
+       UINT32          event;\r
+       UINT8           i;\r
+\r
+       event = WvDeviceConvertEvent(pEvent->type);\r
+       if (event == 0) {\r
+               return;\r
+       }\r
+\r
+       dev = CONTAINING_RECORD(pEvent->context, WV_DEVICE, EventHandler);\r
+\r
+       if (event == WV_IO_EVENT_ERROR) {\r
+               for (i = 0; i < dev->PortCount; i++) {\r
+                       WvDeviceCompleteRequests(&dev->pPorts[i], STATUS_SUCCESS, event);\r
+               }\r
+       } else {\r
+               WvDeviceCompleteRequests(&dev->pPorts[pEvent->port_number - 1],\r
+                                                                STATUS_SUCCESS, event);\r
+       }\r
+}\r
+\r
+static WV_DEVICE *WvDeviceAlloc(WV_PROVIDER *pProvider)\r
+{\r
+       WV_DEVICE       *dev;\r
+\r
+       dev = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_DEVICE), 'cdvw');\r
+       if (dev == NULL) {\r
+               return NULL;\r
+       }\r
+\r
+       dev->pDevice = NULL;\r
+       dev->pVerbs = NULL;\r
+       dev->hVerbsDevice = NULL;\r
+       dev->pPorts = NULL;\r
+       dev->PortCount = 0;\r
+       dev->Ref = 1;\r
+       InitializeListHead(&dev->PdList);\r
+       InitializeListHead(&dev->CqList);\r
+       KeInitializeEvent(&dev->Event, NotificationEvent, FALSE);\r
+       dev->EventHandler.pfn_async_event_cb = WvDeviceEventHandler;\r
+\r
+       dev->pProvider = pProvider;\r
+       WvProviderGet(pProvider);\r
+       return dev;\r
+}\r
+\r
+static ib_ca_attr_t *WvQueryCaAttributes(WV_DEVICE *pDevice)\r
+{\r
+       ib_ca_attr_t    *attr;\r
+       UINT32                  size;\r
+       ib_api_status_t ib_status;\r
+\r
+       size = 0;\r
+       ib_status = pDevice->pVerbs->query_ca(pDevice->pDevice->hDevice, NULL,\r
+                                                                                 &size, NULL);\r
+       if (ib_status != IB_INSUFFICIENT_MEMORY) {\r
+               attr = NULL;\r
+               goto out;\r
+       }\r
+\r
+       attr = ExAllocatePoolWithTag(PagedPool, size, 'acvw');\r
+       if (attr == NULL) {\r
+               goto out;\r
+       }\r
+\r
+       ib_status = pDevice->pVerbs->query_ca(pDevice->pDevice->hDevice, attr,\r
+                                                                                 &size, NULL);\r
+       if (ib_status != IB_SUCCESS) {\r
+               ExFreePool(attr);\r
+               attr = NULL;\r
+       }\r
+\r
+out:\r
+       return attr;\r
+}\r
+\r
+static NTSTATUS WvDeviceCreatePorts(WV_DEVICE *pDevice)\r
+{\r
+       WDF_IO_QUEUE_CONFIG     config;\r
+       ib_ca_attr_t            *attr;\r
+       NTSTATUS                        status;\r
+       UINT8                           i;\r
+\r
+       attr = WvQueryCaAttributes(pDevice);\r
+       if (attr == NULL) {\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       pDevice->PortCount = attr->num_ports;\r
+       ExFreePool(attr);\r
+\r
+       pDevice->pPorts = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_PORT) *\r
+                                                                                       pDevice->PortCount, 'cpvw');\r
+       if (pDevice->pPorts == NULL) {\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);\r
+       for (i = 0; i < pDevice->PortCount; i++) {\r
+               pDevice->pPorts[i].Flags = 0;\r
+               status = WdfIoQueueCreate(ControlDevice, &config, WDF_NO_OBJECT_ATTRIBUTES,\r
+                                                                 &pDevice->pPorts[i].Queue);\r
+               if (!NT_SUCCESS(status)) {\r
+                       goto err;\r
+               }\r
+       }\r
+\r
+       return STATUS_SUCCESS;\r
+\r
+err:\r
+       while (i-- > 0) {\r
+               WdfObjectDelete(pDevice->pPorts[i].Queue);\r
+       }\r
+       pDevice->PortCount = 0;\r
+       return status;\r
+}\r
+\r
+static NTSTATUS WvDeviceInit(WV_DEVICE *pDevice, NET64 Guid,\r
+                                                        ci_umv_buf_t *pVerbsData)\r
+{\r
+       WV_RDMA_DEVICE *dev;\r
+       ib_api_status_t ib_status;\r
+       NTSTATUS                status;\r
+\r
+       dev = WvRdmaDeviceGet(Guid);\r
+       if (dev == NULL) {\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       pDevice->pDevice = dev;\r
+       pDevice->pVerbs = &dev->Interface.Verbs;\r
+\r
+       ib_status = pDevice->pVerbs->um_open_ca(dev->hDevice, pVerbsData,\r
+                                                                                       &pDevice->hVerbsDevice);\r
+       if (ib_status != IB_SUCCESS) {\r
+               goto err1;\r
+       }\r
+\r
+       status = WvDeviceCreatePorts(pDevice);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err2;\r
+       }\r
+\r
+       pDevice->pVerbs->register_event_handler(dev->hDevice, &pDevice->EventHandler);\r
+       return STATUS_SUCCESS;\r
+\r
+err2:\r
+       pDevice->pVerbs->um_close_ca(dev->hDevice, pDevice->hVerbsDevice);\r
+err1:\r
+       WvRdmaDevicePut(dev);\r
+       pDevice->hVerbsDevice = NULL;\r
+       return STATUS_UNSUCCESSFUL;\r
+}\r
+\r
+void WvDeviceOpen(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                *inid, *outid;\r
+       size_t                  inlen, outlen;\r
+       WV_DEVICE               *dev;\r
+       NTSTATUS                status;\r
+       ci_umv_buf_t    verbsData;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &inid, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_ID), &outid, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       dev = WvDeviceAlloc(pProvider);\r
+       if (dev == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err1;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       WvInitVerbsData(&verbsData, inid->VerbInfo, inlen - sizeof(WV_IO_ID),\r
+                                       outlen - sizeof(WV_IO_ID), inid + 1);\r
+       status = WvDeviceInit(dev, inid->Id, &verbsData);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err2;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       outid->Id = IndexListInsertHead(&pProvider->DevIndex, dev);\r
+       if (outid->Id == 0) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err2;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       WvProviderEnableRemove(pProvider);\r
+       outid->VerbInfo = verbsData.status;\r
+       WdfRequestCompleteWithInformation(Request, status, outlen);\r
+       return;\r
+\r
+err2:\r
+       WvDeviceFree(dev);\r
+       WvProviderEnableRemove(pProvider);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvDeviceClose(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_DEVICE       *dev;\r
+       UINT64          *id;\r
+       NTSTATUS        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       dev = IndexListAt(&pProvider->DevIndex, (SIZE_T) *id);\r
+       if (dev == NULL) {\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+       } else if (dev->Ref > 1) {\r
+               status = STATUS_ACCESS_DENIED;\r
+       } else {\r
+               IndexListRemove(&pProvider->DevIndex, (SIZE_T) *id);\r
+               status = STATUS_SUCCESS;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       if (NT_SUCCESS(status)) {\r
+               WvDeviceFree(dev);\r
+       }\r
+       WvProviderEnableRemove(pProvider);\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+static void WvDeviceFreePorts(WV_DEVICE *pDevice)\r
+{\r
+       UINT8 i;\r
+\r
+       for (i = 0; i < pDevice->PortCount; i++) {\r
+               WdfIoQueuePurgeSynchronously(pDevice->pPorts[i].Queue);\r
+               WdfObjectDelete(pDevice->pPorts[i].Queue);\r
+       }\r
+}\r
+\r
+void WvDeviceFree(WV_DEVICE *pDevice)\r
+{\r
+       if (InterlockedDecrement(&pDevice->Ref) > 0) {\r
+               KeWaitForSingleObject(&pDevice->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
+\r
+       if (pDevice->hVerbsDevice != NULL) {\r
+               pDevice->pVerbs->unregister_event_handler(pDevice->pDevice->hDevice,\r
+                                                                                                 &pDevice->EventHandler);\r
+               pDevice->pVerbs->um_close_ca(pDevice->pDevice->hDevice,\r
+                                                                        pDevice->hVerbsDevice);\r
+               WvRdmaDevicePut(pDevice->pDevice);\r
+       }\r
+\r
+       WvDeviceFreePorts(pDevice);\r
+       WvProviderPut(pDevice->pProvider);\r
+       ExFreePool(pDevice);\r
+}\r
+\r
+void WvDeviceRemoveHandler(WV_DEVICE *pDevice)\r
+{\r
+       LIST_ENTRY                              *entry;\r
+       WV_PROTECTION_DOMAIN    *pd;\r
+       WV_COMPLETION_QUEUE             *cq;\r
+\r
+       for (entry = pDevice->PdList.Flink; entry != &pDevice->PdList;\r
+                entry = entry->Flink) {\r
+               pd = CONTAINING_RECORD(entry, WV_PROTECTION_DOMAIN, Entry);\r
+               WvPdRemoveHandler(pd);\r
+       }\r
+\r
+       for (entry = pDevice->CqList.Flink; entry != &pDevice->CqList;\r
+                entry = entry->Flink) {\r
+               cq = CONTAINING_RECORD(entry, WV_COMPLETION_QUEUE, Entry);\r
+               pDevice->pVerbs->destroy_cq(cq->hVerbsCq);\r
+               cq->hVerbsCq = NULL;\r
+               cq->pVerbs = NULL;\r
+       }\r
+\r
+       pDevice->pVerbs->um_close_ca(pDevice->pDevice->hDevice,\r
+                                                                pDevice->hVerbsDevice);\r
+       WvRdmaDevicePut(pDevice->pDevice);\r
+       pDevice->pDevice = NULL;\r
+       pDevice->pVerbs = NULL;\r
+       pDevice->hVerbsDevice = NULL;\r
+}\r
+\r
+static void WvSetDeviceCap(UINT32 *pFlags, ib_ca_attr_t *pCaAttr)\r
+{\r
+       *pFlags = 0;\r
+\r
+       *pFlags |= pCaAttr->bad_pkey_ctr_support ? WV_IO_BAD_PKEY_COUNTER : 0;\r
+       *pFlags |= pCaAttr->bad_qkey_ctr_support ? WV_IO_BAD_QKEY_COUNTER : 0;\r
+       *pFlags |= pCaAttr->apm_support ? WV_IO_PATH_MIGRATION : 0;\r
+       *pFlags |= pCaAttr->av_port_check ? WV_IO_AH_PORT_CHECKING : 0;\r
+       *pFlags |= pCaAttr->change_primary_port ? WV_IO_CHANGE_PHYSICAL_PORT : 0;\r
+       *pFlags |= pCaAttr->modify_wr_depth ? WV_IO_RESIZE_MAX_WR : 0;\r
+       *pFlags |= pCaAttr->modify_srq_depth ? WV_IO_SRQ_RESIZE : 0;\r
+       *pFlags |= pCaAttr->current_qp_state_support ? WV_IO_QP_STATE_MODIFIER : 0;\r
+       *pFlags |= pCaAttr->shutdown_port_capability ? WV_IO_SHUTDOWN_PORT : 0;\r
+       *pFlags |= pCaAttr->init_type_support ? WV_IO_INIT_TYPE : 0;\r
+       *pFlags |= pCaAttr->port_active_event_support ? WV_IO_PORT_ACTIVE_EVENT : 0;\r
+       *pFlags |= pCaAttr->system_image_guid_support ? WV_IO_SYSTEM_IMAGE_GUID : 0;\r
+       *pFlags |= WV_IO_RC_RNR_NAK_GENERATION;\r
+       *pFlags |= WV_IO_BATCH_NOTIFY_CQ;\r
+}\r
+\r
+static void WvSetDevicePages(UINT32 *pFlags, ib_ca_attr_t *pCaAttr)\r
+{\r
+       unsigned int i;\r
+       UINT32 size;\r
+\r
+       *pFlags = 0;\r
+\r
+       for (i = 0; i < pCaAttr->num_page_sizes; i++) {\r
+               size = pCaAttr->p_page_size[i];\r
+               *pFlags |= (size & (size - 1)) ? 0 : size;\r
+       }\r
+}\r
+\r
+static void WvConvertDevAttr(WV_IO_DEVICE_ATTRIBUTES* pAttributes,\r
+                                                        ib_ca_attr_t *pCaAttr)\r
+{\r
+       pAttributes->FwVersion                  = pCaAttr->fw_ver;\r
+       pAttributes->NodeGuid                   = pCaAttr->ca_guid;\r
+       pAttributes->SystemImageGuid    = pCaAttr->system_image_guid;\r
+       pAttributes->VendorId                   = pCaAttr->vend_id;\r
+       pAttributes->VendorPartId               = pCaAttr->dev_id;\r
+       pAttributes->HwVersion                  = pCaAttr->revision;\r
+\r
+       WvSetDeviceCap(&pAttributes->CapabilityFlags, pCaAttr);\r
+       pAttributes->AtomicCapability   = (UINT32) pCaAttr->atomicity;\r
+       WvSetDevicePages(&pAttributes->PageSizeCapabilityFlags, pCaAttr);\r
+\r
+       pAttributes->MaxMrSize                  = pCaAttr->init_region_size;\r
+       pAttributes->MaxQp                              = pCaAttr->max_qps;\r
+       pAttributes->MaxQpWr                    = pCaAttr->max_wrs;\r
+       pAttributes->MaxSge                             = pCaAttr->max_sges;\r
+       pAttributes->MaxCq                              = pCaAttr->max_cqs;\r
+       pAttributes->MaxCqEntries               = pCaAttr->max_cqes;\r
+       pAttributes->MaxMr                              = pCaAttr->init_regions;\r
+       pAttributes->MaxPd                              = pCaAttr->max_pds;\r
+       pAttributes->MaxQpResponderResources    = pCaAttr->max_qp_resp_res;\r
+       pAttributes->MaxResponderResources              = pCaAttr->max_resp_res;\r
+       pAttributes->MaxQpInitiatorDepth                = pCaAttr->max_qp_init_depth;\r
+       pAttributes->MaxMw                              = pCaAttr->init_windows;\r
+       pAttributes->MaxMulticast               = pCaAttr->max_mcast_grps;\r
+       pAttributes->MaxQpAttach                = pCaAttr->max_qps_per_mcast_grp;\r
+       pAttributes->MaxMulticastQp             = pCaAttr->max_mcast_qps;\r
+       pAttributes->MaxAh                              = (UINT32) pCaAttr->max_addr_handles;\r
+       pAttributes->MaxFmr                             = pCaAttr->max_fmr;\r
+       pAttributes->MaxMapPerFmr               = pCaAttr->max_map_per_fmr;\r
+       pAttributes->MaxSrq                             = pCaAttr->max_srq;\r
+       pAttributes->MaxSrqWr                   = pCaAttr->max_srq_wrs;\r
+       pAttributes->MaxSrqSge                  = pCaAttr->max_srq_sges;\r
+       pAttributes->MaxPkeys                   = pCaAttr->max_partitions;\r
+       pAttributes->DeviceType                 = WV_DEVICE_INFINIBAND; // TODO: missing in ib_ca_attr_t\r
+       pAttributes->LocalAckDelay              = pCaAttr->local_ack_delay;\r
+       pAttributes->PhysPortCount              = pCaAttr->num_ports;\r
+}\r
+\r
+static void WvConvertPortCap(UINT32 *pFlags, ib_port_cap_t *pCap)\r
+{\r
+       *pFlags = 0;\r
+\r
+       *pFlags |= pCap->qkey_ctr ? WV_IO_BAD_QKEY_COUNTER : 0;\r
+       *pFlags |= pCap->pkey_ctr ? WV_IO_BAD_PKEY_COUNTER : 0;\r
+       *pFlags |= pCap->apm ? WV_IO_PATH_MIGRATION : 0;\r
+       *pFlags |= pCap->sysguid ? WV_IO_SYSTEM_IMAGE_GUID : 0;\r
+       *pFlags |= pCap->port_active ? WV_IO_PORT_ACTIVE_EVENT : 0;\r
+\r
+       // TODO: missing in ib_port_attr_t:\r
+       // WV_IO_RESIZE_MAX_WR\r
+       // WV_IO_CHANGE_PHYSICAL_PORT\r
+       // WV_IO_AH_PORT_CHECKING\r
+       *pFlags |= WV_IO_QP_STATE_MODIFIER;\r
+       // WV_IO_SHUTDOWN_PORT\r
+       // WV_IO_INIT_TYPE\r
+       *pFlags |= WV_IO_RC_RNR_NAK_GENERATION;\r
+       // WV_IO_SRQ_RESIZE\r
+       *pFlags |= WV_IO_BATCH_NOTIFY_CQ;\r
+}\r
+\r
+static void WvConvertPortAttr(WV_IO_PORT_ATTRIBUTES *pAttributes,\r
+                                                         ib_port_attr_t *pPortAttr)\r
+{\r
+       WvConvertPortCap(&pAttributes->PortCabilityFlags, &pPortAttr->cap);\r
+       pAttributes->State                      = pPortAttr->link_state;\r
+       pAttributes->MaxMtu                     = 0;    // TODO: missing in ib_port_attr_t\r
+       pAttributes->ActiveMtu          = 0x80 << pPortAttr->mtu;\r
+       pAttributes->GidTableLength     = pPortAttr->num_gids;\r
+       pAttributes->MaxMessageSize     = (UINT32) pPortAttr->max_msg_size;\r
+       pAttributes->BadPkeyCounter     = pPortAttr->pkey_ctr;\r
+       pAttributes->QkeyViolationCounter       = pPortAttr->qkey_ctr;\r
+       pAttributes->PkeyTableLength            = pPortAttr->num_pkeys;\r
+       pAttributes->Lid                        = pPortAttr->lid;\r
+       pAttributes->SmLid                      = pPortAttr->sm_lid;\r
+       pAttributes->Lmc                        = pPortAttr->lmc;\r
+       pAttributes->MaxVls                     = (UINT8) pPortAttr->max_vls;\r
+       pAttributes->SmSl                       = pPortAttr->sm_sl;\r
+       pAttributes->SubnetTimeout      = pPortAttr->subnet_timeout;\r
+       pAttributes->InitTypeReply      = pPortAttr->init_type_reply;\r
+       pAttributes->ActiveWidth        = pPortAttr->link_width_supported;\r
+       pAttributes->ActiveSpeed        = 0;    // TODO: missing in ib_port_attr_t\r
+       pAttributes->PhysicalState      = 0;    // TODO: missing in ib_port_attr_t\r
+       pAttributes->Reserved[0]        = 0;\r
+       pAttributes->Reserved[1]        = 0;\r
+}\r
+\r
+void WvDeviceQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                                  *id;\r
+       WV_IO_DEVICE_ATTRIBUTES *attr;\r
+       WV_DEVICE                               *dev;\r
+       ib_ca_attr_t                    *ca_attr;\r
+       NTSTATUS                                status;\r
+       UINT32                                  outlen = 0;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_DEVICE_ATTRIBUTES),\r
+                                                                                       &attr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       dev = WvDeviceAcquire(pProvider, *id);\r
+       if (dev == NULL) {\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+               goto complete;\r
+       }\r
+\r
+       ca_attr = WvQueryCaAttributes(dev);\r
+       WvDeviceRelease(dev);\r
+\r
+       if (ca_attr == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto complete;\r
+       }\r
+\r
+       WvConvertDevAttr(attr, ca_attr);\r
+       outlen = sizeof(WV_IO_DEVICE_ATTRIBUTES);\r
+       ExFreePool(ca_attr);\r
+\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, outlen);\r
+}\r
+\r
+void WvDevicePortQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_DEVICE_PORT_QUERY *query;\r
+       WV_IO_PORT_ATTRIBUTES   *attr;\r
+       WV_DEVICE                               *dev;\r
+       ib_ca_attr_t                    *ca_attr;\r
+       NTSTATUS                                status;\r
+       UINT32                                  outlen = 0;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_DEVICE_PORT_QUERY),\r
+                                                                                  &query, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_PORT_ATTRIBUTES),\r
+                                                                                       &attr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       dev = WvDeviceAcquire(pProvider, query->Id);\r
+       if (dev == NULL) {\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+               goto complete;\r
+       }\r
+\r
+       ca_attr = WvQueryCaAttributes(dev);\r
+       WvDeviceRelease(dev);\r
+\r
+       if (ca_attr == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto complete;\r
+       }\r
+\r
+       if (--query->PortNumber >= ca_attr->num_ports) {\r
+               status = STATUS_INVALID_PORT_HANDLE;\r
+               goto free;\r
+       }\r
+\r
+       WvConvertPortAttr(attr, &ca_attr->p_port_attr[query->PortNumber]);\r
+       outlen = sizeof(WV_IO_PORT_ATTRIBUTES);\r
+\r
+free:\r
+       ExFreePool(ca_attr);\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, outlen);\r
+}\r
+\r
+void WvDeviceGidQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_DEVICE_PORT_QUERY *query;\r
+       WV_IO_GID                               *gid;\r
+       WV_DEVICE                               *dev;\r
+       ib_ca_attr_t                    *ca_attr;\r
+       ib_port_attr_t                  *port_attr;\r
+       NTSTATUS                                status;\r
+       size_t                                  i, size, outlen = 0;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_DEVICE_PORT_QUERY),\r
+                                                                                  &query, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_GID), &gid, &size);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       dev = WvDeviceAcquire(pProvider, query->Id);\r
+       if (dev == NULL) {\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+               goto complete;\r
+       }\r
+\r
+       ca_attr = WvQueryCaAttributes(dev);\r
+       WvDeviceRelease(dev);\r
+\r
+       if (ca_attr == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto complete;\r
+       }\r
+\r
+       if (--query->PortNumber >= ca_attr->num_ports) {\r
+               status = STATUS_INVALID_PORT_HANDLE;\r
+               goto free;\r
+       }\r
+\r
+       size /= sizeof(WV_IO_GID);\r
+       port_attr = &ca_attr->p_port_attr[query->PortNumber];\r
+       for (i = 0; i < size && i < port_attr->num_gids; i++) {\r
+               RtlCopyMemory(&gid[i], &port_attr->p_gid_table[i], sizeof(WV_IO_GID));\r
+       }\r
+\r
+       outlen = i * sizeof(WV_IO_GID);\r
+       if (i < port_attr->num_gids) {\r
+               status = STATUS_MORE_ENTRIES;\r
+       }\r
+\r
+free:\r
+       ExFreePool(ca_attr);\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, outlen);\r
+}\r
+\r
+void WvDevicePkeyQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_DEVICE_PORT_QUERY *query;\r
+       NET16                                   *pkey;\r
+       WV_DEVICE                               *dev;\r
+       ib_ca_attr_t                    *ca_attr;\r
+       ib_port_attr_t                  *port_attr;\r
+       NTSTATUS                                status;\r
+       size_t                                  i, size, outlen = 0;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_DEVICE_PORT_QUERY),\r
+                                                                                  &query, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(NET16), &pkey, &size);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       dev = WvDeviceAcquire(pProvider, query->Id);\r
+       if (dev == NULL) {\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+               goto complete;\r
+       }\r
+\r
+       ca_attr = WvQueryCaAttributes(dev);\r
+       WvDeviceRelease(dev);\r
+\r
+       if (ca_attr == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto complete;\r
+       }\r
+\r
+       if (--query->PortNumber >= ca_attr->num_ports) {\r
+               status = STATUS_INVALID_PORT_HANDLE;\r
+               goto free;\r
+       }\r
+\r
+       size /= sizeof(NET16);\r
+       port_attr = &ca_attr->p_port_attr[query->PortNumber];\r
+       for (i = 0; i < size && i < port_attr->num_pkeys; i++) {\r
+               pkey[i] = port_attr->p_pkey_table[i];\r
+       }\r
+\r
+       outlen = i * sizeof(NET16);\r
+       if (i < port_attr->num_pkeys) {\r
+               status = STATUS_MORE_ENTRIES;\r
+       }\r
+\r
+free:\r
+       ExFreePool(ca_attr);\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, outlen);\r
+}\r
+\r
+void WvDeviceNotify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                *id;\r
+       WV_DEVICE               *dev;\r
+       WV_PORT                 *port;\r
+       NTSTATUS                status;\r
+       UINT32                  *flags;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT32), &flags, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       dev = WvDeviceAcquire(pProvider, id->Id);\r
+       if (dev == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       if (--id->Data >= dev->PortCount) {\r
+               status = STATUS_INVALID_PORT_HANDLE;\r
+               goto release;\r
+       }\r
+\r
+       port = &dev->pPorts[id->Data];\r
+       WdfObjectAcquireLock(port->Queue);\r
+\r
+       if (port->Flags == 0) {\r
+               status = WdfRequestForwardToIoQueue(Request, port->Queue);\r
+       } else {\r
+               *flags = port->Flags;\r
+               WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, sizeof(UINT32));\r
+               port->Flags = 0;\r
+       }\r
+\r
+       WdfObjectReleaseLock(port->Queue);\r
+release:\r
+       WvDeviceRelease(dev);\r
+complete:\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
+}\r
+\r
+void WvDeviceCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                  *id;\r
+       WV_DEVICE               *dev;\r
+       NTSTATUS                status;\r
+       UINT8                   i;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       dev = WvDeviceAcquire(pProvider, *id);\r
+       if (dev == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto out;\r
+       }\r
+\r
+       for (i = 0; i < dev->PortCount; i++) {\r
+               WvDeviceCompleteRequests(&dev->pPorts[i], STATUS_CANCELLED, 0);\r
+       }\r
+       WvDeviceRelease(dev);\r
+\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
diff --git a/core/winverbs/kernel/wv_device.h b/core/winverbs/kernel/wv_device.h
new file mode 100644 (file)
index 0000000..1bbc5fe
--- /dev/null
@@ -0,0 +1,87 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_DEVICE_H_\r
+#define _WV_DEVICE_H_\r
+\r
+#include <ntddk.h>\r
+#include <wdm.h>\r
+#include <iba\ib_types.h>\r
+#include <iba\ib_ci.h>\r
+\r
+#include "wv_driver.h"\r
+#include "wv_provider.h"\r
+\r
+typedef struct _WV_PORT\r
+{\r
+       WDFQUEUE                        Queue;\r
+       UINT32                          Flags;\r
+\r
+}      WV_PORT;\r
+\r
+typedef struct _WV_DEVICE\r
+{\r
+       WV_PROVIDER                     *pProvider;\r
+       WV_RDMA_DEVICE          *pDevice;\r
+       ci_interface_t          *pVerbs;\r
+       LIST_ENTRY                      Entry;\r
+       ib_ca_handle_t          hVerbsDevice;\r
+       ci_event_handler_t      EventHandler;\r
+\r
+       LIST_ENTRY                      PdList;\r
+       LIST_ENTRY                      CqList;\r
+\r
+       KEVENT                          Event;\r
+       LONG                            Ref;\r
+       WV_PORT                         *pPorts;\r
+       UINT8                           PortCount;\r
+\r
+}      WV_DEVICE;\r
+\r
+struct _WV_DEVICE *WvDeviceAcquire(WV_PROVIDER *pProvider, UINT64 Id);\r
+void WvDeviceRelease(WV_DEVICE *pDevice);\r
+void WvDeviceGet(WV_DEVICE *pDevice);\r
+void WvDevicePut(WV_DEVICE *pDevice);\r
+\r
+void WvDeviceOpen(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvDeviceClose(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvDeviceFree(WV_DEVICE *pDevice);\r
+void WvDeviceRemoveHandler(WV_DEVICE *pDevice);\r
+\r
+void WvDeviceQuery(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvDevicePortQuery(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvDeviceGidQuery(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvDevicePkeyQuery(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+\r
+void WvDeviceNotify(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvDeviceCancel(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+\r
+#endif // __WV_DEVICE_H_\r
diff --git a/core/winverbs/kernel/wv_driver.c b/core/winverbs/kernel/wv_driver.c
new file mode 100644 (file)
index 0000000..fb457f2
--- /dev/null
@@ -0,0 +1,564 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include <ntddk.h>\r
+#include <wdf.h>\r
+#include <wdmsec.h>\r
+#include <ntstatus.h>\r
+#include <initguid.h>\r
+\r
+#include "index_list.c"\r
+#include <rdma/verbs.h>\r
+#include "wv_driver.h"\r
+#include "wv_ioctl.h"\r
+#include "wv_provider.h"\r
+#include "wv_device.h"\r
+#include "wv_pd.h"\r
+#include "wv_srq.h"\r
+#include "wv_cq.h"\r
+#include "wv_srq.h"\r
+#include "wv_qp.h"\r
+#include "wv_listen.h"\r
+#include "wv_ep.h"\r
+\r
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WV_RDMA_DEVICE, WvRdmaDeviceGetContext)\r
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WV_PROVIDER, WvProviderGetContext)\r
+\r
+WDFDEVICE                              ControlDevice;\r
+static LIST_ENTRY              DevList;\r
+static LIST_ENTRY              ProvList;\r
+static KGUARDED_MUTEX  Lock;\r
+\r
+static EVT_WDF_DRIVER_DEVICE_ADD                       WvRdmaDeviceAdd;\r
+static EVT_WDF_OBJECT_CONTEXT_CLEANUP          WvRdmaDeviceCleanup;\r
+static EVT_WDF_DEVICE_D0_ENTRY                         WvPowerD0Entry;\r
+static EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL      WvIoDeviceControl;\r
+static EVT_WDF_DEVICE_FILE_CREATE                      WvFileCreate;\r
+static EVT_WDF_FILE_CLEANUP                                    WvFileCleanup;\r
+static EVT_WDF_FILE_CLOSE                                      WvFileClose;\r
+\r
+WV_RDMA_DEVICE *WvRdmaDeviceGet(NET64 Guid)\r
+{\r
+       WV_RDMA_DEVICE  *cur_dev, *dev = NULL;\r
+       LIST_ENTRY              *entry;\r
+\r
+       KeAcquireGuardedMutex(&Lock);\r
+       for (entry = DevList.Flink; entry != &DevList; entry = entry->Flink) {\r
+               cur_dev = CONTAINING_RECORD(entry, WV_RDMA_DEVICE, Entry);\r
+               if (cur_dev->Interface.Verbs.guid == Guid) {\r
+                       InterlockedIncrement(&cur_dev->Ref);\r
+                       dev = cur_dev;\r
+                       break;\r
+               }\r
+       }\r
+       KeReleaseGuardedMutex(&Lock);\r
+       return dev;\r
+}\r
+\r
+void WvRdmaDevicePut(WV_RDMA_DEVICE *pDevice)\r
+{\r
+       if (InterlockedDecrement(&pDevice->Ref) == 0) {\r
+               KeSetEvent(&pDevice->Event, 0, FALSE);\r
+       }\r
+}\r
+\r
+static void WvGuidQuery(WDFREQUEST Request)\r
+{\r
+       WV_IO_GUID_LIST *list;\r
+       size_t                  len = 0;\r
+       WV_RDMA_DEVICE  *dev;\r
+       ULONG                   count, i;\r
+       LIST_ENTRY              *entry;\r
+       NTSTATUS                status;\r
+\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_GUID_LIST),\r
+                                                                                       &list, &len);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       count = (ULONG) ((len - sizeof(NET64)) / sizeof(NET64));\r
+       i = 0;\r
+       len = sizeof(NET64);\r
+       KeAcquireGuardedMutex(&Lock);\r
+       for (entry = DevList.Flink; entry != &DevList; entry = entry->Flink) {\r
+               dev = CONTAINING_RECORD(entry, WV_RDMA_DEVICE, Entry);\r
+               if (i < count) {\r
+                       list->Guid[i] = dev->Interface.Verbs.guid;\r
+                       len += sizeof(NET64);\r
+               }\r
+               i++;\r
+       }\r
+       list->Count = i;\r
+       KeReleaseGuardedMutex(&Lock);\r
+\r
+out:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+static void WvLibraryQuery(WDFREQUEST Request)\r
+{\r
+       NET64                   *guid;\r
+       char                    *name;\r
+       size_t                  len = 0, bytes;\r
+       WV_RDMA_DEVICE  *dev;\r
+       NTSTATUS                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(NET64), &guid, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, 1, &name, &bytes);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       dev = WvRdmaDeviceGet(*guid);\r
+       if (dev == NULL) {\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+               goto out;\r
+       }\r
+\r
+       len = strlen(dev->Interface.Verbs.libname) + 1;\r
+       if (bytes >= len) {\r
+               RtlCopyMemory(name, dev->Interface.Verbs.libname, len);\r
+       } else {\r
+               status = STATUS_BUFFER_TOO_SMALL;\r
+               *name = (char) len;\r
+               len = 1;\r
+       }\r
+       WvRdmaDevicePut(dev);\r
+\r
+out:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+static VOID WvIoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request,\r
+                                                         size_t OutLen, size_t InLen, ULONG IoControlCode)\r
+{\r
+       WDFFILEOBJECT   file;\r
+       WV_PROVIDER             *prov;\r
+       UNREFERENCED_PARAMETER(OutLen);\r
+       UNREFERENCED_PARAMETER(InLen);\r
+       UNREFERENCED_PARAMETER(Queue);\r
+\r
+       file = WdfRequestGetFileObject(Request);\r
+       prov = WvProviderGetContext(file);\r
+\r
+       // TODO: verify this compiles as a jump table, or use function pointers\r
+       switch (IoControlCode) {\r
+       case WV_IOCTL_GUID_QUERY:\r
+               WvGuidQuery(Request);\r
+               break;\r
+       case WV_IOCTL_LIBRARY_QUERY:\r
+               WvLibraryQuery(Request);\r
+               break;\r
+       case WV_IOCTL_DEVICE_OPEN:\r
+               WvDeviceOpen(prov, Request);\r
+               break;\r
+       case WV_IOCTL_DEVICE_CLOSE:\r
+               WvDeviceClose(prov, Request);\r
+               break;\r
+       case WV_IOCTL_DEVICE_QUERY:\r
+               WvDeviceQuery(prov, Request);\r
+               break;\r
+       case WV_IOCTL_DEVICE_PORT_QUERY:\r
+               WvDevicePortQuery(prov, Request);\r
+               break;\r
+       case WV_IOCTL_DEVICE_GID_QUERY:\r
+               WvDeviceGidQuery(prov, Request);\r
+               break;\r
+       case WV_IOCTL_DEVICE_PKEY_QUERY:\r
+               WvDevicePkeyQuery(prov, Request);\r
+               break;\r
+       case WV_IOCTL_DEVICE_NOTIFY:\r
+               WvDeviceNotify(prov, Request);\r
+               break;\r
+       case WV_IOCTL_DEVICE_CANCEL:\r
+               WvDeviceCancel(prov, Request);\r
+               break;\r
+       case WV_IOCTL_PD_ALLOCATE:\r
+               WvPdAllocate(prov, Request);\r
+               break;\r
+       case WV_IOCTL_PD_DEALLOCATE:\r
+               WvPdDeallocate(prov, Request);\r
+               break;\r
+       case WV_IOCTL_MEMORY_REGISTER:\r
+               WvMrRegister(prov, Request);\r
+               break;\r
+       case WV_IOCTL_MEMORY_DEREGISTER:\r
+               WvMrDeregister(prov, Request);\r
+               break;\r
+       case WV_IOCTL_MW_ALLOCATE:\r
+               WvMwAllocate(prov, Request);\r
+               break;\r
+       case WV_IOCTL_MW_DEALLOCATE:\r
+               WvMwDeallocate(prov, Request);\r
+               break;\r
+       case WV_IOCTL_AH_CREATE:\r
+               WvAhCreate(prov, Request);\r
+               break;\r
+       case WV_IOCTL_AH_DESTROY:\r
+               WvAhDestroy(prov, Request);\r
+               break;\r
+       case WV_IOCTL_CQ_CREATE:\r
+               WvCqCreate(prov, Request);\r
+               break;\r
+       case WV_IOCTL_CQ_DESTROY:\r
+               WvCqDestroy(prov, Request);\r
+               break;\r
+       case WV_IOCTL_CQ_RESIZE:\r
+               WvCqResize(prov, Request);\r
+               break;\r
+       case WV_IOCTL_CQ_NOTIFY:\r
+               WvCqNotify(prov, Request);\r
+               break;\r
+       case WV_IOCTL_CQ_CANCEL:\r
+               WvCqCancel(prov, Request);\r
+               break;\r
+       case WV_IOCTL_SRQ_CREATE:\r
+               WvSrqCreate(prov, Request);\r
+               break;\r
+       case WV_IOCTL_SRQ_DESTROY:\r
+               WvSrqDestroy(prov, Request);\r
+               break;\r
+       case WV_IOCTL_SRQ_QUERY:\r
+               WvSrqQuery(prov, Request);\r
+               break;\r
+       case WV_IOCTL_SRQ_MODIFY:\r
+               WvSrqModify(prov, Request);\r
+               break;\r
+       case WV_IOCTL_SRQ_NOTIFY:\r
+               WvSrqNotify(prov, Request);\r
+               break;\r
+       case WV_IOCTL_SRQ_CANCEL:\r
+               WvSrqCancel(prov, Request);\r
+               break;\r
+       case WV_IOCTL_QP_CREATE:\r
+               WvQpCreate(prov, Request);\r
+               break;\r
+       case WV_IOCTL_QP_DESTROY:\r
+               WvQpDestroy(prov, Request);\r
+               break;\r
+       case WV_IOCTL_QP_QUERY:\r
+               WvQpQuery(prov, Request);\r
+               break;\r
+       case WV_IOCTL_QP_MODIFY:\r
+               WvQpModify(prov, Request);\r
+               break;\r
+       case WV_IOCTL_QP_ATTACH:\r
+               WvQpAttach(prov, Request);\r
+               break;\r
+       case WV_IOCTL_QP_DETACH:\r
+               WvQpDetach(prov, Request);\r
+               break;\r
+       case WV_IOCTL_QP_CANCEL:\r
+               WvQpCancel(prov, Request);\r
+               break;\r
+       case WV_IOCTL_ADDRESS_QUERY:\r
+               //WvAddressQuery(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_CREATE:\r
+               //WvEpCreate(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_DESTROY:\r
+               //WvEpDestroy(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_BIND:\r
+               //WvEpBind(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_REJECT:\r
+               //WvEpReject(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_CONNECT:\r
+               //WvEpConnect(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_ACCEPT:\r
+               //WvEpAccept(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_DISCONNECT:\r
+               //WvEpDisconnect(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_DISCONNECT_NOTIFY:\r
+               //WvEpDisconnectNotify(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_QUERY:\r
+               //WvEpQuery(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_LOOKUP:\r
+               //WvEpLookup(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_MULTICAST_JOIN:\r
+               //WvEpMulticastJoin(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_MULTICAST_LEAVE:\r
+               //WvEpMulticastLeave(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_EP_CANCEL:\r
+               //WvEpCancel(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_LISTEN:\r
+               //WvListen(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_LISTEN_DESTROY:\r
+               //WvListenDestroy(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_LISTEN_GET_REQUEST:\r
+               //WvListenGetRequest(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       case WV_IOCTL_LISTEN_CANCEL:\r
+               //WvListenCancel(prov, Request);\r
+               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               break;\r
+       default:\r
+               WdfRequestComplete(Request, STATUS_PROCEDURE_NOT_FOUND);\r
+               break;\r
+       }\r
+}\r
+\r
+static VOID WvFileCreate(WDFDEVICE Device, WDFREQUEST Request,\r
+                                                WDFFILEOBJECT FileObject)\r
+{\r
+       WV_PROVIDER     *prov = WvProviderGetContext(FileObject);\r
+       UNREFERENCED_PARAMETER(Device);\r
+\r
+       WvProviderInit(prov);\r
+       KeAcquireGuardedMutex(&Lock);\r
+       InsertHeadList(&ProvList, &prov->Entry);\r
+       KeReleaseGuardedMutex(&Lock);\r
+       WdfRequestComplete(Request, STATUS_SUCCESS);\r
+}\r
+\r
+static VOID WvFileCleanup(WDFFILEOBJECT FileObject)\r
+{\r
+       WV_PROVIDER *prov = WvProviderGetContext(FileObject);\r
+\r
+       KeAcquireGuardedMutex(&Lock);\r
+       RemoveEntryList(&prov->Entry);\r
+       KeReleaseGuardedMutex(&Lock);\r
+       WvProviderCleanup(prov);\r
+}\r
+\r
+static VOID WvFileClose(WDFFILEOBJECT FileObject)\r
+{\r
+       UNREFERENCED_PARAMETER(FileObject);\r
+}\r
+\r
+static VOID WvCreateControlDevice(WDFDRIVER Driver)\r
+{\r
+       PWDFDEVICE_INIT                 pinit;\r
+       WDF_FILEOBJECT_CONFIG   fileconfig;\r
+       WDF_OBJECT_ATTRIBUTES   attr;\r
+       WDF_IO_QUEUE_CONFIG             ioconfig;\r
+       NTSTATUS                                status;\r
+       WDFQUEUE                                queue;\r
+       DECLARE_CONST_UNICODE_STRING(name, L"\\Device\\WinVerbs");\r
+       DECLARE_CONST_UNICODE_STRING(symlink, L"\\DosDevices\\WinVerbs");\r
+\r
+       pinit = WdfControlDeviceInitAllocate(Driver,\r
+                                                                                &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R);\r
+       if (pinit == NULL) {\r
+                       return;\r
+       }\r
+\r
+       WdfDeviceInitSetExclusive(pinit, FALSE);\r
+       status = WdfDeviceInitAssignName(pinit, &name);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       WDF_FILEOBJECT_CONFIG_INIT(&fileconfig, WvFileCreate, WvFileClose,\r
+                                                          WvFileCleanup);\r
+       WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, WV_PROVIDER);\r
+       WdfDeviceInitSetFileObjectConfig(pinit, &fileconfig, &attr);\r
+\r
+       WDF_OBJECT_ATTRIBUTES_INIT(&attr);\r
+       status = WdfDeviceCreate(&pinit, &attr, &ControlDevice);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       status = WdfDeviceCreateSymbolicLink(ControlDevice, &symlink);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err2;\r
+       }\r
+\r
+       WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioconfig, WdfIoQueueDispatchParallel);\r
+       ioconfig.EvtIoDeviceControl = WvIoDeviceControl;\r
+       status = WdfIoQueueCreate(ControlDevice, &ioconfig,\r
+                                                         WDF_NO_OBJECT_ATTRIBUTES, &queue);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err2;\r
+       }\r
+\r
+       WdfControlFinishInitializing(ControlDevice);\r
+       return;\r
+\r
+err2:\r
+       WdfObjectDelete(ControlDevice);\r
+       return;\r
+err1:\r
+       WdfDeviceInitFree(pinit);\r
+}\r
+\r
+static NTSTATUS WvPowerD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)\r
+{\r
+       WV_RDMA_DEVICE  *dev;\r
+       BOOLEAN                 create;\r
+       NTSTATUS                status;\r
+\r
+       dev = WvRdmaDeviceGetContext(Device);\r
+       if (dev->hDevice != NULL) {\r
+               return STATUS_SUCCESS;\r
+       }\r
+\r
+       status = WdfFdoQueryForInterface(Device, &GUID_RDMA_INTERFACE_VERBS,\r
+                                                                        (PINTERFACE) &dev->Interface,\r
+                                                                        sizeof(dev->Interface), VerbsVersion(2, 0),\r
+                                                                        NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+       dev->hDevice = dev->Interface.Verbs.p_hca_dev;\r
+\r
+       KeAcquireGuardedMutex(&Lock);\r
+       create = IsListEmpty(&DevList);\r
+       InsertHeadList(&DevList, &dev->Entry);\r
+       KeReleaseGuardedMutex(&Lock);\r
+\r
+       if (create) {\r
+               WvCreateControlDevice(WdfGetDriver());\r
+       }\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+static NTSTATUS WvRdmaDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)\r
+{\r
+       WDF_OBJECT_ATTRIBUTES                   attr;\r
+       WDF_PNPPOWER_EVENT_CALLBACKS    power;\r
+       WDFDEVICE                                               dev;\r
+       WV_RDMA_DEVICE                                  *pdev;\r
+       NTSTATUS                                                status;\r
+\r
+       WdfFdoInitSetFilter(DeviceInit);\r
+\r
+       WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, WV_RDMA_DEVICE);\r
+       attr.EvtCleanupCallback = WvRdmaDeviceCleanup;\r
+\r
+       WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&power);\r
+       power.EvtDeviceD0Entry = WvPowerD0Entry;\r
+       WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &power);\r
+\r
+       status = WdfDeviceCreate(&DeviceInit, &attr, &dev);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+\r
+       pdev = WvRdmaDeviceGetContext(dev);\r
+       RtlZeroMemory(pdev, sizeof *pdev);\r
+       pdev->Ref = 1;\r
+       KeInitializeEvent(&pdev->Event, NotificationEvent, FALSE);\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+static VOID WvRdmaDeviceCleanup(WDFDEVICE Device)\r
+{\r
+       WV_RDMA_DEVICE                  *pdev;\r
+       WV_PROVIDER                             *prov;\r
+       LIST_ENTRY                              *entry;\r
+       BOOLEAN                                 destroy;\r
+       WDFDEVICE                               ctrldev;\r
+\r
+       pdev = WvRdmaDeviceGetContext(Device);\r
+       if (pdev->hDevice == NULL) {\r
+               return;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&Lock);\r
+       RemoveEntryList(&pdev->Entry);\r
+       destroy = IsListEmpty(&DevList);\r
+       ctrldev = ControlDevice;\r
+\r
+       for (entry = ProvList.Flink; entry != &ProvList; entry = entry->Flink) {\r
+               prov = CONTAINING_RECORD(entry, WV_PROVIDER, Entry);\r
+               WvProviderRemoveHandler(prov, pdev);\r
+       }\r
+\r
+       KeReleaseGuardedMutex(&Lock);\r
+\r
+       if (InterlockedDecrement(&pdev->Ref) > 0) {\r
+               KeWaitForSingleObject(&pdev->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
+\r
+       pdev->Interface.InterfaceHeader.\r
+               InterfaceDereference(pdev->Interface.InterfaceHeader.Context);\r
+\r
+       if (destroy) {\r
+               WdfObjectDelete(ctrldev);\r
+       }\r
+}\r
+\r
+NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)\r
+{\r
+       WDF_DRIVER_CONFIG               config;\r
+       NTSTATUS                                status;\r
+       WDFDRIVER                               driv;\r
+\r
+       InitializeListHead(&DevList);\r
+       InitializeListHead(&ProvList);\r
+       KeInitializeGuardedMutex(&Lock);\r
+\r
+       WDF_DRIVER_CONFIG_INIT(&config, WvRdmaDeviceAdd);\r
+       status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,\r
+                                                        &config, &driv);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
diff --git a/core/winverbs/kernel/wv_driver.h b/core/winverbs/kernel/wv_driver.h
new file mode 100644 (file)
index 0000000..494334b
--- /dev/null
@@ -0,0 +1,70 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_DRIVER_H_\r
+#define _WV_DRIVER_H_\r
+\r
+#include <ntddk.h>\r
+#include <wdm.h>\r
+#include <wdf.h>\r
+\r
+#include <iba\ib_types.h>\r
+#include <iba\ib_ci.h>\r
+#include <rdma\verbs.h>\r
+#include "wv_ioctl.h"\r
+\r
+extern WDFDEVICE                       ControlDevice;\r
+\r
+typedef struct _WV_RDMA_DEVICE\r
+{\r
+       LIST_ENTRY                              Entry;\r
+       LONG                                    Ref;\r
+       KEVENT                                  Event;\r
+       ib_ca_handle_t                  hDevice;\r
+       RDMA_INTERFACE_VERBS    Interface;\r
+\r
+}      WV_RDMA_DEVICE;\r
+\r
+WV_RDMA_DEVICE *WvRdmaDeviceGet(NET64 Guid);\r
+void WvRdmaDevicePut(WV_RDMA_DEVICE *pDevice);\r
+\r
+static inline void WvInitVerbsData(ci_umv_buf_t *pVerbsData, UINT32 Command,\r
+                                                                  SIZE_T InputLength, SIZE_T OutputLength,\r
+                                                                  void *pBuffer)\r
+{\r
+       pVerbsData->command = Command;\r
+       pVerbsData->input_size = (UINT32) InputLength;\r
+       pVerbsData->output_size = (UINT32) OutputLength;\r
+       pVerbsData->p_inout_buf = (ULONG_PTR) pBuffer;\r
+       pVerbsData->status = 0;\r
+}\r
+\r
+#endif // _WV_DRIVER_H_\r
diff --git a/core/winverbs/kernel/wv_ep.h b/core/winverbs/kernel/wv_ep.h
new file mode 100644 (file)
index 0000000..faaad5e
--- /dev/null
@@ -0,0 +1,56 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_EP_H_\r
+#define _WV_EP_H_\r
+\r
+#include <wdm.h>\r
+#include <iba\ib_types.h>\r
+#include <iba\ib_ci.h>\r
+#include "wv_provider.h"\r
+\r
+typedef struct _WV_CONNECT_ENDPOINT\r
+{\r
+       WV_PROVIDER             *pProvider;\r
+       UINT64                  Id;\r
+       LONG                    nRef;\r
+\r
+}      WV_CONNECT_ENDPOINT;\r
+\r
+typedef struct _WV_DATAGRAM_ENDPOINT\r
+{\r
+       WV_PROVIDER             *pProvider;\r
+       UINT64                  Id;\r
+       LONG                    m_nRef;\r
+\r
+}      WV_DATAGRAM_ENDPOINT;\r
+\r
+#endif // _WV_EP_H_\r
diff --git a/core/winverbs/kernel/wv_listen.h b/core/winverbs/kernel/wv_listen.h
new file mode 100644 (file)
index 0000000..8e94fb1
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_LISTEN_H_\r
+#define _WV_LISTEN_H_\r
+\r
+#include <wdm.h>\r
+#include <iba\ib_types.h>\r
+#include <iba\ib_ci.h>\r
+#include "wv_provider.h"\r
+\r
+typedef struct _WV_LISTEN\r
+{\r
+       WV_PROVIDER             *pProvider;\r
+       UINT64                  Id;\r
+       LONG                    nRef;\r
+\r
+}      WV_LISTEN;\r
+\r
+#endif // _WV_LISTEN_H_\r
diff --git a/core/winverbs/kernel/wv_pd.c b/core/winverbs/kernel/wv_pd.c
new file mode 100644 (file)
index 0000000..d74402e
--- /dev/null
@@ -0,0 +1,605 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include "wv_pd.h"\r
+#include "wv_srq.h"\r
+#include "wv_qp.h"\r
+#include "wv_ioctl.h"\r
+\r
+void WvPdGet(WV_PROTECTION_DOMAIN *pPd)\r
+{\r
+       InterlockedIncrement(&pPd->Ref);\r
+}\r
+\r
+void WvPdPut(WV_PROTECTION_DOMAIN *pPd)\r
+{\r
+       if (InterlockedDecrement(&pPd->Ref) == 0) {\r
+               KeSetEvent(&pPd->Event, 0, FALSE);\r
+       }\r
+}\r
+\r
+WV_PROTECTION_DOMAIN *WvPdAcquire(WV_PROVIDER *pProvider, UINT64 Id)\r
+{\r
+       WV_PROTECTION_DOMAIN *pd;\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       pd = IndexListAt(&pProvider->PdIndex, (SIZE_T) Id);\r
+       if (pd != NULL && pd->hVerbsPd != NULL) {\r
+               WvPdGet(pd);\r
+       } else {\r
+               pd = NULL;\r
+               WvProviderEnableRemove(pProvider);\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       return pd;\r
+}\r
+\r
+void WvPdRelease(WV_PROTECTION_DOMAIN *pPd)\r
+{\r
+       WvProviderEnableRemove(pPd->pDevice->pProvider);\r
+       WvPdPut(pPd);\r
+}\r
+\r
+static NTSTATUS WvPdAlloc(WV_DEVICE *pDevice, WV_PROTECTION_DOMAIN **ppPd,\r
+                                                 ci_umv_buf_t *pVerbsData)\r
+{\r
+       ib_api_status_t                 ib_status;\r
+       WV_PROTECTION_DOMAIN    *pd;\r
+\r
+       pd = ExAllocatePoolWithTag(PagedPool, sizeof(WV_PROTECTION_DOMAIN), 'dpvw');\r
+       if (pd == NULL) {\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       pd->Ref = 1;\r
+       KeInitializeEvent(&pd->Event, NotificationEvent, FALSE);\r
+       InitializeListHead(&pd->QpList);\r
+       InitializeListHead(&pd->SrqList);\r
+       InitializeListHead(&pd->MwList);\r
+       InitializeListHead(&pd->AhList);\r
+       cl_qmap_init(&pd->MrMap);\r
+       KeInitializeGuardedMutex(&pd->Lock);\r
+\r
+       ib_status = pDevice->pVerbs->allocate_pd(pDevice->hVerbsDevice, IB_PDT_NORMAL,\r
+                                                                                        &pd->hVerbsPd, pVerbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               goto err;\r
+       }\r
+\r
+       pd->pDevice = pDevice;\r
+       pd->pVerbs = pDevice->pVerbs;\r
+       *ppPd = pd;\r
+       return STATUS_SUCCESS;\r
+\r
+err:\r
+       ExFreePool(pd);\r
+       return STATUS_UNSUCCESSFUL;\r
+}\r
+\r
+void WvPdAllocate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                                *inid, *outid;\r
+       size_t                                  inlen, outlen;\r
+       WV_DEVICE                               *dev;\r
+       WV_PROTECTION_DOMAIN    *pd;\r
+       NTSTATUS                                status;\r
+       ci_umv_buf_t                    verbsData;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &inid, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_ID), &outid, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       dev = WvDeviceAcquire(pProvider, inid->Id);\r
+       if (dev == NULL) {\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+               goto err1;\r
+       }\r
+\r
+       WvInitVerbsData(&verbsData, inid->VerbInfo, inlen - sizeof(WV_IO_ID),\r
+                                       outlen - sizeof(WV_IO_ID), inid + 1);\r
+       status = WvPdAlloc(dev, &pd, &verbsData);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err2;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       outid->Id = IndexListInsertHead(&pProvider->PdIndex, pd);\r
+       if (outid->Id == 0) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err3;\r
+       }\r
+       InsertHeadList(&dev->PdList, &pd->Entry);\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       WvProviderEnableRemove(pProvider);\r
+       outid->VerbInfo = verbsData.status;\r
+       WdfRequestCompleteWithInformation(Request, status, outlen);\r
+       return;\r
+\r
+err3:\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+       WvPdFree(pd);\r
+err2:\r
+       WvDeviceRelease(dev);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvPdDeallocate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_PROTECTION_DOMAIN    *pd;\r
+       UINT64                                  *id;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       pd = IndexListAt(&pProvider->PdIndex, (SIZE_T) *id);\r
+       if (pd == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+       } else if (pd->Ref > 1) {\r
+               status = STATUS_ACCESS_DENIED;\r
+       } else {\r
+               IndexListRemove(&pProvider->PdIndex, (SIZE_T) *id);\r
+               RemoveEntryList(&pd->Entry);\r
+               status = STATUS_SUCCESS;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       if (NT_SUCCESS(status)) {\r
+               WvPdFree(pd);\r
+       }\r
+       WvProviderEnableRemove(pProvider);\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvPdFree(WV_PROTECTION_DOMAIN *pPd)\r
+{\r
+       WV_MEMORY_REGION        *mr;\r
+       cl_map_item_t           *item;\r
+\r
+       if (InterlockedDecrement(&pPd->Ref) > 0) {\r
+               KeWaitForSingleObject(&pPd->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
+\r
+       for (item = cl_qmap_head(&pPd->MrMap); item != cl_qmap_end(&pPd->MrMap);\r
+                item = cl_qmap_head(&pPd->MrMap)) {\r
+               mr = CONTAINING_RECORD(item, WV_MEMORY_REGION, Item);\r
+               if (mr->hVerbsMr != NULL) {\r
+                       pPd->pVerbs->deregister_mr(mr->hVerbsMr);\r
+               }\r
+\r
+               cl_qmap_remove_item(&pPd->MrMap, &mr->Item);\r
+               ExFreePool(mr);\r
+       }\r
+\r
+       if (pPd->hVerbsPd != NULL) {\r
+               pPd->pVerbs->deallocate_pd(pPd->hVerbsPd);\r
+       }\r
+\r
+       WvDevicePut(pPd->pDevice);\r
+       ExFreePool(pPd);\r
+}\r
+\r
+void WvPdRemoveHandler(WV_PROTECTION_DOMAIN *pPd)\r
+{\r
+       WV_QUEUE_PAIR                   *qp;\r
+       WV_SHARED_RECEIVE_QUEUE *srq;\r
+       WV_MEMORY_REGION                *mr;\r
+       WV_ADDRESS_HANDLE               *ah;\r
+       WV_MEMORY_WINDOW                *mw;\r
+       cl_map_item_t                   *item;\r
+       LIST_ENTRY                              *entry;\r
+\r
+       for (entry = pPd->MwList.Flink; entry != &pPd->MwList; entry = entry->Flink) {\r
+               mw = CONTAINING_RECORD(entry, WV_MEMORY_WINDOW, Entry);\r
+               pPd->pVerbs->destroy_mw(mw->hVerbsMw);\r
+               mw->hVerbsMw = NULL;\r
+       }\r
+\r
+       for (entry = pPd->AhList.Flink; entry != &pPd->AhList; entry = entry->Flink) {\r
+               ah = CONTAINING_RECORD(entry, WV_ADDRESS_HANDLE, Entry);\r
+               pPd->pVerbs->destroy_av(ah->hVerbsAh);\r
+               ah->hVerbsAh = NULL;\r
+       }\r
+\r
+       for (item = cl_qmap_head(&pPd->MrMap); item != cl_qmap_end(&pPd->MrMap);\r
+                item = cl_qmap_next(item)) {\r
+               mr = CONTAINING_RECORD(item, WV_MEMORY_REGION, Item);\r
+               pPd->pVerbs->deregister_mr(mr->hVerbsMr);\r
+               mr->hVerbsMr = NULL;\r
+       }\r
+\r
+       for (entry = pPd->QpList.Flink; entry != &pPd->QpList; entry = entry->Flink) {\r
+               qp = CONTAINING_RECORD(entry, WV_QUEUE_PAIR, Entry);\r
+               WvQpRemoveHandler(qp);\r
+       }\r
+\r
+       for (entry = pPd->SrqList.Flink; entry != &pPd->SrqList; entry = entry->Flink) {\r
+               srq = CONTAINING_RECORD(entry, WV_SHARED_RECEIVE_QUEUE, Entry);\r
+               pPd->pVerbs->destroy_srq(srq->hVerbsSrq);\r
+               srq->hVerbsSrq = NULL;\r
+               srq->pVerbs = NULL;\r
+       }\r
+\r
+       pPd->pVerbs->deallocate_pd(pPd->hVerbsPd);\r
+       pPd->pVerbs = NULL;\r
+       pPd->hVerbsPd = NULL;\r
+}\r
+\r
+void WvMrRegister(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_MEMORY_REGISTER   *reg;\r
+       WV_IO_MEMORY_KEYS               *keys;\r
+       WV_PROTECTION_DOMAIN    *pd;\r
+       WV_MEMORY_REGION                *mr;\r
+       ib_mr_create_t                  attr;\r
+       NTSTATUS                                status;\r
+       ib_api_status_t                 ib_status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_MEMORY_REGISTER),\r
+                                                                                  &reg, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_MEMORY_KEYS),\r
+                                                                                       &keys, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       pd = WvPdAcquire(pProvider, reg->Id);\r
+       if (pd == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto err1;\r
+       }\r
+\r
+       mr = ExAllocatePoolWithTag(PagedPool, sizeof(WV_MEMORY_REGION), 'rmvw');\r
+       if (mr == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err2;\r
+       }\r
+\r
+       attr.access_ctrl = reg->AccessFlags;\r
+       attr.length = reg->BufferLength;\r
+       attr.vaddr = (void *) (ULONG_PTR) reg->Address;\r
+       ib_status = pd->pVerbs->register_mr(pd->hVerbsPd, &attr, &keys->Lkey,\r
+                                                                               &keys->Rkey, &mr->hVerbsMr, TRUE);\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+               goto err3;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pd->Lock);\r
+       cl_qmap_insert(&pd->MrMap, keys->Lkey, &mr->Item);\r
+       KeReleaseGuardedMutex(&pd->Lock);\r
+\r
+       WvPdRelease(pd);\r
+       WdfRequestCompleteWithInformation(Request, status, sizeof(WV_IO_MEMORY_KEYS));\r
+       return;\r
+\r
+err3:\r
+       ExFreePool(mr);\r
+err2:\r
+       WvPdRelease(pd);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvMrDeregister(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                                *id;\r
+       WV_PROTECTION_DOMAIN    *pd;\r
+       WV_MEMORY_REGION                *mr;\r
+       cl_map_item_t                   *item;\r
+       NTSTATUS                                status;\r
+       ib_api_status_t                 ib_status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       pd = WvPdAcquire(pProvider, id->Id);\r
+       if (pd == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pd->Lock);\r
+       item = cl_qmap_remove(&pd->MrMap, id->Data);\r
+       KeReleaseGuardedMutex(&pd->Lock);\r
+\r
+       if (item == cl_qmap_end(&pd->MrMap)) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto release;\r
+       }\r
+\r
+       mr = CONTAINING_RECORD(item, WV_MEMORY_REGION, Item);\r
+\r
+       ib_status = pd->pVerbs->deregister_mr(mr->hVerbsMr);\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+               KeAcquireGuardedMutex(&pd->Lock);\r
+               cl_qmap_insert(&pd->MrMap, id->Data, &mr->Item);\r
+               KeReleaseGuardedMutex(&pd->Lock);\r
+               goto release;\r
+       }\r
+\r
+       ExFreePool(mr);\r
+release:\r
+       WvPdRelease(pd);\r
+complete:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvMwAllocate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                                *inid, *outid;\r
+       size_t                                  inlen, outlen;\r
+       WV_PROTECTION_DOMAIN    *pd;\r
+       WV_MEMORY_WINDOW                *mw;\r
+       NTSTATUS                                status;\r
+       ib_api_status_t                 ib_status;\r
+       ci_umv_buf_t                    verbsData;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &inid, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_ID), &outid, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       pd = WvPdAcquire(pProvider, inid->Id);\r
+       if (pd == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto err1;\r
+       }\r
+\r
+       mw = ExAllocatePoolWithTag(PagedPool, sizeof(WV_MEMORY_WINDOW), 'wmvw');\r
+       if (mw == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err2;\r
+       }\r
+\r
+       WvInitVerbsData(&verbsData, inid->VerbInfo, inlen - sizeof(WV_IO_ID),\r
+                                       outlen - sizeof(WV_IO_ID), inid + 1);\r
+       ib_status = pd->pVerbs->create_mw(pd->hVerbsPd, &outid->Data, &mw->hVerbsMw,\r
+                                                                         &verbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+               goto err3;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       outid->Id = IndexListInsertHead(&pProvider->MwIndex, mw);\r
+       if (outid->Id == 0) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err3;\r
+       }\r
+       InsertHeadList(&pd->MwList, &mw->Entry);\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       mw->pPd = pd;\r
+\r
+       WvProviderEnableRemove(pProvider);\r
+       outid->VerbInfo = verbsData.status;\r
+       WdfRequestCompleteWithInformation(Request, status, outlen);\r
+       return;\r
+\r
+err3:\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+       WvMwFree(mw);\r
+err2:\r
+       WvPdRelease(pd);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvMwDeallocate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_MEMORY_WINDOW        *mw;\r
+       UINT64                          *id;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       mw = IndexListAt(&pProvider->MwIndex, (SIZE_T) *id);\r
+       if (mw == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+       } else {\r
+               IndexListRemove(&pProvider->MwIndex, (SIZE_T) *id);\r
+               RemoveEntryList(&mw->Entry);\r
+               status = STATUS_SUCCESS;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       if (NT_SUCCESS(status)) {\r
+               WvMwFree(mw);\r
+       }\r
+       WvProviderEnableRemove(pProvider);\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvMwFree(WV_MEMORY_WINDOW *pMw)\r
+{\r
+       if (pMw->hVerbsMw != NULL) {\r
+               pMw->pPd->pVerbs->destroy_mw(pMw->hVerbsMw);\r
+       }\r
+\r
+       WvPdPut(pMw->pPd);\r
+       ExFreePool(pMw);\r
+}\r
+\r
+static void WvVerbsConvertAv(ib_av_attr_t *pVerbsAv, WV_IO_AV *pAv)\r
+{\r
+       pVerbsAv->grh_valid = pAv->NetworkRouteValid;\r
+       if (pVerbsAv->grh_valid) {\r
+               pVerbsAv->grh.ver_class_flow =\r
+                       RtlUlongByteSwap(RtlUlongByteSwap(pAv->FlowLabel) | (pAv->TrafficClass << 20));\r
+               pVerbsAv->grh.hop_limit = pAv->HopLimit;\r
+               RtlCopyMemory(&pVerbsAv->grh.src_gid, pAv->SGid, sizeof(pAv->SGid));\r
+               RtlCopyMemory(&pVerbsAv->grh.dest_gid, pAv->DGid, sizeof(pAv->DGid));\r
+       }\r
+\r
+       pVerbsAv->port_num = pAv->PortNumber;\r
+       pVerbsAv->sl = pAv->ServiceLevel;\r
+       pVerbsAv->dlid = pAv->DLid;\r
+       pVerbsAv->static_rate = pAv->StaticRate;\r
+       pVerbsAv->path_bits = pAv->SourcePathBits;\r
+}\r
+\r
+void WvAhCreate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       size_t                                  inlen, outlen;\r
+       WV_PROTECTION_DOMAIN    *pd;\r
+       WV_ADDRESS_HANDLE               *ah;\r
+       WV_IO_AH_CREATE                 *pinAv, *poutAv;\r
+       ib_av_attr_t                    av;\r
+       NTSTATUS                                status;\r
+       ib_api_status_t                 ib_status;\r
+       ci_umv_buf_t                    verbsData;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_AH_CREATE),\r
+                                                                                  &pinAv, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_AH_CREATE),\r
+                                                                                       &poutAv, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       pd = WvPdAcquire(pProvider, pinAv->Id.Id);\r
+       if (pd == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto err1;\r
+       }\r
+\r
+       ah = ExAllocatePoolWithTag(PagedPool, sizeof(WV_ADDRESS_HANDLE), 'havw');\r
+       if (ah == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err2;\r
+       }\r
+\r
+       WvVerbsConvertAv(&av, &pinAv->AddressVector);\r
+       WvInitVerbsData(&verbsData, pinAv->Id.VerbInfo, inlen - sizeof(WV_IO_AH_CREATE),\r
+                                       outlen - sizeof(WV_IO_AH_CREATE), pinAv + 1);\r
+       ib_status = pd->pVerbs->create_av(pd->hVerbsPd, &av, &ah->hVerbsAh, &verbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+               goto err3;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       poutAv->Id.Id = IndexListInsertHead(&pProvider->AhIndex, ah);\r
+       if (poutAv->Id.Id == 0) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err3;\r
+       }\r
+       InsertHeadList(&pd->AhList, &ah->Entry);\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       ah->pPd = pd;\r
+\r
+       WvProviderEnableRemove(pProvider);\r
+       poutAv->Id.VerbInfo = verbsData.status;\r
+       WdfRequestCompleteWithInformation(Request, status, outlen);\r
+       return;\r
+\r
+err3:\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+       WvAhFree(ah);\r
+err2:\r
+       WvPdRelease(pd);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvAhDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_ADDRESS_HANDLE       *ah;\r
+       UINT64                          *id;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       ah = IndexListAt(&pProvider->AhIndex, (SIZE_T) *id);\r
+       if (ah == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+       } else {\r
+               IndexListRemove(&pProvider->AhIndex, (SIZE_T) *id);\r
+               RemoveEntryList(&ah->Entry);\r
+               status = STATUS_SUCCESS;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       if (NT_SUCCESS(status)) {\r
+               WvAhFree(ah);\r
+       }\r
+       WvProviderEnableRemove(pProvider);\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvAhFree(WV_ADDRESS_HANDLE *pAh)\r
+{\r
+       if (pAh->hVerbsAh != NULL) {\r
+               pAh->pPd->pVerbs->destroy_av(pAh->hVerbsAh);\r
+       }\r
+\r
+       WvPdPut(pAh->pPd);\r
+       ExFreePool(pAh);\r
+}\r
diff --git a/core/winverbs/kernel/wv_pd.h b/core/winverbs/kernel/wv_pd.h
new file mode 100644 (file)
index 0000000..e0cd9b1
--- /dev/null
@@ -0,0 +1,109 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_PD_H_\r
+#define _WV_PD_H_\r
+\r
+#include <ntddk.h>\r
+#include <wdm.h>\r
+#include <iba\ib_types.h>\r
+#include <iba\ib_ci.h>\r
+\r
+#include "wv_device.h"\r
+#include "wv_provider.h"\r
+\r
+typedef struct _WV_PROTECTION_DOMAIN\r
+{\r
+       WV_DEVICE                       *pDevice;\r
+       ci_interface_t          *pVerbs;\r
+       ib_pd_handle_t          hVerbsPd;\r
+       LIST_ENTRY                      Entry;\r
+\r
+       LIST_ENTRY                      QpList;\r
+       LIST_ENTRY                      SrqList;\r
+       LIST_ENTRY                      MwList;\r
+       LIST_ENTRY                      AhList;\r
+       KGUARDED_MUTEX          Lock;\r
+       cl_qmap_t                       MrMap;\r
+\r
+       KEVENT                          Event;\r
+       LONG                            Ref;\r
+\r
+}      WV_PROTECTION_DOMAIN;\r
+\r
+WV_PROTECTION_DOMAIN *WvPdAcquire(WV_PROVIDER *pProvider, UINT64 Id);\r
+void WvPdRelease(WV_PROTECTION_DOMAIN *pPd);\r
+void WvPdGet(WV_PROTECTION_DOMAIN *pPd);\r
+void WvPdPut(WV_PROTECTION_DOMAIN *pPd);\r
+\r
+void WvPdAllocate(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvPdDeallocate(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvPdFree(WV_PROTECTION_DOMAIN *pPd);\r
+void WvPdRemoveHandler(WV_PROTECTION_DOMAIN *pPd);\r
+\r
+\r
+typedef struct _WV_MEMORY_REGION\r
+{\r
+       ib_mr_handle_t                  hVerbsMr;\r
+       cl_map_item_t                   Item;\r
+\r
+}      WV_MEMORY_REGION;\r
+\r
+void WvMrRegister(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvMrDeregister(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+\r
+\r
+typedef struct _WV_MEMORY_WINDOW\r
+{\r
+       WV_PROTECTION_DOMAIN    *pPd;\r
+       ib_mw_handle_t                  hVerbsMw;\r
+       LIST_ENTRY                              Entry;\r
+\r
+}      WV_MEMORY_WINDOW;\r
+\r
+void WvMwAllocate(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvMwDeallocate(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvMwFree(WV_MEMORY_WINDOW *pMw);\r
+\r
+\r
+typedef struct _WV_ADDRESS_HANDLE\r
+{\r
+       WV_PROTECTION_DOMAIN    *pPd;\r
+       ib_av_handle_t                  hVerbsAh;\r
+       LIST_ENTRY                              Entry;\r
+\r
+}      WV_ADDRESS_HANDLE;\r
+\r
+void WvAhCreate(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvAhDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvAhFree(WV_ADDRESS_HANDLE *pAh);\r
+\r
+#endif // _WV_PD_H_\r
diff --git a/core/winverbs/kernel/wv_provider.c b/core/winverbs/kernel/wv_provider.c
new file mode 100644 (file)
index 0000000..0411641
--- /dev/null
@@ -0,0 +1,206 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include <ntstatus.h>\r
+\r
+#include <rdma\wvstatus.h>\r
+#include "wv_driver.h"\r
+#include "wv_ioctl.h"\r
+#include "wv_provider.h"\r
+#include "wv_device.h"\r
+#include "wv_pd.h"\r
+#include "wv_srq.h"\r
+#include "wv_cq.h"\r
+#include "wv_qp.h"\r
+\r
+void WvProviderGet(WV_PROVIDER *pProvider)\r
+{\r
+       InterlockedIncrement(&pProvider->Ref);\r
+}\r
+\r
+void WvProviderPut(WV_PROVIDER *pProvider)\r
+{\r
+       if (InterlockedDecrement(&pProvider->Ref) == 0) {\r
+               KeSetEvent(&pProvider->Event, 0, FALSE);\r
+       }\r
+}\r
+\r
+void WvProviderInit(WV_PROVIDER *pProvider)\r
+{\r
+       IndexListInit(&pProvider->DevIndex);\r
+       IndexListInit(&pProvider->CqIndex);\r
+       IndexListInit(&pProvider->PdIndex);\r
+       IndexListInit(&pProvider->SrqIndex);\r
+       IndexListInit(&pProvider->QpIndex);\r
+       IndexListInit(&pProvider->MwIndex);\r
+       IndexListInit(&pProvider->AhIndex);\r
+\r
+       KeInitializeGuardedMutex(&pProvider->Lock);\r
+       pProvider->Ref = 1;\r
+       KeInitializeEvent(&pProvider->Event, NotificationEvent, FALSE);\r
+\r
+       pProvider->Pending = 0;\r
+       pProvider->Active = 0;\r
+       KeInitializeEvent(&pProvider->SharedEvent, NotificationEvent, FALSE);\r
+       pProvider->Exclusive = 0;\r
+       KeInitializeEvent(&pProvider->ExclusiveEvent, SynchronizationEvent, FALSE);\r
+}\r
+\r
+void WvProviderCleanup(WV_PROVIDER *pProvider)\r
+{\r
+       WV_DEVICE                               *dev;\r
+       WV_COMPLETION_QUEUE             *cq;\r
+       WV_PROTECTION_DOMAIN    *pd;\r
+       WV_SHARED_RECEIVE_QUEUE *srq;\r
+       WV_QUEUE_PAIR                   *qp;\r
+       WV_MEMORY_WINDOW                *mw;\r
+       WV_ADDRESS_HANDLE               *ah;\r
+\r
+       while ((ah = IndexListRemoveHead(&pProvider->AhIndex)) != NULL) {\r
+               RemoveEntryList(&ah->Entry);\r
+               WvAhFree(ah);\r
+       }\r
+       while ((mw = IndexListRemoveHead(&pProvider->MwIndex)) != NULL) {\r
+               RemoveEntryList(&mw->Entry);\r
+               WvMwFree(mw);\r
+       }\r
+       while ((qp = IndexListRemoveHead(&pProvider->QpIndex)) != NULL) {\r
+               RemoveEntryList(&qp->Entry);\r
+               WvQpFree(qp);\r
+       }\r
+       while ((srq = IndexListRemoveHead(&pProvider->SrqIndex)) != NULL) {\r
+               RemoveEntryList(&srq->Entry);\r
+               WvSrqFree(srq);\r
+       }\r
+       while ((pd = IndexListRemoveHead(&pProvider->PdIndex)) != NULL) {\r
+               RemoveEntryList(&pd->Entry);\r
+               WvPdFree(pd);\r
+       }\r
+       while ((cq = IndexListRemoveHead(&pProvider->CqIndex)) != NULL) {\r
+               RemoveEntryList(&cq->Entry);\r
+               WvCqFree(cq);\r
+       }\r
+       while ((dev = IndexListRemoveHead(&pProvider->DevIndex)) != NULL) {\r
+               WvDeviceFree(dev);\r
+       }\r
+\r
+       if (InterlockedDecrement(&pProvider->Ref) > 0) {\r
+               KeWaitForSingleObject(&pProvider->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
+\r
+       IndexListDestroy(&pProvider->AhIndex);\r
+       IndexListDestroy(&pProvider->MwIndex);\r
+       IndexListDestroy(&pProvider->QpIndex);\r
+       IndexListDestroy(&pProvider->SrqIndex);\r
+       IndexListDestroy(&pProvider->PdIndex);\r
+       IndexListDestroy(&pProvider->CqIndex);\r
+       IndexListDestroy(&pProvider->DevIndex);\r
+}\r
+\r
+// See comment above WvProviderRemoveHandler.\r
+static void WvProviderLockRemove(WV_PROVIDER *pProvider)\r
+{\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       pProvider->Exclusive++;\r
+       KeClearEvent(&pProvider->SharedEvent);\r
+       while (pProvider->Active > 0) {\r
+               KeReleaseGuardedMutex(&pProvider->Lock);\r
+               KeWaitForSingleObject(&pProvider->ExclusiveEvent, Executive, KernelMode,\r
+                                                         FALSE, NULL);\r
+               KeAcquireGuardedMutex(&pProvider->Lock);\r
+       }\r
+       pProvider->Active++;\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+}\r
+\r
+// See comment above WvProviderRemoveHandler.\r
+static void WvProviderUnlockRemove(WV_PROVIDER *pProvider)\r
+{\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       pProvider->Exclusive--;\r
+       pProvider->Active--;\r
+       if (pProvider->Exclusive > 0) {\r
+               KeSetEvent(&pProvider->ExclusiveEvent, 0, FALSE);\r
+       } else if (pProvider->Pending > 0) {\r
+               KeSetEvent(&pProvider->SharedEvent, 0, FALSE);\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+}\r
+\r
+/*\r
+ * Must hold pProvider->Lock.  Function may release and re-acquire.\r
+ * See comment above WvProviderRemoveHandler.\r
+ */\r
+void WvProviderDisableRemove(WV_PROVIDER *pProvider)\r
+{\r
+       while (pProvider->Exclusive > 0) {\r
+               pProvider->Pending++;\r
+               KeReleaseGuardedMutex(&pProvider->Lock);\r
+               KeWaitForSingleObject(&pProvider->SharedEvent, Executive, KernelMode,\r
+                                                         FALSE, NULL);\r
+               KeAcquireGuardedMutex(&pProvider->Lock);\r
+               pProvider->Pending--;\r
+       }\r
+       InterlockedIncrement(&pProvider->Active);\r
+}\r
+\r
+/*\r
+ * No need to hold pProvider->Lock when releasing.\r
+ * See comment above WvProviderRemoveHandler.\r
+ */\r
+void WvProviderEnableRemove(WV_PROVIDER *pProvider)\r
+{\r
+       InterlockedDecrement(&pProvider->Active);\r
+       if (pProvider->Exclusive > 0) {\r
+               KeSetEvent(&pProvider->ExclusiveEvent, 0, FALSE);\r
+       }\r
+}\r
+\r
+/*\r
+ * The remove handler blocks all other threads executing through this\r
+ * provider until the remove has been processed.  Because device removal is\r
+ * rare, we want a simple, optimized code path for all calls that access\r
+ * the underlying hardware device, making use of any locks that we would\r
+ * have to acquire anyway.  The locking for exclusive access can be\r
+ * as ugly and slow as needed.\r
+ */\r
+void WvProviderRemoveHandler(WV_PROVIDER *pProvider, WV_RDMA_DEVICE *pDevice)\r
+{\r
+       WV_DEVICE *dev;\r
+       SIZE_T i;\r
+\r
+       WvProviderLockRemove(pProvider);\r
+       IndexListForEach(&pProvider->DevIndex, i) {\r
+               dev = IndexListAt(&pProvider->DevIndex, i);\r
+               if (dev->pDevice == pDevice) {\r
+                       WvDeviceRemoveHandler(dev);\r
+               }\r
+       }\r
+       WvProviderUnlockRemove(pProvider);\r
+}\r
diff --git a/core/winverbs/kernel/wv_provider.h b/core/winverbs/kernel/wv_provider.h
new file mode 100644 (file)
index 0000000..efcea29
--- /dev/null
@@ -0,0 +1,77 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_PROVIDER_H_\r
+#define _WV_PROVIDER_H_\r
+\r
+#include <ntddk.h>\r
+#include <wdf.h>\r
+#include <wdm.h>\r
+\r
+#include <complib\cl_qmap.h>\r
+#include "wv_driver.h"\r
+#include "index_list.h"\r
+\r
+struct _WV_DEVICE;\r
+struct _WV_PROTECTION_DOMAIN;\r
+\r
+typedef struct _WV_PROVIDER\r
+{\r
+       LIST_ENTRY              Entry;\r
+       INDEX_LIST              DevIndex;\r
+       INDEX_LIST              CqIndex;\r
+       INDEX_LIST              PdIndex;\r
+       INDEX_LIST              SrqIndex;\r
+       INDEX_LIST              QpIndex;\r
+       INDEX_LIST              MwIndex;\r
+       INDEX_LIST              AhIndex;\r
+\r
+       KGUARDED_MUTEX  Lock;\r
+       LONG                    Ref;\r
+       KEVENT                  Event;\r
+       LONG                    Pending;\r
+       LONG                    Active;\r
+       KEVENT                  SharedEvent;\r
+       LONG                    Exclusive;\r
+       KEVENT                  ExclusiveEvent;\r
+\r
+}      WV_PROVIDER;\r
+\r
+void WvProviderGet(WV_PROVIDER *pProvider);\r
+void WvProviderPut(WV_PROVIDER *pProvider);\r
+void WvProviderInit(WV_PROVIDER *pProvider);\r
+void WvProviderCleanup(WV_PROVIDER *pProvider);\r
+\r
+void WvProviderRemoveHandler(WV_PROVIDER *pProvider, WV_RDMA_DEVICE *pDevice);\r
+void WvProviderDisableRemove(WV_PROVIDER *pProvider);\r
+void WvProviderEnableRemove(WV_PROVIDER *pProvider);\r
+\r
+#endif // _WV_PROVIDER_H_\r
diff --git a/core/winverbs/kernel/wv_qp.c b/core/winverbs/kernel/wv_qp.c
new file mode 100644 (file)
index 0000000..3d1ed9d
--- /dev/null
@@ -0,0 +1,760 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include "wv_qp.h"\r
+#include "wv_ioctl.h"\r
+\r
+typedef struct _WV_MULTICAST\r
+{\r
+       LIST_ENTRY                      Entry;\r
+       WV_IO_GID                       Gid;\r
+       NET16                           Lid;\r
+       ib_mcast_handle_t       hVerbsMc;\r
+\r
+}      WV_MULTICAST;\r
+\r
+static void WvVerbsConvertCreate(ib_qp_create_t *pVerbsAttr,\r
+                                                                WV_IO_QP_CREATE *pAttr, WV_QUEUE_PAIR *pQp)\r
+{\r
+       pVerbsAttr->h_sq_cq = pQp->pSendCq->hVerbsCq;\r
+       pVerbsAttr->h_rq_cq = pQp->pReceiveCq->hVerbsCq;\r
+       pVerbsAttr->h_srq = (pQp->pSrq != NULL) ? pQp->pSrq->hVerbsSrq : NULL;\r
+\r
+       pVerbsAttr->qp_type = (ib_qp_type_t) pAttr->QpType;\r
+       pVerbsAttr->sq_depth = pAttr->SendDepth;\r
+       pVerbsAttr->rq_depth = pAttr->ReceiveDepth;\r
+       pVerbsAttr->sq_sge = pAttr->SendSge;\r
+       pVerbsAttr->rq_sge = pAttr->ReceiveSge;\r
+\r
+       pVerbsAttr->sq_signaled = ((pAttr->QpFlags & WV_IO_QP_SIGNAL_SENDS) != 0);\r
+}\r
+\r
+static UINT8 WvQpStateConvertVerbs(ib_qp_state_t State)\r
+{\r
+       switch (State) {\r
+       case IB_QPS_RESET:      return WV_IO_QP_STATE_RESET;\r
+       case IB_QPS_INIT:       return WV_IO_QP_STATE_INIT;\r
+       case IB_QPS_RTR:        return WV_IO_QP_STATE_RTR;\r
+       case IB_QPS_RTS:        return WV_IO_QP_STATE_RTS;\r
+       case IB_QPS_SQD:        return WV_IO_QP_STATE_SQD;\r
+       case IB_QPS_SQERR:      return WV_IO_QP_STATE_SQERROR;\r
+       default:                        return WV_IO_QP_STATE_ERROR;\r
+       }\r
+}\r
+\r
+static UINT8 WvVerbsConvertMtu(UINT32 Mtu)\r
+{\r
+       switch (Mtu) {\r
+       case 256:       return IB_MTU_LEN_256;\r
+       case 512:       return IB_MTU_LEN_512;\r
+       case 1024:      return IB_MTU_LEN_1024;\r
+       case 2048:      return IB_MTU_LEN_2048;\r
+       case 4096:      return IB_MTU_LEN_4096;\r
+       default:        return 0;\r
+       }\r
+}\r
+static void WvAvConvertVerbs(WV_IO_AV *pAv, ib_av_attr_t *pVerbsAv)\r
+{\r
+       pAv->NetworkRouteValid = (uint8_t) pVerbsAv->grh_valid;\r
+       if (pAv->NetworkRouteValid) {\r
+               pAv->FlowLabel = pVerbsAv->grh.ver_class_flow & RtlUlongByteSwap(0x000FFFFF);\r
+               pAv->TrafficClass = (UINT8) (RtlUlongByteSwap(pVerbsAv->grh.ver_class_flow) >> 20);\r
+               pAv->HopLimit = pVerbsAv->grh.hop_limit;\r
+               RtlCopyMemory(pAv->SGid, &pVerbsAv->grh.src_gid, sizeof(pAv->SGid));\r
+               RtlCopyMemory(pAv->DGid, &pVerbsAv->grh.dest_gid, sizeof(pAv->DGid));\r
+       }\r
+\r
+       pAv->PortNumber = pVerbsAv->port_num;\r
+       pAv->ServiceLevel = pVerbsAv->sl;\r
+       pAv->DLid = pVerbsAv->dlid;\r
+       pAv->StaticRate = pVerbsAv->static_rate;\r
+       pAv->SourcePathBits = pVerbsAv->path_bits;\r
+}\r
+\r
+static void WvVerbsConvertAv(ib_av_attr_t *pVerbsAv, WV_IO_AV *pAv,\r
+                                                        WV_IO_QP_ATTRIBUTES *pAttr)\r
+{\r
+       pVerbsAv->grh_valid = pAv->NetworkRouteValid;\r
+       if (pVerbsAv->grh_valid) {\r
+               pVerbsAv->grh.ver_class_flow =\r
+                       RtlUlongByteSwap(RtlUlongByteSwap(pAv->FlowLabel) | (pAv->TrafficClass << 20));\r
+               pVerbsAv->grh.hop_limit = pAv->HopLimit;\r
+               RtlCopyMemory(&pVerbsAv->grh.src_gid, pAv->SGid, sizeof(pAv->SGid));\r
+               RtlCopyMemory(&pVerbsAv->grh.dest_gid, pAv->DGid, sizeof(pAv->DGid));\r
+       }\r
+\r
+       pVerbsAv->port_num = pAv->PortNumber;\r
+       pVerbsAv->sl = pAv->ServiceLevel;\r
+       pVerbsAv->dlid = pAv->DLid;\r
+       pVerbsAv->static_rate = pAv->StaticRate;\r
+       pVerbsAv->path_bits = pAv->SourcePathBits;\r
+\r
+       pVerbsAv->conn.path_mtu = WvVerbsConvertMtu(pAttr->PathMtu);\r
+       pVerbsAv->conn.local_ack_timeout = pAttr->LocalAckTimeout;\r
+       pVerbsAv->conn.seq_err_retry_cnt = pAttr->SequenceErrorRetryCount;\r
+       pVerbsAv->conn.rnr_retry_cnt = pAttr->RnrRetryCount;\r
+}\r
+\r
+static void WvQpAttrConvertVerbs(WV_IO_QP_ATTRIBUTES *pAttr, ib_qp_attr_t *pVerbsAttr)\r
+{\r
+       pAttr->MaxInlineSend = pVerbsAttr->sq_max_inline;\r
+       pAttr->SendDepth = pVerbsAttr->sq_depth;\r
+       pAttr->ReceiveDepth = pVerbsAttr->rq_depth;\r
+       pAttr->SendSge = pVerbsAttr->sq_sge;\r
+       pAttr->ReceiveSge = pVerbsAttr->rq_sge;\r
+       pAttr->InitiatorDepth = pVerbsAttr->init_depth;\r
+       pAttr->ResponderResources = pVerbsAttr->resp_res;\r
+\r
+       pAttr->Options = 0;\r
+       pAttr->QpType = pVerbsAttr->qp_type;\r
+       pAttr->CurrentQpState = WvQpStateConvertVerbs(pVerbsAttr->state);\r
+       pAttr->QpState = pAttr->CurrentQpState;\r
+       pAttr->ApmState = pVerbsAttr->apm_state;\r
+       pAttr->Qpn = pVerbsAttr->num;\r
+       pAttr->DestinationQpn = pVerbsAttr->dest_num;\r
+       pAttr->Qkey = pVerbsAttr->qkey;\r
+       pAttr->SendPsn = pVerbsAttr->sq_psn;\r
+       pAttr->ReceivePsn = pVerbsAttr->rq_psn;\r
+\r
+       pAttr->QpFlags = pVerbsAttr->sq_signaled ? WV_IO_QP_SIGNAL_SENDS : 0;\r
+       pAttr->AccessFlags = (UINT8) pVerbsAttr->access_ctrl;\r
+\r
+       pAttr->AddressVector.PortNumber = pVerbsAttr->primary_port;\r
+       pAttr->AlternateAddressVector.PortNumber = pVerbsAttr->alternate_port;\r
+       WvAvConvertVerbs(&pAttr->AddressVector, &pVerbsAttr->primary_av);\r
+       WvAvConvertVerbs(&pAttr->AlternateAddressVector, &pVerbsAttr->alternate_av);\r
+       pAttr->PathMtu = 0x80 << pVerbsAttr->primary_av.conn.path_mtu;\r
+       pAttr->AlternatePathMtu = 0x80 << pVerbsAttr->alternate_av.conn.path_mtu;\r
+       pAttr->PkeyIndex = pVerbsAttr->pkey_index;\r
+       pAttr->AlternatePkeyIndex = pAttr->PkeyIndex;   // TODO: missing in ib_qp_attr_t\r
+       pAttr->LocalAckTimeout = pVerbsAttr->primary_av.conn.local_ack_timeout;\r
+       pAttr->AlternateLocalAckTimeout = pVerbsAttr->alternate_av.conn.local_ack_timeout;\r
+\r
+       pAttr->RnrNakTimeout = 0;                                               // TODO: missing in ib_ap_attr_t\r
+       pAttr->SequenceErrorRetryCount = pVerbsAttr->primary_av.conn.seq_err_retry_cnt;\r
+       pAttr->RnrRetryCount = pVerbsAttr->primary_av.conn.rnr_retry_cnt;\r
+}\r
+\r
+static ib_qp_opts_t WvVerbsConvertOptions(UINT32 Options)\r
+{\r
+       UINT32 opt = 0;\r
+\r
+       if ((Options & WV_IO_QP_ATTR_CAPABILITIES) != 0) {\r
+               opt |= IB_MOD_QP_SQ_DEPTH | IB_MOD_QP_RQ_DEPTH;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_INITIATOR_DEPTH) != 0) {\r
+               opt |= IB_MOD_QP_INIT_DEPTH;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_RESPONDER_RESOURCES) != 0) {\r
+               opt |= IB_MOD_QP_RESP_RES;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_CURRENT_STATE) != 0) {\r
+               opt |= IB_MOD_QP_CURRENT_STATE;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_PATH_MIG_STATE) != 0) {\r
+               opt |= IB_MOD_QP_APM_STATE;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_QKEY) != 0) {\r
+               opt |= IB_MOD_QP_QKEY;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_ACCESS_FLAGS) != 0) {\r
+               opt |= IB_MOD_QP_ACCESS_CTRL;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_AV) != 0) {\r
+               opt |= IB_MOD_QP_PRIMARY_AV;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_ALTERNATE_AV) != 0) {\r
+               opt |= IB_MOD_QP_ALTERNATE_AV;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_PORT_NUMBER) != 0) {\r
+               opt |= IB_MOD_QP_PRIMARY_PORT;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_PKEY_INDEX) != 0) {\r
+               opt |= IB_MOD_QP_PKEY;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_ACK_TIMEOUT) != 0) {\r
+               opt |= IB_MOD_QP_LOCAL_ACK_TIMEOUT;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_RNR_NAK_TIMEOUT) != 0) {\r
+               opt |= IB_MOD_QP_RNR_NAK_TIMEOUT;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_ERROR_RETRY_COUNT) != 0) {\r
+               opt |= IB_MOD_QP_RETRY_CNT;\r
+       }\r
+       if ((Options & WV_IO_QP_ATTR_RNR_RETRY_COUNT) != 0) {\r
+               opt |= IB_MOD_QP_RNR_RETRY_CNT;\r
+       }\r
+\r
+       return (ib_qp_opts_t) opt;\r
+}\r
+\r
+static ib_qp_state_t WvVerbsConvertState(UINT8 State)\r
+{\r
+       switch (State) {\r
+       case WV_IO_QP_STATE_RESET:              return IB_QPS_RESET;\r
+       case WV_IO_QP_STATE_INIT:               return IB_QPS_INIT;\r
+       case WV_IO_QP_STATE_RTR:                return IB_QPS_RTR;\r
+       case WV_IO_QP_STATE_RTS:                return IB_QPS_RTS;\r
+       case WV_IO_QP_STATE_SQD:                return IB_QPS_SQD;\r
+       case WV_IO_QP_STATE_SQERROR:    return IB_QPS_SQERR;\r
+       default:                                                return IB_QPS_ERROR;\r
+       }\r
+}\r
+\r
+static void WvVerbsConvertAttr(ib_qp_mod_t *pVerbsAttr, WV_IO_QP_ATTRIBUTES *pAttr)\r
+{\r
+       switch (pAttr->QpState) {\r
+       case WV_IO_QP_STATE_RESET:\r
+               pVerbsAttr->req_state = IB_QPS_RESET;\r
+               break;\r
+       case WV_IO_QP_STATE_INIT:\r
+               pVerbsAttr->req_state = IB_QPS_INIT;\r
+\r
+               pVerbsAttr->state.init.primary_port = pAttr->AddressVector.PortNumber;\r
+               pVerbsAttr->state.init.qkey = pAttr->Qkey;\r
+               pVerbsAttr->state.init.pkey_index = pAttr->PkeyIndex;\r
+               pVerbsAttr->state.init.access_ctrl = pAttr->AccessFlags;\r
+               break;\r
+       case WV_IO_QP_STATE_RTR:\r
+               pVerbsAttr->req_state = IB_QPS_RTR;\r
+\r
+               pVerbsAttr->state.rtr.rq_psn = pAttr->ReceivePsn;\r
+               pVerbsAttr->state.rtr.dest_qp = pAttr->DestinationQpn;\r
+               WvVerbsConvertAv(&pVerbsAttr->state.rtr.primary_av,\r
+                                                &pAttr->AddressVector, pAttr);\r
+               pVerbsAttr->state.rtr.resp_res = (UINT8) pAttr->ResponderResources;\r
+               pVerbsAttr->state.rtr.rnr_nak_timeout = pAttr->RnrNakTimeout;\r
+\r
+               pVerbsAttr->state.rtr.opts = WvVerbsConvertOptions(pAttr->Options);\r
+               WvVerbsConvertAv(&pVerbsAttr->state.rtr.alternate_av,\r
+                                                &pAttr->AlternateAddressVector, pAttr);\r
+               pVerbsAttr->state.rtr.qkey = pAttr->Qkey;\r
+               pVerbsAttr->state.rtr.pkey_index = pAttr->PkeyIndex;\r
+               pVerbsAttr->state.rtr.access_ctrl = pAttr->AccessFlags;\r
+               pVerbsAttr->state.rtr.sq_depth = pAttr->SendDepth;\r
+               pVerbsAttr->state.rtr.rq_depth = pAttr->ReceiveDepth;\r
+               break;\r
+       case WV_IO_QP_STATE_RTS:\r
+               pVerbsAttr->req_state = IB_QPS_RTS;\r
+\r
+               pVerbsAttr->state.rts.sq_psn = pAttr->SendPsn;\r
+               pVerbsAttr->state.rts.retry_cnt = pAttr->SequenceErrorRetryCount;\r
+               pVerbsAttr->state.rts.rnr_retry_cnt     = pAttr->RnrRetryCount;\r
+               pVerbsAttr->state.rts.local_ack_timeout = pAttr->LocalAckTimeout;\r
+               pVerbsAttr->state.rts.init_depth = (UINT8) pAttr->InitiatorDepth;\r
+\r
+               pVerbsAttr->state.rts.opts = WvVerbsConvertOptions(pAttr->Options);\r
+               pVerbsAttr->state.rts.rnr_nak_timeout = pAttr->RnrNakTimeout;\r
+               pVerbsAttr->state.rts.current_state = WvVerbsConvertState(pAttr->CurrentQpState);\r
+               pVerbsAttr->state.rts.qkey = pAttr->Qkey;\r
+               pVerbsAttr->state.rts.access_ctrl = pAttr->AccessFlags;\r
+               pVerbsAttr->state.rts.resp_res = (UINT8) pAttr->ResponderResources;\r
+\r
+               WvVerbsConvertAv(&pVerbsAttr->state.rts.primary_av,\r
+                                                &pAttr->AddressVector, pAttr);\r
+               WvVerbsConvertAv(&pVerbsAttr->state.rts.alternate_av,\r
+                                                &pAttr->AlternateAddressVector, pAttr);\r
+\r
+               pVerbsAttr->state.rts.sq_depth = pAttr->SendDepth;\r
+               pVerbsAttr->state.rts.rq_depth = pAttr->ReceiveDepth;\r
+\r
+               pVerbsAttr->state.rts.apm_state = pAttr->ApmState;\r
+               pVerbsAttr->state.rts.primary_port = pAttr->AddressVector.PortNumber;\r
+               pVerbsAttr->state.rts.pkey_index = pAttr->PkeyIndex;\r
+               break;\r
+       case WV_IO_QP_STATE_SQD:\r
+               pVerbsAttr->req_state = IB_QPS_SQD;\r
+               pVerbsAttr->state.sqd.sqd_event = 1;\r
+               break;\r
+       case WV_IO_QP_STATE_SQERROR:\r
+               pVerbsAttr->req_state = IB_QPS_SQERR;\r
+               break;\r
+       default:\r
+               pVerbsAttr->req_state = IB_QPS_ERROR;\r
+               break;\r
+       }\r
+}\r
+\r
+static void WvQpGet(WV_QUEUE_PAIR *pQp)\r
+{\r
+       InterlockedIncrement(&pQp->Ref);\r
+}\r
+\r
+static void WvQpPut(WV_QUEUE_PAIR *pQp)\r
+{\r
+       if (InterlockedDecrement(&pQp->Ref) == 0) {\r
+               KeSetEvent(&pQp->Event, 0, FALSE);\r
+       }\r
+}\r
+\r
+WV_QUEUE_PAIR *WvQpAcquire(WV_PROVIDER *pProvider, UINT64 Id)\r
+{\r
+       WV_QUEUE_PAIR *qp;\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       qp = IndexListAt(&pProvider->QpIndex, (SIZE_T) Id);\r
+       if (qp != NULL && qp->hVerbsQp != NULL) {\r
+               WvQpGet(qp);\r
+       } else {\r
+               qp = NULL;\r
+               WvProviderEnableRemove(pProvider);\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       return qp;\r
+}\r
+\r
+void WvQpRelease(WV_QUEUE_PAIR *pQp)\r
+{\r
+       WvProviderEnableRemove(pQp->pProvider);\r
+       WvQpPut(pQp);\r
+}\r
+\r
+static NTSTATUS WvQpCreateAcquire(WV_PROVIDER *pProvider, WV_QUEUE_PAIR *pQp,\r
+                                                                 WV_IO_QP_CREATE *pAttributes)\r
+{\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       pQp->pPd = IndexListAt(&pProvider->PdIndex, (SIZE_T) pAttributes->Id.Id);\r
+       if (pQp->pPd != NULL && pQp->pPd->hVerbsPd != NULL) {\r
+               WvPdGet(pQp->pPd);\r
+               pQp->pVerbs = pQp->pPd->pVerbs;\r
+       } else {\r
+               goto err1;\r
+       }\r
+\r
+       pQp->pSendCq = IndexListAt(&pProvider->CqIndex, (SIZE_T) pAttributes->SendCqId);\r
+       if (pQp->pSendCq != NULL && pQp->pSendCq->hVerbsCq != NULL) {\r
+               WvCqGet(pQp->pSendCq);\r
+       } else {\r
+               goto err2;\r
+       }\r
+\r
+       pQp->pReceiveCq = IndexListAt(&pProvider->CqIndex,\r
+                                                                 (SIZE_T) pAttributes->ReceiveCqId);\r
+       if (pQp->pReceiveCq != NULL && pQp->pReceiveCq->hVerbsCq != NULL) {\r
+               WvCqGet(pQp->pReceiveCq);\r
+       } else {\r
+               goto err3;\r
+       }\r
+\r
+       if (pAttributes->SrqId != 0) {\r
+               pQp->pSrq = IndexListAt(&pProvider->SrqIndex, (SIZE_T) pAttributes->SrqId);\r
+               if (pQp->pSrq != NULL && pQp->pSrq->hVerbsSrq != NULL) {\r
+                       WvSrqGet(pQp->pSrq);\r
+               } else {\r
+                       goto err4;\r
+               }\r
+       } else {\r
+               pQp->pSrq = NULL;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       return STATUS_SUCCESS;\r
+\r
+err4:\r
+       WvCqPut(pQp->pReceiveCq);\r
+err3:\r
+       WvCqPut(pQp->pSendCq);\r
+err2:\r
+       WvPdPut(pQp->pPd);\r
+err1:\r
+       WvProviderEnableRemove(pProvider);\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+       return STATUS_NOT_FOUND;\r
+}\r
+\r
+static void WvQpCreateRelease(WV_PROVIDER *pProvider, WV_QUEUE_PAIR *pQp)\r
+{\r
+       WvProviderEnableRemove(pProvider);\r
+       if (pQp->pSrq != NULL) {\r
+               WvSrqPut(pQp->pSrq);\r
+       }\r
+       WvCqPut(pQp->pReceiveCq);\r
+       WvCqPut(pQp->pSendCq);\r
+       WvPdPut(pQp->pPd);\r
+}\r
+\r
+static void WvQpEventHandler(ib_event_rec_t *pEvent)\r
+{\r
+       // TODO: Handle QP events when adding connection handling\r
+       // IB_AE_QP_FATAL\r
+       // IB_AE_QP_COMM\r
+       // IB_AE_QP_APM\r
+       UNREFERENCED_PARAMETER(pEvent);\r
+}\r
+\r
+void WvQpCreate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_QP_CREATE                 *inattr, *outattr;\r
+       size_t                                  inlen, outlen;\r
+       WV_QUEUE_PAIR                   *qp;\r
+       ib_qp_create_t                  create;\r
+       ib_qp_attr_t                    ib_attr;\r
+       NTSTATUS                                status;\r
+       ib_api_status_t                 ib_status;\r
+       ci_umv_buf_t                    verbsData;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_QP_CREATE),\r
+                                                                                  &inattr, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_QP_CREATE),\r
+                                                                                       &outattr, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       qp = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_QUEUE_PAIR), 'pqvw');\r
+       if (qp == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err1;\r
+       }\r
+\r
+       qp->Ref = 1;\r
+       qp->pProvider = pProvider;\r
+       KeInitializeEvent(&qp->Event, NotificationEvent, FALSE);\r
+       InitializeListHead(&qp->McList);\r
+       status = WvQpCreateAcquire(pProvider, qp, inattr);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err2;\r
+       }\r
+\r
+       WvVerbsConvertCreate(&create, inattr, qp);\r
+       WvInitVerbsData(&verbsData, inattr->Id.VerbInfo, inlen - sizeof(WV_IO_QP_CREATE),\r
+                                       outlen - sizeof(WV_IO_QP_CREATE), inattr + 1);\r
+       ib_status = qp->pVerbs->create_qp(qp->pPd->hVerbsPd, qp, WvQpEventHandler,\r
+                                                                         &create, &ib_attr, &qp->hVerbsQp, &verbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+               goto err3;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       outattr->Id.Id = IndexListInsertHead(&pProvider->QpIndex, qp);\r
+       if (outattr->Id.Id == 0) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err4;\r
+       }\r
+       InsertHeadList(&qp->pPd->QpList, &qp->Entry);\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       WvProviderEnableRemove(pProvider);\r
+       outattr->Id.VerbInfo = verbsData.status;\r
+       WdfRequestCompleteWithInformation(Request, status, outlen);\r
+       return;\r
+\r
+err4:\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+       qp->pVerbs->destroy_qp(qp->hVerbsQp, 0);\r
+err3:\r
+       WvQpCreateRelease(pProvider, qp);\r
+err2:\r
+       ExFreePool(qp);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvQpDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_QUEUE_PAIR   *qp;\r
+       UINT64                  *id;\r
+       NTSTATUS                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       qp = IndexListAt(&pProvider->QpIndex, (SIZE_T) *id);\r
+       if (qp == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+       } else if (qp->Ref > 1) {\r
+               status = STATUS_ACCESS_DENIED;\r
+       } else {\r
+               IndexListRemove(&pProvider->QpIndex, (SIZE_T) *id);\r
+               RemoveEntryList(&qp->Entry);\r
+               status = STATUS_SUCCESS;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       if (NT_SUCCESS(status)) {\r
+               WvQpFree(qp);\r
+       }\r
+       WvProviderEnableRemove(pProvider);\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvQpFree(WV_QUEUE_PAIR *pQp)\r
+{\r
+       WV_MULTICAST            *mc;\r
+       LIST_ENTRY                      *entry;\r
+\r
+       while ((entry = RemoveHeadList(&pQp->McList)) != &pQp->McList) {\r
+               mc = CONTAINING_RECORD(entry, WV_MULTICAST, Entry);\r
+               if (mc->hVerbsMc != NULL) {\r
+                       pQp->pVerbs->detach_mcast(mc->hVerbsMc);\r
+               }\r
+               WvQpPut(pQp);\r
+               ExFreePool(mc);\r
+       }\r
+\r
+       if (InterlockedDecrement(&pQp->Ref) > 0) {\r
+               KeWaitForSingleObject(&pQp->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
+\r
+       if (pQp->hVerbsQp != NULL) {\r
+               pQp->pVerbs->destroy_qp(pQp->hVerbsQp, 0);\r
+       }\r
+\r
+       if (pQp->pSrq != NULL) {\r
+               WvSrqPut(pQp->pSrq);\r
+       }\r
+       WvCqPut(pQp->pReceiveCq);\r
+       WvCqPut(pQp->pSendCq);\r
+       WvPdPut(pQp->pPd);\r
+       ExFreePool(pQp);\r
+}\r
+\r
+void WvQpQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                                  *id;\r
+       WV_IO_QP_ATTRIBUTES             *pattr;\r
+       size_t                                  inlen, outlen, len = 0;\r
+       WV_QUEUE_PAIR                   *qp;\r
+       ib_qp_attr_t                    attr;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_QP_ATTRIBUTES),\r
+                                                                                       &pattr, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       qp = WvQpAcquire(pProvider, *id);\r
+       if (qp == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       qp->pVerbs->query_qp(qp->hVerbsQp, &attr, NULL);\r
+       WvQpRelease(qp);\r
+\r
+       WvQpAttrConvertVerbs(pattr, &attr);\r
+       len = outlen;\r
+\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+void WvQpModify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_QP_ATTRIBUTES             *pattr;\r
+       UINT8                                   *out;\r
+       size_t                                  outlen, len = 0;\r
+       WV_QUEUE_PAIR                   *qp;\r
+       ib_qp_mod_t                             attr;\r
+       NTSTATUS                                status;\r
+       ib_api_status_t                 ib_status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_QP_ATTRIBUTES),\r
+                                                                                  &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, 0, &out, &outlen);\r
+       if (!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL) {\r
+               goto complete;\r
+       }\r
+\r
+       WvVerbsConvertAttr(&attr, pattr);\r
+       qp = WvQpAcquire(pProvider, pattr->Id.Id);\r
+       if (qp == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       ib_status = qp->pVerbs->ndi_modify_qp(qp->hVerbsQp, &attr, NULL, (UINT32) outlen, out);\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+       }\r
+       WvQpRelease(qp);\r
+       len = outlen;\r
+\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+void WvQpAttach(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_MULTICAST                    *pmc;\r
+       WV_IO_QP_MULTICAST              *mc;\r
+       WV_QUEUE_PAIR                   *qp;\r
+       NTSTATUS                                status;\r
+       ib_api_status_t                 ib_status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_QP_MULTICAST),\r
+                                                                                  &mc, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       pmc = ExAllocatePoolWithTag(PagedPool, sizeof(WV_MULTICAST), 'cmvw');\r
+       if (pmc == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err1;\r
+       }\r
+\r
+       qp = WvQpAcquire(pProvider, mc->Id.Id);\r
+       if (qp == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto err2;\r
+       }\r
+\r
+       pmc->Gid = mc->Gid;\r
+       pmc->Lid = (NET16) mc->Id.Data;\r
+       ib_status = qp->pVerbs->attach_mcast(qp->hVerbsQp, (ib_gid_t *) &mc->Gid,\r
+                                                                                (NET16) mc->Id.Data, &pmc->hVerbsMc, NULL);\r
+\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+               goto err3;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&qp->pPd->Lock);\r
+       InsertHeadList(&qp->McList, &pmc->Entry);\r
+       KeReleaseGuardedMutex(&qp->pPd->Lock);\r
+\r
+       WvProviderEnableRemove(pProvider);\r
+       WdfRequestComplete(Request, STATUS_SUCCESS);\r
+       return;\r
+\r
+err3:\r
+       WvQpRelease(qp);\r
+err2:\r
+       ExFreePool(pmc);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvQpDetach(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_MULTICAST                    *pmc;\r
+       WV_IO_QP_MULTICAST              *mc;\r
+       WV_QUEUE_PAIR                   *qp;\r
+       LIST_ENTRY                              *entry;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_QP_MULTICAST),\r
+                                                                                  &mc, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       qp = WvQpAcquire(pProvider, mc->Id.Id);\r
+       if (qp == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&qp->pPd->Lock);\r
+       for (entry = qp->McList.Flink; entry != &qp->McList; entry = entry->Flink) {\r
+               pmc = CONTAINING_RECORD(entry, WV_MULTICAST, Entry);\r
+\r
+               if (RtlCompareMemory(&pmc->Gid, &mc->Gid, sizeof(pmc->Gid)) == sizeof(pmc->Gid) &&\r
+                       pmc->Lid == (NET16) mc->Id.Data) {\r
+                       RemoveEntryList(&pmc->Entry);\r
+                       KeReleaseGuardedMutex(&qp->pPd->Lock);\r
+\r
+                       if (pmc->hVerbsMc != NULL) {\r
+                               qp->pVerbs->detach_mcast(pmc->hVerbsMc);\r
+                       }\r
+                       WvQpPut(qp);\r
+                       WvQpRelease(qp);\r
+\r
+                       ExFreePool(pmc);\r
+                       status = STATUS_SUCCESS;\r
+                       goto complete;\r
+               }\r
+       }\r
+       KeReleaseGuardedMutex(&qp->pPd->Lock);\r
+       WvQpRelease(qp);\r
+       status = STATUS_NOT_FOUND;\r
+\r
+complete:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvQpRemoveHandler(WV_QUEUE_PAIR *pQp)\r
+{\r
+       WV_MULTICAST            *mc;\r
+       LIST_ENTRY                      *entry;\r
+\r
+       for (entry = pQp->McList.Flink; entry != &pQp->McList; entry = entry->Flink) {\r
+               mc = CONTAINING_RECORD(entry, WV_MULTICAST, Entry);\r
+               pQp->pVerbs->detach_mcast(mc->hVerbsMc);\r
+               mc->hVerbsMc = NULL;\r
+       }\r
+\r
+       pQp->pVerbs->destroy_qp(pQp->hVerbsQp, 0);\r
+       pQp->hVerbsQp = NULL;\r
+}\r
+\r
+void WvQpCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                          *id;\r
+       WV_QUEUE_PAIR           *qp;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       qp = WvQpAcquire(pProvider, *id);\r
+       if (qp == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto out;\r
+       }\r
+\r
+       // CI does not yet support async operations\r
+       WvQpRelease(qp);\r
+\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
diff --git a/core/winverbs/kernel/wv_qp.h b/core/winverbs/kernel/wv_qp.h
new file mode 100644 (file)
index 0000000..680a6e4
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_QP_H_\r
+#define _WV_QP_H_\r
+\r
+#include <ntddk.h>\r
+#include <wdm.h>\r
+#include <iba\ib_types.h>\r
+#include <iba\ib_ci.h>\r
+\r
+#include "wv_pd.h"\r
+#include "wv_provider.h"\r
+#include "wv_cq.h"\r
+#include "wv_srq.h"\r
+\r
+typedef struct _WV_QUEUE_PAIR\r
+{\r
+       WV_PROVIDER                             *pProvider;\r
+       WV_PROTECTION_DOMAIN    *pPd;\r
+       WV_COMPLETION_QUEUE             *pSendCq;\r
+       WV_COMPLETION_QUEUE             *pReceiveCq;\r
+       WV_SHARED_RECEIVE_QUEUE *pSrq;\r
+       ci_interface_t                  *pVerbs;\r
+       ib_qp_handle_t                  hVerbsQp;\r
+       LIST_ENTRY                              Entry;\r
+       LIST_ENTRY                              McList;\r
+\r
+       KEVENT                                  Event;\r
+       LONG                                    Ref;\r
+\r
+}      WV_QUEUE_PAIR;\r
+\r
+void WvQpCreate(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvQpDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvQpFree(WV_QUEUE_PAIR *pQp);\r
+void WvQpRemoveHandler(WV_QUEUE_PAIR *pQp);\r
+\r
+void WvQpModify(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvQpQuery(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvQpAttach(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvQpDetach(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvQpCancel(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+\r
+#endif // _WV_QP_H_\r
diff --git a/core/winverbs/kernel/wv_srq.c b/core/winverbs/kernel/wv_srq.c
new file mode 100644 (file)
index 0000000..2be9e56
--- /dev/null
@@ -0,0 +1,391 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include "wv_driver.h"\r
+#include "wv_srq.h"\r
+#include "wv_ioctl.h"\r
+\r
+void WvSrqGet(WV_SHARED_RECEIVE_QUEUE *pSrq)\r
+{\r
+       InterlockedIncrement(&pSrq->Ref);\r
+}\r
+\r
+void WvSrqPut(WV_SHARED_RECEIVE_QUEUE *pSrq)\r
+{\r
+       if (InterlockedDecrement(&pSrq->Ref) == 0) {\r
+               KeSetEvent(&pSrq->Event, 0, FALSE);\r
+       }\r
+}\r
+\r
+WV_SHARED_RECEIVE_QUEUE *WvSrqAcquire(WV_PROVIDER *pProvider, UINT64 Id)\r
+{\r
+       WV_SHARED_RECEIVE_QUEUE *srq;\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       srq = IndexListAt(&pProvider->SrqIndex, (SIZE_T) Id);\r
+       if (srq != NULL && srq->hVerbsSrq != NULL) {\r
+               WvSrqGet(srq);\r
+       } else {\r
+               srq = NULL;\r
+               WvProviderEnableRemove(pProvider);\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       return srq;\r
+}\r
+\r
+void WvSrqRelease(WV_SHARED_RECEIVE_QUEUE *pSrq)\r
+{\r
+       WvProviderEnableRemove(pSrq->pProvider);\r
+       WvSrqPut(pSrq);\r
+}\r
+\r
+static void WvVerbsConvertSrq(ib_srq_attr_t *pVerbsAttr,\r
+                                                         WV_IO_SRQ_ATTRIBUTES *pAttr)\r
+{\r
+       pVerbsAttr->max_wr        = pAttr->MaxWr;\r
+       pVerbsAttr->max_sge       = pAttr->MaxSge;\r
+       pVerbsAttr->srq_limit = pAttr->SrqLimit;\r
+}\r
+\r
+static void WvSrqCompleteRequests(WV_SHARED_RECEIVE_QUEUE *pSrq, NTSTATUS ReqStatus)\r
+{\r
+       WDFREQUEST      request;\r
+       NTSTATUS        status;\r
+\r
+       WdfObjectAcquireLock(pSrq->Queue);\r
+       status = WdfIoQueueRetrieveNextRequest(pSrq->Queue, &request);\r
+\r
+       while (NT_SUCCESS(status)) {\r
+               WdfRequestComplete(request, ReqStatus);\r
+               status = WdfIoQueueRetrieveNextRequest(pSrq->Queue, &request);\r
+       }\r
+       WdfObjectReleaseLock(pSrq->Queue);\r
+}\r
+\r
+static void WvSrqEventHandler(ib_event_rec_t *pEvent)\r
+{\r
+       switch (pEvent->type) {\r
+       case IB_AE_SRQ_LIMIT_REACHED:\r
+               WvSrqCompleteRequests(pEvent->context, STATUS_ALERTED);\r
+               break;\r
+       case IB_AE_SRQ_QP_LAST_WQE_REACHED:\r
+               WvSrqCompleteRequests(pEvent->context, STATUS_NOTIFY_CLEANUP);\r
+               break;\r
+       default:\r
+               WvSrqCompleteRequests(pEvent->context, STATUS_UNEXPECTED_IO_ERROR);\r
+               break;\r
+       }\r
+}\r
+\r
+static NTSTATUS WvSrqAlloc(WV_PROTECTION_DOMAIN *pPd, WV_IO_SRQ_ATTRIBUTES *pAttr,\r
+                                                 WV_SHARED_RECEIVE_QUEUE **ppSrq, ci_umv_buf_t *pVerbsData)\r
+{\r
+       WV_SHARED_RECEIVE_QUEUE *srq;\r
+       ib_srq_attr_t                   attr;\r
+       ib_api_status_t                 ib_status;\r
+       NTSTATUS                                status;\r
+       WDF_IO_QUEUE_CONFIG             config;\r
+\r
+       srq = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_SHARED_RECEIVE_QUEUE), 'rsvw');\r
+       if (srq == NULL) {\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       srq->Ref = 1;\r
+       KeInitializeEvent(&srq->Event, NotificationEvent, FALSE);\r
+\r
+       WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);\r
+       status = WdfIoQueueCreate(ControlDevice, &config,\r
+                                                         WDF_NO_OBJECT_ATTRIBUTES, &srq->Queue);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       WvVerbsConvertSrq(&attr, pAttr);\r
+       ib_status = pPd->pVerbs->create_srq(pPd->hVerbsPd, srq, WvSrqEventHandler,\r
+                                                                               &attr, &srq->hVerbsSrq, pVerbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               goto err2;\r
+       }\r
+\r
+       srq->pPd = pPd;\r
+       srq->pProvider = pPd->pDevice->pProvider;\r
+       srq->pVerbs = pPd->pVerbs;\r
+       *ppSrq = srq;\r
+       return STATUS_SUCCESS;\r
+\r
+err2:\r
+       WdfObjectDelete(srq->Queue);\r
+err1:\r
+       ExFreePool(srq);\r
+       return STATUS_UNSUCCESSFUL;\r
+}\r
+\r
+void WvSrqCreate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_SRQ_ATTRIBUTES    *inAttr, *outAttr;\r
+       size_t                                  inlen, outlen;\r
+       WV_PROTECTION_DOMAIN    *pd;\r
+       WV_SHARED_RECEIVE_QUEUE *srq;\r
+       NTSTATUS                                status;\r
+       ci_umv_buf_t                    verbsData;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
+                                                                                  &inAttr, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
+                                                                                       &outAttr, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       pd = WvPdAcquire(pProvider, inAttr->Id.Id);\r
+       if (pd == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto err1;\r
+       }\r
+\r
+       WvInitVerbsData(&verbsData, inAttr->Id.VerbInfo, inlen - sizeof(WV_IO_SRQ_ATTRIBUTES),\r
+                                       outlen - sizeof(WV_IO_SRQ_ATTRIBUTES), inAttr + 1);\r
+       status = WvSrqAlloc(pd, inAttr, &srq, &verbsData);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err2;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       outAttr->Id.Id = IndexListInsertHead(&pProvider->SrqIndex, srq);\r
+       if (outAttr->Id.Id == 0) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err3;\r
+       }\r
+       InsertHeadList(&pd->SrqList, &srq->Entry);\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       WvProviderEnableRemove(pProvider);\r
+       outAttr->Id.VerbInfo = verbsData.status;\r
+       WdfRequestCompleteWithInformation(Request, status, outlen);\r
+       return;\r
+\r
+err3:\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+       WvSrqFree(srq);\r
+err2:\r
+       WvPdRelease(pd);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvSrqDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_SHARED_RECEIVE_QUEUE *srq;\r
+       UINT64                                  *id;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       srq = IndexListAt(&pProvider->SrqIndex, (SIZE_T) *id);\r
+       if (srq == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+       } else if (srq->Ref > 1) {\r
+               status = STATUS_ACCESS_DENIED;\r
+       } else {\r
+               IndexListRemove(&pProvider->SrqIndex, (SIZE_T) *id);\r
+               RemoveEntryList(&srq->Entry);\r
+               status = STATUS_SUCCESS;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       if (NT_SUCCESS(status)) {\r
+               WvSrqFree(srq);\r
+       }\r
+       WvProviderEnableRemove(pProvider);\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvSrqFree(WV_SHARED_RECEIVE_QUEUE *pSrq)\r
+{\r
+       if (InterlockedDecrement(&pSrq->Ref) > 0) {\r
+               KeWaitForSingleObject(&pSrq->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
+\r
+       if (pSrq->hVerbsSrq != NULL) {\r
+               pSrq->pVerbs->destroy_srq(pSrq->hVerbsSrq);\r
+       }\r
+\r
+       WdfIoQueuePurgeSynchronously(pSrq->Queue);\r
+       WdfObjectDelete(pSrq->Queue);\r
+       WvPdPut(pSrq->pPd);\r
+       ExFreePool(pSrq);\r
+}\r
+\r
+void WvSrqModify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_SRQ_ATTRIBUTES    *pinAttr, *poutAttr;\r
+       size_t                                  inlen, outlen, len = 0;\r
+       WV_SHARED_RECEIVE_QUEUE *srq;\r
+       ib_srq_attr_t                   attr;\r
+       NTSTATUS                                status;\r
+       ib_api_status_t                 ib_status;\r
+       ci_umv_buf_t                    verbsData;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
+                                                                                  &pinAttr, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
+                                                                                       &poutAttr, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       srq = WvSrqAcquire(pProvider, pinAttr->Id.Id);\r
+       if (srq == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WvInitVerbsData(&verbsData, pinAttr->Id.VerbInfo, inlen - sizeof(WV_IO_SRQ_ATTRIBUTES),\r
+                                       outlen - sizeof(WV_IO_SRQ_ATTRIBUTES), pinAttr + 1);\r
+       WvVerbsConvertSrq(&attr, pinAttr);\r
+       ib_status = srq->pVerbs->modify_srq(srq->hVerbsSrq, &attr,\r
+                                                                               IB_SRQ_MAX_WR | IB_SRQ_LIMIT, &verbsData);\r
+       WvSrqRelease(srq);\r
+\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       len = outlen;\r
+       poutAttr->Id.VerbInfo = verbsData.status;\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+void WvSrqQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_SRQ_ATTRIBUTES    *pinAttr, *poutAttr;\r
+       size_t                                  inlen, outlen, len = 0;\r
+       WV_SHARED_RECEIVE_QUEUE *srq;\r
+       ib_srq_attr_t                   attr;\r
+       NTSTATUS                                status;\r
+       ci_umv_buf_t                    verbsData;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
+                                                                                  &pinAttr, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
+                                                                                       &poutAttr, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       srq = WvSrqAcquire(pProvider, pinAttr->Id.Id);\r
+       if (srq == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WvInitVerbsData(&verbsData, pinAttr->Id.VerbInfo, inlen - sizeof(WV_IO_SRQ_ATTRIBUTES),\r
+                                       outlen - sizeof(WV_IO_SRQ_ATTRIBUTES), pinAttr + 1);\r
+       srq->pVerbs->query_srq(srq->hVerbsSrq, &attr, &verbsData);\r
+       WvSrqRelease(srq);\r
+\r
+       poutAttr->Id.VerbInfo = verbsData.status;\r
+       poutAttr->MaxWr = attr.max_wr;\r
+       poutAttr->MaxSge = attr.max_sge;\r
+       poutAttr->SrqLimit = attr.srq_limit;\r
+       len = outlen;\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+void WvSrqNotify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                                  *id;\r
+       WV_SHARED_RECEIVE_QUEUE *srq;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       srq = WvSrqAcquire(pProvider, *id);\r
+       if (srq == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto out;\r
+       }\r
+\r
+       WdfObjectAcquireLock(srq->Queue);\r
+       status = WdfRequestForwardToIoQueue(Request, srq->Queue);\r
+       WdfObjectReleaseLock(srq->Queue);\r
+       WvSrqRelease(srq);\r
+\r
+out:\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
+}\r
+\r
+void WvSrqCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                                  *id;\r
+       WV_SHARED_RECEIVE_QUEUE *srq;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       srq = WvSrqAcquire(pProvider, *id);\r
+       if (srq == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto out;\r
+       }\r
+\r
+       WvSrqCompleteRequests(srq, STATUS_CANCELLED);\r
+       WvSrqRelease(srq);\r
+\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
diff --git a/core/winverbs/kernel/wv_srq.h b/core/winverbs/kernel/wv_srq.h
new file mode 100644 (file)
index 0000000..97bb93d
--- /dev/null
@@ -0,0 +1,71 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_SRQ_H_\r
+#define _WV_SRQ_H_\r
+\r
+#include <ntddk.h>\r
+#include <wdm.h>\r
+#include <iba\ib_types.h>\r
+#include <iba\ib_ci.h>\r
+\r
+#include "wv_pd.h"\r
+#include "wv_provider.h"\r
+\r
+typedef struct _WV_SHARED_RECEIVE_QUEUE\r
+{\r
+       WV_PROVIDER                             *pProvider;\r
+       WV_PROTECTION_DOMAIN    *pPd;\r
+       ci_interface_t                  *pVerbs;\r
+       ib_srq_handle_t                 hVerbsSrq;\r
+       LIST_ENTRY                              Entry;\r
+\r
+       KEVENT                                  Event;\r
+       LONG                                    Ref;\r
+       WDFQUEUE                                Queue;\r
+\r
+}      WV_SHARED_RECEIVE_QUEUE;\r
+\r
+void WvSrqCreate(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvSrqDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvSrqFree(WV_SHARED_RECEIVE_QUEUE *pSrq);\r
+\r
+WV_SHARED_RECEIVE_QUEUE *WvSrqAcquire(WV_PROVIDER *pProvider, UINT64 Id);\r
+void WvSrqRelease(WV_SHARED_RECEIVE_QUEUE *pSrq);\r
+void WvSrqGet(WV_SHARED_RECEIVE_QUEUE *pSrq);\r
+void WvSrqPut(WV_SHARED_RECEIVE_QUEUE *pSrq);\r
+\r
+void WvSrqModify(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvSrqQuery(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvSrqNotify(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvSrqCancel(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+\r
+#endif // _WV_SRQ_H_\r
diff --git a/core/winverbs/user/SOURCES b/core/winverbs/user/SOURCES
new file mode 100644 (file)
index 0000000..101315e
--- /dev/null
@@ -0,0 +1,39 @@
+!if $(FREEBUILD)\r
+TARGETNAME = winverbs\r
+!else\r
+TARGETNAME = winverbsd\r
+!endif\r
+\r
+TARGETPATH = ..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = DYNLINK\r
+\r
+!if $(_NT_TOOLS_VERSION) == 0x700\r
+DLLDEF = $O\wv_exports.def\r
+!else\r
+DLLDEF = $(OBJ_PATH)\$O\wv_exports.def\r
+!endif\r
+\r
+DLLENTRY = DllMain\r
+USE_NTDLL = 1\r
+\r
+SOURCES = \\r
+       winverbs.rc             \\r
+       wv_main.cpp             \\r
+       wv_base.cpp             \\r
+       wv_cq.cpp               \\r
+       wv_device.cpp   \\r
+       wv_ep.cpp               \\r
+       wv_listen.cpp   \\r
+       wv_pd.cpp               \\r
+       wv_provider.cpp \\r
+       wv_qp.cpp               \\r
+       wv_srq.cpp              \\r
+       wv_uverbs.cpp\r
+\r
+INCLUDES = ..;..\..\..\inc;..\..\..\inc\user;\r
+\r
+USER_C_FLAGS = $(USER_C_FLAGS) -DEXPORT_WV_SYMBOLS\r
+\r
+TARGETLIBS = \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\uuid.lib\r
diff --git a/core/winverbs/user/makefile b/core/winverbs/user/makefile
new file mode 100644 (file)
index 0000000..bffacaa
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the OpenIB Windows project.\r
+#\r
+\r
+!INCLUDE ..\..\..\inc\openib.def\r
diff --git a/core/winverbs/user/winverbs.rc b/core/winverbs/user/winverbs.rc
new file mode 100644 (file)
index 0000000..1be0d5c
--- /dev/null
@@ -0,0 +1,46 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+\r
+#include <oib_ver.h>\r
+\r
+#define VER_FILETYPE                   VFT_DLL\r
+#define VER_FILESUBTYPE                        VFT2_UNKNOWN\r
+\r
+#ifdef _DEBUG_\r
+#define VER_FILEDESCRIPTION_STR                "WinVerbs (Debug)"\r
+#define VER_INTERNALNAME_STR           "winverbsd.dll"\r
+#define VER_ORIGINALFILENAME_STR       "winverbsd.dll"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR                "WinVerbs"\r
+#define VER_INTERNALNAME_STR           "winverbs.dll"\r
+#define VER_ORIGINALFILENAME_STR       "winverbs.dll"\r
+#endif\r
+\r
+#include <common.ver>\r
diff --git a/core/winverbs/user/wv_base.cpp b/core/winverbs/user/wv_base.cpp
new file mode 100644 (file)
index 0000000..d47fd6f
--- /dev/null
@@ -0,0 +1,101 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include <iba\ib_ci.h>\r
+#include "wv_base.h"\r
+#include "wv_cq.h"\r
+#include "wv_qp.h"\r
+#include "wv_ioctl.h"\r
+\r
+CWVBase::CWVBase()\r
+{\r
+       InitializeCriticalSection(&m_CritSec);\r
+       m_Overlap.hEvent = NULL;\r
+       m_nRef = 1;\r
+       m_Id = 0;\r
+}\r
+\r
+CWVBase::~CWVBase()\r
+{\r
+       if (m_Overlap.hEvent != NULL) {\r
+               CloseHandle(m_Overlap.hEvent);\r
+       }\r
+}\r
+\r
+STDMETHODIMP CWVBase::\r
+Init(void)\r
+{\r
+       m_Overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
+       return (m_Overlap.hEvent != NULL) ? WV_SUCCESS : WV_INSUFFICIENT_RESOURCES;\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVBase::\r
+AddRef(void)\r
+{\r
+       return InterlockedIncrement(&m_nRef);\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVBase::\r
+Release(void)\r
+{\r
+       ULONG ref;\r
+\r
+       ref = (ULONG) InterlockedDecrement(&m_nRef);\r
+       if (ref == 0) {\r
+               Delete();\r
+       }\r
+       return ref;\r
+}\r
+\r
+BOOL CWVBase::\r
+WvDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,\r
+                                 LPVOID lpInBuffer, DWORD nInBufferSize,\r
+                                 LPVOID lpOutBuffer, DWORD nOutBufferSize,\r
+                                 LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)\r
+{\r
+       BOOL ret;\r
+\r
+       if (lpOverlapped == NULL) {\r
+               EnterCriticalSection(&m_CritSec);\r
+               DeviceIoControl(hDevice, dwIoControlCode,\r
+                                               lpInBuffer, nInBufferSize,\r
+                                               lpOutBuffer, nOutBufferSize,\r
+                                               lpBytesReturned, &m_Overlap);\r
+\r
+               ret = GetOverlappedResult(hDevice, &m_Overlap, lpBytesReturned, TRUE);\r
+               LeaveCriticalSection(&m_CritSec);\r
+       } else {\r
+               ret = DeviceIoControl(hDevice, dwIoControlCode,\r
+                                                         lpInBuffer, nInBufferSize,\r
+                                                         lpOutBuffer, nOutBufferSize,\r
+                                                         lpBytesReturned, lpOverlapped);\r
+       }\r
+\r
+       return ret;\r
+}\r
diff --git a/core/winverbs/user/wv_base.h b/core/winverbs/user/wv_base.h
new file mode 100644 (file)
index 0000000..ef4aa2e
--- /dev/null
@@ -0,0 +1,96 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_BASE_H_\r
+#define _WV_BASE_H_\r
+\r
+#include <windows.h>\r
+#include <rdma\winverbs.h>\r
+#include <winioctl.h>\r
+\r
+#include <iba\ib_types.h>\r
+#include <iba\ib_uvp.h>\r
+\r
+HRESULT WvConvertIbStatus(ib_api_status_t status);\r
+HRESULT WvGetUserVerbs(HMODULE hLib, uvp_interface_t *pVerbs);\r
+\r
+\r
+class CWVBase\r
+{\r
+public:\r
+       CWVBase();\r
+       ~CWVBase();\r
+       STDMETHODIMP_(ULONG) AddRef();\r
+       STDMETHODIMP_(ULONG) Release();\r
+\r
+       STDMETHODIMP Init();\r
+       virtual void Delete() {};\r
+       BOOL WvDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,\r
+                                                  LPVOID lpInBuffer, DWORD nInBufferSize,\r
+                                                  LPVOID lpOutBuffer, DWORD nOutBufferSize,\r
+                                                  LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped);\r
+\r
+       HANDLE                                  m_hFile;\r
+       volatile LONG                   m_nRef;\r
+       UINT64                                  m_Id;\r
+\r
+protected:\r
+       OVERLAPPED                              m_Overlap;\r
+       CRITICAL_SECTION                m_CritSec;\r
+};\r
+\r
+\r
+#if defined(_WIN64)\r
+       #define WvConvertSgl(pSgl, nSge)        ((ib_local_ds_t *) pSgl)\r
+       #define WvConvertSends(pSend)           ((ib_send_wr_t *) pSend)\r
+#else\r
+       static inline ib_local_ds_t *WvConvertSgl(WV_SGE* pSgl, SIZE_T nSge)\r
+       {\r
+               SIZE_T n;\r
+\r
+               for (n = 0; n < nSge; n++) {\r
+                       pSgl[n].Reserved = 0;\r
+               }\r
+               return (ib_local_ds_t *) pSgl;\r
+       }\r
+\r
+       static inline ib_send_wr_t *WvConvertSends(WV_SEND_REQUEST *pSend)\r
+       {\r
+               WV_SEND_REQUEST *preq;\r
+\r
+               for (preq = pSend; preq != NULL; preq = preq->pNext) {\r
+                       WvConvertSgl(preq->pSgl, preq->nSge);\r
+               }\r
+               return (ib_send_wr_t *) pSend;\r
+       }\r
+#endif (_WIN64)\r
+\r
+#endif // _WV_BASE_H_
\ No newline at end of file
diff --git a/core/winverbs/user/wv_cq.cpp b/core/winverbs/user/wv_cq.cpp
new file mode 100644 (file)
index 0000000..fafce97
--- /dev/null
@@ -0,0 +1,274 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include <iba\ib_ci.h>\r
+#include "wv_memory.h"\r
+#include "wv_cq.h"\r
+#include "wv_qp.h"\r
+#include "wv_ioctl.h"\r
+\r
+CWVCompletionQueue::CWVCompletionQueue(CWVDevice *pDevice)\r
+{\r
+       pDevice->AddRef();\r
+       m_pDevice = pDevice;\r
+       m_pVerbs = &pDevice->m_Verbs;\r
+       m_hFile = pDevice->m_hFile;\r
+\r
+       m_hVerbsCq = NULL;\r
+}\r
+\r
+STDMETHODIMP CWVCompletionQueue::\r
+Create(SIZE_T *pEntries)\r
+{\r
+       WV_IO_ID                *pId;\r
+       DWORD                   bytes;\r
+       ib_api_status_t stat;\r
+       HRESULT                 hr;\r
+       ci_umv_buf_t    verbsData;\r
+       CWVBuffer               buf;\r
+\r
+       stat = m_pVerbs->pre_create_cq(m_pDevice->m_hVerbsDevice, (UINT32 *) pEntries,\r
+                                                                  &verbsData, &m_hVerbsCq);\r
+       if (stat != IB_SUCCESS) {\r
+               return WvConvertIbStatus(stat);\r
+       }\r
+\r
+       bytes = sizeof WV_IO_ID + max(verbsData.input_size, verbsData.output_size);\r
+       pId = (WV_IO_ID *) buf.Get(bytes);\r
+       if (pId == NULL) {\r
+               hr = WV_NO_MEMORY;\r
+               goto post;\r
+       }\r
+\r
+       pId->Id = m_pDevice->m_Id;\r
+       pId->VerbInfo = verbsData.command;\r
+       pId->Data = (UINT32) *pEntries;\r
+       RtlCopyMemory(pId + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,\r
+                                 verbsData.input_size);\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_CQ_CREATE,\r
+                                                 pId, sizeof WV_IO_ID + verbsData.input_size,\r
+                                                 pId, sizeof WV_IO_ID + verbsData.output_size,\r
+                                                 &bytes, NULL)) {\r
+               hr = WV_SUCCESS;\r
+               m_Id = pId->Id;\r
+               *pEntries = pId->Data;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       verbsData.status = pId->VerbInfo;\r
+       RtlCopyMemory((void *) (ULONG_PTR) verbsData.p_inout_buf, pId + 1,\r
+                                 verbsData.output_size);\r
+       buf.Put();\r
+\r
+post:\r
+       m_pVerbs->post_create_cq(m_pDevice->m_hVerbsDevice, (ib_api_status_t) hr,\r
+                                                        (UINT32) *pEntries, &m_hVerbsCq, &verbsData);\r
+       return hr;\r
+}\r
+\r
+CWVCompletionQueue::~CWVCompletionQueue()\r
+{\r
+       DWORD   bytes;\r
+       HRESULT hr;\r
+\r
+       if (m_Id != NULL) {\r
+               m_pVerbs->pre_destroy_cq(m_hVerbsCq);\r
+               hr = WvDeviceIoControl(m_hFile, WV_IOCTL_CQ_DESTROY, &m_Id, sizeof m_Id,\r
+                                                          NULL, 0, &bytes, NULL) ?\r
+                                                          WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
+               m_pVerbs->post_destroy_cq(m_hVerbsCq, (ib_api_status_t) hr);\r
+       }\r
+       m_pDevice->Release();\r
+}\r
+\r
+STDMETHODIMP CWVCompletionQueue::\r
+QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
+{\r
+       if (riid != IID_IUnknown && riid != IID_IWVCompletionQueue) {\r
+               *ppvObj = NULL;\r
+               return E_NOINTERFACE;\r
+       }\r
+\r
+       *ppvObj = this;\r
+       AddRef();\r
+       return WV_SUCCESS;\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVCompletionQueue::\r
+AddRef(void)\r
+{\r
+       return CWVBase::AddRef();\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVCompletionQueue::\r
+Release(void)\r
+{\r
+       return CWVBase::Release();\r
+}\r
+\r
+STDMETHODIMP CWVCompletionQueue::\r
+CancelOverlappedRequests(void)\r
+{\r
+       DWORD   bytes;\r
+\r
+       return WvDeviceIoControl(m_hFile, WV_IOCTL_CQ_CANCEL, &m_Id, sizeof m_Id,\r
+                                                        NULL, 0, &bytes, NULL) ?\r
+                                                        WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
+}\r
+\r
+STDMETHODIMP CWVCompletionQueue::\r
+GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                       DWORD *pNumberOfBytesTransferred, BOOL bWait)\r
+{\r
+       return ::GetOverlappedResult(m_hFile, pOverlapped,\r
+                                                                pNumberOfBytesTransferred, bWait);\r
+}\r
+\r
+STDMETHODIMP CWVCompletionQueue::\r
+Resize(SIZE_T* pEntries)\r
+{\r
+       WV_IO_ID                *pId;\r
+       DWORD                   bytes;\r
+       ib_api_status_t stat;\r
+       HRESULT                 hr;\r
+       ci_umv_buf_t    verbsData;\r
+       CWVBuffer               buf;\r
+\r
+       stat = m_pVerbs->pre_resize_cq(m_hVerbsCq, (UINT32 *) pEntries, &verbsData);\r
+       if (stat != IB_SUCCESS) {\r
+               return WvConvertIbStatus(stat);\r
+       }\r
+\r
+       bytes = sizeof WV_IO_ID + max(verbsData.input_size, verbsData.output_size);\r
+       pId = (WV_IO_ID *) buf.Get(bytes);\r
+       if (pId == NULL) {\r
+               hr = WV_NO_MEMORY;\r
+               goto post;\r
+       }\r
+\r
+       pId->Id = m_Id;\r
+       pId->VerbInfo = verbsData.command;\r
+       pId->Data = (UINT32) *pEntries;\r
+       RtlCopyMemory(pId + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,\r
+                                 verbsData.input_size);\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_CQ_RESIZE,\r
+                                                 pId, sizeof WV_IO_ID + verbsData.input_size,\r
+                                                 pId, sizeof WV_IO_ID + verbsData.output_size,\r
+                                                 &bytes, NULL)) {\r
+               hr = WV_SUCCESS;\r
+               *pEntries = pId->Data;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       verbsData.status = pId->VerbInfo;\r
+       RtlCopyMemory((void *) (ULONG_PTR) verbsData.p_inout_buf, pId + 1,\r
+                                 verbsData.output_size);\r
+       buf.Put();\r
+\r
+post:\r
+       m_pVerbs->post_resize_cq(m_hVerbsCq, (ib_api_status_t) hr,\r
+                                                        (UINT32) *pEntries, &verbsData);\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CWVCompletionQueue::\r
+Peek(SIZE_T* pCompletedEntries)\r
+{\r
+       ib_api_status_t stat;\r
+\r
+       stat = m_pVerbs->peek_cq(m_hVerbsCq, (UINT32 *) pCompletedEntries);\r
+       if (stat != IB_SUCCESS) {\r
+               return WvConvertIbStatus(stat);\r
+       }\r
+\r
+       return WV_SUCCESS;\r
+}\r
+\r
+STDMETHODIMP CWVCompletionQueue::\r
+Notify(WV_CQ_NOTIFY_TYPE Type, OVERLAPPED* pOverlapped)\r
+{\r
+       WV_IO_ID        id;\r
+       DWORD           bytes;\r
+       HRESULT         hr;\r
+\r
+       id.Id = m_Id;\r
+       id.Data = Type;\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_CQ_NOTIFY, &id, sizeof id,\r
+                                                 NULL, 0, &bytes, pOverlapped)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       if (SUCCEEDED(hr) || hr == WV_IO_PENDING) {\r
+               switch (Type) {\r
+               case WvCqSolicited:\r
+                       m_pVerbs->rearm_cq(m_hVerbsCq, 1);\r
+                       break;\r
+               case WvCqNextCompletion:\r
+                       m_pVerbs->rearm_cq(m_hVerbsCq, 0);\r
+                       break;\r
+               default:\r
+                       break;\r
+               }\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CWVCompletionQueue::\r
+BatchNotify(SIZE_T CompletedEntries, OVERLAPPED* pOverlapped)\r
+{\r
+       DWORD           bytes;\r
+       HRESULT         hr;\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_CQ_NOTIFY, &m_Id, sizeof m_Id,\r
+                                                 NULL, 0, &bytes, pOverlapped)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       if (SUCCEEDED(hr) || hr == WV_IO_PENDING) {\r
+               m_pVerbs->rearm_n_cq(m_hVerbsCq, (UINT32) CompletedEntries);\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP_(SIZE_T) CWVCompletionQueue::\r
+Poll(WV_COMPLETION Completions[], SIZE_T Entries)\r
+{\r
+       // WV_COMPLETION aligns with uvp_wc_t by design.\r
+       return m_pVerbs->poll_cq_array(m_hVerbsCq, (UINT32) Entries, (uvp_wc_t *) Completions);\r
+}\r
diff --git a/core/winverbs/user/wv_cq.h b/core/winverbs/user/wv_cq.h
new file mode 100644 (file)
index 0000000..717d944
--- /dev/null
@@ -0,0 +1,103 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_CQ_H_\r
+#define _WV_CQ_H_\r
+\r
+#include <rdma\winverbs.h>\r
+#include "wv_device.h"\r
+#include "wv_base.h"\r
+\r
+class CWVCompletionQueue : IWVCompletionQueue, public CWVBase\r
+{\r
+public:\r
+       // IUnknown methods\r
+       STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);\r
+       STDMETHODIMP_(ULONG) AddRef();\r
+       STDMETHODIMP_(ULONG) Release();\r
+\r
+       // IWVOverlapped methods\r
+       STDMETHODIMP CancelOverlappedRequests();\r
+       STDMETHODIMP GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                                                        DWORD *pNumberOfBytesTransferred, BOOL bWait);\r
+\r
+       // IWVCompletionQueue methods\r
+       STDMETHODIMP Resize(SIZE_T* pEntries);\r
+       STDMETHODIMP Peek(SIZE_T* pCompletedEntries);\r
+       STDMETHODIMP Notify(WV_CQ_NOTIFY_TYPE Type, OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP BatchNotify(SIZE_T CompletedEntries, OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP_(SIZE_T) Poll(WV_COMPLETION Completions[], SIZE_T Entries);\r
+\r
+       CWVCompletionQueue(CWVDevice *pDevice);\r
+       ~CWVCompletionQueue();\r
+       void Delete() {delete this;}\r
+       static STDMETHODIMP\r
+       CreateInstance(CWVDevice *pDevice, SIZE_T *pEntries, IWVCompletionQueue** ppCq)\r
+       {\r
+               HRESULT hr;\r
+               CWVCompletionQueue *cq;\r
+\r
+               cq = new CWVCompletionQueue(pDevice);\r
+               if (cq == NULL) {\r
+                       hr = WV_NO_MEMORY;\r
+                       goto err1;\r
+               }\r
+\r
+               hr = cq->Init();\r
+               if (FAILED(hr)) {\r
+                       goto err2;\r
+               }\r
+\r
+               hr = cq->Create(pEntries);\r
+               if (FAILED(hr)) {\r
+                       goto err2;\r
+               }\r
+\r
+               *ppCq = cq;\r
+               return WV_SUCCESS;\r
+\r
+       err2:\r
+               cq->Release();\r
+       err1:\r
+               *ppCq = NULL;\r
+               return hr;\r
+       }\r
+\r
+       CWVDevice               *m_pDevice;\r
+       uvp_interface_t *m_pVerbs;\r
+\r
+       ib_cq_handle_t  m_hVerbsCq;\r
+\r
+protected:\r
+       STDMETHODIMP Create(SIZE_T *pEntries);\r
+};\r
+\r
+#endif //_WV_CQ_H_
\ No newline at end of file
diff --git a/core/winverbs/user/wv_device.cpp b/core/winverbs/user/wv_device.cpp
new file mode 100644 (file)
index 0000000..a90b214
--- /dev/null
@@ -0,0 +1,385 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include <windows.h>\r
+#include <iba\ib_ci.h>\r
+#include "wv_memory.h"\r
+#include "wv_device.h"\r
+#include "wv_cq.h"\r
+#include "wv_ioctl.h"\r
+#include "wv_pd.h"\r
+\r
+#ifdef _DEBUG_\r
+static char *WV_LIB_EXTENSION = "d.dll";\r
+#else\r
+static char *WV_LIB_EXTENSION = ".dll";\r
+#endif\r
+\r
+CWVDevice::CWVDevice(CWVProvider *pProvider)\r
+{\r
+       pProvider->AddRef();\r
+       m_pProvider = pProvider;\r
+       m_hFile = pProvider->m_hFile;\r
+\r
+       m_hVerbsDevice = NULL;\r
+       m_hLib = NULL;\r
+}\r
+\r
+// Destructor will do necessary cleanup.\r
+STDMETHODIMP CWVDevice::\r
+Open(NET64 Guid)\r
+{\r
+       char                            libname[WV_MAX_LIB_NAME];\r
+       WV_IO_ID                        *pId;\r
+       DWORD                           bytes;\r
+       ib_api_status_t         stat;\r
+       HRESULT                         hr;\r
+       ci_umv_buf_t            verbsData;\r
+       CWVBuffer                       buf;\r
+\r
+       m_Guid = Guid;\r
+       if (!WvDeviceIoControl(m_hFile, WV_IOCTL_LIBRARY_QUERY, &m_Guid,\r
+                                                  (DWORD) sizeof m_Guid, libname,\r
+                                                  WV_MAX_LIB_NAME - strlen(WV_LIB_EXTENSION),\r
+                                                  &bytes, NULL)) {\r
+               return HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       strcpy(libname + bytes - 1, WV_LIB_EXTENSION);\r
+       m_hLib = LoadLibrary(libname);\r
+       if (m_hLib == NULL) {\r
+               return HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       hr = WvGetUserVerbs(m_hLib, &m_Verbs);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       stat = m_Verbs.pre_open_ca(m_Guid, &verbsData, &m_hVerbsDevice);\r
+       if (stat != IB_SUCCESS) {\r
+               return WvConvertIbStatus(stat);\r
+       }\r
+\r
+       bytes = sizeof WV_IO_ID + max(verbsData.input_size, verbsData.output_size);\r
+       pId = (WV_IO_ID *) buf.Get(bytes);\r
+       if (pId == NULL) {\r
+               hr = WV_NO_MEMORY;\r
+               goto post;\r
+       }\r
+\r
+       pId->Id = m_Guid;\r
+       pId->VerbInfo = verbsData.command;\r
+       RtlCopyMemory(pId + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,\r
+                                 verbsData.input_size);\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_DEVICE_OPEN,\r
+                                                 pId, sizeof WV_IO_ID + verbsData.input_size,\r
+                                                 pId, sizeof WV_IO_ID + verbsData.output_size,\r
+                                                 &bytes, NULL)) {\r
+               m_Id = pId->Id;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       verbsData.status = pId->VerbInfo;\r
+       RtlCopyMemory((void *) (ULONG_PTR) verbsData.p_inout_buf, pId + 1,\r
+                                 verbsData.output_size);\r
+       buf.Put();\r
+\r
+post:\r
+       stat = m_Verbs.post_open_ca(m_Guid, (ib_api_status_t) hr,\r
+                                                               &m_hVerbsDevice, &verbsData);\r
+       if (SUCCEEDED(hr) && stat != IB_SUCCESS) {\r
+               hr = WvConvertIbStatus(stat);\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
+CWVDevice::~CWVDevice()\r
+{\r
+       DWORD   bytes;\r
+       HRESULT hr;\r
+\r
+       if (m_hVerbsDevice != NULL) {\r
+               m_Verbs.pre_close_ca(m_hVerbsDevice);\r
+               hr = WvDeviceIoControl(m_hFile, WV_IOCTL_DEVICE_CLOSE, &m_Id, sizeof m_Id,\r
+                                                          NULL, 0, &bytes, NULL) ?\r
+                                                          WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
+               m_Verbs.post_close_ca(m_hVerbsDevice, (ib_api_status_t) hr);\r
+       }\r
+\r
+       if (m_hLib != NULL) {\r
+               FreeLibrary(m_hLib);\r
+       }\r
+       m_pProvider->Release();\r
+}\r
+\r
+STDMETHODIMP CWVDevice::\r
+QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
+{\r
+       if (riid != IID_IUnknown && riid != IID_IWVDevice) {\r
+               *ppvObj = NULL;\r
+               return E_NOINTERFACE;\r
+       }\r
+\r
+       *ppvObj = this;\r
+       AddRef();\r
+       return WV_SUCCESS;\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVDevice::\r
+AddRef(void)\r
+{\r
+       return CWVBase::AddRef();\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVDevice::\r
+Release(void)\r
+{\r
+       return CWVBase::Release();\r
+}\r
+\r
+STDMETHODIMP CWVDevice::\r
+CancelOverlappedRequests(void)\r
+{\r
+       DWORD   bytes;\r
+\r
+       return WvDeviceIoControl(m_hFile, WV_IOCTL_DEVICE_CANCEL, &m_Id, sizeof m_Id,\r
+                                                        NULL, 0, &bytes, NULL) ?\r
+                                                        WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
+}\r
+\r
+STDMETHODIMP CWVDevice::\r
+GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                       DWORD *pNumberOfBytesTransferred, BOOL bWait)\r
+{\r
+       return ::GetOverlappedResult(m_hFile, pOverlapped,\r
+                                                                pNumberOfBytesTransferred, bWait);\r
+}\r
+\r
+STDMETHODIMP CWVDevice::\r
+Query(WV_DEVICE_ATTRIBUTES* pAttributes)\r
+{\r
+       WV_IO_DEVICE_ATTRIBUTES attr;\r
+       DWORD                                   bytes;\r
+\r
+       if (!WvDeviceIoControl(m_hFile, WV_IOCTL_DEVICE_QUERY, &m_Id, sizeof m_Id,\r
+                                                  &attr, sizeof attr, &bytes, NULL)) {\r
+               return HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       pAttributes->FwVersion = attr.FwVersion;\r
+       pAttributes->NodeGuid = attr.NodeGuid;\r
+       pAttributes->SystemImageGuid = attr.SystemImageGuid;\r
+       pAttributes->VendorId = attr.VendorId;\r
+       pAttributes->VendorPartId = attr.VendorPartId;\r
+       pAttributes->HwVersion = attr.HwVersion;\r
+       pAttributes->CapabilityFlags = attr.CapabilityFlags;\r
+       pAttributes->AtomicCapability = (WV_ATOMIC_CAPABILITIES) attr.AtomicCapability;\r
+       pAttributes->PageSizeCapabilityFlags = attr.PageSizeCapabilityFlags;\r
+       pAttributes->MaxMrSize = (SIZE_T) attr.MaxMrSize;\r
+       pAttributes->MaxQp = attr.MaxQp;\r
+       pAttributes->MaxQpWr = attr.MaxQpWr;\r
+       pAttributes->MaxSge = attr.MaxSge;\r
+       pAttributes->MaxCq = attr.MaxCq;\r
+       pAttributes->MaxCqEntries = attr.MaxCqEntries;\r
+       pAttributes->MaxMr = attr.MaxMr;\r
+       pAttributes->MaxPd = attr.MaxPd;\r
+       pAttributes->MaxQpResponderResources = attr.MaxQpResponderResources;\r
+       pAttributes->MaxResponderResources = attr.MaxResponderResources;\r
+       pAttributes->MaxQpInitiatorDepth = attr.MaxQpInitiatorDepth;\r
+       pAttributes->MaxInlineSend = attr.MaxInlineSend;\r
+       pAttributes->MaxMw = attr.MaxMw;\r
+       pAttributes->MaxMulticast = attr.MaxMulticast;\r
+       pAttributes->MaxQpAttach = attr.MaxQpAttach;\r
+       pAttributes->MaxMulticastQp = attr.MaxMulticastQp;\r
+       pAttributes->MaxAh = attr.MaxAh;\r
+       pAttributes->MaxFmr = attr.MaxFmr;\r
+       pAttributes->MaxMapPerFmr = attr.MaxMapPerFmr;\r
+       pAttributes->MaxSrq = attr.MaxSrq;\r
+       pAttributes->MaxSrqWr = attr.MaxSrqWr;\r
+       pAttributes->MaxSrqSge = attr.MaxSrqSge;\r
+       pAttributes->MaxPkeys = attr.MaxPkeys;\r
+       pAttributes->DeviceType = (WV_DEVICE_TYPE) attr.DeviceType;\r
+       pAttributes->LocalAckDelay = attr.LocalAckDelay;\r
+       pAttributes->PhysPortCount = attr.PhysPortCount;\r
+\r
+       return WV_SUCCESS;\r
+}\r
+\r
+STDMETHODIMP CWVDevice::\r
+QueryPort(UINT8 PortNumber, WV_PORT_ATTRIBUTES* pAttributes)\r
+{\r
+       WV_IO_DEVICE_PORT_QUERY query;\r
+       DWORD                                   bytes;\r
+\r
+       query.Id = m_Id;\r
+       query.PortNumber = PortNumber;\r
+       RtlZeroMemory(&query.Reserved, sizeof query.Reserved);\r
+\r
+       if (!WvDeviceIoControl(m_hFile, WV_IOCTL_DEVICE_PORT_QUERY, &query,\r
+                                                  sizeof query, pAttributes, sizeof *pAttributes,\r
+                                                  &bytes, NULL)) {\r
+               return HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       return WV_SUCCESS;\r
+}\r
+\r
+STDMETHODIMP CWVDevice::\r
+QueryGid(UINT8 PortNumber, DWORD Index, WV_GID* pGid)\r
+{\r
+       WV_IO_DEVICE_PORT_QUERY query;\r
+       WV_GID                                  *gidtable;\r
+       DWORD                                   ngid, bytes;\r
+       HRESULT                                 hr;\r
+       CWVBuffer                               buf;\r
+\r
+       bytes = sizeof WV_GID * (Index + 1);\r
+       gidtable = (WV_GID *) buf.Get(bytes);\r
+       if (gidtable == NULL) {\r
+               return WV_NO_MEMORY;\r
+       }\r
+\r
+       query.Id = m_Id;\r
+       query.PortNumber = PortNumber;\r
+       RtlZeroMemory(&query.Reserved, sizeof query.Reserved);\r
+\r
+       if (!WvDeviceIoControl(m_hFile, WV_IOCTL_DEVICE_GID_QUERY, &query,\r
+                                                  sizeof query, gidtable, bytes, &bytes, NULL)) {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+               goto out;\r
+       }\r
+\r
+       ngid = bytes / sizeof WV_GID;\r
+       if (Index >= ngid) {\r
+               hr = WV_INVALID_PARAMETER_2;\r
+               goto out;\r
+       }\r
+       *pGid = gidtable[Index];\r
+       hr = WV_SUCCESS;\r
+\r
+out:\r
+       buf.Put();\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CWVDevice::\r
+FindGidIndex(UINT8 PortNumber, WV_GID *pGid, UINT16 *pIndex)\r
+{\r
+       WV_GID  gid;\r
+       DWORD   index;\r
+       HRESULT hr;\r
+\r
+       for (index = 0; true; index++) {\r
+               hr = QueryGid(PortNumber, index, &gid);\r
+               if (FAILED(hr)) {\r
+                       break;\r
+               }\r
+\r
+               if (RtlCompareMemory(pGid, &gid, sizeof(gid)) == sizeof(gid)) {\r
+                       *pIndex = (UINT16) index;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CWVDevice::\r
+QueryPkey(UINT8 PortNumber, DWORD Index, NET16* pPkey)\r
+{\r
+       WV_IO_DEVICE_PORT_QUERY query;\r
+       NET16                                   *pkeytable;\r
+       DWORD                                   npkey, bytes;\r
+       HRESULT                                 hr;\r
+       CWVBuffer                               buf;\r
+\r
+       bytes = sizeof NET16 * (Index + 1);\r
+       pkeytable = (NET16 *) buf.Get(bytes);\r
+       if (pkeytable == NULL) {\r
+               return WV_NO_MEMORY;\r
+       }\r
+\r
+       query.Id = m_Id;\r
+       query.PortNumber = PortNumber;\r
+       RtlZeroMemory(&query.Reserved, sizeof query.Reserved);\r
+\r
+       if (!WvDeviceIoControl(m_hFile, WV_IOCTL_DEVICE_PKEY_QUERY, &query,\r
+                                                  sizeof query, pkeytable, bytes, &bytes, NULL)) {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+               goto out;\r
+       }\r
+\r
+       npkey = bytes / sizeof NET16;\r
+       if (Index >= npkey) {\r
+               hr = WV_INVALID_PARAMETER_2;\r
+               goto out;\r
+       }\r
+       *pPkey = pkeytable[Index];\r
+       hr = WV_SUCCESS;\r
+\r
+out:\r
+       buf.Put();\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CWVDevice::\r
+CreateCompletionQueue(SIZE_T *pEntries, IWVCompletionQueue** ppCq)\r
+{\r
+       return CWVCompletionQueue::CreateInstance(this, pEntries, ppCq);\r
+}\r
+\r
+STDMETHODIMP CWVDevice::\r
+AllocateProtectionDomain(IWVProtectionDomain** ppPd)\r
+{\r
+       return CWVProtectionDomain::CreateInstance(this, ppPd);\r
+}\r
+\r
+STDMETHODIMP CWVDevice::\r
+Notify(UINT8 PortNumber, OVERLAPPED* pOverlapped, DWORD* pFlags)\r
+{\r
+       WV_IO_ID        id;\r
+       DWORD           bytes;\r
+       HRESULT         hr;\r
+\r
+       id.Id = m_Id;\r
+       id.Data = PortNumber;\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_DEVICE_NOTIFY, &id, sizeof id,\r
+                                                 pFlags, sizeof DWORD, &bytes, pOverlapped)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       return hr;\r
+}\r
diff --git a/core/winverbs/user/wv_device.h b/core/winverbs/user/wv_device.h
new file mode 100644 (file)
index 0000000..613bab9
--- /dev/null
@@ -0,0 +1,110 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_DEVICE_H_\r
+#define _WV_DEVICE_H_\r
+\r
+#include <iba\ib_types.h>\r
+#include <iba\ib_uvp.h>\r
+#include <rdma\winverbs.h>\r
+#include "wv_provider.h"\r
+#include "wv_base.h"\r
+\r
+class CWVDevice : IWVDevice, public CWVBase\r
+{\r
+public:\r
+       // IUnknown methods\r
+       STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);\r
+       STDMETHODIMP_(ULONG) AddRef();\r
+       STDMETHODIMP_(ULONG) Release();\r
+\r
+       // IWVOverlapped methods\r
+       STDMETHODIMP CancelOverlappedRequests();\r
+       STDMETHODIMP GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                                                        DWORD *pNumberOfBytesTransferred, BOOL bWait);\r
+\r
+       // IWVDevice methods\r
+       STDMETHODIMP Query(WV_DEVICE_ATTRIBUTES* pAttributes);\r
+       STDMETHODIMP QueryPort(UINT8 PortNumber, WV_PORT_ATTRIBUTES* pAttributes);\r
+       STDMETHODIMP QueryGid(UINT8 PortNumber, DWORD Index, WV_GID* pGid);\r
+       STDMETHODIMP QueryPkey(UINT8 PortNumber, DWORD Index, NET16* pPkey);\r
+       STDMETHODIMP CreateCompletionQueue(SIZE_T *pEntries, IWVCompletionQueue** ppCq);\r
+       STDMETHODIMP AllocateProtectionDomain(IWVProtectionDomain** ppPd);\r
+       STDMETHODIMP Notify(UINT8 PortNumber, OVERLAPPED* pOverlapped, DWORD* pFlags);\r
+\r
+       CWVDevice(CWVProvider *pProvider);\r
+       ~CWVDevice();\r
+       void Delete() {delete this;}\r
+       static STDMETHODIMP\r
+       CreateInstance(CWVProvider *pProvider, NET64 Guid, IWVDevice** ppDevice)\r
+       {\r
+               HRESULT hr;\r
+               CWVDevice *dev;\r
+\r
+               dev = new CWVDevice(pProvider);\r
+               if (dev == NULL) {\r
+                       hr = WV_NO_MEMORY;\r
+                       goto err1;\r
+               }\r
+\r
+               hr = dev->Init();\r
+               if (FAILED(hr)) {\r
+                       goto err2;\r
+               }\r
+\r
+               hr = dev->Open(Guid);\r
+               if (FAILED(hr)) {\r
+                       goto err2;\r
+               }\r
+\r
+               *ppDevice = dev;\r
+               return WV_SUCCESS;\r
+\r
+       err2:\r
+               dev->Release();\r
+       err1:\r
+               *ppDevice = NULL;\r
+               return hr;\r
+       }\r
+       STDMETHODIMP FindGidIndex(UINT8 PortNumber, WV_GID *pGid, UINT16 *pIndex);\r
+\r
+       CWVProvider             *m_pProvider;\r
+       uvp_interface_t m_Verbs;\r
+\r
+       ib_ca_handle_t  m_hVerbsDevice;\r
+       NET64                   m_Guid;\r
+\r
+protected:\r
+       HMODULE                 m_hLib;\r
+       STDMETHODIMP Open(NET64 Guid);\r
+};\r
+\r
+#endif // __WV_DEVICE_H_\r
diff --git a/core/winverbs/user/wv_ep.cpp b/core/winverbs/user/wv_ep.cpp
new file mode 100644 (file)
index 0000000..832abbc
--- /dev/null
@@ -0,0 +1,270 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include "wv_memory.h"\r
+#include "wv_ep.h"\r
+#include "wv_ioctl.h"\r
+\r
+CWVConnectEndpoint::CWVConnectEndpoint(CWVProvider *pProvider)\r
+{\r
+       pProvider->AddRef();\r
+       m_pProvider = pProvider;\r
+       m_hFile = pProvider->m_hFile;\r
+}\r
+\r
+CWVConnectEndpoint::~CWVConnectEndpoint()\r
+{\r
+       m_pProvider->Release();\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
+{\r
+       if (riid != IID_IUnknown && riid != IID_IWVEndpoint &&\r
+               riid != IID_IWVConnectEndpoint) {\r
+               *ppvObj = NULL;\r
+               return E_NOINTERFACE;\r
+       }\r
+\r
+       *ppvObj = this;\r
+       AddRef();\r
+       return WV_SUCCESS;\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVConnectEndpoint::\r
+AddRef(void)\r
+{\r
+       return CWVBase::AddRef();\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVConnectEndpoint::\r
+Release(void)\r
+{\r
+       return CWVBase::Release();\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+CancelOverlappedRequests(void)\r
+{\r
+       DWORD   bytes;\r
+\r
+       return WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CANCEL, &m_Id, sizeof m_Id,\r
+                                                        NULL, 0, &bytes, NULL) ?\r
+                                                        WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                       DWORD *pNumberOfBytesTransferred, BOOL bWait)\r
+{\r
+       return ::GetOverlappedResult(m_hFile, pOverlapped,\r
+                                                                pNumberOfBytesTransferred, bWait);\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+BindAddress(const struct sockaddr* pAddress)\r
+{\r
+       UNREFERENCED_PARAMETER(pAddress);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength)\r
+{\r
+       UNREFERENCED_PARAMETER(pPrivateData);\r
+       UNREFERENCED_PARAMETER(PrivateDataLength);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+Connect(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped)\r
+{\r
+       UNREFERENCED_PARAMETER(pQp);\r
+       UNREFERENCED_PARAMETER(pParam);\r
+       UNREFERENCED_PARAMETER(pOverlapped);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+Accept(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped)\r
+{\r
+       UNREFERENCED_PARAMETER(pQp);\r
+       UNREFERENCED_PARAMETER(pParam);\r
+       UNREFERENCED_PARAMETER(pOverlapped);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+Disconnect(OVERLAPPED* pOverlapped)\r
+{\r
+       UNREFERENCED_PARAMETER(pOverlapped);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+NotifyDisconnect(OVERLAPPED* pOverlapped)\r
+{\r
+       UNREFERENCED_PARAMETER(pOverlapped);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+Query(WV_CONNECT_ATTRIBUTES* pAttributes)\r
+{\r
+       UNREFERENCED_PARAMETER(pAttributes);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+\r
+CWVDatagramEndpoint::CWVDatagramEndpoint(CWVProvider *pProvider)\r
+{\r
+       pProvider->AddRef();\r
+       m_pProvider = pProvider;\r
+       m_hFile = pProvider->m_hFile;\r
+}\r
+\r
+CWVDatagramEndpoint::~CWVDatagramEndpoint()\r
+{\r
+       m_pProvider->Release();\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
+{\r
+       if (riid != IID_IUnknown && riid != IID_IWVEndpoint &&\r
+               riid != IID_IWVDatagramEndpoint) {\r
+               *ppvObj = NULL;\r
+               return E_NOINTERFACE;\r
+       }\r
+\r
+       *ppvObj = this;\r
+       AddRef();\r
+       return WV_SUCCESS;\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVDatagramEndpoint::\r
+AddRef(void)\r
+{\r
+       return CWVBase::AddRef();\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVDatagramEndpoint::\r
+Release(void)\r
+{\r
+       return CWVBase::Release();\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+CancelOverlappedRequests(void)\r
+{\r
+       DWORD   bytes;\r
+\r
+       return WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CANCEL, &m_Id, sizeof m_Id,\r
+                                                        NULL, 0, &bytes, NULL) ?\r
+                                                        WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                       DWORD *pNumberOfBytesTransferred, BOOL bWait)\r
+{\r
+       return ::GetOverlappedResult(m_hFile, pOverlapped,\r
+                                                                pNumberOfBytesTransferred, bWait);\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+BindAddress(const struct sockaddr* pAddress)\r
+{\r
+       UNREFERENCED_PARAMETER(pAddress);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength)\r
+{\r
+       UNREFERENCED_PARAMETER(pPrivateData);\r
+       UNREFERENCED_PARAMETER(PrivateDataLength);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+Lookup(const struct sockaddr* pAddress, const VOID* pPrivateData,\r
+          SIZE_T PrivateDataLength, OVERLAPPED* pOverlapped)\r
+{\r
+       UNREFERENCED_PARAMETER(pAddress);\r
+       UNREFERENCED_PARAMETER(pPrivateData);\r
+       UNREFERENCED_PARAMETER(PrivateDataLength);\r
+       UNREFERENCED_PARAMETER(pOverlapped);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+Accept(WV_DATAGRAM_PARAM* pParam, OVERLAPPED* pOverlapped)\r
+{\r
+       UNREFERENCED_PARAMETER(pParam);\r
+       UNREFERENCED_PARAMETER(pOverlapped);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+JoinMulticast(const struct sockaddr* pAddress, OVERLAPPED* pOverlapped)\r
+{\r
+       UNREFERENCED_PARAMETER(pAddress);\r
+       UNREFERENCED_PARAMETER(pOverlapped);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+LeaveMulticast(const struct sockaddr* pAddress, OVERLAPPED* pOverlapped)\r
+{\r
+       UNREFERENCED_PARAMETER(pAddress);\r
+       UNREFERENCED_PARAMETER(pOverlapped);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+Query(WV_DATAGRAM_ATTRIBUTES* pAttributes)\r
+{\r
+       UNREFERENCED_PARAMETER(pAttributes);\r
+\r
+       return E_NOTIMPL;\r
+}\r
diff --git a/core/winverbs/user/wv_ep.h b/core/winverbs/user/wv_ep.h
new file mode 100644 (file)
index 0000000..ab2fd14
--- /dev/null
@@ -0,0 +1,158 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_EP_H_\r
+#define _WV_EP_H_\r
+\r
+#include <rdma\winverbs.h>\r
+#include "wv_provider.h"\r
+#include "wv_base.h"\r
+\r
+class CWVConnectEndpoint : IWVConnectEndpoint, public CWVBase\r
+{\r
+public:\r
+       // IUnknown methods\r
+       STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);\r
+       STDMETHODIMP_(ULONG) AddRef();\r
+       STDMETHODIMP_(ULONG) Release();\r
+\r
+       // IWVOverlapped methods\r
+       STDMETHODIMP CancelOverlappedRequests();\r
+       STDMETHODIMP GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                                                        DWORD *pNumberOfBytesTransferred, BOOL bWait);\r
+\r
+       // IWVEndpoint methods\r
+       STDMETHODIMP BindAddress(const struct sockaddr* pAddress);\r
+       STDMETHODIMP Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength);\r
+\r
+       // IWVConnectEndpoint methods\r
+       STDMETHODIMP Connect(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam,\r
+                                                OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP Accept(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam,\r
+                                               OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP Disconnect(OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP NotifyDisconnect(OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP Query(WV_CONNECT_ATTRIBUTES* pAttributes);\r
+\r
+       CWVConnectEndpoint(CWVProvider *pProvider);\r
+       ~CWVConnectEndpoint();\r
+       void Delete() {delete this;}\r
+       static STDMETHODIMP\r
+       CreateInstance(CWVProvider *pProvider, IWVConnectEndpoint** ppConnectEndpoint)\r
+       {\r
+               HRESULT hr;\r
+               CWVConnectEndpoint *ep;\r
+\r
+               ep = new CWVConnectEndpoint(pProvider);\r
+               if (ep == NULL) {\r
+                       hr = WV_NO_MEMORY;\r
+                       goto err1;\r
+               }\r
+\r
+               hr = ep->Init();\r
+               if (FAILED(hr)) {\r
+                       goto err2;\r
+               }\r
+\r
+               *ppConnectEndpoint = ep;\r
+               return WV_SUCCESS;\r
+\r
+       err2:\r
+               ep->Release();\r
+       err1:\r
+               *ppConnectEndpoint = NULL;\r
+               return hr;\r
+       }\r
+\r
+       CWVProvider             *m_pProvider;\r
+};\r
+\r
+class CWVDatagramEndpoint : IWVDatagramEndpoint, public CWVBase\r
+{\r
+public:\r
+       // IUnknown methods\r
+       STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);\r
+       STDMETHODIMP_(ULONG) AddRef();\r
+       STDMETHODIMP_(ULONG) Release();\r
+\r
+       // IWVOverlapped methods\r
+       STDMETHODIMP CancelOverlappedRequests();\r
+       STDMETHODIMP GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                                                        DWORD *pNumberOfBytesTransferred, BOOL bWait);\r
+\r
+       // IWVEndpoint methods\r
+       STDMETHODIMP BindAddress(const struct sockaddr* pAddress);\r
+       STDMETHODIMP Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength);\r
+\r
+       // IWVDatagramEndpoint methods\r
+       STDMETHODIMP Lookup(const struct sockaddr* pAddress, const VOID* pPrivateData,\r
+                                               SIZE_T PrivateDataLength, OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP Accept(WV_DATAGRAM_PARAM* pParam, OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP JoinMulticast(const struct sockaddr* pAddress,\r
+                                                          OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP LeaveMulticast(const struct sockaddr* pAddress,\r
+                                                               OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP Query(WV_DATAGRAM_ATTRIBUTES* pAttributes);\r
+\r
+       CWVDatagramEndpoint(CWVProvider *pProvider);\r
+       ~CWVDatagramEndpoint();\r
+       void Delete() {delete this;}\r
+       static STDMETHODIMP\r
+       CreateInstance(CWVProvider *pProvider, IWVDatagramEndpoint** ppDatagramEndpoint)\r
+       {\r
+               HRESULT hr;\r
+               CWVDatagramEndpoint *ep;\r
+\r
+               ep = new CWVDatagramEndpoint(pProvider);\r
+               if (ep == NULL) {\r
+                       hr = WV_NO_MEMORY;\r
+                       goto err1;\r
+               }\r
+\r
+               hr = ep->Init();\r
+               if (FAILED(hr)) {\r
+                       goto err2;\r
+               }\r
+\r
+               *ppDatagramEndpoint = ep;\r
+               return WV_SUCCESS;\r
+\r
+       err2:\r
+               ep->Release();\r
+       err1:\r
+               *ppDatagramEndpoint = NULL;\r
+               return hr;\r
+       }\r
+\r
+       CWVProvider             *m_pProvider;\r
+};\r
+\r
+#endif // _WV_EP_H_\r
diff --git a/core/winverbs/user/wv_exports.src b/core/winverbs/user/wv_exports.src
new file mode 100644 (file)
index 0000000..ed6a38c
--- /dev/null
@@ -0,0 +1,9 @@
+#if DBG\r
+LIBRARY winverbsd.dll\r
+#else\r
+LIBRARY winverbs.dll\r
+#endif\r
+\r
+EXPORTS\r
+DllCanUnloadNow        PRIVATE\r
+\r
diff --git a/core/winverbs/user/wv_listen.cpp b/core/winverbs/user/wv_listen.cpp
new file mode 100644 (file)
index 0000000..6ec7de4
--- /dev/null
@@ -0,0 +1,105 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include "wv_memory.h"\r
+#include "wv_listen.h"\r
+#include "wv_ioctl.h"\r
+\r
+CWVListen::CWVListen(CWVProvider *pProvider)\r
+{\r
+       pProvider->AddRef();\r
+       m_pProvider = pProvider;\r
+       m_hFile = pProvider->m_hFile;\r
+}\r
+\r
+CWVListen::~CWVListen()\r
+{\r
+       m_pProvider->Release();\r
+}\r
+\r
+STDMETHODIMP CWVListen::\r
+QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
+{\r
+       if (riid != IID_IUnknown && riid != IID_IWVListen) {\r
+               *ppvObj = NULL;\r
+               return E_NOINTERFACE;\r
+       }\r
+\r
+       *ppvObj = this;\r
+       AddRef();\r
+       return WV_SUCCESS;\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVListen::\r
+AddRef(void)\r
+{\r
+       return CWVBase::AddRef();\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWVListen::\r
+Release(void)\r
+{\r
+       return CWVBase::Release();\r
+}\r
+\r
+STDMETHODIMP CWVListen::\r
+CancelOverlappedRequests(void)\r
+{\r
+       DWORD   bytes;\r
+\r
+       return WvDeviceIoControl(m_hFile, WV_IOCTL_LISTEN_CANCEL, &m_Id, sizeof m_Id,\r
+                                                        NULL, 0, &bytes, NULL) ?\r
+                                                        WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
+}\r
+\r
+STDMETHODIMP CWVListen::\r
+GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                       DWORD *pNumberOfBytesTransferred, BOOL bWait)\r
+{\r
+       return ::GetOverlappedResult(m_hFile, pOverlapped,\r
+                                                                pNumberOfBytesTransferred, bWait);\r
+}\r
+\r
+STDMETHODIMP CWVListen::\r
+Listen(const struct sockaddr* pAddress, SIZE_T Backlog)\r
+{\r
+       UNREFERENCED_PARAMETER(pAddress);\r
+       UNREFERENCED_PARAMETER(Backlog);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVListen::\r
+GetRequest(IWVEndpoint* pEndpoint, OVERLAPPED* pOverlapped)\r
+{\r
+       UNREFERENCED_PARAMETER(pEndpoint);\r
+       UNREFERENCED_PARAMETER(pOverlapped);\r
+\r
+       return E_NOTIMPL;\r
+}\r
diff --git a/core/winverbs/user/wv_listen.h b/core/winverbs/user/wv_listen.h
new file mode 100644 (file)
index 0000000..55bcc55
--- /dev/null
@@ -0,0 +1,96 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifndef _WV_LISTEN_H_\r
+#define _WV_LISTEN_H_\r
+\r
+#include <rdma\winverbs.h>\r
+#include "wv_provider.h"\r
+#include "wv_base.h"\r
+\r
+class CWVListen : IWVListen, public CWVBase\r
+{\r
+public:\r
+       // IUnknown methods\r
+       STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);\r
+       STDMETHODIMP_(ULONG) AddRef();\r
+       STDMETHODIMP_(ULONG) Release();\r
+\r
+       // IWVOverlapped methods\r
+       STDMETHODIMP CancelOverlappedRequests();\r
+       STDMETHODIMP GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                                                        DWORD *pNumberOfBytesTransferred, BOOL bWait);\r
+\r
+       // IWVListen methods\r
+       STDMETHODIMP GetRequest(IWVEndpoint* pEndpoint, OVERLAPPED* pOverlapped);\r
+\r
+       STDMETHODIMP Listen(const struct sockaddr* pAddress, SIZE_T Backlog);\r
+\r
+       CWVListen(CWVProvider *pProvider);\r
+       ~CWVListen();\r
+       void Delete() {delete this;}\r
+       static STDMETHODIMP\r
+       CreateInstance(CWVProvider *pProvider, const struct sockaddr* pAddress,\r
+                                  SIZE_T Backlog, IWVListen** ppListen)\r
+       {\r
+               HRESULT hr;\r
+               CWVListen *listener;\r
+\r
+               listener = new CWVListen(pProvider);\r
+               if (listener == NULL) {\r
+                       hr = WV_NO_MEMORY;\r
+                       goto err1;\r
+               }\r
+\r
+               hr = listener->Init();\r
+               if (FAILED(hr)) {\r
+                       goto err2;\r
+               }\r
+\r
+               hr = listener->Listen(pAddress, Backlog);\r
+               if (FAILED(hr)) {\r
+                       goto err2;\r
+               }\r
+\r
+               *ppListen = listener;\r
+               return WV_SUCCESS;\r
+\r
+       err2:\r
+               listener->Release();\r
+       err1:\r
+               *ppListen = NULL;\r
+               return hr;\r
+       }\r
+\r
+       CWVProvider             *m_pProvider;\r
+};\r
+\r
+#endif // _WV_LISTEN_H_
\ No newline at end of file
diff --git a/core/winverbs/user/wv_main.cpp b/core/winverbs/user/wv_main.cpp
new file mode 100644 (file)
index 0000000..f6e1c78
--- /dev/null
@@ -0,0 +1,118 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include "wv_memory.h"\r
+#include "wv_provider.h"\r
+#include "wv_base.h"\r
+\r
+volatile LONG WvRef;\r
+\r
+BOOLEAN WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)\r
+{\r
+       UNREFERENCED_PARAMETER(hInstance);\r
+       UNREFERENCED_PARAMETER(dwReason);\r
+       UNREFERENCED_PARAMETER(lpReserved);\r
+\r
+       return TRUE;\r
+}\r
+\r
+STDAPI DllCanUnloadNow(void)\r
+{\r
+       return WvRef ? S_FALSE : S_OK;\r
+}\r
+\r
+__declspec(dllexport) HRESULT WvGetObject(REFIID riid, LPVOID FAR* ppvObj)\r
+{\r
+       if (riid != IID_IWVProvider) {\r
+               *ppvObj = NULL;\r
+               return E_NOINTERFACE;\r
+       }\r
+\r
+       return CWVProvider::CreateInstance((IWVProvider **) ppvObj);\r
+}\r
+\r
+HRESULT WvConvertIbStatus(ib_api_status_t status)\r
+{\r
+       switch (status) {\r
+       case IB_SUCCESS:                                return WV_SUCCESS;\r
+       case IB_INSUFFICIENT_RESOURCES: return WV_INSUFFICIENT_RESOURCES;\r
+       case IB_INSUFFICIENT_MEMORY:    return WV_NO_MEMORY;\r
+       case IB_INVALID_PARAMETER:              return WV_INVALID_PARAMETER;\r
+       case IB_INVALID_SETTING:                return WV_INVALID_PARAMETER;\r
+       case IB_NOT_FOUND:                              return WV_INVALID_ADDRESS;\r
+       case IB_TIMEOUT:                                return WV_TIMEOUT;\r
+       case IB_CANCELED:                               return WV_CANCELLED;\r
+       case IB_INTERRUPTED:                    return WV_CANCELLED;\r
+       case IB_INVALID_PERMISSION:             return WV_ACCESS_VIOLATION;\r
+       case IB_UNSUPPORTED:                    return WV_NOT_SUPPORTED;\r
+       case IB_OVERFLOW:                               return WV_BUFFER_OVERFLOW;\r
+       case IB_MAX_MCAST_QPS_REACHED:  return WV_INSUFFICIENT_RESOURCES;\r
+       case IB_INVALID_QP_STATE:               return WV_INVALID_PARAMETER;\r
+       case IB_INVALID_APM_STATE:              return WV_INVALID_PARAMETER;\r
+       case IB_INVALID_PORT_STATE:             return WV_INVALID_PARAMETER;\r
+       case IB_INVALID_STATE:                  return WV_INVALID_PARAMETER;\r
+       case IB_RESOURCE_BUSY:                  return WV_DEVICE_BUSY;\r
+       case IB_INVALID_PKEY:                   return WV_INVALID_HANDLE;\r
+       case IB_INVALID_LKEY:                   return WV_INVALID_HANDLE;\r
+       case IB_INVALID_RKEY:                   return WV_INVALID_HANDLE;\r
+       case IB_INVALID_MAX_WRS:                return WV_INSUFFICIENT_RESOURCES;\r
+       case IB_INVALID_MAX_SGE:                return WV_INSUFFICIENT_RESOURCES;\r
+       case IB_INVALID_CQ_SIZE:                return WV_INSUFFICIENT_RESOURCES;\r
+       case IB_INVALID_SRQ_SIZE:               return WV_INSUFFICIENT_RESOURCES;\r
+       case IB_INVALID_SERVICE_TYPE:   return WV_NOT_SUPPORTED;\r
+       case IB_INVALID_GID:                    return WV_INVALID_ADDRESS;\r
+       case IB_INVALID_LID:                    return WV_INVALID_ADDRESS;\r
+       case IB_INVALID_GUID:                   return WV_INVALID_ADDRESS;\r
+       case IB_INVALID_CA_HANDLE:              return WV_INVALID_HANDLE;\r
+       case IB_INVALID_AV_HANDLE:              return WV_INVALID_HANDLE;\r
+       case IB_INVALID_CQ_HANDLE:              return WV_INVALID_HANDLE;\r
+       case IB_INVALID_QP_HANDLE:              return WV_INVALID_HANDLE;\r
+       case IB_INVALID_SRQ_HANDLE:             return WV_INVALID_HANDLE;\r
+       case IB_INVALID_PD_HANDLE:              return WV_INVALID_HANDLE;\r
+       case IB_INVALID_MR_HANDLE:              return WV_INVALID_HANDLE;\r
+       case IB_INVALID_FMR_HANDLE:             return WV_INVALID_HANDLE;\r
+       case IB_INVALID_MW_HANDLE:              return WV_INVALID_HANDLE;\r
+       case IB_INVALID_MCAST_HANDLE:   return WV_INVALID_HANDLE;\r
+       case IB_INVALID_CALLBACK:               return WV_INVALID_PARAMETER;\r
+       case IB_INVALID_AL_HANDLE:              return WV_INVALID_HANDLE;\r
+       case IB_INVALID_HANDLE:                 return WV_INVALID_HANDLE;\r
+       case IB_ERROR:                                  return WV_UNKNOWN_ERROR;\r
+       case IB_REMOTE_ERROR:                   return WV_REMOTE_OP_ERROR;\r
+       case IB_VERBS_PROCESSING_DONE:  return WV_SUCCESS;\r
+       case IB_INVALID_WR_TYPE:                return WV_INVALID_PARAMETER;\r
+       case IB_QP_IN_TIMEWAIT:                 return WV_INVALID_PARAMETER;\r
+       case IB_EE_IN_TIMEWAIT:                 return WV_INVALID_PARAMETER;\r
+       case IB_INVALID_PORT:                   return WV_INVALID_ADDRESS;\r
+       case IB_NOT_DONE:                               return WV_PENDING;\r
+       case IB_INVALID_INDEX:                  return WV_INVALID_PARAMETER;\r
+       case IB_NO_MATCH:                               return WV_INVALID_PARAMETER;\r
+       case IB_PENDING:                                return WV_PENDING;\r
+       default:                                                return WV_UNKNOWN_ERROR;\r
+       }\r
+}\r
diff --git a/core/winverbs/user/wv_memory.h b/core/winverbs/user/wv_memory.h
new file mode 100644 (file)
index 0000000..17a5953
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided