[IBBUS,IPoIB] add debug prints. [mlnx: 4838]
[mirror/winof/.git] / core / bus / kernel / bus_driver.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 2006 Mellanox Technologies.  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  * Provides the driver entry points for the InfiniBand Bus Driver.\r
36  */\r
37 \r
38 #include <complib/cl_types.h>\r
39 #include "bus_driver.h"\r
40 #include "bus_pnp.h"\r
41 #include "al_mgr.h"\r
42 #include "al_dev.h"\r
43 #include "al_debug.h"\r
44 #include <complib/cl_init.h>\r
45 #include "iba/ipoib_ifc.h"\r
46 \r
47 #if defined(EVENT_TRACING)\r
48 #ifdef offsetof\r
49 #undef offsetof\r
50 #endif\r
51 #include "bus_driver.tmh"\r
52 #endif\r
53 \r
54 #ifdef WINIB\r
55 #define DEFAULT_NODE_DESC       "Mellanox Windows® Host"\r
56 #else\r
57 #define DEFAULT_NODE_DESC       "OpenIB Windows® Host"\r
58 #endif\r
59 \r
60 \r
61 \r
62 char    node_desc[IB_NODE_DESCRIPTION_SIZE];\r
63 PDEVICE_OBJECT  g_ControlDeviceObject=NULL;\r
64 UNICODE_STRING  g_CDO_dev_name, g_CDO_dos_name;\r
65 \r
66 bus_globals_t   bus_globals = {\r
67         BUS_DBG_ERROR,\r
68         TRUE,\r
69         NULL,\r
70         NULL,\r
71         NULL,\r
72         NULL\r
73 };\r
74 \r
75 static void\r
76 __read_machine_name( void );\r
77 \r
78 static NTSTATUS\r
79 __read_registry(\r
80         IN                              UNICODE_STRING* const           p_Param_Path );\r
81 \r
82 static NTSTATUS\r
83 bus_drv_open(\r
84         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
85         IN                              IRP                                                     *p_irp );\r
86 \r
87 static NTSTATUS\r
88 bus_drv_cleanup(\r
89         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
90         IN                              IRP                                                     *p_irp );\r
91 \r
92 static NTSTATUS\r
93 bus_drv_close(\r
94         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
95         IN                              IRP                                                     *p_irp );\r
96 \r
97 static NTSTATUS\r
98 bus_drv_ioctl(\r
99         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
100         IN                              IRP                                                     *p_irp );\r
101 \r
102 /***f* InfiniBand Bus Driver/bus_drv_sysctl\r
103 * NAME\r
104 *       bus_drv_sysctl\r
105 *\r
106 * DESCRIPTION\r
107 *       Entry point for handling WMI IRPs.\r
108 *\r
109 * SYNOPSIS\r
110 */\r
111 static NTSTATUS\r
112 bus_drv_sysctl(\r
113         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
114         IN                              IRP                                                     *p_irp );\r
115 /**********/\r
116 \r
117 static void\r
118 bus_drv_unload(\r
119         IN                              DRIVER_OBJECT                           *p_driver_obj );\r
120 \r
121 NTSTATUS\r
122 DriverEntry(\r
123         IN                              DRIVER_OBJECT                           *p_driver_obj,\r
124         IN                              UNICODE_STRING                          *p_registry_path );\r
125 \r
126 \r
127 child_device_info_t g_default_device_info;\r
128 \r
129 static void __create_default_dev_info(child_device_info_t *pNewDevList)\r
130 {\r
131         UNICODE_STRING                          keyValue;\r
132 \r
133         /* DeviceId*/\r
134         RtlInitUnicodeString(&keyValue, L"IBA\\IPoIBP\0");              \r
135         pNewDevList->device_id_size = keyValue.Length + sizeof(WCHAR);\r
136         RtlStringCchCopyW( pNewDevList->device_id, \r
137                 sizeof(pNewDevList->device_id)/sizeof(wchar_t), keyValue.Buffer );\r
138         /* HardwareId*/\r
139         RtlInitUnicodeString(&keyValue, L"IBA\\IPoIBP\0\0");    \r
140         pNewDevList->hardware_id_size = keyValue.Length + 2*sizeof(WCHAR);\r
141         RtlStringCchCopyW( pNewDevList->hardware_id, \r
142                 sizeof(pNewDevList->hardware_id)/sizeof(wchar_t), keyValue.Buffer );\r
143         /* CompatibleId*/\r
144         RtlInitUnicodeString(&keyValue, L"IBA\\SID_1000066a00020000\0\0");      \r
145         pNewDevList->compatible_id_size = keyValue.Length + 2*sizeof(WCHAR); //2 \r
146         RtlStringCchCopyW( pNewDevList->compatible_id, \r
147                 sizeof(pNewDevList->compatible_id)/sizeof(wchar_t), keyValue.Buffer );\r
148         /* Device Description */\r
149         RtlInitUnicodeString(&keyValue, L"OpenIB IPoIB Adapter");\r
150         pNewDevList->description_size = keyValue.Length + sizeof(WCHAR);\r
151         RtlStringCchCopyW( pNewDevList->description, \r
152                 sizeof(pNewDevList->description)/sizeof(wchar_t), keyValue.Buffer );\r
153         /* Pkey */\r
154         RtlInitUnicodeString(&keyValue, L"FFFF");               /* Pkey */\r
155         RtlStringCchCopyW( pNewDevList->pkey, \r
156                 sizeof(pNewDevList->pkey)/sizeof(wchar_t), keyValue.Buffer );\r
157 }\r
158 \r
159 \r
160 static void\r
161 __read_machine_name( void )\r
162 {\r
163         NTSTATUS                                        status;\r
164         /* Remember the terminating entry in the table below. */\r
165         RTL_QUERY_REGISTRY_TABLE        table[2];\r
166         UNICODE_STRING                          hostNamePath;\r
167         UNICODE_STRING                          hostNameW;\r
168         ANSI_STRING                                     hostName;\r
169 \r
170         BUS_ENTER( BUS_DBG_DRV );\r
171 \r
172         /* Get the host name. */\r
173         RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" );\r
174         RtlInitUnicodeString( &hostNameW, NULL );\r
175 \r
176         /*\r
177          * Clear the table.  This clears all the query callback pointers,\r
178          * and sets up the terminating table entry.\r
179          */\r
180         cl_memclr( table, sizeof(table) );\r
181         cl_memclr( node_desc, sizeof(node_desc) );\r
182 \r
183         /* Setup the table entries. */\r
184         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;\r
185         table[0].Name = L"ComputerName";\r
186         table[0].EntryContext = &hostNameW;\r
187         table[0].DefaultType = REG_SZ;\r
188         table[0].DefaultData = &hostNameW;\r
189         table[0].DefaultLength = 0;\r
190 \r
191         /* Have at it! */\r
192         status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL, \r
193                 hostNamePath.Buffer, table, NULL, NULL );\r
194         if( NT_SUCCESS( status ) )\r
195         {\r
196                 /* Convert the UNICODE host name to UTF-8 (ASCII). */\r
197                 hostName.Length = 0;\r
198                 hostName.MaximumLength = sizeof(node_desc);\r
199                 hostName.Buffer = node_desc;\r
200                 status = RtlUnicodeStringToAnsiString( &hostName, &hostNameW, FALSE );\r
201                 RtlFreeUnicodeString( &hostNameW );\r
202         }\r
203         else\r
204         {\r
205                 BUS_TRACE(BUS_DBG_ERROR , ("Failed to get host name.\n") );\r
206                 /* Use the default name... */\r
207                 RtlStringCbCopyNA( node_desc, sizeof(node_desc),\r
208                         DEFAULT_NODE_DESC, sizeof(DEFAULT_NODE_DESC) );\r
209         }\r
210         BUS_EXIT( BUS_DBG_DRV );\r
211 }\r
212 \r
213 /************************************************************************************\r
214 * name  :       __prepare_pKey_array\r
215 *           parses registry string and exrtacts pkey value(s) from it.\r
216 *                       pkey pattern is 0xABCD\r
217 * input :       UNICODE_STRING *str\r
218 * output:       pkey_array\r
219 * return:       uint16_t number of pkey(s) found\r
220 *************************************************************************************/\r
221 static void __prepare_pKey_array(IN const char *str, size_t str_len,OUT pkey_array_t *cur_pkey)\r
222 {\r
223         NTSTATUS status;\r
224         size_t i;\r
225         uint8_t j;\r
226         char pkey_str[7];\r
227         ULONG   tmp_val;\r
228         BUS_ENTER( BUS_DBG_DRV );\r
229 \r
230         CL_ASSERT(cur_pkey);\r
231         CL_ASSERT(str);\r
232 \r
233         cur_pkey->pkey_num = 0;\r
234         j = 0;\r
235 \r
236         for (i = 0; (i < str_len) && (cur_pkey->pkey_num < MAX_NUM_PKEY) ; i++)\r
237         {\r
238                 if(str[i] == ' ')\r
239                         continue;\r
240 \r
241                 if( (str[i] != ',') && (str[i] != '\0'))\r
242                 {\r
243                     if(j >= 7)\r
244                         {\r
245                                 BUS_TRACE(BUS_DBG_ERROR ,\r
246                                 ("Incorrect format of pkey value\n") );\r
247                                 break;\r
248                         }\r
249                         pkey_str[j] = str[i];\r
250                         j++;\r
251                 }\r
252                 else\r
253                 {\r
254                         pkey_str[j] = '\0';\r
255                         status = RtlCharToInteger(&pkey_str[2],16,&tmp_val);\r
256                         if(! NT_SUCCESS(status))\r
257                         {\r
258                                 BUS_TRACE(BUS_DBG_ERROR ,\r
259                                 ("Failed to convert, status = 0x%08X\n",status) );\r
260                                 break;   \r
261                         }\r
262                         cur_pkey->pkey_array[cur_pkey->pkey_num++] = (uint16_t)tmp_val;\r
263                         j = 0;\r
264                 }\r
265         }\r
266         BUS_EXIT( BUS_DBG_DRV );\r
267 }\r
268 \r
269 \r
270 static void     _free_static_iodevices()\r
271 {\r
272         child_device_info_list_t *pDevList, *pDevList1;\r
273 \r
274         pDevList = bus_globals.p_device_list;\r
275 \r
276         while(pDevList)\r
277         {\r
278                 pDevList1 = pDevList->next_device_info;\r
279                 cl_free(pDevList);\r
280                 pDevList = pDevList1;\r
281         }\r
282 \r
283 }\r
284 \r
285 static NTSTATUS __create_static_devices(PUNICODE_STRING p_param_path)\r
286 {\r
287         RTL_QUERY_REGISTRY_TABLE        table[2];\r
288         UNICODE_STRING                          keyPath;\r
289         UNICODE_STRING                          keyValue;\r
290         UNICODE_STRING                          defaultKeyValue;\r
291         UNICODE_STRING                          child_name;\r
292         WCHAR                                           *key_path_buffer;\r
293         WCHAR                                           *key_value_buffer;\r
294         WCHAR                                           *static_child_name;\r
295         NTSTATUS                                        status;\r
296         #define BUF_SIZE                        256             /* use hard-coded size to make it simple*/\r
297 \r
298         cl_memclr( table, sizeof(table) );\r
299 \r
300         \r
301         key_path_buffer = cl_zalloc(BUF_SIZE*sizeof(WCHAR)*3);\r
302 \r
303         if(!key_path_buffer)\r
304         {\r
305                 BUS_TRACE(BUS_DBG_ERROR ,("Not enough memory for key_path_buffer.\n") );\r
306                 status = STATUS_UNSUCCESSFUL;\r
307                 goto __create_static_devices_exit;\r
308         }\r
309 \r
310         key_value_buffer = key_path_buffer + BUF_SIZE;\r
311         static_child_name = key_value_buffer + BUF_SIZE;\r
312 \r
313         RtlInitUnicodeString( &keyPath, NULL );\r
314         keyPath.MaximumLength = BUF_SIZE*sizeof(WCHAR);\r
315         keyPath.Buffer = key_path_buffer;\r
316 \r
317         RtlInitUnicodeString( &keyValue, NULL );\r
318         keyValue.MaximumLength = BUF_SIZE*sizeof(WCHAR);\r
319         keyValue.Buffer = key_value_buffer;\r
320 \r
321         RtlInitUnicodeString( &child_name, NULL );\r
322         child_name.MaximumLength = BUF_SIZE*sizeof(WCHAR);\r
323         child_name.Buffer = static_child_name;\r
324 \r
325 \r
326         RtlCopyUnicodeString( &keyPath, p_param_path );\r
327 \r
328         RtlInitUnicodeString(&defaultKeyValue, L"IPoIB\0\0");\r
329 \r
330         /* Setup the table entries. */\r
331         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND;\r
332         table[0].Name = L"StaticChild";\r
333         table[0].EntryContext = &child_name;\r
334         table[0].DefaultType = REG_MULTI_SZ;\r
335         table[0].DefaultData = defaultKeyValue.Buffer;\r
336         table[0].DefaultLength = defaultKeyValue.Length;\r
337 \r
338         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
339                 keyPath.Buffer, table, NULL, NULL );\r
340 \r
341         if(NT_SUCCESS(status))\r
342         {\r
343                 WCHAR *curChild;\r
344                 child_device_info_list_t *pPrevList, *pNewDevList;\r
345 \r
346                 curChild = static_child_name;\r
347                 pPrevList = bus_globals.p_device_list;\r
348                 while(*curChild)\r
349                 {\r
350                         RtlCopyUnicodeString(&keyPath, p_param_path);\r
351                         RtlAppendUnicodeToString(&keyPath, L"\\");\r
352                         RtlAppendUnicodeToString(&keyPath, curChild);\r
353 \r
354                         pNewDevList = cl_zalloc(sizeof(child_device_info_list_t));\r
355                         if(!pNewDevList)\r
356                         {\r
357                                 BUS_TRACE(BUS_DBG_ERROR ,("Not enough memory for key_path_buffer.\n") );\r
358                                 status = STATUS_UNSUCCESSFUL;\r
359                                 goto __create_static_devices_exit;\r
360                         }\r
361                         pNewDevList->next_device_info = NULL;\r
362 \r
363                         if(pPrevList == NULL)\r
364                         {\r
365                                 bus_globals.p_device_list = pNewDevList;\r
366                         }else\r
367                         {\r
368                                 pPrevList->next_device_info = pNewDevList;\r
369                         }\r
370 \r
371                         pPrevList = pNewDevList;\r
372 \r
373                         /* get DeviceId*/\r
374                         RtlInitUnicodeString(&defaultKeyValue, L"IBA\\IPoIB\0");\r
375                         RtlInitUnicodeString( &keyValue, NULL );\r
376                         keyValue.MaximumLength = sizeof(pNewDevList->io_device_info.device_id);\r
377                         keyValue.Buffer = pNewDevList->io_device_info.device_id;\r
378 \r
379                         /* Setup the table entries. */\r
380                         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
381                         table[0].Name = L"DeviceId";\r
382                         table[0].EntryContext = &keyValue; \r
383                         table[0].DefaultType = REG_SZ;\r
384                         table[0].DefaultData = defaultKeyValue.Buffer;\r
385                         table[0].DefaultLength = defaultKeyValue.Length;\r
386 \r
387                         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
388                                 keyPath.Buffer, table, NULL, NULL );\r
389                         if(!NT_SUCCESS(status))\r
390                         {\r
391                                 BUS_TRACE(BUS_DBG_ERROR ,("Failed to read DeviceId.\n") );\r
392                                 goto __create_static_devices_exit;\r
393                         }\r
394                         pNewDevList->io_device_info.device_id_size = keyValue.Length + sizeof(WCHAR);\r
395 \r
396                         /* Get HardwareId*/\r
397                         RtlInitUnicodeString(&defaultKeyValue, L"IBA\\IPoIB\0\0");\r
398                         RtlInitUnicodeString( &keyValue, NULL );\r
399                         keyValue.MaximumLength = sizeof(pNewDevList->io_device_info.hardware_id);\r
400                         keyValue.Buffer = pNewDevList->io_device_info.hardware_id;\r
401 \r
402                         /* Setup the table entries. */\r
403                         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
404                         table[0].Name = L"HardwareId";\r
405                         table[0].EntryContext = &keyValue; \r
406                         table[0].DefaultType = REG_MULTI_SZ;\r
407                         table[0].DefaultData = defaultKeyValue.Buffer;\r
408                         table[0].DefaultLength = defaultKeyValue.Length;\r
409 \r
410                         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
411                                 keyPath.Buffer, table, NULL, NULL );\r
412                         if(!NT_SUCCESS(status))\r
413                         {\r
414                                 BUS_TRACE(BUS_DBG_ERROR ,("Failed to read HardwareId.\n") );\r
415                                 goto __create_static_devices_exit;\r
416                         }\r
417                         pNewDevList->io_device_info.hardware_id_size = keyValue.Length + 2*sizeof(WCHAR);\r
418 \r
419                         /* Get CompatibleId*/\r
420                         RtlInitUnicodeString(&defaultKeyValue, L"IBA\\SID_1000066a00020000\0\0");\r
421                         RtlInitUnicodeString( &keyValue, NULL );\r
422                         keyValue.MaximumLength = sizeof(pNewDevList->io_device_info.compatible_id);\r
423                         keyValue.Buffer = pNewDevList->io_device_info.compatible_id;\r
424 \r
425                         /* Setup the table entries. */\r
426                         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
427                         table[0].Name = L"CompatibleId";\r
428                         table[0].EntryContext = &keyValue; \r
429                         table[0].DefaultType = REG_MULTI_SZ;\r
430                         table[0].DefaultData = defaultKeyValue.Buffer;\r
431                         table[0].DefaultLength = defaultKeyValue.Length;\r
432 \r
433                         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
434                                 keyPath.Buffer, table, NULL, NULL );\r
435                         if(!NT_SUCCESS(status))\r
436                         {\r
437                                 BUS_TRACE(BUS_DBG_ERROR ,("Failed to read CompatibleId.\n") );\r
438                                 goto __create_static_devices_exit;\r
439                         }\r
440                         pNewDevList->io_device_info.compatible_id_size = keyValue.Length + 2*sizeof(WCHAR); //2 null\r
441 \r
442                         /* Get Description*/\r
443                         RtlInitUnicodeString(&defaultKeyValue, L"OpenIB IPoIB Adapter");\r
444                         RtlInitUnicodeString( &keyValue, NULL );\r
445                         keyValue.MaximumLength = sizeof(pNewDevList->io_device_info.description);\r
446                         keyValue.Buffer = pNewDevList->io_device_info.description;\r
447 \r
448                         /* Setup the table entries. */\r
449                         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
450                         table[0].Name = L"Description";\r
451                         table[0].EntryContext = &keyValue; \r
452                         table[0].DefaultType = REG_SZ;\r
453                         table[0].DefaultData = defaultKeyValue.Buffer;\r
454                         table[0].DefaultLength = defaultKeyValue.Length;\r
455 \r
456                         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
457                                 keyPath.Buffer, table, NULL, NULL );\r
458                         if(!NT_SUCCESS(status))\r
459                         {\r
460                                 BUS_TRACE(BUS_DBG_ERROR ,("Failed to read Description.\n") );\r
461                                 goto __create_static_devices_exit;\r
462                         }\r
463 \r
464                         pNewDevList->io_device_info.description_size = keyValue.Length + sizeof(WCHAR);\r
465 \r
466 \r
467                         if((pNewDevList->io_device_info.description_size > MAX_DEVICE_ID_LEN) ||\r
468                            (pNewDevList->io_device_info.hardware_id_size > MAX_DEVICE_ID_LEN) ||\r
469                            (pNewDevList->io_device_info.compatible_id_size > MAX_DEVICE_ID_LEN) ||\r
470                            (pNewDevList->io_device_info.device_id_size > MAX_DEVICE_ID_LEN)\r
471                            )\r
472                         {\r
473                                 BUS_TRACE(BUS_DBG_ERROR ,("Id or description size is too big.\n") );\r
474                                 status = STATUS_UNSUCCESSFUL;\r
475                                 goto __create_static_devices_exit;\r
476                         }\r
477 \r
478                         /* Get Pkey */\r
479                         RtlInitUnicodeString(&defaultKeyValue, L"FFFF");\r
480                         RtlInitUnicodeString( &keyValue, NULL );\r
481                         keyValue.MaximumLength = sizeof(pNewDevList->io_device_info.pkey);\r
482                         keyValue.Buffer = pNewDevList->io_device_info.pkey;\r
483 \r
484                         /* Setup the table entries. */\r
485                         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
486                         table[0].Name = L"PartitionKey";\r
487                         table[0].EntryContext = &keyValue; \r
488                         table[0].DefaultType = REG_SZ;\r
489                         table[0].DefaultData = defaultKeyValue.Buffer;\r
490                         table[0].DefaultLength = defaultKeyValue.Length;\r
491 \r
492                         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
493                                 keyPath.Buffer, table, NULL, NULL );\r
494                         if(!NT_SUCCESS(status))\r
495                         {\r
496                                 BUS_TRACE(BUS_DBG_ERROR ,("Failed to read PartitionKey.\n") );\r
497                                 goto __create_static_devices_exit;\r
498                         }\r
499 \r
500                         while(*curChild) curChild++;\r
501                         curChild++;\r
502                 }\r
503         }\r
504 \r
505 __create_static_devices_exit:\r
506         if(key_path_buffer)\r
507         {\r
508                 cl_free(key_path_buffer);\r
509         }\r
510 \r
511         if(!NT_SUCCESS(status))\r
512         {\r
513                 _free_static_iodevices();\r
514         }\r
515 \r
516         return status;\r
517 }\r
518 \r
519 static pkey_conf_t*\r
520 create_pkey_conf(pkey_conf_t **pp_cur_conf, char *guid_str, uint32_t guid_str_len)\r
521 {\r
522         NTSTATUS status;\r
523         char    tmp_char;\r
524         uint32_t tmp_val;\r
525 \r
526         if (! *pp_cur_conf)\r
527                 pp_cur_conf = &bus_globals.p_pkey_conf;\r
528         else\r
529                 pp_cur_conf = &((*pp_cur_conf)->next_conf);\r
530 \r
531         *pp_cur_conf = cl_zalloc( sizeof( pkey_conf_t ) );\r
532         if (!(*pp_cur_conf) )\r
533         {\r
534                 BUS_TRACE(BUS_DBG_ERROR ,\r
535                 ("Failed to allocate pkey configuration\n") );\r
536                 return NULL;    \r
537         }\r
538 \r
539         tmp_char = guid_str[1 + guid_str_len/2];\r
540         guid_str[1 + guid_str_len/2] = '\0';\r
541         status = RtlCharToInteger(&guid_str[2],16,(PULONG)&tmp_val);\r
542         if(! NT_SUCCESS(status))\r
543         {\r
544                 cl_free((*pp_cur_conf));\r
545                 (*pp_cur_conf) = NULL;\r
546                 BUS_TRACE(BUS_DBG_ERROR ,\r
547                 ("Failed to convert, status = 0x%08X\n",status) );\r
548                 return NULL;    \r
549         }\r
550         guid_str[1 + guid_str_len/2] = tmp_char;\r
551         (*pp_cur_conf)->pkeys_per_port.port_guid = tmp_val;\r
552 \r
553         status = RtlCharToInteger(&guid_str[1 + guid_str_len/2],16,(PULONG)&tmp_val);\r
554         if(! NT_SUCCESS(status))\r
555         {\r
556                 cl_free((*pp_cur_conf));\r
557                 (*pp_cur_conf) = NULL;\r
558                 BUS_TRACE(BUS_DBG_ERROR ,\r
559                 ("Failed to convert, status = 0x%08X\n",status) );\r
560                 return NULL;    \r
561         }\r
562         (*pp_cur_conf)->pkeys_per_port.port_guid = ((*pp_cur_conf)->pkeys_per_port.port_guid << 32) | tmp_val;\r
563         return (*pp_cur_conf);\r
564 }\r
565 \r
566 /************************************************************************\r
567 * name:         __build_pkeys_per_port\r
568 *                       extracts pkeys and port guids from registry string.\r
569 *                       builds pkey array per port\r
570 * input:        UNICODE_STRING *str\r
571 * return:       NTSTATUS\r
572 ************************************************************************/\r
573 static NTSTATUS\r
574 __build_pkeys_per_port(IN const UNICODE_STRING *str)\r
575 {\r
576         NTSTATUS    status;\r
577         ANSI_STRING ansi_str;\r
578         uint32_t i,j;\r
579         char *p_end, *p_start;\r
580         boolean_t       port_guid_found;\r
581         pkey_conf_t     *cur_pkey_conf = NULL;\r
582         char tmp_guid[32] = {'\0'};\r
583         p_start = NULL;\r
584 \r
585         status = RtlUnicodeStringToAnsiString(&ansi_str,str,TRUE);\r
586         if(! NT_SUCCESS(status))\r
587         {\r
588                 BUS_TRACE(BUS_DBG_ERROR ,\r
589                 ("RtlUnicodeStringToAnsiString returned 0x%.8x\n", status) );\r
590                 return status;\r
591         }\r
592 \r
593         port_guid_found = FALSE;\r
594         j = 0;\r
595         for ( i = 0; i < ansi_str.MaximumLength; i++)\r
596         {\r
597                 if(! port_guid_found)\r
598                 {\r
599                         if(ansi_str.Buffer[i] == ':')\r
600                         {\r
601                                 port_guid_found = TRUE;\r
602                                 tmp_guid[j] = '\0';\r
603                                 cur_pkey_conf = create_pkey_conf(&cur_pkey_conf,(char*)tmp_guid,j);\r
604                                 if(! cur_pkey_conf)\r
605                                 {\r
606                                    RtlFreeAnsiString(&ansi_str);\r
607                                    BUS_TRACE(BUS_DBG_ERROR ,\r
608                                    ("Failed to create pkey configuration\n"));\r
609                                    return STATUS_INVALID_PARAMETER;\r
610                                 }\r
611                             RtlZeroMemory(tmp_guid,sizeof(tmp_guid));\r
612                                 j = 0;\r
613                                 p_start = NULL;\r
614                         }\r
615                         else\r
616                         {\r
617                                 tmp_guid[j] = ansi_str.Buffer[i]; \r
618                                 j++;\r
619                                 continue;\r
620                         }\r
621                 }\r
622                 else\r
623                 {\r
624                         if(!p_start)\r
625                                 p_start = &ansi_str.Buffer[i]; \r
626 \r
627                         if(ansi_str.Buffer[i] == ';')\r
628                         {\r
629                                 p_end = &ansi_str.Buffer[i];\r
630                                 ansi_str.Buffer[i] = '\0';\r
631                                 __prepare_pKey_array(p_start,(size_t)(p_end - p_start) + 1,&cur_pkey_conf->pkeys_per_port);\r
632 \r
633                                 ansi_str.Buffer[i] = ';';\r
634                                 p_start = NULL;\r
635                                 port_guid_found = FALSE;\r
636                         }\r
637                 }\r
638         }\r
639     RtlFreeAnsiString(&ansi_str);\r
640         return STATUS_SUCCESS;\r
641 }\r
642 \r
643 static NTSTATUS\r
644 __read_registry(\r
645         IN                              UNICODE_STRING* const           p_registry_path )\r
646 {\r
647         NTSTATUS                                        status;\r
648         /* Remember the terminating entry in the table below. */\r
649         RTL_QUERY_REGISTRY_TABLE        table[12];\r
650         UNICODE_STRING                          param_path;\r
651         UNICODE_STRING                          pkeyString;\r
652         UNICODE_STRING                          empty_string;\r
653 \r
654         BUS_ENTER( BUS_DBG_DRV );\r
655 \r
656         __read_machine_name();\r
657 \r
658         RtlInitUnicodeString( &empty_string,NULL);\r
659         RtlInitUnicodeString( &param_path, NULL );\r
660         param_path.MaximumLength = p_registry_path->Length + \r
661                 sizeof(L"\\Parameters");\r
662         param_path.Buffer = cl_zalloc( param_path.MaximumLength );\r
663         if( !param_path.Buffer )\r
664         {\r
665                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
666                         ("Failed to allocate parameters path buffer.\n") );\r
667                 return STATUS_INSUFFICIENT_RESOURCES;\r
668         }\r
669 \r
670         RtlAppendUnicodeStringToString( &param_path, p_registry_path );\r
671         RtlAppendUnicodeToString( &param_path, L"\\Parameters" );\r
672         RtlInitUnicodeString( &pkeyString, NULL );\r
673     pkeyString.MaximumLength = 1024*sizeof(WCHAR);\r
674     pkeyString.Buffer = cl_zalloc( pkeyString.MaximumLength );\r
675     if( !pkeyString.Buffer )\r
676         {\r
677                 cl_free(param_path.Buffer);\r
678                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
679                       ("Failed to allocate parameters path pkeyString.\n") );\r
680         return STATUS_INSUFFICIENT_RESOURCES;\r
681     }\r
682 \r
683         /*\r
684          * Clear the table.  This clears all the query callback pointers,\r
685          * and sets up the terminating table entry.\r
686          */\r
687         cl_memclr( table, sizeof(table) );\r
688 \r
689         /* Setup the table entries. */\r
690         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
691         table[0].Name = L"ReportPortNIC";\r
692         table[0].EntryContext = &bus_globals.b_report_port_nic;\r
693         table[0].DefaultType = REG_DWORD;\r
694         table[0].DefaultData = &bus_globals.b_report_port_nic;\r
695         table[0].DefaultLength = sizeof(ULONG);\r
696 \r
697         table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
698         table[1].Name = L"DebugFlags";\r
699         table[1].EntryContext = &bus_globals.dbg_lvl;\r
700         table[1].DefaultType = REG_DWORD;\r
701         table[1].DefaultData = &bus_globals.dbg_lvl;\r
702         table[1].DefaultLength = sizeof(ULONG);\r
703 \r
704         table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
705         table[2].Name = L"IbalDebugLevel";\r
706         table[2].EntryContext = &g_al_dbg_level;\r
707         table[2].DefaultType = REG_DWORD;\r
708         table[2].DefaultData = &g_al_dbg_level;\r
709         table[2].DefaultLength = sizeof(ULONG);\r
710 \r
711         table[3].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
712         table[3].Name = L"IbalDebugFlags";\r
713         table[3].EntryContext = &g_al_dbg_flags;\r
714         table[3].DefaultType = REG_DWORD;\r
715         table[3].DefaultData = &g_al_dbg_flags;\r
716         table[3].DefaultLength = sizeof(ULONG);\r
717         \r
718 \r
719         table[4].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
720         table[4].Name = L"SmiPollInterval";\r
721         table[4].EntryContext = &g_smi_poll_interval;\r
722         table[4].DefaultType = REG_DWORD;\r
723         table[4].DefaultData = &g_smi_poll_interval;\r
724         table[4].DefaultLength = sizeof(ULONG);\r
725 \r
726         table[5].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
727         table[5].Name = L"IocQueryTimeout";\r
728         table[5].EntryContext = &g_ioc_query_timeout;\r
729         table[5].DefaultType = REG_DWORD;\r
730         table[5].DefaultData = &g_ioc_query_timeout;\r
731         table[5].DefaultLength = sizeof(ULONG);\r
732 \r
733         table[6].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
734         table[6].Name = L"IocQueryRetries";\r
735         table[6].EntryContext = &g_ioc_query_retries;\r
736         table[6].DefaultType = REG_DWORD;\r
737         table[6].DefaultData = &g_ioc_query_retries;\r
738         table[6].DefaultLength = sizeof(ULONG);\r
739 \r
740         table[7].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
741         table[7].Name = L"IocPollInterval";\r
742         table[7].EntryContext = &g_ioc_poll_interval;\r
743         table[7].DefaultType = REG_DWORD;\r
744         table[7].DefaultData = &g_ioc_poll_interval;\r
745         table[7].DefaultLength = sizeof(ULONG);\r
746 \r
747         table[8].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
748         table[8].Name = L"PartitionKey";\r
749         table[8].EntryContext = &pkeyString;\r
750         table[8].DefaultType  = REG_SZ;\r
751         table[8].DefaultData  = &empty_string;\r
752         table[8].DefaultLength = 0;\r
753 \r
754         /* Have at it! */\r
755         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
756                 param_path.Buffer, table, NULL, NULL );\r
757         if (NT_SUCCESS(status))\r
758         {\r
759                         if( !NT_SUCCESS(__build_pkeys_per_port(&pkeyString)))\r
760                                 BUS_TRACE(BUS_DBG_ERROR ,\r
761                                                  ("Failed to build pkey configuration\n"));\r
762 \r
763                         if(!NT_SUCCESS(__create_static_devices(&param_path))){\r
764                                 BUS_TRACE(BUS_DBG_ERROR ,\r
765                                                  ("Failed to create devices\n"));\r
766                         }\r
767         }\r
768 #if DBG & !defined( EVENT_TRACING )\r
769         if( g_al_dbg_flags & AL_DBG_ERR )\r
770                 g_al_dbg_flags |= CL_DBG_ERROR;\r
771 \r
772         //bus_globals.dbg_lvl |= BUS_DBG_DRV | BUS_DBG_PNP | BUS_DBG_POWER;\r
773 #endif\r
774 \r
775         BUS_TRACE(BUS_DBG_DRV ,\r
776                         ("debug level %d debug flags 0x%.8x\n",\r
777                         g_al_dbg_level,\r
778                         g_al_dbg_flags));\r
779 \r
780         cl_free( pkeyString.Buffer );\r
781         cl_free( param_path.Buffer );\r
782         BUS_EXIT( BUS_DBG_DRV );\r
783         return status;\r
784 }\r
785 \r
786 \r
787 static NTSTATUS\r
788 bus_drv_open(\r
789         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
790         IN                              IRP                                                     *p_irp )\r
791 {\r
792         UNUSED_PARAM( p_dev_obj );\r
793 \r
794         CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );\r
795 \r
796         /* We always succeed file handles creation. */\r
797         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
798         p_irp->IoStatus.Information = 0;\r
799         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
800 \r
801         return STATUS_SUCCESS;\r
802 }\r
803 \r
804 \r
805 static NTSTATUS\r
806 bus_drv_cleanup(\r
807         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
808         IN                              IRP                                                     *p_irp )\r
809 {\r
810         NTSTATUS                        status;\r
811 \r
812         UNUSED_PARAM( p_dev_obj );\r
813 \r
814         CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );\r
815 \r
816         /*\r
817          * Note that we don't acquire the remove and stop lock on close to allow\r
818          * applications to close the device when the locks are already held.\r
819          */\r
820         status = cl_to_ntstatus( al_dev_close( p_irp ) );\r
821 \r
822         /* Complete the IRP. */\r
823         p_irp->IoStatus.Status = status;\r
824         p_irp->IoStatus.Information = 0;\r
825         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
826 \r
827         return status;\r
828 }\r
829 \r
830 \r
831 static NTSTATUS\r
832 bus_drv_close(\r
833         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
834         IN                              IRP                                                     *p_irp )\r
835 {\r
836         UNUSED_PARAM( p_dev_obj );\r
837 \r
838         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
839         p_irp->IoStatus.Information = 0;\r
840         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
841 \r
842         return STATUS_SUCCESS;\r
843 }\r
844 \r
845 \r
846 static NTSTATUS\r
847 bus_drv_ioctl(\r
848         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
849         IN                              IRP                                                     *p_irp )\r
850 {\r
851         NTSTATUS                        status;\r
852         bus_fdo_ext_t           *p_ext;\r
853         PIO_STACK_LOCATION      p_io_stack;\r
854 \r
855         /* Get the extension. */\r
856         p_ext = p_dev_obj->DeviceExtension;\r
857 \r
858         /* Get the stack location. */\r
859         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
860 \r
861         /* Acquire the stop lock. */\r
862         status = IoAcquireRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );\r
863         if( !NT_SUCCESS( status ) )\r
864         {\r
865                 p_irp->IoStatus.Status = status;\r
866                 p_irp->IoStatus.Information = 0;\r
867                 IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
868                 BUS_EXIT( BUS_DBG_DRV );\r
869                 return status;\r
870         }\r
871 \r
872         /* Acquire the remove lock. */\r
873         status = IoAcquireRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
874         if( !NT_SUCCESS( status ) )\r
875         {\r
876                 IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );\r
877                 p_irp->IoStatus.Status = status;\r
878                 p_irp->IoStatus.Information = 0;\r
879                 IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
880                 BUS_EXIT( BUS_DBG_DRV );\r
881                 return status;\r
882         }\r
883         \r
884         status = cl_to_ntstatus( al_dev_ioctl( p_irp ) );\r
885         \r
886         /* Only pass down if not handled and not PDO device. */\r
887         if( status == STATUS_INVALID_DEVICE_REQUEST && p_ext->cl_ext.p_next_do )\r
888         {\r
889                 IoSkipCurrentIrpStackLocation( p_irp );\r
890                 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
891         }\r
892 \r
893         /* Release the remove and stop locks. */\r
894         IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
895         IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );\r
896 \r
897         return status;\r
898 }\r
899 \r
900 cl_status_t\r
901 bus_add_pkey(cl_ioctl_handle_t                  h_ioctl)\r
902 {\r
903         cl_status_t                             status;\r
904         pkey_array_t                            *pkeys;\r
905         PIO_STACK_LOCATION                      pIoStack;\r
906 \r
907         BUS_ENTER( BUS_DBG_DRV );\r
908 \r
909         pIoStack = IoGetCurrentIrpStackLocation(h_ioctl);\r
910         if ( (! h_ioctl->AssociatedIrp.SystemBuffer) || \r
911                  pIoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof (pkey_array_t))\r
912         {\r
913                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
914                         ("Invalid parameters.\n") );\r
915                 return CL_INVALID_PARAMETER;\r
916         }\r
917 \r
918         pkeys =  (pkey_array_t*)h_ioctl->AssociatedIrp.SystemBuffer;\r
919 \r
920         /* create additional pdo */\r
921         status = port_mgr_pkey_add(pkeys);\r
922         if (! NT_SUCCESS(status))\r
923         {\r
924                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
925                         ("port_mgr_pkey_add returned %08x.\n", status) );\r
926         }\r
927 \r
928         BUS_EXIT( BUS_DBG_DRV );\r
929         return status;\r
930 }\r
931 \r
932 cl_status_t\r
933 bus_rem_pkey(cl_ioctl_handle_t                  h_ioctl)\r
934 {\r
935         cl_status_t                             status;\r
936         pkey_array_t                            *pkeys;\r
937         PIO_STACK_LOCATION                      pIoStack;\r
938 \r
939         BUS_ENTER( BUS_DBG_DRV );\r
940 \r
941         pIoStack = IoGetCurrentIrpStackLocation(h_ioctl);\r
942         if ( (! h_ioctl->AssociatedIrp.SystemBuffer) || \r
943                  pIoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof (pkey_array_t))\r
944         {\r
945                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
946                         ("Invalid parameters.\n") );\r
947                 return CL_INVALID_PARAMETER;\r
948         }\r
949 \r
950         pkeys =  (pkey_array_t*)h_ioctl->AssociatedIrp.SystemBuffer;\r
951 \r
952         /* removes pdo */\r
953         status = port_mgr_pkey_rem(pkeys);\r
954         if (! NT_SUCCESS(status))\r
955         {\r
956                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
957                         ("port_mgr_pkey_rem returned %08x.\n", status) );\r
958         }\r
959 \r
960         BUS_EXIT( BUS_DBG_DRV );\r
961         return status;\r
962 }\r
963 static NTSTATUS\r
964 bus_drv_sysctl(\r
965         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
966         IN                              IRP                                                     *p_irp )\r
967 {\r
968         NTSTATUS                status;\r
969         bus_fdo_ext_t   *p_ext;\r
970 \r
971         BUS_ENTER( BUS_DBG_DRV );\r
972 \r
973         CL_ASSERT( p_dev_obj );\r
974         CL_ASSERT( p_irp );\r
975 \r
976         p_ext = p_dev_obj->DeviceExtension;\r
977 \r
978         if( p_ext->cl_ext.p_next_do )\r
979         {\r
980                 IoSkipCurrentIrpStackLocation( p_irp );\r
981                 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
982         }\r
983         else\r
984         {\r
985                 status = p_irp->IoStatus.Status;\r
986                 IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
987         }\r
988 \r
989         BUS_EXIT( BUS_DBG_DRV );\r
990         return status;\r
991 }\r
992 \r
993 \r
994 static void\r
995 bus_drv_unload(\r
996         IN                              DRIVER_OBJECT                           *p_driver_obj )\r
997 {\r
998         pkey_conf_t *cur_conf,*tmp;\r
999         UNUSED_PARAM( p_driver_obj );\r
1000 \r
1001         BUS_ENTER( BUS_DBG_DRV );\r
1002         \r
1003         cur_conf = bus_globals.p_pkey_conf;\r
1004         while(cur_conf)\r
1005         {\r
1006                 tmp = cur_conf;\r
1007                 cur_conf = cur_conf->next_conf;\r
1008                 cl_free(tmp);\r
1009         }\r
1010 \r
1011         _free_static_iodevices();\r
1012 \r
1013 \r
1014         CL_DEINIT;\r
1015 \r
1016 #if defined(EVENT_TRACING)\r
1017         WPP_CLEANUP(p_driver_obj);\r
1018 #endif\r
1019 \r
1020         BUS_TRACE_EXIT( BUS_DBG_DRV, \r
1021                 ("=====> IBBUS: bus_drv_unload exited\n") );\r
1022 }\r
1023 \r
1024 \r
1025 NTSTATUS\r
1026 DriverEntry(\r
1027         IN                              DRIVER_OBJECT                           *p_driver_obj,\r
1028         IN                              UNICODE_STRING                          *p_registry_path )\r
1029 {\r
1030         NTSTATUS                status;\r
1031 \r
1032         BUS_ENTER( BUS_DBG_DRV );\r
1033 \r
1034 #if defined(EVENT_TRACING)\r
1035         WPP_INIT_TRACING(p_driver_obj ,p_registry_path);\r
1036 #endif\r
1037 \r
1038         status = CL_INIT;\r
1039         if( !NT_SUCCESS(status) )\r
1040         {\r
1041                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1042                         ("cl_init returned %08X.\n", status) );\r
1043                 return status;\r
1044         }\r
1045 \r
1046         /* Store the driver object pointer in the global parameters. */\r
1047         bus_globals.p_driver_obj = p_driver_obj;\r
1048 \r
1049         /* Get the registry values. */\r
1050         status = __read_registry( p_registry_path );\r
1051         if( !NT_SUCCESS(status) )\r
1052         {\r
1053                 CL_DEINIT;\r
1054                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
1055                         ("__read_registry returned %08x.\n", status) );\r
1056                 return status;\r
1057         }\r
1058 \r
1059         /* create default device descrition for Partition Manager */\r
1060         __create_default_dev_info( &g_default_device_info );\r
1061         \r
1062         /* Setup the entry points. */\r
1063         p_driver_obj->MajorFunction[IRP_MJ_CREATE] = bus_drv_open;\r
1064         p_driver_obj->MajorFunction[IRP_MJ_CLEANUP] = bus_drv_cleanup;\r
1065         p_driver_obj->MajorFunction[IRP_MJ_CLOSE] = bus_drv_close;\r
1066         p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;\r
1067         p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;\r
1068         p_driver_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = bus_drv_ioctl;\r
1069         p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = bus_drv_sysctl;\r
1070         p_driver_obj->DriverUnload = bus_drv_unload;\r
1071         p_driver_obj->DriverExtension->AddDevice = bus_add_device;\r
1072 \r
1073         // Mutex to synchronize multiple threads creating & deleting \r
1074         // control deviceobjects. \r
1075 \r
1076         KeInitializeEvent(&g_ControlEvent, SynchronizationEvent, TRUE);\r
1077         g_bfi_InstanceCount = 0;\r
1078         memset(  __out_bcount(sizeof(g_bus_filters)) (void*)g_bus_filters, 0,\r
1079                         sizeof(g_bus_filters) );\r
1080         \r
1081         BUS_TRACE_EXIT( BUS_DBG_DRV, \r
1082                 ("=====> IBBUS: Driver exited\n") );\r
1083         return STATUS_SUCCESS;\r
1084 }\r