83f95c68b0ec901995ce6c94ead0b6082755082a
[mirror/winof/.git] / ulp / wsd / user / extensions.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 #include "ibspdll.h"\r
33 \r
34 \r
35 /* Function: IBSPRegisterMemory\r
36  *  Description:\r
37  *    Registers buffer memory\r
38  */\r
39 HANDLE WSPAPI\r
40 IBSPRegisterMemory(\r
41         IN                              SOCKET                                          s,\r
42         IN                              PVOID                                           lpBuffer,\r
43         IN                              DWORD                                           dwBufferLength,\r
44         IN                              DWORD                                           dwFlags,\r
45                 OUT                     LPINT                                           lpErrno )\r
46 {\r
47         struct ibsp_socket_info *socket_info = (struct ibsp_socket_info *)s;\r
48         ib_access_t access_ctrl;\r
49         struct memory_node *node;\r
50 \r
51         IBSP_ENTER( IBSP_DBG_MEM );\r
52 \r
53         fzprint(("%s():%d:0x%x:0x%x: socket=0x%p \n", __FUNCTION__,\r
54                          __LINE__, GetCurrentProcessId(), GetCurrentThreadId(), s));\r
55 \r
56         if( lpBuffer == NULL )\r
57         {\r
58                 IBSP_ERROR_EXIT( ("invalid buffer %p\n", lpBuffer) );\r
59                 *lpErrno = WSAEFAULT;\r
60                 return NULL;\r
61         }\r
62 \r
63         if( dwBufferLength > socket_info->socket_options.max_msg_size )\r
64         {\r
65                 IBSP_ERROR_EXIT( ("invalid buffer length %d\n", dwBufferLength) );\r
66                 *lpErrno = WSAEFAULT;\r
67                 return NULL;\r
68         }\r
69 \r
70         switch( dwFlags )\r
71         {\r
72         case MEM_READ:\r
73                 access_ctrl = 0;\r
74                 break;\r
75 \r
76         case MEM_WRITE:\r
77                 access_ctrl = IB_AC_LOCAL_WRITE;\r
78                 break;\r
79 \r
80         case MEM_READWRITE:\r
81                 access_ctrl = IB_AC_LOCAL_WRITE;\r
82                 break;\r
83 \r
84         default:\r
85                 IBSP_ERROR_EXIT( ("invalid flags %x\n", dwFlags) );\r
86                 *lpErrno = WSAEINVAL;\r
87                 return NULL;\r
88         }\r
89 \r
90         node = ib_register_memory( &socket_info->buf_mem_list, socket_info->hca_pd,\r
91                 lpBuffer, dwBufferLength, access_ctrl, lpErrno );\r
92 \r
93         fzprint(("%s():%d:0x%x:0x%x: registering MEM from %p to %p, len %d, handle %p\n",\r
94                          __FUNCTION__, __LINE__, GetCurrentProcessId(), GetCurrentThreadId(),\r
95                          lpBuffer, (unsigned char *)lpBuffer + dwBufferLength, dwBufferLength, node));\r
96 \r
97 \r
98         if( node == NULL )\r
99         {\r
100                 IBSP_ERROR_EXIT(\r
101                         ("ib_register_memory failed (pd=%p)\n", socket_info->hca_pd) );\r
102                 *lpErrno = WSAENOBUFS;\r
103         }\r
104         else\r
105         {\r
106                 IBSP_TRACE_EXIT( IBSP_DBG_MEM, ("returning node %p\n", node) );\r
107                 *lpErrno = 0;\r
108         }\r
109 \r
110         IBSP_EXIT( IBSP_DBG_MEM );\r
111 \r
112         return (HANDLE) node;\r
113 }\r
114 \r
115 /* Function: IBSPDeregisterMemory\r
116  *  Description:\r
117  *    This is our provider's DeregisterMemory function.\r
118  */\r
119 int WSPAPI\r
120 IBSPDeregisterMemory(\r
121         IN                              SOCKET                                          s,\r
122         IN                              HANDLE                                          handle,\r
123                 OUT                     LPINT                                           lpErrno )\r
124 {\r
125         struct memory_node *node = handle;\r
126         struct ibsp_socket_info *socket_info = (struct ibsp_socket_info *)s;\r
127         int ret;\r
128 \r
129         IBSP_ENTER( IBSP_DBG_MEM );\r
130 \r
131         fzprint(("%s():%d:0x%x:0x%x: handle=0x%p socket=0x%p \n", __FUNCTION__,\r
132                          __LINE__, GetCurrentProcessId(), GetCurrentThreadId(), handle, s));\r
133 \r
134         if( s == INVALID_SOCKET )\r
135         {\r
136                 IBSP_ERROR( ("invalid socket handle %x\n", s) );\r
137                 *lpErrno = WSAENOTSOCK;\r
138                 return SOCKET_ERROR;\r
139         }\r
140 \r
141         ret = ib_deregister_memory( &socket_info->buf_mem_list, node, lpErrno );\r
142 \r
143 \r
144         fzprint(("%s():%d:0x%x:0x%x: unregistering MEM %p, mr_num=%d, ret=%d\n",\r
145                          __FUNCTION__,\r
146                          __LINE__, GetCurrentProcessId(),\r
147                          GetCurrentThreadId(), node, g_ibsp.mr_num, ret));\r
148 \r
149         IBSP_EXIT( IBSP_DBG_MEM );\r
150 \r
151         return ret;\r
152 }\r
153 \r
154 /* Function: IBSPRegisterRdmaMemory\r
155  *  Description:\r
156  *    This is our provider's RegisterRdmaMemory function.\r
157 */\r
158 int WSPAPI\r
159 IBSPRegisterRdmaMemory(\r
160         IN                              SOCKET                                          s,\r
161         IN                              PVOID                                           lpBuffer,\r
162         IN                              DWORD                                           dwBufferLength,\r
163         IN                              DWORD                                           dwFlags,\r
164                 OUT                     LPVOID                                          lpRdmaBufferDescriptor,\r
165         IN      OUT                     LPDWORD                                         lpdwDescriptorLength,\r
166                 OUT                     LPINT                                           lpErrno )\r
167 {\r
168         struct memory_node *node;\r
169         struct rdma_memory_desc *desc;\r
170         struct ibsp_socket_info *socket_info = (struct ibsp_socket_info *)s;\r
171         ib_access_t access_ctrl;\r
172         struct ibsp_hca *hca;\r
173 \r
174         IBSP_ENTER( IBSP_DBG_MEM );\r
175 \r
176         fzprint(("%s():%d:0x%x:0x%x: socket=0x%p \n", __FUNCTION__,\r
177                          __LINE__, GetCurrentProcessId(), GetCurrentThreadId(), s));\r
178 \r
179         if( *lpdwDescriptorLength < sizeof(struct rdma_memory_desc) )\r
180         {\r
181                 /* This is the probe from the switch to learn the length of the descriptor. */\r
182                 IBSP_ERROR_EXIT(\r
183                         ("invalid descriptor length %d (usually not an error)\n",\r
184                         *lpdwDescriptorLength) );\r
185                 *lpdwDescriptorLength = sizeof(struct rdma_memory_desc);\r
186                 *lpErrno = WSAEFAULT;\r
187                 return SOCKET_ERROR;\r
188         }\r
189 \r
190         if( lpBuffer == NULL )\r
191         {\r
192                 IBSP_ERROR_EXIT( ("invalid buffer %p\n", lpBuffer) );\r
193                 *lpErrno = WSAEFAULT;\r
194                 return SOCKET_ERROR;\r
195         }\r
196 \r
197         if( dwBufferLength > socket_info->socket_options.max_msg_size )\r
198         {\r
199                 IBSP_ERROR_EXIT( ("invalid buffer length %d\n", dwBufferLength) );\r
200                 *lpErrno = WSAEFAULT;\r
201                 return SOCKET_ERROR;\r
202         }\r
203 \r
204         access_ctrl = IB_AC_LOCAL_WRITE;\r
205 \r
206         switch( dwFlags )\r
207         {\r
208         case MEM_READ:\r
209                 access_ctrl |= IB_AC_RDMA_READ;\r
210                 break;\r
211 \r
212         case MEM_WRITE:\r
213                 access_ctrl |= IB_AC_RDMA_WRITE;\r
214                 break;\r
215 \r
216         case MEM_READWRITE:\r
217                 access_ctrl |= (IB_AC_RDMA_READ | IB_AC_RDMA_WRITE);\r
218                 break;\r
219 \r
220         default:\r
221                 IBSP_ERROR_EXIT( ("invalid flags %x\n", dwFlags) );\r
222                 *lpErrno = WSAEINVAL;\r
223                 return SOCKET_ERROR;\r
224         }\r
225 \r
226         hca = socket_info->port->hca;\r
227 \r
228         node = ib_register_memory( &hca->rdma_mem_list, hca->pd,\r
229                 lpBuffer, dwBufferLength, access_ctrl, lpErrno );\r
230 \r
231         if( node == NULL )\r
232         {\r
233                 IBSP_ERROR_EXIT( ("ib_register_memory failed %d\n", *lpErrno) );\r
234                 *lpErrno = WSAENOBUFS;\r
235                 return SOCKET_ERROR;\r
236         }\r
237 \r
238         desc = lpRdmaBufferDescriptor;\r
239 \r
240         desc->iova = (uint64_t) (uintptr_t) lpBuffer;\r
241         desc->lkey = node->lkey;\r
242         desc->rkey = node->rkey;\r
243         desc->node = node;\r
244 \r
245         *lpErrno = 0;\r
246 \r
247         fzprint(("%s(): registering RDMA MEM from %p to %p, len %d, handle %p\n",\r
248                          __FUNCTION__, lpBuffer, (unsigned char *)lpBuffer + dwBufferLength,\r
249                          dwBufferLength, node));\r
250 \r
251         IBSP_EXIT( IBSP_DBG_MEM );\r
252 \r
253         return 0;\r
254 }\r
255 \r
256 /* Function: IBSPDeregisterRdmaMemory\r
257  *  Description:\r
258  *    This is our provider's DeregisterRdmaMemory function.\r
259  */\r
260 int WSPAPI\r
261 IBSPDeregisterRdmaMemory(\r
262         IN                              SOCKET                                          s,\r
263         IN                              LPVOID                                          lpRdmaBufferDescriptor,\r
264         IN                              DWORD                                           dwDescriptorLength,\r
265                 OUT                     LPINT                                           lpErrno )\r
266 {\r
267         struct rdma_memory_desc *desc;\r
268         struct ibsp_socket_info *socket_info = (struct ibsp_socket_info *)s;\r
269         int ret;\r
270         struct ibsp_hca *hca;\r
271 \r
272         IBSP_ENTER( IBSP_DBG_MEM );\r
273 \r
274         fzprint(("%s():%d:0x%x:0x%x: socket=0x%p \n", __FUNCTION__,\r
275                          __LINE__, GetCurrentProcessId(), GetCurrentThreadId(), s));\r
276 \r
277         if( s == INVALID_SOCKET )\r
278         {\r
279                 /* Seen in real life with overlap/client test.\r
280                  * The switch closes a socket then calls this. Why? */\r
281                 IBSP_ERROR_EXIT( ("invalid socket handle %x\n", s) );\r
282                 *lpErrno = WSAENOTSOCK;\r
283                 return SOCKET_ERROR;\r
284         }\r
285 \r
286 \r
287         CL_ASSERT( lpRdmaBufferDescriptor );\r
288 \r
289         if( dwDescriptorLength < sizeof(struct rdma_memory_desc) )\r
290         {\r
291                 IBSP_ERROR_EXIT(\r
292                         ("invalid descriptor length %d)\n", dwDescriptorLength) );\r
293                 *lpErrno = WSAEINVAL;\r
294                 return SOCKET_ERROR;\r
295         }\r
296 \r
297         desc = lpRdmaBufferDescriptor;\r
298 \r
299         hca = socket_info->port->hca;\r
300         ret = ib_deregister_memory( &hca->rdma_mem_list, desc->node, lpErrno );\r
301 \r
302         fzprint(("%s():%d:0x%x:0x%x: Unregistering RDMA MEM %p\n",\r
303                          __FUNCTION__, __LINE__, GetCurrentProcessId(),\r
304                          GetCurrentThreadId(), desc->node));\r
305 \r
306         IBSP_EXIT( IBSP_DBG_MEM );\r
307 \r
308         return ret;\r
309 }\r
310 \r
311 \r
312 /*\r
313  * Do a RDMA read or write operation since the code for both is very close. \r
314  */\r
315 static int\r
316 do_rdma_op(\r
317         IN                              SOCKET                                          s,\r
318         IN                              LPWSABUFEX                                      lpBuffers,\r
319         IN                              DWORD                                           dwBufferCount,\r
320         IN                              LPVOID                                          lpTargetBufferDescriptor,\r
321         IN                              DWORD                                           dwTargetDescriptorLength,\r
322         IN                              DWORD                                           dwTargetBufferOffset,\r
323         IN                              LPWSAOVERLAPPED                         lpOverlapped,\r
324         IN                              ib_wr_type_t                            wr_type,\r
325                 OUT                     LPINT                                           lpErrno )\r
326 {\r
327         struct ibsp_socket_info *socket_info = (struct ibsp_socket_info *)s;\r
328         ib_api_status_t                 status;\r
329         struct rdma_memory_desc *desc;  /* remote descriptor */\r
330         struct _wr                              *wr;\r
331         ib_send_wr_t                    send_wr;\r
332         ib_local_ds_t                   local_ds[QP_ATTRIB_SQ_SGE];\r
333         DWORD                                   ds_idx;\r
334 \r
335         IBSP_ENTER( IBSP_DBG_IO );\r
336 \r
337         CL_ASSERT( wr_type == WR_RDMA_WRITE || wr_type == WR_RDMA_READ );\r
338 \r
339         cl_spinlock_acquire( &socket_info->mutex );\r
340         switch( socket_info->socket_state )\r
341         {\r
342         case IBSP_CONNECTED:\r
343         case IBSP_DISCONNECTED:\r
344                 break;\r
345 \r
346         default:\r
347                 cl_spinlock_release( &socket_info->mutex );\r
348                 IBSP_ERROR_EXIT(\r
349                         ("Socket is not in connected socket_state state=%s\n",\r
350                         IBSP_SOCKET_STATE_STR( socket_info->socket_state )) );\r
351                 *lpErrno = WSAENOTCONN;\r
352                 return SOCKET_ERROR;\r
353         }\r
354         cl_spinlock_release( &socket_info->mutex );\r
355 \r
356         if( socket_info->qp_error )\r
357         {\r
358                 IBSP_ERROR_EXIT(\r
359                         ("QP is in error state %d\n", socket_info->qp_error) );\r
360                 *lpErrno = socket_info->qp_error;\r
361                 return SOCKET_ERROR;\r
362         }\r
363 \r
364         /* This function only works for that case. */\r
365         if( dwBufferCount > QP_ATTRIB_SQ_SGE )\r
366         {\r
367                 CL_ASSERT( dwBufferCount <= QP_ATTRIB_SQ_SGE );\r
368                 /* TODO - support splitting large requests into multiple RDMA operations. */\r
369                 IBSP_ERROR_EXIT(\r
370                         ("dwBufferCount is greater than %d\n", QP_ATTRIB_SQ_SGE) );\r
371                 *lpErrno = WSAEINVAL;\r
372                 return SOCKET_ERROR;\r
373         }\r
374 \r
375         if( dwTargetDescriptorLength != sizeof(struct rdma_memory_desc) )\r
376         {\r
377                 IBSP_ERROR_EXIT(\r
378                         ("invalid descriptor length %d)\n", dwTargetDescriptorLength) );\r
379                 *lpErrno = WSAEINVAL;\r
380                 return SOCKET_ERROR;\r
381         }\r
382 \r
383         desc = lpTargetBufferDescriptor;\r
384 \r
385         /* The send lock is only used to serialize posting. */\r
386         cl_spinlock_acquire( &socket_info->send_lock );\r
387         if( socket_info->send_cnt == QP_ATTRIB_SQ_DEPTH )\r
388         {\r
389                 /* TODO: queue requests. */\r
390                 cl_spinlock_release( &socket_info->send_lock );\r
391                 IBSP_ERROR_EXIT( ("not enough wr on the free list\n") );\r
392                 *lpErrno = WSAENETDOWN;\r
393                 return SOCKET_ERROR;\r
394         }\r
395 \r
396         wr = &socket_info->send_wr[socket_info->send_idx];\r
397 \r
398         wr->lpOverlapped = lpOverlapped;\r
399         wr->socket_info = socket_info;\r
400 \r
401         /* Format the send work request and post. */\r
402         send_wr.p_next = NULL;\r
403         send_wr.wr_id = (uint64_t)(void* __ptr64)wr;\r
404         send_wr.wr_type = wr_type;\r
405         send_wr.send_opt = 0;\r
406         send_wr.num_ds = dwBufferCount;\r
407         send_wr.ds_array = local_ds;\r
408 \r
409         send_wr.remote_ops.vaddr = desc->iova + dwTargetBufferOffset;\r
410         send_wr.remote_ops.rkey = desc->rkey;\r
411 \r
412         lpOverlapped->InternalHigh = 0;\r
413         for( ds_idx = 0; ds_idx < dwBufferCount; ds_idx++ )\r
414         {\r
415                 local_ds[ds_idx].vaddr = (uint64_t)(void* __ptr64)lpBuffers[ds_idx].buf;\r
416                 local_ds[ds_idx].length = lpBuffers[ds_idx].len;\r
417                 local_ds[ds_idx].lkey = ((struct memory_node*)lpBuffers[ds_idx].handle)->lkey;\r
418 \r
419                 lpOverlapped->InternalHigh += lpBuffers[ds_idx].len;\r
420         }\r
421 \r
422         if( wr_type == WR_RDMA_READ )\r
423         {\r
424                 /*\r
425                  * Next send must be fenced since it could indicate that this\r
426                  * RDMA READ is complete.\r
427                  */\r
428                 socket_info->send_opt = IB_SEND_OPT_FENCE;\r
429         }\r
430         else if( lpOverlapped->InternalHigh <= socket_info->max_inline )\r
431         {\r
432                 send_wr.send_opt |= IB_SEND_OPT_INLINE;\r
433         }\r
434 \r
435         /*\r
436          * We must set this now, because the operation could complete\r
437          * before ib_post_send returns.\r
438          */\r
439         lpOverlapped->Internal = WSS_OPERATION_IN_PROGRESS;\r
440 \r
441         cl_atomic_inc( &socket_info->send_cnt );\r
442 \r
443 #ifdef _DEBUG_\r
444         if( lpOverlapped->hEvent == 0 )\r
445         {\r
446                 cl_atomic_inc( &g_ibsp.overlap_h0_count );\r
447         }\r
448         else\r
449         {\r
450                 cl_atomic_inc( &g_ibsp.overlap_h1_count );\r
451                 cl_atomic_inc( &g_ibsp.overlap_h1_comp_count );\r
452         }\r
453 \r
454         fzprint(("%s():%d:0x%x:0x%x: ov=0x%p h0_cnt=%d h1_cnt=%d\n",\r
455                          __FUNCTION__, __LINE__, GetCurrentProcessId(),\r
456                          GetCurrentThreadId(), lpOverlapped,\r
457                          g_ibsp.overlap_h0_count, g_ibsp.overlap_h1_count));\r
458 \r
459 #endif\r
460 \r
461         status = ib_post_send( socket_info->qp, &send_wr, NULL );\r
462 \r
463         if( status == IB_SUCCESS )\r
464         {\r
465                 /* Update the index and wrap as needed */\r
466 #if QP_ATTRIB_SQ_DEPTH == 256 || QP_ATTRIB_SQ_DEPTH == 128 || \\r
467         QP_ATTRIB_SQ_DEPTH == 64 || QP_ATTRIB_SQ_DEPTH == 32 || \\r
468         QP_ATTRIB_SQ_DEPTH == 16 || QP_ATTRIB_SQ_DEPTH == 8\r
469                 socket_info->send_idx++;\r
470                 socket_info->send_idx &= (QP_ATTRIB_SQ_DEPTH - 1);\r
471 #else\r
472                 if( ++socket_info->send_idx == QP_ATTRIB_SQ_DEPTH )\r
473                         socket_info->send_idx = 0;\r
474 #endif\r
475 \r
476                 *lpErrno = WSA_IO_PENDING;\r
477 \r
478                 IBSP_TRACE1( IBSP_DBG_IO,\r
479                         ("Posted RDMA: socket=%p, ov=%p, type=%d, local=%p dest=%I64x, len=%d\n",\r
480                         s, lpOverlapped, wr_type, lpBuffers[0].buf,\r
481                         send_wr.remote_ops.vaddr, lpBuffers[0].len) );\r
482 \r
483                 fzprint(("posted RDMA %p, len=%d, op=%d, mr handle=%p\n",\r
484                                 lpOverlapped, lpBuffers[0].len, wr_type, node));\r
485         }\r
486         else\r
487         {\r
488                 IBSP_ERROR(\r
489                         ("ib_post_send returned %s\n", ib_get_err_str( status )) );\r
490 \r
491 #ifdef _DEBUG_\r
492 \r
493                 if( lpOverlapped->hEvent == 0 )\r
494                 {\r
495                         cl_atomic_dec( &g_ibsp.overlap_h0_count );\r
496                 }\r
497                 else\r
498                 {\r
499                         cl_atomic_dec( &g_ibsp.overlap_h1_count );\r
500                         cl_atomic_dec( &g_ibsp.overlap_h1_comp_count );\r
501                 }\r
502 \r
503                 memset( wr, 0x44, sizeof(struct _wr) );\r
504 #endif\r
505                 cl_atomic_dec( &socket_info->send_cnt );\r
506 \r
507                 *lpErrno = ibal_to_wsa_error( status );\r
508         }\r
509 \r
510         cl_spinlock_release( &socket_info->send_lock );\r
511 \r
512         /* We never complete the operation here. */\r
513         IBSP_EXIT( IBSP_DBG_IO );\r
514         return SOCKET_ERROR;\r
515 }\r
516 \r
517 \r
518 /* Function: IBSPRdmaWrite\r
519  Description:\r
520     This is our provider's RdmaWrite function. When an app calls WSAIoctl\r
521     to request the function pointer to RdmaWrite, we return pointer to this \r
522         function and this function is called by application directly using the function pointer.\r
523 */\r
524 int WSPAPI\r
525 IBSPRdmaWrite(\r
526         IN                              SOCKET                                          s,\r
527         IN                              LPWSABUFEX                                      lpBuffers,\r
528         IN                              DWORD                                           dwBufferCount,\r
529         IN                              LPVOID                                          lpTargetBufferDescriptor,\r
530         IN                              DWORD                                           dwTargetDescriptorLength,\r
531         IN                              DWORD                                           dwTargetBufferOffset,\r
532                 OUT                     LPDWORD                                         lpdwNumberOfBytesWritten,\r
533         IN                              DWORD                                           dwFlags,\r
534         IN                              LPWSAOVERLAPPED                         lpOverlapped,\r
535         IN                              LPWSAOVERLAPPED_COMPLETION_ROUTINE      lpCompletionRoutine,\r
536         IN                              LPWSATHREADID                           lpThreadId,\r
537                 OUT                     LPINT                                           lpErrno )\r
538 {\r
539         int ret;\r
540 \r
541         IBSP_ENTER( IBSP_DBG_IO );\r
542 \r
543         UNUSED_PARAM( lpThreadId );\r
544         UNUSED_PARAM( lpCompletionRoutine );\r
545         UNUSED_PARAM( lpdwNumberOfBytesWritten );\r
546 \r
547         if( s == INVALID_SOCKET )\r
548         {\r
549                 IBSP_ERROR_EXIT( ("invalid socket handle %x\n", s) );\r
550                 *lpErrno = WSAENOTSOCK;\r
551                 return SOCKET_ERROR;\r
552         }\r
553 \r
554         fzprint(("%s():%d:0x%x:0x%x: socket=0x%p overlapped=0x%p\n", __FUNCTION__,\r
555                          __LINE__, GetCurrentProcessId(), GetCurrentThreadId(), s, lpOverlapped));\r
556 \r
557         /* Store the flags for reporting back in IBSPGetOverlappedResult */\r
558         lpOverlapped->Offset = dwFlags;\r
559 \r
560         ret = do_rdma_op( s, lpBuffers, dwBufferCount, lpTargetBufferDescriptor,\r
561                 dwTargetDescriptorLength, dwTargetBufferOffset,\r
562                 lpOverlapped, WR_RDMA_WRITE, lpErrno );\r
563 \r
564         IBSP_EXIT( IBSP_DBG_IO );\r
565 \r
566         return ret;\r
567 }\r
568 \r
569 \r
570 /* Function: IBSPRdmaRead\r
571  Description:\r
572     This is our provider's RdmaRead function. When an app calls WSAIoctl\r
573     to request the function pointer to RdmaRead, we return pointer to this \r
574         function and this function is called by application directly using the function pointer.\r
575 */\r
576 int WSPAPI\r
577 IBSPRdmaRead(\r
578         IN                              SOCKET                                          s,\r
579         IN                              LPWSABUFEX                                      lpBuffers,\r
580         IN                              DWORD                                           dwBufferCount,\r
581         IN                              LPVOID                                          lpTargetBufferDescriptor,\r
582         IN                              DWORD                                           dwTargetDescriptorLength,\r
583         IN                              DWORD                                           dwTargetBufferOffset,\r
584                 OUT                     LPDWORD                                         lpdwNumberOfBytesRead,\r
585         IN                              DWORD                                           dwFlags,\r
586         IN                              LPWSAOVERLAPPED                         lpOverlapped,\r
587         IN                              LPWSAOVERLAPPED_COMPLETION_ROUTINE      lpCompletionRoutine,\r
588         IN                              LPWSATHREADID                           lpThreadId,\r
589                 OUT                     LPINT                                           lpErrno )\r
590 {\r
591         int ret;\r
592 \r
593         IBSP_ENTER( IBSP_DBG_IO );\r
594 \r
595         UNUSED_PARAM( lpThreadId );\r
596         UNUSED_PARAM( lpCompletionRoutine );\r
597         UNUSED_PARAM( lpdwNumberOfBytesRead );\r
598 \r
599         fzprint(("%s():%d:0x%x:0x%x: socket=0x%p overlapped=0x%p \n", __FUNCTION__,\r
600                          __LINE__, GetCurrentProcessId(), GetCurrentThreadId(), s, lpOverlapped));\r
601 \r
602         /* Store the flags for reporting back in IBSPGetOverlappedResult */\r
603         lpOverlapped->Offset = dwFlags;\r
604 \r
605         ret = do_rdma_op( s, lpBuffers, dwBufferCount, lpTargetBufferDescriptor,\r
606                 dwTargetDescriptorLength, dwTargetBufferOffset,\r
607                 lpOverlapped, WR_RDMA_READ, lpErrno );\r
608 \r
609         IBSP_EXIT( IBSP_DBG_IO );\r
610 \r
611         return ret;\r
612 }\r
613 \r
614 \r
615 /* Function: IBSPMemoryRegistrationCacheCallback\r
616  *  Description:\r
617  *   This is our provider's MemoryRegistrationCacheCallback\r
618  *   function. When an app calls WSAIoctl to request the function\r
619  *   pointer to MemoryRegistrationCacheCallback, we return pointer to\r
620  *   this function and this function is called by application directly\r
621  *   using the function pointer.\r
622  */\r
623 int WSPAPI\r
624 IBSPMemoryRegistrationCacheCallback(\r
625         IN                              LPVOID                                          lpvAddress,\r
626         IN                              SIZE_T                                          Size,\r
627                 OUT                     LPINT                                           lpErrno )\r
628 {\r
629         IBSP_ENTER( IBSP_DBG_MEM );\r
630 \r
631         UNUSED_PARAM( lpvAddress );\r
632         UNUSED_PARAM( Size );\r
633         UNUSED_PARAM( lpErrno );\r
634 \r
635         IBSP_EXIT( IBSP_DBG_MEM );\r
636         return 0;\r
637 }\r