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