ND Provider source.
authorftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 7 Apr 2009 23:21:37 +0000 (23:21 +0000)
committerftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 7 Apr 2009 23:21:37 +0000 (23:21 +0000)
Signed-off-by: Fab Tillier <ftillier@microsoft.com>
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@2087 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

21 files changed:
ulp/nd/user/NdAdapter.cpp [new file with mode: 0644]
ulp/nd/user/NdAdapter.h [new file with mode: 0644]
ulp/nd/user/NdConnector.cpp [new file with mode: 0644]
ulp/nd/user/NdConnector.h [new file with mode: 0644]
ulp/nd/user/NdCq.cpp [new file with mode: 0644]
ulp/nd/user/NdCq.h [new file with mode: 0644]
ulp/nd/user/NdEndpoint.cpp [new file with mode: 0644]
ulp/nd/user/NdEndpoint.h [new file with mode: 0644]
ulp/nd/user/NdListen.cpp [new file with mode: 0644]
ulp/nd/user/NdListen.h [new file with mode: 0644]
ulp/nd/user/NdMr.cpp [new file with mode: 0644]
ulp/nd/user/NdMr.h [new file with mode: 0644]
ulp/nd/user/NdMw.cpp [new file with mode: 0644]
ulp/nd/user/NdMw.h [new file with mode: 0644]
ulp/nd/user/NdProv.cpp [new file with mode: 0644]
ulp/nd/user/NdProv.def [new file with mode: 0644]
ulp/nd/user/NdProv.h [new file with mode: 0644]
ulp/nd/user/NdProv.rc [new file with mode: 0644]
ulp/nd/user/SOURCES
ulp/nd/user/makefile
ulp/nd/user/nddebug.h [new file with mode: 0644]

diff --git a/ulp/nd/user/NdAdapter.cpp b/ulp/nd/user/NdAdapter.cpp
new file mode 100644 (file)
index 0000000..a174d94
--- /dev/null
@@ -0,0 +1,950 @@
+/*\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
diff --git a/ulp/nd/user/NdAdapter.h b/ulp/nd/user/NdAdapter.h
new file mode 100644 (file)
index 0000000..79b79e0
--- /dev/null
@@ -0,0 +1,210 @@
+/*\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
diff --git a/ulp/nd/user/NdConnector.cpp b/ulp/nd/user/NdConnector.cpp
new file mode 100644 (file)
index 0000000..3cb4aa2
--- /dev/null
@@ -0,0 +1,935 @@
+/*\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
diff --git a/ulp/nd/user/NdConnector.h b/ulp/nd/user/NdConnector.h
new file mode 100644 (file)
index 0000000..6f701a9
--- /dev/null
@@ -0,0 +1,172 @@
+/*\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
diff --git a/ulp/nd/user/NdCq.cpp b/ulp/nd/user/NdCq.cpp
new file mode 100644 (file)
index 0000000..94c71c3
--- /dev/null
@@ -0,0 +1,487 @@
+/*\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
diff --git a/ulp/nd/user/NdCq.h b/ulp/nd/user/NdCq.h
new file mode 100644 (file)
index 0000000..f4bdb79
--- /dev/null
@@ -0,0 +1,113 @@
+/*\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
diff --git a/ulp/nd/user/NdEndpoint.cpp b/ulp/nd/user/NdEndpoint.cpp
new file mode 100644 (file)
index 0000000..3325477
--- /dev/null
@@ -0,0 +1,944 @@
+/*\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
diff --git a/ulp/nd/user/NdEndpoint.h b/ulp/nd/user/NdEndpoint.h
new file mode 100644 (file)
index 0000000..f47a6c3
--- /dev/null
@@ -0,0 +1,202 @@
+/*\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
diff --git a/ulp/nd/user/NdListen.cpp b/ulp/nd/user/NdListen.cpp
new file mode 100644 (file)
index 0000000..82f0111
--- /dev/null
@@ -0,0 +1,385 @@
+/*\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
diff --git a/ulp/nd/user/NdListen.h b/ulp/nd/user/NdListen.h
new file mode 100644 (file)
index 0000000..3372fbf
--- /dev/null
@@ -0,0 +1,115 @@
+/*\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
diff --git a/ulp/nd/user/NdMr.cpp b/ulp/nd/user/NdMr.cpp
new file mode 100644 (file)
index 0000000..2216e63
--- /dev/null
@@ -0,0 +1,48 @@
+/*\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
diff --git a/ulp/nd/user/NdMr.h b/ulp/nd/user/NdMr.h
new file mode 100644 (file)
index 0000000..c0eb405
--- /dev/null
@@ -0,0 +1,57 @@
+/*\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
diff --git a/ulp/nd/user/NdMw.cpp b/ulp/nd/user/NdMw.cpp
new file mode 100644 (file)
index 0000000..cc10eb0
--- /dev/null
@@ -0,0 +1,110 @@
+/*\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
diff --git a/ulp/nd/user/NdMw.h b/ulp/nd/user/NdMw.h
new file mode 100644 (file)
index 0000000..c3589c5
--- /dev/null
@@ -0,0 +1,117 @@
+/*\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
diff --git a/ulp/nd/user/NdProv.cpp b/ulp/nd/user/NdProv.cpp
new file mode 100644 (file)
index 0000000..e242877
--- /dev/null
@@ -0,0 +1,561 @@
+/*\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
diff --git a/ulp/nd/user/NdProv.def b/ulp/nd/user/NdProv.def
new file mode 100644 (file)
index 0000000..f2fb99c
--- /dev/null
@@ -0,0 +1,6 @@
+LIBRARY                IbNdProv.dll\r
+\r
+EXPORTS\r
+       DllGetClassObject       private\r
+       WSPStartup                      \r
+       DllCanUnloadNow private
\ No newline at end of file
diff --git a/ulp/nd/user/NdProv.h b/ulp/nd/user/NdProv.h
new file mode 100644 (file)
index 0000000..21de4a7
--- /dev/null
@@ -0,0 +1,110 @@
+/*\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
diff --git a/ulp/nd/user/NdProv.rc b/ulp/nd/user/NdProv.rc
new file mode 100644 (file)
index 0000000..6f5908b
--- /dev/null
@@ -0,0 +1,49 @@
+/*\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
index 75d006a..67f80f7 100644 (file)
@@ -1,15 +1,62 @@
-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
index d366266..bffacaa 100644 (file)
@@ -3,4 +3,5 @@
 # file to this component.  This file merely indirects to the real make file\r
 # that is shared by all the driver components of the OpenIB Windows project.\r
 #\r
+\r
 !INCLUDE ..\..\..\inc\openib.def\r
diff --git a/ulp/nd/user/nddebug.h b/ulp/nd/user/nddebug.h
new file mode 100644 (file)
index 0000000..ab5607b
--- /dev/null
@@ -0,0 +1,160 @@
+/*\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