WinMad driver and library.
authorshefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 17 Dec 2008 20:27:48 +0000 (20:27 +0000)
committershefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 17 Dec 2008 20:27:48 +0000 (20:27 +0000)
libibumad compatibility library.

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

37 files changed:
core/dirs
core/winmad/dirs [new file with mode: 0644]
core/winmad/kernel/SOURCES [new file with mode: 0644]
core/winmad/kernel/makefile [new file with mode: 0644]
core/winmad/kernel/makefile.inc [new file with mode: 0644]
core/winmad/kernel/winmad.inx [new file with mode: 0644]
core/winmad/kernel/winmad.rc [new file with mode: 0644]
core/winmad/kernel/wm_driver.c [new file with mode: 0644]
core/winmad/kernel/wm_driver.h [new file with mode: 0644]
core/winmad/kernel/wm_provider.c [new file with mode: 0644]
core/winmad/kernel/wm_provider.h [new file with mode: 0644]
core/winmad/kernel/wm_reg.c [new file with mode: 0644]
core/winmad/kernel/wm_reg.h [new file with mode: 0644]
core/winmad/user/SOURCES [new file with mode: 0644]
core/winmad/user/makefile [new file with mode: 0644]
core/winmad/user/winmad.rc [new file with mode: 0644]
core/winmad/user/wm_exports.src [new file with mode: 0644]
core/winmad/user/wm_main.cpp [new file with mode: 0644]
core/winmad/user/wm_memory.h [new file with mode: 0644]
core/winmad/user/wm_provider.cpp [new file with mode: 0644]
core/winmad/user/wm_provider.h [new file with mode: 0644]
core/winmad/wm_ioctl.h [new file with mode: 0644]
docs/maintainers.txt
inc/user/iba/winmad.h [new file with mode: 0644]
ulp/dirs
ulp/libibumad/AUTHORS [new file with mode: 0644]
ulp/libibumad/COPYING [new file with mode: 0644]
ulp/libibumad/dirs [new file with mode: 0644]
ulp/libibumad/include/infiniband/umad.h [new file with mode: 0644]
ulp/libibumad/src/Sources [new file with mode: 0644]
ulp/libibumad/src/ibum_export.def [new file with mode: 0644]
ulp/libibumad/src/ibum_exports.src [new file with mode: 0644]
ulp/libibumad/src/ibum_main.cpp [new file with mode: 0644]
ulp/libibumad/src/ibumad.h [new file with mode: 0644]
ulp/libibumad/src/ibumad.rc [new file with mode: 0644]
ulp/libibumad/src/makefile [new file with mode: 0644]
ulp/libibumad/src/umad.cpp [new file with mode: 0644]

index 0162fac..73c7806 100644 (file)
--- a/core/dirs
+++ b/core/dirs
@@ -4,4 +4,5 @@ DIRS=\
        bus                     \\r
        iou                     \\r
        ibat            \\r
-       winverbs\r
+       winverbs        \\r
+       winmad\r
diff --git a/core/winmad/dirs b/core/winmad/dirs
new file mode 100644 (file)
index 0000000..697ddcd
--- /dev/null
@@ -0,0 +1,3 @@
+DIRS=\\r
+       kernel  \\r
+       user
\ No newline at end of file
diff --git a/core/winmad/kernel/SOURCES b/core/winmad/kernel/SOURCES
new file mode 100644 (file)
index 0000000..e387657
--- /dev/null
@@ -0,0 +1,21 @@
+TARGETNAME = winmad\r
+TARGETPATH = ..\..\..\bin\kernel\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = DRIVER\r
+\r
+KMDF_VERSION_MAJOR = 1\r
+INF_NAME = winmad\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
+       winmad.rc               \\r
+       wm_driver.c             \\r
+       wm_provider.c   \\r
+       wm_reg.c\r
+\r
+INCLUDES = ..;..\..\..\inc;..\..\..\inc\kernel;..\..\..\inc\user;..\..\..\etc\kernel;\r
+\r
+C_DEFINES = $(C_DEFINES) -DIOCTL_INTERFACE=1\r
diff --git a/core/winmad/kernel/makefile b/core/winmad/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/winmad/kernel/makefile.inc b/core/winmad/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/winmad/kernel/winmad.inx b/core/winmad/kernel/winmad.inx
new file mode 100644 (file)
index 0000000..89427ae
--- /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 = InfiniBandController\r
+ClassGUID = {58517E00-D3CF-40c9-A679-CEE5752F4491}\r
+Provider = %OFA%\r
+DriverVer = 05/20/2008\r
+CatalogFile = winmad.cat\r
+\r
+[SourceDisksNames]\r
+1 = %DiskId%\r
+\r
+[SourceDisksFiles]\r
+winmad.sys = 1\r
+winmad.dll = 1\r
+winmadd.dll = 1\r
+\r
+[DefaultInstall]\r
+AddReg = WmClassAddReg\r
+CopyFiles = WmClassCopySysFiles, WmClassCopyDllFiles\r
+\r
+[WmClassAddReg]\r
+HKLM, System\CurrentControlSet\Control\Class\{58517E00-D3CF-40c9-A679-CEE5752F4491}, UpperFilters, 0x00010008, winmad\r
+\r
+[DestinationDirs]\r
+WmClassCopySysFiles = 12\r
+WmClassCopyDllFiles = 11\r
+\r
+[WmClassCopySysFiles]\r
+winmad.sys\r
+\r
+[WmClassCopyDllFiles]\r
+winmad.dll\r
+winmadd.dll\r
+\r
+[Manufacturer]\r
+%OFA% = WmModel\r
+\r
+[WmModel]\r
+%winmad.DeviceDesc% = WmDevice, root\winmad\r
+\r
+[DefaultInstall.Services]\r
+AddService = winmad,, WmClassService\r
+\r
+[WmClassService]\r
+DisplayName = %winmad.ServiceDesc%\r
+ServiceType = 1\r
+StartType = 3\r
+ErrorControl = 1\r
+ServiceBinary  = %12%\winmad.sys\r
+LoadOrderGroup = PNP Filter\r
+\r
+[WmDevice.CoInstallers]\r
+AddReg = WmDeviceCoInstAddReg\r
+CopyFiles = WmDeviceCoInstCopyFiles\r
+\r
+[DestinationDirs]\r
+WmDeviceCoInstCopyFiles = 11\r
+\r
+[WmDeviceCoInstAddReg]\r
+HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll, WdfCoInstaller"\r
+\r
+[WmDeviceCoInstCopyFiles]\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll\r
+\r
+[SourceDisksFiles]\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1\r
+\r
+[WmDevice.Wdf]\r
+KmdfService = winmad, WmWdfSect\r
+\r
+[WmWdfSect]\r
+KmdfLibraryVersion = $KMDFVERSION$\r
+\r
+[Strings]\r
+OFA = "OpenFabrics"\r
+DiskId = "OpenFabrics WinMad Installation"\r
+winmad.DeviceDesc = "WinMad Driver"\r
+winmad.ServiceDesc = "WinMad Service"\r
+ClassName = "WinMad Device"\r
diff --git a/core/winmad/kernel/winmad.rc b/core/winmad/kernel/winmad.rc
new file mode 100644 (file)
index 0000000..3669ed2
--- /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 WinMad (Debug)"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR                "Kernel WinMad"\r
+#endif\r
+\r
+#define VER_INTERNALNAME_STR           "winmad.sys"\r
+#define VER_ORIGINALFILENAME_STR       "winmad.sys"\r
+\r
+#include <common.ver>\r
diff --git a/core/winmad/kernel/wm_driver.c b/core/winmad/kernel/wm_driver.c
new file mode 100644 (file)
index 0000000..8ac92b6
--- /dev/null
@@ -0,0 +1,419 @@
+/*\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 "wm_ioctl.h"\r
+#include "wm_driver.h"\r
+#include "wm_provider.h"\r
+#include "wm_reg.h"\r
+\r
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WM_IB_DEVICE, WmIbDeviceGetContext)\r
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WM_PROVIDER, WmProviderGetContext)\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                       WmIbDeviceAdd;\r
+static EVT_WDF_OBJECT_CONTEXT_CLEANUP          WmIbDeviceCleanup;\r
+static EVT_WDF_DEVICE_D0_ENTRY                         WmPowerD0Entry;\r
+static EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL      WmIoDeviceControl;\r
+static EVT_WDF_IO_QUEUE_IO_READ                                WmIoRead;\r
+static EVT_WDF_IO_QUEUE_IO_WRITE                       WmIoWrite;\r
+static EVT_WDF_DEVICE_FILE_CREATE                      WmFileCreate;\r
+static EVT_WDF_FILE_CLEANUP                                    WmFileCleanup;\r
+static EVT_WDF_FILE_CLOSE                                      WmFileClose;\r
+\r
+static WM_IB_DEVICE *WmIbDeviceFind(NET64 Guid)\r
+{\r
+       WM_IB_DEVICE    *cur_dev, *dev = NULL;\r
+       LIST_ENTRY              *entry;\r
+\r
+       for (entry = DevList.Flink; entry != &DevList; entry = entry->Flink) {\r
+               cur_dev = CONTAINING_RECORD(entry, WM_IB_DEVICE, Entry);\r
+               if (cur_dev->Guid == Guid) {\r
+                       dev = cur_dev;\r
+                       break;\r
+               }\r
+       }\r
+       return dev;\r
+}\r
+\r
+WM_IB_DEVICE *WmIbDeviceGet(NET64 Guid)\r
+{\r
+       WM_IB_DEVICE *dev;\r
+\r
+       KeAcquireGuardedMutex(&Lock);\r
+       dev = WmIbDeviceFind(Guid);\r
+       if (dev != NULL) {\r
+                       InterlockedIncrement(&dev->Ref);\r
+       }\r
+       KeReleaseGuardedMutex(&Lock);\r
+       return dev;\r
+}\r
+\r
+void WmIbDevicePut(WM_IB_DEVICE *pDevice)\r
+{\r
+       if (InterlockedDecrement(&pDevice->Ref) == 0) {\r
+               KeSetEvent(&pDevice->Event, 0, FALSE);\r
+       }\r
+}\r
+\r
+static VOID WmIoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request,\r
+                                                         size_t OutLen, size_t InLen, ULONG IoControlCode)\r
+{\r
+       WDFFILEOBJECT   file;\r
+       WM_PROVIDER             *prov;\r
+       UNREFERENCED_PARAMETER(OutLen);\r
+       UNREFERENCED_PARAMETER(InLen);\r
+       UNREFERENCED_PARAMETER(Queue);\r
+\r
+       file = WdfRequestGetFileObject(Request);\r
+       prov = WmProviderGetContext(file);\r
+\r
+       switch (IoControlCode) {\r
+       case WM_IOCTL_REGISTER:\r
+               WmRegister(prov, Request);\r
+               break;\r
+       case WM_IOCTL_DEREGISTER:\r
+               WmDeregister(prov, Request);\r
+               break;\r
+       case WM_IOCTL_CANCEL:\r
+               WmProviderCancel(prov, Request);\r
+               break;\r
+       default:\r
+               WdfRequestComplete(Request, STATUS_PROCEDURE_NOT_FOUND);\r
+               break;\r
+       }\r
+}\r
+\r
+static VOID WmIoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length)\r
+{\r
+       WDFFILEOBJECT   file;\r
+       WM_PROVIDER             *prov;\r
+       UNREFERENCED_PARAMETER(Queue);\r
+\r
+       file = WdfRequestGetFileObject(Request);\r
+       prov = WmProviderGetContext(file);\r
+       WmProviderRead(prov, Request);\r
+}\r
+\r
+static VOID WmIoWrite(WDFQUEUE Queue, WDFREQUEST Request, size_t Length)\r
+{\r
+       WDFFILEOBJECT   file;\r
+       WM_PROVIDER             *prov;\r
+       UNREFERENCED_PARAMETER(Queue);\r
+\r
+       file = WdfRequestGetFileObject(Request);\r
+       prov = WmProviderGetContext(file);\r
+       WmProviderWrite(prov, Request);\r
+}\r
+\r
+static VOID WmFileCreate(WDFDEVICE Device, WDFREQUEST Request,\r
+                                                WDFFILEOBJECT FileObject)\r
+{\r
+       WM_PROVIDER     *prov = WmProviderGetContext(FileObject);\r
+       UNREFERENCED_PARAMETER(Device);\r
+\r
+       WmProviderInit(prov);\r
+       KeAcquireGuardedMutex(&Lock);\r
+       InsertHeadList(&ProvList, &prov->Entry);\r
+       KeReleaseGuardedMutex(&Lock);\r
+       WdfRequestComplete(Request, STATUS_SUCCESS);\r
+}\r
+\r
+static VOID WmFileCleanup(WDFFILEOBJECT FileObject)\r
+{\r
+       WM_PROVIDER *prov = WmProviderGetContext(FileObject);\r
+\r
+       KeAcquireGuardedMutex(&Lock);\r
+       RemoveEntryList(&prov->Entry);\r
+       KeReleaseGuardedMutex(&Lock);\r
+       WmProviderCleanup(prov);\r
+}\r
+\r
+static VOID WmFileClose(WDFFILEOBJECT FileObject)\r
+{\r
+       UNREFERENCED_PARAMETER(FileObject);\r
+}\r
+\r
+static VOID WmCreateControlDevice(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\\WinMad");\r
+       DECLARE_CONST_UNICODE_STRING(symlink, L"\\DosDevices\\WinMad");\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, WmFileCreate, WmFileClose,\r
+                                                          WmFileCleanup);\r
+       WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, WM_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 = WmIoDeviceControl;\r
+       ioconfig.EvtIoRead = WmIoRead;\r
+       ioconfig.EvtIoWrite = WmIoWrite;\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 ib_ca_attr_t *WmQueryCaAttributes(WM_IB_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->VerbsInterface.Verbs.\r
+                               query_ca(pDevice->VerbsInterface.Verbs.p_hca_dev, NULL, &size, NULL);\r
+       if (ib_status != IB_INSUFFICIENT_MEMORY) {\r
+               attr = NULL;\r
+               goto out;\r
+       }\r
+\r
+       attr = ExAllocatePoolWithTag(PagedPool, size, 'acmw');\r
+       if (attr == NULL) {\r
+               goto out;\r
+       }\r
+\r
+       ib_status = pDevice->VerbsInterface.Verbs.\r
+                               query_ca(pDevice->VerbsInterface.Verbs.p_hca_dev, attr, &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 WmAddCa(WM_IB_DEVICE *pDevice)\r
+{\r
+       NTSTATUS                status;\r
+       ib_api_status_t ib_status;\r
+       ib_ca_attr_t    *attr;\r
+       UINT32                  size;\r
+       UINT8                   i;\r
+\r
+       attr = WmQueryCaAttributes(pDevice);\r
+       if (attr == NULL) {\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       size = sizeof(WM_IB_PORT) * attr->num_ports;\r
+       pDevice->pPortArray = ExAllocatePoolWithTag(PagedPool, size, 'pimw');\r
+       if (pDevice->pPortArray == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto out;\r
+       }\r
+\r
+       for (i = 0; i < attr->num_ports; i++) {\r
+               pDevice->pPortArray[i].Guid = attr->p_port_attr[i].port_guid;\r
+       }\r
+       pDevice->PortCount = attr->num_ports;\r
+\r
+       status = STATUS_SUCCESS;\r
+out:\r
+       ExFreePool(attr);\r
+       return status;\r
+}\r
+\r
+static NTSTATUS WmPowerD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)\r
+{\r
+       WM_IB_DEVICE    *dev;\r
+       BOOLEAN                 create;\r
+       NTSTATUS                status;\r
+\r
+       dev = WmIbDeviceGetContext(Device);\r
+       status = WdfFdoQueryForInterface(Device, &GUID_RDMA_INTERFACE_VERBS,\r
+                                                                        (PINTERFACE) &dev->VerbsInterface,\r
+                                                                        sizeof(dev->VerbsInterface), VerbsVersion(2, 0),\r
+                                                                        NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+\r
+       dev->Guid = dev->VerbsInterface.Verbs.guid;\r
+       status = WmAddCa(dev);\r
+\r
+       dev->VerbsInterface.InterfaceHeader.InterfaceDereference(dev->VerbsInterface.\r
+                                                                                                                        InterfaceHeader.Context);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+\r
+       status = WdfFdoQueryForInterface(Device, &GUID_IB_AL_INTERFACE,\r
+                                                                        (PINTERFACE) &dev->IbInterface,\r
+                                                                        sizeof(dev->IbInterface),\r
+                                                                        AL_INTERFACE_VERSION, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&Lock);\r
+       create = IsListEmpty(&DevList);\r
+       InsertHeadList(&DevList, &dev->Entry);\r
+       KeReleaseGuardedMutex(&Lock);\r
+\r
+       if (create) {\r
+               WmCreateControlDevice(WdfGetDriver());\r
+       }\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+static NTSTATUS WmIbDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)\r
+{\r
+       WDF_OBJECT_ATTRIBUTES                   attr;\r
+       WDF_PNPPOWER_EVENT_CALLBACKS    power;\r
+       WDFDEVICE                                               dev;\r
+       WM_IB_DEVICE                                    *pdev;\r
+       NTSTATUS                                                status;\r
+\r
+       WdfFdoInitSetFilter(DeviceInit);\r
+\r
+       WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, WM_IB_DEVICE);\r
+       attr.EvtCleanupCallback = WmIbDeviceCleanup;\r
+\r
+       WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&power);\r
+       power.EvtDeviceD0Entry = WmPowerD0Entry;\r
+       WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &power);\r
+\r
+       status = WdfDeviceCreate(&DeviceInit, &attr, &dev);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+\r
+       pdev = WmIbDeviceGetContext(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 WmIbDeviceCleanup(WDFDEVICE Device)\r
+{\r
+       WM_PROVIDER                     *prov;\r
+       WM_IB_DEVICE            *pdev;\r
+       WM_REGISTRATION         *reg;\r
+       LIST_ENTRY                      *entry;\r
+       BOOLEAN                         destroy;\r
+       WDFDEVICE                       ctrldev;\r
+\r
+       pdev = (WmIbDeviceGetContext(Device));\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, WM_PROVIDER, Entry);\r
+               WmProviderRemoveHandler(prov, pdev);\r
+       } \r
+       KeReleaseGuardedMutex(&Lock);\r
+\r
+       if (InterlockedDecrement(&pdev->Ref) > 0) {\r
+               KeWaitForSingleObject(&pdev->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
+\r
+       pdev->IbInterface.wdm.InterfaceDereference(pdev->IbInterface.wdm.Context);\r
+       if (pdev->pPortArray != NULL) {\r
+               ExFreePool(pdev->pPortArray);\r
+       }\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, WmIbDeviceAdd);\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/winmad/kernel/wm_driver.h b/core/winmad/kernel/wm_driver.h
new file mode 100644 (file)
index 0000000..423b1bf
--- /dev/null
@@ -0,0 +1,81 @@
+/*\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 _WM_DRIVER_H_\r
+#define _WM_DRIVER_H_\r
+\r
+#include <ntddk.h>\r
+#include <wdm.h>\r
+#include <wdf.h>\r
+\r
+#include <rdma\verbs.h>\r
+#include <iba\ib_al_ifc.h>\r
+#include "wm_ioctl.h"\r
+\r
+#if WINVER <= _WIN32_WINNT_WINXP\r
+#define KGUARDED_MUTEX FAST_MUTEX\r
+#define KeInitializeGuardedMutex ExInitializeFastMutex\r
+#define KeAcquireGuardedMutex ExAcquireFastMutex\r
+#define KeReleaseGuardedMutex ExReleaseFastMutex\r
+#endif\r
+\r
+extern WDFDEVICE                       ControlDevice;\r
+\r
+typedef struct _WM_IB_PORT\r
+{\r
+       NET64                                   Guid;\r
+\r
+}      WM_IB_PORT;\r
+\r
+typedef struct _WM_IB_DEVICE\r
+{\r
+       LIST_ENTRY                              Entry;\r
+       LONG                                    Ref;\r
+       KEVENT                                  Event;\r
+       NET64                                   Guid;\r
+       union\r
+       {\r
+               RDMA_INTERFACE_VERBS    VerbsInterface;\r
+               ib_al_ifc_t                             IbInterface;\r
+       };\r
+       ib_al_handle_t                  hIbal;\r
+       ib_pnp_handle_t                 hPnp;\r
+       //ib_ca_handle_t                        hDevice;\r
+       //ib_pd_handle_t                        hPd;\r
+       int                                             PortCount;\r
+       WM_IB_PORT                              *pPortArray;\r
+\r
+}      WM_IB_DEVICE;\r
+\r
+WM_IB_DEVICE *WmIbDeviceGet(NET64 Guid);\r
+void WmIbDevicePut(WM_IB_DEVICE *pDevice);\r
+\r
+#endif // _WM_DRIVER_H_\r
diff --git a/core/winmad/kernel/wm_provider.c b/core/winmad/kernel/wm_provider.c
new file mode 100644 (file)
index 0000000..7efdba3
--- /dev/null
@@ -0,0 +1,430 @@
+/*\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 "index_list.c"\r
+#include "wm_driver.h"\r
+#include "wm_ioctl.h"\r
+#include "wm_provider.h"\r
+#include "wm_reg.h"\r
+\r
+void WmProviderGet(WM_PROVIDER *pProvider)\r
+{\r
+       InterlockedIncrement(&pProvider->Ref);\r
+}\r
+\r
+void WmProviderPut(WM_PROVIDER *pProvider)\r
+{\r
+       if (InterlockedDecrement(&pProvider->Ref) == 0) {\r
+               KeSetEvent(&pProvider->Event, 0, FALSE);\r
+       }\r
+}\r
+\r
+NTSTATUS WmProviderInit(WM_PROVIDER *pProvider)\r
+{\r
+       WDF_IO_QUEUE_CONFIG     config;\r
+       NTSTATUS status;\r
+\r
+       IndexListInit(&pProvider->RegIndex);\r
+       pProvider->MadHead = NULL;\r
+       pProvider->MadTail = NULL;\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
+       WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);\r
+       status = WdfIoQueueCreate(ControlDevice, &config,\r
+                                                         WDF_NO_OBJECT_ATTRIBUTES, &pProvider->ReadQueue);\r
+       return status;\r
+}\r
+\r
+static void WmInsertMad(WM_PROVIDER *pProvider, ib_mad_element_t *pMad)\r
+{\r
+       if (pProvider->MadHead == NULL) {\r
+               pProvider->MadHead = pMad;\r
+       } else {\r
+               pProvider->MadTail->p_next = pMad;\r
+       }\r
+       pProvider->MadTail = pMad;\r
+}\r
+\r
+static ib_mad_element_t *WmRemoveMad(WM_PROVIDER *pProvider)\r
+{\r
+       ib_mad_element_t *mad;\r
+\r
+       mad = pProvider->MadHead;\r
+       if (mad != NULL) {\r
+               pProvider->MadHead = (ib_mad_element_t *) mad->p_next;\r
+               mad->p_next = NULL;\r
+       }\r
+       return mad;\r
+}\r
+\r
+void WmProviderFlushReceives(WM_PROVIDER *pProvider, WM_REGISTRATION *pRegistration)\r
+{\r
+       ib_mad_element_t        *mad, *next, *list;\r
+\r
+       WdfObjectAcquireLock(pProvider->ReadQueue);\r
+       list = pProvider->MadHead;\r
+       pProvider->MadHead = NULL;\r
+\r
+       for (mad = list; mad != NULL; mad = next) {\r
+               next = mad->p_next;\r
+               mad->p_next = NULL;\r
+\r
+               if (mad->send_context1 == pRegistration) {\r
+                       pRegistration->pDevice->IbInterface.put_mad(mad);\r
+               } else {\r
+                       WmInsertMad(pProvider, mad);\r
+               }\r
+       }\r
+       WdfObjectReleaseLock(pProvider->ReadQueue);\r
+}\r
+\r
+void WmProviderCleanup(WM_PROVIDER *pProvider)\r
+{\r
+       WM_REGISTRATION         *reg;\r
+\r
+       while ((reg = IndexListRemoveHead(&pProvider->RegIndex)) != NULL) {\r
+               WmRegFree(reg);\r
+       }\r
+\r
+       if (InterlockedDecrement(&pProvider->Ref) > 0) {\r
+               KeWaitForSingleObject(&pProvider->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
+\r
+       WdfIoQueuePurgeSynchronously(pProvider->ReadQueue);\r
+       WdfObjectDelete(pProvider->ReadQueue);\r
+\r
+       IndexListDestroy(&pProvider->RegIndex);\r
+}\r
+\r
+// See comment above WmProviderRemoveHandler.\r
+static void WmProviderLockRemove(WM_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 WmProviderRemoveHandler.\r
+static void WmProviderUnlockRemove(WM_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 WmProviderRemoveHandler.\r
+ */\r
+void WmProviderDisableRemove(WM_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 WmProviderRemoveHandler.\r
+ */\r
+void WmProviderEnableRemove(WM_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 WmProviderRemoveHandler(WM_PROVIDER *pProvider, WM_IB_DEVICE *pDevice)\r
+{\r
+       WM_REGISTRATION *reg;\r
+       SIZE_T i;\r
+\r
+       WmProviderLockRemove(pProvider);\r
+       IndexListForEach(&pProvider->RegIndex, i) {\r
+               reg = IndexListAt(&pProvider->RegIndex, i);\r
+               if (reg->pDevice == pDevice) {\r
+                       WmRegRemoveHandler(reg);\r
+               }\r
+       }\r
+       WmProviderUnlockRemove(pProvider);\r
+}\r
+\r
+static NTSTATUS WmCopyRead(WM_PROVIDER *pProvider, WM_IO_MAD *pIoMad,\r
+                                                  ib_mad_element_t *pMad, size_t *pLen)\r
+{\r
+       WM_REGISTRATION         *reg;\r
+\r
+       reg = (WM_REGISTRATION *) pMad->send_context1;\r
+       pIoMad->Id = reg->Id;\r
+\r
+       pIoMad->Status = pMad->status;\r
+       pIoMad->Timeout = pMad->timeout_ms;\r
+       pIoMad->Retries = pMad->retry_cnt;\r
+       pIoMad->Length = pMad->size;\r
+\r
+       pIoMad->Address.Qpn = pMad->remote_qp;\r
+       pIoMad->Address.Qkey = pMad->remote_qkey;\r
+       pIoMad->Address.PkeyIndex = pMad->pkey_index;\r
+\r
+       if ((pIoMad->Address.GrhValid = (UINT8) pMad->grh_valid)) {\r
+               pIoMad->Address.VersionClassFlow = pMad->p_grh->ver_class_flow;\r
+               pIoMad->Address.HopLimit = pMad->p_grh->hop_limit;\r
+               pIoMad->Address.GidIndex = 0;   // TODO: update IBAL to use SGID index\r
+               RtlCopyMemory(pIoMad->Address.Gid, pMad->p_grh->dest_gid.raw, 16);\r
+       }\r
+\r
+       pIoMad->Address.Lid = pMad->remote_lid;\r
+       pIoMad->Address.ServiceLevel = pMad->remote_sl;\r
+       pIoMad->Address.PathBits = pMad->path_bits;\r
+       pIoMad->Address.StaticRate = 0;\r
+       pIoMad->Address.Reserved = 0;\r
+\r
+       if (*pLen >= sizeof(WM_IO_MAD) + pMad->size) {\r
+               RtlCopyMemory(pIoMad + 1, pMad->p_mad_buf, pMad->size);\r
+               *pLen = sizeof(WM_IO_MAD) + pMad->size;\r
+               return STATUS_SUCCESS;\r
+       } else {\r
+               *pLen = sizeof(WM_IO_MAD);\r
+               return STATUS_MORE_ENTRIES;\r
+       }\r
+}\r
+\r
+void WmProviderRead(WM_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WM_REGISTRATION         *reg;\r
+       NTSTATUS                        status;\r
+       WM_IO_MAD                       *wmad;\r
+       size_t                          outlen, len = 0;\r
+\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WM_IO_MAD), &wmad, &outlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       WdfObjectAcquireLock(pProvider->ReadQueue);\r
+       if (pProvider->MadHead == NULL) {\r
+               status = WdfRequestForwardToIoQueue(Request, pProvider->ReadQueue);\r
+               WdfObjectReleaseLock(pProvider->ReadQueue);\r
+               if (NT_SUCCESS(status)) {\r
+                       return;\r
+               }\r
+               goto out;\r
+       }\r
+\r
+       len = outlen;\r
+       status = WmCopyRead(pProvider, wmad, pProvider->MadHead, &len);\r
+       if (NT_SUCCESS(status)) {\r
+               reg = (WM_REGISTRATION *) pProvider->MadHead->send_context1;\r
+               reg->pDevice->IbInterface.put_mad(WmRemoveMad(pProvider));\r
+       }\r
+       WdfObjectReleaseLock(pProvider->ReadQueue);\r
+\r
+out:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+static NTSTATUS WmSendMad(WM_REGISTRATION *pRegistration, WM_IO_MAD *pIoMad, UINT32 size)\r
+{\r
+       ib_al_ifc_t                     *pifc;\r
+       NTSTATUS                        status;\r
+       ib_mad_element_t        *mad;\r
+       ib_api_status_t         ib_status;\r
+\r
+       pifc = &pRegistration->pDevice->IbInterface;\r
+       ib_status = pifc->get_mad(pRegistration->hMadPool, size, &mad);\r
+       if (ib_status != IB_SUCCESS) {\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       mad->context1 = pRegistration;\r
+       RtlCopyMemory(mad->p_mad_buf, pIoMad + 1, size);\r
+       mad->remote_qp = pIoMad->Address.Qpn;\r
+       mad->remote_qkey = pIoMad->Address.Qkey;\r
+       mad->resp_expected = (pIoMad->Timeout > 0);\r
+       mad->timeout_ms = pIoMad->Timeout;\r
+       mad->retry_cnt = pIoMad->Retries;\r
+\r
+       if ((mad->grh_valid = pIoMad->Address.GrhValid)) {\r
+               mad->p_grh->ver_class_flow = pIoMad->Address.VersionClassFlow;\r
+               mad->p_grh->hop_limit = pIoMad->Address.HopLimit;\r
+               // TODO: update IBAL to use SGID index\r
+               // mad->p_grh->src_gid_index = pIoMad->Address.GidIndex;\r
+               RtlCopyMemory(mad->p_grh->dest_gid.raw, pIoMad->Address.Gid, 16);\r
+       }\r
+\r
+       mad->remote_lid = pIoMad->Address.Lid;\r
+       mad->remote_sl = pIoMad->Address.ServiceLevel;\r
+       mad->pkey_index = pIoMad->Address.PkeyIndex;\r
+       mad->path_bits = pIoMad->Address.PathBits;\r
+       mad->p_mad_buf->trans_id &= 0xFFFFFFFF00000000;\r
+\r
+       ib_status = pifc->send_mad(pRegistration->hService, mad, NULL);\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+               goto err;\r
+       }\r
+\r
+       return STATUS_SUCCESS;\r
+\r
+err:\r
+       pRegistration->pDevice->IbInterface.put_mad(mad);\r
+       return status;\r
+}\r
+\r
+void WmProviderWrite(WM_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WM_REGISTRATION         *reg;\r
+       NTSTATUS                        status;\r
+       WM_IO_MAD                       *wmad;\r
+       size_t                          inlen;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WM_IO_MAD) + 24,\r
+                                                                                  &wmad, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       reg = WmRegAcquire(pProvider, wmad->Id);\r
+       if (reg == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto out;\r
+       }\r
+\r
+       status = WmSendMad(reg, wmad, (UINT32) (inlen - sizeof(WM_IO_MAD)));\r
+       WmRegRelease(reg);\r
+\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WmReceiveHandler(ib_mad_svc_handle_t hService, void *Context,\r
+                                         ib_mad_element_t *pMad)\r
+{\r
+       WM_REGISTRATION *reg;\r
+       WM_PROVIDER             *prov = Context;\r
+       WDFREQUEST              request;\r
+       NTSTATUS                status;\r
+       WM_IO_MAD               *wmad;\r
+       size_t                  len = 0;\r
+\r
+       UNREFERENCED_PARAMETER(hService);\r
+\r
+       WdfObjectAcquireLock(prov->ReadQueue);\r
+       status = WdfIoQueueRetrieveNextRequest(prov->ReadQueue, &request);\r
+       if (!NT_SUCCESS(status)) {\r
+               WmInsertMad(prov, pMad);\r
+               WdfObjectReleaseLock(prov->ReadQueue);\r
+               return;\r
+       }\r
+\r
+       status = WdfRequestRetrieveOutputBuffer(request, sizeof(WM_IO_MAD), &wmad, &len);\r
+       if (!NT_SUCCESS(status)) {\r
+               reg = (WM_REGISTRATION *) pMad->send_context1;\r
+               reg->pDevice->IbInterface.put_mad(pMad);\r
+               goto out;\r
+       }\r
+\r
+       status = WmCopyRead(prov, wmad, pMad, &len);\r
+       if (NT_SUCCESS(status)) {\r
+               reg = (WM_REGISTRATION *) pMad->send_context1;\r
+               reg->pDevice->IbInterface.put_mad(pMad);\r
+       } else {\r
+               WmInsertMad(prov, pMad);\r
+       }\r
+       WdfObjectReleaseLock(prov->ReadQueue);\r
+\r
+out:\r
+       WdfRequestCompleteWithInformation(request, status, len);        \r
+}\r
+\r
+void WmSendHandler(ib_mad_svc_handle_t hService, void *Context,\r
+                                  ib_mad_element_t *pMad)\r
+{\r
+       if (pMad->status == IB_SUCCESS) {\r
+               ((WM_REGISTRATION *) pMad->context1)->pDevice->IbInterface.put_mad(pMad);\r
+       } else {\r
+               pMad->send_context1 = (void*) pMad->context1;\r
+               WmReceiveHandler(hService, Context, pMad);\r
+       }\r
+}\r
+\r
+void WmProviderCancel(WM_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WDFREQUEST      request;\r
+       NTSTATUS        status;\r
+\r
+       WdfObjectAcquireLock(pProvider->ReadQueue);\r
+       status = WdfIoQueueRetrieveNextRequest(pProvider->ReadQueue, &request);\r
+\r
+       while (NT_SUCCESS(status)) {\r
+               WdfRequestComplete(request, STATUS_CANCELLED);\r
+               status = WdfIoQueueRetrieveNextRequest(pProvider->ReadQueue, &request);\r
+       }\r
+       WdfObjectReleaseLock(pProvider->ReadQueue);\r
+\r
+       WdfRequestComplete(Request, status);\r
+}\r
diff --git a/core/winmad/kernel/wm_provider.h b/core/winmad/kernel/wm_provider.h
new file mode 100644 (file)
index 0000000..d35b87f
--- /dev/null
@@ -0,0 +1,82 @@
+/*\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 _WM_PROVIDER_H_\r
+#define _WM_PROVIDER_H_\r
+\r
+#include <ntddk.h>\r
+#include <wdf.h>\r
+#include <wdm.h>\r
+\r
+#include <iba\ib_al.h>\r
+#include "wm_driver.h"\r
+#include "index_list.h"\r
+\r
+typedef struct _WM_PROVIDER\r
+{\r
+       LIST_ENTRY                      Entry;\r
+       INDEX_LIST                      RegIndex;\r
+       WDFQUEUE                        ReadQueue;\r
+\r
+       ib_mad_element_t        *MadHead;\r
+       ib_mad_element_t        *MadTail;\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
+}      WM_PROVIDER;\r
+\r
+void WmProviderGet(WM_PROVIDER *pProvider);\r
+void WmProviderPut(WM_PROVIDER *pProvider);\r
+NTSTATUS WmProviderInit(WM_PROVIDER *pProvider);\r
+void WmProviderCleanup(WM_PROVIDER *pProvider);\r
+\r
+void WmProviderRemoveHandler(WM_PROVIDER *pProvider, WM_IB_DEVICE *pDevice);\r
+void WmProviderDisableRemove(WM_PROVIDER *pProvider);\r
+void WmProviderEnableRemove(WM_PROVIDER *pProvider);\r
+\r
+void WmProviderRead(WM_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WmProviderWrite(WM_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WmReceiveHandler(ib_mad_svc_handle_t hService, void *Context,\r
+                                         ib_mad_element_t *pMad);\r
+void WmSendHandler(ib_mad_svc_handle_t hService, void *Context,\r
+                                  ib_mad_element_t *pMad);\r
+void WmProviderFlushReceives(WM_PROVIDER *pProvider,\r
+                                                        struct _WM_REGISTRATION *pRegistration);\r
+void WmProviderCancel(WM_PROVIDER *pProvider, WDFREQUEST Request);\r
+\r
+#endif // _WM_PROVIDER_H_\r
diff --git a/core/winmad/kernel/wm_reg.c b/core/winmad/kernel/wm_reg.c
new file mode 100644 (file)
index 0000000..94d6191
--- /dev/null
@@ -0,0 +1,285 @@
+/*\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_al.h>\r
+#include "wm_driver.h"\r
+#include "wm_reg.h"\r
+#include "wm_ioctl.h"\r
+\r
+WM_REGISTRATION *WmRegAcquire(WM_PROVIDER *pProvider, UINT64 Id)\r
+{\r
+       WM_REGISTRATION *reg;\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WmProviderDisableRemove(pProvider);\r
+       reg = IndexListAt(&pProvider->RegIndex, (SIZE_T) Id);\r
+       if (reg != NULL && reg->pDevice != NULL) {\r
+               InterlockedIncrement(&reg->Ref);\r
+       } else {\r
+               reg = NULL;\r
+               WmProviderEnableRemove(pProvider);\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+       return reg;\r
+}\r
+\r
+void WmRegRelease(WM_REGISTRATION *pRegistration)\r
+{\r
+       WmProviderEnableRemove(pRegistration->pProvider);\r
+       InterlockedDecrement(&pRegistration->Ref);\r
+}\r
+\r
+static WM_REGISTRATION *WmRegAlloc(WM_PROVIDER *pProvider)\r
+{\r
+       WM_REGISTRATION *reg;\r
+\r
+       reg = ExAllocatePoolWithTag(PagedPool, sizeof(WM_REGISTRATION), 'grmw');\r
+       if (reg == NULL) {\r
+               return NULL;\r
+       }\r
+\r
+       RtlZeroMemory(reg, sizeof(WM_REGISTRATION));\r
+       reg->Ref = 1;\r
+\r
+       reg->pProvider = pProvider;\r
+       WmProviderGet(pProvider);\r
+       return reg;\r
+}\r
+\r
+static int WmConvertMethods(ib_mad_svc_t *svc, WM_IO_REGISTER *pAttributes)\r
+{\r
+       int i, j, unsolicited = 0;\r
+\r
+       for (i = 0; i < 16; i++) {\r
+               for (j = 0; j < 8; j++) {\r
+                       if (((pAttributes->Methods[i] >> j) & 0x01) != 0) {\r
+                               svc->method_array[i * 8 + j] = 1;\r
+                               unsolicited = 1;\r
+                       }\r
+               }\r
+       }\r
+       return unsolicited;\r
+}\r
+\r
+static NTSTATUS WmRegInit(WM_REGISTRATION *pRegistration, WM_IO_REGISTER *pAttributes)\r
+{\r
+       WM_IB_DEVICE    *dev;\r
+       ib_qp_create_t  attr;\r
+       ib_mad_svc_t    svc;\r
+       ib_api_status_t ib_status;\r
+       NTSTATUS                status;\r
+\r
+       RtlZeroMemory(&attr, sizeof attr);\r
+       if (pAttributes->Qpn == 0) {\r
+               attr.qp_type = IB_QPT_QP0_ALIAS;\r
+       } else if (pAttributes->Qpn == IB_QP1) {\r
+               attr.qp_type = IB_QPT_QP1_ALIAS;\r
+       } else {\r
+               return STATUS_BAD_NETWORK_PATH;\r
+       }\r
+\r
+       dev = WmIbDeviceGet(pAttributes->Guid);\r
+       if (dev == NULL) {\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       if (--pAttributes->Port > dev->PortCount) {\r
+               status = STATUS_INVALID_PORT_HANDLE;\r
+               goto err1;\r
+       }\r
+\r
+       ib_status = dev->IbInterface.open_al(&pRegistration->hIbal);\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+               goto err1;\r
+       }\r
+\r
+       ib_status = dev->IbInterface.open_ca(pRegistration->hIbal, pAttributes->Guid,\r
+                                                                                NULL, NULL, &pRegistration->hCa);\r
+       if (ib_status != IB_SUCCESS) {\r
+               goto err2;\r
+       }\r
+\r
+       ib_status = dev->IbInterface.alloc_pd(pRegistration->hCa, IB_PDT_ALIAS,\r
+                                                                                 NULL, &pRegistration->hPd);\r
+       if (ib_status != IB_SUCCESS) {\r
+               goto err3;\r
+       }\r
+\r
+       attr.sq_depth = attr.rq_depth = 1;\r
+       attr.sq_sge = attr.rq_sge = 1;\r
+       attr.sq_signaled = 1;\r
+\r
+       ib_status = dev->IbInterface.get_spl_qp(pRegistration->hPd,\r
+                                                                                       dev->pPortArray[pAttributes->Port].Guid,\r
+                                                                                       &attr, pRegistration, NULL,\r
+                                                                                       &pRegistration->hMadPool,\r
+                                                                                       &pRegistration->hQp);\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+               goto err4;\r
+       }\r
+\r
+       svc.mad_svc_context = pRegistration->pProvider;\r
+       svc.pfn_mad_send_cb = WmSendHandler;\r
+       svc.pfn_mad_recv_cb = WmReceiveHandler;\r
+       svc.support_unsol = WmConvertMethods(&svc, pAttributes);\r
+       svc.mgmt_class = pAttributes->Class;\r
+       svc.mgmt_version = pAttributes->Version;\r
+    svc.svc_type = IB_MAD_SVC_DEFAULT;\r
+\r
+       ib_status = dev->IbInterface.reg_mad_svc(pRegistration->hQp, &svc,\r
+                                                                                        &pRegistration->hService);\r
+       if (ib_status != IB_SUCCESS) {\r
+               status = STATUS_UNSUCCESSFUL;\r
+               goto err5;\r
+       }\r
+\r
+       pRegistration->pDevice = dev;\r
+       return STATUS_SUCCESS;\r
+\r
+err5:\r
+       dev->IbInterface.destroy_qp(pRegistration->hQp, NULL);\r
+err4:\r
+       dev->IbInterface.dealloc_pd(pRegistration->hPd, NULL);\r
+err3:\r
+       dev->IbInterface.close_ca(pRegistration->hCa, NULL);\r
+err2:\r
+       dev->IbInterface.close_al(pRegistration->hIbal);\r
+err1:\r
+       WmIbDevicePut(dev);\r
+       pRegistration->pDevice = NULL;\r
+       return status;\r
+}\r
+\r
+void WmRegister(WM_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WM_REGISTRATION *reg;\r
+       WM_IO_REGISTER  *attr;\r
+       UINT64                  *id;\r
+       NTSTATUS                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WM_IO_REGISTER), &attr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       reg = WmRegAlloc(pProvider);\r
+       if (reg == NULL) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err1;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WmProviderDisableRemove(pProvider);\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       status = WmRegInit(reg, attr);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err2;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       reg->Id = IndexListInsertHead(&pProvider->RegIndex, reg);\r
+       if (reg->Id == 0) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err2;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       WmProviderEnableRemove(pProvider);\r
+       *id = reg->Id;\r
+       WdfRequestCompleteWithInformation(Request, status, sizeof(UINT64));\r
+       return;\r
+\r
+err2:\r
+       WmRegFree(reg);\r
+       WmProviderEnableRemove(pProvider);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WmDeregister(WM_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WM_REGISTRATION *reg;\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
+       WmProviderDisableRemove(pProvider);\r
+       reg = IndexListAt(&pProvider->RegIndex, (SIZE_T) *id);\r
+       if (reg == NULL) {\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+       } else if (reg->Ref > 1) {\r
+               status = STATUS_ACCESS_DENIED;\r
+       } else {\r
+               IndexListRemove(&pProvider->RegIndex, (SIZE_T) *id);\r
+               status = STATUS_SUCCESS;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       if (NT_SUCCESS(status)) {\r
+               WmRegFree(reg);\r
+       }\r
+       WmProviderEnableRemove(pProvider);\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WmRegFree(WM_REGISTRATION *pRegistatration)\r
+{\r
+       WmRegRemoveHandler(pRegistatration);\r
+       WmProviderPut(pRegistatration->pProvider);\r
+       ExFreePool(pRegistatration);\r
+}\r
+\r
+void WmRegRemoveHandler(WM_REGISTRATION *pRegistration)\r
+{\r
+       if (pRegistration->pDevice == NULL) {\r
+               return;\r
+       }\r
+\r
+       pRegistration->pDevice->IbInterface.destroy_qp(pRegistration->hQp, NULL);\r
+       pRegistration->pDevice->IbInterface.dealloc_pd(pRegistration->hPd, NULL);\r
+       pRegistration->pDevice->IbInterface.close_ca(pRegistration->hCa, NULL);\r
+       pRegistration->pDevice->IbInterface.close_al(pRegistration->hIbal);\r
+\r
+       WmProviderFlushReceives(pRegistration->pProvider, pRegistration);\r
+       WmIbDevicePut(pRegistration->pDevice);\r
+       pRegistration->pDevice = NULL;\r
+}\r
diff --git a/core/winmad/kernel/wm_reg.h b/core/winmad/kernel/wm_reg.h
new file mode 100644 (file)
index 0000000..7de4acc
--- /dev/null
@@ -0,0 +1,67 @@
+/*\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 _WM_REG_H_\r
+#define _WM_REG_H_\r
+\r
+#include <ntddk.h>\r
+#include <wdm.h>\r
+#include <iba\ib_types.h>\r
+\r
+#include "wm_driver.h"\r
+#include "wm_provider.h"\r
+\r
+typedef struct _WM_REGISTRATION\r
+{\r
+       WM_PROVIDER                             *pProvider;\r
+       WM_IB_DEVICE                    *pDevice;\r
+\r
+       ib_al_handle_t                  hIbal;\r
+       ib_ca_handle_t                  hCa;\r
+       ib_pd_handle_t                  hPd;\r
+       ib_qp_handle_t                  hQp;\r
+       ib_pool_key_t                   hMadPool;\r
+       ib_mad_svc_handle_t             hService;\r
+\r
+       SIZE_T                                  Id;\r
+       LONG                                    Ref;\r
+\r
+}      WM_REGISTRATION;\r
+\r
+void WmRegister(WM_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WmDeregister(WM_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WmRegFree(WM_REGISTRATION *pRegistration);\r
+void WmRegRemoveHandler(WM_REGISTRATION *pRegistration);\r
+\r
+WM_REGISTRATION *WmRegAcquire(WM_PROVIDER *pProvider, UINT64 Id);\r
+void WmRegRelease(WM_REGISTRATION *pRegistration);\r
+\r
+#endif // __WM_REG_H_\r
diff --git a/core/winmad/user/SOURCES b/core/winmad/user/SOURCES
new file mode 100644 (file)
index 0000000..f66b99c
--- /dev/null
@@ -0,0 +1,30 @@
+!if $(FREEBUILD)\r
+TARGETNAME = winmad\r
+!else\r
+TARGETNAME = winmadd\r
+!endif\r
+\r
+TARGETPATH = ..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = DYNLINK\r
+\r
+!if $(_NT_TOOLS_VERSION) == 0x700\r
+DLLDEF = $O\wm_exports.def\r
+!else\r
+DLLDEF = $(OBJ_PATH)\$O\wm_exports.def\r
+!endif\r
+\r
+DLLENTRY = DllMain\r
+USE_MSVCRT=1\r
+\r
+SOURCES = \\r
+       winmad.rc               \\r
+       wm_main.cpp             \\r
+       wm_provider.cpp\r
+\r
+INCLUDES = ..;..\..\..\inc;..\..\..\inc\user;\r
+\r
+USER_C_FLAGS = $(USER_C_FLAGS) -DEXPORT_WM_SYMBOLS\r
+\r
+TARGETLIBS = \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\uuid.lib\r
diff --git a/core/winmad/user/makefile b/core/winmad/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/winmad/user/winmad.rc b/core/winmad/user/winmad.rc
new file mode 100644 (file)
index 0000000..ab68fe7
--- /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                "WinMad (Debug)"\r
+#define VER_INTERNALNAME_STR           "winmadd.dll"\r
+#define VER_ORIGINALFILENAME_STR       "winmadd.dll"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR                "WinMad"\r
+#define VER_INTERNALNAME_STR           "winmad.dll"\r
+#define VER_ORIGINALFILENAME_STR       "winmad.dll"\r
+#endif\r
+\r
+#include <common.ver>\r
diff --git a/core/winmad/user/wm_exports.src b/core/winmad/user/wm_exports.src
new file mode 100644 (file)
index 0000000..2c26af3
--- /dev/null
@@ -0,0 +1,9 @@
+#if DBG\r
+LIBRARY winmadd.dll\r
+#else\r
+LIBRARY winmad.dll\r
+#endif\r
+\r
+EXPORTS\r
+DllCanUnloadNow        PRIVATE\r
+\r
diff --git a/core/winmad/user/wm_main.cpp b/core/winmad/user/wm_main.cpp
new file mode 100644 (file)
index 0000000..59a19e6
--- /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
+#include "wm_provider.h"\r
+\r
+volatile LONG WmRef;\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 WmRef ? S_FALSE : S_OK;\r
+}\r
+\r
+__declspec(dllexport) HRESULT WmGetObject(REFIID riid, LPVOID FAR* ppvObj)\r
+{\r
+       if (riid != IID_IWMProvider) {\r
+               *ppvObj = NULL;\r
+               return E_NOINTERFACE;\r
+       }\r
+\r
+       return CWMProvider::CreateInstance((IWMProvider **) ppvObj);\r
+}\r
diff --git a/core/winmad/user/wm_memory.h b/core/winmad/user/wm_memory.h
new file mode 100644 (file)
index 0000000..30cbfb9
--- /dev/null
@@ -0,0 +1,47 @@
+/*\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 _WM_MEMORY_H_\r
+#define _WM_MEMORY_H_\r
+\r
+#include <windows.h>\r
+\r
+__inline void* __cdecl operator new(size_t size)\r
+{\r
+       return HeapAlloc(GetProcessHeap(), 0, size);\r
+}\r
+\r
+__inline void __cdecl operator delete(void *pObj)\r
+{\r
+       HeapFree(GetProcessHeap(), 0, pObj);\r
+}\r
+\r
+#endif // _WM_MEMORY_H_
\ No newline at end of file
diff --git a/core/winmad/user/wm_provider.cpp b/core/winmad/user/wm_provider.cpp
new file mode 100644 (file)
index 0000000..e5f99ca
--- /dev/null
@@ -0,0 +1,242 @@
+/*\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 <winioctl.h>\r
+\r
+#include "wm_memory.h"\r
+#include "wm_provider.h"\r
+#include "wm_ioctl.h"\r
+\r
+CWMProvider::CWMProvider()\r
+{\r
+       InitializeCriticalSection(&m_CritSecRead);\r
+       InitializeCriticalSection(&m_CritSecWrite);\r
+       m_OverlapRead.hEvent = NULL;\r
+       m_OverlapWrite.hEvent = NULL;\r
+       m_nRef = 1;\r
+       m_hFile = INVALID_HANDLE_VALUE;\r
+       InterlockedIncrement(&WmRef);\r
+}\r
+\r
+STDMETHODIMP CWMProvider::\r
+Init(void)\r
+{\r
+       m_OverlapRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
+       m_OverlapWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
+\r
+       return (m_OverlapRead.hEvent != NULL && m_OverlapWrite.hEvent != NULL) ?\r
+                       NOERROR : E_OUTOFMEMORY;\r
+}\r
+\r
+CWMProvider::~CWMProvider()\r
+{\r
+       if (m_OverlapRead.hEvent != NULL) {\r
+               CloseHandle(m_OverlapWrite.hEvent);\r
+       }\r
+       if (m_OverlapWrite.hEvent != NULL) {\r
+               CloseHandle(m_OverlapWrite.hEvent);\r
+       }\r
+       CloseHandle(m_hFile);\r
+       InterlockedDecrement(&WmRef);\r
+}\r
+\r
+STDMETHODIMP CWMProvider::\r
+QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
+{\r
+       if (riid != IID_IUnknown && riid != IID_IWMProvider) {\r
+               *ppvObj = NULL;\r
+               return E_NOINTERFACE;\r
+       }\r
+\r
+       *ppvObj = this;\r
+       AddRef();\r
+       return NOERROR;\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWMProvider::\r
+AddRef(void)\r
+{\r
+       return InterlockedIncrement(&m_nRef);\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CWMProvider::\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
+STDMETHODIMP CWMProvider::\r
+CancelOverlappedRequests(void)\r
+{\r
+       DWORD   bytes;\r
+\r
+       return WmDeviceIoControl(m_hFile, WM_IOCTL_CANCEL, NULL, 0,\r
+                                                        NULL, 0, &bytes, NULL) ?\r
+                                                        NOERROR : HRESULT_FROM_WIN32(GetLastError());\r
+}\r
+\r
+STDMETHODIMP CWMProvider::\r
+GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                       DWORD *pNumberOfBytesTransferred, BOOL bWait)\r
+{\r
+       return ::GetOverlappedResult(m_hFile, pOverlapped,\r
+                                                                pNumberOfBytesTransferred, bWait);\r
+}\r
+\r
+STDMETHODIMP_(HANDLE) CWMProvider::\r
+GetFileHandle(void)\r
+{\r
+       return m_hFile;\r
+}\r
+\r
+STDMETHODIMP_(BOOL) CWMProvider::\r
+WmDeviceIoControl(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_CritSecWrite);\r
+               DeviceIoControl(hDevice, dwIoControlCode,\r
+                                               lpInBuffer, nInBufferSize,\r
+                                               lpOutBuffer, nOutBufferSize,\r
+                                               lpBytesReturned, &m_OverlapWrite);\r
+               ret = GetOverlappedResult(&m_OverlapWrite, lpBytesReturned, TRUE);\r
+               LeaveCriticalSection(&m_CritSecWrite);\r
+       } else {\r
+               ret = DeviceIoControl(hDevice, dwIoControlCode,\r
+                                                         lpInBuffer, nInBufferSize,\r
+                                                         lpOutBuffer, nOutBufferSize,\r
+                                                         lpBytesReturned, lpOverlapped);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+STDMETHODIMP_(BOOL) CWMProvider::\r
+WmReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,\r
+                  LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)\r
+{\r
+       BOOL ret;\r
+\r
+       if (lpOverlapped == NULL) {\r
+               EnterCriticalSection(&m_CritSecRead);\r
+               ReadFile(hFile, lpBuffer, nNumberOfBytesToRead,\r
+                                lpNumberOfBytesRead, &m_OverlapRead);\r
+               ret = GetOverlappedResult(&m_OverlapRead, lpNumberOfBytesRead, TRUE);\r
+               LeaveCriticalSection(&m_CritSecRead);\r
+       } else {\r
+               ret = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead,\r
+                                          lpNumberOfBytesRead, lpOverlapped);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+STDMETHODIMP_(BOOL) CWMProvider::\r
+WmWriteFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberIfBytesToWrite,\r
+                       LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)\r
+{\r
+       BOOL ret;\r
+\r
+       if (lpOverlapped == NULL) {\r
+               EnterCriticalSection(&m_CritSecWrite);\r
+               WriteFile(hFile, lpBuffer, nNumberIfBytesToWrite,\r
+                                 lpNumberOfBytesWritten, &m_OverlapWrite);\r
+               ret = GetOverlappedResult(&m_OverlapWrite, lpNumberOfBytesWritten, TRUE);\r
+               LeaveCriticalSection(&m_CritSecWrite);\r
+       } else {\r
+               ret = WriteFile(hFile, lpBuffer, nNumberIfBytesToWrite,\r
+                                               lpNumberOfBytesWritten, lpOverlapped);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+STDMETHODIMP CWMProvider::\r
+Register(WM_REGISTER *pAttributes, UINT64 *pId)\r
+{\r
+       DWORD bytes;\r
+\r
+       if (WmDeviceIoControl(m_hFile, WM_IOCTL_REGISTER,\r
+                                                 pAttributes, sizeof WM_REGISTER,\r
+                                                 pId, sizeof UINT64, &bytes, NULL)) {\r
+               return NOERROR;\r
+       } else {\r
+               return HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+}\r
+\r
+STDMETHODIMP CWMProvider::\r
+Deregister(UINT64 Id)\r
+{\r
+       DWORD bytes;\r
+\r
+       if (WmDeviceIoControl(m_hFile, WM_IOCTL_DEREGISTER,\r
+                                                 &Id, sizeof UINT64,\r
+                                                 NULL, 0, &bytes, NULL)) {\r
+               return NOERROR;\r
+       } else {\r
+               return HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+}\r
+\r
+STDMETHODIMP CWMProvider::\r
+Send(WM_MAD *pMad, OVERLAPPED *pOverlapped)\r
+{\r
+       DWORD bytes;\r
+\r
+       if (WmWriteFile(m_hFile, pMad, (DWORD) sizeof(WM_MAD) + pMad->Length,\r
+                                       &bytes, pOverlapped)) {\r
+               return NOERROR;\r
+       } else {\r
+               return HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+}\r
+\r
+STDMETHODIMP CWMProvider::\r
+Receive(WM_MAD *pMad, SIZE_T BufferSize, OVERLAPPED *pOverlapped)\r
+{\r
+       DWORD bytes;\r
+\r
+       if (WmReadFile(m_hFile, pMad, (DWORD) BufferSize, &bytes, pOverlapped)) {\r
+               return NOERROR;\r
+       } else {\r
+               return HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+}\r
diff --git a/core/winmad/user/wm_provider.h b/core/winmad/user/wm_provider.h
new file mode 100644 (file)
index 0000000..b75c2c2
--- /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
+#pragma once\r
+\r
+#ifndef _WM_PROVIDER_H_\r
+#define _WM_PROVIDER_H_\r
+\r
+#include <iba\winmad.h>\r
+\r
+extern volatile LONG WmRef;\r
+\r
+class CWMProvider : IWMProvider\r
+{\r
+public:\r
+       // IUnknown methods\r
+       STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);\r
+       STDMETHODIMP_(ULONG) AddRef();\r
+       STDMETHODIMP_(ULONG) Release();\r
+\r
+       // IWVProvider methods\r
+       STDMETHODIMP CancelOverlappedRequests();\r
+       STDMETHODIMP GetOverlappedResult(OVERLAPPED *pOverlapped,\r
+                                                                        DWORD *pNumberOfBytesTransferred, BOOL bWait);\r
+\r
+       STDMETHODIMP_(HANDLE) GetFileHandle();\r
+       STDMETHODIMP Register(WM_REGISTER *pAttributes, UINT64 *pId);\r
+       STDMETHODIMP Deregister(UINT64 Id);\r
+       STDMETHODIMP Send(WM_MAD *pMad, OVERLAPPED *pOverlapped);\r
+       STDMETHODIMP Receive(WM_MAD *pMad, SIZE_T BufferSize, OVERLAPPED *pOverlapped);\r
+\r
+       CWMProvider();\r
+       STDMETHODIMP Init();\r
+       ~CWMProvider();\r
+       void Delete() {delete this;}\r
+       static STDMETHODIMP CreateInstance(IWMProvider** ppProvider)\r
+       {\r
+               HRESULT hr;\r
+               CWMProvider *wm;\r
+\r
+               wm = new CWMProvider;\r
+               if (wm == NULL) {\r
+                       hr = E_OUTOFMEMORY;\r
+                       goto err1;\r
+               }\r
+\r
+               hr = wm->Init();\r
+               if (FAILED(hr)) {\r
+                       goto err2;\r
+               }\r
+\r
+               wm->m_hFile = CreateFileW(L"\\\\.\\WinMad", GENERIC_READ | GENERIC_WRITE,\r
+                                                                 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,\r
+                                                                 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);\r
+               if (wm->m_hFile == INVALID_HANDLE_VALUE) {\r
+                       hr = HRESULT_FROM_WIN32(GetLastError());\r
+                       goto err2;\r
+               }\r
+               *ppProvider = wm;\r
+               return NOERROR;\r
+\r
+       err2:\r
+               wm->Release();\r
+       err1:\r
+               *ppProvider = NULL;\r
+               return hr;\r
+       }\r
+\r
+       HANDLE                                  m_hFile;\r
+       volatile LONG                   m_nRef;\r
+protected:\r
+       STDMETHODIMP_(BOOL) WmDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,\r
+                                                                                 LPVOID lpInBuffer, DWORD nInBufferSize,\r
+                                                                                 LPVOID lpOutBuffer, DWORD nOutBufferSize,\r
+                                                                                 LPDWORD lpBytesReturned,\r
+                                                                                 LPOVERLAPPED lpOverlapped);\r
+       STDMETHODIMP_(BOOL) WmReadFile(HANDLE hFile, LPVOID lpBuffer,\r
+                                                                  DWORD nNumberOfBytesToRead,\r
+                                                                  LPDWORD lpNumberOfBytesRead,\r
+                                                                  LPOVERLAPPED lpOverlapped);\r
+       STDMETHODIMP_(BOOL) WmWriteFile(HANDLE hFile, LPVOID lpBuffer,\r
+                                                                       DWORD nNumberIfBytesToWrite,\r
+                                                                       LPDWORD lpNumberOfBytesWritten,\r
+                                                                       LPOVERLAPPED lpOverlapped);\r
+\r
+       OVERLAPPED                              m_OverlapWrite;\r
+       OVERLAPPED                              m_OverlapRead;\r
+       CRITICAL_SECTION                m_CritSecWrite;\r
+       CRITICAL_SECTION                m_CritSecRead;\r
+};\r
+\r
+#endif // _WM_PROVIDER_H_
\ No newline at end of file
diff --git a/core/winmad/wm_ioctl.h b/core/winmad/wm_ioctl.h
new file mode 100644 (file)
index 0000000..628b5b6
--- /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
+#pragma once\r
+\r
+#ifndef _WM_IOCTL_H_\r
+#define _WM_IOCTL_H_\r
+\r
+typedef UINT16 NET16;\r
+typedef UINT32 NET32;\r
+typedef UINT64 NET64;\r
+\r
+#define WM_IOCTL(f)    CTL_CODE(FILE_DEVICE_INFINIBAND, f, METHOD_BUFFERED,\\r
+                                                        FILE_READ_DATA | FILE_WRITE_DATA)\r
+\r
+// input parameter / output parameter\r
+// IOCTL\r
+#define WM_IO_FUNCTION_BASE                            0x800\r
+\r
+enum {\r
+       WM_IO_FUNCTION_MIN,\r
+       WM_IO_FUNCTION_REGISTER,\r
+       WM_IO_FUNCTION_DEREGISTER,\r
+       WM_IO_FUNCTION_CANCEL,\r
+       WM_IO_FUNCTION_MAX\r
+};\r
+\r
+// WM_IO_REGISTER / UINT64 Id\r
+#define WM_IOCTL_REGISTER                              WM_IOCTL(WM_IO_FUNCTION_BASE + \\r
+                                                                                                WM_IO_FUNCTION_REGISTER)\r
+\r
+// UINT64 Id / none\r
+#define WM_IOCTL_DEREGISTER                            WM_IOCTL(WM_IO_FUNCTION_BASE + \\r
+                                                                                                WM_IO_FUNCTION_DEREGISTER)\r
+\r
+// none / none\r
+#define WM_IOCTL_CANCEL                                        WM_IOCTL(WM_IO_FUNCTION_BASE + \\r
+                                                                                                WM_IO_FUNCTION_CANCEL)\r
+\r
+#define WM_IOCTL_MIN                                   WM_IO_FUNCTION_BASE + WM_IO_FUNCTION_MIN\r
+#define WM_IOCTL_MAX                                   WM_IO_FUNCTION_BASE + WM_IO_FUNCTION_MAX\r
+\r
+typedef struct _WM_IO_REGISTER\r
+{\r
+       NET64                   Guid;\r
+       NET32                   Qpn;\r
+       UINT8                   Port;\r
+       UINT8                   Class;\r
+       UINT8                   Version;\r
+       UINT8                   Reserved[6];\r
+       UINT8                   Oui[3];\r
+       UINT8                   Methods[16];\r
+\r
+}      WM_IO_REGISTER;\r
+\r
+typedef struct _WM_IO_MAD_AV\r
+{\r
+       NET32                   Qpn;\r
+       NET32                   Qkey;\r
+       NET32                   VersionClassFlow;       \r
+       UINT16                  PkeyIndex;\r
+       UINT8                   HopLimit;\r
+       UINT8                   GidIndex;\r
+       UINT8                   Gid[16];\r
+\r
+       UINT16                  Reserved;\r
+       NET16                   Lid;\r
+       UINT8                   ServiceLevel;\r
+       UINT8                   PathBits;\r
+       UINT8                   StaticRate;\r
+       UINT8                   GrhValid;\r
+\r
+}      WM_IO_MAD_AV;\r
+\r
+#pragma warning(push)\r
+#pragma warning(disable: 4200)\r
+typedef struct _WM_IO_MAD\r
+{\r
+       UINT64                  Id;\r
+       WM_IO_MAD_AV    Address;\r
+\r
+       UINT32                  Status;\r
+       UINT32                  Timeout;\r
+       UINT32                  Retries;\r
+       UINT32                  Length;\r
+\r
+       UINT8                   Data[0];\r
+\r
+}      WM_IO_MAD;\r
+#pragma warning(pop)\r
+\r
+#endif // _WM_IOCTL_H_\r
index b38bc95..085aaa4 100644 (file)
@@ -22,6 +22,10 @@ mthca
 Leonid Keller <leonid@mellanox.co.il>\r
 Tzachi Dar <tzachid@mellanox.co.il>\r
 \r
+OFED compatibility libraries:\r
+libibverbs, libibumad, librdmacm\r
+Sean Hefty <sean.hefty@intel.com>\r
+\r
 OpenSM\r
 Yevgeny Kliteynik <kliteyn@dev.mellanox.co.il>\r
 \r
@@ -35,6 +39,11 @@ Eleanor Witiak <eleanor.witiak@qlogic.com>
 WinOF Installer\r
 Stan Smith <stan.smith@intel.com>\r
 \r
+WinMAD\r
+Sean Hefty <sean.hefty@intel.com>\r
+\r
+WinVerbs\r
+Sean Hefty <sean.hefty@intel.com>\r
+\r
 WSD\r
 Tzachi Dar <tzachid@mellanox.co.il>\r
-\r
diff --git a/inc/user/iba/winmad.h b/inc/user/iba/winmad.h
new file mode 100644 (file)
index 0000000..779ef74
--- /dev/null
@@ -0,0 +1,159 @@
+/*\r
+ * Copyright (c) 1996-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 _WINMAD_H_\r
+#define _WINMAD_H_\r
+\r
+#include <initguid.h>\r
+\r
+#include <unknwn.h>\r
+\r
+typedef UINT64 NET64;\r
+typedef UINT32 NET32;\r
+typedef UINT16 NET16;\r
+\r
+typedef struct _WM_REGISTER\r
+{\r
+       NET64                   Guid;\r
+       NET32                   Qpn;\r
+       UINT8                   Port;\r
+       UINT8                   Class;\r
+       UINT8                   Version;\r
+       UINT8                   Reserved[6];\r
+       UINT8                   Oui[3];\r
+       UINT8                   Methods[16];\r
+\r
+}      WM_REGISTER;\r
+\r
+typedef struct _WM_MAD_AV\r
+{\r
+       NET32                   Qpn;\r
+       NET32                   Qkey;\r
+       NET32                   VersionClassFlow;       \r
+       UINT16                  PkeyIndex;\r
+       UINT8                   HopLimit;\r
+       UINT8                   GidIndex;\r
+       UINT8                   Gid[16];\r
+\r
+       UINT16                  Reserved;\r
+       NET16                   Lid;\r
+       UINT8                   ServiceLevel;\r
+       UINT8                   PathBits;\r
+       UINT8                   StaticRate;\r
+       UINT8                   GrhValid;\r
+\r
+}      WM_MAD_AV;\r
+\r
+#pragma warning(push)\r
+#pragma warning(disable: 4200)\r
+typedef struct _WM_MAD\r
+{\r
+       UINT64                  Id;\r
+       WM_MAD_AV               Address;\r
+\r
+       UINT32                  Status;\r
+       UINT32                  Timeout;\r
+       UINT32                  Retries;\r
+       UINT32                  Length;\r
+\r
+       UINT8                   Data[0];\r
+\r
+}      WM_MAD;\r
+#pragma warning(pop)\r
+\r
+\r
+#undef INTERFACE\r
+#define INTERFACE IWMProvider\r
+// {66094220-A6C0-4206-B620-1D766DB2DE63}\r
+DEFINE_GUID(IID_IWMProvider, 0x66094220, 0xa6c0, 0x4206,\r
+                       0xb6, 0x20, 0x1d, 0x76, 0x6d, 0xb2, 0xde, 0x63);\r
+\r
+DECLARE_INTERFACE_(IWMProvider, IUnknown)\r
+{\r
+       // IUnknown methods\r
+       __override STDMETHOD(QueryInterface)(\r
+               THIS_\r
+               REFIID riid,\r
+               LPVOID FAR* ppvObj\r
+               ) PURE;\r
+\r
+       __override STDMETHOD_(ULONG,AddRef)(\r
+               THIS\r
+               ) PURE;\r
+\r
+       __override STDMETHOD_(ULONG,Release)(\r
+               THIS\r
+               ) PURE;\r
+\r
+       // IWVProvider methods\r
+       STDMETHOD(CancelOverlappedRequests)(\r
+               THIS\r
+               ) PURE;\r
+\r
+       STDMETHOD(GetOverlappedResult)(\r
+               THIS_\r
+               __inout_opt OVERLAPPED *pOverlapped,\r
+               __out DWORD *pNumberOfBytesTransferred,\r
+               __in BOOL bWait\r
+               ) PURE;\r
+\r
+       STDMETHOD_(HANDLE,GetFileHandle)(\r
+               THIS\r
+               ) PURE;\r
+\r
+       STDMETHOD(Register)(\r
+               THIS_\r
+               __in WM_REGISTER* pAttributes,\r
+               __deref_out UINT64* pId\r
+               ) PURE;\r
+\r
+       STDMETHOD(Deregister)(\r
+               THIS_\r
+               __in UINT64 Id\r
+               ) PURE;\r
+\r
+       STDMETHOD(Send)(\r
+               THIS_\r
+               __in WM_MAD* pMad,\r
+               __inout_opt OVERLAPPED *pOverlapped\r
+               ) PURE;\r
+\r
+       STDMETHOD(Receive)(\r
+               THIS_\r
+               __inout_bcount_part(*pBufferSize, *pBufferSize) WM_MAD* pMad,\r
+               __in SIZE_T pBufferSize,\r
+               __inout_opt OVERLAPPED *pOverlapped\r
+               ) PURE;\r
+};\r
+\r
+__declspec(dllexport) HRESULT WmGetObject(REFIID riid, LPVOID FAR* ppvObj);\r
+\r
+#endif // _WINMAD_H_\r
index fcd11f9..92a560e 100644 (file)
--- a/ulp/dirs
+++ b/ulp/dirs
@@ -1,10 +1,11 @@
-DIRS=\\r
-       opensm  \\r
-       dapl    \\r
-       dapl2   \\r
-       ipoib   \\r
-       srp             \\r
-       wsd             \\r
+DIRS =                 \\r
+       opensm          \\r
+       dapl            \\r
+       dapl2           \\r
+       ipoib           \\r
+       srp                     \\r
+       wsd                     \\r
        qlgcvnic        \\r
        libibverbs      \\r
+       libibumad       \\r
        nd\r
diff --git a/ulp/libibumad/AUTHORS b/ulp/libibumad/AUTHORS
new file mode 100644 (file)
index 0000000..1fd9242
--- /dev/null
@@ -0,0 +1,4 @@
+Shahar Frank           <shahar@voltaire.com>\r
+Hal Rosenstock         <halr@voltaire.com>\r
+Sasha Khapyorsky       <sashak@voltaire.com>\r
+Sean Hefty                     <sean.hefty@intel.com>
\ No newline at end of file
diff --git a/ulp/libibumad/COPYING b/ulp/libibumad/COPYING
new file mode 100644 (file)
index 0000000..8d74119
--- /dev/null
@@ -0,0 +1,27 @@
+Copyright (c) 2004, 2005 Voltaire, Inc.  All rights reserved.\r
+Copyright (c) 2008 Intel Corporation.  All rights reserved.\r
+\r
+This software is available to you under the OpenFabrics.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
diff --git a/ulp/libibumad/dirs b/ulp/libibumad/dirs
new file mode 100644 (file)
index 0000000..b1cbe45
--- /dev/null
@@ -0,0 +1,2 @@
+DIRS =         \\r
+       src
\ No newline at end of file
diff --git a/ulp/libibumad/include/infiniband/umad.h b/ulp/libibumad/include/infiniband/umad.h
new file mode 100644 (file)
index 0000000..16adf8c
--- /dev/null
@@ -0,0 +1,224 @@
+/*\r
+ * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.\r
+ * Copyright (c) 2008 Intel Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenFabrics.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 UMAD_H\r
+#define UMAD_H\r
+\r
+#include <windows.h>\r
+#include <iba\winmad.h>\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*\r
+ * Interfaces based on libibumad 1.2.0\r
+ */\r
+\r
+typedef unsigned __int8                uint8_t;\r
+typedef unsigned __int16       uint16_t;\r
+typedef unsigned __int32       uint32_t;\r
+typedef unsigned __int64       uint64_t;\r
+\r
+#define EIO                    5\r
+#define EWOULDBLOCK    11\r
+#define ENOMEM         12\r
+#define EINVAL         22\r
+#define ETIMEDOUT      110\r
+\r
+#define UMAD_ANY_PORT          1       // TODO: support this properly\r
+\r
+// Allow casting to WM_MAD_AV\r
+typedef struct ib_mad_addr\r
+{\r
+       uint32_t                qpn;\r
+       uint32_t                qkey;\r
+       uint32_t                flow_label;\r
+       uint16_t                pkey_index;\r
+       uint8_t                 hop_limit;\r
+       uint8_t                 gid_index;\r
+       uint8_t                 gid[16];\r
+\r
+       uint8_t                 grh_present;\r
+       uint8_t                 reserved_grh;\r
+       uint16_t                lid;\r
+       uint8_t                 sl;\r
+       uint8_t                 path_bits;\r
+       uint8_t                 reserved_rate;\r
+       uint8_t                 traffic_class;\r
+\r
+}      ib_mad_addr_t;\r
+\r
+// Allow casting to WM_MAD\r
+#pragma warning(push)\r
+#pragma warning(disable: 4200)\r
+typedef struct ib_user_mad\r
+{\r
+       uint32_t                agent_id;\r
+       uint32_t                reserved_id;\r
+       ib_mad_addr_t   addr;\r
+\r
+       uint32_t                status;\r
+       uint32_t                timeout_ms;\r
+       uint32_t                retries;\r
+       uint32_t                length;\r
+       uint8_t                 data[0];\r
+\r
+}      ib_user_mad_t;\r
+#pragma warning(pop)\r
+\r
+#define UMAD_CA_NAME_LEN       64\r
+#define UMAD_CA_MAX_PORTS      10      /* 0 - 9 */\r
+#define UMAD_MAX_PORTS         64\r
+\r
+typedef struct umad_port\r
+{\r
+       char                    ca_name[UMAD_CA_NAME_LEN];\r
+       int                             portnum;\r
+       unsigned                base_lid;\r
+       unsigned                lmc;\r
+       unsigned                sm_lid;\r
+       unsigned                sm_sl;\r
+       unsigned                state;\r
+       unsigned                phys_state;\r
+       unsigned                rate;\r
+       uint64_t                capmask;\r
+       uint64_t                gid_prefix;\r
+       uint64_t                port_guid;\r
+       unsigned                pkeys_size;\r
+       uint16_t                *pkeys;\r
+\r
+}      umad_port_t;\r
+\r
+typedef struct umad_ca\r
+{\r
+       char                    ca_name[UMAD_CA_NAME_LEN];\r
+       unsigned                node_type;\r
+       int                             numports;\r
+       char                    fw_ver[20];\r
+       char                    ca_type[40];\r
+       char                    hw_ver[20];\r
+       uint64_t                node_guid;\r
+       uint64_t                system_guid;\r
+       umad_port_t             *ports[UMAD_CA_MAX_PORTS];\r
+\r
+}      umad_ca_t;\r
+\r
+__declspec(dllexport)\r
+int umad_init(void);\r
+__declspec(dllexport)\r
+int umad_done(void);\r
+\r
+__declspec(dllexport)\r
+int umad_get_cas_names(char cas[][UMAD_CA_NAME_LEN], int max);\r
+__declspec(dllexport)\r
+int umad_get_ca_portguids(char *ca_name, uint64_t *portguids, int max);\r
+\r
+__declspec(dllexport)\r
+int umad_get_ca(char *ca_name, umad_ca_t *ca);\r
+__declspec(dllexport)\r
+int umad_release_ca(umad_ca_t *ca);\r
+\r
+__declspec(dllexport)\r
+int umad_get_port(char *ca_name, int portnum, umad_port_t *port);\r
+__declspec(dllexport)\r
+int umad_release_port(umad_port_t *port);\r
+\r
+__declspec(dllexport)\r
+int umad_get_issm_path(char *ca_name, int portnum, char path[], int max);\r
+\r
+__declspec(dllexport)\r
+int umad_open_port(char *ca_name, int portnum);\r
+__declspec(dllexport)\r
+int umad_close_port(int portid);\r
+\r
+__declspec(dllexport)\r
+void *umad_get_mad(void *umad);\r
+\r
+__declspec(dllexport)\r
+size_t umad_size(void);\r
+\r
+__declspec(dllexport)\r
+int umad_status(void *umad);\r
+\r
+__declspec(dllexport)\r
+ib_mad_addr_t *umad_get_mad_addr(void *umad);\r
+__declspec(dllexport)\r
+int umad_set_grh_net(void *umad, void *mad_addr);\r
+__declspec(dllexport)\r
+int umad_set_grh(void *umad, void *mad_addr);\r
+__declspec(dllexport)\r
+int umad_set_addr_net(void *umad, int dlid, int dqp, int sl, int qkey);\r
+__declspec(dllexport)\r
+int umad_set_addr(void *umad, int dlid, int dqp, int sl, int qkey);\r
+__declspec(dllexport)\r
+int umad_set_pkey(void *umad, int pkey_index);\r
+__declspec(dllexport)\r
+int umad_get_pkey(void *umad);\r
+\r
+__declspec(dllexport)\r
+int umad_send(int portid, int agentid, void *umad, int length,\r
+                 int timeout_ms, int retries);\r
+__declspec(dllexport)\r
+int umad_recv(int portid, void *umad, int *length, int timeout_ms);\r
+__declspec(dllexport)\r
+int umad_poll(int portid, int timeout_ms);\r
+HANDLE umad_get_fd(int portid);\r
+\r
+__declspec(dllexport)\r
+int umad_register(int portid, int mgmt_class, int mgmt_version,\r
+                                 uint8_t rmpp_version, long method_mask[16/sizeof(long)]);\r
+__declspec(dllexport)\r
+int umad_register_oui(int portid, int mgmt_class, uint8_t rmpp_version,\r
+                                         uint8_t oui[3], long method_mask[16/sizeof(long)]);\r
+__declspec(dllexport)\r
+int umad_unregister(int portid, int agentid);\r
+\r
+\r
+__declspec(dllexport)\r
+int umad_debug(int level);\r
+__declspec(dllexport)\r
+void umad_addr_dump(ib_mad_addr_t *addr);\r
+__declspec(dllexport)\r
+void umad_dump(void *umad);\r
+\r
+__declspec(dllexport)\r
+void *umad_alloc(int num, size_t size);\r
+\r
+__declspec(dllexport)\r
+void umad_free(void *umad);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* UMAD_H */\r
diff --git a/ulp/libibumad/src/Sources b/ulp/libibumad/src/Sources
new file mode 100644 (file)
index 0000000..1d53cf2
--- /dev/null
@@ -0,0 +1,38 @@
+!if $(FREEBUILD)\r
+TARGETNAME = libibumad\r
+!else\r
+TARGETNAME = libibumadd\r
+!endif\r
+\r
+TARGETPATH = ..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = DYNLINK\r
+\r
+!if $(_NT_TOOLS_VERSION) == 0x700\r
+DLLDEF = $O\ibum_exports.def\r
+!else\r
+DLLDEF = $(OBJ_PATH)\$O\ibum_exports.def\r
+!endif\r
+\r
+DLLENTRY = DllMain\r
+USE_MSVCRT=1\r
+\r
+SOURCES = \\r
+       ibumad.rc               \\r
+       ibum_main.cpp   \\r
+       umad.cpp\r
+\r
+INCLUDES = ..\include;..\..\libibverbs\include;..\..\..\inc;..\..\..\inc\user;\r
+\r
+USER_C_FLAGS = $(USER_C_FLAGS) -DEXPORT_IBUM_SYMBOLS\r
+\r
+TARGETLIBS = \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\uuid.lib                \\r
+       $(SDK_LIB_PATH)\ws2_32.lib              \\r
+!if $(FREEBUILD)\r
+       $(TARGETPATH)\*\winmad.lib              \\r
+       $(TARGETPATH)\*\libibverbs.lib\r
+!else\r
+       $(TARGETPATH)\*\winmadd.lib             \\r
+       $(TARGETPATH)\*\libibverbsd.lib\r
+!endif\r
diff --git a/ulp/libibumad/src/ibum_export.def b/ulp/libibumad/src/ibum_export.def
new file mode 100644 (file)
index 0000000..1d6e3af
--- /dev/null
@@ -0,0 +1,34 @@
+/*\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
+LIBRARY        LIBIBUMAD.DLL\r
+\r
+EXPORTS\r
+       DllCanUnloadNow         PRIVATE\r
+       DllGetClassObject       PRIVATE\r
diff --git a/ulp/libibumad/src/ibum_exports.src b/ulp/libibumad/src/ibum_exports.src
new file mode 100644 (file)
index 0000000..d79244e
--- /dev/null
@@ -0,0 +1,39 @@
+#if DBG\r
+LIBRARY libibumadd.dll\r
+#else\r
+LIBRARY libibumad.dll\r
+#endif\r
+\r
+#ifndef _WIN64\r
+EXPORTS\r
+       umad_init;\r
+       umad_done;\r
+       umad_get_cas_names;\r
+       umad_get_ca_portguids;\r
+       umad_open_port;\r
+       umad_get_ca;\r
+       umad_release_ca;\r
+       umad_get_port;\r
+       umad_release_port;\r
+       umad_close_port;\r
+       umad_get_mad;\r
+       umad_get_issm_path;\r
+       umad_size;\r
+       umad_set_grh;\r
+       umad_set_pkey;\r
+       umad_get_pkey;\r
+       umad_set_addr;\r
+       umad_set_addr_net;\r
+       umad_send;\r
+       umad_recv;\r
+       umad_poll;\r
+       umad_get_fd;\r
+       umad_register;\r
+       umad_register_oui;\r
+       umad_unregister;\r
+       umad_status;\r
+       umad_get_mad_addr;\r
+       umad_debug;\r
+       umad_addr_dump;\r
+       umad_dump;\r
+#endif\r
diff --git a/ulp/libibumad/src/ibum_main.cpp b/ulp/libibumad/src/ibum_main.cpp
new file mode 100644 (file)
index 0000000..f57d13c
--- /dev/null
@@ -0,0 +1,39 @@
+/*\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
+\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
diff --git a/ulp/libibumad/src/ibumad.h b/ulp/libibumad/src/ibumad.h
new file mode 100644 (file)
index 0000000..2ec5965
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+ * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.\r
+ * Copyright (c) 2007 Cisco Systems, Inc.  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
+#ifndef IB_UMAD_H\r
+#define IB_UMAD_H\r
+\r
+__inline void* __cdecl operator new(size_t size)\r
+{\r
+       return HeapAlloc(GetProcessHeap(), 0, size);\r
+}\r
+\r
+__inline void __cdecl operator delete(void *pObj)\r
+{\r
+       HeapFree(GetProcessHeap(), 0, pObj);\r
+}\r
+\r
+#endif /* IB_UMAD_H */\r
diff --git a/ulp/libibumad/src/ibumad.rc b/ulp/libibumad/src/ibumad.rc
new file mode 100644 (file)
index 0000000..11cb546
--- /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                "LibIbVerbs (Debug)"\r
+#define VER_INTERNALNAME_STR           "libibverbsd.dll"\r
+#define VER_ORIGINALFILENAME_STR       "libibverbsd.dll"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR                "LibIbVerbs"\r
+#define VER_INTERNALNAME_STR           "libibverbs.dll"\r
+#define VER_ORIGINALFILENAME_STR       "libibverbs.dll"\r
+#endif\r
+\r
+#include <common.ver>\r
diff --git a/ulp/libibumad/src/makefile b/ulp/libibumad/src/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/ulp/libibumad/src/umad.cpp b/ulp/libibumad/src/umad.cpp
new file mode 100644 (file)
index 0000000..45efdcb
--- /dev/null
@@ -0,0 +1,695 @@
+/*\r
+ * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.\r
+ * Copyright (c) 2008 Intel Corp., Inc.  All rights reserved.\r
+ *\r
+ * This software is available to you under a choice of one of two\r
+ * licenses.  You may choose to be licensed under the terms of the GNU\r
+ * General Public License (GPL) Version 2, available from the file\r
+ * COPYING in the main directory of this source tree, or the\r
+ * OpenIB.org BSD license 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 <windows.h>\r
+#include <stdio.h>\r
+\r
+#include <infiniband/umad.h>\r
+#include <infiniband/verbs.h>\r
+#include <rdma/wvstatus.h>\r
+#include "ibumad.h"\r
+\r
+#define IB_OPENIB_OUI                 (0x001405)\r
+\r
+#define UMAD_MAX_PKEYS 16\r
+\r
+typedef struct um_port\r
+{\r
+       IWMProvider *prov;\r
+       NET64           dev_guid;\r
+       OVERLAPPED      overlap;\r
+       BOOL            pending;\r
+       UINT8           port_num;\r
+\r
+}      um_port_t;\r
+\r
+CRITICAL_SECTION crit_sec;\r
+um_port_t ports[UMAD_MAX_PORTS];\r
+\r
+\r
+__declspec(dllexport)\r
+int umad_init(void)\r
+{\r
+       InitializeCriticalSection(&crit_sec);\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_done(void)\r
+{\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_get_cas_names(char cas[][UMAD_CA_NAME_LEN], int max)\r
+{\r
+       struct ibv_device       **list;\r
+       int                                     cnt, i;\r
+\r
+       list = ibv_get_device_list(&cnt);\r
+       if (list == NULL) {\r
+               return 0;\r
+       }\r
+\r
+       for (i = 0; i < min(cnt, max); i++) {\r
+               strcpy(cas[i], ibv_get_device_name(list[i]));\r
+       }\r
+\r
+       ibv_free_device_list(list);\r
+       return i;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_get_ca_portguids(char *ca_name, uint64_t *portguids, int max)\r
+{\r
+       umad_ca_t       ca;\r
+       int                     ports = 0, i;\r
+\r
+       if (umad_get_ca(ca_name, &ca) < 0)\r
+               return -1;\r
+\r
+       if (ca.numports + 1 > max) {\r
+               umad_release_ca(&ca);\r
+               return -ENOMEM;\r
+       }\r
+\r
+       for (i = 0; i <= ca.numports; i++)\r
+               portguids[ports++] = ca.ports[i]->port_guid;\r
+\r
+       umad_release_ca(&ca);\r
+       return ports;\r
+}\r
+\r
+static void umad_convert_ca_attr(umad_ca_t *ca, ibv_device_attr *attr)\r
+{\r
+       ca->node_type = 1;      // HCA\r
+       ca->numports = attr->phys_port_cnt;\r
+       strncpy(ca->fw_ver, attr->fw_ver, 20);\r
+       memset(ca->ca_type, 0, 40);             // TODO: determine what this should be\r
+       sprintf(ca->hw_ver, "0x%x", attr->hw_ver);\r
+       ca->node_guid = attr->node_guid;\r
+       ca->system_guid = attr->sys_image_guid;\r
+}\r
+\r
+static int umad_query_port(struct ibv_context *context, umad_port_t *port)\r
+{\r
+       ibv_port_attr   attr;\r
+       ibv_gid                 gid;\r
+       int                             i, ret;\r
+\r
+       ret = ibv_query_port(context, (uint8_t) port->portnum, &attr);\r
+       if (ret != 0) {\r
+               return ret;\r
+       }\r
+\r
+       port->base_lid = attr.lid;\r
+       port->lmc = attr.lmc;\r
+       port->sm_lid = attr.sm_lid;\r
+       port->sm_sl = attr.sm_sl;\r
+       port->state = attr.state;\r
+       port->phys_state = attr.phys_state;\r
+       port->rate = attr.active_speed;\r
+       port->capmask = attr.port_cap_flags;\r
+\r
+       // Assume GID 0 contains port GUID and gid prefix\r
+       ret = ibv_query_gid(context, (uint8_t) port->portnum, 0, &gid);\r
+       if (ret != 0) {\r
+               return ret;\r
+       }\r
+\r
+       port->gid_prefix = gid.global.subnet_prefix;\r
+       port->port_guid = gid.global.interface_id;\r
+\r
+       port->pkeys_size = min(UMAD_MAX_PKEYS, attr.pkey_tbl_len);\r
+       for (i = 0; i < (int) port->pkeys_size; i++) {\r
+               ret = ibv_query_pkey(context,(uint8_t)  port->portnum, i, &port->pkeys[i]);\r
+               if (ret != 0) {\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_get_ca(char *ca_name, umad_ca_t *ca)\r
+{\r
+       struct ibv_device       **list;\r
+       struct ibv_context      *context;\r
+       ibv_device_attr         dev_attr;\r
+       int                                     cnt, i, ret = 0;\r
+       uint8_t                         *ports;\r
+       size_t                          port_size;\r
+\r
+       list = ibv_get_device_list(&cnt);\r
+       if (list == NULL) {\r
+               return -ENOMEM;\r
+       }\r
+\r
+       for (i = 0; i < cnt; i++) {\r
+               if (!strcmp(ca_name, ibv_get_device_name(list[i]))) {\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (i == cnt) {\r
+               ret = -EINVAL;\r
+               goto free;\r
+       }\r
+\r
+       context = ibv_open_device(list[i]);\r
+       if (context == NULL) {\r
+               ret = -ENOMEM;\r
+               goto free;\r
+       }\r
+\r
+       ret = ibv_query_device(context, &dev_attr);\r
+       if (ret != 0) {\r
+               goto close;\r
+       }\r
+\r
+       port_size = sizeof(umad_port_t) + sizeof(uint16_t) * UMAD_MAX_PKEYS;\r
+       ports = new uint8_t[port_size * dev_attr.phys_port_cnt];\r
+       if (ports == NULL) {\r
+               ret = -ENOMEM;\r
+               goto close;\r
+       }\r
+\r
+       strcpy(ca->ca_name, ca_name);\r
+       umad_convert_ca_attr(ca, &dev_attr);\r
+\r
+       for (i = 0; i < dev_attr.phys_port_cnt; i++, ports += port_size) {\r
+\r
+               ca->ports[i] = (umad_port_t *) ports;\r
+               strcpy(ca->ports[i]->ca_name, ca_name);\r
+               ca->ports[i]->portnum = i + 1;\r
+               ca->ports[i]->pkeys = (uint16_t *) (ports + sizeof(umad_port_t));\r
+\r
+               ret = umad_query_port(context, ca->ports[i]);\r
+               if (ret != 0) {\r
+                       goto close;\r
+               }\r
+       }\r
+\r
+close:\r
+       ibv_close_device(context);\r
+free:\r
+       ibv_free_device_list(list);\r
+       if (ret != 0) {\r
+               delete ca;\r
+       }\r
+       return ret;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_release_ca(umad_ca_t *ca)\r
+{\r
+       delete ca->ports[0];\r
+       return 0;\r
+}\r
+\r
+static uint64_t umad_get_ca_guid(char *ca_name)\r
+{\r
+       umad_ca_t       ca;\r
+       uint64_t        guid;\r
+       int                     ret;\r
+\r
+       ret = umad_get_ca(ca_name, &ca);\r
+       if (ret != 0) {\r
+               return 0;\r
+       }\r
+\r
+       guid = ca.node_guid;\r
+       umad_release_ca(&ca);\r
+       return guid;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_get_port(char *ca_name, int portnum, umad_port_t *port)\r
+{\r
+       umad_ca_t       ca;\r
+       int                     ret;\r
+\r
+       ret = umad_get_ca(ca_name, &ca);\r
+       if (ret != 0) {\r
+               return ret;\r
+       }\r
+\r
+       memcpy(port, ca.ports[portnum - 1], sizeof(umad_port_t));\r
+\r
+       port->pkeys = new uint16_t[ca.ports[portnum - 1]->pkeys_size];\r
+       if (port->pkeys == NULL) {\r
+               ret = -ENOMEM;\r
+               goto out;\r
+       }\r
+\r
+       memcpy(port->pkeys, ca.ports[portnum - 1]->pkeys,\r
+                  sizeof(uint16_t) * ca.ports[portnum - 1]->pkeys_size);\r
+out:\r
+       umad_release_ca(&ca);\r
+       return ret;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_release_port(umad_port_t *port)\r
+{\r
+       delete port->pkeys;\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_get_issm_path(char *ca_name, int portnum, char path[], int max)\r
+{\r
+       return -EINVAL;\r
+}\r
+\r
+static uint8_t umad_find_port(char *ca_name, enum ibv_port_state state)\r
+{\r
+       umad_ca_t       ca;\r
+       int                     i, ret;\r
+\r
+       ret = umad_get_ca(ca_name, &ca);\r
+       if (ret != 0) {\r
+               return 0;\r
+       }\r
+\r
+       for (i = 0; i < ca.numports; i++) {\r
+               if (ca.ports[i]->state == state) {\r
+                       i = ca.ports[i]->portnum;\r
+                       umad_release_ca(&ca);\r
+                       return (uint8_t) i;\r
+               }\r
+       }\r
+\r
+       umad_release_ca(&ca);\r
+       return 0;\r
+}\r
+\r
+static int umad_find_ca_port(enum ibv_port_state state, char *ca_name, uint8_t *port)\r
+{\r
+       char            names[8][UMAD_CA_NAME_LEN];\r
+       int                     cnt, i;\r
+\r
+       cnt = umad_get_cas_names(names, 8);\r
+\r
+       for (i = 0; i < cnt; i++) {\r
+               *port = umad_find_port(names[i], state);\r
+               if (*port != 0) {\r
+                       strcpy(ca_name, names[i]);\r
+                       return 0;\r
+               }\r
+       }\r
+       return -1;\r
+}\r
+\r
+static int umad_resolve_ca_port(char *ca_name, uint8_t *port)\r
+{\r
+       int ret;\r
+\r
+       if (ca_name[0] != NULL) {\r
+               if (*port != 0) {\r
+                       return 0;\r
+               }\r
+\r
+               *port = umad_find_port(ca_name, IBV_PORT_ACTIVE);\r
+               if (*port != 0) {\r
+                       return 0;\r
+               }\r
+               *port = umad_find_port(ca_name, IBV_PORT_INIT);\r
+               if (*port != 0) {\r
+                       return 0;\r
+               }\r
+               *port = umad_find_port(ca_name, IBV_PORT_DOWN);\r
+               return (*port == 0);\r
+       }\r
+\r
+       ret = umad_find_ca_port(IBV_PORT_ACTIVE, ca_name, port);\r
+       if (ret == 0) {\r
+               return 0;\r
+       }\r
+       ret = umad_find_ca_port(IBV_PORT_INIT, ca_name, port);\r
+       if (ret == 0) {\r
+               return 0;\r
+       }\r
+       ret = umad_find_ca_port(IBV_PORT_DOWN, ca_name, port);\r
+       return ret;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_open_port(char *ca_name, int portnum)\r
+{\r
+       char    name[UMAD_CA_NAME_LEN];\r
+       uint8_t port;\r
+       HRESULT hr;\r
+       int             portid;\r
+\r
+       if (ca_name != NULL) {\r
+               strcpy(name, ca_name);\r
+               port = (uint8_t) portnum;\r
+       } else {\r
+               name[0] = NULL;\r
+               port = 0;\r
+       }\r
+\r
+       hr = umad_resolve_ca_port(name, &port);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       EnterCriticalSection(&crit_sec);\r
+       for (portid = 0; portid < UMAD_MAX_PORTS; portid++) {\r
+               if (ports[portid].prov == NULL) {\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (portid == UMAD_MAX_PORTS) {\r
+               portid = -ENOMEM;\r
+               goto out;\r
+       }\r
+\r
+       ports[portid].overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
+       if (ports[portid].overlap.hEvent == NULL) {\r
+               portid = -ENOMEM;\r
+               goto out;\r
+       }\r
+\r
+       hr = WmGetObject(IID_IWMProvider, (LPVOID*) &ports[portid].prov);\r
+       if (FAILED(hr)) {\r
+               CloseHandle(ports[portid].overlap.hEvent);\r
+               portid = GetLastError() & 0x80000000;\r
+               goto out;\r
+       }\r
+\r
+       ports[portid].dev_guid = umad_get_ca_guid(name);\r
+       ports[portid].port_num = port;\r
+\r
+out:\r
+       LeaveCriticalSection(&crit_sec);\r
+       return portid;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_close_port(int portid)\r
+{\r
+       CloseHandle(ports[portid].overlap.hEvent);\r
+       ports[portid].prov->Release();\r
+\r
+       EnterCriticalSection(&crit_sec);\r
+       ports[portid].prov = NULL;\r
+       LeaveCriticalSection(&crit_sec);\r
+\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_set_grh_net(void *umad, void *mad_addr)\r
+{\r
+       struct ib_user_mad *mad = (struct ib_user_mad *) umad;\r
+       struct ib_mad_addr *addr = (struct ib_mad_addr *) mad_addr;\r
+\r
+       if (mad_addr) {\r
+               mad->addr.grh_present = 1;\r
+               memcpy(mad->addr.gid, addr->gid, 16);\r
+               mad->addr.flow_label = addr->flow_label;\r
+               mad->addr.hop_limit = addr->hop_limit;\r
+               mad->addr.traffic_class = addr->traffic_class;\r
+       } else\r
+               mad->addr.grh_present = 0;\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_set_grh(void *umad, void *mad_addr)\r
+{\r
+       struct ib_user_mad *mad = (struct ib_user_mad *) umad;\r
+       struct ib_mad_addr *addr = (struct ib_mad_addr *) mad_addr;\r
+\r
+       if (mad_addr) {\r
+               mad->addr.grh_present = 1;\r
+               memcpy(mad->addr.gid, addr->gid, 16);\r
+               mad->addr.flow_label = htonl(addr->flow_label);\r
+               mad->addr.hop_limit = addr->hop_limit;\r
+               mad->addr.traffic_class = addr->traffic_class;\r
+       } else\r
+               mad->addr.grh_present = 0;\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_set_pkey(void *umad, int pkey_index)\r
+{\r
+       struct ib_user_mad *mad = (struct ib_user_mad *) umad;\r
+\r
+       mad->addr.pkey_index = (uint16_t) pkey_index;\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_get_pkey(void *umad)\r
+{\r
+       struct ib_user_mad *mad = (struct ib_user_mad *) umad;\r
+\r
+       return mad->addr.pkey_index;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_set_addr(void *umad, int dlid, int dqp, int sl, int qkey)\r
+{\r
+       struct ib_user_mad *mad = (struct ib_user_mad *) umad;\r
+\r
+       mad->addr.qpn = htonl(dqp);\r
+       mad->addr.lid = htons((uint16_t) dlid);\r
+       mad->addr.qkey = htonl(qkey);\r
+       mad->addr.sl = (uint8_t) sl;\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_set_addr_net(void *umad, int dlid, int dqp, int sl, int qkey)\r
+{\r
+       struct ib_user_mad *mad = (struct ib_user_mad *) umad;\r
+\r
+       mad->addr.qpn = dqp;\r
+       mad->addr.lid = (uint16_t) dlid;\r
+       mad->addr.qkey = qkey;\r
+       mad->addr.sl = (uint8_t) sl;\r
+\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_status(void *umad)\r
+{\r
+       return ((struct ib_user_mad *) umad)->status;\r
+}\r
+\r
+__declspec(dllexport)\r
+ib_mad_addr_t *umad_get_mad_addr(void *umad)\r
+{\r
+       return &((struct ib_user_mad *) umad)->addr;\r
+}\r
+\r
+__declspec(dllexport)\r
+void *umad_get_mad(void *umad)\r
+{\r
+       return ((struct ib_user_mad *)umad)->data;\r
+}\r
+\r
+__declspec(dllexport)\r
+void *umad_alloc(int num, size_t size)\r
+{\r
+       return new uint8_t[num * size];\r
+}\r
+\r
+__declspec(dllexport)\r
+void umad_free(void *umad)\r
+{\r
+       delete umad;\r
+}\r
+\r
+__declspec(dllexport)\r
+size_t umad_size(void)\r
+{\r
+       return sizeof(struct ib_user_mad);\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_send(int portid, int agentid, void *umad, int length,\r
+                         int timeout_ms, int retries)\r
+{\r
+       struct ib_user_mad *mad = (struct ib_user_mad *) umad;\r
+       HRESULT hr;\r
+\r
+       mad->agent_id = agentid;\r
+       mad->reserved_id = 0;\r
+\r
+       mad->timeout_ms = (uint32_t) timeout_ms;\r
+       mad->retries    = (uint32_t) retries;\r
+       mad->length             = (uint32_t) length;\r
+\r
+       hr = ports[portid].prov->Send((WM_MAD *) mad, NULL);\r
+       if (FAILED(hr)) {\r
+               return GetLastError();\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_recv(int portid, void *umad, int *length, int timeout_ms)\r
+{\r
+       WM_MAD          *mad = (WM_MAD *) umad;\r
+       um_port_t       *port;\r
+       HRESULT         hr;\r
+\r
+       port = &ports[portid];\r
+       hr = port->prov->Receive(mad, sizeof(WM_MAD) + (size_t) *length, &port->overlap);\r
+\r
+       if (hr == WV_IO_PENDING) {\r
+               if (port->pending && timeout_ms == 0) {\r
+                       do {\r
+                               hr = WaitForSingleObject(port->overlap.hEvent, 250);\r
+                       } while (hr == WAIT_TIMEOUT && port->pending);\r
+               } else {\r
+                       hr = WaitForSingleObject(port->overlap.hEvent, (DWORD) timeout_ms);\r
+                       if (hr == WAIT_TIMEOUT) {\r
+                               return -EWOULDBLOCK;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (FAILED(hr)) {\r
+               return -EIO;\r
+       }\r
+\r
+       if (mad->Length <= (UINT32) *length) {\r
+               port->pending = FALSE;\r
+       }\r
+\r
+       *length = mad->Length;\r
+       return (int) mad->Id;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_poll(int portid, int timeout_ms)\r
+{\r
+       WM_MAD          mad;\r
+       um_port_t       *port;\r
+       HRESULT         hr;\r
+\r
+       port = &ports[portid];\r
+       hr = port->prov->Receive(&mad, sizeof mad, &port->overlap);\r
+\r
+       if (hr == WV_IO_PENDING) {\r
+               hr = WaitForSingleObject(port->overlap.hEvent, (DWORD) timeout_ms);\r
+               if (hr == WAIT_TIMEOUT) {\r
+                       return -ETIMEDOUT;\r
+               }\r
+       }\r
+\r
+       if (FAILED(hr) && hr != ERROR_MORE_DATA) {\r
+               return -EIO;\r
+       }\r
+\r
+       port->pending = TRUE;\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_register_oui(int portid, int mgmt_class, uint8_t rmpp_version,\r
+                                         uint8_t oui[3], long method_mask[16/sizeof(long)])\r
+{\r
+       WM_REGISTER reg;\r
+       UINT64          id = 0;\r
+\r
+       UNREFERENCED_PARAMETER(rmpp_version);\r
+\r
+       reg.Guid = ports[portid].dev_guid;\r
+       reg.Qpn = (mgmt_class == 0x01 || mgmt_class == 0x81) ? 0 : htonl(1);\r
+       reg.Port = ports[portid].port_num;\r
+       reg.Class = (uint8_t) mgmt_class;\r
+       reg.Version = 1;\r
+       memset(reg.Reserved, 0, sizeof(reg.Reserved));\r
+       memcpy(reg.Oui, oui, sizeof(oui));\r
+       if (method_mask != NULL) {\r
+               memcpy(reg.Methods, method_mask, sizeof(reg.Methods));\r
+       } else {\r
+               memset(reg.Methods, 0, sizeof(reg.Methods));\r
+       }\r
+       ports[portid].prov->Register(&reg, &id);\r
+\r
+       return (int) id;\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_register(int portid, int mgmt_class, int mgmt_version,\r
+                                 uint8_t rmpp_version, long method_mask[16/sizeof(long)])\r
+{\r
+       uint8_t oui[3];\r
+\r
+       memset(oui, 0, 3);\r
+       return umad_register_oui(portid, mgmt_class, rmpp_version, oui, method_mask);\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_unregister(int portid, int agentid)\r
+{\r
+       ports[portid].pending = FALSE;\r
+       return ports[portid].prov->Deregister((UINT64) agentid);\r
+}\r
+\r
+HANDLE umad_get_fd(int portid)\r
+{\r
+       return ports[portid].prov->GetFileHandle();\r
+}\r
+\r
+__declspec(dllexport)\r
+int umad_debug(int level)\r
+{\r
+       UNREFERENCED_PARAMETER(level);\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+void umad_addr_dump(ib_mad_addr_t *addr)\r
+{\r
+       UNREFERENCED_PARAMETER(addr);\r
+}\r
+\r
+__declspec(dllexport)\r
+void umad_dump(void *umad)\r
+{\r
+       UNREFERENCED_PARAMETER(umad);\r
+}\r