[IBAL] Change CEP DREP API
[mirror/winof/.git] / core / al / user / ual_cm_cep.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\r
8  *     Redistribution and use in source and binary forms, with or\r
9  *     without modification, are permitted provided that the following\r
10  *     conditions are met:\r
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\r
16  *      - Redistributions in binary form must reproduce the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer in the documentation and/or other materials\r
19  *        provided with the distribution.\r
20  *\r
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
28  * SOFTWARE.\r
29  *\r
30  * $Id$\r
31  */\r
32 \r
33 \r
34 #include <iba/ib_al.h>\r
35 #include <complib/cl_ptr_vector.h>\r
36 #include <complib/cl_qlist.h>\r
37 #include "al_common.h"\r
38 #include "al_cm_cep.h"\r
39 #include "al_cm_conn.h"\r
40 #include "al_cm_sidr.h"\r
41 #include "al_debug.h"\r
42 \r
43 #if defined(EVENT_TRACING)\r
44 #ifdef offsetof\r
45 #undef offsetof\r
46 #endif\r
47 #include "ual_cm_cep.tmh"\r
48 #endif\r
49 \r
50 #include "ib_common.h"\r
51 #include "al_mgr.h"\r
52 //#include "al_ca.h"\r
53 #include "al.h"\r
54 //#include "al_mad.h"\r
55 #include "al_qp.h"\r
56 \r
57 \r
58 #define UAL_CEP_MIN                                     (512)\r
59 #define UAL_CEP_GROW                            (256)\r
60 \r
61 \r
62 /* Global connection manager object. */\r
63 typedef struct _ual_cep_mgr\r
64 {\r
65         al_obj_t                                obj;\r
66 \r
67         cl_ptr_vector_t                 cep_vector;\r
68 \r
69         /* File handle on which to issue query IOCTLs. */\r
70         HANDLE                                  h_file;\r
71 \r
72 }       ual_cep_mgr_t;\r
73 \r
74 \r
75 typedef struct _al_ucep\r
76 {\r
77         al_pfn_cep_cb_t                         pfn_cb;\r
78         ib_al_handle_t                          h_al;\r
79         cl_list_item_t                          al_item;\r
80 \r
81         ib_pfn_destroy_cb_t                     pfn_destroy_cb;\r
82         void*                                           destroy_context;\r
83         net32_t                                         cid;\r
84 \r
85         OVERLAPPED                                      ov;\r
86         atomic32_t                                      ref_cnt;\r
87 \r
88 }       ucep_t;\r
89 \r
90 \r
91 /* Global instance of the CM agent. */\r
92 ual_cep_mgr_t           *gp_cep_mgr = NULL;\r
93 \r
94 \r
95 /*\r
96  * Frees the global CEP manager.  Invoked during al_obj destruction.\r
97  */\r
98 static void\r
99 __free_cep_mgr(\r
100         IN                              al_obj_t*                                       p_obj )\r
101 {\r
102         AL_ENTER( AL_DBG_CM );\r
103 \r
104         CL_ASSERT( &gp_cep_mgr->obj == p_obj );\r
105 \r
106         if( gp_cep_mgr->h_file != INVALID_HANDLE_VALUE )\r
107                 CloseHandle( gp_cep_mgr->h_file );\r
108 \r
109         cl_ptr_vector_destroy( &gp_cep_mgr->cep_vector );\r
110 \r
111         destroy_al_obj( p_obj );\r
112 \r
113         cl_free( gp_cep_mgr );\r
114         gp_cep_mgr = NULL;\r
115 \r
116         AL_EXIT( AL_DBG_CM );\r
117 }\r
118 \r
119 \r
120 /*\r
121  * Allocates and initialized the global user-mode CM agent.\r
122  */\r
123 ib_api_status_t\r
124 create_cep_mgr(\r
125         IN                              al_obj_t* const                         p_parent_obj )\r
126 {\r
127         ib_api_status_t         status;\r
128         cl_status_t                     cl_status;\r
129 \r
130         AL_ENTER( AL_DBG_CM );\r
131 \r
132         CL_ASSERT( gp_cep_mgr == NULL );\r
133 \r
134         /* Allocate the global CM agent. */\r
135         gp_cep_mgr = (ual_cep_mgr_t*)cl_zalloc( sizeof(ual_cep_mgr_t) );\r
136         if( !gp_cep_mgr )\r
137         {\r
138                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
139                         ("Failed allocation of global CEP manager.\n") );\r
140                 return IB_INSUFFICIENT_MEMORY;\r
141         }\r
142 \r
143         construct_al_obj( &gp_cep_mgr->obj, AL_OBJ_TYPE_CM );\r
144         cl_ptr_vector_construct( &gp_cep_mgr->cep_vector );\r
145         gp_cep_mgr->h_file = INVALID_HANDLE_VALUE;\r
146 \r
147         status = init_al_obj( &gp_cep_mgr->obj, NULL, FALSE,\r
148                 NULL, NULL, __free_cep_mgr );\r
149         if( status != IB_SUCCESS )\r
150         {\r
151                 __free_cep_mgr( &gp_cep_mgr->obj );\r
152                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
153                         ("init_al_obj failed with status %s.\n", ib_get_err_str(status)) );\r
154                 return status;\r
155         }\r
156         /* Attach to the parent object. */\r
157         status = attach_al_obj( p_parent_obj, &gp_cep_mgr->obj );\r
158         if( status != IB_SUCCESS )\r
159         {\r
160                 gp_cep_mgr->obj.pfn_destroy( &gp_cep_mgr->obj, NULL );\r
161                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
162                         ("attach_al_obj returned %s.\n", ib_get_err_str(status)) );\r
163                 return status;\r
164         }\r
165 \r
166         cl_status = cl_ptr_vector_init(\r
167                 &gp_cep_mgr->cep_vector, UAL_CEP_MIN, UAL_CEP_GROW );\r
168         if( cl_status != CL_SUCCESS )\r
169         {\r
170                 gp_cep_mgr->obj.pfn_destroy( &gp_cep_mgr->obj, NULL );\r
171                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
172                         ("cl_vector_init failed with status %s.\n",\r
173                         CL_STATUS_MSG(cl_status)) );\r
174                 return ib_convert_cl_status( cl_status );\r
175         }\r
176 \r
177         /* Create a file object on which to issue all CM requests. */\r
178         gp_cep_mgr->h_file = ual_create_async_file( UAL_BIND_CM );\r
179         if( gp_cep_mgr->h_file == INVALID_HANDLE_VALUE )\r
180         {\r
181                 gp_cep_mgr->obj.pfn_destroy( &gp_cep_mgr->obj, NULL );\r
182                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
183                         ("ual_create_async_file for UAL_BIND_CM returned %d.\n",\r
184                         GetLastError()) );\r
185                 return IB_ERROR;\r
186         }\r
187 \r
188         /* Release the reference from init_al_obj */\r
189         deref_al_obj( &gp_cep_mgr->obj );\r
190 \r
191         AL_EXIT( AL_DBG_CM );\r
192         return IB_SUCCESS;\r
193 }\r
194 \r
195 \r
196 void\r
197 al_cep_cleanup_al(\r
198         IN              const   ib_al_handle_t                          h_al )\r
199 {\r
200         cl_list_item_t          *p_item;\r
201         net32_t                         cid;\r
202 \r
203         AL_ENTER( AL_DBG_CM );\r
204 \r
205         /* Destroy all CEPs associated with the input instance of AL. */\r
206         cl_spinlock_acquire( &h_al->obj.lock );\r
207         for( p_item = cl_qlist_head( &h_al->cep_list );\r
208                 p_item != cl_qlist_end( &h_al->cep_list );\r
209                 p_item = cl_qlist_head( &h_al->cep_list ) )\r
210         {\r
211                 /*\r
212                  * Note that we don't walk the list - we can't hold the AL\r
213                  * lock when cleaning up its CEPs because the cleanup path\r
214                  * takes the CEP's lock.  We always want to take the CEP\r
215                  * before the AL lock to prevent any possibilities of deadlock.\r
216                  *\r
217                  * So we just get the CID, and then release the AL lock and try to\r
218                  * destroy.  This should unbind the CEP from the AL instance and\r
219                  * remove it from the list, allowing the next CEP to be cleaned up\r
220                  * in the next pass through.\r
221                  */\r
222                 cid = PARENT_STRUCT( p_item, ucep_t, al_item )->cid;\r
223                 cl_spinlock_release( &h_al->obj.lock );\r
224                 al_destroy_cep( h_al, &cid, FALSE );\r
225                 cl_spinlock_acquire( &h_al->obj.lock );\r
226         }\r
227         cl_spinlock_release( &h_al->obj.lock );\r
228 \r
229         AL_EXIT( AL_DBG_CM );\r
230 }\r
231 \r
232 \r
233 static void\r
234 __destroy_ucep(\r
235         IN                              ucep_t* const                           p_cep )\r
236 {\r
237         if( p_cep->pfn_destroy_cb )\r
238                 p_cep->pfn_destroy_cb( p_cep->destroy_context );\r
239         cl_free( p_cep );\r
240 }\r
241 \r
242 \r
243 ib_api_status_t\r
244 __create_ucep(\r
245         IN                              ib_al_handle_t                          h_al,\r
246         IN                              net32_t                                         cid,\r
247         IN                              al_pfn_cep_cb_t                         pfn_cb,\r
248         IN                              void*                                           context,\r
249         IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb,\r
250         IN      OUT                     net32_t* const                          p_cid )\r
251 {\r
252         ucep_t                                  *p_cep;\r
253         DWORD                                   bytes_ret;\r
254         ual_create_cep_ioctl_t  ioctl;\r
255 \r
256         AL_ENTER( AL_DBG_CM );\r
257 \r
258         p_cep = cl_zalloc( sizeof(ucep_t) );\r
259         if( !p_cep )\r
260         {\r
261                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("Failed to allocate ucep_t\n") );\r
262                 return IB_INSUFFICIENT_MEMORY;\r
263         }\r
264 \r
265         /* Initialize to two - one for the CEP, and one for the IOCTL. */\r
266         p_cep->ref_cnt = 2;\r
267 \r
268         /* Store user parameters. */\r
269         p_cep->pfn_cb = pfn_cb;\r
270         p_cep->destroy_context = context; //TODO: context will no be longer __ptr64\r
271 \r
272         /* Create a kernel CEP only if we don't already have a CID. */\r
273         if( cid == AL_INVALID_CID )\r
274         {\r
275                 if( !DeviceIoControl( g_al_device, UAL_CREATE_CEP, &context, \r
276                         sizeof(context), &ioctl, sizeof(ioctl), &bytes_ret, NULL ) ||\r
277                         bytes_ret != sizeof(ioctl) )\r
278                 {\r
279                         __destroy_ucep( p_cep );\r
280                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
281                                 ("UAL_CREATE_CEP IOCTL failed with %d.\n", GetLastError()) );\r
282                         return IB_ERROR;\r
283                 }\r
284 \r
285                 if( ioctl.status != IB_SUCCESS )\r
286                 {\r
287                         __destroy_ucep( p_cep );\r
288                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("UAL_CREATE_CEP IOCTL returned %s\n",\r
289                                 ib_get_err_str( ioctl.status )) );\r
290                         return ioctl.status;\r
291                 }\r
292 \r
293                 p_cep->cid = ioctl.cid;\r
294         }\r
295         else\r
296         {\r
297                 p_cep->cid = cid;\r
298         }\r
299 \r
300         /* Track the CEP before we issue any further IOCTLs on it. */\r
301         cl_spinlock_acquire( &gp_cep_mgr->obj.lock );\r
302         cl_ptr_vector_set_min_size( &gp_cep_mgr->cep_vector, p_cep->cid + 1 );\r
303         CL_ASSERT( !cl_ptr_vector_get( &gp_cep_mgr->cep_vector, p_cep->cid ) );\r
304         cl_ptr_vector_set( &gp_cep_mgr->cep_vector, p_cep->cid, p_cep );\r
305         cl_spinlock_release( &gp_cep_mgr->obj.lock );\r
306 \r
307         /* Now issue a poll request.  This request is async. */\r
308         if( DeviceIoControl( gp_cep_mgr->h_file, UAL_CEP_GET_EVENT,\r
309                 &p_cep->cid, sizeof(p_cep->cid),\r
310                 NULL, 0, NULL, &p_cep->ov ) ||\r
311                 GetLastError() != ERROR_IO_PENDING )\r
312         {\r
313                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Failed to issue CEP poll IOCTL.\n") );\r
314                 cl_spinlock_acquire( &gp_cep_mgr->obj.lock );\r
315                 cl_ptr_vector_set( &gp_cep_mgr->cep_vector, p_cep->cid, NULL );\r
316                 cl_spinlock_release( &gp_cep_mgr->obj.lock );\r
317 \r
318                 DeviceIoControl( g_al_device, UAL_DESTROY_CEP, &p_cep->cid,\r
319                         sizeof(p_cep->cid), NULL, 0, &bytes_ret, NULL );\r
320 \r
321                 __destroy_ucep( p_cep );\r
322                 AL_EXIT( AL_DBG_CM );\r
323                 return IB_ERROR;\r
324         }\r
325 \r
326         p_cep->h_al = h_al;\r
327 \r
328         /* Track the CEP in its owning AL instance. */\r
329         cl_spinlock_acquire( &h_al->obj.lock );\r
330         if( p_cid )\r
331         {\r
332                 if( *p_cid != AL_INVALID_CID )\r
333                 {\r
334                         cl_spinlock_release( &h_al->obj.lock );\r
335                         al_destroy_cep( h_al, &cid, TRUE );\r
336                         return IB_INVALID_STATE;\r
337                 }\r
338                 p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
339                 *p_cid = p_cep->cid;\r
340         }\r
341 \r
342         cl_qlist_insert_tail( &h_al->cep_list, &p_cep->al_item );\r
343 \r
344         cl_spinlock_release( &h_al->obj.lock );\r
345 \r
346         AL_EXIT( AL_DBG_CM );\r
347         return IB_SUCCESS;\r
348 }\r
349 \r
350 \r
351 ib_api_status_t\r
352 al_create_cep(\r
353         IN                              ib_al_handle_t                          h_al,\r
354         IN                              al_pfn_cep_cb_t                         pfn_cb,\r
355         IN                              void*                                           context,\r
356         IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb,\r
357         IN      OUT                     net32_t* const                          p_cid )\r
358 {\r
359         ib_api_status_t         status;\r
360 \r
361         AL_ENTER( AL_DBG_CM );\r
362 \r
363         status = __create_ucep(\r
364                 h_al, AL_INVALID_CID, pfn_cb, context, pfn_destroy_cb, p_cid );\r
365 \r
366         AL_EXIT( AL_DBG_CM );\r
367         return status;\r
368 }\r
369 \r
370 \r
371 /*\r
372  * Note that destroy_cep is synchronous.  It does however handle the case\r
373  * where a user calls it from a callback context.\r
374  */\r
375 void\r
376 al_destroy_cep(\r
377         IN                              ib_al_handle_t                          h_al,\r
378         IN      OUT                     net32_t* const                          p_cid,\r
379         IN                              boolean_t                                       reusable )\r
380 {\r
381         ucep_t          *p_cep;\r
382         DWORD           bytes_ret;\r
383 \r
384         AL_ENTER( AL_DBG_CM );\r
385 \r
386         CL_ASSERT( h_al );\r
387 \r
388         cl_spinlock_acquire( &gp_cep_mgr->obj.lock );\r
389         if( *p_cid < cl_ptr_vector_get_size( &gp_cep_mgr->cep_vector ) )\r
390         {\r
391                 p_cep = cl_ptr_vector_get( &gp_cep_mgr->cep_vector, *p_cid );\r
392                 if( p_cep && p_cep->h_al == h_al )\r
393                         cl_ptr_vector_set( &gp_cep_mgr->cep_vector, *p_cid, NULL );\r
394                 else\r
395                         goto invalid;\r
396         }\r
397         else\r
398         {\r
399 invalid:\r
400                 if( !reusable )\r
401                         *p_cid = AL_RESERVED_CID;\r
402 \r
403                 cl_spinlock_release( &gp_cep_mgr->obj.lock );\r
404                 AL_EXIT( AL_DBG_CM );\r
405                 return;\r
406         }\r
407 \r
408         /*\r
409          * Destroy the kernel CEP right away.  We must synchronize with issuing\r
410          * the next GET_EVENT IOCTL.\r
411          */\r
412         DeviceIoControl( g_al_device, UAL_DESTROY_CEP, &p_cep->cid,\r
413                 sizeof(p_cep->cid), NULL, 0, &bytes_ret, NULL );\r
414         if( reusable )\r
415                 *p_cid = AL_INVALID_CID;\r
416         else\r
417                 *p_cid = AL_RESERVED_CID;\r
418 \r
419         cl_spinlock_release( &gp_cep_mgr->obj.lock );\r
420 \r
421         /*\r
422          * Remove from the AL instance.  Note that once removed, all\r
423          * callbacks for an item will stop.\r
424          */\r
425         cl_spinlock_acquire( &h_al->obj.lock );\r
426         cl_qlist_remove_item( &h_al->cep_list, &p_cep->al_item );\r
427 \r
428         cl_spinlock_release( &h_al->obj.lock );\r
429 \r
430         if( !cl_atomic_dec( &p_cep->ref_cnt ) )\r
431         {\r
432                 /* We have no remaining refrences. */\r
433                 __destroy_ucep( p_cep );\r
434         }\r
435 \r
436         AL_EXIT( AL_DBG_CM );\r
437 }\r
438 \r
439 \r
440 ib_api_status_t\r
441 al_cep_listen(\r
442         IN                              ib_al_handle_t                          h_al,\r
443         IN                              net32_t                                         cid,\r
444         IN                              ib_cep_listen_t* const          p_listen_info )\r
445 {\r
446         ual_cep_listen_ioctl_t  ioctl;\r
447         ib_api_status_t                 status;\r
448         DWORD                                   bytes_ret;\r
449 \r
450         AL_ENTER( AL_DBG_CM );\r
451     cl_memclr(&ioctl, sizeof(ioctl));\r
452         if( !h_al )\r
453         {\r
454                 AL_EXIT( AL_DBG_CM );\r
455                 return IB_INVALID_HANDLE;\r
456         }\r
457 \r
458         if( !p_listen_info )\r
459         {\r
460                 AL_EXIT( AL_DBG_CM );\r
461                 return IB_INVALID_PARAMETER;\r
462         }\r
463 \r
464         ioctl.cid = cid;\r
465         ioctl.cep_listen = *p_listen_info;\r
466         if( p_listen_info->p_cmp_buf )\r
467         {\r
468                 if( p_listen_info->cmp_len > IB_REQ_PDATA_SIZE )\r
469                 {\r
470                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
471                                 ("Listen compare data larger than REQ private data.\n") );\r
472                         return IB_INVALID_SETTING;\r
473                 }\r
474 \r
475                 cl_memcpy( ioctl.compare, p_listen_info->p_cmp_buf,\r
476                         p_listen_info->cmp_len );\r
477         }\r
478 \r
479         if( !DeviceIoControl( g_al_device, UAL_CEP_LISTEN, &ioctl,\r
480                 sizeof(ioctl), &status, sizeof(status), &bytes_ret, NULL ) ||\r
481                 bytes_ret != sizeof(status) )\r
482         {\r
483                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
484                         ("ual_cep_listen IOCTL failed with %d.\n", GetLastError()) );\r
485                 return IB_ERROR;\r
486         }\r
487 \r
488         AL_EXIT( AL_DBG_CM );\r
489         return status;\r
490 }\r
491 \r
492 \r
493 ib_api_status_t\r
494 al_cep_pre_req(\r
495         IN                              ib_al_handle_t                          h_al,\r
496         IN                              net32_t                                         cid,\r
497         IN              const   ib_cm_req_t* const                      p_cm_req,\r
498                 OUT                     ib_qp_mod_t* const                      p_init )\r
499 {\r
500         ual_cep_req_ioctl_t             ioctl;\r
501         DWORD                                   bytes_ret;\r
502 \r
503         AL_ENTER( AL_DBG_CM );\r
504 \r
505         if( !h_al )\r
506         {\r
507                 AL_EXIT( AL_DBG_CM );\r
508                 return IB_INVALID_HANDLE;\r
509         }\r
510 \r
511         if( !p_cm_req )\r
512         {\r
513                 AL_EXIT( AL_DBG_CM );\r
514                 return IB_INVALID_PARAMETER;\r
515         }\r
516 \r
517         if( !p_init )\r
518         {\r
519                 AL_EXIT( AL_DBG_ERROR );\r
520                 return IB_INVALID_PARAMETER;\r
521         }\r
522     cl_memclr(&ioctl, sizeof(ioctl));\r
523         ioctl.in.cid = cid;\r
524         ioctl.in.cm_req = *p_cm_req;\r
525         ioctl.in.cm_req.h_qp = (ib_qp_handle_t VOID_PTR64) HDL_TO_PTR(p_cm_req->h_qp->obj.hdl);\r
526         ioctl.in.paths[0] = *(p_cm_req->p_primary_path);\r
527         if( p_cm_req->p_alt_path )\r
528                 ioctl.in.paths[1] = *(p_cm_req->p_alt_path);\r
529         /* Copy private data, if any. */\r
530         if( p_cm_req->p_req_pdata )\r
531         {\r
532                 if( p_cm_req->req_length > IB_REQ_PDATA_SIZE )\r
533                 {\r
534                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
535                                 ("private data larger than REQ private data.\n") );\r
536                         return IB_INVALID_SETTING;\r
537                 }\r
538 \r
539                 cl_memcpy( ioctl.in.pdata, p_cm_req->p_req_pdata,\r
540                         p_cm_req->req_length );\r
541         }\r
542 \r
543         /* Copy compare data, if any. */\r
544         if( p_cm_req->p_compare_buffer )\r
545         {\r
546                 if( p_cm_req->compare_length > IB_REQ_PDATA_SIZE )\r
547                 {\r
548                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
549                                 ("REQ compare data larger than REQ private data.\n") );\r
550                         return IB_INVALID_SETTING;\r
551                 }\r
552 \r
553                 cl_memcpy( ioctl.in.compare, p_cm_req->p_compare_buffer,\r
554                         p_cm_req->compare_length );\r
555         }\r
556 \r
557         if( !DeviceIoControl( g_al_device, UAL_CEP_PRE_REQ, &ioctl,\r
558                 sizeof(ioctl.in), &ioctl, sizeof(ioctl.out), &bytes_ret, NULL ) ||\r
559                 bytes_ret != sizeof(ioctl.out) )\r
560         {\r
561                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
562                         ("UAL_CEP_PRE_REQ IOCTL failed with %d.\n", GetLastError()) );\r
563                 return IB_ERROR;\r
564         }\r
565 \r
566         if( ioctl.out.status == IB_SUCCESS )\r
567                 *p_init = ioctl.out.init;\r
568 \r
569         AL_EXIT( AL_DBG_CM );\r
570         return ioctl.out.status;\r
571 }\r
572 \r
573 \r
574 ib_api_status_t\r
575 al_cep_send_req(\r
576         IN                              ib_al_handle_t                          h_al,\r
577         IN                              net32_t                                         cid )\r
578 {\r
579         ib_api_status_t         status;\r
580         DWORD                           bytes_ret;\r
581 \r
582         AL_ENTER( AL_DBG_CM );\r
583 \r
584         if( !h_al )\r
585         {\r
586                 AL_EXIT( AL_DBG_CM );\r
587                 return IB_INVALID_HANDLE;\r
588         }\r
589 \r
590         if( !DeviceIoControl( g_al_device, UAL_CEP_SEND_REQ, &cid,\r
591                 sizeof(cid), &status, sizeof(status), &bytes_ret, NULL ) ||\r
592                 bytes_ret != sizeof(status) )\r
593         {\r
594                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
595                         ("UAL_CEP_SEND_REQ IOCTL failed with %d.\n", GetLastError()) );\r
596                 return IB_ERROR;\r
597         }\r
598 \r
599         AL_EXIT( AL_DBG_CM );\r
600         return status;\r
601 }\r
602 \r
603 \r
604 ib_api_status_t\r
605 al_cep_pre_rep(\r
606         IN                              ib_al_handle_t                          h_al,\r
607         IN                              net32_t                                         cid,\r
608         IN                              void*                                           context,\r
609         IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb,\r
610         IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
611         IN      OUT                     net32_t* const                          p_cid,\r
612                 OUT                     ib_qp_mod_t* const                      p_init )\r
613 {\r
614         ucep_t                                  *p_cep;\r
615         ual_cep_rep_ioctl_t             ioctl;\r
616         DWORD                                   bytes_ret;\r
617 \r
618         AL_ENTER( AL_DBG_CM );\r
619 \r
620         if( !h_al )\r
621         {\r
622                 AL_EXIT( AL_DBG_CM );\r
623                 return IB_INVALID_HANDLE;\r
624         }\r
625 \r
626         if( !p_cm_rep )\r
627         {\r
628                 AL_EXIT( AL_DBG_CM );\r
629                 return IB_INVALID_PARAMETER;\r
630         }\r
631 \r
632         if( !p_init )\r
633         {\r
634                 AL_EXIT( AL_DBG_ERROR );\r
635                 return IB_INVALID_PARAMETER;\r
636         }\r
637     cl_memclr(&ioctl, sizeof (ioctl));\r
638 \r
639         /* Store the context for the CEP. */\r
640         cl_spinlock_acquire( &gp_cep_mgr->obj.lock );\r
641         p_cep = cl_ptr_vector_get( &gp_cep_mgr->cep_vector, cid );\r
642         if( !p_cep )\r
643         {\r
644                 cl_spinlock_release( &gp_cep_mgr->obj.lock );\r
645                 AL_EXIT( AL_DBG_ERROR );\r
646                 return IB_INVALID_PARAMETER;\r
647         }\r
648         p_cep->destroy_context = context;\r
649         cl_spinlock_release( &gp_cep_mgr->obj.lock );\r
650 \r
651         ioctl.in.context = context;\r
652         ioctl.in.cid = cid;\r
653         ioctl.in.cm_rep = *p_cm_rep;\r
654         ioctl.in.cm_rep.h_qp = (ib_qp_handle_t VOID_PTR64)HDL_TO_PTR(p_cm_rep->h_qp->obj.hdl);\r
655         /* Copy private data, if any. */\r
656         if( p_cm_rep->p_rep_pdata )\r
657         {\r
658                 if( p_cm_rep->rep_length > IB_REP_PDATA_SIZE )\r
659                 {\r
660                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
661                                 ("private data larger than REP private data.\n") );\r
662                         return IB_INVALID_SETTING;\r
663                 }\r
664 \r
665                 cl_memcpy( ioctl.in.pdata, p_cm_rep->p_rep_pdata,\r
666                         p_cm_rep->rep_length );\r
667         }\r
668 \r
669         if( !DeviceIoControl( g_al_device, UAL_CEP_PRE_REP, &ioctl,\r
670                 sizeof(ioctl.in), &ioctl, sizeof(ioctl.out), &bytes_ret, NULL ) ||\r
671                 bytes_ret != sizeof(ioctl.out) )\r
672         {\r
673                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
674                         ("UAL_CEP_PRE_REQ IOCTL failed with %d.\n", GetLastError()) );\r
675                 return IB_ERROR;\r
676         }\r
677 \r
678         if( ioctl.out.status == IB_SUCCESS )\r
679         {\r
680                 cl_spinlock_acquire( &h_al->obj.lock );\r
681                 if( *p_cid != AL_INVALID_CID )\r
682                 {\r
683                         cl_spinlock_release( &h_al->obj.lock );\r
684                         return IB_INVALID_STATE;\r
685                 }\r
686                 p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
687                 *p_cid = p_cep->cid;\r
688                 *p_init = ioctl.out.init;\r
689                 cl_spinlock_release( &h_al->obj.lock );\r
690         }\r
691 \r
692         AL_EXIT( AL_DBG_CM );\r
693         return ioctl.out.status;\r
694 }\r
695 \r
696 \r
697 ib_api_status_t\r
698 al_cep_send_rep(\r
699         IN                              ib_al_handle_t                          h_al,\r
700         IN                              net32_t                                         cid )\r
701 {\r
702         ib_api_status_t         status;\r
703         DWORD                           bytes_ret;\r
704 \r
705         AL_ENTER( AL_DBG_CM );\r
706 \r
707         if( !h_al )\r
708         {\r
709                 AL_EXIT( AL_DBG_CM );\r
710                 return IB_INVALID_HANDLE;\r
711         }\r
712 \r
713         if( !DeviceIoControl( g_al_device, UAL_CEP_SEND_REP, &cid,\r
714                 sizeof(cid), &status, sizeof(status), &bytes_ret, NULL ) ||\r
715                 bytes_ret != sizeof(status) )\r
716         {\r
717                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
718                         ("UAL_CEP_SEND_REP IOCTL failed with %d.\n", GetLastError()) );\r
719                 return IB_ERROR;\r
720         }\r
721 \r
722         AL_EXIT( AL_DBG_CM );\r
723         return status;\r
724 }\r
725 \r
726 \r
727 ib_api_status_t\r
728 al_cep_get_rtr_attr(\r
729         IN                              ib_al_handle_t                          h_al,\r
730         IN                              net32_t                                         cid,\r
731                 OUT                     ib_qp_mod_t* const                      p_rtr )\r
732 {\r
733         ual_cep_get_rtr_ioctl_t ioctl;\r
734         DWORD                                   bytes_ret;\r
735 \r
736         AL_ENTER( AL_DBG_CM );\r
737 \r
738         if( !h_al )\r
739         {\r
740                 AL_EXIT( AL_DBG_CM );\r
741                 return IB_INVALID_HANDLE;\r
742         }\r
743 \r
744         if( !p_rtr )\r
745         {\r
746                 AL_EXIT( AL_DBG_ERROR );\r
747                 return IB_INVALID_PARAMETER;\r
748         }\r
749 \r
750         if( !DeviceIoControl( g_al_device, UAL_CEP_GET_RTR, &cid,\r
751                 sizeof(cid), &ioctl, sizeof(ioctl), &bytes_ret, NULL ) ||\r
752                 bytes_ret != sizeof(ioctl) )\r
753         {\r
754                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
755                         ("UAL_CEP_GET_RTR IOCTL failed with %d.\n", GetLastError()) );\r
756                 return IB_ERROR;\r
757         }\r
758 \r
759         if( ioctl.status == IB_SUCCESS )\r
760                 *p_rtr = ioctl.rtr;\r
761 \r
762         AL_EXIT( AL_DBG_CM );\r
763         return ioctl.status;\r
764 }\r
765 \r
766 \r
767 ib_api_status_t\r
768 al_cep_get_rts_attr(\r
769         IN                              ib_al_handle_t                          h_al,\r
770         IN                              net32_t                                         cid,\r
771                 OUT                     ib_qp_mod_t* const                      p_rts )\r
772 {\r
773         ual_cep_get_rts_ioctl_t ioctl;\r
774         DWORD                                   bytes_ret;\r
775 \r
776         AL_ENTER( AL_DBG_CM );\r
777 \r
778         if( !h_al )\r
779         {\r
780                 AL_EXIT( AL_DBG_CM );\r
781                 return IB_INVALID_HANDLE;\r
782         }\r
783 \r
784         if( !p_rts )\r
785         {\r
786                 AL_EXIT( AL_DBG_ERROR );\r
787                 return IB_INVALID_PARAMETER;\r
788         }\r
789 \r
790         if( !DeviceIoControl( g_al_device, UAL_CEP_GET_RTS, &cid,\r
791                 sizeof(cid), &ioctl, sizeof(ioctl), &bytes_ret, NULL ) ||\r
792                 bytes_ret != sizeof(ioctl) )\r
793         {\r
794                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
795                         ("UAL_CEP_GET_RTS IOCTL failed with %d.\n", GetLastError()) );\r
796                 return IB_ERROR;\r
797         }\r
798 \r
799         if( ioctl.status == IB_SUCCESS )\r
800                 *p_rts = ioctl.rts;\r
801 \r
802         AL_EXIT( AL_DBG_CM );\r
803         return ioctl.status;\r
804 }\r
805 \r
806 \r
807 ib_api_status_t\r
808 al_cep_rtu(\r
809         IN                              ib_al_handle_t                          h_al,\r
810         IN                              net32_t                                         cid,\r
811         IN              const   uint8_t*                                        p_pdata OPTIONAL,\r
812         IN                              uint8_t                                         pdata_len )\r
813 {\r
814         ib_api_status_t                 status;\r
815         ual_cep_rtu_ioctl_t             ioctl;\r
816         DWORD                                   bytes_ret;\r
817 \r
818         AL_ENTER( AL_DBG_CM );\r
819 \r
820         if( !h_al )\r
821         {\r
822                 AL_EXIT( AL_DBG_CM );\r
823                 return IB_INVALID_HANDLE;\r
824         }\r
825     cl_memclr(&ioctl, sizeof(ioctl));\r
826         ioctl.cid = cid;\r
827         /* Copy private data, if any. */\r
828         if( p_pdata )\r
829         {\r
830                 if( pdata_len > IB_RTU_PDATA_SIZE )\r
831                 {\r
832                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
833                                 ("private data larger than RTU private data.\n") );\r
834                         return IB_INVALID_SETTING;\r
835                 }\r
836 \r
837                 cl_memcpy( ioctl.pdata, p_pdata, pdata_len );\r
838         }\r
839         ioctl.pdata_len = pdata_len;\r
840 \r
841         if( !DeviceIoControl( g_al_device, UAL_CEP_RTU, &ioctl,\r
842                 sizeof(ioctl), &status, sizeof(status), &bytes_ret, NULL ) ||\r
843                 bytes_ret != sizeof(status) )\r
844         {\r
845                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
846                         ("UAL_CEP_RTU IOCTL failed with %d.\n", GetLastError()) );\r
847                 return IB_ERROR;\r
848         }\r
849 \r
850         AL_EXIT( AL_DBG_CM );\r
851         return status;\r
852 }\r
853 \r
854 \r
855 ib_api_status_t\r
856 al_cep_rej(\r
857         IN                              ib_al_handle_t                          h_al,\r
858         IN                              net32_t                                         cid,\r
859         IN                              ib_rej_status_t                         rej_status,\r
860         IN              const   uint8_t* const                          p_ari,\r
861         IN                              uint8_t                                         ari_len,\r
862         IN              const   uint8_t* const                          p_pdata,\r
863         IN                              uint8_t                                         pdata_len )\r
864 {\r
865         ib_api_status_t                 status;\r
866         ual_cep_rej_ioctl_t             ioctl;\r
867         DWORD                                   bytes_ret;\r
868 \r
869         AL_ENTER( AL_DBG_CM );\r
870 \r
871         if( !h_al )\r
872         {\r
873                 AL_EXIT( AL_DBG_CM );\r
874                 return IB_INVALID_HANDLE;\r
875         }\r
876     cl_memclr(&ioctl, sizeof(ioctl));\r
877         ioctl.cid = cid;\r
878         ioctl.rej_status = rej_status;\r
879         if( p_ari )\r
880         {\r
881                 if( ari_len > IB_ARI_SIZE )\r
882                 {\r
883                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
884                                 ("private data larger than REJ ARI data.\n") );\r
885                         return IB_INVALID_SETTING;\r
886                 }\r
887 \r
888                 cl_memcpy( ioctl.ari, p_ari, ari_len );\r
889                 ioctl.ari_len = ari_len;\r
890         }\r
891         else\r
892         {\r
893                 ioctl.ari_len = 0;\r
894         }\r
895         /* Copy private data, if any. */\r
896         if( p_pdata)\r
897         {\r
898                 if( pdata_len > IB_REJ_PDATA_SIZE )\r
899                 {\r
900                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
901                                 ("private data larger than REJ private data.\n") );\r
902                         return IB_INVALID_SETTING;\r
903                 }\r
904 \r
905                 cl_memcpy( ioctl.pdata, p_pdata, pdata_len );\r
906                 ioctl.pdata_len = pdata_len;\r
907         }\r
908         else\r
909         {\r
910                 ioctl.pdata_len = 0;\r
911         }\r
912 \r
913         if( !DeviceIoControl( g_al_device, UAL_CEP_REJ, &ioctl,\r
914                 sizeof(ioctl), &status, sizeof(status), &bytes_ret, NULL ) ||\r
915                 bytes_ret != sizeof(status) )\r
916         {\r
917                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
918                         ("UAL_CEP_PRE_REQ IOCTL failed with %d.\n", GetLastError()) );\r
919                 return IB_ERROR;\r
920         }\r
921 \r
922         AL_EXIT( AL_DBG_CM );\r
923         return status;\r
924 }\r
925 \r
926 \r
927 ib_api_status_t\r
928 al_cep_mra(\r
929         IN                              ib_al_handle_t                          h_al,\r
930         IN                              net32_t                                         cid,\r
931         IN              const   ib_cm_mra_t* const                      p_cm_mra )\r
932 {\r
933         ib_api_status_t                 status;\r
934         ual_cep_mra_ioctl_t             ioctl;\r
935         DWORD                                   bytes_ret;\r
936 \r
937         AL_ENTER( AL_DBG_CM );\r
938 \r
939         if( !h_al )\r
940         {\r
941                 AL_EXIT( AL_DBG_CM );\r
942                 return IB_INVALID_HANDLE;\r
943         }\r
944 \r
945         if( !p_cm_mra )\r
946         {\r
947                 AL_EXIT( AL_DBG_CM );\r
948                 return IB_INVALID_HANDLE;\r
949         }\r
950     cl_memclr(&ioctl, sizeof (ioctl));\r
951         ioctl.cid = cid;\r
952         ioctl.cm_mra = *p_cm_mra;\r
953         /* Copy private data, if any. */\r
954         if( p_cm_mra->p_mra_pdata )\r
955         {\r
956                 if( p_cm_mra->mra_length > IB_MRA_PDATA_SIZE )\r
957                 {\r
958                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
959                                 ("private data larger than MRA private data.\n") );\r
960                         return IB_INVALID_SETTING;\r
961                 }\r
962 \r
963                 cl_memcpy(\r
964                         ioctl.pdata, p_cm_mra->p_mra_pdata, p_cm_mra->mra_length );\r
965         }\r
966 \r
967         if( !DeviceIoControl( g_al_device, UAL_CEP_MRA, &ioctl,\r
968                 sizeof(ioctl), &status, sizeof(status), &bytes_ret, NULL ) ||\r
969                 bytes_ret != sizeof(status) )\r
970         {\r
971                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
972                         ("UAL_CEP_MRA IOCTL failed with %d.\n", GetLastError()) );\r
973                 return IB_ERROR;\r
974         }\r
975 \r
976         AL_EXIT( AL_DBG_CM );\r
977         return status;\r
978 }\r
979 \r
980 \r
981 ib_api_status_t\r
982 al_cep_lap(\r
983         IN                              ib_al_handle_t                          h_al,\r
984         IN                              net32_t                                         cid,\r
985         IN              const   ib_cm_lap_t* const                      p_cm_lap )\r
986 {\r
987         ib_api_status_t                 status;\r
988         ual_cep_lap_ioctl_t             ioctl;\r
989         DWORD                                   bytes_ret;\r
990 \r
991         AL_ENTER( AL_DBG_CM );\r
992 \r
993         if( !h_al )\r
994         {\r
995                 AL_EXIT( AL_DBG_CM );\r
996                 return IB_INVALID_HANDLE;\r
997         }\r
998 \r
999         if( !p_cm_lap )\r
1000         {\r
1001                 AL_EXIT( AL_DBG_CM );\r
1002                 return IB_INVALID_HANDLE;\r
1003         }\r
1004 \r
1005         if( !p_cm_lap->p_alt_path )\r
1006         {\r
1007                 AL_EXIT( AL_DBG_CM );\r
1008                 return IB_INVALID_HANDLE;\r
1009         }\r
1010     cl_memclr(&ioctl,sizeof (ioctl));\r
1011         ioctl.cid = cid;\r
1012         ioctl.cm_lap = *p_cm_lap;\r
1013         ioctl.cm_lap.h_qp = (ib_qp_handle_t VOID_PTR64) HDL_TO_PTR(p_cm_lap->h_qp->obj.hdl);\r
1014         ioctl.alt_path = *(p_cm_lap->p_alt_path);\r
1015         /* Copy private data, if any. */\r
1016         if( p_cm_lap->p_lap_pdata )\r
1017         {\r
1018                 if( p_cm_lap->lap_length > IB_LAP_PDATA_SIZE )\r
1019                 {\r
1020                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1021                                 ("private data larger than LAP private data.\n") );\r
1022                         return IB_INVALID_SETTING;\r
1023                 }\r
1024 \r
1025                 cl_memcpy(\r
1026                         ioctl.pdata, p_cm_lap->p_lap_pdata, p_cm_lap->lap_length );\r
1027         }\r
1028 \r
1029         if( !DeviceIoControl( g_al_device, UAL_CEP_LAP, &ioctl,\r
1030                 sizeof(ioctl), &status, sizeof(status), &bytes_ret, NULL ) ||\r
1031                 bytes_ret != sizeof(status) )\r
1032         {\r
1033                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1034                         ("UAL_CEP_LAP IOCTL failed with %d.\n", GetLastError()) );\r
1035                 return IB_ERROR;\r
1036         }\r
1037 \r
1038         AL_EXIT( AL_DBG_CM );\r
1039         return status;\r
1040 }\r
1041 \r
1042 \r
1043 ib_api_status_t\r
1044 al_cep_pre_apr(\r
1045         IN                              ib_al_handle_t                          h_al,\r
1046         IN                              net32_t                                         cid,\r
1047         IN              const   ib_cm_apr_t* const                      p_cm_apr,\r
1048                 OUT                     ib_qp_mod_t* const                      p_apr )\r
1049 {\r
1050         ual_cep_apr_ioctl_t             ioctl;\r
1051         DWORD                                   bytes_ret;\r
1052 \r
1053         AL_ENTER( AL_DBG_CM );\r
1054 \r
1055         if( !h_al )\r
1056         {\r
1057                 AL_EXIT( AL_DBG_CM );\r
1058                 return IB_INVALID_HANDLE;\r
1059         }\r
1060 \r
1061         if( !p_cm_apr || !p_apr )\r
1062         {\r
1063                 AL_EXIT( AL_DBG_CM );\r
1064                 return IB_INVALID_PARAMETER;\r
1065         }\r
1066     cl_memclr(&ioctl, sizeof (ioctl));\r
1067         ioctl.in.cid = cid;\r
1068         ioctl.in.cm_apr = *p_cm_apr;\r
1069         ioctl.in.cm_apr.h_qp = (ib_qp_handle_t VOID_PTR64)HDL_TO_PTR(p_cm_apr->h_qp->obj.hdl);\r
1070         if( p_cm_apr->p_info )\r
1071         {\r
1072                 if( p_cm_apr->info_length > IB_APR_INFO_SIZE )\r
1073                 {\r
1074                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1075                                 ("private data larger than APR info data.\n") );\r
1076                         return IB_INVALID_SETTING;\r
1077                 }\r
1078 \r
1079                 cl_memcpy(\r
1080                         ioctl.in.apr_info, p_cm_apr->p_info, p_cm_apr->info_length );\r
1081         }\r
1082         /* Copy private data, if any. */\r
1083         if( p_cm_apr->p_apr_pdata )\r
1084         {\r
1085                 if( p_cm_apr->apr_length > IB_APR_PDATA_SIZE) //TODO ??????\r
1086                 {\r
1087                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1088                                 ("private data larger than APR private data.\n") );\r
1089                         return IB_INVALID_SETTING;\r
1090                 }\r
1091 \r
1092                 cl_memcpy(\r
1093                         ioctl.in.pdata, p_cm_apr->p_apr_pdata, p_cm_apr->apr_length );\r
1094         }\r
1095 \r
1096         if( !DeviceIoControl( g_al_device, UAL_CEP_PRE_APR, &ioctl.in,\r
1097                 sizeof(ioctl.in), &ioctl.out, sizeof(ioctl.out), &bytes_ret, NULL ) ||\r
1098                 bytes_ret != sizeof(ioctl.out) )\r
1099         {\r
1100                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1101                         ("UAL_CEP_PRE_REQ IOCTL failed with %d.\n", GetLastError()) );\r
1102                 return IB_ERROR;\r
1103         }\r
1104         \r
1105         if( ioctl.out.status == IB_SUCCESS )\r
1106                 *p_apr = ioctl.out.apr;\r
1107 \r
1108         AL_EXIT( AL_DBG_CM );\r
1109         return ioctl.out.status;\r
1110 }\r
1111 \r
1112 \r
1113 ib_api_status_t\r
1114 al_cep_send_apr(\r
1115         IN                              ib_al_handle_t                          h_al,\r
1116         IN                              net32_t                                         cid )\r
1117 {\r
1118         ib_api_status_t         status;\r
1119         DWORD                           bytes_ret;\r
1120 \r
1121         AL_ENTER( AL_DBG_CM );\r
1122 \r
1123         if( !h_al )\r
1124         {\r
1125                 AL_EXIT( AL_DBG_CM );\r
1126                 return IB_INVALID_HANDLE;\r
1127         }\r
1128 \r
1129         if( !DeviceIoControl( g_al_device, UAL_CEP_SEND_APR, &cid,\r
1130                 sizeof(cid), &status, sizeof(status), &bytes_ret, NULL ) ||\r
1131                 bytes_ret != sizeof(status) )\r
1132         {\r
1133                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1134                         ("UAL_CEP_SEND_APR IOCTL failed with %d.\n", GetLastError()) );\r
1135                 return IB_ERROR;\r
1136         }\r
1137 \r
1138         AL_EXIT( AL_DBG_CM );\r
1139         return status;\r
1140 }\r
1141 \r
1142 \r
1143 ib_api_status_t\r
1144 al_cep_dreq(\r
1145         IN                              ib_al_handle_t                          h_al,\r
1146         IN                              net32_t                                         cid,\r
1147         IN              const   uint8_t* const                          p_pdata OPTIONAL,\r
1148         IN              const   uint8_t                                         pdata_len )\r
1149 {\r
1150         ib_api_status_t                 status;\r
1151         ual_cep_dreq_ioctl_t    ioctl;\r
1152         DWORD                                   bytes_ret;\r
1153 \r
1154         AL_ENTER( AL_DBG_CM );\r
1155 \r
1156         if( !h_al )\r
1157         {\r
1158                 AL_EXIT( AL_DBG_CM );\r
1159                 return IB_INVALID_HANDLE;\r
1160         }\r
1161     cl_memclr(&ioctl, sizeof(ioctl));\r
1162         ioctl.cid = cid;\r
1163         /* Copy private data, if any. */\r
1164         if( p_pdata )\r
1165         {\r
1166                 if( pdata_len > IB_DREQ_PDATA_SIZE )\r
1167                 {\r
1168                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1169                                 ("private data larger than DREQ private data.\n") );\r
1170                         return IB_INVALID_SETTING;\r
1171                 }\r
1172 \r
1173                 cl_memcpy( ioctl.pdata, p_pdata, pdata_len );\r
1174                 ioctl.pdata_len = pdata_len;\r
1175         }\r
1176         else\r
1177         {\r
1178                 ioctl.pdata_len = 0;\r
1179         }\r
1180 \r
1181         if( !DeviceIoControl( g_al_device, UAL_CEP_DREQ, &ioctl,\r
1182                 sizeof(ioctl), &status, sizeof(status), &bytes_ret, NULL ) ||\r
1183                 bytes_ret != sizeof(status) )\r
1184         {\r
1185                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1186                         ("UAL_CEP_DREQ IOCTL failed with %d.\n", GetLastError()) );\r
1187                 return IB_ERROR;\r
1188         }\r
1189 \r
1190         AL_EXIT( AL_DBG_CM );\r
1191         return status;\r
1192 }\r
1193 \r
1194 \r
1195 ib_api_status_t\r
1196 al_cep_drep(\r
1197         IN                              ib_al_handle_t                          h_al,\r
1198         IN                              net32_t                                         cid,\r
1199         IN              const   uint8_t* const                          p_pdata OPTIONAL,\r
1200         IN              const   uint8_t                                         pdata_len )\r
1201 {\r
1202         ib_api_status_t                 status;\r
1203         ual_cep_drep_ioctl_t    ioctl;\r
1204         DWORD                                   bytes_ret;\r
1205 \r
1206         AL_ENTER( AL_DBG_CM );\r
1207 \r
1208         if( !h_al )\r
1209         {\r
1210                 AL_EXIT( AL_DBG_CM );\r
1211                 return IB_INVALID_HANDLE;\r
1212         }\r
1213 \r
1214         ioctl.cid = cid;\r
1215         /* Copy private data, if any. */\r
1216         if( p_pdata )\r
1217         {\r
1218                 if( pdata_len > IB_DREP_PDATA_SIZE )\r
1219                 {\r
1220                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1221                                 ("private data larger than DREP private data.\n") );\r
1222                         return IB_INVALID_SETTING;\r
1223                 }\r
1224 \r
1225                 cl_memcpy( ioctl.pdata, p_pdata, pdata_len );\r
1226                 ioctl.pdata_len = pdata_len;\r
1227         }\r
1228         else\r
1229         {\r
1230                 ioctl.pdata_len = 0;\r
1231         }\r
1232 \r
1233         if( !DeviceIoControl( g_al_device, UAL_CEP_DREP, &ioctl,\r
1234                 sizeof(ioctl), &status, sizeof(status), &bytes_ret, NULL ) ||\r
1235                 bytes_ret != sizeof(status) )\r
1236         {\r
1237                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1238                         ("UAL_CEP_DREP IOCTL failed with %d.\n", GetLastError()) );\r
1239                 return IB_ERROR;\r
1240         }\r
1241 \r
1242         AL_EXIT( AL_DBG_CM );\r
1243         return status;\r
1244 }\r
1245 \r
1246 \r
1247 ib_api_status_t\r
1248 al_cep_get_timewait(\r
1249         IN                              ib_al_handle_t                          h_al,\r
1250         IN                              net32_t                                         cid,\r
1251                 OUT                     uint64_t* const                         p_timewait_us )\r
1252 {\r
1253         ual_cep_get_timewait_ioctl_t    ioctl;\r
1254         DWORD                                                   bytes_ret;\r
1255 \r
1256         AL_ENTER( AL_DBG_CM );\r
1257 \r
1258         if( !h_al )\r
1259         {\r
1260                 AL_EXIT( AL_DBG_CM );\r
1261                 return IB_INVALID_HANDLE;\r
1262         }\r
1263 \r
1264         if( !p_timewait_us )\r
1265         {\r
1266                 AL_EXIT( AL_DBG_CM );\r
1267                 return IB_INVALID_HANDLE;\r
1268         }\r
1269 \r
1270         if( !DeviceIoControl( g_al_device, UAL_CEP_GET_TIMEWAIT, &cid, sizeof(cid),\r
1271                 &ioctl, sizeof(ioctl), &bytes_ret, NULL ) ||\r
1272                 bytes_ret != sizeof(ioctl) )\r
1273         {\r
1274                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1275                         ("UAL_CEP_DREP IOCTL failed with %d.\n", GetLastError()) );\r
1276                 return IB_ERROR;\r
1277         }\r
1278 \r
1279         if( ioctl.status == IB_SUCCESS )\r
1280                 *p_timewait_us = ioctl.timewait_us;\r
1281 \r
1282         AL_EXIT( AL_DBG_CM );\r
1283         return ioctl.status;\r
1284 }\r
1285 //\r
1286 //\r
1287 //ib_api_status_t\r
1288 //al_cep_migrate(\r
1289 //      IN                              ib_al_handle_t                          h_al,\r
1290 //      IN                              net32_t                                         cid );\r
1291 //\r
1292 //\r
1293 //ib_api_status_t\r
1294 //al_cep_established(\r
1295 //      IN                              ib_al_handle_t                          h_al,\r
1296 //      IN                              net32_t                                         cid );\r
1297 \r
1298 \r
1299 ib_api_status_t\r
1300 al_cep_poll(\r
1301         IN                              ib_al_handle_t                          h_al,\r
1302         IN                              net32_t                                         cid,\r
1303                 OUT                     void**                                          p_context,\r
1304                 OUT                     net32_t* const                          p_new_cid,\r
1305                 OUT                     ib_mad_element_t** const        pp_mad )\r
1306 {\r
1307         ucep_t                                  *p_cep;\r
1308         ib_api_status_t                 status;\r
1309         ual_cep_poll_ioctl_t    ioctl;\r
1310         DWORD                                   bytes_ret;\r
1311         ib_mad_element_t                *p_mad;\r
1312         ib_grh_t                                *p_grh;\r
1313         ib_mad_t                                *p_mad_buf;\r
1314 \r
1315         AL_ENTER( AL_DBG_CM );\r
1316 \r
1317         if( !h_al )\r
1318         {\r
1319                 AL_EXIT( AL_DBG_CM );\r
1320                 return IB_INVALID_HANDLE;\r
1321         }\r
1322 \r
1323         if( !p_new_cid || !pp_mad )\r
1324         {\r
1325                 AL_EXIT( AL_DBG_CM );\r
1326                 return IB_INVALID_PARAMETER;\r
1327         }\r
1328 \r
1329         cl_spinlock_acquire( &gp_cep_mgr->obj.lock );\r
1330         if( cid > cl_ptr_vector_get_size( &gp_cep_mgr->cep_vector ) )\r
1331                 p_cep = NULL;\r
1332         else\r
1333                 p_cep = cl_ptr_vector_get( &gp_cep_mgr->cep_vector, cid );\r
1334         cl_spinlock_release( &gp_cep_mgr->obj.lock );\r
1335         if( !p_cep )\r
1336         {\r
1337                 AL_EXIT( AL_DBG_CM );\r
1338                 return IB_INVALID_PARAMETER;\r
1339         }\r
1340 \r
1341         status = ib_get_mad( g_pool_key, MAD_BLOCK_SIZE, &p_mad );\r
1342         if( status != IB_SUCCESS )\r
1343         {\r
1344                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1345                         ("ib_get_mad returned %s.\n", ib_get_err_str( status )) );\r
1346                 return status;\r
1347         }\r
1348 \r
1349         p_mad_buf = p_mad->p_mad_buf;\r
1350         p_grh = p_mad->p_grh;\r
1351 \r
1352         if( !DeviceIoControl( g_al_device, UAL_CEP_POLL, &cid,\r
1353                 sizeof(cid), &ioctl, sizeof(ioctl), &bytes_ret, NULL ) ||\r
1354                 bytes_ret != sizeof(ioctl) )\r
1355         {\r
1356                 ib_put_mad( p_mad );\r
1357                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
1358                         ("UAL_CEP_POLL IOCTL failed with %d.\n", GetLastError()) );\r
1359                 return IB_ERROR;\r
1360         }\r
1361 \r
1362         if( ioctl.status == IB_SUCCESS )\r
1363         {\r
1364                 if( ioctl.new_cid != AL_INVALID_CID )\r
1365                 {\r
1366                         /* Need to create a new CEP for user-mode. */\r
1367                         status = __create_ucep( p_cep->h_al, ioctl.new_cid,\r
1368                                 p_cep->pfn_cb, NULL, NULL, NULL );\r
1369                         if( status != IB_SUCCESS )\r
1370                         {\r
1371                                 DeviceIoControl( g_al_device, UAL_DESTROY_CEP,\r
1372                                         &ioctl.new_cid, sizeof(ioctl.new_cid),\r
1373                                         NULL, 0, &bytes_ret, NULL );\r
1374                                 goto err;\r
1375                         }\r
1376                 }\r
1377 \r
1378                 /* Copy the MAD payload as it's all that's used. */\r
1379                 *p_mad = ioctl.element;\r
1380                 p_mad->p_grh = p_grh;\r
1381                 if( p_mad->grh_valid )\r
1382                         cl_memcpy( p_mad->p_grh, &ioctl.grh, sizeof(ib_grh_t) );\r
1383                 p_mad->p_mad_buf = p_mad_buf;\r
1384                 \r
1385                 cl_memcpy( p_mad->p_mad_buf, ioctl.mad_buf, MAD_BLOCK_SIZE );\r
1386 \r
1387                 *p_context = ioctl.context;\r
1388                 *p_new_cid = ioctl.new_cid;\r
1389                 *pp_mad = p_mad;\r
1390         }\r
1391         else\r
1392         {\r
1393 err:\r
1394                 ib_put_mad( p_mad );\r
1395         }\r
1396 \r
1397         AL_EXIT( AL_DBG_CM );\r
1398         return ioctl.status;\r
1399 }\r
1400 \r
1401 \r
1402 /* Callback to process CM events */\r
1403 void\r
1404 cm_cb(\r
1405         IN                              DWORD                                           error_code,\r
1406         IN                              DWORD                                           ret_bytes,\r
1407         IN                              LPOVERLAPPED                            p_ov )\r
1408 {\r
1409         ucep_t                  *p_cep;\r
1410         BOOL                    ret;\r
1411 \r
1412         AL_ENTER( AL_DBG_CM );\r
1413 \r
1414         /* The UAL_CEP_GET_EVENT IOCTL does not have any output data. */\r
1415         UNUSED_PARAM( ret_bytes );\r
1416 \r
1417         p_cep = PARENT_STRUCT( p_ov, ucep_t, ov );\r
1418 \r
1419         if( !error_code  )\r
1420         {\r
1421                 p_cep->pfn_cb( p_cep->h_al, p_cep->cid );\r
1422 \r
1423                 /* Synchronize with destruction. */\r
1424                 cl_spinlock_acquire( &gp_cep_mgr->obj.lock );\r
1425                 ret = DeviceIoControl( gp_cep_mgr->h_file, UAL_CEP_GET_EVENT,\r
1426                         &p_cep->cid, sizeof(p_cep->cid), NULL, 0,\r
1427                         NULL, &p_cep->ov );\r
1428                 cl_spinlock_release( &gp_cep_mgr->obj.lock );\r
1429                 if( !ret && GetLastError() == ERROR_IO_PENDING )\r
1430                 {\r
1431                         AL_EXIT( AL_DBG_CM );\r
1432                         return;\r
1433                 }\r
1434                 else if( GetLastError() != ERROR_INVALID_PARAMETER )\r
1435                 {\r
1436                         /* We can get ERROR_INVALID_PARAMETER if the CEP was destroyed. */\r
1437                         AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
1438                                 ("DeviceIoControl for CEP callback request returned %d.\n",\r
1439                                 GetLastError()) );\r
1440                 }\r
1441         }\r
1442         else\r
1443         {\r
1444                 AL_PRINT(TRACE_LEVEL_WARNING ,AL_DBG_CM ,\r
1445                         ("UAL_CEP_GET_EVENT IOCTL returned %d.\n", error_code) );\r
1446         }\r
1447 \r
1448         /*\r
1449          * We failed to issue the next request or the previous request was\r
1450          * cancelled.  Release the reference held by the previous IOCTL and exit.\r
1451          */\r
1452         if( !cl_atomic_dec( &p_cep->ref_cnt ) )\r
1453                 __destroy_ucep( p_cep );\r
1454 \r
1455         AL_EXIT( AL_DBG_CM );\r
1456 }\r