[CORE] Expose vendor defined device in ibiou.
[mirror/winof/.git] / core / iou / kernel / iou_ioc_mgr.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\r
8  *     Redistribution and use in source and binary forms, with or\r
9  *     without modification, are permitted provided that the following\r
10  *     conditions are met:\r
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\r
16  *      - Redistributions in binary form must reproduce the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer in the documentation and/or other materials\r
19  *        provided with the distribution.\r
20  *\r
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
28  * SOFTWARE.\r
29  *\r
30  * $Id$\r
31  */\r
32 \r
33 \r
34 \r
35 #include <iba/ib_types.h>\r
36 #include <complib/cl_async_proc.h>\r
37 #include <complib/cl_bus_ifc.h>\r
38 #include "iou_driver.h"\r
39 #if defined(EVENT_TRACING)\r
40 #ifdef offsetof\r
41 #undef offsetof\r
42 #endif\r
43 #include "iou_ioc_mgr.tmh"\r
44 #endif\r
45 #include "iou_pnp.h"\r
46 #include "iou_ioc_mgr.h"\r
47 #include <initguid.h>\r
48 #include <wdmguid.h>\r
49 #include "iba/ioc_ifc.h"\r
50 \r
51 \r
52 /* {5A9649F4-0101-4a7c-8337-796C48082DA2} */\r
53 DEFINE_GUID(GUID_BUS_TYPE_IBA,\r
54 0x5a9649f4, 0x101, 0x4a7c, 0x83, 0x37, 0x79, 0x6c, 0x48, 0x8, 0x2d, 0xa2);\r
55 \r
56 \r
57 /*\r
58  * Size of device descriptions, as defined in\r
59  *      A1.2.3.1.1 - Creating Compatibility Strings for an I/O Controller\r
60  */\r
61 #define IOC_DEV_ID_SIZE         \\r
62         sizeof(L"IBA\\VxxxxxxPxxxxxxxxSxxxxxxsxxxxxxxxvxxxx")\r
63 #define IOC_HW_ID_SIZE          \\r
64         sizeof(L"IBA\\VxxxxxxPxxxxxxxxSxxxxxxsxxxxxxxxvxxxx") + \\r
65         sizeof(L"IBA\\VxxxxxxPxxxxxxxxSxxxxxxsxxxxxxxx") + \\r
66         sizeof(L"IBA\\VxxxxxxPxxxxxxxxvxxxx") + \\r
67         sizeof(L"IBA\\VxxxxxxPxxxxxxxx\0\0")\r
68 #define IOC_COMPAT_ID_SIZE      \\r
69         sizeof(L"IBA\\Cxxxxcxxxxpxxxxrxxxx") + \\r
70         sizeof(L"IBA\\Cxxxxcxxxxpxxxx\0\0")\r
71 #define IOC_LOCATION_SIZE       \\r
72         sizeof(L"Chassis 0xxxxxxxxxxxxxxxxx, Slot xx, IOC xx")\r
73 \r
74 /*\r
75  * Device extension for IOU PDOs.\r
76  */\r
77 typedef struct _ioc_ext\r
78 {\r
79         iou_pdo_ext_t                   pdo;\r
80 \r
81         ib_ioc_info_t                   info;\r
82         ib_svc_entry_t                  svc_entries[1];\r
83 \r
84 }       ioc_ext_t;\r
85 \r
86 \r
87 /*\r
88  * Function prototypes.\r
89  */\r
90 void\r
91 destroying_ioc_mgr(\r
92         IN                              cl_obj_t*                                       p_obj );\r
93 \r
94 void\r
95 free_ioc_mgr(\r
96         IN                              cl_obj_t*                                       p_obj );\r
97 \r
98 ib_api_status_t\r
99 ioc_mgr_pnp_cb(\r
100         IN                              ib_pnp_rec_t*                           p_pnp_rec );\r
101 \r
102 ib_api_status_t\r
103 ioc_mgr_ioc_add(\r
104         IN                              ib_pnp_ioc_rec_t*                       p_pnp_rec );\r
105 \r
106 void\r
107 ioc_mgr_ioc_remove(\r
108         IN                              ib_pnp_ioc_rec_t*                       p_pnp_rec );\r
109 \r
110 static NTSTATUS\r
111 ioc_start(\r
112         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
113         IN                              IRP* const                                      p_irp,\r
114                 OUT                     cl_irp_action_t* const          p_action );\r
115 \r
116 static void\r
117 ioc_release_resources(\r
118         IN                              DEVICE_OBJECT* const            p_dev_obj );\r
119 \r
120 static NTSTATUS\r
121 ioc_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 NTSTATUS\r
127 ioc_surprise_remove(\r
128         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
129         IN                              IRP* const                                      p_irp,\r
130                 OUT                     cl_irp_action_t* const          p_action );\r
131 \r
132 static NTSTATUS\r
133 ioc_query_capabilities(\r
134         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
135         IN                              IRP* const                                      p_irp,\r
136                 OUT                     cl_irp_action_t* const          p_action );\r
137 \r
138 static NTSTATUS\r
139 ioc_query_target_relations(\r
140         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
141         IN                              IRP* const                                      p_irp,\r
142                 OUT                     cl_irp_action_t* const          p_action );\r
143 \r
144 static NTSTATUS\r
145 ioc_query_device_id(\r
146         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
147         IN                              IRP* const                                      p_irp );\r
148 \r
149 static NTSTATUS\r
150 ioc_query_hardware_ids(\r
151         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
152         IN                              IRP* const                                      p_irp );\r
153 \r
154 static NTSTATUS\r
155 ioc_query_compatible_ids(\r
156         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
157         IN                              IRP* const                                      p_irp );\r
158 \r
159 static NTSTATUS\r
160 ioc_query_unique_id(\r
161         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
162         IN                              IRP* const                                      p_irp );\r
163 \r
164 static NTSTATUS\r
165 ioc_query_description(\r
166         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
167         IN                              IRP* const                                      p_irp );\r
168 \r
169 static NTSTATUS\r
170 ioc_query_location(\r
171         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
172         IN                              IRP* const                                      p_irp );\r
173 \r
174 static NTSTATUS\r
175 ioc_query_bus_info(\r
176         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
177         IN                              IRP* const                                      p_irp,\r
178                 OUT                     cl_irp_action_t* const          p_action );\r
179 \r
180 static NTSTATUS\r
181 ioc_query_interface(\r
182         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
183         IN                              IRP* const                                      p_irp,\r
184                 OUT                     cl_irp_action_t* const          p_action );\r
185 \r
186 static NTSTATUS\r
187 ioc_set_power(\r
188         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
189         IN                              IRP* const                                      p_irp,\r
190                 OUT                     cl_irp_action_t* const          p_action );\r
191 \r
192 \r
193 \r
194 /*\r
195  * Global virtual function pointer tables shared between all\r
196  * instances of Port PDOs.\r
197  */\r
198 static const cl_vfptr_pnp_po_t          vfptr_ioc_pnp = {\r
199         "IB IOC",\r
200         ioc_start,\r
201         cl_irp_succeed,\r
202         cl_irp_succeed,\r
203         cl_irp_succeed,\r
204         cl_irp_succeed,\r
205         ioc_release_resources,\r
206         ioc_remove,\r
207         cl_irp_succeed,\r
208         ioc_surprise_remove,\r
209         ioc_query_capabilities,\r
210         cl_irp_complete,\r
211         cl_irp_complete,\r
212         cl_irp_succeed,\r
213         cl_irp_complete,\r
214         cl_irp_complete,\r
215         cl_irp_complete,\r
216         ioc_query_target_relations,\r
217         cl_irp_complete,\r
218         cl_irp_complete,\r
219         cl_irp_complete,\r
220         ioc_query_bus_info,\r
221         ioc_query_interface,\r
222         cl_irp_complete,\r
223         cl_irp_complete,\r
224         cl_irp_complete,\r
225         cl_irp_complete,\r
226         cl_irp_succeed,                         // QueryPower\r
227         ioc_set_power,                          // SetPower\r
228         cl_irp_unsupported,                     // PowerSequence\r
229         cl_irp_unsupported                      // WaitWake\r
230 };\r
231 \r
232 \r
233 static const cl_vfptr_query_txt_t               vfptr_iou_query_txt = {\r
234         ioc_query_device_id,\r
235         ioc_query_hardware_ids,\r
236         ioc_query_compatible_ids,\r
237         ioc_query_unique_id,\r
238         ioc_query_description,\r
239         ioc_query_location\r
240 };\r
241 \r
242 \r
243 void\r
244 ioc_mgr_construct(\r
245         IN      OUT                     ioc_mgr_t* const                        p_ioc_mgr )\r
246 {\r
247         IOU_ENTER( IOU_DBG_PNP );\r
248 \r
249         /* Construct the IOC manager service. */\r
250         cl_obj_construct( &p_ioc_mgr->obj, 0 );\r
251         cl_mutex_construct( &p_ioc_mgr->pdo_mutex );\r
252         cl_qlist_init( &p_ioc_mgr->pdo_list );\r
253 \r
254         IOU_EXIT( IOU_DBG_PNP );\r
255 }\r
256 \r
257 \r
258 ib_api_status_t\r
259 ioc_mgr_init(\r
260         IN      OUT                     ioc_mgr_t* const                        p_ioc_mgr )\r
261 {\r
262         ib_pnp_req_t            pnp_req;\r
263         ib_api_status_t         status;\r
264         cl_status_t                     cl_status;\r
265 \r
266         IOU_ENTER( IOU_DBG_PNP );\r
267 \r
268         cl_status = cl_mutex_init( &p_ioc_mgr->pdo_mutex );\r
269         if( cl_status != CL_SUCCESS )\r
270         {\r
271                 free_ioc_mgr( &p_ioc_mgr->obj );\r
272                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
273                         ("cl_mutex_init returned %#x.\n", cl_status) );\r
274                 return IB_ERROR;\r
275         }\r
276 \r
277         cl_status = cl_mutex_init( &p_ioc_mgr->pdo_mutex );\r
278         if( cl_status != CL_SUCCESS )\r
279         {\r
280                 free_ioc_mgr( &p_ioc_mgr->obj );\r
281                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
282                         ("cl_mutex_init returned %#x.\n", cl_status) );\r
283                 return IB_ERROR;\r
284         }       \r
285 \r
286         /* Initialize the load service object. */\r
287         cl_status = cl_obj_init( &p_ioc_mgr->obj, CL_DESTROY_SYNC,\r
288                 destroying_ioc_mgr, NULL, free_ioc_mgr );\r
289         if( cl_status != CL_SUCCESS )\r
290         {\r
291                 free_ioc_mgr( &p_ioc_mgr->obj );\r
292                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
293                         ("cl_obj_init returned %#x.\n", cl_status) );\r
294                 return IB_ERROR;\r
295         }\r
296 \r
297         status = p_ioc_mgr->ifc.open_al( &p_ioc_mgr->h_al );\r
298         if( status != IB_SUCCESS )\r
299         {\r
300                 cl_obj_destroy( &p_ioc_mgr->obj );\r
301                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
302                         ("open_al returned %s.\n",\r
303                         p_ioc_mgr->ifc.get_err_str(status)) );\r
304                 return status;\r
305         }\r
306 \r
307         /* Register for IOC PnP events. */\r
308         cl_memclr( &pnp_req, sizeof( ib_pnp_req_t ) );\r
309         pnp_req.pnp_class       = IB_PNP_IOC;\r
310         pnp_req.pnp_context = p_ioc_mgr;\r
311         pnp_req.pfn_pnp_cb      = ioc_mgr_pnp_cb;\r
312 \r
313         status = p_ioc_mgr->ifc.reg_pnp(\r
314                 p_ioc_mgr->h_al, &pnp_req, &p_ioc_mgr->h_pnp );\r
315         if( status != IB_SUCCESS )\r
316         {\r
317                 cl_obj_destroy( &p_ioc_mgr->obj );\r
318                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
319                         ("ib_reg_pnp returned %s.\n",\r
320                         p_ioc_mgr->ifc.get_err_str(status)) );\r
321                 return status;\r
322         }\r
323 \r
324         /* Reference the load service on behalf of the ib_reg_pnp call. */\r
325         cl_obj_ref( &p_ioc_mgr->obj );\r
326 \r
327         IOU_EXIT( IOU_DBG_PNP );\r
328         return IB_SUCCESS;\r
329 }\r
330 \r
331 \r
332 /*\r
333  * Pre-destroy the load service.\r
334  */\r
335 void\r
336 destroying_ioc_mgr(\r
337         IN                              cl_obj_t*                                       p_obj )\r
338 {\r
339         ioc_mgr_t                               *p_ioc_mgr;\r
340         ib_api_status_t                 status;\r
341 \r
342         IOU_ENTER( IOU_DBG_PNP );\r
343 \r
344         CL_ASSERT( p_obj );\r
345 \r
346         p_ioc_mgr = PARENT_STRUCT( p_obj, ioc_mgr_t, obj );\r
347 \r
348         /* Deregister for port PnP events. */\r
349         if( p_ioc_mgr->h_pnp )\r
350         {\r
351                 status = p_ioc_mgr->ifc.dereg_pnp(\r
352                         p_ioc_mgr->h_pnp, (ib_pfn_destroy_cb_t)cl_obj_deref );\r
353                 CL_ASSERT( status == IB_SUCCESS );\r
354         }\r
355         IOU_EXIT( IOU_DBG_PNP );\r
356 }\r
357 \r
358 \r
359 /*\r
360  * Free the load service.\r
361  */\r
362 void\r
363 free_ioc_mgr(\r
364         IN                              cl_obj_t*                                       p_obj )\r
365 {\r
366         ioc_mgr_t               *p_ioc_mgr;\r
367         ioc_ext_t               *p_iou_ext;\r
368         cl_list_item_t  *p_list_item;\r
369 \r
370         IOU_ENTER( IOU_DBG_PNP );\r
371 \r
372         CL_ASSERT( p_obj );\r
373         p_ioc_mgr = PARENT_STRUCT( p_obj, ioc_mgr_t, obj );\r
374 \r
375         /*\r
376          * Mark all IOCs as no longer present.  This will cause them\r
377          * to be removed when they process the IRP_MN_REMOVE_DEVICE.\r
378          */\r
379         p_list_item = cl_qlist_remove_head( &p_ioc_mgr->pdo_list );\r
380         while( p_list_item != cl_qlist_end( &p_ioc_mgr->pdo_list ) )\r
381         {\r
382                 p_iou_ext = PARENT_STRUCT(\r
383                         PARENT_STRUCT( p_list_item, iou_pdo_ext_t, list_item ),\r
384                         ioc_ext_t, pdo );\r
385                 p_list_item = cl_qlist_remove_head( &p_ioc_mgr->pdo_list );\r
386                 if( p_iou_ext->pdo.cl_ext.pnp_state == SurpriseRemoved )\r
387                 {\r
388                         CL_ASSERT( !p_iou_ext->pdo.b_present );\r
389                         p_iou_ext->pdo.b_reported_missing = TRUE;\r
390                         continue;\r
391                 }\r
392                 IoDeleteDevice( p_iou_ext->pdo.cl_ext.p_self_do );\r
393         }\r
394 \r
395         cl_mutex_destroy( &p_ioc_mgr->pdo_mutex );\r
396         cl_obj_deinit( p_obj );\r
397         IOU_EXIT( IOU_DBG_PNP );\r
398 }\r
399 \r
400 \r
401 /*\r
402  * Load service PnP event callback.\r
403  */\r
404 ib_api_status_t\r
405 ioc_mgr_pnp_cb(\r
406         IN                              ib_pnp_rec_t*                           p_pnp_rec )\r
407 {\r
408         ib_api_status_t         status;\r
409         ioc_mgr_t                       *p_ioc_mgr;\r
410 \r
411         IOU_ENTER( IOU_DBG_PNP );\r
412 \r
413         CL_ASSERT( p_pnp_rec );\r
414         p_ioc_mgr = (ioc_mgr_t*)p_pnp_rec->pnp_context;\r
415 \r
416         switch( p_pnp_rec->pnp_event )\r
417         {\r
418         case IB_PNP_IOC_ADD:\r
419                 status = ioc_mgr_ioc_add( (ib_pnp_ioc_rec_t*)p_pnp_rec );\r
420                 break;\r
421 \r
422         case IB_PNP_IOC_REMOVE:\r
423                 ioc_mgr_ioc_remove( (ib_pnp_ioc_rec_t*)p_pnp_rec );\r
424 \r
425         default:\r
426                 status = IB_SUCCESS;\r
427                 break;\r
428         }\r
429         IOU_EXIT( IOU_DBG_PNP );\r
430         return status;\r
431 }\r
432 \r
433 \r
434 /*\r
435  * Called to get child relations for the bus root.\r
436  */\r
437 NTSTATUS\r
438 ioc_mgr_get_iou_relations(\r
439         IN                              ioc_mgr_t* const                        p_ioc_mgr,\r
440         IN                              IRP* const                                      p_irp )\r
441 {\r
442         NTSTATUS                        status;\r
443         size_t                          n_devs;\r
444         DEVICE_RELATIONS        *p_rel;\r
445 \r
446         IOU_ENTER( IOU_DBG_PNP );\r
447 \r
448         /* If there are already relations, copy them. */\r
449         cl_mutex_acquire( &p_ioc_mgr->pdo_mutex );\r
450         n_devs = cl_qlist_count( &p_ioc_mgr->pdo_list );        \r
451         if( !n_devs )\r
452         {\r
453                 cl_mutex_release( &p_ioc_mgr->pdo_mutex );\r
454                 IOU_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IOU_DBG_PNP,\r
455                         ("No child PDOs.\n") );\r
456                 return STATUS_NO_SUCH_DEVICE;\r
457         }\r
458 \r
459         /* Add space for our child IOUs. */\r
460         status = cl_alloc_relations( p_irp, n_devs );\r
461         if( !NT_SUCCESS( status ) )\r
462         {\r
463                 cl_mutex_release( &p_ioc_mgr->pdo_mutex );\r
464                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
465                         ("cl_alloc_relations returned %08x.\n", status) );\r
466                 return status;\r
467         }\r
468 \r
469         p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
470         update_relations( &p_ioc_mgr->pdo_list, p_rel );\r
471         cl_mutex_release( &p_ioc_mgr->pdo_mutex );\r
472         IOU_EXIT( IOU_DBG_PNP );\r
473         return STATUS_SUCCESS;\r
474 }\r
475 \r
476 BOOLEAN is_vnic_profile_ioc(ib_ioc_profile_t    *p_profile)\r
477 {\r
478         BOOLEAN b_vnic = FALSE;\r
479 \r
480         if( ib_ioc_profile_get_vend_id( p_profile ) == 0x00066a &&\r
481                 p_profile->dev_id == CL_HTON32(0x00000030) ) \r
482         {\r
483 \r
484                 b_vnic = TRUE;\r
485         }\r
486 \r
487         return b_vnic;\r
488         \r
489 }\r
490 \r
491 ib_api_status_t\r
492 ioc_mgr_ioc_add(\r
493         IN                              ib_pnp_ioc_rec_t*                       p_pnp_rec )\r
494 {\r
495         NTSTATUS                status;\r
496         DEVICE_OBJECT   *p_pdo = NULL;\r
497         iou_fdo_ext_t   *p_ext;\r
498         ioc_mgr_t               *p_ioc_mgr;\r
499         ioc_ext_t               *p_ioc_ext;\r
500         uint32_t                ext_size;\r
501         child_device_info_list_t *pCurList;\r
502         BOOLEAN                 b_vnic_ioc = FALSE;\r
503         ca_ioc_map_t            *p_map = NULL;\r
504 \r
505         IOU_ENTER( IOU_DBG_PNP );\r
506 \r
507         p_ioc_mgr = PARENT_STRUCT( p_pnp_rec->pnp_rec.pnp_context, ioc_mgr_t, obj );\r
508         p_ext = PARENT_STRUCT( p_ioc_mgr, iou_fdo_ext_t, ioc_mgr );\r
509 \r
510         if( p_pnp_rec->ca_guid != p_ioc_mgr->info.ca_guid ||\r
511                 p_pnp_rec->info.chassis_guid != p_ioc_mgr->info.chassis_guid ||\r
512                 p_pnp_rec->info.chassis_slot != p_ioc_mgr->info.slot||\r
513                 p_pnp_rec->info.iou_guid != p_ioc_mgr->info.guid )\r
514         {\r
515                 IOU_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IOU_DBG_PNP,\r
516                         ("IOC not in this IOU.\n") );\r
517                 return IB_NOT_DONE;\r
518         }\r
519 \r
520         p_map = cl_zalloc(sizeof(ca_ioc_map_t));\r
521 \r
522         if ( !p_map ) \r
523         {\r
524                 IOU_PRINT_EXIT(TRACE_LEVEL_INFORMATION, IOU_DBG_PNP, \r
525                                 (" Insufficient Memory.\n" ));\r
526                 return IB_INSUFFICIENT_MEMORY;\r
527         }\r
528 \r
529         p_map->ca_guid = p_pnp_rec->ca_guid;\r
530         p_map->info = p_pnp_rec->info;\r
531         p_map->p_ioc_mgr = p_ioc_mgr;\r
532         cl_memcpy( p_map->svc_entry_array, p_pnp_rec->svc_entry_array,\r
533                         p_pnp_rec->info.profile.num_svc_entries );\r
534 \r
535         cl_mutex_acquire(&iou_globals.list_mutex);\r
536         cl_qlist_insert_tail( &iou_globals.ca_ioc_map_list, &p_map->ioc_list);\r
537         cl_mutex_release( &iou_globals.list_mutex );\r
538 \r
539         b_vnic_ioc = is_vnic_profile_ioc( &p_pnp_rec->info.profile );\r
540         pCurList = iou_globals.p_device_list;\r
541 \r
542         if ( b_vnic_ioc && !pCurList ) \r
543         {\r
544                 IOU_PRINT_EXIT(TRACE_LEVEL_INFORMATION, IOU_DBG_PNP, \r
545                                 ("There is no device list for VNIC IOCs\n"));\r
546                 return IB_NOT_DONE;\r
547         }\r
548 \r
549         ext_size = sizeof(ioc_ext_t) +\r
550                 (sizeof(ib_svc_entry_t) * p_pnp_rec->info.profile.num_svc_entries);\r
551 \r
552         do\r
553         {\r
554                 if ( b_vnic_ioc ) \r
555                 {\r
556                         if ( p_pnp_rec->ca_guid != \r
557                                 pCurList->io_device_info.ca_ioc_path.ca_guid ||\r
558                                 p_pnp_rec->info.profile.ioc_guid != \r
559                                 pCurList->io_device_info.ca_ioc_path.info.profile.ioc_guid)\r
560                         {\r
561                                 pCurList = pCurList->next_device_info;\r
562                                 continue;\r
563                         }\r
564                 }\r
565         /* Create the PDO for the new port device. */\r
566         status = IoCreateDevice( iou_globals.p_driver_obj, ext_size,\r
567                 NULL, FILE_DEVICE_CONTROLLER,\r
568                 FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,\r
569                 FALSE, &p_pdo );\r
570         if( !NT_SUCCESS( status ) )\r
571         {\r
572                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
573                         ("IoCreateDevice returned %08x.\n", status) );\r
574                 return IB_ERROR;\r
575         }\r
576 \r
577         /* Initialize the device extension. */\r
578         cl_init_pnp_po_ext( p_pdo, NULL, p_pdo, g_iou_dbg_flags,\r
579                 &vfptr_ioc_pnp, &vfptr_iou_query_txt );\r
580 \r
581         /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
582         p_pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
583 \r
584         p_ioc_ext = p_pdo->DeviceExtension;\r
585         p_ioc_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
586         p_ioc_ext->pdo.p_parent_ext = p_ext;\r
587         p_ioc_ext->pdo.b_present = TRUE;\r
588         p_ioc_ext->pdo.b_reported_missing = FALSE;\r
589         p_ioc_ext->pdo.ca_guid = p_pnp_rec->ca_guid;\r
590                 \r
591 \r
592                 if ( b_vnic_ioc ) \r
593                 {\r
594                         p_ioc_ext->pdo.p_pdo_device_info = &pCurList->io_device_info;\r
595                 }\r
596 \r
597                 \r
598         /* Copy the IOC profile and service entries. */\r
599         p_ioc_ext->info = p_pnp_rec->info;\r
600         cl_memcpy( p_ioc_ext->svc_entries, p_pnp_rec->svc_entry_array,\r
601                 p_pnp_rec->info.profile.num_svc_entries );\r
602         /* Make sure the IOC string is null terminated. */\r
603         p_ioc_ext->info.profile.id_string[CTRL_ID_STRING_LEN-1] = '\0';\r
604 \r
605         /* Store the device extension in the PDO list for future queries. */\r
606         cl_mutex_acquire( &p_ioc_mgr->pdo_mutex );\r
607                 cl_qlist_insert_tail( &p_ioc_mgr->pdo_list,\r
608                 &p_ioc_ext->pdo.list_item );\r
609         cl_mutex_release( &p_ioc_mgr->pdo_mutex );\r
610 \r
611                 IoInvalidateDeviceRelations( p_ext->cl_ext.p_pdo, BusRelations );\r
612 \r
613                 if ( b_vnic_ioc ) \r
614                 {\r
615                         pCurList = pCurList->next_device_info;\r
616                 } \r
617                 else \r
618                 {\r
619                         break;\r
620                 }\r
621 \r
622 \r
623         } while( pCurList );\r
624 \r
625         /*\r
626          * Set the context of the PNP event.  The context is passed in for future\r
627          * events on the same port.\r
628          */\r
629 \r
630         //p_pnp_rec->pnp_rec.context = p_ioc_ext;\r
631         /* Tell the PnP Manager to rescan for bus relations. */\r
632 \r
633         IOU_EXIT( IOU_DBG_PNP );\r
634         return IB_SUCCESS;\r
635 }\r
636 \r
637 \r
638 ca_ioc_map_t    *find_ca_ioc_map(net64_t        ca_guid,\r
639                                  ib_net64_t     ioc_guid/*ib_pnp_ioc_rec_t      *p_pnp_rec*/)\r
640 {\r
641         cl_list_item_t  *list_item;\r
642         ca_ioc_map_t    *p_map = NULL;\r
643 \r
644         cl_mutex_acquire( &iou_globals.list_mutex );\r
645 \r
646         list_item = cl_qlist_head( &iou_globals.ca_ioc_map_list );\r
647 \r
648         while( list_item != cl_qlist_end( &iou_globals.ca_ioc_map_list ) ) \r
649         {\r
650                 p_map = ( ca_ioc_map_t * ) list_item;\r
651                 if ( p_map->ca_guid != ca_guid || \r
652                     p_map->info.profile.ioc_guid != ioc_guid )\r
653                 {\r
654 \r
655                         list_item = cl_qlist_next( list_item );\r
656                         continue;\r
657                 }\r
658                 break;\r
659         }\r
660 \r
661         if ( list_item == cl_qlist_end( &iou_globals.ca_ioc_map_list ) )\r
662                 p_map = NULL;\r
663 \r
664         cl_mutex_release( &iou_globals.list_mutex );\r
665         return p_map;\r
666 }\r
667 \r
668 void\r
669 ioc_mgr_ioc_remove(\r
670         IN                              ib_pnp_ioc_rec_t*                       p_pnp_rec )\r
671 {\r
672         ioc_mgr_t       *p_ioc_mgr;\r
673         ioc_ext_t       *p_ioc_ext;\r
674         iou_pdo_ext_t   *p_iou_pdo_ext;\r
675 \r
676         ca_ioc_map_t    *p_map;\r
677         cl_list_item_t  *list_item;\r
678 \r
679         IOU_ENTER( IOU_DBG_PNP );\r
680 \r
681         p_ioc_mgr = PARENT_STRUCT( p_pnp_rec->pnp_rec.pnp_context, ioc_mgr_t, obj );\r
682 \r
683         p_map = find_ca_ioc_map( p_pnp_rec->ca_guid, \r
684                                 p_pnp_rec->info.profile.ioc_guid );\r
685 \r
686         if ( p_map ) \r
687         {\r
688                 cl_mutex_acquire( &iou_globals.list_mutex );\r
689                 cl_qlist_remove_item( &iou_globals.ca_ioc_map_list, &p_map->ioc_list );\r
690                 cl_mutex_release( &iou_globals.list_mutex );\r
691                 cl_free(p_map);\r
692         } \r
693 \r
694         list_item = cl_qlist_head(&p_ioc_mgr->pdo_list); \r
695 \r
696         while ( list_item != cl_qlist_end(&p_ioc_mgr->pdo_list) )\r
697         {\r
698                 p_iou_pdo_ext = PARENT_STRUCT(list_item, iou_pdo_ext_t, list_item);\r
699                 p_ioc_ext = PARENT_STRUCT(p_iou_pdo_ext, ioc_ext_t, pdo);\r
700 \r
701                 if ( p_pnp_rec->ca_guid != p_ioc_ext->pdo.ca_guid ||\r
702                     p_pnp_rec->info.profile.ioc_guid != \r
703                     p_ioc_ext->info.profile.ioc_guid ) \r
704                 {\r
705                         list_item = cl_qlist_next( list_item );\r
706                         continue;\r
707                 }\r
708         cl_mutex_acquire( &p_ioc_mgr->pdo_mutex );\r
709         p_ioc_ext->pdo.b_present = FALSE;\r
710                 cl_mutex_release( &p_ioc_mgr->pdo_mutex );\r
711 \r
712                 list_item = cl_qlist_next( list_item );\r
713         /* Invalidate bus relations for the bus root. */\r
714         IoInvalidateDeviceRelations(\r
715                 p_ioc_ext->pdo.p_parent_ext->cl_ext.p_pdo, BusRelations );\r
716 \r
717 \r
718         }\r
719 \r
720         IOU_EXIT( IOU_DBG_PNP );\r
721 }\r
722 \r
723 \r
724 static NTSTATUS\r
725 ioc_start(\r
726         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
727         IN                                      IRP* const                              p_irp,\r
728                 OUT                             cl_irp_action_t* const  p_action )\r
729 {\r
730         iou_pdo_ext_t   *p_ext;\r
731 \r
732         IOU_ENTER( IOU_DBG_PNP );\r
733 \r
734         UNUSED_PARAM( p_irp );\r
735 \r
736         p_ext = p_dev_obj->DeviceExtension;\r
737 \r
738         /* Notify the Power Manager that the device is started. */\r
739         PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
740 \r
741         *p_action = IrpComplete;\r
742         IOU_EXIT( IOU_DBG_PNP );\r
743         return STATUS_SUCCESS;\r
744 }\r
745 \r
746 \r
747 static void\r
748 ioc_release_resources(\r
749         IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
750 {\r
751         ioc_mgr_t               *p_ioc_mgr;\r
752         ioc_ext_t               *p_ext;\r
753         POWER_STATE             po_state;\r
754 \r
755         IOU_ENTER( IOU_DBG_PNP );\r
756 \r
757         p_ext = p_dev_obj->DeviceExtension;\r
758         p_ioc_mgr = &p_ext->pdo.p_parent_ext->ioc_mgr;\r
759 \r
760         /* Remove this PDO from its list. */\r
761         cl_mutex_acquire( &p_ioc_mgr->pdo_mutex );\r
762         IOU_PRINT( TRACE_LEVEL_INFORMATION, IOU_DBG_PNP,\r
763                 ("Removing IOC from list.\n") );\r
764         cl_qlist_remove_item( &p_ioc_mgr->pdo_list, &p_ext->pdo.list_item );\r
765         cl_mutex_release( &p_ioc_mgr->pdo_mutex );\r
766         po_state.DeviceState = PowerDeviceD3;\r
767         PoSetPowerState( p_ext->pdo.cl_ext.p_pdo, DevicePowerState, po_state );\r
768 \r
769         IOU_EXIT( IOU_DBG_PNP );\r
770 }\r
771 \r
772 \r
773 static NTSTATUS\r
774 ioc_remove(\r
775         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
776         IN                                      IRP* const                              p_irp,\r
777                 OUT                             cl_irp_action_t* const  p_action )\r
778 {\r
779         ioc_ext_t       *p_ext;\r
780 \r
781         IOU_ENTER( IOU_DBG_PNP );\r
782 \r
783         p_ext = p_dev_obj->DeviceExtension;\r
784 \r
785         if( p_ext->pdo.b_present )\r
786         {\r
787                 CL_ASSERT( p_ext->pdo.cl_ext.pnp_state != NotStarted );\r
788                 CL_ASSERT( !p_ext->pdo.b_reported_missing );\r
789                 /* Reset the state to NotStarted.  CompLib set it to Deleted. */\r
790                 cl_set_pnp_state( &p_ext->pdo.cl_ext, NotStarted );\r
791                 /* Don't delete the device.  It may simply be disabled. */\r
792                 *p_action = IrpComplete;\r
793                 IOU_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IOU_DBG_PNP,\r
794                         ("Device still present.\n") );\r
795                 return STATUS_SUCCESS;\r
796         }\r
797 \r
798         if( !p_ext->pdo.b_reported_missing )\r
799         {\r
800                 /* Reset the state to RemovePending.  Complib set it to Deleted. */\r
801                 cl_rollback_pnp_state( &p_ext->pdo.cl_ext );\r
802                 *p_action = IrpComplete;\r
803                 IOU_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IOU_DBG_PNP,\r
804                         ("Device not reported missing yet.\n") );\r
805                 return STATUS_SUCCESS;\r
806         }\r
807 \r
808         /* Wait for all I/O operations to complete. */\r
809         IoReleaseRemoveLockAndWait( &p_ext->pdo.cl_ext.remove_lock, p_irp );\r
810 \r
811         /* Release resources if it was not done yet. */\r
812         if( p_ext->pdo.cl_ext.last_pnp_state != SurpriseRemoved )\r
813                 p_ext->pdo.cl_ext.vfptr_pnp_po->pfn_release_resources( p_dev_obj );\r
814 \r
815         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
816         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
817 \r
818         IoDeleteDevice( p_dev_obj );\r
819 \r
820         *p_action = IrpDoNothing;\r
821         IOU_EXIT( IOU_DBG_PNP );\r
822         return STATUS_SUCCESS;\r
823 }\r
824 \r
825 \r
826 static NTSTATUS\r
827 ioc_surprise_remove(\r
828         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
829         IN                              IRP* const                                      p_irp,\r
830                 OUT                     cl_irp_action_t* const          p_action )\r
831 {\r
832         ioc_ext_t       *p_ext;\r
833 \r
834         IOU_ENTER( IOU_DBG_PNP );\r
835 \r
836         UNUSED_PARAM( p_irp );\r
837 \r
838         p_ext = p_dev_obj->DeviceExtension;\r
839         p_ext->pdo.b_present = FALSE;\r
840         p_ext->pdo.b_reported_missing = TRUE;\r
841 \r
842         *p_action = IrpComplete;\r
843 \r
844         IOU_EXIT( IOU_DBG_PNP );\r
845         return STATUS_SUCCESS;\r
846 }\r
847 \r
848 \r
849 static NTSTATUS\r
850 ioc_query_capabilities(\r
851         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
852         IN                                      IRP* const                              p_irp,\r
853                 OUT                             cl_irp_action_t* const  p_action )\r
854 {\r
855         DEVICE_CAPABILITIES             *p_caps;\r
856         IO_STACK_LOCATION               *p_io_stack;\r
857 \r
858         IOU_ENTER( IOU_DBG_PNP );\r
859 \r
860         UNUSED_PARAM( p_dev_obj );\r
861 \r
862         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
863         p_caps = p_io_stack->Parameters.DeviceCapabilities.Capabilities;\r
864 \r
865         p_caps->DeviceD1 = FALSE;\r
866         p_caps->DeviceD2 = FALSE;\r
867         p_caps->LockSupported = FALSE;\r
868         p_caps->EjectSupported = FALSE;\r
869         p_caps->Removable = TRUE;\r
870         p_caps->DockDevice = FALSE;\r
871         p_caps->UniqueID = TRUE;\r
872         p_caps->SilentInstall = TRUE;\r
873         p_caps->RawDeviceOK = FALSE;\r
874         p_caps->SurpriseRemovalOK = FALSE;\r
875         p_caps->WakeFromD0 = FALSE;\r
876         p_caps->WakeFromD1 = FALSE;\r
877         p_caps->WakeFromD2 = FALSE;\r
878         p_caps->WakeFromD3 = FALSE;\r
879         p_caps->HardwareDisabled = FALSE;\r
880         p_caps->DeviceState[PowerSystemWorking] = PowerDeviceD0;\r
881         p_caps->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;\r
882         p_caps->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;\r
883         p_caps->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;\r
884         p_caps->DeviceState[PowerSystemHibernate] = PowerDeviceD3;\r
885         p_caps->DeviceState[PowerSystemShutdown] = PowerDeviceD3;\r
886         p_caps->SystemWake = PowerSystemUnspecified;\r
887         p_caps->DeviceWake = PowerDeviceUnspecified;\r
888         p_caps->D1Latency = 0;\r
889         p_caps->D2Latency = 0;\r
890         p_caps->D3Latency = 0;\r
891 \r
892         *p_action = IrpComplete;\r
893         IOU_EXIT( IOU_DBG_PNP );\r
894         return STATUS_SUCCESS;\r
895 }\r
896 \r
897 \r
898 static NTSTATUS\r
899 ioc_query_target_relations(\r
900         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
901         IN                                      IRP* const                              p_irp,\r
902                 OUT                             cl_irp_action_t* const  p_action )\r
903 {\r
904         NTSTATUS                        status;\r
905         DEVICE_RELATIONS        *p_rel;\r
906 \r
907         IOU_ENTER( IOU_DBG_PNP );\r
908 \r
909         *p_action = IrpComplete;\r
910 \r
911         status = cl_alloc_relations( p_irp, 1 );\r
912         if( !NT_SUCCESS( status ) )\r
913         {\r
914                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
915                         ("cl_alloc_relations returned 0x%08x.\n", status) );\r
916                 return status;\r
917         }\r
918 \r
919         p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
920         p_rel->Count = 1;\r
921         p_rel->Objects[0] = p_dev_obj;\r
922 \r
923         ObReferenceObject( p_dev_obj );\r
924 \r
925         IOU_EXIT( IOU_DBG_PNP );\r
926         return status;\r
927 }\r
928 \r
929 \r
930 static NTSTATUS\r
931 ioc_query_device_id(\r
932         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
933                 OUT                             IRP* const                              p_irp )\r
934 {\r
935         ioc_ext_t                       *p_ext;\r
936         WCHAR                           *p_string;\r
937         uint32_t                        dev_id_size;\r
938         NTSTATUS                        status;\r
939 \r
940         IOU_ENTER( IOU_DBG_PNP );\r
941 \r
942         p_ext = (ioc_ext_t*)p_dev_obj->DeviceExtension;\r
943 \r
944         if( !p_ext->pdo.b_present )\r
945         {\r
946                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
947                         ("Device not present.\n") );\r
948                 return STATUS_NO_SUCH_DEVICE;\r
949         }\r
950 \r
951         if (p_ext->pdo.p_pdo_device_info) \r
952         {\r
953 \r
954                 dev_id_size = (p_ext->pdo.p_pdo_device_info)->device_id_size;\r
955                 p_string = ExAllocatePoolWithTag( PagedPool, dev_id_size, 'didq' );\r
956 \r
957                 if( !p_string )\r
958                 {\r
959                         IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
960                                 ( "Failed to allocate device ID buffer (%u bytes).\n",\r
961                                 dev_id_size ) );\r
962                         return STATUS_INSUFFICIENT_RESOURCES;\r
963                 }\r
964 \r
965                 RtlZeroMemory( p_string, dev_id_size );\r
966 \r
967                 cl_memcpy( p_string, p_ext->pdo.p_pdo_device_info->device_id, dev_id_size );\r
968         } \r
969         else \r
970         {\r
971         p_string = ExAllocatePoolWithTag( PagedPool, IOC_DEV_ID_SIZE, 'didq' );\r
972         if( !p_string )\r
973         {\r
974                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
975                         ("Failed to allocate device ID buffer (%d bytes).\n",\r
976                         IOC_DEV_ID_SIZE) );\r
977                 return STATUS_INSUFFICIENT_RESOURCES;\r
978         }\r
979 \r
980         status = RtlStringCbPrintfW( p_string, IOC_DEV_ID_SIZE,\r
981                 L"IBA\\V%06xP%08xS%06xs%08xv%04x",\r
982                 ib_ioc_profile_get_vend_id( &p_ext->info.profile ),\r
983                 cl_ntoh32( p_ext->info.profile.dev_id ),\r
984                 ib_ioc_profile_get_subsys_vend_id( &p_ext->info.profile ),\r
985                 cl_ntoh32( p_ext->info.profile.subsys_id ),\r
986                 cl_ntoh16( p_ext->info.profile.dev_ver ) );\r
987         if( !NT_SUCCESS( status ) )\r
988         {\r
989                 ExFreePool( p_string );\r
990                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
991                         ("Failed to format device ID string.\n") );\r
992                 return status;\r
993         }\r
994                 \r
995         }\r
996 \r
997         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
998 \r
999         IOU_EXIT( IOU_DBG_PNP );\r
1000         return STATUS_SUCCESS;\r
1001 }\r
1002 \r
1003 \r
1004 static NTSTATUS\r
1005 ioc_query_hardware_ids(\r
1006         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1007                 OUT                             IRP* const                              p_irp )\r
1008 {\r
1009         ioc_ext_t                       *p_ext;\r
1010         WCHAR                           *p_string, *p_start;\r
1011         size_t                          size;\r
1012         uint32_t                        V,P,S,s, hw_id_size;\r
1013         uint16_t                        v;\r
1014         NTSTATUS                        status;\r
1015 \r
1016         IOU_ENTER( IOU_DBG_PNP );\r
1017 \r
1018         p_ext = (ioc_ext_t*)p_dev_obj->DeviceExtension;\r
1019         if( !p_ext->pdo.b_present )\r
1020         {\r
1021                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1022                         ("Device not present.\n") );\r
1023                 return STATUS_NO_SUCH_DEVICE;\r
1024         }\r
1025 \r
1026         if (p_ext->pdo.p_pdo_device_info) \r
1027         {\r
1028                 hw_id_size = p_ext->pdo.p_pdo_device_info->hardware_id_size;\r
1029 \r
1030                 p_string = ExAllocatePoolWithTag( PagedPool, hw_id_size, 'ihqi' );\r
1031                 if( !p_string )\r
1032                 {\r
1033                         IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1034                                 ( "Failed to allocate hardware ID buffer (%d bytes).\n",\r
1035                                 hw_id_size ) );\r
1036                         return STATUS_INSUFFICIENT_RESOURCES;\r
1037                 }\r
1038 \r
1039                 RtlZeroMemory( p_string, hw_id_size );\r
1040 \r
1041                 cl_memcpy( p_string, p_ext->pdo.p_pdo_device_info->hardware_id, hw_id_size );\r
1042         } \r
1043         else \r
1044         {\r
1045         p_string = ExAllocatePoolWithTag( PagedPool, IOC_HW_ID_SIZE, 'ihqi' );\r
1046         if( !p_string )\r
1047         {\r
1048                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1049                         ("Failed to allocate hardware ID buffer (%d bytes).\n",\r
1050                         IOC_HW_ID_SIZE) );\r
1051                 return STATUS_INSUFFICIENT_RESOURCES;\r
1052         }\r
1053 \r
1054         V = ib_ioc_profile_get_vend_id( &p_ext->info.profile );\r
1055         P = cl_ntoh32( p_ext->info.profile.dev_id );\r
1056         S = ib_ioc_profile_get_subsys_vend_id( &p_ext->info.profile );\r
1057         s = cl_ntoh32( p_ext->info.profile.subsys_id );\r
1058         v = cl_ntoh16( p_ext->info.profile.dev_ver );\r
1059 \r
1060         /* Fill in the first hardware ID. */\r
1061         p_start = p_string;\r
1062         size = IOC_HW_ID_SIZE;\r
1063         status = RtlStringCbPrintfExW( p_start, size, &p_start, &size,\r
1064                 STRSAFE_FILL_BEHIND_NULL, L"IBA\\V%06xP%08xS%06xs%08xv%04x",\r
1065                 V, P, S, s, v );\r
1066         if( !NT_SUCCESS( status ) )\r
1067         {\r
1068                 ExFreePool( p_string );\r
1069                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1070                         ("Failed to format hardware ID string.\n") );\r
1071                 return status;\r
1072         }\r
1073         /* Fill in the second hardware ID. */\r
1074         p_start++;\r
1075         size -= sizeof(WCHAR);\r
1076         status = RtlStringCbPrintfExW( p_start, size, &p_start, &size,\r
1077                 STRSAFE_FILL_BEHIND_NULL, L"IBA\\V%06xP%08xS%06xs%08x", V, P, S, s );\r
1078         if( !NT_SUCCESS( status ) )\r
1079         {\r
1080                 ExFreePool( p_string );\r
1081                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1082                         ("Failed to format hardware ID string.\n") );\r
1083                 return status;\r
1084         }\r
1085         /* Fill in the third hardware ID. */\r
1086         p_start++;\r
1087         size -= sizeof(WCHAR);\r
1088         status = RtlStringCbPrintfExW( p_start, size, &p_start, &size,\r
1089                 STRSAFE_FILL_BEHIND_NULL, L"IBA\\V%06xP%08xv%04x", V, P, v );\r
1090         if( !NT_SUCCESS( status ) )\r
1091         {\r
1092                 ExFreePool( p_string );\r
1093                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1094                         ("Failed to format hardware ID string.\n") );\r
1095                 return status;\r
1096         }\r
1097         /* Fill in the fourth hardware ID. */\r
1098         p_start++;\r
1099         size -= sizeof(WCHAR);\r
1100         status = RtlStringCbPrintfExW( p_start, size, &p_start, &size,\r
1101                 STRSAFE_FILL_BEHIND_NULL, L"IBA\\V%06xP%08x", V, P );\r
1102         if( !NT_SUCCESS( status ) )\r
1103         {\r
1104                 ExFreePool( p_string );\r
1105                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1106                         ("Failed to format hardware ID string.\n") );\r
1107                 return status;\r
1108         }\r
1109         }\r
1110 \r
1111         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1112 \r
1113         IOU_EXIT( IOU_DBG_PNP );\r
1114         return STATUS_SUCCESS;\r
1115 }\r
1116 \r
1117 \r
1118 static NTSTATUS\r
1119 ioc_query_compatible_ids(\r
1120         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1121                 OUT                             IRP* const                              p_irp )\r
1122 {\r
1123         ioc_ext_t                       *p_ext;\r
1124         WCHAR                           *p_string, *p_start;\r
1125         uint32_t                        compat_id_size;\r
1126         size_t                          size;\r
1127         uint16_t                        C, c, p, r;\r
1128         NTSTATUS                        status;\r
1129 \r
1130 \r
1131         IOU_ENTER( IOU_DBG_PNP );\r
1132 \r
1133         p_ext = (ioc_ext_t*)p_dev_obj->DeviceExtension;\r
1134         if( !p_ext->pdo.b_present )\r
1135         {\r
1136                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1137                         ("Device not present.\n") );\r
1138                 return STATUS_NO_SUCH_DEVICE;\r
1139         }\r
1140 \r
1141         if ( p_ext->pdo.p_pdo_device_info )\r
1142         {\r
1143 \r
1144                 compat_id_size = p_ext->pdo.p_pdo_device_info->compatible_id_size;\r
1145 \r
1146                 p_string = ExAllocatePoolWithTag( PagedPool, compat_id_size, 'icqi' );\r
1147 \r
1148                 if( !p_string )\r
1149                 {\r
1150                         IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1151                                 ("Failed to allocate compatible ID buffer (%d bytes).\n",\r
1152                                 compat_id_size) );\r
1153                         return STATUS_INSUFFICIENT_RESOURCES;\r
1154                 }\r
1155 \r
1156                 RtlZeroMemory( p_string, compat_id_size );\r
1157 \r
1158                 cl_memcpy( p_string, p_ext->pdo.p_pdo_device_info->compatible_id, compat_id_size );\r
1159         } \r
1160         else \r
1161         {\r
1162         p_string = ExAllocatePoolWithTag( PagedPool, IOC_COMPAT_ID_SIZE, 'icqi' );\r
1163         if( !p_string )\r
1164         {\r
1165                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1166                         ("Failed to allocate compatible ID buffer (%d bytes).\n",\r
1167                         IOC_HW_ID_SIZE) );\r
1168                 return STATUS_INSUFFICIENT_RESOURCES;\r
1169         }\r
1170 \r
1171         C = cl_ntoh16( p_ext->info.profile.io_class );\r
1172         c = cl_ntoh16( p_ext->info.profile.io_subclass );\r
1173         p = cl_ntoh16( p_ext->info.profile.protocol );\r
1174         r = cl_ntoh16( p_ext->info.profile.protocol_ver );\r
1175 \r
1176         p_start = p_string;\r
1177         size = IOC_COMPAT_ID_SIZE;\r
1178         /* Fill in the first compatible ID. */\r
1179         status = RtlStringCbPrintfExW( p_start, size, &p_start, &size,\r
1180                 STRSAFE_FILL_BEHIND_NULL, L"IBA\\C%04xc%04xp%04xr%04x", C, c, p, r );\r
1181         if( !NT_SUCCESS( status ) )\r
1182         {\r
1183                 ExFreePool( p_string );\r
1184                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1185                         ("Failed to format device ID string.\n") );\r
1186                 return status;\r
1187         }\r
1188         /* Fill in the second compatible ID. */\r
1189         p_start++;\r
1190         size -= sizeof(WCHAR);\r
1191         status = RtlStringCbPrintfExW( p_start, size, NULL, NULL,\r
1192                 STRSAFE_FILL_BEHIND_NULL, L"IBA\\C%04xc%04xp%04x", C, c, p );\r
1193         if( !NT_SUCCESS( status ) )\r
1194         {\r
1195                 ExFreePool( p_string );\r
1196                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1197                         ("Failed to format device ID string.\n") );\r
1198                 return status;\r
1199         }\r
1200         }\r
1201 \r
1202         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1203 \r
1204         IOU_EXIT( IOU_DBG_PNP );\r
1205         return STATUS_SUCCESS;\r
1206 }\r
1207 \r
1208 \r
1209 static NTSTATUS\r
1210 ioc_query_unique_id(\r
1211         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1212                 OUT                             IRP* const                              p_irp )\r
1213 {\r
1214         NTSTATUS                        status;\r
1215         WCHAR                           *p_string;\r
1216         ioc_ext_t                       *p_ext;\r
1217 \r
1218         IOU_ENTER( IOU_DBG_PNP );\r
1219 \r
1220         p_ext = p_dev_obj->DeviceExtension;\r
1221         if( !p_ext->pdo.b_present )\r
1222         {\r
1223                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1224                         ("Device not present.\n") );\r
1225                 return STATUS_NO_SUCH_DEVICE;\r
1226         }\r
1227 \r
1228         /* The instance ID is the port GUID. */\r
1229         if ( p_ext->pdo.p_pdo_device_info ) \r
1230         {\r
1231 \r
1232                 p_string = ExAllocatePoolWithTag( PagedPool, sizeof(WCHAR) * 41, 'iuqi' );\r
1233                 if( !p_string )\r
1234                 {\r
1235                         IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1236                                 ("Failed to allocate instance ID buffer (%d bytes).\n",\r
1237                                 sizeof(WCHAR) * 41) );\r
1238                         return STATUS_NO_MEMORY;\r
1239                 }\r
1240 \r
1241                 status = RtlStringCchPrintfW ( p_string, 41, L"%016I64x%016I64x%08x",\r
1242                                          p_ext->info.profile.ioc_guid, p_ext->pdo.ca_guid,\r
1243                                          p_ext->pdo.p_pdo_device_info->uniqueinstanceid);\r
1244                 if( !NT_SUCCESS( status ) )\r
1245                 {\r
1246                         CL_ASSERT( NT_SUCCESS( status ) );\r
1247                         ExFreePool( p_string );\r
1248                         IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1249                                 ("RtlStringCchPrintfW returned %08x.\n", status) );\r
1250                         return status;\r
1251                 }\r
1252         } \r
1253         else \r
1254         {\r
1255         p_string = ExAllocatePoolWithTag( PagedPool, sizeof(WCHAR) * 33, 'iuqi' );\r
1256         if( !p_string )\r
1257         {\r
1258                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1259                         ("Failed to allocate instance ID buffer (%d bytes).\n",\r
1260                         sizeof(WCHAR) * 17) );\r
1261                 return STATUS_NO_MEMORY;\r
1262         }\r
1263 \r
1264         status = RtlStringCchPrintfW(p_string, 33, L"%016I64x%016I64x",\r
1265                  p_ext->info.profile.ioc_guid,p_ext->pdo.ca_guid);\r
1266         if( !NT_SUCCESS( status ) )\r
1267         {\r
1268                 CL_ASSERT( NT_SUCCESS( status ) );\r
1269                 ExFreePool( p_string );\r
1270                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1271                         ("RtlStringCchPrintfW returned %08x.\n", status) );\r
1272                 return status;\r
1273         }\r
1274 \r
1275         }\r
1276 \r
1277         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1278 \r
1279         IOU_EXIT( IOU_DBG_PNP );\r
1280         return STATUS_SUCCESS;\r
1281 }\r
1282 \r
1283 \r
1284 static NTSTATUS\r
1285 ioc_query_description(\r
1286         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1287                 OUT                             IRP* const                              p_irp )\r
1288 {\r
1289         NTSTATUS                        status;\r
1290         WCHAR                           *p_string;\r
1291         ioc_ext_t                       *p_ext;\r
1292 \r
1293         IOU_ENTER( IOU_DBG_PNP );\r
1294 \r
1295         p_ext = p_dev_obj->DeviceExtension;\r
1296         if( !p_ext->pdo.b_present )\r
1297         {\r
1298                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1299                         ("Device not present.\n") );\r
1300                 return STATUS_NO_SUCH_DEVICE;\r
1301         }\r
1302 \r
1303         if ( p_ext->pdo.p_pdo_device_info ) \r
1304         {\r
1305                 p_string = ExAllocatePoolWithTag( PagedPool, p_ext->pdo.p_pdo_device_info->description_size, \r
1306                                                 'edqi' );\r
1307                 if( !p_string )\r
1308                 {\r
1309                         IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1310                                 ( "Failed to allocate description buffer (%d bytes).\n",\r
1311                                 p_ext->pdo.p_pdo_device_info->description_size ) );\r
1312                         return STATUS_INSUFFICIENT_RESOURCES;\r
1313                 }\r
1314 \r
1315                 RtlZeroMemory( p_string, p_ext->pdo.p_pdo_device_info->description_size );\r
1316 \r
1317                 cl_memcpy( p_string, p_ext->pdo.p_pdo_device_info->description,\r
1318                                 p_ext->pdo.p_pdo_device_info->description_size );\r
1319 \r
1320         } \r
1321         else \r
1322         {\r
1323         p_string = ExAllocatePoolWithTag( PagedPool,\r
1324                                                                           sizeof(WCHAR) * sizeof(p_ext->info.profile.id_string),\r
1325                                                                           'edqi');\r
1326         if( !p_string )\r
1327         {\r
1328                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1329                         ("Failed to allocate device description buffer (%d bytes).\n",\r
1330                         sizeof(WCHAR) * sizeof(p_ext->info.profile.id_string)) );\r
1331                 return STATUS_INSUFFICIENT_RESOURCES;\r
1332         }\r
1333 \r
1334         if( ib_ioc_profile_get_vend_id( &p_ext->info.profile ) == 0x00066a &&\r
1335                 p_ext->info.profile.dev_id == CL_HTON32(0x00000030) )\r
1336         {\r
1337                 status = RtlStringCchPrintfW(\r
1338                         p_string, sizeof(p_ext->info.profile.id_string),\r
1339                         L"SilverStorm Technologies VEx I/O Controller" );\r
1340         }\r
1341         else if( ib_ioc_profile_get_vend_id( &p_ext->info.profile ) == 0x00066a &&\r
1342                 p_ext->info.profile.dev_id == CL_HTON32(0x00000038) )\r
1343         {\r
1344                 status = RtlStringCchPrintfW(\r
1345                         p_string, sizeof(p_ext->info.profile.id_string),\r
1346                         L"SilverStorm Technologies VFx I/O Controller" );\r
1347         }\r
1348         else\r
1349         {\r
1350                 status = RtlStringCchPrintfW(\r
1351                         p_string, sizeof(p_ext->info.profile.id_string),\r
1352                         L"%S", p_ext->info.profile.id_string );\r
1353         }\r
1354         if( !NT_SUCCESS( status ) )\r
1355         {\r
1356                 CL_ASSERT( NT_SUCCESS( status ) );\r
1357                 ExFreePool( p_string );\r
1358                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1359                         ("RtlStringCchPrintfW returned %08x.\n", status) );\r
1360                 return status;\r
1361         }\r
1362         }\r
1363 \r
1364         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1365 \r
1366         IOU_EXIT( IOU_DBG_PNP );\r
1367         return STATUS_SUCCESS;\r
1368 }\r
1369 \r
1370 \r
1371 static NTSTATUS\r
1372 ioc_query_location(\r
1373         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1374                 OUT                             IRP* const                              p_irp )\r
1375 {\r
1376         NTSTATUS                        status;\r
1377         ioc_ext_t                       *p_ext;\r
1378         WCHAR                           *p_string;\r
1379 \r
1380         IOU_ENTER( IOU_DBG_PNP );\r
1381 \r
1382         p_ext = (ioc_ext_t*)p_dev_obj->DeviceExtension;\r
1383         if( !p_ext->pdo.b_present )\r
1384         {\r
1385                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1386                         ("Device not present.\n") );\r
1387                 return STATUS_NO_SUCH_DEVICE;\r
1388         }\r
1389 \r
1390         p_string = ExAllocatePoolWithTag( PagedPool, \r
1391                                                                           max( IOC_LOCATION_SIZE, sizeof( WCHAR ) *\r
1392                                                                                ( sizeof( p_ext->info.profile.id_string ) + 1 )),\r
1393                                                                           'olqi');\r
1394         if( !p_string )\r
1395         {\r
1396                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1397                         ("Failed to allocate location buffer (%d bytes).\n",\r
1398                         IOC_LOCATION_SIZE) );\r
1399                 return STATUS_INSUFFICIENT_RESOURCES;\r
1400         }\r
1401 \r
1402         if( ib_ioc_profile_get_vend_id( &p_ext->info.profile ) == 0x00066a )\r
1403         {\r
1404                 status = RtlStringCchPrintfW(\r
1405                         p_string, sizeof(p_ext->info.profile.id_string),\r
1406                         L"%S", p_ext->info.profile.id_string );\r
1407         }\r
1408         else\r
1409         {\r
1410                 status = RtlStringCbPrintfW( p_string, IOC_LOCATION_SIZE,\r
1411                         L"Chassis 0x%016I64x, Slot %d, IOC %d",\r
1412                         cl_ntoh64( p_ext->info.chassis_guid ),\r
1413                         p_ext->info.chassis_slot, p_ext->info.iou_slot );\r
1414         }\r
1415         if( !NT_SUCCESS( status ) )\r
1416         {\r
1417                 ExFreePool( p_string );\r
1418                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1419                         ("Failed to format device ID string.\n") );\r
1420                 return status;\r
1421         }\r
1422         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1423 \r
1424         IOU_EXIT( IOU_DBG_PNP );\r
1425         return STATUS_SUCCESS;\r
1426 }\r
1427 \r
1428 \r
1429 static NTSTATUS\r
1430 ioc_query_bus_info(\r
1431         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1432         IN                                      IRP* const                              p_irp,\r
1433                 OUT                             cl_irp_action_t* const  p_action )\r
1434 {\r
1435         ioc_ext_t                       *p_ext;\r
1436         PNP_BUS_INFORMATION     *p_iou_info;\r
1437 \r
1438         IOU_ENTER( IOU_DBG_PNP );\r
1439 \r
1440         p_ext = (ioc_ext_t*)p_dev_obj->DeviceExtension;\r
1441         if( !p_ext->pdo.b_present )\r
1442         {\r
1443                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1444                         ("Device not present.\n") );\r
1445                 return STATUS_NO_SUCH_DEVICE;\r
1446         }\r
1447 \r
1448         *p_action = IrpComplete;\r
1449 \r
1450         p_iou_info = ExAllocatePoolWithTag( PagedPool, sizeof(PNP_BUS_INFORMATION), 'ibqi' );\r
1451         if( !p_iou_info )\r
1452         {\r
1453                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1454                         ("Failed to allocate PNP_BUS_INFORMATION (%d bytes).\n",\r
1455                         sizeof(PNP_BUS_INFORMATION)) );\r
1456                 return STATUS_INSUFFICIENT_RESOURCES;\r
1457         }\r
1458 \r
1459 \r
1460         p_iou_info->BusTypeGuid = GUID_BUS_TYPE_IBA;\r
1461         //TODO: Memory from Intel - storage miniport would not stay loaded unless\r
1462         //TODO: bus type was PCI.  Look here if SRP is having problems staying\r
1463         //TODO: loaded.\r
1464         p_iou_info->LegacyBusType = PNPBus;\r
1465         p_iou_info->BusNumber = p_ext->info.iou_slot;\r
1466 \r
1467         p_irp->IoStatus.Information = (ULONG_PTR)p_iou_info;\r
1468         IOU_EXIT( IOU_DBG_PNP );\r
1469         return STATUS_SUCCESS;\r
1470 }\r
1471 \r
1472 \r
1473 static __ref_ioc_ifc(\r
1474         IN                              ioc_ext_t*                                              p_ext )\r
1475 {\r
1476         IOU_ENTER( IOU_DBG_PNP );\r
1477 \r
1478         cl_atomic_inc( &p_ext->pdo.p_parent_ext->cl_ext.n_ifc_ref );\r
1479         ObReferenceObject( p_ext->pdo.p_parent_ext->cl_ext.p_self_do );\r
1480 \r
1481         IOU_EXIT( IOU_DBG_PNP );\r
1482 }\r
1483 \r
1484 \r
1485 static void\r
1486 __deref_ioc_ifc(\r
1487         IN                              ioc_ext_t*                                              p_ext )\r
1488 {\r
1489         IOU_ENTER( IOU_DBG_PNP );\r
1490 \r
1491         cl_atomic_dec( &p_ext->pdo.p_parent_ext->cl_ext.n_ifc_ref );\r
1492         ObDereferenceObject( p_ext->pdo.p_parent_ext->cl_ext.p_self_do );\r
1493 \r
1494         IOU_EXIT( IOU_DBG_PNP );\r
1495 }\r
1496 \r
1497 \r
1498 \r
1499 \r
1500 static NTSTATUS\r
1501 ioc_query_interface(\r
1502         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1503         IN                              IRP* const                                      p_irp,\r
1504                 OUT                     cl_irp_action_t* const          p_action )\r
1505 {\r
1506         NTSTATUS                                status;\r
1507         IO_STACK_LOCATION               *p_io_stack;\r
1508         ib_al_ifc_t                             *p_ifc;\r
1509         ib_al_ifc_data_t                *p_ifc_data;\r
1510         ioc_ifc_data_t                  *p_ioc_data;\r
1511         ioc_ext_t                               *p_ext;\r
1512         const GUID                              *p_guid;\r
1513 \r
1514         IOU_ENTER( IOU_DBG_PNP );\r
1515 \r
1516         CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
1517 \r
1518         p_ext = p_dev_obj->DeviceExtension;\r
1519         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1520         p_guid = p_io_stack->Parameters.QueryInterface.InterfaceType;\r
1521         /* Bottom of the stack - IRP must be completed. */\r
1522         *p_action = IrpComplete;\r
1523 \r
1524         /* Compare requested GUID with our supported interface GUIDs. */\r
1525         if( IsEqualGUID( p_guid, &GUID_BUS_INTERFACE_STANDARD ) )\r
1526         {\r
1527                 IOU_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IOU_DBG_PNP,\r
1528                         ("BUS_INTERFACE_STANDARD\n") );\r
1529                 return cl_fwd_query_ifc(\r
1530                         p_ext->pdo.p_parent_ext->cl_ext.p_self_do, p_io_stack );\r
1531         }\r
1532 \r
1533         if( !IsEqualGUID( p_guid, &GUID_IB_AL_INTERFACE ) )\r
1534         {\r
1535                 IOU_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IOU_DBG_PNP,\r
1536                         ("Unsupported interface: \n\t"\r
1537                         "0x%08x, 0x%04x, 0x%04x, 0x%02x, 0x%02x, 0x%02x,"\r
1538                         "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n",\r
1539                         p_guid->Data1, p_guid->Data2, p_guid->Data3,\r
1540                         p_guid->Data4[0], p_guid->Data4[1], p_guid->Data4[2],\r
1541                         p_guid->Data4[3], p_guid->Data4[4], p_guid->Data4[5],\r
1542                         p_guid->Data4[6], p_guid->Data4[7]) );\r
1543                 return p_irp->IoStatus.Status;\r
1544         }\r
1545 \r
1546         /* Get the interface. */\r
1547         status = cl_fwd_query_ifc(\r
1548                 p_ext->pdo.p_parent_ext->cl_ext.p_self_do, p_io_stack );\r
1549         if( !NT_SUCCESS( status ) )\r
1550         {\r
1551                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1552                         ("Failed to forward interface query: %08X\n", status) );\r
1553                 return status;\r
1554         }\r
1555 \r
1556         if( !p_io_stack->Parameters.QueryInterface.InterfaceSpecificData )\r
1557         {\r
1558                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1559                         ("No interface specific data!\n") );\r
1560                 return status;\r
1561         }\r
1562 \r
1563         p_ifc = (ib_al_ifc_t*)p_io_stack->Parameters.QueryInterface.Interface;\r
1564 \r
1565         p_ifc_data = (ib_al_ifc_data_t*)\r
1566                 p_io_stack->Parameters.QueryInterface.InterfaceSpecificData;\r
1567         p_guid = p_ifc_data->type;\r
1568         if( !IsEqualGUID( p_guid, &GUID_IOC_INTERFACE_DATA ) ||\r
1569                 p_ifc_data->version != IOC_INTERFACE_DATA_VERSION )\r
1570         {\r
1571                 p_ifc->wdm.InterfaceDereference( p_ifc->wdm.Context );\r
1572                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1573                         ("Unsupported interface data: \n\t"\r
1574                         "0x%08x, 0x%04x, 0x%04x, 0x%02x, 0x%02x, 0x%02x,"\r
1575                         "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n",\r
1576                         p_guid->Data1, p_guid->Data2, p_guid->Data3,\r
1577                         p_guid->Data4[0], p_guid->Data4[1], p_guid->Data4[2],\r
1578                         p_guid->Data4[3], p_guid->Data4[4], p_guid->Data4[5],\r
1579                         p_guid->Data4[6], p_guid->Data4[7]) );\r
1580                 return STATUS_INVALID_PARAMETER;\r
1581         }\r
1582 \r
1583         ASSERT( p_ifc_data->p_data );\r
1584 \r
1585         if( p_ifc_data->size != sizeof(ioc_ifc_data_t) )\r
1586         {\r
1587                 p_ifc->wdm.InterfaceDereference( p_ifc->wdm.Context );\r
1588                 IOU_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IOU_DBG_PNP,\r
1589                         ("Buffer too small (%d given, %d required).\n",\r
1590                         p_ifc_data->size,\r
1591                         sizeof(ioc_ifc_data_t)) );\r
1592                 return STATUS_BUFFER_TOO_SMALL;\r
1593         }\r
1594 \r
1595         /* Set the interface data. */\r
1596         p_ioc_data = (ioc_ifc_data_t*)p_ifc_data->p_data;\r
1597 \r
1598         p_ioc_data->ca_guid = p_ext->pdo.p_parent_ext->ioc_mgr.info.ca_guid;\r
1599         p_ioc_data->guid = p_ext->info.profile.ioc_guid;\r
1600 \r
1601         IOU_EXIT( IOU_DBG_PNP );\r
1602         return STATUS_SUCCESS;\r
1603 }\r
1604 \r
1605 \r
1606 /*\r
1607  * The PDOs created by the IB Bus driver are software devices.  As such,\r
1608  * all power states are supported.  It is left to the HCA power policy\r
1609  * owner to handle which states can be supported by the HCA.\r
1610  */\r
1611 static NTSTATUS\r
1612 ioc_set_power(\r
1613         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1614         IN                              IRP* const                                      p_irp,\r
1615                 OUT                     cl_irp_action_t* const          p_action )\r
1616 {\r
1617         IO_STACK_LOCATION       *p_io_stack;\r
1618         iou_pdo_ext_t           *p_ext;\r
1619 \r
1620         IOU_ENTER( IOU_DBG_POWER );\r
1621 \r
1622         p_ext = p_dev_obj->DeviceExtension;\r
1623         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1624 \r
1625         if( p_io_stack->Parameters.Power.Type == DevicePowerState )\r
1626         {\r
1627                 /* Notify the power manager. */\r
1628                 p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
1629                 PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
1630         }\r
1631 \r
1632         *p_action = IrpComplete;\r
1633         IOU_EXIT( IOU_DBG_POWER );\r
1634         return STATUS_SUCCESS;\r
1635 }\r
1636 \r
1637 ib_api_status_t\r
1638 _create_ioc_pdo(\r
1639         IN                              child_device_info_t*                    p_child_dev,\r
1640         IN                              ca_ioc_map_t*                           p_ca_ioc_map)\r
1641 {\r
1642         NTSTATUS                status;\r
1643         DEVICE_OBJECT   *p_pdo = NULL;\r
1644         iou_fdo_ext_t   *p_ext;\r
1645         ioc_mgr_t               *p_ioc_mgr;\r
1646         ioc_ext_t               *p_ioc_ext;\r
1647         uint32_t                ext_size;\r
1648         BOOLEAN                 b_vnic_ioc = FALSE;\r
1649 \r
1650         p_ioc_mgr = p_ca_ioc_map->p_ioc_mgr;\r
1651 \r
1652         p_ext = PARENT_STRUCT( p_ioc_mgr, iou_fdo_ext_t, ioc_mgr );\r
1653 \r
1654         if( p_child_dev->ca_ioc_path.ca_guid != p_ioc_mgr->info.ca_guid ||\r
1655                 p_child_dev->ca_ioc_path.info.chassis_guid != p_ioc_mgr->info.chassis_guid ||\r
1656                 p_child_dev->ca_ioc_path.info.chassis_slot != p_ioc_mgr->info.slot||\r
1657                 p_child_dev->ca_ioc_path.info.iou_guid != p_ioc_mgr->info.guid )\r
1658         {\r
1659                 IOU_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IOU_DBG_PNP,\r
1660                         ("Child PDO's IOC not in this IOU.\n") );\r
1661                 return IB_NOT_DONE;\r
1662         }\r
1663 \r
1664         ext_size = sizeof(ioc_ext_t) +\r
1665                 ( sizeof(ib_svc_entry_t) * p_ca_ioc_map->info.profile.num_svc_entries );\r
1666 \r
1667         status = IoCreateDevice( iou_globals.p_driver_obj, ext_size,\r
1668                         NULL, FILE_DEVICE_CONTROLLER,\r
1669                         FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,\r
1670                         FALSE, &p_pdo );\r
1671         if( !NT_SUCCESS( status ) )\r
1672         {\r
1673                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
1674                         ( "IoCreateDevice returned %08x.\n", status ) );\r
1675                 return IB_ERROR;\r
1676         }\r
1677 \r
1678         b_vnic_ioc = is_vnic_profile_ioc( &p_ca_ioc_map->info.profile );        \r
1679 \r
1680         /* Initialize the device extension. */\r
1681         cl_init_pnp_po_ext( p_pdo, NULL, p_pdo, g_iou_dbg_flags,\r
1682                 &vfptr_ioc_pnp, &vfptr_iou_query_txt );\r
1683         /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
1684         p_pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
1685 \r
1686         p_ioc_ext = p_pdo->DeviceExtension;\r
1687         p_ioc_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
1688         p_ioc_ext->pdo.p_parent_ext = p_ext;\r
1689         p_ioc_ext->pdo.b_present = TRUE;\r
1690         p_ioc_ext->pdo.b_reported_missing = FALSE;\r
1691         p_ioc_ext->pdo.ca_guid = p_child_dev->ca_ioc_path.ca_guid;\r
1692 \r
1693         if ( b_vnic_ioc ) \r
1694         {\r
1695                 p_ioc_ext->pdo.p_pdo_device_info = p_child_dev;\r
1696         }\r
1697 \r
1698         /* Copy the IOC profile and service entries. */\r
1699         p_ioc_ext->info = p_child_dev->ca_ioc_path.info;\r
1700         cl_memcpy( p_ioc_ext->svc_entries, p_child_dev->ca_ioc_path.svc_entry_array,\r
1701                 p_child_dev->ca_ioc_path.info.profile.num_svc_entries );\r
1702         /* Make sure the IOC string is null terminated. */\r
1703         p_ioc_ext->info.profile.id_string[CTRL_ID_STRING_LEN-1] = '\0';\r
1704 \r
1705         /* Store the device extension in the PDO list for future queries. */\r
1706         cl_mutex_acquire( &p_ioc_mgr->pdo_mutex );\r
1707         cl_qlist_insert_tail( &p_ioc_mgr->pdo_list,\r
1708                                 &p_ioc_ext->pdo.list_item );\r
1709         cl_mutex_release( &p_ioc_mgr->pdo_mutex );\r
1710 \r
1711         IoInvalidateDeviceRelations( p_ext->cl_ext.p_pdo, BusRelations );\r
1712 \r
1713         IOU_EXIT(IOU_DBG_PNP);\r
1714 \r
1715         return IB_SUCCESS;\r
1716 }\r