--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#include "NdCq.h"\r
+#include "NdAdapter.h"\r
+#include "NdMw.h"\r
+#include "NdEndpoint.h"\r
+#include "NdProv.h"\r
+#include "NdMr.h"\r
+#include "NdListen.h"\r
+#include "NdConnector.h"\r
+\r
+#include "al_dev.h"\r
+#pragma warning( push, 3 )\r
+#include "winternl.h"\r
+#pragma warning( pop )\r
+\r
+#include <assert.h>\r
+#include <limits.h>\r
+#include <strsafe.h>\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdAdapter.tmh"\r
+#endif\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// HPC Pack 2008 Beta 2 SPI\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+CAdapter::CAdapter(void) :\r
+ m_nRef( 1 ),\r
+ m_hSync( INVALID_HANDLE_VALUE ),\r
+ m_hAsync( INVALID_HANDLE_VALUE ),\r
+ m_hCa( 0 ),\r
+ m_hPd( 0 ),\r
+ m_uCa( NULL ),\r
+ m_uPd( NULL ),\r
+ m_pParent( NULL )\r
+{\r
+ m_Ifc.h_uvp_lib = NULL;\r
+}\r
+\r
+CAdapter::~CAdapter(void)\r
+{\r
+ if( m_hPd )\r
+ DeallocPd();\r
+\r
+ if( m_hCa )\r
+ CloseCa();\r
+\r
+ if( m_hSync != INVALID_HANDLE_VALUE )\r
+ CloseHandle( m_hSync );\r
+\r
+ if( m_hAsync != INVALID_HANDLE_VALUE )\r
+ CloseHandle( m_hAsync );\r
+\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+}\r
+\r
+HRESULT CAdapter::Initialize(\r
+ CProvider* pParent,\r
+ const struct sockaddr* pAddr,\r
+ const IBAT_PORT_RECORD* pPortRecord )\r
+{\r
+ m_pParent = pParent;\r
+ m_pParent->AddRef();\r
+\r
+ HRESULT hr = OpenFiles();\r
+ if( FAILED( hr ) )\r
+ return hr;\r
+\r
+ hr = OpenCa( pPortRecord->CaGuid );\r
+ if( FAILED( hr ) )\r
+ return hr;\r
+\r
+ hr = AllocPd();\r
+ if( FAILED( hr ) )\r
+ return hr;\r
+\r
+ m_PortNum = pPortRecord->PortNum;\r
+ m_PortGuid = pPortRecord->PortGuid;\r
+\r
+ switch( pAddr->sa_family )\r
+ {\r
+ case AF_INET:\r
+ RtlCopyMemory( &m_Addr.v4, pAddr, sizeof(m_Addr.v4) );\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Local address: IP %#x, port %#hx\n", \r
+ cl_hton32(m_Addr.v4.sin_addr.S_un.S_addr), cl_hton16(m_Addr.v4.sin_port) ) );\r
+ break;\r
+ case AF_INET6:\r
+ RtlCopyMemory( &m_Addr.v6, pAddr, sizeof(m_Addr.v6) );\r
+ break;\r
+ default:\r
+ return ND_INVALID_ADDRESS;\r
+ }\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CAdapter::Create(\r
+ CProvider* pParent,\r
+ const struct sockaddr* pAddr,\r
+ const IBAT_PORT_RECORD* pPortRecord,\r
+ __out INDAdapter** ppAdapter\r
+ )\r
+{\r
+ CAdapter* pAdapter = new CAdapter();\r
+ if( pAdapter == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ HRESULT hr = pAdapter->Initialize( pParent, pAddr, pPortRecord );\r
+ if( FAILED( hr ) )\r
+ {\r
+ delete pAdapter;\r
+ return hr;\r
+ }\r
+\r
+ *ppAdapter = pAdapter;\r
+ return ND_SUCCESS;\r
+}\r
+\r
+// IUnknown overrides.\r
+HRESULT CAdapter::QueryInterface(\r
+ const IID &riid,\r
+ LPVOID FAR *ppvObj )\r
+{\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDAdapter ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+ULONG CAdapter::AddRef(void)\r
+{\r
+ return InterlockedIncrement( &m_nRef );\r
+}\r
+\r
+ULONG CAdapter::Release(void)\r
+{\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+}\r
+\r
+// *** INDOverlapped methods ***\r
+HRESULT CAdapter::CancelOverlappedRequests(void)\r
+{\r
+ // Memory registration IOCTLs can't be cancelled.\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CAdapter::GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ *pNumberOfBytesTransferred = 0;\r
+ ::GetOverlappedResult(\r
+ m_hAsync,\r
+ pOverlapped,\r
+ (DWORD*)pNumberOfBytesTransferred,\r
+ bWait );\r
+ return (HRESULT)pOverlapped->Internal;\r
+}\r
+\r
+// INDAdapter overrides.\r
+HANDLE CAdapter::GetFileHandle(void)\r
+{\r
+ return m_hAsync;\r
+}\r
+\r
+HRESULT CAdapter::Query(\r
+ __in DWORD VersionRequested,\r
+ __out_bcount_part_opt(*pBufferSize, *pBufferSize) ND_ADAPTER_INFO* pInfo,\r
+ __inout_opt SIZE_T* pBufferSize\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( VersionRequested != 1 )\r
+ return ND_NOT_SUPPORTED;\r
+\r
+ if( *pBufferSize < sizeof(ND_ADAPTER_INFO1) )\r
+ {\r
+ *pBufferSize = sizeof(ND_ADAPTER_INFO1);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+\r
+ ib_ca_attr_t* pAttr = NULL;\r
+ DWORD size = 0;\r
+ HRESULT hr = QueryCa( pAttr, &size );\r
+ if( hr != ND_BUFFER_OVERFLOW )\r
+ return hr;\r
+\r
+ pAttr = (ib_ca_attr_t*)HeapAlloc( GetProcessHeap(), 0, size );\r
+ if( !pAttr )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ hr = QueryCa( pAttr, &size );\r
+ if( FAILED( hr ) )\r
+ {\r
+ HeapFree( GetProcessHeap(), 0, pAttr );\r
+ return hr;\r
+ }\r
+\r
+ pInfo->MaxInboundSge = pAttr->max_sges;\r
+ pInfo->MaxInboundRequests = pAttr->max_wrs;\r
+ pInfo->MaxInboundLength = INT_MAX;\r
+ pInfo->MaxOutboundSge = pAttr->max_sges;\r
+ pInfo->MaxOutboundRequests = pAttr->max_wrs;\r
+ pInfo->MaxOutboundLength = INT_MAX;\r
+ pInfo->MaxInboundReadLimit = pAttr->max_qp_resp_res;\r
+ pInfo->MaxOutboundReadLimit = pAttr->max_qp_init_depth;\r
+ pInfo->MaxCqEntries = pAttr->max_cqes;\r
+#ifndef SIZE_MAX\r
+#ifdef _WIN64\r
+#define SIZE_MAX _UI64_MAX\r
+#else\r
+#define SIZE_MAX UINT_MAX\r
+#endif\r
+#endif\r
+ if( pAttr->init_region_size > SIZE_MAX )\r
+ pInfo->MaxRegistrationSize = SIZE_MAX;\r
+ else\r
+ pInfo->MaxRegistrationSize = (SIZE_T)pAttr->init_region_size;\r
+ pInfo->MaxWindowSize = pInfo->MaxRegistrationSize;\r
+ pInfo->LargeRequestThreshold = 16 * 1024;\r
+ pInfo->MaxCallerData = 56;\r
+ pInfo->MaxCalleeData = 148;\r
+ *pBufferSize = sizeof(ND_ADAPTER_INFO1);\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CAdapter::Control(\r
+ __in DWORD IoControlCode,\r
+ __in_bcount_opt(InBufferSize) const void* pInBuffer,\r
+ __in SIZE_T InBufferSize,\r
+ __out_bcount_opt(OutBufferSize) void* pOutBuffer,\r
+ __in SIZE_T OutBufferSize,\r
+ __out SIZE_T* pBytesReturned,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ UNREFERENCED_PARAMETER( IoControlCode );\r
+ UNREFERENCED_PARAMETER( pInBuffer );\r
+ UNREFERENCED_PARAMETER( InBufferSize );\r
+ UNREFERENCED_PARAMETER( pOutBuffer );\r
+ UNREFERENCED_PARAMETER( OutBufferSize );\r
+ UNREFERENCED_PARAMETER( pBytesReturned );\r
+ UNREFERENCED_PARAMETER( pOverlapped );\r
+ \r
+ return ND_NOT_SUPPORTED;\r
+}\r
+\r
+HRESULT CAdapter::CreateCompletionQueue(\r
+ __in SIZE_T nEntries,\r
+ __deref_out INDCompletionQueue** ppCq\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ CCq* pCq = new CCq();\r
+ if( pCq == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ HRESULT hr = pCq->Initialize( this, nEntries );\r
+ if( FAILED(hr) )\r
+ {\r
+ delete pCq;\r
+ return hr;\r
+ }\r
+\r
+ *ppCq = pCq;\r
+ return S_OK;\r
+}\r
+\r
+\r
+HRESULT CAdapter::RegisterMemory(\r
+ __in_bcount(BufferSize) const void* pBuffer,\r
+ __in SIZE_T BufferSize,\r
+ __inout OVERLAPPED* pOverlapped,\r
+ __deref_out ND_MR_HANDLE* phMr\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* Get a MR tracking structure. */\r
+ CMr* pMr = new CMr();\r
+ if( pMr == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ pMr->pBase = (const char*)pBuffer;\r
+\r
+ if( BufferSize > ULONG_MAX )\r
+ return ND_INVALID_PARAMETER_2;\r
+ pMr->Length = (uint32_t)BufferSize;\r
+\r
+ /* Clear the mr_ioctl */\r
+ pMr->mr_ioctl.in.h_pd = m_hPd;\r
+ pMr->mr_ioctl.in.mem_create.vaddr_padding = (ULONG_PTR)pBuffer;\r
+ pMr->mr_ioctl.in.mem_create.length = BufferSize;\r
+ // No support for MWs yet, so simulate it.\r
+ pMr->mr_ioctl.in.mem_create.access_ctrl =\r
+ IB_AC_RDMA_READ | IB_AC_RDMA_WRITE | IB_AC_LOCAL_WRITE;\r
+\r
+ *phMr = (ND_MR_HANDLE)pMr;\r
+ //\r
+ // We must issue the IOCTL on the synchronous file handle.\r
+ // If the user bound the async file handle to an I/O completion port\r
+ // DeviceIoControl could succeed, but not return data, so the MR\r
+ // wouldn't be updated.\r
+ //\r
+ // We use a second IOCTL to complet the user's overlapped.\r
+ //\r
+ DWORD bytes_ret = 0;\r
+ BOOL ret = DeviceIoControl( m_hSync, UAL_REG_MR,\r
+ &pMr->mr_ioctl.in, sizeof(pMr->mr_ioctl.in),\r
+ &pMr->mr_ioctl.out, sizeof(pMr->mr_ioctl.out),\r
+ &bytes_ret, NULL );\r
+ if( !ret )\r
+ {\r
+ CL_ASSERT( GetLastError() != ERROR_IO_PENDING );\r
+\r
+ delete pMr;\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+ if( bytes_ret != sizeof(pMr->mr_ioctl.out) || \r
+ pMr->mr_ioctl.out.status != IB_SUCCESS )\r
+ {\r
+ delete pMr;\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+\r
+ //\r
+ // The registration succeeded. Now issue the user's IOCTL.\r
+ //\r
+ pOverlapped->Internal = ND_PENDING;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_hAsync,\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_NOOP,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ 0 );\r
+\r
+ if( hr != ND_PENDING && hr != ND_SUCCESS )\r
+ {\r
+ delete pMr;\r
+ return hr;\r
+ }\r
+\r
+ AddRef();\r
+ return ND_SUCCESS;\r
+}\r
+\r
+HRESULT CAdapter::DeregisterMemory(\r
+ __in ND_MR_HANDLE hMr,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ CMr* pMr = (CMr*)hMr;\r
+\r
+ //\r
+ // We must issue the IOCTL on the synchronous file handle.\r
+ // If the user bound the async file handle to an I/O completion port\r
+ // DeviceIoControl could succeed, but not return data, so the MR\r
+ // wouldn't be updated.\r
+ //\r
+ // We use a second IOCTL to complet the user's overlapped.\r
+ //\r
+ DWORD bytes_ret = 0;\r
+ BOOL ret = DeviceIoControl( m_hSync, UAL_DEREG_MR,\r
+ &pMr->mr_ioctl.out.h_mr, sizeof(pMr->mr_ioctl.out.h_mr),\r
+ &pMr->mr_ioctl.out.status, sizeof(pMr->mr_ioctl.out.status),\r
+ &bytes_ret, NULL );\r
+ if( !ret )\r
+ {\r
+ CL_ASSERT( GetLastError() != ERROR_IO_PENDING );\r
+ pMr->mr_ioctl.out.status = IB_ERROR;\r
+ }\r
+ if( bytes_ret != sizeof(pMr->mr_ioctl.out.status) )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ switch( pMr->mr_ioctl.out.status )\r
+ {\r
+ case IB_SUCCESS:\r
+ {\r
+ delete pMr;\r
+ Release();\r
+\r
+ //\r
+ // The deregistration succeeded. Now issue the user's IOCTL.\r
+ //\r
+ pOverlapped->Internal = ND_PENDING;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_hAsync,\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_NOOP,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ 0 );\r
+ CL_ASSERT( SUCCEEDED( hr ) );\r
+ return hr;\r
+ }\r
+ case IB_RESOURCE_BUSY:\r
+ return ND_DEVICE_BUSY;\r
+\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CAdapter::CreateMemoryWindow(\r
+ __out ND_RESULT* pInvalidateResult,\r
+ __deref_out INDMemoryWindow** ppMw\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ CMw* pMw = new CMw();\r
+ if( pMw == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ HRESULT hr = pMw->Initialize( this, pInvalidateResult );\r
+ if( FAILED(hr) )\r
+ {\r
+ delete pMw;\r
+ return hr;\r
+ }\r
+\r
+ *ppMw = pMw;\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CAdapter::CreateConnector(\r
+ __deref_out INDConnector** ppConnector\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ return CConnector::Create( this, ppConnector );\r
+}\r
+\r
+HRESULT CAdapter::Listen(\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort,\r
+ __deref_out INDListen** ppListen\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ return CListen::Create(\r
+ this,\r
+ Backlog,\r
+ Protocol,\r
+ Port,\r
+ pAssignedPort,\r
+ ppListen\r
+ );\r
+}\r
+\r
+HRESULT CAdapter::GetLocalAddress(\r
+ __out_bcount_part(*pAddressLength, *pAddressLength) struct sockaddr *pAddr,\r
+ __inout SIZE_T *pAddressLength )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ switch( m_Addr.v4.sin_family )\r
+ {\r
+ case AF_INET:\r
+ if( *pAddressLength < sizeof(struct sockaddr_in) )\r
+ {\r
+ *pAddressLength = sizeof(struct sockaddr_in);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ *(struct sockaddr_in*)pAddr = m_Addr.v4;\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Local address: IP %#x, port %#hx\n", \r
+ cl_hton32(m_Addr.v4.sin_addr.S_un.S_addr), cl_hton16(m_Addr.v4.sin_port) ) );\r
+ return S_OK;\r
+\r
+ case AF_INET6:\r
+ if( *pAddressLength < sizeof(struct sockaddr_in6) )\r
+ {\r
+ *pAddressLength = sizeof(struct sockaddr_in6);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ *(struct sockaddr_in6*)pAddr = m_Addr.v6;\r
+ return S_OK;\r
+\r
+ default:\r
+ return ND_INVALID_ADDRESS;\r
+ }\r
+}\r
+\r
+HRESULT CAdapter::OpenFiles(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* First open the kernel device. */\r
+ CL_ASSERT( m_hSync == INVALID_HANDLE_VALUE );\r
+ m_hSync = CreateFile(\r
+ "\\\\.\\ibal",\r
+ GENERIC_READ | GENERIC_WRITE,\r
+ FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+ NULL,\r
+ OPEN_EXISTING,\r
+ 0,\r
+ NULL\r
+ );\r
+ if( m_hSync == INVALID_HANDLE_VALUE )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ // Now issue the BIND IOCTL which associates us as a client.\r
+ ULONG ver = AL_IOCTL_VERSION;\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_BIND,\r
+ &ver,\r
+ sizeof(ver),\r
+ NULL,\r
+ 0,\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+ if( fSuccess != TRUE )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ // Now create the async file.\r
+ m_hAsync = CreateFile(\r
+ "\\\\.\\ibal",\r
+ GENERIC_READ | GENERIC_WRITE,\r
+ FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+ NULL,\r
+ OPEN_EXISTING,\r
+ FILE_FLAG_OVERLAPPED,\r
+ NULL\r
+ );\r
+ if( m_hAsync == INVALID_HANDLE_VALUE )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ /*\r
+ * Send an IOCTL down on the main file handle to bind this file\r
+ * handle with our proxy context.\r
+ */\r
+ UINT64 hFile = (ULONG_PTR)m_hAsync;\r
+ fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_BIND_ND,\r
+ &hFile,\r
+ sizeof(hFile),\r
+ NULL,\r
+ 0,\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+ if( fSuccess != TRUE )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CAdapter::OpenCa(\r
+ __in UINT64 CaGuid )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ual_get_uvp_name_ioctl_t al_ioctl;\r
+\r
+ /* Initialize assuming no user-mode support */\r
+ cl_memclr( &al_ioctl, sizeof(al_ioctl) );\r
+ cl_memclr( &m_Ifc, sizeof(m_Ifc) );\r
+\r
+ /* init with the guid */\r
+ m_Ifc.guid = CaGuid;\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_GET_VENDOR_LIBCFG,\r
+ &CaGuid, sizeof(CaGuid),\r
+ &al_ioctl.out, sizeof(al_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(al_ioctl.out) )\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+\r
+ if( !strlen( al_ioctl.out.uvp_lib_name ) )\r
+ {\r
+ /* Vendor does not implement user-mode library */\r
+ return ND_NOT_SUPPORTED;\r
+ }\r
+\r
+ /*\r
+ * The vendor supports a user-mode library\r
+ * open the library and get the interfaces supported\r
+ */\r
+#if DBG\r
+ HRESULT hr = StringCbCatA( al_ioctl.out.uvp_lib_name, 32, "d.dll" );\r
+#else\r
+ HRESULT hr = StringCbCatA( al_ioctl.out.uvp_lib_name, 32, ".dll" );\r
+#endif\r
+ if( FAILED( hr ) )\r
+ return ND_NOT_SUPPORTED;\r
+\r
+ m_Ifc.h_uvp_lib = LoadLibrary( al_ioctl.out.uvp_lib_name );\r
+ if( m_Ifc.h_uvp_lib == NULL )\r
+ return ND_NOT_SUPPORTED;\r
+\r
+ uvp_get_interface_t pfn_uvp_ifc = (uvp_get_interface_t)GetProcAddress(\r
+ m_Ifc.h_uvp_lib,\r
+ "uvp_get_interface"\r
+ );\r
+\r
+ if( pfn_uvp_ifc == NULL )\r
+ return ND_NOT_SUPPORTED;\r
+\r
+ /* Query the vendor-supported user-mode functions */\r
+ pfn_uvp_ifc( IID_UVP, &m_Ifc.user_verbs );\r
+\r
+ ual_open_ca_ioctl_t ca_ioctl;\r
+ cl_memclr( &ca_ioctl, sizeof(ca_ioctl) );\r
+\r
+ /* Pre call to the UVP library */\r
+ ib_api_status_t status = IB_ERROR;\r
+ if( m_Ifc.user_verbs.pre_open_ca )\r
+ {\r
+ status = m_Ifc.user_verbs.pre_open_ca(\r
+ CaGuid,\r
+ &ca_ioctl.in.umv_buf,\r
+ (ib_ca_handle_t*)(ULONG_PTR)&m_uCa\r
+ );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ CL_ASSERT( status != IB_VERBS_PROCESSING_DONE );\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+ }\r
+ }\r
+\r
+ ca_ioctl.in.guid = CaGuid;\r
+ ca_ioctl.in.context = (ULONG_PTR)this;\r
+\r
+ fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_OPEN_CA,\r
+ &ca_ioctl.in,\r
+ sizeof(ca_ioctl.in),\r
+ &ca_ioctl.out,\r
+ sizeof(ca_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(ca_ioctl.out) )\r
+ {\r
+ status = IB_ERROR;\r
+ }\r
+ else\r
+ {\r
+ status = ca_ioctl.out.status;\r
+ m_hCa = ca_ioctl.out.h_ca;\r
+ }\r
+\r
+ /* Post uvp call */\r
+ if( m_Ifc.user_verbs.post_open_ca )\r
+ {\r
+ status = m_Ifc.user_verbs.post_open_ca(\r
+ CaGuid,\r
+ status,\r
+ (ib_ca_handle_t*)(ULONG_PTR)&m_uCa,\r
+ &ca_ioctl.out.umv_buf );\r
+ }\r
+\r
+ // TODO: Does the UVP need a query call to succeed?\r
+ // IBAL always does this internally.\r
+\r
+ return (status == IB_SUCCESS? S_OK : ND_INSUFFICIENT_RESOURCES );\r
+}\r
+\r
+HRESULT CAdapter::QueryCa(\r
+ __out_bcount(*pSize) ib_ca_attr_t* pAttr,\r
+ __inout DWORD* pSize )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ual_query_ca_ioctl_t ca_ioctl;\r
+\r
+ cl_memclr( &ca_ioctl, sizeof(ca_ioctl) );\r
+\r
+ ca_ioctl.in.h_ca = m_hCa;\r
+ ca_ioctl.in.p_ca_attr = (ULONG_PTR)pAttr;\r
+ ca_ioctl.in.byte_cnt = *pSize;\r
+\r
+ /* Call the uvp pre call if the vendor library provided a valid ca handle */\r
+ ib_api_status_t status;\r
+ if( m_uCa && m_Ifc.user_verbs.pre_query_ca )\r
+ {\r
+ /* Pre call to the UVP library */\r
+ status = m_Ifc.user_verbs.pre_query_ca(\r
+ m_uCa, pAttr, *pSize, &ca_ioctl.in.umv_buf );\r
+ if( status != IB_SUCCESS )\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_QUERY_CA,\r
+ &ca_ioctl.in,\r
+ sizeof(ca_ioctl.in),\r
+ &ca_ioctl.out,\r
+ sizeof(ca_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+ if( fSuccess != TRUE || BytesRet != sizeof(ca_ioctl.out) )\r
+ {\r
+ status = IB_ERROR;\r
+ }\r
+ else\r
+ {\r
+ *pSize = ca_ioctl.out.byte_cnt;\r
+ status = ca_ioctl.out.status;\r
+ }\r
+\r
+ /* The attributes, if any, will be directly copied by proxy */\r
+ /* Post uvp call */\r
+ if( m_uCa && m_Ifc.user_verbs.post_query_ca )\r
+ {\r
+ m_Ifc.user_verbs.post_query_ca( m_uCa,\r
+ status, pAttr, ca_ioctl.out.byte_cnt, &ca_ioctl.out.umv_buf );\r
+ }\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_MEMORY:\r
+ return ND_BUFFER_OVERFLOW;\r
+ default:\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+ }\r
+}\r
+\r
+void CAdapter::CloseCa(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ib_api_status_t status;\r
+\r
+ /* Call the uvp pre call if the vendor library provided a valid ca handle */\r
+ if( m_uCa && m_Ifc.user_verbs.pre_close_ca )\r
+ {\r
+ /* Pre call to the UVP library */\r
+ status = m_Ifc.user_verbs.pre_close_ca( m_uCa );\r
+ if( status != IB_SUCCESS )\r
+ return;\r
+ }\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_CLOSE_CA,\r
+ &m_hCa,\r
+ sizeof(m_hCa),\r
+ &status,\r
+ sizeof(status),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(status) )\r
+ status = IB_ERROR;\r
+\r
+ if( m_uCa && m_Ifc.user_verbs.post_close_ca )\r
+ m_Ifc.user_verbs.post_close_ca( m_uCa, status );\r
+\r
+ if( m_Ifc.h_uvp_lib )\r
+ FreeLibrary( m_Ifc.h_uvp_lib );\r
+\r
+ m_hCa = 0;\r
+}\r
+\r
+HRESULT CAdapter::AllocPd(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* Clear the pd_ioctl */\r
+ ual_alloc_pd_ioctl_t pd_ioctl;\r
+ cl_memclr( &pd_ioctl, sizeof(pd_ioctl) );\r
+\r
+ /* Pre call to the UVP library */\r
+ ib_api_status_t status;\r
+ if( m_uCa && m_Ifc.user_verbs.pre_allocate_pd )\r
+ {\r
+ status = m_Ifc.user_verbs.pre_allocate_pd(\r
+ m_uCa,\r
+ &pd_ioctl.in.umv_buf,\r
+ (ib_pd_handle_t*)(ULONG_PTR)&m_uPd\r
+ );\r
+ if( status != IB_SUCCESS )\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+ }\r
+\r
+ pd_ioctl.in.h_ca = m_hCa;\r
+ pd_ioctl.in.type = IB_PDT_NORMAL;\r
+ pd_ioctl.in.context = (ULONG_PTR)this;\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_ALLOC_PD,\r
+ &pd_ioctl.in,\r
+ sizeof(pd_ioctl.in),\r
+ &pd_ioctl.out,\r
+ sizeof(pd_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(pd_ioctl.out) )\r
+ {\r
+ status = IB_ERROR;\r
+ }\r
+ else\r
+ {\r
+ status = pd_ioctl.out.status;\r
+ if( pd_ioctl.out.status == IB_SUCCESS )\r
+ m_hPd = pd_ioctl.out.h_pd;\r
+ }\r
+\r
+ /* Post uvp call */\r
+ if( m_uCa && m_Ifc.user_verbs.post_allocate_pd )\r
+ {\r
+ m_Ifc.user_verbs.post_allocate_pd(\r
+ m_uCa,\r
+ status,\r
+ (ib_pd_handle_t*)(ULONG_PTR)&m_uPd,\r
+ &pd_ioctl.out.umv_buf );\r
+ }\r
+\r
+ return (status == IB_SUCCESS? S_OK : ND_INSUFFICIENT_RESOURCES);\r
+}\r
+\r
+void CAdapter::DeallocPd(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ib_api_status_t status;\r
+\r
+ /* Call the uvp pre call if the vendor library provided a valid ca handle */\r
+ if( m_uPd && m_Ifc.user_verbs.pre_deallocate_pd )\r
+ {\r
+ /* Pre call to the UVP library */\r
+ status = m_Ifc.user_verbs.pre_deallocate_pd( m_uPd );\r
+ if( status != IB_SUCCESS )\r
+ return;\r
+ }\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_DEALLOC_PD,\r
+ &m_hPd,\r
+ sizeof(m_hPd),\r
+ &status,\r
+ sizeof(status),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess == FALSE || BytesRet != sizeof(status) )\r
+ status = IB_ERROR;\r
+\r
+ /* Call vendor's post_close ca */\r
+ if( m_uPd && m_Ifc.user_verbs.post_deallocate_pd )\r
+ m_Ifc.user_verbs.post_deallocate_pd( m_uPd, status );\r
+\r
+ m_hPd = 0;\r
+}\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+\r
+#include "ndspi.h"\r
+#include "nddebug.h"\r
+#include <iba/ib_al.h>\r
+#include <iba/ib_at_ioctl.h>\r
+#include <ws2tcpip.h>\r
+#include "ual_ci_ca.h"\r
+\r
+#include "NdProv.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+class CCq;\r
+class CAddr;\r
+class CProvider;\r
+\r
+class CAdapter :\r
+ public INDAdapter\r
+{\r
+ friend class CCq;\r
+ friend class CEndpoint;\r
+ friend class CConnector;\r
+ friend class CMw;\r
+ friend class CMr;\r
+ friend class CListen;\r
+\r
+private:\r
+ CAdapter(void);\r
+ ~CAdapter(void);\r
+\r
+ HRESULT Initialize(\r
+ CProvider* pParent,\r
+ const struct sockaddr* pAddr,\r
+ const IBAT_PORT_RECORD* pPortRecord\r
+ );\r
+\r
+public:\r
+ static HRESULT Create(\r
+ CProvider* pParent,\r
+ const struct sockaddr* pAddr,\r
+ const IBAT_PORT_RECORD* pPortRecord,\r
+ __out INDAdapter** ppAdapter\r
+ );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT STDMETHODCALLTYPE CancelOverlappedRequests(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ );\r
+\r
+ // *** INDAdapter methods ***\r
+ HANDLE STDMETHODCALLTYPE GetFileHandle(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE Query(\r
+ __in DWORD VersionRequested,\r
+ __out_bcount_part_opt(*pBufferSize, *pBufferSize) ND_ADAPTER_INFO* pInfo,\r
+ __inout_opt SIZE_T* pBufferSize\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Control(\r
+ __in DWORD IoControlCode,\r
+ __in_bcount_opt(InBufferSize) const void* pInBuffer,\r
+ __in SIZE_T InBufferSize,\r
+ __out_bcount_opt(OutBufferSize) void* pOutBuffer,\r
+ __in SIZE_T OutBufferSize,\r
+ __out SIZE_T* pBytesReturned,\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CreateCompletionQueue(\r
+ __in SIZE_T nEntries,\r
+ __deref_out INDCompletionQueue** ppCq\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE RegisterMemory(\r
+ __in_bcount(BufferSize) const void* pBuffer,\r
+ __in SIZE_T BufferSize,\r
+ __inout OVERLAPPED* pOverlapped,\r
+ __deref_out ND_MR_HANDLE* phMr\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CompleteRegisterMemory(\r
+ __in ND_MR_HANDLE hMr,\r
+ __in OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE DeregisterMemory(\r
+ __in ND_MR_HANDLE hMr,\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CompleteDeregisterMemory(\r
+ __in ND_MR_HANDLE hMr,\r
+ __in OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CreateMemoryWindow(\r
+ __out ND_RESULT* pInvalidateResult,\r
+ __deref_out INDMemoryWindow** ppMw\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CreateConnector(\r
+ __deref_out INDConnector** ppConnector\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Listen(\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort,\r
+ __deref_out INDListen** ppListen\r
+ );\r
+\r
+ HRESULT GetLocalAddress(\r
+ __out_bcount_part(*pAddressLength, *pAddressLength) struct sockaddr* pAddr,\r
+ __inout SIZE_T *pAddressLength );\r
+\r
+private:\r
+ HRESULT OpenFiles(void);\r
+\r
+ HRESULT OpenCa(\r
+ __in UINT64 CaGuid\r
+ );\r
+\r
+ HRESULT QueryCa(\r
+ __out_bcount(*pSize) ib_ca_attr_t* pAttr,\r
+ __inout DWORD* pSize\r
+ );\r
+\r
+ void CloseCa(void);\r
+\r
+ HRESULT AllocPd(void);\r
+\r
+ void DeallocPd(void);\r
+\r
+protected:\r
+ volatile LONG m_nRef;\r
+\r
+ CProvider* m_pParent;\r
+ UINT64 m_PortGuid;\r
+ UINT8 m_PortNum;\r
+\r
+ HANDLE m_hSync;\r
+ HANDLE m_hAsync;\r
+\r
+ ual_ci_interface_t m_Ifc;\r
+ // Kernel IBAL handles.\r
+ uint64_t m_hCa;\r
+ uint64_t m_hPd;\r
+ // UVP handles.\r
+ ib_ca_handle_t m_uCa;\r
+ ib_pd_handle_t m_uPd;\r
+\r
+ union _addr\r
+ {\r
+ struct sockaddr unspec;\r
+ struct sockaddr_in v4;\r
+ struct sockaddr_in6 v6;\r
+\r
+ } m_Addr;\r
+};\r
+\r
+} // namespace
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#include "NdCq.h"\r
+#include "NdAdapter.h"\r
+#include "NdMw.h"\r
+#include "NdEndpoint.h"\r
+#include "NdProv.h"\r
+#include "NdMr.h"\r
+#include "NdListen.h"\r
+#include "NdConnector.h"\r
+\r
+#include "al_dev.h"\r
+#pragma warning( push, 3 )\r
+#include "winternl.h"\r
+#pragma warning( pop )\r
+#include "iba/ibat.h"\r
+\r
+#include <assert.h>\r
+#include <limits.h>\r
+#include <strsafe.h>\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdConnector.tmh"\r
+#endif\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+CConnector::CConnector(void) :\r
+ m_nRef( 1 ),\r
+ m_pParent( NULL ),\r
+ m_pEndpoint( NULL ),\r
+ m_Protocol( 0 ),\r
+ m_LocalPort( 0 ),\r
+ m_cid( 0 ),\r
+ m_fActive( false )\r
+{\r
+}\r
+\r
+CConnector::~CConnector(void)\r
+{\r
+ FreeCid();\r
+\r
+ if( m_pEndpoint )\r
+ m_pEndpoint->Release();\r
+\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+}\r
+\r
+void CConnector::FreeCid(void)\r
+{\r
+ if( m_cid != 0 )\r
+ {\r
+ DWORD bytes_ret;\r
+ DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_DESTROY_CEP,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ NULL,\r
+ 0,\r
+ &bytes_ret,\r
+ NULL );\r
+\r
+ m_cid = 0;\r
+ }\r
+}\r
+\r
+HRESULT CConnector::Create(\r
+ __in CAdapter* pParent,\r
+ __deref_out INDConnector** ppConnector\r
+ )\r
+{\r
+ CConnector* pConnector = new CConnector();\r
+ if( pConnector == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ pConnector->m_pParent = pParent;\r
+ pParent->AddRef();\r
+\r
+ *ppConnector = pConnector;\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CConnector::QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ )\r
+{\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDConnector ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+ULONG CConnector::AddRef(void)\r
+{\r
+ return InterlockedIncrement( &m_nRef );\r
+}\r
+\r
+ULONG CConnector::Release(void)\r
+{\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+}\r
+\r
+// *** INDOverlapped methods ***\r
+HRESULT CConnector::CancelOverlappedRequests(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ DWORD bytes_ret;\r
+ BOOL ret = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_NDI_CANCEL_CM_IRPS,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ NULL,\r
+ 0,\r
+ &bytes_ret,\r
+ NULL );\r
+\r
+ if( ret )\r
+ return S_OK;\r
+ else\r
+ return ND_UNSUCCESSFUL;\r
+}\r
+\r
+HRESULT CConnector::GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ *pNumberOfBytesTransferred = 0;\r
+ ::GetOverlappedResult(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped,\r
+ (DWORD*)pNumberOfBytesTransferred,\r
+ bWait );\r
+ return (HRESULT)pOverlapped->Internal;\r
+}\r
+\r
+HRESULT CConnector::CreateEndpoint(\r
+ __in INDCompletionQueue* pInboundCq,\r
+ __in INDCompletionQueue* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData,\r
+ __deref_out INDEndpoint** ppEndpoint\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ //\r
+ // Check that the verb provider supports user-mode operations.\r
+ // If not, a different class should be created.\r
+ //\r
+ if( m_pParent->m_Ifc.user_verbs.pre_create_qp == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_create_qp == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.nd_get_qp_state == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.pre_destroy_qp == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_destroy_qp == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_send == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_recv == NULL /*||\r
+ m_pParent->m_Ifc.user_verbs.bind_mw == NULL*/ )\r
+ {\r
+ return ND_NOT_SUPPORTED;\r
+ }\r
+\r
+ if( m_pEndpoint != NULL )\r
+ return ND_NOT_SUPPORTED;\r
+\r
+ HRESULT hr = CEndpoint::Create(\r
+ m_pParent,\r
+ static_cast<CCq*>(pInboundCq),\r
+ static_cast<CCq*>(pOutboundCq),\r
+ nInboundEntries,\r
+ nOutboundEntries,\r
+ nInboundSge,\r
+ nOutboundSge,\r
+ InboundReadLimit,\r
+ OutboundReadLimit,\r
+ pMaxInlineData,\r
+ (INDEndpoint**)&m_pEndpoint\r
+ );\r
+\r
+ if( SUCCEEDED( hr ) )\r
+ {\r
+ m_pEndpoint->AddRef();\r
+ *ppEndpoint = m_pEndpoint;\r
+ }\r
+\r
+ return hr;\r
+}\r
+\r
+//\r
+// Connects an endpoint to the specified destinaton address.\r
+//\r
+// Only basic checks on input data are performed in user-mode,\r
+// and request is handed to the kernel, where:\r
+// 1. the destination address is resolved to a destination GID\r
+// 2. the destination GID is used to get a path record\r
+// 3. the path record is used to issue a CM REQ\r
+// 4. a CM REP is received (or REJ or timeout).\r
+// 5. the request is completed.\r
+//\r
+HRESULT CConnector::Connect(\r
+ __inout INDEndpoint* pEndpoint,\r
+ __in_bcount(AddressLength) const struct sockaddr* pAddress,\r
+ __in SIZE_T AddressLength,\r
+ __in INT Protocol,\r
+ __in_opt USHORT LocalPort,\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( AddressLength < sizeof(struct sockaddr) )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ if( Protocol > UCHAR_MAX || Protocol < 0 )\r
+ return ND_INVALID_PARAMETER_4;\r
+\r
+ m_Protocol = (UINT8)Protocol;\r
+\r
+ //\r
+ // CM REQ supports 92 bytes of private data. We expect to use IP\r
+ // addressing annex, which eats up 36 bytes, leaving us with 56.\r
+ //\r
+ if( PrivateDataLength > 56 )\r
+ return ND_BUFFER_OVERFLOW;\r
+\r
+ //\r
+ // Only support connecting the endpoint we created.\r
+ //\r
+ if( pEndpoint != m_pEndpoint )\r
+ return ND_INVALID_PARAMETER_1;\r
+\r
+ //\r
+ // Format the private data to match the RDMA CM annex spec as we\r
+ // check the address validity.\r
+ //\r
+ ual_ndi_req_cm_ioctl_in_t ioctl;\r
+ ioctl.pdata.maj_min_ver = 0;\r
+ if( LocalPort == 0 )\r
+ {\r
+ m_LocalPort = (USHORT)_byteswap_ulong( m_pEndpoint->m_Qpn );\r
+ }\r
+ else\r
+ {\r
+ m_LocalPort = LocalPort;\r
+ }\r
+ ioctl.pdata.src_port = _byteswap_ushort( m_LocalPort );\r
+\r
+ // Resolve the GIDs.\r
+ HRESULT hr = IBAT::Resolve(\r
+ &m_pParent->m_Addr.unspec,\r
+ pAddress,\r
+ (IBAT_PATH_BLOB*)&ioctl.path\r
+ );\r
+ if( FAILED( hr ) )\r
+ {\r
+ if( hr == E_PENDING )\r
+ {\r
+ //\r
+ // Complete the request with a timeout status.\r
+ //\r
+ pOverlapped->Internal = ND_PENDING;\r
+ hr = NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_NOOP,\r
+ &hr,\r
+ sizeof(hr),\r
+ NULL,\r
+ 0 );\r
+ }\r
+ return hr;\r
+ }\r
+\r
+ switch( ((struct sockaddr_in*)pAddress)->sin_family )\r
+ {\r
+ case AF_INET:\r
+ if( AddressLength != sizeof(struct sockaddr_in) )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ if( m_pParent->m_Addr.v4.sin_family != AF_INET )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ //\r
+ // Copy the destination address so we can satisfy a\r
+ // GetPeerAddress request.\r
+ //\r
+ m_PeerAddr.v4 = *(struct sockaddr_in*)pAddress;\r
+\r
+ ioctl.dst_port = m_PeerAddr.v4.sin_port;\r
+ ioctl.pdata.ipv = 0x40;\r
+\r
+ // Local address.\r
+ RtlZeroMemory( &ioctl.pdata.src_ip_addr, ATS_IPV4_OFFSET );\r
+ CopyMemory(\r
+ &ioctl.pdata.src_ip_addr[ATS_IPV4_OFFSET>>2],\r
+ (uint8_t*)&m_pParent->m_Addr.v4.sin_addr,\r
+ sizeof( m_pParent->m_Addr.v4.sin_addr )\r
+ );\r
+\r
+ // Destination address.\r
+ RtlZeroMemory( &ioctl.pdata.dst_ip_addr, ATS_IPV4_OFFSET );\r
+ CopyMemory(\r
+ &ioctl.pdata.dst_ip_addr[ATS_IPV4_OFFSET>>2],\r
+ (uint8_t*)&m_PeerAddr.v4.sin_addr,\r
+ sizeof( m_PeerAddr.v4.sin_addr )\r
+ );\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("local address: IP %#x, port %#hx, dest address: IP %#x, port %#hx\n", \r
+ cl_hton32(m_pParent->m_Addr.v4.sin_addr.S_un.S_addr), cl_hton16(m_pParent->m_Addr.v4.sin_port),\r
+ cl_hton32(m_PeerAddr.v4.sin_addr.S_un.S_addr), cl_hton16(m_PeerAddr.v4.sin_port) ) );\r
+ break;\r
+\r
+ case AF_INET6:\r
+ if( AddressLength != sizeof(struct sockaddr_in6) )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ //\r
+ // Copy the destination address so we can satisfy a\r
+ // GetPeerAddress request.\r
+ //\r
+ m_PeerAddr.v6 = *(struct sockaddr_in6*)pAddress;\r
+\r
+ ioctl.dst_port = m_PeerAddr.v6.sin6_port;\r
+ ioctl.pdata.ipv = 0x60;\r
+\r
+ // Local address.\r
+ CopyMemory(\r
+ ioctl.pdata.src_ip_addr,\r
+ m_pParent->m_Addr.v6.sin6_addr.u.Byte,\r
+ sizeof(ioctl.pdata.src_ip_addr)\r
+ );\r
+\r
+ // Destination address.\r
+ CopyMemory( ioctl.pdata.dst_ip_addr,\r
+ m_PeerAddr.v6.sin6_addr.u.Byte,\r
+ sizeof(ioctl.pdata.dst_ip_addr)\r
+ );\r
+ break;\r
+\r
+ default:\r
+ return ND_INVALID_ADDRESS;\r
+ }\r
+\r
+ // Copy the user's private data.\r
+ CopyMemory( ioctl.pdata.pdata, pPrivateData, PrivateDataLength );\r
+\r
+ //\r
+ // It's only valid to call Connect with a new or reused endpoint:\r
+ // the QP must be in the INIT state.\r
+ //\r
+ switch( m_pParent->m_Ifc.user_verbs.nd_get_qp_state( m_pEndpoint->m_uQp ) )\r
+ {\r
+ case IB_QPS_INIT:\r
+ break;\r
+\r
+ case IB_QPS_RTS:\r
+ return ND_CONNECTION_ACTIVE;\r
+\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+\r
+ //\r
+ // Create the CEP. We do this so that we have a valid CID in user-mode\r
+ // in case the user calls CancelOverlappedRequests or releases the object.\r
+ //\r
+ UINT64 context = 0;\r
+ ual_create_cep_ioctl_t create;\r
+ DWORD bytes_ret;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_CREATE_CEP,\r
+ &context,\r
+ sizeof(context),\r
+ &create,\r
+ sizeof(create),\r
+ &bytes_ret,\r
+ NULL\r
+ );\r
+ if( !fSuccess ||\r
+ bytes_ret != sizeof(create) ||\r
+ create.status != IB_SUCCESS )\r
+ {\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+ }\r
+\r
+ m_cid = create.cid;\r
+\r
+ //\r
+ // Fill in the rest of the input buffer and send the request down\r
+ // to the kernel and let everything else be done there.\r
+ //\r
+ ioctl.h_qp = m_pEndpoint->m_hQp;\r
+ ioctl.guid = m_pParent->m_PortGuid;\r
+ ioctl.cid = m_cid;\r
+ ioctl.prot = m_Protocol;\r
+ ioctl.pdata_size = sizeof(ioctl.pdata);\r
+ ioctl.init_depth = m_pEndpoint->m_Ord;\r
+ ioctl.resp_res = m_pEndpoint->m_Ird;\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Connect QP %#I64x, QPn %#x, Guid %#I64x \n",\r
+ m_pEndpoint->m_hQp,\r
+ m_pEndpoint->m_Qpn,\r
+ m_pParent->m_PortGuid ) );\r
+\r
+ m_fActive = true;\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ hr = NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_REQ_CM,\r
+ &ioctl,\r
+ sizeof(ioctl),\r
+ NULL,\r
+ 0 );\r
+\r
+ if( FAILED( hr ) )\r
+ {\r
+ FreeCid();\r
+ m_pEndpoint->Release();\r
+ m_pEndpoint = NULL;\r
+ }\r
+\r
+ return hr;\r
+}\r
+\r
+HRESULT CConnector::CompleteConnect(\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( !m_fActive )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ if( m_pEndpoint == NULL )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ //\r
+ // Get the UVP's buffer for modify operations.\r
+ //\r
+ void* pOutbuf;\r
+ DWORD szOutbuf;\r
+\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp(\r
+ (const ib_qp_handle_t)m_pEndpoint->m_uQp,\r
+ &pOutbuf,\r
+ &szOutbuf\r
+ );\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("CompleteConnect QP %#I64x, QPn %#x\n", m_pEndpoint->m_hQp, m_pEndpoint->m_Qpn ) );\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ return NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_RTU_CM,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ pOutbuf,\r
+ szOutbuf );\r
+}\r
+\r
+HRESULT CConnector::Accept(\r
+ __in INDEndpoint* pEndpoint,\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( PrivateDataLength > IB_REJ_PDATA_SIZE )\r
+ return ND_BUFFER_OVERFLOW;\r
+\r
+ //\r
+ // Only support connecting the endpoint we created.\r
+ //\r
+ if( pEndpoint != m_pEndpoint )\r
+ return ND_INVALID_PARAMETER_1;\r
+\r
+ //\r
+ // Get the UVP's buffer for modify operations.\r
+ //\r
+ void* pOutbuf;\r
+ DWORD szOutbuf;\r
+\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp(\r
+ static_cast<CEndpoint*>(pEndpoint)->m_uQp,\r
+ &pOutbuf,\r
+ &szOutbuf\r
+ );\r
+\r
+ ual_ndi_rep_cm_ioctl_in_t ioctl;\r
+ ioctl.h_qp = m_pEndpoint->m_hQp;\r
+ ioctl.cid = m_cid;\r
+ ioctl.init_depth = m_pEndpoint->m_Ord;\r
+ ioctl.resp_res = m_pEndpoint->m_Ird;\r
+ ioctl.pdata_size = (uint8_t)PrivateDataLength;\r
+ CopyMemory( &ioctl.pdata, pPrivateData, PrivateDataLength );\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Accept QP %#I64x, cid %d \n", ioctl.h_qp, ioctl.cid ) );\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_REP_CM,\r
+ &ioctl,\r
+ sizeof(ioctl),\r
+ pOutbuf,\r
+ szOutbuf );\r
+\r
+ if( FAILED( hr ) )\r
+ {\r
+ m_pEndpoint->Release();\r
+ m_pEndpoint = NULL;\r
+ }\r
+ return hr;\r
+}\r
+\r
+HRESULT CConnector::Reject(\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( PrivateDataLength > IB_REJ_PDATA_SIZE )\r
+ return ND_BUFFER_OVERFLOW;\r
+\r
+ ual_ndi_rej_cm_ioctl_in_t ioctl;\r
+ ioctl.cid = m_cid;\r
+ ioctl.pdata_size = (uint8_t)PrivateDataLength;\r
+ if( pPrivateData != NULL )\r
+ {\r
+ CopyMemory( &ioctl.pdata, pPrivateData, PrivateDataLength );\r
+ }\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI, \r
+ ("Connection rejected with pdata_size %d, cid %d\n", \r
+ (int)PrivateDataLength, ioctl.cid ));\r
+\r
+ IO_STATUS_BLOCK IoStatus;\r
+ return NtDeviceIoControlFile(\r
+ m_pParent->m_hSync,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ &IoStatus,\r
+ UAL_NDI_REJ_CM,\r
+ &ioctl,\r
+ sizeof(ioctl),\r
+ NULL,\r
+ 0 );\r
+}\r
+\r
+HRESULT CConnector::GetConnectionData(\r
+ __out_opt SIZE_T* pInboundReadLimit,\r
+ __out_opt SIZE_T* pOutboundReadLimit,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ IO_STATUS_BLOCK IoStatus;\r
+ ual_cep_get_pdata_ioctl_t IoctlBuf;\r
+\r
+ IoctlBuf.in.cid = m_cid;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_pParent->m_hSync,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ &IoStatus,\r
+ UAL_CEP_GET_PDATA,\r
+ &IoctlBuf,\r
+ sizeof(IoctlBuf.in),\r
+ &IoctlBuf,\r
+ sizeof(IoctlBuf.out) );\r
+\r
+ // UAL_CEP_GET_PDATA never returns pending.\r
+ if( FAILED( hr ) )\r
+ return hr;\r
+\r
+ // On the passive side, check that we got the REQ private data.\r
+ if( !m_fActive )\r
+ {\r
+ hr = GetPdataForPassive(\r
+ IoctlBuf.out.pdata,\r
+ IoctlBuf.out.pdata_len,\r
+ pPrivateData,\r
+ pPrivateDataLength\r
+ );\r
+ }\r
+ else\r
+ {\r
+ hr = GetPdataForActive(\r
+ IoctlBuf.out.pdata,\r
+ IoctlBuf.out.pdata_len,\r
+ pPrivateData,\r
+ pPrivateDataLength\r
+ );\r
+ }\r
+\r
+ if( FAILED( hr ) && hr != ND_BUFFER_OVERFLOW )\r
+ return hr;\r
+\r
+ if( pInboundReadLimit )\r
+ {\r
+ *pInboundReadLimit = IoctlBuf.out.resp_res;\r
+ }\r
+\r
+ if( pOutboundReadLimit )\r
+ {\r
+ *pOutboundReadLimit = IoctlBuf.out.init_depth;\r
+ }\r
+\r
+ return hr;\r
+}\r
+\r
+HRESULT CConnector::GetLocalAddress(\r
+ __out_bcount_part_opt(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( m_pEndpoint == NULL )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ ib_qp_state_t state =\r
+ m_pParent->m_Ifc.user_verbs.nd_get_qp_state( m_pEndpoint->m_uQp );\r
+ if( state != IB_QPS_RTS )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ HRESULT hr = m_pParent->GetLocalAddress( pAddress, pAddressLength );\r
+ if( FAILED(hr) )\r
+ return hr;\r
+\r
+ // V4 and V6 addresses have the port number in the same place.\r
+ ((struct sockaddr_in*)pAddress)->sin_port = m_LocalPort;\r
+#if DBG || defined(EVENT_TRACING)\r
+ struct sockaddr_in*pAddrV4 = (struct sockaddr_in*)pAddress;\r
+#endif \r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Local address: IP %#x, port %#hx\n", \r
+ cl_hton32(pAddrV4->sin_addr.S_un.S_addr), cl_hton16(pAddrV4->sin_port) ) );\r
+\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CConnector::GetAddressFromPdata(\r
+ __out_bcount_part(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ IO_STATUS_BLOCK IoStatus;\r
+ ual_cep_get_pdata_ioctl_t IoctlBuf;\r
+\r
+ IoctlBuf.in.cid = m_cid;\r
+\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_pParent->m_hSync,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ &IoStatus,\r
+ UAL_CEP_GET_PDATA,\r
+ &IoctlBuf,\r
+ sizeof(IoctlBuf.in),\r
+ &IoctlBuf,\r
+ sizeof(IoctlBuf.out) );\r
+\r
+ // UAL_CEP_GET_PDATA never returns pending.\r
+ if( FAILED( hr ) )\r
+ {\r
+ CL_ASSERT( hr != ND_PENDING );\r
+ return hr;\r
+ }\r
+\r
+ if( IoctlBuf.out.pdata_len != IB_REQ_PDATA_SIZE )\r
+ return ND_CONNECTION_ABORTED;\r
+\r
+ ib_cm_rdma_req_t* pIpData = (ib_cm_rdma_req_t*)&IoctlBuf.out.pdata;\r
+ CL_ASSERT( pIpData->maj_min_ver == 0 );\r
+\r
+ SIZE_T len;\r
+ switch( pIpData->ipv )\r
+ {\r
+ case 0x40:\r
+ len = 4;\r
+ break;\r
+ case 0x60:\r
+ len = 16;\r
+ break;\r
+ default:\r
+ CL_ASSERT( pIpData->ipv == 0x40 || pIpData->ipv == 0x60 );\r
+ len = 0;\r
+ break;\r
+ }\r
+\r
+ if( len > *pAddressLength )\r
+ {\r
+ *pAddressLength = len;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+\r
+ ((struct sockaddr_in*)pAddress)->sin_port =\r
+ _byteswap_ushort( pIpData->src_port );\r
+\r
+ switch( pIpData->ipv )\r
+ {\r
+ case 0x40:\r
+ ((struct sockaddr_in*)pAddress)->sin_family = AF_INET;\r
+ ((struct sockaddr_in*)pAddress)->sin_addr.s_addr = pIpData->src_ip_addr[3];\r
+ ZeroMemory( ((struct sockaddr_in*)pAddress)->sin_zero,\r
+ sizeof( ((struct sockaddr_in*)pAddress)->sin_zero ) );\r
+ break;\r
+\r
+ case 0x60:\r
+ ((struct sockaddr_in6*)pAddress)->sin6_family = AF_INET6;\r
+ ((struct sockaddr_in6*)pAddress)->sin6_flowinfo = 0;\r
+ RtlCopyMemory( (char*)((struct sockaddr_in6*)pAddress)->sin6_addr.s6_bytes,\r
+ (char *const)pIpData->src_ip_addr, sizeof(pIpData->src_ip_addr) );\r
+ ((struct sockaddr_in6*)pAddress)->sin6_scope_id = 0;\r
+ break;\r
+ }\r
+\r
+ *pAddressLength = len;\r
+ return hr;\r
+}\r
+\r
+HRESULT CConnector::GetPeerAddress(\r
+ __out_bcount_part_opt(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( !m_fActive )\r
+ return GetAddressFromPdata( pAddress, pAddressLength );\r
+\r
+ if( m_pEndpoint == NULL )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ ib_qp_state_t state =\r
+ m_pParent->m_Ifc.user_verbs.nd_get_qp_state( m_pEndpoint->m_uQp );\r
+ if( state != IB_QPS_RTS )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ switch( m_PeerAddr.v4.sin_family )\r
+ {\r
+ case AF_INET:\r
+ if( *pAddressLength < sizeof(struct sockaddr_in) )\r
+ {\r
+ *pAddressLength = sizeof(struct sockaddr_in);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ *(struct sockaddr_in*)pAddress = m_PeerAddr.v4;\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Peer address: IP %#x, port %#hx\n", \r
+ cl_hton32(m_PeerAddr.v4.sin_addr.S_un.S_addr), cl_hton16(m_PeerAddr.v4.sin_port) ) );\r
+ break;\r
+\r
+ case AF_INET6:\r
+ if( *pAddressLength < sizeof(struct sockaddr_in6) )\r
+ {\r
+ *pAddressLength = sizeof(struct sockaddr_in6);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ *(struct sockaddr_in6*)pAddress = m_PeerAddr.v6;\r
+ break;\r
+\r
+ default:\r
+ return ND_CONNECTION_INVALID;\r
+ }\r
+\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CConnector::NotifyDisconnect(\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ return NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_NOTIFY_DREQ,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ NULL,\r
+ 0 );\r
+}\r
+\r
+HRESULT CConnector::Disconnect(\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( m_pEndpoint == NULL )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ ib_qp_state_t state =\r
+ m_pParent->m_Ifc.user_verbs.nd_get_qp_state( m_pEndpoint->m_uQp );\r
+ if( state != IB_QPS_RTS )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ //\r
+ // Get the UVP's buffer for modify operations.\r
+ //\r
+ void* pOutbuf;\r
+ DWORD szOutbuf;\r
+\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp(\r
+ m_pEndpoint->m_uQp,\r
+ &pOutbuf,\r
+ &szOutbuf\r
+ );\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Disconnect QP %#I64x, QPn %#x\n", m_pEndpoint->m_hQp, m_pEndpoint->m_Qpn ) );\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_DREQ_CM,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ pOutbuf,\r
+ szOutbuf );\r
+\r
+ if( SUCCEEDED( hr ) )\r
+ {\r
+ m_pEndpoint->Release();\r
+ m_pEndpoint = NULL;\r
+ }\r
+\r
+ return hr;\r
+}\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+\r
+#include "ndspi.h"\r
+#include "nddebug.h"\r
+#include <iba/ib_al.h>\r
+#include <iba/ib_at_ioctl.h>\r
+#include <ws2tcpip.h>\r
+#include "ual_ci_ca.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+class CConnector :\r
+ public INDConnector\r
+{\r
+ friend class CListen;\r
+\r
+private:\r
+ CConnector(void);\r
+ ~CConnector(void);\r
+ void FreeCid(void);\r
+\r
+public:\r
+ static HRESULT Create(\r
+ __in CAdapter* pParent,\r
+ __deref_out INDConnector** ppConnector\r
+ );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT STDMETHODCALLTYPE CancelOverlappedRequests(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ );\r
+\r
+ // *** INDConnector methods ***\r
+ HRESULT STDMETHODCALLTYPE CreateEndpoint(\r
+ __in INDCompletionQueue* pInboundCq,\r
+ __in INDCompletionQueue* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData,\r
+ __deref_out INDEndpoint** ppEndpoint\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Connect(\r
+ __in INDEndpoint* pEndpoint,\r
+ __in_bcount(AddressLength) const struct sockaddr* pAddress,\r
+ __in SIZE_T AddressLength,\r
+ __in INT Protocol,\r
+ __in_opt USHORT LocalPort,\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength,\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CompleteConnect(\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Accept(\r
+ __in INDEndpoint* pEndpoint,\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength,\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Reject(\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE GetConnectionData(\r
+ __out_opt SIZE_T* pInboundReadLimit,\r
+ __out_opt SIZE_T* pOutboundReadLimit,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE GetLocalAddress(\r
+ __out_bcount_part_opt(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE GetPeerAddress(\r
+ __out_bcount_part_opt(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE NotifyDisconnect(\r
+ __inout_opt OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Disconnect(\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+private:\r
+ HRESULT GetAddressFromPdata(\r
+ __out_bcount_part(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ );\r
+\r
+protected:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter* m_pParent;\r
+\r
+ CEndpoint* m_pEndpoint;\r
+\r
+ UINT8 m_Protocol;\r
+ USHORT m_LocalPort;\r
+ net32_t m_cid;\r
+ bool m_fActive;\r
+\r
+ union _addr\r
+ {\r
+ struct sockaddr_in v4;\r
+ struct sockaddr_in6 v6;\r
+\r
+ } m_PeerAddr;\r
+};\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#include "NdCq.h"\r
+#include "NdAdapter.h"\r
+#include "al_cq.h"\r
+#include "al_dev.h"\r
+#include "al.h"\r
+#include "al_verbs.h"\r
+#pragma warning( push, 3 )\r
+#include "winternl.h"\r
+#pragma warning( pop )\r
+#include "limits.h"\r
+#include "nddebug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdCq.tmh"\r
+#endif\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ CCq::CCq(void) :\r
+ m_nRef( 1 ),\r
+ m_pParent( NULL ),\r
+ m_hCq( 0 ),\r
+ m_uCq( NULL )\r
+ {\r
+ }\r
+\r
+ CCq::~CCq(void)\r
+ {\r
+ if( m_hCq )\r
+ CloseCq();\r
+\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+ }\r
+\r
+ HRESULT CCq::Initialize(\r
+ CAdapter* pParent,\r
+ SIZE_T nEntries )\r
+ {\r
+ if( nEntries > UINT_MAX )\r
+ return ND_INVALID_PARAMETER;\r
+\r
+ m_pParent = pParent;\r
+ pParent->AddRef();\r
+\r
+ return CreateCq( (UINT32)nEntries );\r
+ }\r
+\r
+ HRESULT CCq::QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ )\r
+ {\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDCompletionQueue ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ ULONG CCq::AddRef(void)\r
+ {\r
+ return InterlockedIncrement( &m_nRef );\r
+ }\r
+\r
+ ULONG CCq::Release(void)\r
+ {\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+ }\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT CCq::CancelOverlappedRequests(void)\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ DWORD BytesRet;\r
+ DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_NDI_CANCEL_CQ,\r
+ &m_hCq,\r
+ sizeof(m_hCq),\r
+ NULL,\r
+ 0,\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ return S_OK;\r
+ }\r
+\r
+ HRESULT CCq::GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ *pNumberOfBytesTransferred = 0;\r
+ ::GetOverlappedResult(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped,\r
+ (DWORD*)pNumberOfBytesTransferred,\r
+ bWait );\r
+ ND_PRINT( TRACE_LEVEL_VERBOSE, ND_DBG_NDI,\r
+ ("==> %s, result %#x, bytes %d\n", __FUNCTION__, (int)pOverlapped->Internal, (int)*pNumberOfBytesTransferred ));\r
+ return (HRESULT)pOverlapped->Internal;\r
+ }\r
+\r
+ // *** INDCompletionQueue methods ***\r
+ HRESULT CCq::Resize(\r
+ __in SIZE_T nEntries\r
+ )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( nEntries > UINT_MAX )\r
+ return ND_INVALID_PARAMETER;\r
+\r
+ ib_api_status_t status;\r
+\r
+ /* Clear the IOCTL buffer */\r
+ ual_modify_cq_ioctl_t cq_ioctl;\r
+ cl_memclr( &cq_ioctl, sizeof(cq_ioctl) );\r
+\r
+ /* Call the uvp pre call if the vendor library provided a valid ca handle */\r
+ if( m_uCq && m_pParent->m_Ifc.user_verbs.pre_resize_cq )\r
+ {\r
+ /* Pre call to the UVP library */\r
+ status = m_pParent->m_Ifc.user_verbs.pre_resize_cq(\r
+ m_uCq, (uint32_t*)&nEntries, &cq_ioctl.in.umv_buf );\r
+ if( status != IB_SUCCESS )\r
+ goto exit;\r
+ }\r
+\r
+ cq_ioctl.in.h_cq = m_hCq;\r
+ cq_ioctl.in.size = (DWORD)nEntries;\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_MODIFY_CQ,\r
+ &cq_ioctl.in,\r
+ sizeof(cq_ioctl.in),\r
+ &cq_ioctl.out,\r
+ sizeof(cq_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(cq_ioctl.out) )\r
+ status = IB_ERROR;\r
+ else\r
+ status = cq_ioctl.out.status;\r
+\r
+ /* Post uvp call */\r
+ if( m_uCq && m_pParent->m_Ifc.user_verbs.post_resize_cq )\r
+ {\r
+ m_pParent->m_Ifc.user_verbs.post_resize_cq(\r
+ m_uCq, status, cq_ioctl.out.size, &cq_ioctl.out.umv_buf );\r
+ }\r
+\r
+exit:\r
+ switch( status )\r
+ {\r
+ case IB_INVALID_CQ_SIZE:\r
+ return ND_INVALID_PARAMETER;\r
+\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+ }\r
+\r
+ HRESULT CCq::Notify(\r
+ __in DWORD Type,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+ {\r
+// ND_ENTER( ND_DBG_NDI );\r
+\r
+ ual_ndi_notify_cq_ioctl_in_t ioctl;\r
+ ioctl.h_cq = m_hCq;\r
+ ioctl.notify_comps = (boolean_t)Type;\r
+ pOverlapped->Internal = ND_PENDING;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_NOTIFY_CQ,\r
+ &ioctl,\r
+ sizeof(ioctl),\r
+ NULL,\r
+ 0 );\r
+\r
+ if( hr == ND_PENDING && Type != ND_CQ_NOTIFY_ERRORS )\r
+ {\r
+ m_pParent->m_Ifc.user_verbs.rearm_cq(\r
+ m_uCq,\r
+ (Type == ND_CQ_NOTIFY_SOLICITED) ? TRUE : FALSE\r
+ );\r
+ ND_PRINT( TRACE_LEVEL_VERBOSE, ND_DBG_NDI,\r
+ ("==> %s, rearming with Type %d\n", __FUNCTION__, Type));\r
+ }\r
+ else\r
+ {\r
+ ND_PRINT( TRACE_LEVEL_ERROR, ND_DBG_NDI,\r
+ ("==> %s failed: hr %#x, notify_type %d \n", __FUNCTION__, hr, Type ));\r
+ }\r
+ return hr;\r
+ }\r
+\r
+ SIZE_T CCq::GetResults(\r
+ __out_ecount(nResults) ND_RESULT* pResults[],\r
+ __in SIZE_T nResults\r
+ )\r
+ {\r
+#if DBG \r
+ if (!(++g.c_cnt % 100000000)) // || !(rcv_pkts % 1000) || !(snd_pkts % 1000)\r
+ ND_PRINT( TRACE_LEVEL_VERBOSE, ND_DBG_NDI,\r
+ ("==> %s, cnt %I64d, rcv: %I64d:%I64d:%I64d, snd %I64d:%I64d:%I64d\n", \r
+ __FUNCTION__, g.c_cnt, \r
+ g.c_rcv_pkts, g.c_rcv_bytes, g.c_rcv_pkts_err,\r
+ g.c_snd_pkts, g.c_snd_bytes, g.c_snd_pkts_err));\r
+#endif \r
+ SIZE_T i = 0;\r
+\r
+ while( nResults-- )\r
+ {\r
+ ib_wc_t wc;\r
+ ib_wc_t* pWc = &wc;\r
+ ib_wc_t* pDoneWc;\r
+ wc.p_next = NULL;\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.poll_cq( m_uCq, &pWc, &pDoneWc );\r
+\r
+ if( status != IB_SUCCESS )\r
+ break;\r
+\r
+ pResults[i] = (ND_RESULT*)wc.wr_id;\r
+ if( wc.wc_type == IB_WC_RECV )\r
+ pResults[i]->BytesTransferred = wc.length;\r
+\r
+ if( wc.recv.conn.recv_opt & IB_RECV_OPT_IMMEDIATE )\r
+ {\r
+ // Emulated receive with invalidate - the immediate\r
+ // data holds the RKey that is supposed to be invalidated.\r
+\r
+ //TODO: We need the QP handle (or context) so we can force an\r
+ // error if we don't find a matching MW for the given RKEY.\r
+ // We also need to change the receive status in this case to\r
+ // ND_INVALIDATION_ERROR;\r
+ }\r
+\r
+ switch( wc.status )\r
+ {\r
+ case IB_WCS_SUCCESS:\r
+ pResults[i]->Status = ND_SUCCESS;\r
+ break;\r
+ case IB_WCS_LOCAL_LEN_ERR:\r
+ pResults[i]->Status = ND_LOCAL_LENGTH;\r
+ break;\r
+ case IB_WCS_LOCAL_OP_ERR:\r
+ case IB_WCS_LOCAL_ACCESS_ERR:\r
+ case IB_WCS_GENERAL_ERR:\r
+ default:\r
+ pResults[i]->Status = ND_INTERNAL_ERROR;\r
+ break;\r
+ case IB_WCS_LOCAL_PROTECTION_ERR:\r
+ case IB_WCS_MEM_WINDOW_BIND_ERR:\r
+ pResults[i]->Status = ND_ACCESS_VIOLATION;\r
+ break;\r
+ case IB_WCS_WR_FLUSHED_ERR:\r
+ pResults[i]->Status = ND_CANCELED;\r
+ break;\r
+ case IB_WCS_REM_INVALID_REQ_ERR:\r
+ pResults[i]->Status = ND_BUFFER_OVERFLOW;\r
+ break;\r
+ case IB_WCS_REM_ACCESS_ERR:\r
+ case IB_WCS_REM_OP_ERR:\r
+ case IB_WCS_BAD_RESP_ERR:\r
+ pResults[i]->Status = ND_REMOTE_ERROR;\r
+ break;\r
+ case IB_WCS_RNR_RETRY_ERR:\r
+ case IB_WCS_TIMEOUT_RETRY_ERR:\r
+ pResults[i]->Status = ND_TIMEOUT;\r
+ break;\r
+ }\r
+ i++;\r
+ // leo\r
+#if DBG\r
+ {\r
+ if (wc.wc_type == IB_WC_RECV)\r
+ { \r
+ if (!wc.status)\r
+ {\r
+ ++g.c_rcv_pkts;\r
+ g.c_rcv_bytes += wc.length;\r
+ }\r
+ else\r
+ ++g.c_rcv_pkts_err;\r
+ }\r
+ else\r
+ { \r
+ if (!wc.status)\r
+ {\r
+ ++g.c_snd_pkts;\r
+ g.c_snd_bytes += wc.length;\r
+ }\r
+ else\r
+ ++g.c_snd_pkts_err;\r
+ }\r
+ }\r
+#endif\r
+ continue;\r
+ }\r
+ return i;\r
+ }\r
+\r
+ HRESULT CCq::CreateCq(\r
+ __in UINT32 nEntries )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* Clear the IOCTL buffer */\r
+ ual_create_cq_ioctl_t cq_ioctl;\r
+ cl_memclr( &cq_ioctl, sizeof(cq_ioctl) );\r
+\r
+ /* Pre call to the UVP library */\r
+ ib_api_status_t status;\r
+ if( m_pParent->m_uCa && m_pParent->m_Ifc.user_verbs.pre_create_cq )\r
+ {\r
+ status = m_pParent->m_Ifc.user_verbs.pre_create_cq(\r
+ m_pParent->m_uCa,\r
+ &nEntries,\r
+ &cq_ioctl.in.umv_buf,\r
+ (ib_cq_handle_t*)(ULONG_PTR)&m_uCq\r
+ );\r
+ if( status != IB_SUCCESS )\r
+ goto done;\r
+ }\r
+\r
+ cq_ioctl.in.h_ca = m_pParent->m_hCa;\r
+ cq_ioctl.in.size = nEntries;\r
+ cq_ioctl.in.h_wait_obj = NULL;\r
+ cq_ioctl.in.context = (ULONG_PTR)this;\r
+ cq_ioctl.in.ev_notify = FALSE;\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_NDI_CREATE_CQ,\r
+ &cq_ioctl.in,\r
+ sizeof(cq_ioctl.in),\r
+ &cq_ioctl.out,\r
+ sizeof(cq_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(cq_ioctl.out) )\r
+ status = IB_ERROR;\r
+ else\r
+ status = cq_ioctl.out.status;\r
+\r
+ m_hCq = cq_ioctl.out.h_cq;\r
+\r
+ /* Post uvp call */\r
+ if( m_pParent->m_uCa && m_pParent->m_Ifc.user_verbs.post_create_cq )\r
+ {\r
+ m_pParent->m_Ifc.user_verbs.post_create_cq(\r
+ m_pParent->m_uCa,\r
+ status,\r
+ cq_ioctl.out.size,\r
+ (ib_cq_handle_t*)(ULONG_PTR)&m_uCq,\r
+ &cq_ioctl.out.umv_buf );\r
+ }\r
+\r
+done:\r
+ switch( status )\r
+ {\r
+ case IB_INVALID_CQ_SIZE:\r
+ return ND_INVALID_PARAMETER;\r
+\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+\r
+ case IB_INSUFFICIENT_MEMORY:\r
+ return ND_NO_MEMORY;\r
+\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+ }\r
+\r
+ void CCq::CloseCq(void)\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ib_api_status_t status;\r
+\r
+ if( m_uCq && m_pParent->m_Ifc.user_verbs.pre_destroy_cq )\r
+ {\r
+ /* Pre call to the UVP library */\r
+ status = m_pParent->m_Ifc.user_verbs.pre_destroy_cq( m_uCq );\r
+ if( status != IB_SUCCESS )\r
+ return;\r
+ }\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_DESTROY_CQ,\r
+ &m_hCq,\r
+ sizeof(m_hCq),\r
+ &status,\r
+ sizeof(status),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(status) )\r
+ status = IB_ERROR;\r
+\r
+ if( m_uCq && m_pParent->m_Ifc.user_verbs.post_destroy_cq )\r
+ m_pParent->m_Ifc.user_verbs.post_destroy_cq( m_uCq, status );\r
+ }\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+#include "ndspi.h"\r
+#include <iba/ib_al.h>\r
+#include "al_cq.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+ class CAdapter;\r
+\r
+ class CCq :\r
+ public INDCompletionQueue\r
+ {\r
+ friend class CEndpoint;\r
+ public:\r
+ CCq(void);\r
+ ~CCq(void);\r
+\r
+ HRESULT Initialize(\r
+ CAdapter* pParent,\r
+ SIZE_T nEntries );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT STDMETHODCALLTYPE CancelOverlappedRequests(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE GetOverlappedResult(\r
+ __inout_opt OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ );\r
+\r
+ // *** INDCompletionQueue methods ***\r
+ HANDLE STDMETHODCALLTYPE GetAdapterFileHandle(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE Close(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE Resize(\r
+ __in SIZE_T nEntries\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Notify(\r
+ __in DWORD Type,\r
+ __inout_opt OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ SIZE_T STDMETHODCALLTYPE GetResults(\r
+ __out_ecount(nResults) ND_RESULT* pResults[],\r
+ __in SIZE_T nResults\r
+ );\r
+\r
+ private:\r
+ HRESULT CreateCq(\r
+ __in UINT32 nEntries );\r
+\r
+ HRESULT Complete(\r
+ __in HRESULT Status );\r
+\r
+ HRESULT ModifyCq(\r
+ __in SIZE_T nEntries );\r
+\r
+ void CloseCq(void);\r
+\r
+ private:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter* m_pParent;\r
+\r
+ UINT64 m_hCq;\r
+ ib_cq_handle_t m_uCq;\r
+ };\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#include "NdEndpoint.h"\r
+#include "NdCq.h"\r
+#include "NdAdapter.h"\r
+#include "NdMr.h"\r
+#include "NdListen.h"\r
+#include "limits.h"\r
+#include "al_dev.h"\r
+#pragma warning( push, 3 )\r
+#include "winternl.h"\r
+#pragma warning( pop )\r
+#include "nddebug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdEndpoint.tmh"\r
+#endif\r
+\r
+#if DBG\r
+dbg_data g = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };\r
+#endif\r
+\r
+#ifndef SIZE_MAX\r
+#ifdef _WIN64\r
+#define SIZE_MAX _UI64_MAX\r
+#else\r
+#define SIZE_MAX UINT_MAX\r
+#endif\r
+#endif\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// HPC Pack 2008 Beta 2 SPI\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+CEndpoint::CEndpoint(void) :\r
+ m_nRef( 1 ),\r
+ m_pParent( NULL ),\r
+ m_hQp( 0 )\r
+{\r
+}\r
+\r
+CEndpoint::~CEndpoint(void)\r
+{\r
+ if( m_hQp )\r
+ DestroyQp();\r
+\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+}\r
+\r
+HRESULT CEndpoint::Initialize(\r
+ __in CAdapter* pParent,\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( InboundReadLimit > UCHAR_MAX )\r
+ return ND_INVALID_PARAMETER_8;\r
+\r
+ if( OutboundReadLimit > UCHAR_MAX )\r
+ return ND_INVALID_PARAMETER_9;\r
+\r
+ m_pParent = pParent;\r
+ m_pParent->AddRef();\r
+\r
+ CL_ASSERT(\r
+ m_pParent->m_Ifc.user_verbs.pre_create_qp != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_create_qp != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.nd_get_qp_state != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.pre_destroy_qp != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_destroy_qp != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_send != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_recv != NULL /*||\r
+ m_pParent->m_Ifc.user_verbs.bind_mw != NULL*/ );\r
+\r
+ HRESULT hr = CreateQp(\r
+ pInboundCq,\r
+ pOutboundCq,\r
+ nInboundEntries,\r
+ nOutboundEntries,\r
+ nInboundSge,\r
+ nOutboundSge,\r
+ InboundReadLimit,\r
+ OutboundReadLimit );\r
+\r
+ if( FAILED( hr ) )\r
+ return hr;\r
+\r
+ m_Ird = (UINT8)InboundReadLimit;\r
+ m_Ord = (UINT8)OutboundReadLimit;\r
+\r
+ // Move the QP to the INIT state so users can post receives.\r
+ hr = ModifyQp( IB_QPS_INIT );\r
+ if( FAILED( hr ) )\r
+ DestroyQp();\r
+\r
+ if( SUCCEEDED( hr ) && pMaxInlineData != NULL )\r
+ {\r
+ // Worst case.\r
+ *pMaxInlineData = nOutboundSge * 12;\r
+ }\r
+\r
+ return hr;\r
+}\r
+\r
+HRESULT CEndpoint::Create(\r
+ __in CAdapter* pParent,\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData,\r
+ __out INDEndpoint** ppEndpoint\r
+ )\r
+{\r
+ CEndpoint* pEp = new CEndpoint();\r
+ if( pEp == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ HRESULT hr = pEp->Initialize(\r
+ pParent,\r
+ pInboundCq,\r
+ pOutboundCq,\r
+ nInboundEntries,\r
+ nOutboundEntries,\r
+ nInboundSge,\r
+ nOutboundSge,\r
+ InboundReadLimit,\r
+ OutboundReadLimit,\r
+ pMaxInlineData\r
+ );\r
+\r
+ if( FAILED( hr ) )\r
+ {\r
+ pEp->Release();\r
+ return hr;\r
+ }\r
+\r
+ *ppEndpoint = pEp;\r
+ return ND_SUCCESS;\r
+}\r
+\r
+HRESULT CEndpoint::QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ )\r
+{\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDEndpoint ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+ULONG CEndpoint::AddRef(void)\r
+{\r
+ return InterlockedIncrement( &m_nRef );\r
+}\r
+\r
+ULONG CEndpoint::Release(void)\r
+{\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+}\r
+\r
+// *** INDEndpoint methods ***\r
+HRESULT CEndpoint::Flush(void)\r
+{\r
+ return ModifyQp( IB_QPS_ERROR );\r
+}\r
+\r
+void CEndpoint::StartRequestBatch(void)\r
+{\r
+ return;\r
+}\r
+\r
+void CEndpoint::SubmitRequestBatch(void)\r
+{\r
+ return;\r
+}\r
+\r
+HRESULT CEndpoint::Send(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+ ib_send_wr_t wr;\r
+ ib_local_ds_t* pDs;\r
+ ib_local_ds_t ds[4];\r
+\r
+ if( nSge > UINT_MAX )\r
+ return ND_DATA_OVERRUN;\r
+ else if( nSge <= 4 )\r
+ pDs = ds;\r
+ else\r
+ {\r
+ pDs = new ib_local_ds_t[nSge];\r
+ if( !pDs )\r
+ return ND_NO_MEMORY;\r
+ }\r
+\r
+ pResult->BytesTransferred = 0;\r
+ for( SIZE_T i = 0; i < nSge; i++ )\r
+ {\r
+ pDs[i].vaddr = (ULONG_PTR)pSgl[i].pAddr;\r
+ if( pSgl[i].Length > UINT_MAX )\r
+ {\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ pDs[i].length = (uint32_t)pSgl[i].Length;\r
+ pDs[i].lkey = ((CMr*)pSgl[i].hMr)->mr_ioctl.out.lkey;\r
+\r
+ // Send completions don't include the length. It's going to\r
+ // be all or nothing, so store it now and we can reset if the\r
+ // request fails.\r
+ pResult->BytesTransferred += pSgl[i].Length;\r
+ }\r
+\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.wr_type = WR_SEND;\r
+ wr.send_opt = 0;\r
+ if( !(Flags & ND_OP_FLAG_SILENT_SUCCESS) )\r
+ wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
+ if( Flags & ND_OP_FLAG_READ_FENCE )\r
+ wr.send_opt |= IB_SEND_OPT_FENCE;\r
+ if( Flags & ND_OP_FLAG_SEND_AND_SOLICIT_EVENT )\r
+ wr.send_opt |= IB_SEND_OPT_SOLICITED;\r
+ wr.num_ds = (uint32_t)nSge;\r
+ wr.ds_array = pDs;\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_send( m_uQp, &wr, NULL );\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+\r
+ // leo\r
+ CL_ASSERT( nSge || pSgl == NULL );\r
+#if DBG\r
+ if (!status )\r
+ {\r
+ if (pSgl)\r
+ {\r
+ ++g.snd_pkts;\r
+ g.snd_bytes += pSgl[0].Length;\r
+ }\r
+ else\r
+ ++g.snd_pkts_zero;\r
+ }\r
+ else\r
+ ++g.snd_pkts_err;\r
+#endif\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_MAX_SGE:\r
+ return ND_DATA_OVERRUN;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::SendAndInvalidate(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ib_send_wr_t wr;\r
+ ib_local_ds_t* pDs;\r
+\r
+ if( nSge > UINT_MAX )\r
+ return ND_DATA_OVERRUN;\r
+\r
+ pDs = new ib_local_ds_t[nSge];\r
+ if( !pDs )\r
+ return ND_NO_MEMORY;\r
+\r
+ pResult->BytesTransferred = 0;\r
+ for( SIZE_T i = 0; i < nSge; i++ )\r
+ {\r
+ pDs[i].vaddr = (ULONG_PTR)pSgl[i].pAddr;\r
+ if( pSgl[i].Length > UINT_MAX )\r
+ {\r
+ delete[] pDs;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ pDs[i].length = (uint32_t)pSgl[i].Length;\r
+ pDs[i].lkey = ((CMr*)pSgl[i].hMr)->mr_ioctl.out.lkey;\r
+\r
+ // Send completions don't include the length. It's going to\r
+ // be all or nothing, so store it now and we can reset if the\r
+ // request fails.\r
+ pResult->BytesTransferred += pSgl[i].Length;\r
+ }\r
+\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.wr_type = WR_SEND;\r
+ // We simulate invalidate operations (since we simulate MW use). We\r
+ // put the RKey in the immediate data, the recipient will do the\r
+ // lookup of the MW based on that (as they would with a regular\r
+ // invalidate request).\r
+ wr.send_opt = IB_SEND_OPT_IMMEDIATE;\r
+ if( !(Flags & ND_OP_FLAG_SILENT_SUCCESS) )\r
+ wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
+ if( Flags & ND_OP_FLAG_READ_FENCE )\r
+ wr.send_opt |= IB_SEND_OPT_FENCE;\r
+ if( Flags & ND_OP_FLAG_SEND_AND_SOLICIT_EVENT )\r
+ wr.send_opt |= IB_SEND_OPT_SOLICITED;\r
+ wr.num_ds = (uint32_t)nSge;\r
+ wr.ds_array = pDs;\r
+ // Put the RKey in the immeditate data.\r
+ wr.immediate_data = pRemoteMwDescriptor->Token;\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_send( m_uQp, &wr, NULL );\r
+ delete[] pDs;\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_MAX_SGE:\r
+ return ND_DATA_OVERRUN;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::Receive(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge\r
+ )\r
+{\r
+#if DBG \r
+ if (!(++g.rcv_cnt % 1000))\r
+ ND_PRINT( TRACE_LEVEL_VERBOSE, ND_DBG_NDI,\r
+ ("==> %s, cnt %I64d, rcv %I64d:%I64d:%I64d:%I64d\n",\r
+ __FUNCTION__, g.rcv_cnt, g.rcv_pkts, g.rcv_bytes, g.rcv_pkts_err, g.rcv_pkts_zero ));\r
+#endif\r
+ ib_recv_wr_t wr;\r
+ ib_local_ds_t* pDs;\r
+ ib_local_ds_t ds[4];\r
+\r
+ if( nSge > UINT_MAX )\r
+ return ND_DATA_OVERRUN;\r
+ else if( nSge <= 4 )\r
+ pDs = ds;\r
+ else\r
+ {\r
+ pDs = new ib_local_ds_t[nSge];\r
+ if( !pDs )\r
+ return ND_NO_MEMORY;\r
+ }\r
+\r
+ for( SIZE_T i = 0; i < nSge; i++ )\r
+ {\r
+ pDs[i].vaddr = (ULONG_PTR)pSgl[i].pAddr;\r
+ if( pSgl[i].Length > UINT_MAX )\r
+ {\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ pDs[i].length = (uint32_t)pSgl[i].Length;\r
+ pDs[i].lkey = ((CMr*)pSgl[i].hMr)->mr_ioctl.out.lkey;\r
+ }\r
+\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.num_ds = (uint32_t)nSge;\r
+ wr.ds_array = pDs;\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_recv( m_uQp, &wr, NULL );\r
+\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+\r
+ // leo\r
+ CL_ASSERT( nSge || pSgl == NULL );\r
+#if DBG\r
+ if (!status)\r
+ {\r
+ if (pSgl)\r
+ {\r
+ ++g.rcv_pkts;\r
+ g.rcv_bytes += pSgl[0].Length;\r
+ }\r
+ else\r
+ ++g.rcv_pkts_zero;\r
+ }\r
+ else\r
+ ++g.rcv_pkts_err;\r
+#endif\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_MAX_SGE:\r
+ return ND_DATA_OVERRUN;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::Bind(\r
+ __out ND_RESULT* pResult,\r
+ __in ND_MR_HANDLE hMr,\r
+ __in INDMemoryWindow* pMw,\r
+ __in_bcount(BufferSize) const void* pBuffer,\r
+ __in SIZE_T BufferSize,\r
+ __in DWORD Flags,\r
+ __out ND_MW_DESCRIPTOR* pMwDescriptor\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ UNREFERENCED_PARAMETER( pMw );\r
+ UNREFERENCED_PARAMETER( Flags );\r
+\r
+ CMr* pMr = ((CMr*)hMr);\r
+\r
+ if( pBuffer < pMr->pBase ||\r
+ pBuffer > pMr->pBase + pMr->Length )\r
+ {\r
+ return ND_INVALID_PARAMETER_4;\r
+ }\r
+\r
+ if( ((const char*)pBuffer + BufferSize) > (pMr->pBase + pMr->Length) )\r
+ {\r
+ return ND_INVALID_PARAMETER_5;\r
+ }\r
+\r
+ // Ok, this here is a workaround since the Mellanox HCA driver doesn't\r
+ // support MWs. This should be pushed into the HCA driver.\r
+ pMwDescriptor->Base = _byteswap_uint64( (UINT64)(ULONG_PTR)pBuffer );\r
+ pMwDescriptor->Length = _byteswap_uint64( BufferSize );\r
+ pMwDescriptor->Token = pMr->mr_ioctl.out.rkey;\r
+\r
+ // Zero-byte RDMA write. Could also be a no-op on the send queue\r
+ // which would be better, but requires changing the HCA driver.\r
+ ib_send_wr_t wr;\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.wr_type = WR_RDMA_WRITE;\r
+ wr.send_opt = IB_SEND_OPT_SIGNALED;\r
+ wr.num_ds = 0;\r
+ wr.ds_array = NULL;\r
+\r
+ wr.remote_ops.vaddr = 0;\r
+ wr.remote_ops.rkey = 0;\r
+\r
+ pResult->BytesTransferred = 0;\r
+\r
+ // TODO: Track the MW by rkey, so we can unbind it.\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_send( m_uQp, &wr, NULL );\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::Invalidate(\r
+ __out ND_RESULT* pResult,\r
+ __in INDMemoryWindow* pMw,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ UNREFERENCED_PARAMETER( pMw );\r
+ UNREFERENCED_PARAMETER( Flags );\r
+\r
+ // Zero-byte RDMA write. Could also be a no-op on the send queue\r
+ // which would be better, but requires changing the HCA driver.\r
+ ib_send_wr_t wr;\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.wr_type = WR_RDMA_WRITE;\r
+ wr.send_opt = IB_SEND_OPT_SIGNALED;\r
+ wr.num_ds = 0;\r
+ wr.ds_array = NULL;\r
+\r
+ wr.remote_ops.vaddr = 0;\r
+ wr.remote_ops.rkey = 0;\r
+\r
+ pResult->BytesTransferred = 0;\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_send( m_uQp, &wr, NULL );\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ // TODO: Stop trackign MW\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::Rdma(\r
+ __out ND_RESULT* pResult,\r
+ __in ib_wr_type_t Type,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+// ND_ENTER( ND_DBG_NDI );\r
+\r
+ ib_send_wr_t wr;\r
+ ib_local_ds_t* pDs;\r
+ ib_local_ds_t ds[4];\r
+\r
+ if( nSge > UINT_MAX )\r
+ return ND_DATA_OVERRUN;\r
+ else if( nSge <= 4 )\r
+ pDs = ds;\r
+ else\r
+ {\r
+ pDs = new ib_local_ds_t[nSge];\r
+ if( !pDs )\r
+ return ND_NO_MEMORY;\r
+ }\r
+\r
+ pResult->BytesTransferred = 0;\r
+ for( SIZE_T i = 0; i < nSge; i++ )\r
+ {\r
+ pDs[i].vaddr = (ULONG_PTR)pSgl[i].pAddr;\r
+ if( pSgl[i].Length > UINT_MAX )\r
+ {\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ pDs[i].length = (uint32_t)pSgl[i].Length;\r
+ pDs[i].lkey = ((CMr*)pSgl[i].hMr)->mr_ioctl.out.lkey;\r
+\r
+ //TODO: temporary - a workaround of test bug\r
+ //leo\r
+ if( (int)pSgl[i].Length < 0 )\r
+ {\r
+ pDs[i].length = 0 - (int)pSgl[i].Length;\r
+#if DBG \r
+ ND_PRINT( TRACE_LEVEL_VERBOSE, ND_DBG_NDI,\r
+ ("nSge %d, i %d, Length %#x\n", nSge, i, pSgl[i].Length ));\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+ return ND_BUFFER_OVERFLOW;\r
+#endif \r
+ }\r
+\r
+ // Send completions don't include the length. It's going to\r
+ // be all or nothing, so store it now and we can reset if the\r
+ // request fails.\r
+ pResult->BytesTransferred += pSgl[i].Length;\r
+ }\r
+\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.wr_type = Type;\r
+ wr.send_opt = 0;\r
+ if( !(Flags & ND_OP_FLAG_SILENT_SUCCESS) )\r
+ wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
+ if( Flags & ND_OP_FLAG_READ_FENCE )\r
+ wr.send_opt |= IB_SEND_OPT_FENCE;\r
+ wr.num_ds = (uint32_t)nSge;\r
+ wr.ds_array = pDs;\r
+\r
+ UINT64 vaddr = _byteswap_uint64( pRemoteMwDescriptor->Base );\r
+ vaddr += Offset;\r
+ wr.remote_ops.vaddr = vaddr;\r
+ wr.remote_ops.rkey = pRemoteMwDescriptor->Token;\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_send( m_uQp, &wr, NULL );\r
+\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_MAX_SGE:\r
+ return ND_DATA_OVERRUN;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::Read(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+// ND_ENTER( ND_DBG_NDI );\r
+\r
+ return Rdma( pResult, WR_RDMA_READ, pSgl, nSge,\r
+ pRemoteMwDescriptor, Offset, Flags );\r
+}\r
+\r
+HRESULT CEndpoint::Write(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+// ND_ENTER( ND_DBG_NDI );\r
+\r
+ return Rdma( pResult, WR_RDMA_WRITE, pSgl, nSge,\r
+ pRemoteMwDescriptor, Offset, Flags );\r
+}\r
+\r
+HRESULT CEndpoint::CreateQp(\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( nInboundEntries > UINT_MAX )\r
+ return ND_INVALID_PARAMETER_4;\r
+ if( nOutboundEntries > UINT_MAX )\r
+ return ND_INVALID_PARAMETER_5;\r
+ if( nInboundSge > UINT_MAX )\r
+ return ND_INVALID_PARAMETER_6;\r
+ if( nOutboundSge > UINT_MAX )\r
+ return ND_INVALID_PARAMETER_7;\r
+ if( InboundReadLimit > UCHAR_MAX )\r
+ return ND_INVALID_PARAMETER_9;\r
+ if( OutboundReadLimit > UCHAR_MAX )\r
+ return ND_INVALID_PARAMETER_10;\r
+\r
+ /* Setup the qp_ioctl */\r
+ ual_create_qp_ioctl_t qp_ioctl;\r
+ cl_memclr( &qp_ioctl, sizeof(qp_ioctl) );\r
+\r
+ qp_ioctl.in.qp_create.qp_type = IB_QPT_RELIABLE_CONN;\r
+ qp_ioctl.in.qp_create.sq_depth = (uint32_t)nOutboundEntries;\r
+ qp_ioctl.in.qp_create.rq_depth = (uint32_t)nInboundEntries;\r
+ qp_ioctl.in.qp_create.sq_sge = (uint32_t)nOutboundSge;\r
+ qp_ioctl.in.qp_create.rq_sge = (uint32_t)nInboundSge;\r
+ qp_ioctl.in.qp_create.h_srq = NULL;\r
+ qp_ioctl.in.qp_create.sq_signaled = FALSE;\r
+\r
+ /* Pre call to the UVP library */\r
+ CL_ASSERT( m_pParent->m_Ifc.user_verbs.pre_create_qp );\r
+ qp_ioctl.in.qp_create.h_sq_cq = pOutboundCq->m_uCq;\r
+ qp_ioctl.in.qp_create.h_rq_cq = pInboundCq->m_uCq;\r
+ ib_api_status_t status = m_pParent->m_Ifc.user_verbs.pre_create_qp(\r
+ m_pParent->m_uPd,\r
+ &qp_ioctl.in.qp_create,\r
+ &qp_ioctl.in.umv_buf,\r
+ (ib_qp_handle_t*)(ULONG_PTR)&m_uQp\r
+ );\r
+ if( status != IB_SUCCESS )\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+\r
+ /*\r
+ * Convert the handles to KAL handles once again starting\r
+ * from the input qp attribute\r
+ */\r
+ qp_ioctl.in.h_pd = m_pParent->m_hPd;\r
+ qp_ioctl.in.qp_create.h_sq_cq = (ib_cq_handle_t)pOutboundCq->m_hCq;\r
+ qp_ioctl.in.qp_create.h_rq_cq = (ib_cq_handle_t)pInboundCq->m_hCq;\r
+ qp_ioctl.in.context = (ULONG_PTR)this;\r
+ qp_ioctl.in.ev_notify = FALSE;\r
+\r
+ DWORD bytes_ret;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_CREATE_QP,\r
+ &qp_ioctl.in,\r
+ sizeof(qp_ioctl.in),\r
+ &qp_ioctl.out,\r
+ sizeof(qp_ioctl.out),\r
+ &bytes_ret,\r
+ NULL );\r
+\r
+ if( fSuccess != TRUE || bytes_ret != sizeof(qp_ioctl.out) )\r
+ qp_ioctl.out.status = IB_ERROR;\r
+\r
+ /* Post uvp call */\r
+ CL_ASSERT( m_pParent->m_Ifc.user_verbs.post_create_qp );\r
+ m_pParent->m_Ifc.user_verbs.post_create_qp(\r
+ m_pParent->m_uPd,\r
+ qp_ioctl.out.status,\r
+ (ib_qp_handle_t*)(ULONG_PTR)&m_uQp,\r
+ &qp_ioctl.out.umv_buf\r
+ );\r
+\r
+\r
+ switch( qp_ioctl.out.status )\r
+ {\r
+ case IB_SUCCESS:\r
+ m_hQp = qp_ioctl.out.h_qp;\r
+ m_Qpn = qp_ioctl.out.attr.num;\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Created QP %#I64x, QPn %#x, pd %#I64x, context %p \n", \r
+ m_hQp, m_Qpn, m_pParent->m_hPd, this ) );\r
+ return S_OK;\r
+\r
+ case IB_INVALID_MAX_WRS:\r
+ if( nInboundEntries > nOutboundEntries )\r
+ return ND_INVALID_PARAMETER_4;\r
+ else\r
+ return ND_INVALID_PARAMETER_5;\r
+\r
+ case IB_INVALID_MAX_SGE:\r
+ if( nInboundSge > nOutboundSge )\r
+ return ND_INVALID_PARAMETER_6;\r
+ else\r
+ return ND_INVALID_PARAMETER_7;\r
+\r
+ case IB_INSUFFICIENT_MEMORY:\r
+ return ND_NO_MEMORY;\r
+\r
+ default:\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+ }\r
+}\r
+\r
+void CEndpoint::DestroyQp()\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* Call the uvp pre call if the vendor library provided a valid QP handle */\r
+ CL_ASSERT( m_pParent->m_Ifc.user_verbs.pre_destroy_qp );\r
+ m_pParent->m_Ifc.user_verbs.pre_destroy_qp( m_uQp );\r
+\r
+ ual_destroy_qp_ioctl_t qp_ioctl;\r
+ cl_memclr( &qp_ioctl, sizeof(qp_ioctl) );\r
+ qp_ioctl.in.h_qp = m_hQp;\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Destroy QP %I64x\n", m_hQp) );\r
+\r
+ DWORD bytes_ret;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_DESTROY_QP,\r
+ &qp_ioctl.in,\r
+ sizeof(qp_ioctl.in),\r
+ &qp_ioctl.out,\r
+ sizeof(qp_ioctl.out),\r
+ &bytes_ret,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || bytes_ret != sizeof(qp_ioctl.out) )\r
+ qp_ioctl.out.status = IB_ERROR;\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Destroyed QP %#I64x, QPn %#x, pd %#I64x, context %p \n", \r
+ m_hQp, m_Qpn, m_pParent->m_hPd, this ) );\r
+ \r
+ /* Call vendor's post_destroy_qp */\r
+ CL_ASSERT( m_pParent->m_Ifc.user_verbs.post_destroy_qp );\r
+ m_pParent->m_Ifc.user_verbs.post_destroy_qp(\r
+ m_uQp,\r
+ qp_ioctl.out.status\r
+ );\r
+ m_hQp = NULL;\r
+}\r
+\r
+HRESULT CEndpoint::ModifyQp(\r
+ __in ib_qp_state_t NewState )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* Setup the qp_ioctl */\r
+ ual_ndi_modify_qp_ioctl_in_t qp_ioctl;\r
+ cl_memclr( &qp_ioctl, sizeof(qp_ioctl) );\r
+\r
+ switch( NewState )\r
+ {\r
+ case IB_QPS_INIT:\r
+ qp_ioctl.qp_mod.state.init.primary_port = m_pParent->m_PortNum;\r
+ qp_ioctl.qp_mod.state.init.qkey = 0;\r
+ qp_ioctl.qp_mod.state.init.pkey_index = 0;\r
+ qp_ioctl.qp_mod.state.init.access_ctrl =\r
+ IB_AC_LOCAL_WRITE | IB_AC_RDMA_READ | IB_AC_RDMA_WRITE;\r
+\r
+ // Fall through.\r
+ case IB_QPS_RESET:\r
+ case IB_QPS_ERROR:\r
+ qp_ioctl.qp_mod.req_state = NewState;\r
+ }\r
+\r
+ /* Call the uvp ND modify verb */\r
+ CL_ASSERT( m_pParent->m_Ifc.user_verbs.nd_modify_qp );\r
+ void* pOutbuf;\r
+ DWORD szOutbuf;\r
+\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp(\r
+ m_uQp,\r
+ &pOutbuf,\r
+ &szOutbuf\r
+ );\r
+\r
+ qp_ioctl.h_qp = m_hQp;\r
+\r
+ DWORD bytes_ret;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_NDI_MODIFY_QP,\r
+ &qp_ioctl,\r
+ sizeof(qp_ioctl),\r
+ pOutbuf,\r
+ szOutbuf,\r
+ &bytes_ret,\r
+ NULL );\r
+\r
+ if( fSuccess != TRUE )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ return S_OK;\r
+}\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+#include "ndspi.h"\r
+#include <iba/ib_al.h>\r
+#include <ws2tcpip.h>\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// HPC Pack 2008 Beta 2 SPI\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+class CAdapter;\r
+class CCq;\r
+\r
+class CEndpoint :\r
+ public INDEndpoint\r
+{\r
+ friend class CConnector;\r
+\r
+private:\r
+ CEndpoint(void);\r
+ ~CEndpoint(void);\r
+\r
+ HRESULT Initialize(\r
+ __in CAdapter* pParent,\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData\r
+ );\r
+\r
+public:\r
+ static HRESULT Create(\r
+ __in CAdapter* pParent,\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData,\r
+ __out INDEndpoint** ppEndpoint\r
+ );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDEndpoint methods ***\r
+ HRESULT STDMETHODCALLTYPE Flush(void);\r
+\r
+ void STDMETHODCALLTYPE StartRequestBatch(void);\r
+\r
+ void STDMETHODCALLTYPE SubmitRequestBatch(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE Send(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in DWORD Flags\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE SendAndInvalidate(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in DWORD Flags\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Receive(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Bind(\r
+ __out ND_RESULT* pResult,\r
+ __in ND_MR_HANDLE hMr,\r
+ __in INDMemoryWindow* pMw,\r
+ __in_bcount(BufferSize) const void* pBuffer,\r
+ __in SIZE_T BufferSize,\r
+ __in DWORD Flags,\r
+ __out ND_MW_DESCRIPTOR* pMwDescriptor\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Invalidate(\r
+ __out ND_RESULT* pResult,\r
+ __in INDMemoryWindow* pMw,\r
+ __in DWORD Flags\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Read(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Write(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ );\r
+\r
+private:\r
+ HRESULT Rdma(\r
+ __out ND_RESULT* pResult,\r
+ __in ib_wr_type_t Type,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ );\r
+\r
+ HRESULT CreateQp(\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit\r
+ );\r
+\r
+ void DestroyQp();\r
+\r
+ HRESULT ModifyQp(\r
+ __in ib_qp_state_t NewState\r
+ );\r
+\r
+protected:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter* m_pParent;\r
+\r
+ uint64_t m_hQp;\r
+ ib_qp_handle_t m_uQp;\r
+\r
+ net32_t m_Qpn;\r
+\r
+ UINT8 m_Ird;\r
+ UINT8 m_Ord;\r
+};\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#include "NdListen.h"\r
+#include "NdAdapter.h"\r
+#include "NdEndpoint.h"\r
+#include "NdConnector.h"\r
+#include "al_dev.h"\r
+#pragma warning( push, 3 )\r
+#include "winternl.h"\r
+#pragma warning( pop )\r
+#include <complib/cl_byteswap.h>\r
+#include <limits.h>\r
+#include "nddebug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdListen.tmh"\r
+#endif\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+HRESULT GetPdataForPassive(\r
+ __in UINT8* pSrc,\r
+ __in SIZE_T SrcLength,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ )\r
+{\r
+ if( SrcLength != IB_REQ_PDATA_SIZE )\r
+ {\r
+ ND_PRINT( TRACE_LEVEL_ERROR, ND_DBG_NDI, \r
+ ("Connection aborted: incorrect pdata_len %d \n", (int)SrcLength ));\r
+ return ND_CONNECTION_ABORTED;\r
+ }\r
+\r
+ if( pPrivateDataLength == NULL )\r
+ return S_OK;\r
+\r
+ ib_cm_rdma_req_t* pIpData = (ib_cm_rdma_req_t*)pSrc;\r
+ CL_ASSERT( pIpData->maj_min_ver == 0 );\r
+ CL_ASSERT( pIpData->ipv == 0x40 || pIpData->ipv == 0x60 );\r
+\r
+ if( *pPrivateDataLength == 0 )\r
+ {\r
+ *pPrivateDataLength = sizeof(pIpData->pdata);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+\r
+ CopyMemory(\r
+ pPrivateData,\r
+ pIpData->pdata,\r
+ min( *pPrivateDataLength, sizeof(pIpData->pdata) )\r
+ );\r
+\r
+ HRESULT hr;\r
+ if( *pPrivateDataLength < sizeof(pIpData->pdata) )\r
+ {\r
+ hr = ND_BUFFER_OVERFLOW;\r
+ }\r
+ else\r
+ {\r
+ hr = S_OK;\r
+ }\r
+\r
+ *pPrivateDataLength = sizeof(pIpData->pdata);\r
+ return hr;\r
+}\r
+\r
+HRESULT GetPdataForActive(\r
+ __in UINT8* pSrc,\r
+ __in SIZE_T SrcLength,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ )\r
+{\r
+ if( pPrivateDataLength == NULL )\r
+ return S_OK;\r
+\r
+ if( *pPrivateDataLength == 0 )\r
+ {\r
+ *pPrivateDataLength = SrcLength;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+\r
+ CopyMemory(\r
+ pPrivateData,\r
+ pSrc,\r
+ min( *pPrivateDataLength, SrcLength ) );\r
+\r
+ HRESULT hr;\r
+ if( *pPrivateDataLength < IB_REJ_PDATA_SIZE )\r
+ {\r
+ hr = ND_BUFFER_OVERFLOW;\r
+ }\r
+ else\r
+ {\r
+ hr = S_OK;\r
+ }\r
+\r
+ *pPrivateDataLength = SrcLength;\r
+ return hr;\r
+}\r
+\r
+ CListen::CListen(void) :\r
+ m_nRef( 1 ),\r
+ m_pParent( NULL ),\r
+ m_cid( 0 )\r
+ {\r
+ }\r
+\r
+ CListen::~CListen(void)\r
+ {\r
+ if( m_cid != 0 )\r
+ {\r
+ DWORD bytes_ret;\r
+ DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_DESTROY_CEP,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ NULL,\r
+ 0,\r
+ &bytes_ret,\r
+ NULL );\r
+ }\r
+\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+ }\r
+\r
+ HRESULT CListen::Initialize(\r
+ __in CAdapter* pParent,\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort\r
+ )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ m_pParent = pParent;\r
+ m_pParent->AddRef();\r
+\r
+ UNREFERENCED_PARAMETER( Backlog );\r
+\r
+ if( Port == 0 && pAssignedPort == NULL )\r
+ return ND_INVALID_PARAMETER_MIX;\r
+\r
+ //\r
+ // IP Addressing Annex only supports a single byte for protocol.\r
+ //\r
+ if( Protocol > UCHAR_MAX || Protocol < 0 )\r
+ return ND_INVALID_PARAMETER_3;\r
+\r
+ ual_cep_listen_ioctl_t listen;\r
+ listen.cid = 0;\r
+\r
+ listen.cep_listen.svc_id = \r
+ 0x0000000001000000 | Protocol << 16 | Port;\r
+\r
+ listen.cep_listen.port_guid = m_pParent->m_PortGuid;\r
+\r
+ switch( m_pParent->m_Addr.v4.sin_family )\r
+ {\r
+ case AF_INET:\r
+ ZeroMemory( listen.compare, ATS_IPV4_OFFSET );\r
+ CopyMemory( &listen.compare[ATS_IPV4_OFFSET],\r
+ (uint8_t*)&m_pParent->m_Addr.v4.sin_addr,\r
+ sizeof(m_pParent->m_Addr.v4.sin_addr) );\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Listen for: IP %#x, port %#hx\n", \r
+ cl_hton32(m_pParent->m_Addr.v4.sin_addr.S_un.S_addr), cl_hton16(m_pParent->m_Addr.v4.sin_port) ) );\r
+ break;\r
+ case AF_INET6:\r
+ CopyMemory( listen.compare,\r
+ (uint8_t*)&m_pParent->m_Addr.v6.sin6_addr,\r
+ sizeof(m_pParent->m_Addr.v6.sin6_addr) );\r
+ break;\r
+ }\r
+ listen.cep_listen.p_cmp_buf = listen.compare;\r
+ listen.cep_listen.cmp_len = 16;\r
+ listen.cep_listen.cmp_offset = FIELD_OFFSET( ib_cm_rdma_req_t, dst_ip_addr );\r
+\r
+ IO_STATUS_BLOCK IoStatus;\r
+ IoStatus.Status = NtDeviceIoControlFile(\r
+ m_pParent->m_hSync,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ &IoStatus,\r
+ UAL_NDI_LISTEN_CM,\r
+ &listen,\r
+ sizeof(listen),\r
+ &m_cid,\r
+ sizeof(m_cid) );\r
+\r
+ switch( IoStatus.Status )\r
+ {\r
+ case ND_SUCCESS:\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Listen for: Guid %#I64x, sid %#I64x\n", \r
+ m_pParent->m_PortGuid, listen.cep_listen.svc_id ) );\r
+ break;\r
+\r
+ case IB_INVALID_SETTING:\r
+ return ND_ADDRESS_ALREADY_EXISTS;\r
+\r
+ default:\r
+ return IoStatus.Status;\r
+ }\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Created listen CEP with cid %d \n", m_cid ) );\r
+\r
+ // TODO: Come up with something better for port number.\r
+ if( Port == 0 )\r
+ Port = (USHORT)m_cid | (USHORT)(m_cid >> 16);\r
+\r
+ if( pAssignedPort )\r
+ *pAssignedPort = Port;\r
+\r
+ m_Protocol = (UINT8)Protocol;\r
+ return S_OK;\r
+ }\r
+\r
+ HRESULT CListen::Create(\r
+ __in CAdapter* pParent,\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort,\r
+ __deref_out INDListen** ppListen\r
+ )\r
+ {\r
+ CListen* pListen = new CListen();\r
+ if( pListen == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ HRESULT hr = pListen->Initialize(\r
+ pParent,\r
+ Backlog,\r
+ Protocol,\r
+ Port,\r
+ pAssignedPort );\r
+ if( FAILED( hr ) )\r
+ {\r
+ delete pListen;\r
+ return hr;\r
+ }\r
+\r
+ *ppListen = pListen;\r
+ return S_OK;\r
+ }\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT CListen::QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ )\r
+ {\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDListen ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ ULONG CListen::AddRef(void)\r
+ {\r
+ return InterlockedIncrement( &m_nRef );\r
+ }\r
+\r
+ ULONG CListen::Release(void)\r
+ {\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+ }\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT CListen::CancelOverlappedRequests(void)\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ DWORD bytes_ret;\r
+ BOOL ret = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_NDI_CANCEL_CM_IRPS,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ NULL,\r
+ 0,\r
+ &bytes_ret,\r
+ NULL );\r
+\r
+ if( ret )\r
+ return S_OK;\r
+ else\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+\r
+ HRESULT CListen::GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ *pNumberOfBytesTransferred = 0;\r
+ ::GetOverlappedResult(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped,\r
+ (DWORD*)pNumberOfBytesTransferred,\r
+ bWait );\r
+ return (HRESULT)pOverlapped->Internal;\r
+ }\r
+\r
+ // *** INDListen methods ***\r
+ HRESULT CListen::GetConnectionRequest(\r
+ __inout INDConnector* pConnector,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ static_cast<CConnector*>(pConnector)->m_Protocol = m_Protocol;\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ return NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_GET_REQ_CM,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ &static_cast<CConnector*>(pConnector)->m_cid,\r
+ sizeof(static_cast<CConnector*>(pConnector)->m_cid) );\r
+ }\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+#include "ndspi.h"\r
+#include <iba/ib_al.h>\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+HRESULT GetPdataForPassive(\r
+ __in UINT8* pSrc,\r
+ __in SIZE_T SrcLength,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ );\r
+\r
+HRESULT GetPdataForActive(\r
+ __in UINT8* pSrc,\r
+ __in SIZE_T SrcLength,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ );\r
+\r
+class CAdapter;\r
+\r
+class CListen :\r
+ public INDListen\r
+{\r
+private:\r
+ CListen(void);\r
+ ~CListen(void);\r
+\r
+ HRESULT Initialize(\r
+ __in CAdapter* pParent,\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort\r
+ );\r
+\r
+public:\r
+ static HRESULT Create(\r
+ __in CAdapter* pParent,\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort,\r
+ __deref_out INDListen** ppListen\r
+ );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT STDMETHODCALLTYPE CancelOverlappedRequests(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ );\r
+\r
+ // *** INDListen methods ***\r
+ HRESULT STDMETHODCALLTYPE GetConnectionRequest(\r
+ __inout INDConnector* pConnector,\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+private:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter* m_pParent;\r
+\r
+ UINT8 m_Protocol;\r
+ net32_t m_cid;\r
+};\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#include <initguid.h>\r
+#include "ndspi.h"\r
+#include "NdMr.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ CMr::CMr(void)\r
+ {\r
+ }\r
+\r
+ CMr::~CMr(void)\r
+ {\r
+ }\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+\r
+#include "iba/ib_al_ioctl.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ class CMr\r
+ {\r
+ friend class CAdapter;\r
+ friend class CEndpoint;\r
+\r
+ friend class CAdapter_Beta1;\r
+ friend class CEndpoint_Beta1;\r
+ public:\r
+ CMr(void);\r
+ ~CMr(void);\r
+\r
+ protected:\r
+ const char* pBase;\r
+ uint32_t Length;\r
+ ual_reg_mem_ioctl_t mr_ioctl;\r
+ };\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#include "NdMw.h"\r
+#include "NdAdapter.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdMw.tmh"\r
+#endif\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ CMw::CMw(void) :\r
+ m_nRef( 1 ),\r
+ m_pParent( NULL )\r
+ {\r
+ }\r
+\r
+ CMw::~CMw(void)\r
+ {\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+ }\r
+\r
+ HRESULT CMw::Initialize(\r
+ CAdapter* pParent,\r
+ ND_RESULT* pInvalidateResult\r
+ )\r
+ {\r
+ m_pParent = pParent;\r
+ m_pParent->AddRef();\r
+\r
+ m_pInvalidateResult = pInvalidateResult;\r
+ return S_OK;\r
+ }\r
+\r
+ HRESULT CMw::QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ )\r
+ {\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDMemoryWindow ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ ULONG CMw::AddRef(void)\r
+ {\r
+ return InterlockedIncrement( &m_nRef );\r
+ }\r
+\r
+ ULONG CMw::Release(void)\r
+ {\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+ }\r
+\r
+ HRESULT CMw::Close(void)\r
+ {\r
+ Release();\r
+ return S_OK;\r
+ }\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+#include "ndspi.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ class CAdapter;\r
+\r
+ class CMw :\r
+ public INDMemoryWindow\r
+ {\r
+ public:\r
+ CMw(void);\r
+ ~CMw(void);\r
+\r
+ HRESULT Initialize(\r
+ CAdapter* pParent,\r
+ ND_RESULT* pInvalidateResult );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDMemoryWindow methods ***\r
+ HRESULT STDMETHODCALLTYPE Close(void);\r
+\r
+ //operator ND_RESULT*(){ return m_pInvalidateResult; };\r
+\r
+ private:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter* m_pParent;\r
+\r
+ ND_RESULT* m_pInvalidateResult;\r
+ };\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// HPC Pack 2008 Beta 1 SPI\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+ class CAdapter_Beta1;\r
+\r
+ class CMw_Beta1 :\r
+ public INDMemoryWindow\r
+ {\r
+ public:\r
+ CMw_Beta1(void);\r
+ ~CMw_Beta1(void);\r
+\r
+ HRESULT Initialize(\r
+ CAdapter_Beta1* pParent,\r
+ ND_RESULT* pInvalidateResult );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDMemoryWindow methods ***\r
+ HRESULT STDMETHODCALLTYPE Close(void);\r
+\r
+ //operator ND_RESULT*(){ return m_pInvalidateResult; };\r
+\r
+ private:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter_Beta1* m_pParent;\r
+\r
+ ND_RESULT* m_pInvalidateResult;\r
+ };\r
+\r
+} // namespace
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#include <tchar.h>\r
+#include <ndspi.h>\r
+#include <iba/ib_at_ioctl.h>\r
+#include <complib/cl_types.h>\r
+#include <complib/cl_ioctl.h>\r
+#pragma warning( push, 3 )\r
+#include <unknwn.h>\r
+#include <assert.h>\r
+#include <ws2tcpip.h>\r
+#include <winioctl.h>\r
+#include <limits.h>\r
+#include <ws2spi.h>\r
+#pragma warning( pop )\r
+#include "ndprov.h"\r
+#include "ndadapter.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdProv.tmh"\r
+#endif\r
+\r
+#include "nddebug.h"\r
+\r
+uint32_t g_nd_dbg_level = TRACE_LEVEL_ERROR;\r
+/* WPP doesn't want here literals! */\r
+uint32_t g_nd_dbg_flags = 0x80000001; /* ND_DBG_ERROR | ND_DBG_NDI; */\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ static LONG gnRef = 0;\r
+\r
+ CProvider::CProvider() :\r
+ m_nRef( 1 )\r
+ {\r
+ InterlockedIncrement( &gnRef );\r
+ }\r
+\r
+ CProvider::~CProvider()\r
+ {\r
+ InterlockedDecrement( &gnRef );\r
+ }\r
+\r
+ HRESULT CProvider::QueryInterface(\r
+ const IID &riid,\r
+ void **ppObject )\r
+ {\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppObject = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDProvider ) )\r
+ {\r
+ *ppObject = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ ULONG CProvider::AddRef()\r
+ {\r
+ return InterlockedIncrement( &m_nRef );\r
+ }\r
+\r
+ ULONG CProvider::Release()\r
+ {\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+ }\r
+\r
+ HRESULT CProvider::QueryAddressList(\r
+ __out_bcount_part_opt(*pBufferSize, *pBufferSize) SOCKET_ADDRESS_LIST* pAddressList,\r
+ __inout SIZE_T* pBufferSize )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ HANDLE hIbatDev = CreateFileW( IBAT_WIN32_NAME,\r
+ MAXIMUM_ALLOWED, 0, NULL,\r
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
+ if( hIbatDev == INVALID_HANDLE_VALUE )\r
+ return ND_NO_MEMORY;\r
+\r
+ IOCTL_IBAT_IP_ADDRESSES_IN addrIn;\r
+\r
+ addrIn.Version = IBAT_IOCTL_VERSION;\r
+ addrIn.PortGuid = 0;\r
+\r
+ DWORD size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
+ IOCTL_IBAT_IP_ADDRESSES_OUT *pAddrOut;\r
+ do\r
+ {\r
+ pAddrOut = (IOCTL_IBAT_IP_ADDRESSES_OUT*)HeapAlloc(\r
+ GetProcessHeap(),\r
+ 0,\r
+ size );\r
+ if( !pAddrOut )\r
+ {\r
+ //AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
+ // ("Failed to allocate output buffer.\n") );\r
+ return ND_NO_MEMORY;\r
+ }\r
+\r
+ if( !DeviceIoControl( hIbatDev, IOCTL_IBAT_IP_ADDRESSES,\r
+ &addrIn, sizeof(addrIn), pAddrOut, size, &size, NULL ) )\r
+ {\r
+ HeapFree( GetProcessHeap(), 0, pAddrOut );\r
+ //AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
+ // ("IOCTL_IBAT_IP_ADDRESSES failed (%x).\n", GetLastError()) );\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+\r
+ if( pAddrOut->Size > size )\r
+ {\r
+ size = pAddrOut->Size;\r
+ HeapFree( GetProcessHeap(), 0, pAddrOut );\r
+ pAddrOut = NULL;\r
+ }\r
+\r
+ } while( !pAddrOut );\r
+\r
+ CloseHandle( hIbatDev );\r
+\r
+ //\r
+ // Note: the required size computed is a few bytes larger than necessary, \r
+ // but that keeps the code clean.\r
+ //\r
+ SIZE_T size_req = sizeof(SOCKET_ADDRESS_LIST);\r
+\r
+ switch( pAddrOut->AddressCount )\r
+ {\r
+ case 0:\r
+ break;\r
+\r
+ default:\r
+ size_req += (pAddrOut->AddressCount - 1) *\r
+ (sizeof(SOCKET_ADDRESS) + sizeof(SOCKADDR));\r
+ /* Fall through. */\r
+ __fallthrough;\r
+\r
+ case 1:\r
+ /* Add the space for the first address. */\r
+ size_req += sizeof(SOCKADDR);\r
+ break;\r
+ }\r
+\r
+ if( size_req > *pBufferSize )\r
+ {\r
+ HeapFree( GetProcessHeap(), 0, pAddrOut );\r
+ *pBufferSize = size_req;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+\r
+ ZeroMemory( pAddressList, *pBufferSize );\r
+\r
+ /* We store the array of addresses after the last address pointer:\r
+ * iAddressCount\r
+ * Address[0]; <-- points to sockaddr[0]\r
+ * Address[1]; <-- points to sockaddr[1]\r
+ * ...\r
+ * Address[n-1]; <-- points to sockaddr[n-1]\r
+ * sockaddr[0];\r
+ * sockaddr[1];\r
+ * ...\r
+ * sockaddr[n-1]\r
+ */\r
+ BYTE* pBuf = (BYTE*)(&(pAddressList->Address[pAddrOut->AddressCount]));\r
+ *pBufferSize = size_req;\r
+\r
+ pAddressList->iAddressCount = 0;\r
+ for( LONG i = 0; i < pAddrOut->AddressCount; i++ )\r
+ {\r
+ pAddressList->Address[pAddressList->iAddressCount].lpSockaddr =\r
+ (LPSOCKADDR)pBuf;\r
+\r
+ switch( pAddrOut->Address[i].IpVersion )\r
+ {\r
+ case 4:\r
+ {\r
+ struct sockaddr_in* pAddr4 = ((struct sockaddr_in*)pBuf);\r
+ pAddr4->sin_family = AF_INET;\r
+ pAddr4->sin_addr.s_addr =\r
+ *((u_long*)&pAddrOut->Address[i].Address[12]);\r
+ pAddressList->Address[pAddressList->iAddressCount].iSockaddrLength =\r
+ sizeof(struct sockaddr_in);\r
+ }\r
+ break;\r
+\r
+ case 6:\r
+ {\r
+ struct sockaddr_in6* pAddr6 = ((struct sockaddr_in6*)pBuf);\r
+ pAddr6->sin6_family = AF_INET6;\r
+ CopyMemory(\r
+ &pAddr6->sin6_addr,\r
+ pAddrOut->Address[i].Address,\r
+ sizeof(pAddr6->sin6_addr) );\r
+ pAddressList->Address[pAddressList->iAddressCount].iSockaddrLength =\r
+ sizeof(struct sockaddr_in6);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ continue;\r
+ }\r
+\r
+ pBuf += pAddressList->Address[pAddressList->iAddressCount++].iSockaddrLength;\r
+ }\r
+\r
+ HeapFree( GetProcessHeap(), 0, pAddrOut );\r
+\r
+ return S_OK;\r
+ }\r
+\r
+ HRESULT CProvider::OpenAdapter(\r
+ __in_bcount(AddressLength) const struct sockaddr* pAddress,\r
+ __in SIZE_T AddressLength,\r
+ __deref_out INDAdapter** ppAdapter )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( AddressLength < sizeof(struct sockaddr) )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ IOCTL_IBAT_IP_TO_PORT_IN in;\r
+ in.Version = IBAT_IOCTL_VERSION;\r
+\r
+ switch( pAddress->sa_family )\r
+ {\r
+ case AF_INET:\r
+ if( AddressLength < sizeof(struct sockaddr_in) )\r
+ return ND_INVALID_ADDRESS;\r
+ in.Address.IpVersion = 4;\r
+ RtlCopyMemory(\r
+ &in.Address.Address[12],\r
+ &((struct sockaddr_in*)pAddress)->sin_addr,\r
+ sizeof( ((struct sockaddr_in*)pAddress)->sin_addr ) );\r
+ break;\r
+\r
+ case AF_INET6:\r
+ if( AddressLength < sizeof(struct sockaddr_in6) )\r
+ return ND_INVALID_ADDRESS;\r
+ in.Address.IpVersion = 6;\r
+ RtlCopyMemory(\r
+ in.Address.Address,\r
+ &((struct sockaddr_in6*)pAddress)->sin6_addr,\r
+ sizeof(in.Address.Address) );\r
+ break;\r
+\r
+ default:\r
+ return ND_INVALID_ADDRESS;\r
+ }\r
+\r
+ HANDLE hIbatDev = CreateFileW( IBAT_WIN32_NAME,\r
+ MAXIMUM_ALLOWED, 0, NULL,\r
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
+ if( hIbatDev == INVALID_HANDLE_VALUE )\r
+ return ND_NO_MEMORY;\r
+\r
+ IBAT_PORT_RECORD out;\r
+ DWORD size;\r
+ BOOL fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_IP_TO_PORT,\r
+ &in, sizeof(in), &out, sizeof(out), &size, NULL );\r
+ \r
+ CloseHandle( hIbatDev );\r
+ if( !fSuccess || size == 0 )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ return CAdapter::Create( this, pAddress, &out, ppAdapter );\r
+ }\r
+\r
+ CClassFactory::CClassFactory(void) :\r
+ m_nRef( 1 )\r
+ {\r
+ InterlockedIncrement( &gnRef );\r
+ }\r
+\r
+ CClassFactory::~CClassFactory(void)\r
+ {\r
+ InterlockedDecrement( &gnRef );\r
+ }\r
+\r
+ HRESULT CClassFactory::QueryInterface(\r
+ REFIID riid,\r
+ void** ppObject )\r
+ {\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppObject = this;\r
+ return S_OK;\r
+ }\r
+ if( IsEqualIID( riid, IID_IClassFactory ) )\r
+ {\r
+ *ppObject = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ ULONG CClassFactory::AddRef()\r
+ {\r
+ return InterlockedIncrement( &m_nRef );\r
+ }\r
+\r
+ ULONG CClassFactory::Release()\r
+ {\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+ }\r
+\r
+ HRESULT CClassFactory::CreateInstance(\r
+ IUnknown* pUnkOuter,\r
+ REFIID riid,\r
+ void** ppObject )\r
+ {\r
+ if( pUnkOuter != NULL )\r
+ return CLASS_E_NOAGGREGATION;\r
+\r
+ if( IsEqualIID( riid, IID_INDProvider ) )\r
+ {\r
+ *ppObject = new CProvider();\r
+ if( !*ppObject )\r
+ return E_OUTOFMEMORY;\r
+\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ HRESULT CClassFactory::LockServer( BOOL fLock )\r
+ { \r
+ UNREFERENCED_PARAMETER( fLock );\r
+ return S_OK;\r
+ }\r
+\r
+} // namespace\r
+\r
+void* __cdecl operator new(\r
+ size_t count\r
+ )\r
+{\r
+ return HeapAlloc( GetProcessHeap(), 0, count );\r
+}\r
+\r
+\r
+void __cdecl operator delete(\r
+ void* object\r
+ )\r
+{\r
+ HeapFree( GetProcessHeap(), 0, object );\r
+}\r
+\r
+extern "C" {\r
+STDAPI DllGetClassObject(\r
+ REFCLSID rclsid,\r
+ REFIID riid,\r
+ LPVOID * ppv\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ UNREFERENCED_PARAMETER( rclsid );\r
+\r
+ if( IsEqualIID( riid, IID_IClassFactory ) )\r
+ {\r
+ NetworkDirect::CClassFactory* pFactory = new NetworkDirect::CClassFactory();\r
+ if( pFactory == NULL )\r
+ return E_OUTOFMEMORY;\r
+\r
+ *ppv = pFactory;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+STDAPI DllCanUnloadNow(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( InterlockedCompareExchange( &NetworkDirect::gnRef, 0, 0 ) != 0 )\r
+ return S_FALSE;\r
+\r
+ return S_OK;\r
+}\r
+\r
+int\r
+WSPAPI\r
+WSPStartup(\r
+ IN WORD wVersionRequested,\r
+ OUT LPWSPDATA lpWSPData,\r
+ IN LPWSAPROTOCOL_INFOW lpProtocolInfo,\r
+ IN WSPUPCALLTABLE UpcallTable,\r
+ OUT LPWSPPROC_TABLE lpProcTable\r
+ )\r
+{\r
+ UNREFERENCED_PARAMETER( wVersionRequested );\r
+ UNREFERENCED_PARAMETER( lpWSPData );\r
+ UNREFERENCED_PARAMETER( lpProtocolInfo );\r
+ UNREFERENCED_PARAMETER( UpcallTable );\r
+ UNREFERENCED_PARAMETER( lpProcTable );\r
+ return WSASYSNOTREADY;\r
+}\r
+\r
+static BOOL\r
+_DllMain(\r
+ IN HINSTANCE hinstDll,\r
+ IN DWORD dwReason,\r
+ IN LPVOID lpvReserved )\r
+{\r
+\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ UNUSED_PARAM( hinstDll );\r
+ UNUSED_PARAM( lpvReserved );\r
+\r
+ switch( dwReason )\r
+ {\r
+ case DLL_PROCESS_ATTACH:\r
+\r
+\r
+#if defined(EVENT_TRACING)\r
+#if DBG\r
+ WPP_INIT_TRACING(L"ibndprov.dll");\r
+#else\r
+ WPP_INIT_TRACING(L"ibndprov.dll");\r
+#endif\r
+#endif\r
+\r
+\r
+#if !defined(EVENT_TRACING)\r
+#if DBG \r
+ TCHAR env_var[16];\r
+ DWORD i;\r
+\r
+ i = GetEnvironmentVariable( "IBNDPROV_DBG_LEVEL", env_var, sizeof(env_var) );\r
+ if( i && i <= 16 )\r
+ {\r
+ g_nd_dbg_level = _tcstoul( env_var, NULL, 16 );\r
+ }\r
+\r
+ i = GetEnvironmentVariable( "IBNDPROV_DBG_FLAGS", env_var, sizeof(env_var) );\r
+ if( i && i <= 16 )\r
+ {\r
+ g_nd_dbg_flags = _tcstoul( env_var, NULL, 16 );\r
+ }\r
+\r
+ if( g_nd_dbg_flags & ND_DBG_ERR )\r
+ g_nd_dbg_flags |= CL_DBG_ERROR;\r
+\r
+ ND_PRINT( TRACE_LEVEL_ERROR, ND_DBG_ERR ,\r
+ ("(pcs %#x) IbNdProv: Debug print: level:%d, flags 0x%x\n",\r
+ GetCurrentProcessId(), g_nd_dbg_level ,g_nd_dbg_flags) );\r
+\r
+#endif\r
+#endif\r
+\r
+ ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI, ("DllMain: DLL_PROCESS_ATTACH\n") );\r
+ break;\r
+\r
+ case DLL_PROCESS_DETACH:\r
+ ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("DllMain: DLL_PROCESS_DETACH, ref count %d\n", NetworkDirect::gnRef) );\r
+\r
+#if defined(EVENT_TRACING)\r
+ WPP_CLEANUP();\r
+#endif\r
+ break;\r
+ }\r
+\r
+ ND_EXIT( ND_DBG_NDI );\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
+extern BOOL APIENTRY\r
+_DllMainCRTStartupForGS(\r
+ IN HINSTANCE h_module,\r
+ IN DWORD ul_reason_for_call, \r
+ IN LPVOID lp_reserved );\r
+\r
+\r
+BOOL APIENTRY\r
+DllMain(\r
+ IN HINSTANCE h_module,\r
+ IN DWORD ul_reason_for_call, \r
+ IN LPVOID lp_reserved )\r
+{\r
+ switch( ul_reason_for_call )\r
+ {\r
+ case DLL_PROCESS_ATTACH:\r
+ if( !_DllMainCRTStartupForGS(\r
+ h_module, ul_reason_for_call, lp_reserved ) )\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ return _DllMain( h_module, ul_reason_for_call, lp_reserved );\r
+\r
+ case DLL_THREAD_ATTACH:\r
+ ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI, ("DllMain: DLL_THREAD_ATTACH\n") );\r
+ break;\r
+\r
+ case DLL_THREAD_DETACH:\r
+ ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI, ("DllMain: DLL_THREAD_DETACH\n") );\r
+ break;\r
+\r
+ case DLL_PROCESS_DETACH:\r
+ _DllMain( h_module, ul_reason_for_call, lp_reserved );\r
+\r
+ return _DllMainCRTStartupForGS(\r
+ h_module, ul_reason_for_call, lp_reserved );\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+} // extern "C"\r
+\r
--- /dev/null
+LIBRARY IbNdProv.dll\r
+\r
+EXPORTS\r
+ DllGetClassObject private\r
+ WSPStartup \r
+ DllCanUnloadNow private
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+#include <iba/ib_at_ioctl.h>\r
+\r
+#ifdef __cplusplus\r
+namespace NetworkDirect\r
+{\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// HPC Pack 2008 Beta 2 SPI\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+class CProvider :\r
+ public INDProvider\r
+{\r
+ friend class CClassFactory;\r
+\r
+public:\r
+ CProvider(void);\r
+ ~CProvider(void);\r
+\r
+ // IUnknown Methods\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ void** ppObject\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // INDProvider Methods\r
+ HRESULT STDMETHODCALLTYPE QueryAddressList(\r
+ __out_bcount_part_opt(*pBufferSize, *pBufferSize) SOCKET_ADDRESS_LIST* pAddressList,\r
+ __inout SIZE_T* pBufferSize\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE OpenAdapter(\r
+ __in_bcount(AddressLength) const struct sockaddr* pAddress,\r
+ __in SIZE_T AddressLength,\r
+ __deref_out INDAdapter** ppAdapter\r
+ );\r
+\r
+private:\r
+ volatile LONG m_nRef;\r
+};\r
+\r
+\r
+class CClassFactory : public IClassFactory\r
+{\r
+public:\r
+ CClassFactory(void);\r
+ ~CClassFactory(void);\r
+\r
+ // IUnknown Methods.\r
+ HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppObject );\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // IClassFactory Methods.\r
+ HRESULT STDMETHODCALLTYPE CreateInstance( IUnknown* pUnkOuter, REFIID riid, void** ppObject );\r
+ HRESULT STDMETHODCALLTYPE LockServer( BOOL fLock );\r
+\r
+private:\r
+ volatile LONG m_nRef;\r
+};\r
+\r
+} // namespace\r
+\r
+void* __cdecl operator new(\r
+ size_t count\r
+ );\r
+\r
+void __cdecl operator delete(\r
+ void* object\r
+ );\r
+\r
+#endif // __cplusplus\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id$\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 "OpenFabrics Network Direct Provider (Debug)"\r
+#define VER_INTERNALNAME_STR "ibndprov.dll"\r
+#define VER_ORIGINALFILENAME_STR "ibndprov.dll"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR "OpenFabrics Network Direct Provider"\r
+#define VER_INTERNALNAME_STR "ibndprov.dll"\r
+#define VER_ORIGINALFILENAME_STR "ibndprov.dll"\r
+#endif\r
+\r
+#include <common.ver>\r
+\r
-TARGETNAME=fake\r
+TARGETNAME=ibndprov\r
+\r
TARGETPATH=..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
-TARGETTYPE=PROGRAM\r
-UMTYPE=console\r
-USE_MSVCRT=1\r
+TARGETTYPE=DYNLINK\r
+DLLDEF=NdProv.def\r
+DLLENTRY=DllMain\r
+\r
+!if $(FREEBUILD)\r
+ENABLE_EVENT_TRACING=1\r
+#!else\r
+#ENABLE_EVENT_TRACING=1\r
+!endif\r
+\r
+USE_NTDLL=1\r
+\r
+SOURCES=\\r
+ NdProv.rc \\r
+ NdAdapter.cpp \\r
+ NdCq.cpp \\r
+ NdEndpoint.cpp \\r
+ NdListen.cpp \\r
+ NdMr.cpp \\r
+ NdMw.cpp \\r
+ NdProv.cpp \\r
+ NdConnector.cpp\r
+\r
+\r
+INCLUDES=$(SDK_INC_PATH);..;..\..\..\inc;..\..\..\inc\user;..\..\..\core\al;..\..\..\core\al\user;$(ND_INC);$(PLATFORM_SDK_PATH)\Include\r
+\r
+USER_C_FLAGS=$(USER_C_FLAGS) -DEXPORT_AL_SYMBOLS -DCL_NO_TRACK_MEM -DWPP_OLDCC\r
+\r
+#/GL\r
+#LINKER_FLAGS=$(LINKER_FLAGS) /LTCG\r
+\r
+TARGETLIBS= \\r
+ $(SDK_LIB_PATH)\Kernel32.lib\\r
+ $(SDK_LIB_PATH)\Advapi32.lib\\r
+ $(SDK_LIB_PATH)\ws2_32.lib \\r
+ $(SDK_LIB_PATH)\iphlpapi.lib \\r
+ $(TARGETPATH)\*\ibat.lib \\r
+!if $(FREEBUILD)\r
+ $(TARGETPATH)\*\complib.lib \\r
+!else\r
+ $(TARGETPATH)\*\complibd.lib\\r
+!endif\r
+ $(SDK_LIB_PATH)\uuid.lib\r
+\r
\r
-SOURCES=fake.c\r
+!IFDEF ENABLE_EVENT_TRACING\r
\r
-INCLUDES=..;..\..\..\inc;..\..\..\inc\kernel;\r
+C_DEFINES = $(C_DEFINES) -DEVENT_TRACING\r
\r
-ND_TARGET1=..\..\..\bin\user\$(O)\ibndprov.dll\r
-ND_TARGET2=..\..\..\bin\user\$(O)\ndinstall.exe\r
+RUN_WPP = $(SOURCES) -ext: .c .h .C .H \\r
+ -scan:nddebug.h \\r
+ -func:ND_PRINT(LEVEL,FLAGS,(MSG,...)) \\r
+ -func:ND_PRINT_EXIT(LEVEL,FLAGS,(MSG,...)) \\r
+ -dll\r
+!ENDIF\r
\r
-NTTARGETFILES=$(ND_TARGET1) $(ND_TARGET2)\r
+BUILD_PRODUCES=NetworkDirect\r
\r
+MSC_WARNING_LEVEL= /W4\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
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft 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
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifdef __MODULE__\r
+#undef __MODULE__\r
+#endif\r
+#define __MODULE__ "[ND]"\r
+\r
+\r
+#include <complib/cl_debug.h>\r
+\r
+extern uint32_t g_nd_dbg_level;\r
+extern uint32_t g_nd_dbg_flags;\r
+\r
+#if defined(EVENT_TRACING)\r
+//\r
+// Software Tracing Definitions \r
+//\r
+\r
+\r
+#define WPP_CONTROL_GUIDS \\r
+ WPP_DEFINE_CONTROL_GUID(NDCtlGuid1,(1463B4CE,7A66,47a4,ABDB,09EE7AD9E698), \\r
+ WPP_DEFINE_BIT( ND_DBG_ERROR)\\r
+ WPP_DEFINE_BIT( ND_DBG_NDI))\r
+ \r
+\r
+\r
+#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)\r
+#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags)\r
+#define WPP_FLAG_ENABLED(flags)(WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= TRACE_LEVEL_VERBOSE)\r
+#define WPP_FLAG_LOGGER(flags) WPP_LEVEL_LOGGER(flags)\r
+\r
+\r
+// begin_wpp config\r
+// ND_ENTER( FLAG );\r
+// ND_EXIT( FLAG );\r
+// USEPREFIX(ND_PRINT, "%!STDPREFIX! [ND] :%!FUNC!() :");\r
+// USESUFFIX(ND_ENTER, " [ND] :%!FUNC!():[");\r
+// USESUFFIX(ND_EXIT, " [ND] :%!FUNC!():]");\r
+// end_wpp\r
+\r
+\r
+\r
+#else\r
+\r
+#include <wmistr.h>\r
+#include <evntrace.h>\r
+\r
+/*\r
+ * Debug macros\r
+ */\r
+\r
+\r
+/* Debug message source */\r
+#define ND_DBG_ERR (1 << 0)\r
+#define ND_DBG_NDI (1 << 1)\r
+\r
+#define ND_DBG_ERROR (CL_DBG_ERROR | ND_DBG_ERR)\r
+\r
+#if DBG\r
+\r
+// assignment of _level_ is need to to overcome warning C4127\r
+#define ND_PRINT( _level_,_flag_,_msg_) \\r
+ { \\r
+ if( g_nd_dbg_level >= (_level_) ) \\r
+ CL_TRACE( _flag_, g_nd_dbg_flags, _msg_ ); \\r
+ }\r
+\r
+\r
+#define ND_PRINT_EXIT( _level_,_flag_,_msg_) \\r
+ { \\r
+ if( g_nd_dbg_level >= (_level_) ) \\r
+ CL_TRACE( _flag_, g_nd_dbg_flags, _msg_ );\\r
+ ND_EXIT( _flag_ );\\r
+ }\r
+\r
+#define ND_ENTER( _flag_) \\r
+ { \\r
+ if( g_nd_dbg_level >= TRACE_LEVEL_VERBOSE ) \\r
+ CL_ENTER( _flag_, g_nd_dbg_flags ); \\r
+ }\r
+\r
+#define ND_EXIT( _flag_)\\r
+ { \\r
+ if( g_nd_dbg_level >= TRACE_LEVEL_VERBOSE ) \\r
+ CL_EXIT( _flag_, g_nd_dbg_flags ); \\r
+ }\r
+\r
+\r
+#else\r
+\r
+#define ND_PRINT( lvl, flags, msg)\r
+\r
+#define ND_PRINT_EXIT( _level_,_flag_,_msg_)\r
+\r
+#define ND_ENTER( _flag_)\r
+\r
+#define ND_EXIT( _flag_)\r
+\r
+\r
+#endif\r
+\r
+#endif //EVENT_TRACING\r
+\r
+\r
+#if DBG\r
+struct dbg_data\r
+{ \r
+ int64_t rcv_cnt;\r
+ int64_t rcv_pkts;\r
+ int64_t rcv_bytes;\r
+ int64_t rcv_pkts_err;\r
+ int64_t rcv_pkts_zero;\r
+ int64_t snd_cnt;\r
+ int64_t snd_pkts;\r
+ int64_t snd_bytes;\r
+ int64_t snd_pkts_err;\r
+ int64_t snd_pkts_zero;\r
+ int64_t c_cnt;\r
+ int64_t c_rcv_pkts;\r
+ int64_t c_rcv_bytes;\r
+ int64_t c_rcv_pkts_err;\r
+ int64_t c_snd_pkts;\r
+ int64_t c_snd_bytes;\r
+ int64_t c_snd_pkts_err;\r
+};\r
+\r
+extern dbg_data g;\r
+\r
+#endif\r