82c9f823b199ba66766c90648955c8249cff7fad
[mirror/winof/.git] / core / al / kernel / al_proxy_ndi.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
4  * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
5  *\r
6  * This software is available to you under the OpenIB.org BSD license\r
7  * below:\r
8  *\r
9  *     Redistribution and use in source and binary forms, with or\r
10  *     without modification, are permitted provided that the following\r
11  *     conditions are met:\r
12  *\r
13  *      - Redistributions of source code must retain the above\r
14  *        copyright notice, this list of conditions and the following\r
15  *        disclaimer.\r
16  *\r
17  *      - Redistributions in binary form must reproduce the above\r
18  *        copyright notice, this list of conditions and the following\r
19  *        disclaimer in the documentation and/or other materials\r
20  *        provided with the distribution.\r
21  *\r
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
29  * SOFTWARE.\r
30  *\r
31  * $Id: al_proxy_verbs.c 548 2006-11-27 20:03:51Z leonidk $\r
32  */\r
33 \r
34 \r
35 #include <complib/comp_lib.h>\r
36 #include <iba/ib_al.h>\r
37 #include <iba/ib_al_ioctl.h>\r
38 #include "al.h"\r
39 #include "al_qp.h"\r
40 #include "al_debug.h"\r
41 #include "al_cm_cep.h"\r
42 \r
43 #if defined(EVENT_TRACING)\r
44 #ifdef offsetof\r
45 #undef offsetof\r
46 #endif\r
47 #include "al_proxy_ndi.tmh"\r
48 #endif\r
49 \r
50 #include "al_dev.h"\r
51 /* Get the internal definitions of apis for the proxy */\r
52 #include "al_ca.h"\r
53 #include "ib_common.h"\r
54 #include "al_proxy_ndi.h"\r
55 #include "al_ndi_cm.h"\r
56 \r
57 /*******************************************************************\r
58  *\r
59  * IOCTLS\r
60  *\r
61  ******************************************************************/\r
62 \r
63 /*\r
64  * Process the ioctl UAL_NDI_CREATE_CQ:\r
65  */\r
66 static cl_status_t\r
67 __ndi_create_cq(\r
68         IN              void                                    *p_open_context,\r
69         IN              cl_ioctl_handle_t               h_ioctl,\r
70                 OUT     size_t                                  *p_ret_bytes )\r
71 {\r
72         ual_create_cq_ioctl_t   *p_ioctl =\r
73                 (ual_create_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
74         al_dev_open_context_t   *p_context =\r
75                 (al_dev_open_context_t *)p_open_context;\r
76         ib_ca_handle_t                  h_ca;\r
77         ib_cq_handle_t                  h_cq;\r
78         ib_cq_create_t                  cq_create;\r
79         ci_umv_buf_t                    *p_umv_buf = NULL;\r
80         ib_api_status_t                 status;\r
81         ib_pfn_event_cb_t               pfn_ev;\r
82 \r
83         AL_ENTER( AL_DBG_NDI );\r
84 \r
85         /* Validate input buffers. */\r
86         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
87                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
88                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
89         {\r
90                 status = CL_INVALID_PARAMETER;\r
91                 goto exit;\r
92         }\r
93 \r
94         /* Validate CA handle */\r
95         h_ca = (ib_ca_handle_t)\r
96                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_ca, AL_OBJ_TYPE_H_CA );\r
97         if( !h_ca )\r
98         {\r
99                 status = IB_INVALID_CA_HANDLE;\r
100                 goto proxy_create_cq_err1;\r
101         }\r
102 \r
103         cq_create.size = p_ioctl->in.size;\r
104 \r
105         /* Override with proxy's cq callback */\r
106         cq_create.pfn_comp_cb = ndi_cq_compl_cb;\r
107         cq_create.h_wait_obj = NULL;\r
108         pfn_ev = ndi_cq_error_cb;\r
109 \r
110         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
111         if( status != IB_SUCCESS )\r
112                 goto proxy_create_cq_err2;\r
113 \r
114         status = create_cq( h_ca, &cq_create,\r
115                 (void*)(ULONG_PTR)p_ioctl->in.context, pfn_ev, &h_cq, p_umv_buf );\r
116 \r
117         if( status != IB_SUCCESS )\r
118                 goto proxy_create_cq_err2;\r
119 \r
120         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
121         if( status == IB_SUCCESS )\r
122         {\r
123                 p_ioctl->out.size = cq_create.size;\r
124                 p_ioctl->out.h_cq = h_cq->obj.hdl;\r
125                 h_cq->obj.hdl_valid = TRUE;\r
126                 deref_al_obj( &h_cq->obj );\r
127         }\r
128         else\r
129         {\r
130                 h_cq->obj.pfn_destroy( &h_cq->obj, NULL );\r
131 \r
132 proxy_create_cq_err2:\r
133                 cl_waitobj_deref( cq_create.h_wait_obj );\r
134 \r
135 proxy_create_cq_err1:\r
136                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
137                 p_ioctl->out.h_cq = AL_INVALID_HANDLE;\r
138                 p_ioctl->out.size = 0;\r
139         }\r
140         free_umvbuf( p_umv_buf );\r
141 \r
142         if( h_ca )\r
143                 deref_al_obj( &h_ca->obj );\r
144 \r
145         p_ioctl->out.status = status;\r
146         *p_ret_bytes = sizeof(p_ioctl->out);\r
147 \r
148 exit:\r
149         AL_EXIT( AL_DBG_NDI );\r
150         return CL_SUCCESS;\r
151 }\r
152 \r
153 \r
154 static cl_status_t\r
155 __ndi_notify_cq(\r
156         IN              void                                    *p_open_context,\r
157         IN              cl_ioctl_handle_t               h_ioctl,\r
158                 OUT     size_t                                  *p_ret_bytes )\r
159 {\r
160         cl_status_t cl_status;\r
161         ual_ndi_notify_cq_ioctl_in_t *p_ioctl;\r
162         al_dev_open_context_t *p_context;\r
163         ib_cq_handle_t h_cq;\r
164         UNUSED_PARAM(p_ret_bytes);\r
165         \r
166         AL_ENTER( AL_DBG_NDI );\r
167 \r
168         p_context = (al_dev_open_context_t*)p_open_context;\r
169         p_ioctl = (ual_ndi_notify_cq_ioctl_in_t*)cl_ioctl_in_buf( h_ioctl );\r
170 \r
171         /* Validate user parameters. */\r
172         if( cl_ioctl_in_size( h_ioctl ) != sizeof(ual_ndi_notify_cq_ioctl_in_t) )\r
173         {\r
174                 cl_status = CL_INVALID_PARAMETER;\r
175                 goto exit;\r
176         }\r
177 \r
178         /* Validate CQ handle */\r
179         h_cq = (ib_cq_handle_t)\r
180                 al_hdl_ref( p_context->h_al, p_ioctl->h_cq, AL_OBJ_TYPE_H_CQ );\r
181         if( !h_cq )\r
182         {\r
183                 cl_status = CL_INVALID_HANDLE;\r
184                 goto exit;\r
185         }\r
186 \r
187         /* enqueue the IRP (h_cq is referenced in al_hdl_ref) */\r
188         if (p_ioctl->notify_comps)\r
189                 IoCsqInsertIrp( &h_cq->compl.csq, h_ioctl, NULL );\r
190         else\r
191                 IoCsqInsertIrp( &h_cq->error.csq, h_ioctl, NULL );\r
192 \r
193         cl_status = CL_PENDING;\r
194 \r
195 exit:\r
196         AL_EXIT( AL_DBG_NDI );\r
197         return cl_status;\r
198 }\r
199 \r
200 static cl_status_t\r
201 __ndi_cancel_cq(\r
202         IN              void                                    *p_open_context,\r
203         IN              cl_ioctl_handle_t               h_ioctl,\r
204                 OUT     size_t                                  *p_ret_bytes )\r
205 {\r
206         cl_status_t cl_status;\r
207         ib_cq_handle_t h_cq = NULL;\r
208         al_dev_open_context_t *p_context;\r
209         UNUSED_PARAM(p_ret_bytes);\r
210         \r
211         AL_ENTER( AL_DBG_NDI );\r
212 \r
213         p_context = (al_dev_open_context_t*)p_open_context;\r
214 \r
215         /* Validate user parameters. */\r
216         if( cl_ioctl_in_size( h_ioctl ) != sizeof(uint64_t) )\r
217         {\r
218                 cl_status = CL_INVALID_PARAMETER;\r
219                 goto exit;\r
220         }\r
221 \r
222         /* Validate CQ handle */\r
223         h_cq = (ib_cq_handle_t)\r
224                 al_hdl_ref( p_context->h_al, \r
225                         *(uint64_t*)cl_ioctl_in_buf( h_ioctl ), AL_OBJ_TYPE_H_CQ );\r
226         if( !h_cq )\r
227         {\r
228                 cl_status = CL_INVALID_HANDLE;\r
229                 goto exit;\r
230         }\r
231 \r
232         /* flush IRP queues */\r
233         ndi_cq_flush_ques( h_cq );\r
234 \r
235         cl_status = CL_SUCCESS;\r
236         deref_al_obj( &h_cq->obj );\r
237 \r
238 exit:\r
239         AL_EXIT( AL_DBG_NDI );\r
240         return cl_status;\r
241 }\r
242 \r
243 static cl_status_t\r
244 __ndi_modify_qp(\r
245         IN              void                                    *p_open_context,\r
246         IN              cl_ioctl_handle_t               h_ioctl,\r
247                 OUT     size_t                                  *p_ret_bytes )\r
248 {\r
249         cl_status_t cl_status;\r
250         ib_api_status_t status;\r
251         ib_qp_handle_t h_qp = NULL;\r
252         al_dev_open_context_t *p_context;\r
253         ual_ndi_modify_qp_ioctl_in_t *p_req = \r
254                 (ual_ndi_modify_qp_ioctl_in_t*)cl_ioctl_in_buf( h_ioctl );\r
255 \r
256         UNUSED_PARAM(p_ret_bytes);\r
257         \r
258         AL_ENTER( AL_DBG_NDI );\r
259 \r
260         p_context = (al_dev_open_context_t*)p_open_context;\r
261 \r
262         /* Validate user parameters. */\r
263         if( cl_ioctl_in_size( h_ioctl ) < sizeof(ual_ndi_modify_qp_ioctl_in_t))\r
264         {\r
265                 cl_status = CL_INVALID_PARAMETER;\r
266                 goto exit;\r
267         }\r
268 \r
269         /* Validate QP handle */\r
270         h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al, p_req->h_qp, AL_OBJ_TYPE_H_QP );\r
271         if( !h_qp )\r
272         {\r
273                 cl_status = CL_INVALID_HANDLE;\r
274                 goto exit;\r
275         }\r
276 \r
277         /* Check QP type */\r
278         if( h_qp->type != IB_QPT_RELIABLE_CONN )\r
279         {\r
280                 cl_status = CL_INVALID_HANDLE;\r
281                 goto err;\r
282         }\r
283 \r
284         /* perform the ioctl */\r
285         status = ndi_modify_qp( h_qp, &p_req->qp_mod, \r
286                 cl_ioctl_out_size( h_ioctl ), cl_ioctl_out_buf( h_ioctl ) );\r
287         if ( status != IB_SUCCESS )\r
288         {\r
289                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
290                         ("ndi_modify_qp returned %s.\n", ib_get_err_str(status) ) );\r
291                 cl_status = CL_ERROR;\r
292         }\r
293         else\r
294         {\r
295                 cl_status = CL_SUCCESS;\r
296                 *p_ret_bytes = cl_ioctl_out_size( h_ioctl );\r
297         }\r
298 \r
299 err:\r
300         deref_al_obj( &h_qp->obj );\r
301 \r
302 exit:\r
303         AL_EXIT( AL_DBG_NDI );\r
304         return cl_status;\r
305 }\r
306 \r
307 static cl_status_t\r
308 __ndi_req_cm(\r
309         IN              void                                    *p_open_context,\r
310         IN              cl_ioctl_handle_t               h_ioctl,\r
311                 OUT     size_t                                  *p_ret_bytes )\r
312 {\r
313         cl_status_t cl_status;\r
314         ib_qp_handle_t h_qp = NULL;\r
315         al_dev_open_context_t *p_context;\r
316         ual_ndi_req_cm_ioctl_in_t *p_req = \r
317                 (ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( h_ioctl );\r
318         UNUSED_PARAM(p_ret_bytes);\r
319         \r
320         AL_ENTER( AL_DBG_NDI );\r
321 \r
322         p_context = (al_dev_open_context_t*)p_open_context;\r
323 \r
324         /* Validate user parameters. */\r
325         if( cl_ioctl_in_size( h_ioctl ) < sizeof(ual_ndi_req_cm_ioctl_in_t) )\r
326         {\r
327                 cl_status = CL_INVALID_PARAMETER;\r
328                 goto exit;\r
329         }\r
330 \r
331         /* Validate QP handle */\r
332         h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al, p_req->h_qp, AL_OBJ_TYPE_H_QP );\r
333         if( !h_qp )\r
334         {\r
335                 cl_status = CL_INVALID_HANDLE;\r
336                 goto exit;\r
337         }\r
338 \r
339         /* Check QP type */\r
340         if( h_qp->type != IB_QPT_RELIABLE_CONN )\r
341         {\r
342                 cl_status = CL_INVALID_HANDLE;\r
343                 goto err;\r
344         }\r
345 \r
346         /* Check psize */\r
347         if ( p_req->pdata_size > sizeof(p_req->pdata) )\r
348         {\r
349                 cl_status = CL_INVALID_PARAMETER;\r
350                 goto err;\r
351         }\r
352 \r
353         /* perform the ioctl */\r
354         cl_status = ndi_req_cm( p_context->h_al, h_ioctl );\r
355 \r
356 err:\r
357         deref_al_obj( &h_qp->obj );\r
358 \r
359 exit:\r
360         AL_EXIT( AL_DBG_NDI );\r
361         return cl_status;\r
362 }\r
363 \r
364 static cl_status_t\r
365 __ndi_rep_cm(\r
366         IN              void                                    *p_open_context,\r
367         IN              cl_ioctl_handle_t               h_ioctl,\r
368                 OUT     size_t                                  *p_ret_bytes )\r
369 {\r
370         cl_status_t cl_status;\r
371         ib_qp_handle_t h_qp = NULL;\r
372         al_dev_open_context_t *p_context;\r
373         ual_ndi_rep_cm_ioctl_in_t *p_rep = \r
374                 (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( h_ioctl );\r
375         UNUSED_PARAM(p_ret_bytes);\r
376 \r
377         AL_ENTER( AL_DBG_NDI );\r
378 \r
379         p_context = (al_dev_open_context_t*)p_open_context;\r
380 \r
381         /* Validate user parameters. */\r
382         if( (cl_ioctl_in_size( h_ioctl ) < sizeof(ual_ndi_rep_cm_ioctl_in_t)) )\r
383         {\r
384                 cl_status = CL_INVALID_PARAMETER;\r
385                 goto exit;\r
386         }\r
387 \r
388         AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,\r
389                 ("CID = %d\n", p_rep->cid) );\r
390 \r
391         /* Get and validate QP handle */\r
392         h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al, p_rep->h_qp, AL_OBJ_TYPE_H_QP );\r
393         if( !h_qp )\r
394         {\r
395                 cl_status = CL_INVALID_HANDLE;\r
396                 goto exit;\r
397         }\r
398 \r
399         if( h_qp->type != IB_QPT_RELIABLE_CONN )\r
400         {\r
401                 cl_status = CL_INVALID_HANDLE;\r
402                 goto err;\r
403         }\r
404 \r
405         /* Check psize */\r
406         if ( p_rep->pdata_size >= sizeof(p_rep->pdata) )\r
407         {\r
408                 cl_status = CL_INVALID_PARAMETER;\r
409                 goto err;\r
410         }\r
411 \r
412         /* perform the ioctls */\r
413         cl_status = ndi_rep_cm( p_context->h_al, h_ioctl );\r
414 \r
415 err:\r
416         deref_al_obj( &h_qp->obj );\r
417 \r
418 exit:\r
419         AL_EXIT( AL_DBG_NDI );\r
420         return cl_status;\r
421 }\r
422 \r
423 \r
424 static cl_status_t\r
425 __ndi_rej_cm(\r
426         IN              void                                    *p_open_context,\r
427         IN              cl_ioctl_handle_t               h_ioctl,\r
428                 OUT     size_t                                  *p_ret_bytes )\r
429 {\r
430         al_dev_open_context_t *p_context;\r
431         ib_api_status_t status;\r
432         ual_ndi_rej_cm_ioctl_in_t *p_rej = \r
433                 (ual_ndi_rej_cm_ioctl_in_t*)cl_ioctl_in_buf( h_ioctl );\r
434         NTSTATUS ntstatus;\r
435         UNUSED_PARAM(p_ret_bytes);\r
436 \r
437         AL_ENTER( AL_DBG_NDI );\r
438 \r
439         p_context = (al_dev_open_context_t*)p_open_context;\r
440 \r
441         /* Check psize */\r
442         if ( p_rej->pdata_size >= sizeof(p_rej->pdata) )\r
443         {\r
444                 ntstatus = CL_INVALID_PARAMETER;\r
445                 goto exit;\r
446         }\r
447 \r
448         /* perform the ioctl */\r
449         status = al_cep_rej( p_context->h_al, p_rej->cid, IB_REJ_USER_DEFINED,\r
450                 NULL, 0, p_rej->pdata, p_rej->pdata_size);\r
451         if (status != IB_SUCCESS)\r
452         {\r
453                 ntstatus = CL_INVALID_HANDLE;\r
454                 goto exit;\r
455         }\r
456 \r
457         ntstatus = STATUS_SUCCESS;\r
458 \r
459 exit:\r
460         AL_EXIT( AL_DBG_NDI );\r
461         return ntstatus;\r
462 }\r
463 \r
464 static cl_status_t\r
465 __ndi_rtu_cm(\r
466         IN              void                                    *p_open_context,\r
467         IN              cl_ioctl_handle_t               h_ioctl,\r
468                 OUT     size_t                                  *p_ret_bytes )\r
469 {\r
470         cl_status_t cl_status;\r
471         nd_csq_t* p_csq;\r
472         al_dev_open_context_t *p_context;\r
473 \r
474         UNUSED_PARAM(p_ret_bytes);\r
475         \r
476         AL_ENTER( AL_DBG_NDI );\r
477 \r
478         p_context = (al_dev_open_context_t*)p_open_context;\r
479 \r
480         /* Validate user parameters. */\r
481         if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )\r
482         {\r
483                 cl_status = CL_INVALID_PARAMETER;\r
484                 goto exit;\r
485         }\r
486 \r
487         p_csq = kal_cep_get_context(\r
488                 p_context->h_al,\r
489                 *(net32_t*)cl_ioctl_in_buf( h_ioctl ),\r
490                 nd_cm_handler,\r
491                 nd_csq_ref\r
492                 );\r
493         if( p_csq == NULL )\r
494         {\r
495                 cl_status = CL_INVALID_HANDLE;\r
496                 goto exit;\r
497         }\r
498 \r
499         /* perform the ioctl */\r
500         cl_status = ndi_rtu_cm( p_csq, h_ioctl );\r
501 \r
502         nd_csq_release( p_csq );\r
503 \r
504 exit:\r
505         AL_EXIT( AL_DBG_NDI );\r
506         return cl_status;\r
507 }\r
508 \r
509 static cl_status_t\r
510 __ndi_dreq_cm(\r
511         IN              void                                    *p_open_context,\r
512         IN              cl_ioctl_handle_t               h_ioctl,\r
513                 OUT     size_t                                  *p_ret_bytes )\r
514 {\r
515         cl_status_t cl_status;\r
516         nd_csq_t *p_csq;\r
517         al_dev_open_context_t *p_context;\r
518 \r
519         UNUSED_PARAM(p_ret_bytes);\r
520         \r
521         AL_ENTER( AL_DBG_NDI );\r
522 \r
523         p_context = (al_dev_open_context_t*)p_open_context;\r
524 \r
525         /* Validate user parameters. */\r
526         if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )\r
527         {\r
528                 cl_status = CL_INVALID_PARAMETER;\r
529                 goto exit;\r
530         }\r
531 \r
532         /* Validate CID */\r
533         p_csq = (nd_csq_t*)kal_cep_get_context(\r
534                 p_context->h_al,\r
535                 *(net32_t*)cl_ioctl_in_buf( h_ioctl ),\r
536                 nd_cm_handler,\r
537                 nd_csq_ref\r
538                 );\r
539 \r
540         if( p_csq == NULL )\r
541         {\r
542                 cl_status = CL_CONNECTION_INVALID;\r
543                 goto exit;\r
544         }\r
545 \r
546         /* perform the ioctl */\r
547         cl_status = ndi_dreq_cm( p_csq, h_ioctl );\r
548 \r
549         nd_csq_release( p_csq );\r
550 \r
551 exit:\r
552         AL_EXIT( AL_DBG_NDI );\r
553         return cl_status;\r
554 }\r
555 \r
556 static NTSTATUS\r
557 __ndi_notify_dreq_cm(\r
558         IN              void                                    *p_open_context,\r
559         IN              cl_ioctl_handle_t               h_ioctl,\r
560                 OUT     size_t                                  *p_ret_bytes )\r
561 {\r
562         NTSTATUS status;\r
563         nd_csq_t *p_csq;\r
564         al_dev_open_context_t *p_context;\r
565 \r
566         UNUSED_PARAM(p_ret_bytes);\r
567         \r
568         AL_ENTER( AL_DBG_NDI );\r
569 \r
570         p_context = (al_dev_open_context_t*)p_open_context;\r
571 \r
572         /* Validate user parameters. */\r
573         if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )\r
574         {\r
575                 status = STATUS_INVALID_PARAMETER;\r
576                 goto exit;\r
577         }\r
578 \r
579         /* Validate CID */\r
580         p_csq = (nd_csq_t*)kal_cep_get_context(\r
581                 p_context->h_al,\r
582                 *(net32_t*)cl_ioctl_in_buf( h_ioctl ),\r
583                 nd_cm_handler,\r
584                 nd_csq_ref\r
585                 );\r
586 \r
587         if( p_csq == NULL )\r
588         {\r
589                 status = STATUS_CONNECTION_INVALID;\r
590                 goto exit;\r
591         }\r
592 \r
593         /* perform the ioctl */\r
594         status = IoCsqInsertIrpEx(\r
595                 &p_csq->csq,\r
596                 h_ioctl,\r
597                 NULL,\r
598                 (VOID*)(ULONG_PTR)NDI_CM_CONNECTED_DREQ_RCVD\r
599                 );\r
600 \r
601         nd_csq_release( p_csq );\r
602 \r
603 exit:\r
604         AL_EXIT( AL_DBG_NDI );\r
605         return status;\r
606 }\r
607 \r
608 static cl_status_t\r
609 __ndi_cancel_cm_irps(\r
610         IN              void                                    *p_open_context,\r
611         IN              cl_ioctl_handle_t               h_ioctl,\r
612                 OUT     size_t                                  *p_ret_bytes )\r
613 {\r
614         nd_csq_t *p_csq;\r
615         al_dev_open_context_t *p_context;\r
616 \r
617         UNUSED_PARAM(p_ret_bytes);\r
618         \r
619         AL_ENTER( AL_DBG_NDI );\r
620 \r
621         p_context = (al_dev_open_context_t*)p_open_context;\r
622 \r
623         /* Validate user parameters. */\r
624         if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )\r
625         {\r
626                 AL_EXIT( AL_DBG_NDI );\r
627                 return STATUS_INVALID_PARAMETER;\r
628         }\r
629 \r
630         /* Validate CID */\r
631         p_csq = (nd_csq_t*)kal_cep_get_context(\r
632                 p_context->h_al,\r
633                 *(net32_t*)cl_ioctl_in_buf( h_ioctl ),\r
634                 nd_cm_handler,\r
635                 nd_csq_ref\r
636                 );\r
637 \r
638         if( p_csq == NULL )\r
639         {\r
640                 AL_EXIT( AL_DBG_NDI );\r
641                 return STATUS_UNSUCCESSFUL;\r
642         }\r
643 \r
644         /* perform the ioctl */\r
645         ndi_cancel_cm_irps( p_csq );\r
646         nd_csq_release( p_csq );\r
647 \r
648         AL_EXIT( AL_DBG_NDI );\r
649         return STATUS_SUCCESS;\r
650 }\r
651 \r
652 static cl_status_t\r
653 __ndi_listen_cm(\r
654         IN              void                                    *p_open_context,\r
655         IN              cl_ioctl_handle_t               h_ioctl,\r
656                 OUT     size_t                                  *p_ret_bytes )\r
657 {\r
658         al_dev_open_context_t *p_context;\r
659         ual_cep_listen_ioctl_t *p_listen = \r
660                 (ual_cep_listen_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
661         net32_t* p_cid =\r
662                 (net32_t*)cl_ioctl_out_buf( h_ioctl );\r
663 \r
664         AL_ENTER( AL_DBG_NDI );\r
665 \r
666         p_context = (al_dev_open_context_t*)p_open_context;\r
667 \r
668         /* Validate user parameters. */\r
669         if( cl_ioctl_in_size( h_ioctl ) < sizeof(*p_listen) ||\r
670                 cl_ioctl_out_size( h_ioctl ) != sizeof(*p_cid) )\r
671         {\r
672                 AL_EXIT( AL_DBG_NDI );\r
673                 return CL_INVALID_PARAMETER;\r
674         }\r
675 \r
676         /* Set the private data compare buffer to our kernel copy. */\r
677         if( p_listen->cep_listen.p_cmp_buf )\r
678                 p_listen->cep_listen.p_cmp_buf = p_listen->compare;\r
679 \r
680         AL_EXIT( AL_DBG_NDI );\r
681         return ndi_listen_cm( p_context->h_al, &p_listen->cep_listen, p_cid, p_ret_bytes );\r
682 }\r
683 \r
684 static cl_status_t\r
685 __ndi_get_req_cm(\r
686         IN              void                                    *p_open_context,\r
687         IN              cl_ioctl_handle_t               h_ioctl,\r
688                 OUT     size_t                                  *p_ret_bytes )\r
689 {\r
690         al_dev_open_context_t *p_context;\r
691         nd_csq_t *p_csq;\r
692         NTSTATUS status;\r
693 \r
694         AL_ENTER( AL_DBG_NDI );\r
695 \r
696         UNREFERENCED_PARAMETER( p_ret_bytes );\r
697 \r
698         p_context = (al_dev_open_context_t*)p_open_context;\r
699 \r
700         /* Validate user parameters. */\r
701         if( cl_ioctl_in_size( h_ioctl ) != sizeof(net32_t) ||\r
702                 cl_ioctl_out_size( h_ioctl ) != sizeof(net32_t) )\r
703         {\r
704                 AL_EXIT( AL_DBG_NDI );\r
705                 return CL_INVALID_PARAMETER;\r
706         }\r
707 \r
708         /* Validate CID */\r
709         p_csq = (nd_csq_t*)kal_cep_get_context(\r
710                 p_context->h_al,\r
711                 *(net32_t*)cl_ioctl_in_buf( h_ioctl ),\r
712                 nd_cm_handler,\r
713                 nd_csq_ref\r
714                 );\r
715 \r
716         if( p_csq == NULL )\r
717         {\r
718                 AL_EXIT( AL_DBG_NDI );\r
719                 return STATUS_UNSUCCESSFUL;\r
720         }\r
721 \r
722         status = ndi_get_req_cm( p_csq, h_ioctl );\r
723         nd_csq_release( p_csq );\r
724         AL_EXIT( AL_DBG_NDI );\r
725         return status;\r
726 }\r
727 \r
728 cl_status_t\r
729 ndi_ioctl(\r
730         IN              cl_ioctl_handle_t               h_ioctl,\r
731                 OUT     size_t                                  *p_ret_bytes )\r
732 {\r
733         cl_status_t                             cl_status;\r
734         IO_STACK_LOCATION               *p_io_stack;\r
735         void                                    *p_context;\r
736 \r
737         AL_ENTER( AL_DBG_NDI );\r
738 \r
739         p_io_stack = IoGetCurrentIrpStackLocation( h_ioctl );\r
740         p_context = p_io_stack->FileObject->FsContext;\r
741 \r
742         if( !p_context )\r
743         {\r
744                 AL_EXIT( AL_DBG_DEV );\r
745                 return CL_INVALID_PARAMETER;\r
746         }\r
747 \r
748         switch( cl_ioctl_ctl_code( h_ioctl ) )\r
749         {\r
750         case UAL_NDI_CREATE_CQ:\r
751                 cl_status = __ndi_create_cq( p_context, h_ioctl, p_ret_bytes );\r
752                 break;\r
753         case UAL_NDI_NOTIFY_CQ:\r
754                 cl_status = __ndi_notify_cq( p_context, h_ioctl, p_ret_bytes );\r
755                 break;\r
756         case UAL_NDI_CANCEL_CQ:\r
757                 cl_status = __ndi_cancel_cq( p_context, h_ioctl, p_ret_bytes );\r
758                 break;\r
759         case UAL_NDI_MODIFY_QP:\r
760                 cl_status = __ndi_modify_qp( p_context, h_ioctl, p_ret_bytes );\r
761                 break;\r
762         case UAL_NDI_REQ_CM:\r
763                 cl_status = __ndi_req_cm( p_context, h_ioctl, p_ret_bytes );\r
764                 break;\r
765         case UAL_NDI_REP_CM:\r
766                 cl_status = __ndi_rep_cm( p_context, h_ioctl, p_ret_bytes );\r
767                 break;\r
768         case UAL_NDI_RTU_CM:\r
769                 cl_status = __ndi_rtu_cm( p_context, h_ioctl, p_ret_bytes );\r
770                 break;\r
771         case UAL_NDI_REJ_CM:\r
772                 cl_status = __ndi_rej_cm( p_context, h_ioctl, p_ret_bytes );\r
773                 break;\r
774         case UAL_NDI_DREQ_CM:\r
775                 cl_status = __ndi_dreq_cm( p_context, h_ioctl, p_ret_bytes );\r
776                 break;\r
777     case UAL_NDI_NOOP:\r
778         IoMarkIrpPending( h_ioctl );\r
779         if( cl_ioctl_in_size( h_ioctl ) != 0 )\r
780             h_ioctl->IoStatus.Status = STATUS_TIMEOUT;\r
781         else\r
782             h_ioctl->IoStatus.Status = CL_SUCCESS;\r
783         h_ioctl->IoStatus.Information = 0;\r
784 \r
785                 AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,\r
786                         ("UAL_NDI_NOOP completed with %08x\n", h_ioctl->IoStatus.Status) );\r
787         IoCompleteRequest( h_ioctl, IO_NETWORK_INCREMENT );\r
788         cl_status = CL_PENDING;\r
789         break;\r
790         case UAL_NDI_NOTIFY_DREQ:\r
791                 cl_status = __ndi_notify_dreq_cm( p_context, h_ioctl, p_ret_bytes );\r
792                 break;\r
793         case UAL_NDI_CANCEL_CM_IRPS:\r
794                 cl_status = __ndi_cancel_cm_irps( p_context, h_ioctl, p_ret_bytes );\r
795                 break;\r
796         case UAL_NDI_LISTEN_CM:\r
797                 cl_status = __ndi_listen_cm( p_context, h_ioctl, p_ret_bytes );\r
798                 break;\r
799         case UAL_NDI_GET_REQ_CM:\r
800                 cl_status = __ndi_get_req_cm( p_context, h_ioctl, p_ret_bytes );\r
801                 break;\r
802         default:\r
803                 cl_status = CL_INVALID_PARAMETER;\r
804                 break;\r
805         }\r
806 \r
807         AL_EXIT( AL_DBG_NDI );\r
808         return cl_status;\r
809 }\r
810 \r