removed Revison keyword since ID keyword exists, deleted unused files
[mirror/winof/.git] / core / bus / kernel / bus_iou_mgr.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 \r
33 #include <iba/ib_types.h>\r
34 #include <complib/cl_async_proc.h>\r
35 #include <complib/cl_bus_ifc.h>\r
36 #include "ib_common.h"\r
37 #include "al_ca.h"\r
38 #include "al_mgr.h"\r
39 #include "bus_pnp.h"\r
40 #include "bus_iou_mgr.h"\r
41 #include <initguid.h>\r
42 #include <wdmguid.h>\r
43 #include "iba/iou_ifc.h"\r
44 \r
45 \r
46 /* {5A9649F4-0101-4a7c-8337-796C48082DA2} */\r
47 DEFINE_GUID(GUID_BUS_TYPE_IBA, \r
48 0x5a9649f4, 0x101, 0x4a7c, 0x83, 0x37, 0x79, 0x6c, 0x48, 0x8, 0x2d, 0xa2);\r
49 \r
50 \r
51 /*\r
52  * Size of device descriptions, in the format:\r
53  *      IBA\VxxxxxxPxxxxxxxxvxxxxxxxx\r
54  */\r
55 #define IOU_DEV_ID_SIZE         sizeof(L"IBA\\VxxxxxxPxxxxxxxxvxxxxxxxx")\r
56 #define IOU_HW_ID_SIZE          \\r
57         sizeof(L"IBA\\VxxxxxxPxxxxxxxxvxxxxxxxx\0IBA\\VxxxxxxPxxxxxxxx\0\0")\r
58 #define IOU_COMPAT_ID           L"IBA\\IB_IOU\0\0"\r
59 #define IOU_LOCATION_SIZE       \\r
60         sizeof(L"Chassis 0xxxxxxxxxxxxxxxxx, Slot xx")\r
61 \r
62 /*\r
63  * Device extension for IOU PDOs.\r
64  */\r
65 typedef struct _bus_iou_ext\r
66 {\r
67         bus_pdo_ext_t                   pdo;\r
68 \r
69         net64_t                                 chassis_guid;\r
70         uint8_t                                 slot;\r
71         net64_t                                 guid;\r
72         net32_t                                 vend_id;\r
73         net16_t                                 dev_id;\r
74         net32_t                                 revision;\r
75         char                                    desc[IB_NODE_DESCRIPTION_SIZE + 1];\r
76 \r
77         /* Number of references on the upper interface. */\r
78         atomic32_t                              n_ifc_ref;\r
79 \r
80 }       bus_iou_ext_t;\r
81 \r
82 \r
83 iou_mgr_t*                                              gp_iou_mgr = NULL;\r
84 \r
85 \r
86 /*\r
87  * Function prototypes.\r
88  */\r
89 void\r
90 destroying_iou_mgr(\r
91         IN                              cl_obj_t*                                       p_obj );\r
92 \r
93 void\r
94 free_iou_mgr(\r
95         IN                              cl_obj_t*                                       p_obj );\r
96 \r
97 ib_api_status_t\r
98 bus_reg_iou_pnp( void );\r
99 \r
100 ib_api_status_t\r
101 iou_mgr_pnp_cb(\r
102         IN                              ib_pnp_rec_t*                           p_pnp_rec );\r
103 \r
104 ib_api_status_t\r
105 iou_mgr_iou_add(\r
106         IN                              ib_pnp_iou_rec_t*                       p_pnp_rec );\r
107 \r
108 void\r
109 iou_mgr_iou_remove(\r
110         IN                              ib_pnp_iou_rec_t*                       p_pnp_rec );\r
111 \r
112 static NTSTATUS\r
113 iou_start(\r
114         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
115         IN                              IRP* const                                      p_irp, \r
116                 OUT                     cl_irp_action_t* const          p_action );\r
117 \r
118 static NTSTATUS\r
119 iou_query_remove(\r
120         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
121         IN                              IRP* const                                      p_irp, \r
122                 OUT                     cl_irp_action_t* const          p_action );\r
123 \r
124 static void\r
125 iou_release_resources(\r
126         IN                              DEVICE_OBJECT* const            p_dev_obj );\r
127 \r
128 static NTSTATUS\r
129 iou_remove(\r
130         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
131         IN                              IRP* const                                      p_irp, \r
132                 OUT                     cl_irp_action_t* const          p_action );\r
133 \r
134 static NTSTATUS\r
135 iou_surprise_remove(\r
136         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
137         IN                              IRP* const                                      p_irp, \r
138                 OUT                     cl_irp_action_t* const          p_action );\r
139 \r
140 static NTSTATUS\r
141 iou_query_capabilities(\r
142         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
143         IN                              IRP* const                                      p_irp, \r
144                 OUT                     cl_irp_action_t* const          p_action );\r
145 \r
146 static NTSTATUS\r
147 iou_query_target_relations(\r
148         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
149         IN                              IRP* const                                      p_irp, \r
150                 OUT                     cl_irp_action_t* const          p_action );\r
151 \r
152 static NTSTATUS\r
153 iou_query_device_id(\r
154         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
155         IN                              IRP* const                                      p_irp );\r
156 \r
157 static NTSTATUS\r
158 iou_query_hardware_ids(\r
159         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
160         IN                              IRP* const                                      p_irp );\r
161 \r
162 static NTSTATUS\r
163 iou_query_compatible_ids(\r
164         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
165         IN                              IRP* const                                      p_irp );\r
166 \r
167 static NTSTATUS\r
168 iou_query_unique_id(\r
169         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
170         IN                              IRP* const                                      p_irp );\r
171 \r
172 static NTSTATUS\r
173 iou_query_description(\r
174         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
175         IN                              IRP* const                                      p_irp );\r
176 \r
177 static NTSTATUS\r
178 iou_query_location(\r
179         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
180         IN                              IRP* const                                      p_irp );\r
181 \r
182 static NTSTATUS\r
183 iou_query_bus_info(\r
184         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
185         IN                              IRP* const                                      p_irp, \r
186                 OUT                     cl_irp_action_t* const          p_action );\r
187 \r
188 static NTSTATUS\r
189 iou_query_interface(\r
190         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
191         IN                              IRP* const                                      p_irp, \r
192                 OUT                     cl_irp_action_t* const          p_action );\r
193 \r
194 static NTSTATUS\r
195 iou_set_power(\r
196         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
197         IN                              IRP* const                                      p_irp,\r
198                 OUT                     cl_irp_action_t* const          p_action );\r
199 \r
200 \r
201 /* All PnP code is called at passive, so it can all be paged out. */\r
202 #ifdef ALLOC_PRAGMA\r
203 #pragma alloc_text (PAGE, iou_start)\r
204 #pragma alloc_text (PAGE, iou_query_remove)\r
205 #pragma alloc_text (PAGE, iou_release_resources)\r
206 #pragma alloc_text (PAGE, iou_remove)\r
207 #pragma alloc_text (PAGE, iou_surprise_remove)\r
208 #pragma alloc_text (PAGE, iou_query_capabilities)\r
209 #pragma alloc_text (PAGE, iou_query_target_relations)\r
210 #pragma alloc_text (PAGE, iou_query_device_id)\r
211 #pragma alloc_text (PAGE, iou_query_hardware_ids)\r
212 #pragma alloc_text (PAGE, iou_query_compatible_ids)\r
213 #pragma alloc_text (PAGE, iou_query_unique_id)\r
214 #pragma alloc_text (PAGE, iou_query_description)\r
215 #pragma alloc_text (PAGE, iou_query_location)\r
216 #pragma alloc_text (PAGE, iou_query_bus_info)\r
217 #pragma alloc_text (PAGE, iou_query_interface)\r
218 #pragma alloc_text (PAGE_PNP, iou_set_power)\r
219 #pragma alloc_text (PAGE, iou_mgr_iou_add)\r
220 #pragma alloc_text (PAGE, iou_mgr_iou_remove)\r
221 #endif\r
222 \r
223 \r
224 /*\r
225  * Global virtual function pointer tables shared between all \r
226  * instances of Port PDOs.\r
227  */\r
228 static const cl_vfptr_pnp_po_t          vfptr_iou_pnp = {\r
229         "IB IOU",\r
230         iou_start,\r
231         cl_irp_succeed,\r
232         cl_irp_succeed,\r
233         cl_irp_succeed,\r
234         iou_query_remove,\r
235         iou_release_resources,\r
236         iou_remove,\r
237         cl_irp_succeed,\r
238         iou_surprise_remove,\r
239         iou_query_capabilities,\r
240         cl_irp_complete,\r
241         cl_irp_complete,\r
242         cl_irp_succeed,\r
243         cl_irp_complete,\r
244         cl_irp_complete,\r
245         cl_irp_complete,\r
246         iou_query_target_relations,\r
247         cl_irp_complete,\r
248         cl_irp_complete,\r
249         cl_irp_complete,\r
250         iou_query_bus_info,\r
251         iou_query_interface,\r
252         cl_irp_complete,\r
253         cl_irp_complete,\r
254         cl_irp_complete,\r
255         cl_irp_complete,\r
256         cl_irp_succeed,                         // QueryPower\r
257         iou_set_power,                          // SetPower\r
258         cl_irp_unsupported,                     // PowerSequence\r
259         cl_irp_unsupported                      // WaitWake\r
260 };\r
261 \r
262 \r
263 static const cl_vfptr_query_txt_t               vfptr_iou_query_txt = {\r
264         iou_query_device_id,\r
265         iou_query_hardware_ids,\r
266         iou_query_compatible_ids,\r
267         iou_query_unique_id,\r
268         iou_query_description,\r
269         iou_query_location\r
270 };\r
271 \r
272 \r
273 /*\r
274  * Create the AL load service.\r
275  */\r
276 ib_api_status_t\r
277 create_iou_mgr(\r
278                 OUT                     iou_mgr_t** const                       pp_iou_mgr )\r
279 {\r
280         ib_api_status_t         status;\r
281         cl_status_t                     cl_status;\r
282 \r
283         BUS_ENTER( BUS_DBG_PNP );\r
284 \r
285         CL_ASSERT( !gp_iou_mgr );\r
286 \r
287         gp_iou_mgr = cl_zalloc( sizeof(iou_mgr_t) );\r
288         if( !gp_iou_mgr )\r
289         {\r
290                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
291                         ("Failed to allocate port manager.\n") );\r
292                 return IB_INSUFFICIENT_MEMORY;\r
293         }\r
294 \r
295         /* Construct the load service. */\r
296         cl_obj_construct( &gp_iou_mgr->obj, AL_OBJ_TYPE_LOADER );\r
297         cl_mutex_construct( &gp_iou_mgr->pdo_mutex );\r
298         cl_qlist_init( &gp_iou_mgr->iou_list );\r
299 \r
300         cl_status = cl_mutex_init( &gp_iou_mgr->pdo_mutex );\r
301         if( cl_status != CL_SUCCESS )\r
302         {\r
303                 free_iou_mgr( &gp_iou_mgr->obj );\r
304                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
305                         ("cl_mutex_init returned %s.\n", cl_status_text[cl_status]) );\r
306                 return ib_convert_cl_status( cl_status );\r
307         }\r
308 \r
309         /* Initialize the load service object. */\r
310         cl_status = cl_obj_init( &gp_iou_mgr->obj, CL_DESTROY_SYNC,\r
311                 destroying_iou_mgr, NULL, free_iou_mgr );\r
312         if( cl_status != CL_SUCCESS )\r
313         {\r
314                 free_iou_mgr( &gp_iou_mgr->obj );\r
315                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
316                         ("cl_obj_init returned %s.\n", cl_status_text[cl_status]) );\r
317                 return ib_convert_cl_status( cl_status );\r
318         }\r
319 \r
320         /* Register for port PnP events. */\r
321         status = bus_reg_iou_pnp();\r
322         if( status != IB_SUCCESS )\r
323         {\r
324                 cl_obj_destroy( &gp_iou_mgr->obj );\r
325                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
326                         ("ib_reg_pnp returned %s.\n", ib_get_err_str(status)) );\r
327                 return status;\r
328         }\r
329 \r
330         *pp_iou_mgr = gp_iou_mgr;\r
331 \r
332         BUS_EXIT( BUS_DBG_PNP );\r
333         return IB_SUCCESS;\r
334 }\r
335 \r
336 \r
337 /*\r
338  * Pre-destroy the load service.\r
339  */\r
340 void\r
341 destroying_iou_mgr(\r
342         IN                              cl_obj_t*                                       p_obj )\r
343 {\r
344         ib_api_status_t                 status;\r
345 \r
346         BUS_ENTER( BUS_DBG_PNP );\r
347 \r
348         CL_ASSERT( p_obj );\r
349         CL_ASSERT( gp_iou_mgr == PARENT_STRUCT( p_obj, iou_mgr_t, obj ) );\r
350         UNUSED_PARAM( p_obj );\r
351 \r
352         /* Deregister for port PnP events. */\r
353         if( gp_iou_mgr->h_pnp )\r
354         {\r
355                 status = ib_dereg_pnp( gp_iou_mgr->h_pnp,\r
356                         (ib_pfn_destroy_cb_t)cl_obj_deref );\r
357                 CL_ASSERT( status == IB_SUCCESS );\r
358         }\r
359         BUS_EXIT( BUS_DBG_PNP );\r
360 }\r
361 \r
362 \r
363 /*\r
364  * Free the load service.\r
365  */\r
366 void\r
367 free_iou_mgr(\r
368         IN                              cl_obj_t*                                       p_obj )\r
369 {\r
370         bus_pdo_ext_t   *p_ext;\r
371         cl_list_item_t  *p_list_item;\r
372 \r
373         BUS_ENTER( BUS_DBG_PNP );\r
374 \r
375         CL_ASSERT( p_obj );\r
376         CL_ASSERT( gp_iou_mgr == PARENT_STRUCT( p_obj, iou_mgr_t, obj ) );\r
377 \r
378         /*\r
379          * Mark all IPoIB PDOs as no longer present.  This will cause them\r
380          * to be removed when they process the IRP_MN_REMOVE_DEVICE.\r
381          */\r
382         p_list_item = cl_qlist_remove_head( &gp_iou_mgr->iou_list );\r
383         while( p_list_item != cl_qlist_end( &gp_iou_mgr->iou_list ) )\r
384         {\r
385                 p_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
386                 p_list_item = cl_qlist_remove_head( &gp_iou_mgr->iou_list );\r
387                 if( p_ext->cl_ext.pnp_state == SurpriseRemoved )\r
388                 {\r
389                         CL_ASSERT( !p_ext->b_present );\r
390                         p_ext->b_reported_missing = TRUE;\r
391                         continue;\r
392                 }\r
393                 if( p_ext->h_ca )\r
394                 {\r
395                         /* Invalidate bus relations for the HCA. */\r
396                         IoInvalidateDeviceRelations(\r
397                                 p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
398 \r
399                         /* Release the reference on the CA object. */\r
400                         deref_al_obj( &p_ext->h_ca->obj );\r
401                 }\r
402                 IoDeleteDevice( p_ext->cl_ext.p_self_do );\r
403         }\r
404 \r
405         cl_mutex_destroy( &gp_iou_mgr->pdo_mutex );\r
406         cl_obj_deinit( p_obj );\r
407         cl_free( gp_iou_mgr );\r
408         gp_iou_mgr = NULL;\r
409         BUS_EXIT( BUS_DBG_PNP );\r
410 }\r
411 \r
412 \r
413 /*\r
414  * Register the load service for the given PnP class events.\r
415  */\r
416 ib_api_status_t\r
417 bus_reg_iou_pnp( void )\r
418 {\r
419         ib_pnp_req_t                    pnp_req;\r
420         ib_api_status_t                 status;\r
421 \r
422         cl_memclr( &pnp_req, sizeof( ib_pnp_req_t ) );\r
423         pnp_req.pnp_class       = IB_PNP_IOU | IB_PNP_FLAG_REG_SYNC;\r
424         pnp_req.pnp_context = gp_iou_mgr;\r
425         pnp_req.pfn_pnp_cb      = iou_mgr_pnp_cb;\r
426 \r
427         status = ib_reg_pnp( gh_al, &pnp_req, &gp_iou_mgr->h_pnp );\r
428 \r
429         if( status == IB_SUCCESS )\r
430         {\r
431                 /* Reference the load service on behalf of the ib_reg_pnp call. */\r
432                 cl_obj_ref( &gp_iou_mgr->obj );\r
433         }\r
434 \r
435         return status;\r
436 }\r
437 \r
438 \r
439 /*\r
440  * Load service PnP event callback.\r
441  */\r
442 ib_api_status_t\r
443 iou_mgr_pnp_cb(\r
444         IN                              ib_pnp_rec_t*                           p_pnp_rec )\r
445 {\r
446         ib_api_status_t         status;\r
447 \r
448         BUS_ENTER( BUS_DBG_PNP );\r
449 \r
450         CL_ASSERT( p_pnp_rec );\r
451         CL_ASSERT( gp_iou_mgr == p_pnp_rec->pnp_context );\r
452 \r
453         switch( p_pnp_rec->pnp_event )\r
454         {\r
455         case IB_PNP_IOU_ADD:\r
456                 status = iou_mgr_iou_add( (ib_pnp_iou_rec_t*)p_pnp_rec );\r
457                 break;\r
458 \r
459         case IB_PNP_IOU_REMOVE:\r
460                 iou_mgr_iou_remove( (ib_pnp_iou_rec_t*)p_pnp_rec );\r
461 \r
462         default:\r
463                 status = IB_SUCCESS;\r
464                 break;\r
465         }\r
466         BUS_EXIT( BUS_DBG_PNP );\r
467         return status;\r
468 }\r
469 \r
470 \r
471 /*\r
472  * Called to get child relations for the bus root.\r
473  */\r
474 NTSTATUS\r
475 iou_mgr_get_bus_relations(\r
476         IN              const   net64_t                                         ca_guid,\r
477         IN                              IRP* const                                      p_irp )\r
478 {\r
479         NTSTATUS                        status;\r
480 \r
481         BUS_ENTER( BUS_DBG_PNP );\r
482 \r
483         cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
484         status = bus_get_relations( &gp_iou_mgr->iou_list, ca_guid, p_irp );\r
485         cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
486 \r
487         BUS_EXIT( BUS_DBG_PNP );\r
488         return status;\r
489 }\r
490 \r
491 \r
492 ib_api_status_t\r
493 iou_mgr_iou_add(\r
494         IN                              ib_pnp_iou_rec_t*                       p_pnp_rec )\r
495 {\r
496         NTSTATUS                status;\r
497         DEVICE_OBJECT   *p_pdo;\r
498         bus_iou_ext_t   *p_iou_ext;\r
499 \r
500         BUS_ENTER( BUS_DBG_PNP );\r
501 \r
502         /* Create the PDO for the new port device. */\r
503         status = IoCreateDevice( bus_globals.p_driver_obj, sizeof(bus_iou_ext_t),\r
504                 NULL, FILE_DEVICE_CONTROLLER, \r
505                 FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,\r
506                 FALSE, &p_pdo );\r
507         if( !NT_SUCCESS( status ) )\r
508         {\r
509                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
510                         ("IoCreateDevice returned %08x.\n", status) );\r
511                 return IB_ERROR;\r
512         }\r
513 \r
514         /* Initialize the device extension. */\r
515         cl_init_pnp_po_ext( p_pdo, NULL, p_pdo, bus_globals.dbg_lvl,\r
516                 &vfptr_iou_pnp, &vfptr_iou_query_txt );\r
517 \r
518         /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
519         p_pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
520         \r
521         p_iou_ext = p_pdo->DeviceExtension;\r
522         p_iou_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
523         p_iou_ext->pdo.p_parent_ext = bus_globals.p_bus_ext;\r
524         p_iou_ext->pdo.b_present = TRUE;\r
525         p_iou_ext->pdo.b_reported_missing = FALSE;\r
526 \r
527         p_iou_ext->guid = p_pnp_rec->pnp_rec.guid;\r
528         p_iou_ext->vend_id = cl_ntoh32( p_pnp_rec->vend_id );\r
529         if( p_iou_ext->vend_id == 0x00066a )\r
530                 p_iou_ext->dev_id = (net16_t)(p_pnp_rec->pnp_rec.guid >> 32) & 0x00FF;\r
531         else\r
532                 p_iou_ext->dev_id = cl_ntoh16( p_pnp_rec->dev_id );\r
533         p_iou_ext->revision = cl_ntoh32( p_pnp_rec->revision );\r
534         cl_memcpy( p_iou_ext->desc, p_pnp_rec->desc,\r
535                 IB_NODE_DESCRIPTION_SIZE + 1 );\r
536 \r
537         /* Cache the CA GUID. */\r
538         p_iou_ext->pdo.ca_guid = p_pnp_rec->ca_guid;\r
539 \r
540         /* Take a reference on the parent HCA. */\r
541         p_iou_ext->pdo.h_ca = acquire_ca( p_pnp_rec->ca_guid );\r
542         if( !p_iou_ext->pdo.h_ca )\r
543         {\r
544                 IoDeleteDevice( p_pdo );\r
545                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("acquire_ca failed to find CA.\n") );\r
546                 return IB_INVALID_GUID;\r
547         }\r
548 \r
549         /* Store the device extension in the PDO list for future queries. */\r
550         cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
551         cl_qlist_insert_tail( &gp_iou_mgr->iou_list,\r
552                 &p_iou_ext->pdo.list_item );\r
553         cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
554 \r
555         /*\r
556          * Set the context of the PNP event.  The context is passed in for future\r
557          * events on the same port.\r
558          */\r
559         p_pnp_rec->pnp_rec.context = p_iou_ext;\r
560 \r
561         /* Tell the PnP Manager to rescan for the HCA's bus relations. */\r
562         IoInvalidateDeviceRelations(\r
563                 p_iou_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
564 \r
565         /* Invalidate removal relations for the bus driver. */\r
566         IoInvalidateDeviceRelations(\r
567                 bus_globals.p_bus_ext->cl_ext.p_pdo, RemovalRelations );\r
568 \r
569         BUS_EXIT( BUS_DBG_PNP );\r
570 \r
571         return IB_SUCCESS;\r
572 }\r
573 \r
574 \r
575 void\r
576 iou_mgr_iou_remove(\r
577         IN                              ib_pnp_iou_rec_t*                       p_pnp_rec )\r
578 {\r
579         bus_pdo_ext_t   *p_ext;\r
580 \r
581         BUS_ENTER( BUS_DBG_PNP );\r
582 \r
583         /* The PNP record's context is the port extension. */\r
584         p_ext = p_pnp_rec->pnp_rec.context;\r
585         CL_ASSERT( p_ext );\r
586 \r
587         /*\r
588          * Flag the port PDO as no longer being present.  We have to wait until\r
589          * the PnP manager removes it to clean up.  However, we do release the\r
590          * reference on the CA object in order to allow the removal of the HCA\r
591          * to proceed should it occur before the port's PDO is cleaned up.\r
592          */\r
593         cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
594         p_ext->b_present = FALSE;\r
595 \r
596         /* Invalidate removal relations for the bus driver. */\r
597         IoInvalidateDeviceRelations( bus_globals.p_bus_ext->cl_ext.p_pdo,\r
598                 RemovalRelations );\r
599 \r
600         /* Invalidate bus relations for the HCA. */\r
601         IoInvalidateDeviceRelations(\r
602                 p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
603 \r
604         deref_al_obj( &p_ext->h_ca->obj );\r
605         p_ext->h_ca = NULL;\r
606         cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
607 \r
608         BUS_EXIT( BUS_DBG_PNP );\r
609 }\r
610 \r
611 \r
612 static NTSTATUS\r
613 iou_start(\r
614         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
615         IN                                      IRP* const                              p_irp, \r
616                 OUT                             cl_irp_action_t* const  p_action )\r
617 {\r
618         bus_pdo_ext_t   *p_ext;\r
619 \r
620         BUS_ENTER( BUS_DBG_PNP );\r
621 \r
622         UNUSED_PARAM( p_irp );\r
623 \r
624         p_ext = p_dev_obj->DeviceExtension;\r
625 \r
626         /* Notify the Power Manager that the device is started. */\r
627         PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
628 \r
629         *p_action = IrpComplete;\r
630         BUS_EXIT( BUS_DBG_PNP );\r
631         return STATUS_SUCCESS;\r
632 }\r
633 \r
634 \r
635 static NTSTATUS\r
636 iou_query_remove(\r
637         IN                              DEVICE_OBJECT* const    p_dev_obj,\r
638         IN                              IRP* const                              p_irp, \r
639                 OUT                     cl_irp_action_t* const  p_action )\r
640 {\r
641         bus_iou_ext_t   *p_ext;\r
642 \r
643         BUS_ENTER( BUS_DBG_PNP );\r
644 \r
645         UNUSED_PARAM( p_irp );\r
646 \r
647         p_ext = p_dev_obj->DeviceExtension;\r
648 \r
649         *p_action = IrpComplete;\r
650         if( p_ext->n_ifc_ref )\r
651         {\r
652                 /*\r
653                  * Our interface is still being held by someone.\r
654                  * Rollback the PnP state that was changed in the complib handler.\r
655                  */\r
656                 cl_rollback_pnp_state( &p_ext->pdo.cl_ext );\r
657 \r
658                 /* Fail the query. */\r
659                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Failing IRP_MN_QUERY_REMOVE_DEVICE:\n"\r
660                         "\tInterface has %d reference\n", p_ext->n_ifc_ref ) );\r
661                 return STATUS_UNSUCCESSFUL;\r
662         }\r
663 \r
664         BUS_EXIT( BUS_DBG_PNP );\r
665         return STATUS_SUCCESS;\r
666 }\r
667 \r
668 \r
669 static void\r
670 iou_release_resources(\r
671         IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
672 {\r
673         bus_iou_ext_t   *p_ext;\r
674         POWER_STATE             po_state;\r
675 \r
676         BUS_ENTER( BUS_DBG_PNP );\r
677 \r
678         p_ext = p_dev_obj->DeviceExtension;\r
679 \r
680         /* Remove this PDO from its list. */\r
681         cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
682         BUS_TRACE( BUS_DBG_PNP, ("Removing IOU from list.\n") );\r
683         cl_qlist_remove_item( &gp_iou_mgr->iou_list, &p_ext->pdo.list_item );\r
684         cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
685         po_state.DeviceState = PowerDeviceD3;\r
686         PoSetPowerState( p_ext->pdo.cl_ext.p_pdo, DevicePowerState, po_state );\r
687 \r
688         BUS_EXIT( BUS_DBG_PNP );\r
689 }\r
690 \r
691 \r
692 static NTSTATUS\r
693 iou_remove(\r
694         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
695         IN                                      IRP* const                              p_irp, \r
696                 OUT                             cl_irp_action_t* const  p_action )\r
697 {\r
698         bus_iou_ext_t   *p_ext;\r
699 \r
700         BUS_ENTER( BUS_DBG_PNP );\r
701 \r
702         p_ext = p_dev_obj->DeviceExtension;\r
703 \r
704         if( p_ext->pdo.b_present )\r
705         {\r
706                 CL_ASSERT( p_ext->pdo.cl_ext.pnp_state != NotStarted );\r
707                 CL_ASSERT( !p_ext->pdo.b_reported_missing );\r
708                 /* Reset the state to NotStarted.  CompLib set it to Deleted. */\r
709                 cl_set_pnp_state( &p_ext->pdo.cl_ext, NotStarted );\r
710                 /* Don't delete the device.  It may simply be disabled. */\r
711                 *p_action = IrpComplete;\r
712                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Device still present.\n") );\r
713                 return STATUS_SUCCESS;\r
714         }\r
715 \r
716         if( !p_ext->pdo.b_reported_missing )\r
717         {\r
718                 /* Reset the state to RemovePending.  Complib set it to Deleted. */\r
719                 cl_rollback_pnp_state( &p_ext->pdo.cl_ext );\r
720                 *p_action = IrpComplete;\r
721                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Device not reported missing yet.\n") );\r
722                 return STATUS_SUCCESS;\r
723         }\r
724 \r
725         /* Wait for all I/O operations to complete. */\r
726         IoReleaseRemoveLockAndWait( &p_ext->pdo.cl_ext.remove_lock, p_irp );\r
727 \r
728         /* Release resources if it was not done yet. */\r
729         if( p_ext->pdo.cl_ext.last_pnp_state != SurpriseRemoved )\r
730                 p_ext->pdo.cl_ext.vfptr_pnp_po->pfn_release_resources( p_dev_obj );\r
731 \r
732         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
733         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
734 \r
735         IoDeleteDevice( p_dev_obj );\r
736 \r
737         *p_action = IrpDoNothing;\r
738         BUS_EXIT( BUS_DBG_PNP );\r
739         return STATUS_SUCCESS;\r
740 }\r
741 \r
742 \r
743 static NTSTATUS\r
744 iou_surprise_remove(\r
745         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
746         IN                              IRP* const                                      p_irp, \r
747                 OUT                     cl_irp_action_t* const          p_action )\r
748 {\r
749         bus_iou_ext_t   *p_ext;\r
750 \r
751         BUS_ENTER( BUS_DBG_PNP );\r
752 \r
753         UNUSED_PARAM( p_irp );\r
754 \r
755         p_ext = p_dev_obj->DeviceExtension;\r
756         p_ext->pdo.b_present = FALSE;\r
757         p_ext->pdo.b_reported_missing = TRUE;\r
758 \r
759         *p_action = IrpComplete;\r
760 \r
761         BUS_EXIT( BUS_DBG_PNP );\r
762         return STATUS_SUCCESS;\r
763 }\r
764 \r
765 \r
766 static NTSTATUS\r
767 iou_query_capabilities(\r
768         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
769         IN                                      IRP* const                              p_irp, \r
770                 OUT                             cl_irp_action_t* const  p_action )\r
771 {\r
772         DEVICE_CAPABILITIES             *p_caps;\r
773         IO_STACK_LOCATION               *p_io_stack;\r
774 \r
775         BUS_ENTER( BUS_DBG_PNP );\r
776 \r
777         UNUSED_PARAM( p_dev_obj );\r
778 \r
779         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
780         p_caps = p_io_stack->Parameters.DeviceCapabilities.Capabilities;\r
781 \r
782         p_caps->DeviceD1 = FALSE;\r
783         p_caps->DeviceD2 = FALSE;\r
784         p_caps->LockSupported = FALSE;\r
785         p_caps->EjectSupported = FALSE;\r
786         p_caps->Removable = TRUE;\r
787         p_caps->DockDevice = FALSE;\r
788         p_caps->UniqueID = TRUE;\r
789         p_caps->SilentInstall = TRUE;\r
790         p_caps->RawDeviceOK = FALSE;\r
791         p_caps->SurpriseRemovalOK = FALSE;\r
792         p_caps->WakeFromD0 = FALSE;\r
793         p_caps->WakeFromD1 = FALSE;\r
794         p_caps->WakeFromD2 = FALSE;\r
795         p_caps->WakeFromD3 = FALSE;\r
796         p_caps->HardwareDisabled = FALSE;\r
797         p_caps->DeviceState[PowerSystemWorking] = PowerDeviceD0;\r
798         p_caps->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;\r
799         p_caps->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;\r
800         p_caps->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;\r
801         p_caps->DeviceState[PowerSystemHibernate] = PowerDeviceD3;\r
802         p_caps->DeviceState[PowerSystemShutdown] = PowerDeviceD3;\r
803         p_caps->SystemWake = PowerSystemUnspecified;\r
804         p_caps->DeviceWake = PowerDeviceUnspecified;\r
805         p_caps->D1Latency = 0;\r
806         p_caps->D2Latency = 0;\r
807         p_caps->D3Latency = 0;\r
808 \r
809         *p_action = IrpComplete;\r
810         BUS_EXIT( BUS_DBG_PNP );\r
811         return STATUS_SUCCESS;\r
812 }\r
813 \r
814 \r
815 static NTSTATUS\r
816 iou_query_target_relations(\r
817         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
818         IN                                      IRP* const                              p_irp, \r
819                 OUT                             cl_irp_action_t* const  p_action )\r
820 {\r
821         NTSTATUS                        status;\r
822         DEVICE_RELATIONS        *p_rel;\r
823 \r
824         BUS_ENTER( BUS_DBG_PNP );\r
825 \r
826         *p_action = IrpComplete;\r
827 \r
828         status = cl_alloc_relations( p_irp, 1 );\r
829         if( !NT_SUCCESS( status ) )\r
830         {\r
831                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
832                         ("cl_alloc_relations returned 0x%08x.\n", status) );\r
833                 return status;\r
834         }\r
835 \r
836         p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
837         p_rel->Count = 1;\r
838         p_rel->Objects[0] = p_dev_obj;\r
839 \r
840         ObReferenceObject( p_dev_obj );\r
841 \r
842         BUS_EXIT( BUS_DBG_PNP );\r
843         return status;\r
844 }\r
845 \r
846 \r
847 static NTSTATUS\r
848 iou_query_device_id(\r
849         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
850                 OUT                             IRP* const                              p_irp )\r
851 {\r
852         NTSTATUS                        status;\r
853         bus_iou_ext_t           *p_ext;\r
854         WCHAR                           *p_string;\r
855 \r
856         BUS_ENTER( BUS_DBG_PNP );\r
857 \r
858         p_ext = (bus_iou_ext_t*)p_dev_obj->DeviceExtension;\r
859         if( !p_ext->pdo.b_present )\r
860         {\r
861                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
862                 return STATUS_NO_SUCH_DEVICE;\r
863         }\r
864 \r
865         /* Device ID is "IBA\SID_<sid> where <sid> is the IPoIB Service ID. */\r
866         p_string = ExAllocatePool( PagedPool, IOU_DEV_ID_SIZE );\r
867         if( !p_string )\r
868         {\r
869                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
870                         ("Failed to allocate device ID buffer (%d bytes).\n",\r
871                         IOU_DEV_ID_SIZE) );\r
872                 return STATUS_INSUFFICIENT_RESOURCES;\r
873         }\r
874 \r
875         status =\r
876                 RtlStringCbPrintfW( p_string, IOU_DEV_ID_SIZE, L"IBA\\V%06xP%08xv%08x",\r
877                         p_ext->vend_id, p_ext->dev_id, p_ext->revision );\r
878         if( !NT_SUCCESS( status ) )\r
879         {\r
880                 ExFreePool( p_string );\r
881                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
882                         ("Failed to format device ID string.\n") );\r
883                 return status;\r
884         }\r
885         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
886 \r
887         BUS_EXIT( BUS_DBG_PNP );\r
888         return STATUS_SUCCESS;\r
889 }\r
890 \r
891 \r
892 static NTSTATUS\r
893 iou_query_hardware_ids(\r
894         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
895                 OUT                             IRP* const                              p_irp )\r
896 {\r
897         NTSTATUS                        status;\r
898         bus_iou_ext_t           *p_ext;\r
899         WCHAR                           *p_string, *p_start;\r
900         size_t                          size;\r
901 \r
902         BUS_ENTER( BUS_DBG_PNP );\r
903 \r
904         p_ext = (bus_iou_ext_t*)p_dev_obj->DeviceExtension;\r
905         if( !p_ext->pdo.b_present )\r
906         {\r
907                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
908                 return STATUS_NO_SUCH_DEVICE;\r
909         }\r
910 \r
911         p_string = ExAllocatePool( PagedPool, IOU_HW_ID_SIZE );\r
912         if( !p_string )\r
913         {\r
914                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
915                         ("Failed to allocate hardware ID buffer (%d bytes).\n",\r
916                         IOU_HW_ID_SIZE) );\r
917                 return STATUS_INSUFFICIENT_RESOURCES;\r
918         }\r
919 \r
920         p_start = p_string;\r
921         size = IOU_HW_ID_SIZE;\r
922         /* Fill in the first HW ID. */\r
923         status = RtlStringCbPrintfExW( p_start, size, &p_start, &size,\r
924                 STRSAFE_FILL_BEHIND_NULL, L"IBA\\V%06xP%04xv%08x",\r
925                 p_ext->vend_id, p_ext->dev_id, p_ext->revision );\r
926         if( !NT_SUCCESS( status ) )\r
927         {\r
928                 ExFreePool( p_string );\r
929                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
930                         ("Failed to format device ID string.\n") );\r
931                 return status;\r
932         }\r
933         /* Fill in the second HW ID. */\r
934         CL_ASSERT( *p_start == L'\0' );\r
935         p_start++;\r
936         size -= sizeof(WCHAR);\r
937         status = RtlStringCbPrintfExW( p_start, size, NULL, NULL,\r
938                 STRSAFE_FILL_BEHIND_NULL, L"IBA\\V%06xP%04x",\r
939                 p_ext->vend_id, p_ext->dev_id );\r
940         if( !NT_SUCCESS( status ) )\r
941         {\r
942                 ExFreePool( p_string );\r
943                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
944                         ("Failed to format device ID string.\n") );\r
945                 return status;\r
946         }\r
947         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
948 \r
949         BUS_EXIT( BUS_DBG_PNP );\r
950         return STATUS_SUCCESS;\r
951 }\r
952 \r
953 \r
954 static NTSTATUS\r
955 iou_query_compatible_ids(\r
956         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
957                 OUT                             IRP* const                              p_irp )\r
958 {\r
959         WCHAR                           *p_string;\r
960 \r
961         BUS_ENTER( BUS_DBG_PNP );\r
962 \r
963         UNUSED_PARAM( p_dev_obj );\r
964 \r
965         p_string = ExAllocatePool( PagedPool, sizeof(IOU_COMPAT_ID) );\r
966         if( !p_string )\r
967         {\r
968                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
969                         ("Failed to allocate compatible ID buffer (%d bytes).\n",\r
970                         IOU_HW_ID_SIZE) );\r
971                 return STATUS_INSUFFICIENT_RESOURCES;\r
972         }\r
973 \r
974         cl_memcpy( p_string, IOU_COMPAT_ID, sizeof(IOU_COMPAT_ID) );\r
975         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
976 \r
977         BUS_EXIT( BUS_DBG_PNP );\r
978         return STATUS_SUCCESS;\r
979 }\r
980 \r
981 \r
982 static NTSTATUS\r
983 iou_query_unique_id(\r
984         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
985                 OUT                             IRP* const                              p_irp )\r
986 {\r
987         NTSTATUS                        status;\r
988         WCHAR                           *p_string;\r
989         bus_iou_ext_t           *p_ext;\r
990 \r
991         BUS_ENTER( BUS_DBG_PNP );\r
992         \r
993         p_ext = p_dev_obj->DeviceExtension;\r
994         if( !p_ext->pdo.b_present )\r
995         {\r
996                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
997                 return STATUS_NO_SUCH_DEVICE;\r
998         }\r
999 \r
1000         /* The instance ID is the port GUID. */\r
1001         p_string = ExAllocatePool( PagedPool, sizeof(WCHAR) * 33 );\r
1002         if( !p_string )\r
1003         {\r
1004                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
1005                         ("Failed to allocate instance ID buffer (%d bytes).\n",\r
1006                         sizeof(WCHAR) * 17) );\r
1007                 return STATUS_NO_MEMORY;\r
1008         }\r
1009 \r
1010         status = RtlStringCchPrintfW( p_string, 33, L"%016I64x%016I64x",\r
1011                 p_ext->guid, p_ext->pdo.ca_guid );\r
1012         if( !NT_SUCCESS( status ) )\r
1013         {\r
1014                 CL_ASSERT( NT_SUCCESS( status ) );\r
1015                 ExFreePool( p_string );\r
1016                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1017                         ("RtlStringCchPrintfW returned %08x.\n", status) );\r
1018                 return status;\r
1019         }\r
1020 \r
1021         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1022 \r
1023         BUS_EXIT( BUS_DBG_PNP );\r
1024         return STATUS_SUCCESS;\r
1025 }\r
1026 \r
1027 \r
1028 static NTSTATUS\r
1029 iou_query_description(\r
1030         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1031                 OUT                             IRP* const                              p_irp )\r
1032 {\r
1033         NTSTATUS                        status;\r
1034         WCHAR                           *p_string;\r
1035         bus_iou_ext_t           *p_ext;\r
1036 \r
1037         BUS_ENTER( BUS_DBG_PNP );\r
1038         \r
1039         p_ext = p_dev_obj->DeviceExtension;\r
1040         if( !p_ext->pdo.b_present )\r
1041         {\r
1042                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
1043                 return STATUS_NO_SUCH_DEVICE;\r
1044         }\r
1045 \r
1046         /* The instance ID is the port GUID. */\r
1047         p_string =\r
1048                 ExAllocatePool( PagedPool, sizeof(WCHAR) * sizeof(p_ext->desc) );\r
1049         if( !p_string )\r
1050         {\r
1051                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
1052                         ("Failed to allocate device description buffer (%d bytes).\n",\r
1053                         sizeof(WCHAR) * sizeof(p_ext->desc)) );\r
1054                 return STATUS_INSUFFICIENT_RESOURCES;\r
1055         }\r
1056 \r
1057         status = RtlStringCchPrintfW( p_string, sizeof(p_ext->desc),\r
1058                 L"%S", p_ext->desc );\r
1059         if( !NT_SUCCESS( status ) )\r
1060         {\r
1061                 CL_ASSERT( NT_SUCCESS( status ) );\r
1062                 ExFreePool( p_string );\r
1063                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1064                         ("RtlStringCchPrintfW returned %08x.\n", status) );\r
1065                 return status;\r
1066         }\r
1067         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1068 \r
1069         BUS_EXIT( BUS_DBG_PNP );\r
1070         return STATUS_SUCCESS;\r
1071 }\r
1072 \r
1073 \r
1074 static NTSTATUS\r
1075 iou_query_location(\r
1076         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1077                 OUT                             IRP* const                              p_irp )\r
1078 {\r
1079         NTSTATUS                        status;\r
1080         bus_iou_ext_t           *p_ext;\r
1081         WCHAR                           *p_string;\r
1082 \r
1083         BUS_ENTER( BUS_DBG_PNP );\r
1084 \r
1085         p_ext = (bus_iou_ext_t*)p_dev_obj->DeviceExtension;\r
1086         if( !p_ext->pdo.b_present )\r
1087         {\r
1088                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
1089                 return STATUS_NO_SUCH_DEVICE;\r
1090         }\r
1091 \r
1092         p_string = ExAllocatePool( PagedPool, IOU_LOCATION_SIZE );\r
1093         if( !p_string )\r
1094         {\r
1095                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
1096                         ("Failed to allocate location buffer (%d bytes).\n",\r
1097                         IOU_LOCATION_SIZE) );\r
1098                 return STATUS_INSUFFICIENT_RESOURCES;\r
1099         }\r
1100 \r
1101         status = RtlStringCbPrintfW( p_string, IOU_LOCATION_SIZE,\r
1102                 L"Chassis 0x%016I64x, Slot %d", p_ext->chassis_guid, p_ext->slot );\r
1103         if( !NT_SUCCESS( status ) )\r
1104         {\r
1105                 ExFreePool( p_string );\r
1106                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1107                         ("Failed to format device ID string.\n") );\r
1108                 return status;\r
1109         }\r
1110         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1111 \r
1112         BUS_EXIT( BUS_DBG_PNP );\r
1113         return STATUS_SUCCESS;\r
1114 }\r
1115 \r
1116 \r
1117 static NTSTATUS\r
1118 iou_query_bus_info(\r
1119         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1120         IN                                      IRP* const                              p_irp, \r
1121                 OUT                             cl_irp_action_t* const  p_action )\r
1122 {\r
1123         PNP_BUS_INFORMATION     *p_bus_info;\r
1124 \r
1125         BUS_ENTER( BUS_DBG_PNP );\r
1126 \r
1127         UNUSED_PARAM( p_dev_obj );\r
1128 \r
1129         *p_action = IrpComplete;\r
1130 \r
1131         p_bus_info = ExAllocatePool( PagedPool, sizeof(PNP_BUS_INFORMATION) );\r
1132         if( !p_bus_info )\r
1133         {\r
1134                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1135                         ("Failed to allocate PNP_BUS_INFORMATION (%d bytes).\n",\r
1136                         sizeof(PNP_BUS_INFORMATION)) );\r
1137                 return STATUS_INSUFFICIENT_RESOURCES;\r
1138         }\r
1139 \r
1140         p_bus_info->BusTypeGuid = GUID_BUS_TYPE_IBA;\r
1141         //TODO: Memory from Intel - storage miniport would not stay loaded unless\r
1142         //TODO: bus type was PCI.  Look here if SRP is having problems staying\r
1143         //TODO: loaded.\r
1144         p_bus_info->LegacyBusType = PNPBus;\r
1145         p_bus_info->BusNumber = 0;\r
1146 \r
1147         p_irp->IoStatus.Information = (ULONG_PTR)p_bus_info;\r
1148         BUS_EXIT( BUS_DBG_PNP );\r
1149         return STATUS_SUCCESS;\r
1150 }\r
1151 \r
1152 \r
1153 static NTSTATUS\r
1154 iou_query_iou_ifc(\r
1155         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1156         IN                              IO_STACK_LOCATION* const        p_io_stack )\r
1157 {\r
1158         NTSTATUS                                status;\r
1159         ib_al_ifc_t                             *p_ifc;\r
1160         ib_al_ifc_data_t                *p_ifc_data;\r
1161         iou_ifc_data_t                  *p_iou_data;\r
1162         bus_iou_ext_t                   *p_ext;\r
1163         const GUID                              *p_guid;\r
1164 \r
1165         BUS_ENTER( BUS_DBG_PNP );\r
1166 \r
1167         CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
1168 \r
1169         p_ext = p_dev_obj->DeviceExtension;\r
1170 \r
1171         /* Get the interface. */\r
1172         status = cl_fwd_query_ifc(\r
1173                 p_ext->pdo.p_parent_ext->cl_ext.p_self_do, p_io_stack );\r
1174         if( !NT_SUCCESS( status ) )\r
1175         {\r
1176                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1177                         ("Failed to forward interface query: %08X\n", status) );\r
1178                 return status;\r
1179         }\r
1180 \r
1181         if( !p_io_stack->Parameters.QueryInterface.InterfaceSpecificData )\r
1182         {\r
1183                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("No interface specific data!\n") );\r
1184                 return status;\r
1185         }\r
1186 \r
1187         p_ifc = (ib_al_ifc_t*)p_io_stack->Parameters.QueryInterface.Interface;\r
1188 \r
1189         p_ifc_data = (ib_al_ifc_data_t*)\r
1190                 p_io_stack->Parameters.QueryInterface.InterfaceSpecificData;\r
1191         p_guid = p_ifc_data->type;\r
1192         if( !IsEqualGUID( p_guid, &GUID_IOU_INTERFACE_DATA ) )\r
1193         {\r
1194                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Unsupported interface data: \n\t"\r
1195                         "0x%08x, 0x%04x, 0x%04x, 0x%02x, 0x%02x, 0x%02x,"\r
1196                         "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n",\r
1197                         p_guid->Data1, p_guid->Data2, p_guid->Data3,\r
1198                         p_guid->Data4[0], p_guid->Data4[1], p_guid->Data4[2],\r
1199                         p_guid->Data4[3], p_guid->Data4[4], p_guid->Data4[5],\r
1200                         p_guid->Data4[6], p_guid->Data4[7]) );\r
1201                 return status;\r
1202         }\r
1203 \r
1204         if( p_ifc_data->version != IOU_INTERFACE_DATA_VERSION )\r
1205         {\r
1206                 p_ifc->wdm.InterfaceDereference( p_ifc->wdm.Context );\r
1207                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1208                         ("Unsupported version %d, expected %d\n",\r
1209                         p_ifc_data->version, IOU_INTERFACE_DATA_VERSION) );\r
1210                 return STATUS_NOT_SUPPORTED;\r
1211         }\r
1212 \r
1213         ASSERT( p_ifc_data->p_data );\r
1214 \r
1215         if( p_ifc_data->size != sizeof(iou_ifc_data_t) )\r
1216         {\r
1217                 p_ifc->wdm.InterfaceDereference( p_ifc->wdm.Context );\r
1218                 BUS_TRACE_EXIT( BUS_DBG_PNP,\r
1219                         ("Buffer too small (%d given, %d required).\n",\r
1220                         p_ifc_data->size,\r
1221                         sizeof(iou_ifc_data_t)) );\r
1222                 return STATUS_BUFFER_TOO_SMALL;\r
1223         }\r
1224 \r
1225         /* Set the interface data. */\r
1226         p_iou_data = (iou_ifc_data_t*)p_ifc_data->p_data;\r
1227 \r
1228         p_iou_data->ca_guid = p_ext->pdo.ca_guid;\r
1229         p_iou_data->chassis_guid = p_ext->chassis_guid;\r
1230         p_iou_data->slot = p_ext->slot;\r
1231         p_iou_data->guid = p_ext->guid;\r
1232 \r
1233         BUS_EXIT( BUS_DBG_PNP );\r
1234         return STATUS_SUCCESS;\r
1235 }\r
1236 \r
1237 \r
1238 static NTSTATUS\r
1239 iou_query_interface(\r
1240         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1241         IN                                      IRP* const                              p_irp, \r
1242                 OUT                             cl_irp_action_t* const  p_action )\r
1243 {\r
1244         bus_pdo_ext_t           *p_ext;\r
1245         NTSTATUS                        status;\r
1246         IO_STACK_LOCATION       *p_io_stack;\r
1247 \r
1248         BUS_ENTER( BUS_DBG_PNP );\r
1249 \r
1250         CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
1251 \r
1252         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1253         \r
1254         /* Bottom of the stack - IRP must be completed. */\r
1255         *p_action = IrpComplete;\r
1256 \r
1257         /* Compare requested GUID with our supported interface GUIDs. */\r
1258         if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
1259                 &GUID_IB_AL_INTERFACE ) )\r
1260         {\r
1261                 status = iou_query_iou_ifc( p_dev_obj, p_io_stack );\r
1262         }\r
1263         else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
1264                 &GUID_BUS_INTERFACE_STANDARD ) )\r
1265         {\r
1266                 p_ext = p_dev_obj->DeviceExtension;\r
1267                 status = cl_fwd_query_ifc(\r
1268                         p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, p_io_stack );\r
1269         }\r
1270         else\r
1271         {\r
1272                 status = p_irp->IoStatus.Status;\r
1273         }\r
1274 \r
1275         BUS_EXIT( BUS_DBG_PNP );\r
1276         return status;\r
1277 }\r
1278 \r
1279 \r
1280 /*\r
1281  * The PDOs created by the IB Bus driver are software devices.  As such,\r
1282  * all power states are supported.  It is left to the HCA power policy \r
1283  * owner to handle which states can be supported by the HCA.\r
1284  */\r
1285 static NTSTATUS\r
1286 iou_set_power(\r
1287         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1288         IN                              IRP* const                                      p_irp,\r
1289                 OUT                     cl_irp_action_t* const          p_action )\r
1290 {\r
1291         IO_STACK_LOCATION       *p_io_stack;\r
1292         bus_pdo_ext_t           *p_ext;\r
1293 \r
1294         BUS_ENTER( BUS_DBG_POWER );\r
1295 \r
1296         p_ext = p_dev_obj->DeviceExtension;\r
1297         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1298 \r
1299         if( p_io_stack->Parameters.Power.Type == DevicePowerState )\r
1300         {\r
1301                 /* Notify the power manager. */\r
1302                 p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
1303                 PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
1304         }\r
1305 \r
1306         *p_action = IrpComplete;\r
1307         BUS_EXIT( BUS_DBG_POWER );\r
1308         return STATUS_SUCCESS;\r
1309 }\r