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