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