[ofw] [PATCH v2 2/3] WinMAD: user space library
Sean Hefty
sean.hefty at intel.com
Thu Dec 11 12:22:02 PST 2008
Define and implement the winmad interfaces. The winmad library itself is a fairly
simple wrapper around ReadFile and WriteFile, plus a couple of IOCTLs.
The winmad library is not dependent on other userspace IB or RDMA libraries. The
winmad interfaces are modeled after COM, similar to that defined for winverbs.
Signed-off-by: Sean Hefty <sean.hefty at intel.com>
---
/*
* Copyright (c) 1996-2008 Intel Corporation. All rights reserved.
*
* This software is available to you under the OpenIB.org BSD license
* below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#ifndef _WINMAD_H_
#define _WINMAD_H_
#include <initguid.h>
#include <unknwn.h>
typedef UINT64 NET64;
typedef UINT32 NET32;
typedef UINT16 NET16;
typedef struct _WM_REGISTER
{
NET64 Guid;
NET32 Qpn;
UINT8 Port;
UINT8 Class;
UINT8 Version;
UINT8 Reserved[6];
UINT8 Oui[3];
UINT8 Methods[16];
} WM_REGISTER;
typedef struct _WM_MAD_AV
{
NET32 Qpn;
NET32 Qkey;
NET32 VersionClassFlow;
UINT16 PkeyIndex;
UINT8 HopLimit;
UINT8 GidIndex;
UINT8 Gid[16];
UINT16 Reserved;
NET16 Lid;
UINT8 ServiceLevel;
UINT8 PathBits;
UINT8 StaticRate;
UINT8 GrhValid;
} WM_MAD_AV;
#pragma warning(push)
#pragma warning(disable: 4200)
typedef struct _WM_MAD
{
UINT64 Id;
WM_MAD_AV Address;
UINT32 Status;
UINT32 Timeout;
UINT32 Retries;
UINT32 Length;
UINT8 Data[0];
} WM_MAD;
#pragma warning(pop)
#undef INTERFACE
#define INTERFACE IWMProvider
// {66094220-A6C0-4206-B620-1D766DB2DE63}
DEFINE_GUID(IID_IWMProvider, 0x66094220, 0xa6c0, 0x4206,
0xb6, 0x20, 0x1d, 0x76, 0x6d, 0xb2, 0xde, 0x63);
DECLARE_INTERFACE_(IWMProvider, IUnknown)
{
// IUnknown methods
__override STDMETHOD(QueryInterface)(
THIS_
REFIID riid,
LPVOID FAR* ppvObj
) PURE;
__override STDMETHOD_(ULONG,AddRef)(
THIS
) PURE;
__override STDMETHOD_(ULONG,Release)(
THIS
) PURE;
// IWVProvider methods
STDMETHOD(CancelOverlappedRequests)(
THIS
) PURE;
STDMETHOD(GetOverlappedResult)(
THIS_
__inout_opt OVERLAPPED *pOverlapped,
__out DWORD *pNumberOfBytesTransferred,
__in BOOL bWait
) PURE;
STDMETHOD_(HANDLE,GetFileHandle)(
THIS
) PURE;
STDMETHOD(Register)(
THIS_
__in WM_REGISTER* pAttributes,
__deref_out UINT64* pId
) PURE;
STDMETHOD(Deregister)(
THIS_
__in UINT64 Id
) PURE;
STDMETHOD(Send)(
THIS_
__in WM_MAD* pMad,
__inout_opt OVERLAPPED *pOverlapped
) PURE;
STDMETHOD(Receive)(
THIS_
__inout_bcount_part(*pBufferSize, *pBufferSize) WM_MAD* pMad,
__in SIZE_T pBufferSize,
__inout_opt OVERLAPPED *pOverlapped
) PURE;
};
__declspec(dllexport) HRESULT WmGetObject(REFIID riid, LPVOID FAR* ppvObj);
#endif // _WINMAD_H_
/*
* Copyright (c) 2008 Intel Corporation. All rights reserved.
*
* This software is available to you under the OpenIB.org BSD license
* below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "wm_provider.h"
volatile LONG WmRef;
BOOLEAN WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(dwReason);
UNREFERENCED_PARAMETER(lpReserved);
return TRUE;
}
STDAPI DllCanUnloadNow(void)
{
return WmRef ? S_FALSE : S_OK;
}
__declspec(dllexport) HRESULT WmGetObject(REFIID riid, LPVOID FAR* ppvObj)
{
if (riid != IID_IWMProvider) {
*ppvObj = NULL;
return E_NOINTERFACE;
}
return CWMProvider::CreateInstance((IWMProvider **) ppvObj);
}
/*
* Copyright (c) 2008 Intel Corporation. All rights reserved.
*
* This software is available to you under the OpenIB.org BSD license
* below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#ifndef _WM_MEMORY_H_
#define _WM_MEMORY_H_
#include <windows.h>
__inline void* __cdecl operator new(size_t size)
{
return HeapAlloc(GetProcessHeap(), 0, size);
}
__inline void __cdecl operator delete(void *pObj)
{
HeapFree(GetProcessHeap(), 0, pObj);
}
#endif // _WM_MEMORY_H_
/*
* Copyright (c) 2008 Intel Corporation. All rights reserved.
*
* This software is available to you under the OpenIB.org BSD license
* below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#ifndef _WM_PROVIDER_H_
#define _WM_PROVIDER_H_
#include <iba\winmad.h>
extern volatile LONG WmRef;
class CWMProvider : IWMProvider
{
public:
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IWVProvider methods
STDMETHODIMP CancelOverlappedRequests();
STDMETHODIMP GetOverlappedResult(OVERLAPPED *pOverlapped,
DWORD *pNumberOfBytesTransferred, BOOL bWait);
STDMETHODIMP_(HANDLE) GetFileHandle();
STDMETHODIMP Register(WM_REGISTER *pAttributes, UINT64 *pId);
STDMETHODIMP Deregister(UINT64 Id);
STDMETHODIMP Send(WM_MAD *pMad, OVERLAPPED *pOverlapped);
STDMETHODIMP Receive(WM_MAD *pMad, SIZE_T BufferSize, OVERLAPPED *pOverlapped);
CWMProvider();
STDMETHODIMP Init();
~CWMProvider();
void Delete() {delete this;}
static STDMETHODIMP CreateInstance(IWMProvider** ppProvider)
{
HRESULT hr;
CWMProvider *wm;
wm = new CWMProvider;
if (wm == NULL) {
hr = E_OUTOFMEMORY;
goto err1;
}
hr = wm->Init();
if (FAILED(hr)) {
goto err2;
}
wm->m_hFile = CreateFileW(L"\\\\.\\WinMad", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (wm->m_hFile == INVALID_HANDLE_VALUE) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto err2;
}
*ppProvider = wm;
return NOERROR;
err2:
wm->Release();
err1:
*ppProvider = NULL;
return hr;
}
HANDLE m_hFile;
volatile LONG m_nRef;
protected:
STDMETHODIMP_(BOOL) WmDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,
LPVOID lpInBuffer, DWORD
nInBufferSize,
LPVOID lpOutBuffer, DWORD
nOutBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped);
STDMETHODIMP_(BOOL) WmReadFile(HANDLE hFile, LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped);
STDMETHODIMP_(BOOL) WmWriteFile(HANDLE hFile, LPVOID lpBuffer,
DWORD nNumberIfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped);
OVERLAPPED m_OverlapWrite;
OVERLAPPED m_OverlapRead;
CRITICAL_SECTION m_CritSecWrite;
CRITICAL_SECTION m_CritSecRead;
};
#endif // _WM_PROVIDER_H_
/*
* Copyright (c) 2008 Intel Corporation. All rights reserved.
*
* This software is available to you under the OpenIB.org BSD license
* below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <windows.h>
#include <winioctl.h>
#include "wm_memory.h"
#include "wm_provider.h"
#include "wm_ioctl.h"
CWMProvider::CWMProvider()
{
InitializeCriticalSection(&m_CritSecRead);
InitializeCriticalSection(&m_CritSecWrite);
m_OverlapRead.hEvent = NULL;
m_OverlapWrite.hEvent = NULL;
m_nRef = 1;
m_hFile = INVALID_HANDLE_VALUE;
InterlockedIncrement(&WmRef);
}
STDMETHODIMP CWMProvider::
Init(void)
{
m_OverlapRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_OverlapWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
return (m_OverlapRead.hEvent != NULL && m_OverlapWrite.hEvent != NULL) ?
NOERROR : E_OUTOFMEMORY;
}
CWMProvider::~CWMProvider()
{
if (m_OverlapRead.hEvent != NULL) {
CloseHandle(m_OverlapWrite.hEvent);
}
if (m_OverlapWrite.hEvent != NULL) {
CloseHandle(m_OverlapWrite.hEvent);
}
CloseHandle(m_hFile);
InterlockedDecrement(&WmRef);
}
STDMETHODIMP CWMProvider::
QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
{
if (riid != IID_IUnknown && riid != IID_IWMProvider) {
*ppvObj = NULL;
return E_NOINTERFACE;
}
*ppvObj = this;
AddRef();
return NOERROR;
}
STDMETHODIMP_(ULONG) CWMProvider::
AddRef(void)
{
return InterlockedIncrement(&m_nRef);
}
STDMETHODIMP_(ULONG) CWMProvider::
Release(void)
{
ULONG ref;
ref = (ULONG) InterlockedDecrement(&m_nRef);
if (ref == 0) {
Delete();
}
return ref;
}
STDMETHODIMP CWMProvider::
CancelOverlappedRequests(void)
{
DWORD bytes;
return WmDeviceIoControl(m_hFile, WM_IOCTL_CANCEL, NULL, 0,
NULL, 0, &bytes, NULL) ?
NOERROR : HRESULT_FROM_WIN32(GetLastError());
}
STDMETHODIMP CWMProvider::
GetOverlappedResult(OVERLAPPED *pOverlapped,
DWORD *pNumberOfBytesTransferred, BOOL bWait)
{
return ::GetOverlappedResult(m_hFile, pOverlapped,
pNumberOfBytesTransferred, bWait);
}
STDMETHODIMP_(HANDLE) CWMProvider::
GetFileHandle(void)
{
return m_hFile;
}
STDMETHODIMP_(BOOL) CWMProvider::
WmDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,
LPVOID lpInBuffer, DWORD nInBufferSize,
LPVOID lpOutBuffer, DWORD nOutBufferSize,
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
{
BOOL ret;
if (lpOverlapped == NULL) {
EnterCriticalSection(&m_CritSecWrite);
DeviceIoControl(hDevice, dwIoControlCode,
lpInBuffer, nInBufferSize,
lpOutBuffer, nOutBufferSize,
lpBytesReturned, &m_OverlapWrite);
ret = GetOverlappedResult(&m_OverlapWrite, lpBytesReturned, TRUE);
LeaveCriticalSection(&m_CritSecWrite);
} else {
ret = DeviceIoControl(hDevice, dwIoControlCode,
lpInBuffer, nInBufferSize,
lpOutBuffer, nOutBufferSize,
lpBytesReturned, lpOverlapped);
}
return ret;
}
STDMETHODIMP_(BOOL) CWMProvider::
WmReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
{
BOOL ret;
if (lpOverlapped == NULL) {
EnterCriticalSection(&m_CritSecRead);
ReadFile(hFile, lpBuffer, nNumberOfBytesToRead,
lpNumberOfBytesRead, &m_OverlapRead);
ret = GetOverlappedResult(&m_OverlapRead, lpNumberOfBytesRead, TRUE);
LeaveCriticalSection(&m_CritSecRead);
} else {
ret = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead,
lpNumberOfBytesRead, lpOverlapped);
}
return ret;
}
STDMETHODIMP_(BOOL) CWMProvider::
WmWriteFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberIfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
{
BOOL ret;
if (lpOverlapped == NULL) {
EnterCriticalSection(&m_CritSecWrite);
WriteFile(hFile, lpBuffer, nNumberIfBytesToWrite,
lpNumberOfBytesWritten, &m_OverlapWrite);
ret = GetOverlappedResult(&m_OverlapWrite, lpNumberOfBytesWritten, TRUE);
LeaveCriticalSection(&m_CritSecWrite);
} else {
ret = WriteFile(hFile, lpBuffer, nNumberIfBytesToWrite,
lpNumberOfBytesWritten, lpOverlapped);
}
return ret;
}
STDMETHODIMP CWMProvider::
Register(WM_REGISTER *pAttributes, UINT64 *pId)
{
DWORD bytes;
if (WmDeviceIoControl(m_hFile, WM_IOCTL_REGISTER,
pAttributes, sizeof WM_REGISTER,
pId, sizeof UINT64, &bytes, NULL)) {
return NOERROR;
} else {
return HRESULT_FROM_WIN32(GetLastError());
}
}
STDMETHODIMP CWMProvider::
Deregister(UINT64 Id)
{
DWORD bytes;
if (WmDeviceIoControl(m_hFile, WM_IOCTL_DEREGISTER,
&Id, sizeof UINT64,
NULL, 0, &bytes, NULL)) {
return NOERROR;
} else {
return HRESULT_FROM_WIN32(GetLastError());
}
}
STDMETHODIMP CWMProvider::
Send(WM_MAD *pMad, OVERLAPPED *pOverlapped)
{
DWORD bytes;
if (WmWriteFile(m_hFile, pMad, (DWORD) sizeof(WM_MAD) + pMad->Length,
&bytes, pOverlapped)) {
return NOERROR;
} else {
return HRESULT_FROM_WIN32(GetLastError());
}
}
STDMETHODIMP CWMProvider::
Receive(WM_MAD *pMad, SIZE_T BufferSize, OVERLAPPED *pOverlapped)
{
DWORD bytes;
if (WmReadFile(m_hFile, pMad, (DWORD) BufferSize, &bytes, pOverlapped)) {
return NOERROR;
} else {
return HRESULT_FROM_WIN32(GetLastError());
}
}
More information about the ofw
mailing list