[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