63599f40b134637b206c9b5bff8a3e0ea4fd1652
[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 };\r
71 \r
72 static void\r
73 __read_machine_name( void );\r
74 \r
75 static NTSTATUS\r
76 __read_registry(\r
77         IN                              UNICODE_STRING* const           p_Param_Path );\r
78 \r
79 static NTSTATUS\r
80 bus_drv_open(\r
81         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
82         IN                              IRP                                                     *p_irp );\r
83 \r
84 static NTSTATUS\r
85 bus_drv_cleanup(\r
86         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
87         IN                              IRP                                                     *p_irp );\r
88 \r
89 static NTSTATUS\r
90 bus_drv_close(\r
91         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
92         IN                              IRP                                                     *p_irp );\r
93 \r
94 static NTSTATUS\r
95 bus_drv_ioctl(\r
96         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
97         IN                              IRP                                                     *p_irp );\r
98 \r
99 /***f* InfiniBand Bus Driver/bus_drv_sysctl\r
100 * NAME\r
101 *       bus_drv_sysctl\r
102 *\r
103 * DESCRIPTION\r
104 *       Entry point for handling WMI IRPs.\r
105 *\r
106 * SYNOPSIS\r
107 */\r
108 static NTSTATUS\r
109 bus_drv_sysctl(\r
110         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
111         IN                              IRP                                                     *p_irp );\r
112 /**********/\r
113 \r
114 static void\r
115 bus_drv_unload(\r
116         IN                              DRIVER_OBJECT                           *p_driver_obj );\r
117 \r
118 NTSTATUS\r
119 DriverEntry(\r
120         IN                              DRIVER_OBJECT                           *p_driver_obj,\r
121         IN                              UNICODE_STRING                          *p_registry_path );\r
122 \r
123 \r
124 #ifdef ALLOC_PRAGMA\r
125 #pragma alloc_text (INIT, DriverEntry)\r
126 #pragma alloc_text (INIT, __read_machine_name)\r
127 #pragma alloc_text (INIT, __read_registry)\r
128 #pragma alloc_text (PAGE, bus_drv_unload)\r
129 #pragma alloc_text (PAGE, bus_drv_open)\r
130 #pragma alloc_text (PAGE, bus_drv_close)\r
131 #pragma alloc_text (PAGE, bus_drv_ioctl)\r
132 #pragma alloc_text (PAGE_PNP, bus_drv_sysctl)\r
133 #endif\r
134 \r
135 \r
136 static void\r
137 __read_machine_name( void )\r
138 {\r
139         NTSTATUS                                        status;\r
140         /* Remember the terminating entry in the table below. */\r
141         RTL_QUERY_REGISTRY_TABLE        table[2];\r
142         UNICODE_STRING                          hostNamePath;\r
143         UNICODE_STRING                          hostNameW;\r
144         ANSI_STRING                                     hostName;\r
145 \r
146         BUS_ENTER( BUS_DBG_DRV );\r
147 \r
148         /* Get the host name. */\r
149         RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" );\r
150         RtlInitUnicodeString( &hostNameW, NULL );\r
151 \r
152         /*\r
153          * Clear the table.  This clears all the query callback pointers,\r
154          * and sets up the terminating table entry.\r
155          */\r
156         cl_memclr( table, sizeof(table) );\r
157         cl_memclr( node_desc, sizeof(node_desc) );\r
158 \r
159         /* Setup the table entries. */\r
160         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;\r
161         table[0].Name = L"ComputerName";\r
162         table[0].EntryContext = &hostNameW;\r
163         table[0].DefaultType = REG_SZ;\r
164         table[0].DefaultData = &hostNameW;\r
165         table[0].DefaultLength = 0;\r
166 \r
167         /* Have at it! */\r
168         status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL, \r
169                 hostNamePath.Buffer, table, NULL, NULL );\r
170         if( NT_SUCCESS( status ) )\r
171         {\r
172                 /* Convert the UNICODE host name to UTF-8 (ASCII). */\r
173                 hostName.Length = 0;\r
174                 hostName.MaximumLength = sizeof(node_desc);\r
175                 hostName.Buffer = node_desc;\r
176                 status = RtlUnicodeStringToAnsiString( &hostName, &hostNameW, FALSE );\r
177                 RtlFreeUnicodeString( &hostNameW );\r
178         }\r
179         else\r
180         {\r
181                 BUS_TRACE(BUS_DBG_ERROR , ("Failed to get host name.\n") );\r
182                 /* Use the default name... */\r
183                 RtlStringCbCopyNA( node_desc, sizeof(node_desc),\r
184                         DEFAULT_NODE_DESC, sizeof(DEFAULT_NODE_DESC) );\r
185         }\r
186         BUS_EXIT( BUS_DBG_DRV );\r
187 }\r
188 \r
189 /************************************************************************************\r
190 * name  :       __prepare_pKey_array\r
191 *           parses registry string and exrtacts pkey value(s) from it.\r
192 *                       pkey pattern is 0xABCD\r
193 * input :       UNICODE_STRING *str\r
194 * output:       pkey_array\r
195 * return:       uint16_t number of pkey(s) found\r
196 *************************************************************************************/\r
197 static void __prepare_pKey_array(IN const char *str, size_t str_len,OUT pkey_array_t *cur_pkey)\r
198 {\r
199         NTSTATUS status;\r
200         size_t i;\r
201         uint8_t j;\r
202         char pkey_str[7];\r
203         ULONG   tmp_val;\r
204         BUS_ENTER( BUS_DBG_DRV );\r
205 \r
206         CL_ASSERT(cur_pkey);\r
207         CL_ASSERT(str);\r
208 \r
209         cur_pkey->pkey_num = 0;\r
210         j = 0;\r
211 \r
212         for (i = 0; (i < str_len) && (cur_pkey->pkey_num < MAX_NUM_PKEY) ; i++)\r
213     {\r
214                 if(str[i] == ' ')\r
215                         continue;\r
216 \r
217                 if( (str[i] != ',') && (str[i] != '\0'))\r
218                 {\r
219                     if(j >= 7)\r
220                         {\r
221                                 BUS_TRACE(BUS_DBG_ERROR ,\r
222                                 ("Incorrect format of pkey value\n") );\r
223                                 break;\r
224                         }\r
225                         pkey_str[j] = str[i];\r
226                         j++;\r
227                 }\r
228                 else\r
229                 {\r
230                         pkey_str[j] = '\0';\r
231                         status = RtlCharToInteger(&pkey_str[2],16,&tmp_val);\r
232                         if(! NT_SUCCESS(status))\r
233                         {\r
234                                 BUS_TRACE(BUS_DBG_ERROR ,\r
235                                 ("Failed to convert, status = 0x%08X\n",status) );\r
236                                 break;   \r
237                         }\r
238                         cur_pkey->pkey_array[cur_pkey->pkey_num++] = (uint16_t)tmp_val;\r
239                         j = 0;\r
240                 }\r
241         }\r
242         BUS_EXIT( BUS_DBG_DRV );\r
243 }\r
244 \r
245 static pkey_conf_t*\r
246 create_pkey_conf(pkey_conf_t **pp_cur_conf, char *guid_str, uint32_t guid_str_len)\r
247 {\r
248         NTSTATUS status;\r
249         char    tmp_char;\r
250         uint32_t tmp_val;\r
251 \r
252         if (! *pp_cur_conf)\r
253                 pp_cur_conf = &bus_globals.p_pkey_conf;\r
254         else\r
255                 pp_cur_conf = &((*pp_cur_conf)->next_conf);\r
256 \r
257         *pp_cur_conf = cl_zalloc( sizeof( pkey_conf_t ) );\r
258         if (!(*pp_cur_conf) )\r
259         {\r
260                 BUS_TRACE(BUS_DBG_ERROR ,\r
261                 ("Failed to allocate pkey configuration\n") );\r
262                 return NULL;    \r
263         }\r
264 \r
265         tmp_char = guid_str[1 + guid_str_len/2];\r
266         guid_str[1 + guid_str_len/2] = '\0';\r
267         status = RtlCharToInteger(&guid_str[2],16,(PULONG)&tmp_val);\r
268         if(! NT_SUCCESS(status))\r
269         {\r
270                 cl_free((*pp_cur_conf));\r
271                 (*pp_cur_conf) = NULL;\r
272                 BUS_TRACE(BUS_DBG_ERROR ,\r
273                 ("Failed to convert, status = 0x%08X\n",status) );\r
274                 return NULL;    \r
275         }\r
276         guid_str[1 + guid_str_len/2] = tmp_char;\r
277         (*pp_cur_conf)->pkeys_per_port.port_guid = tmp_val;\r
278 \r
279         status = RtlCharToInteger(&guid_str[1 + guid_str_len/2],16,(PULONG)&tmp_val);\r
280         if(! NT_SUCCESS(status))\r
281         {\r
282                 cl_free((*pp_cur_conf));\r
283                 (*pp_cur_conf) = NULL;\r
284                 BUS_TRACE(BUS_DBG_ERROR ,\r
285                 ("Failed to convert, status = 0x%08X\n",status) );\r
286                 return NULL;    \r
287         }\r
288         (*pp_cur_conf)->pkeys_per_port.port_guid = ((*pp_cur_conf)->pkeys_per_port.port_guid << 32) | tmp_val;\r
289         return (*pp_cur_conf);\r
290 }\r
291 \r
292 /************************************************************************\r
293 * name:         __build_pkeys_per_port\r
294 *                       extracts pkeys and port guids from registry string.\r
295 *                       builds pkey array per port\r
296 * input:        UNICODE_STRING *str\r
297 * return:       NTSTATUS\r
298 ************************************************************************/\r
299 static NTSTATUS\r
300 __build_pkeys_per_port(IN const UNICODE_STRING *str)\r
301 {\r
302         NTSTATUS    status;\r
303         ANSI_STRING ansi_str;\r
304         uint32_t i,j;\r
305         char *p_end, *p_start;\r
306         boolean_t       port_guid_found;\r
307         pkey_conf_t     *cur_pkey_conf = NULL;\r
308         char tmp_guid[32] = {'\0'};\r
309         p_start = NULL;\r
310 \r
311         status = RtlUnicodeStringToAnsiString(&ansi_str,str,TRUE);\r
312         if(! NT_SUCCESS(status))\r
313         {\r
314                 BUS_TRACE(BUS_DBG_ERROR ,\r
315                 ("RtlUnicodeStringToAnsiString returned 0x%.8x\n", status) );\r
316                 return status;\r
317         }\r
318 \r
319         port_guid_found = FALSE;\r
320         j = 0;\r
321         for ( i = 0; i < ansi_str.MaximumLength; i++)\r
322         {\r
323                 if(! port_guid_found)\r
324                 {\r
325                         if(ansi_str.Buffer[i] == ':')\r
326                         {\r
327                                 port_guid_found = TRUE;\r
328                                 tmp_guid[j] = '\0';\r
329                                 cur_pkey_conf = create_pkey_conf(&cur_pkey_conf,(char*)tmp_guid,j);\r
330                                 if(! cur_pkey_conf)\r
331                                 {\r
332                                    RtlFreeAnsiString(&ansi_str);\r
333                                    BUS_TRACE(BUS_DBG_ERROR ,\r
334                                    ("Failed to create pkey configuration\n"));\r
335                                    return STATUS_INVALID_PARAMETER;\r
336                                 }\r
337                             RtlZeroMemory(tmp_guid,sizeof(tmp_guid));\r
338                                 j = 0;\r
339                                 p_start = NULL;\r
340                         }\r
341                         else\r
342                         {\r
343                                 tmp_guid[j] = ansi_str.Buffer[i]; \r
344                                 j++;\r
345                                 continue;\r
346                         }\r
347                 }\r
348                 else\r
349                 {\r
350                         if(!p_start)\r
351                                 p_start = &ansi_str.Buffer[i]; \r
352 \r
353                         if(ansi_str.Buffer[i] == ';')\r
354                         {\r
355                                 p_end = &ansi_str.Buffer[i];\r
356                                 ansi_str.Buffer[i] = '\0';\r
357                                 __prepare_pKey_array(p_start,(size_t)(p_end - p_start) + 1,&cur_pkey_conf->pkeys_per_port);\r
358 \r
359                                 ansi_str.Buffer[i] = ';';\r
360                                 p_start = NULL;\r
361                                 port_guid_found = FALSE;\r
362                         }\r
363                 }\r
364         }\r
365     RtlFreeAnsiString(&ansi_str);\r
366         return STATUS_SUCCESS;\r
367 }\r
368 \r
369 static NTSTATUS\r
370 __read_registry(\r
371         IN                              UNICODE_STRING* const           p_registry_path )\r
372 {\r
373         NTSTATUS                                        status;\r
374         /* Remember the terminating entry in the table below. */\r
375         RTL_QUERY_REGISTRY_TABLE        table[12];\r
376         UNICODE_STRING                          param_path;\r
377         UNICODE_STRING                          pkeyString;\r
378         UNICODE_STRING                          empty_string;\r
379 \r
380         BUS_ENTER( BUS_DBG_DRV );\r
381 \r
382         __read_machine_name();\r
383 \r
384         RtlInitUnicodeString( &empty_string,NULL);\r
385         RtlInitUnicodeString( &param_path, NULL );\r
386         param_path.MaximumLength = p_registry_path->Length + \r
387                 sizeof(L"\\Parameters");\r
388         param_path.Buffer = cl_zalloc( param_path.MaximumLength );\r
389         if( !param_path.Buffer )\r
390         {\r
391                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
392                         ("Failed to allocate parameters path buffer.\n") );\r
393                 return STATUS_INSUFFICIENT_RESOURCES;\r
394         }\r
395 \r
396         RtlAppendUnicodeStringToString( &param_path, p_registry_path );\r
397         RtlAppendUnicodeToString( &param_path, L"\\Parameters" );\r
398         RtlInitUnicodeString( &pkeyString, NULL );\r
399     pkeyString.MaximumLength = 1024*sizeof(WCHAR);\r
400     pkeyString.Buffer = cl_zalloc( pkeyString.MaximumLength );\r
401     if( !pkeyString.Buffer )\r
402         {\r
403                 cl_free(param_path.Buffer);\r
404                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
405                       ("Failed to allocate parameters path pkeyString.\n") );\r
406         return STATUS_INSUFFICIENT_RESOURCES;\r
407     }\r
408 \r
409         /*\r
410          * Clear the table.  This clears all the query callback pointers,\r
411          * and sets up the terminating table entry.\r
412          */\r
413         cl_memclr( table, sizeof(table) );\r
414 \r
415         /* Setup the table entries. */\r
416         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
417         table[0].Name = L"ReportPortNIC";\r
418         table[0].EntryContext = &bus_globals.b_report_port_nic;\r
419         table[0].DefaultType = REG_DWORD;\r
420         table[0].DefaultData = &bus_globals.b_report_port_nic;\r
421         table[0].DefaultLength = sizeof(ULONG);\r
422 \r
423         table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
424         table[1].Name = L"DebugFlags";\r
425         table[1].EntryContext = &bus_globals.dbg_lvl;\r
426         table[1].DefaultType = REG_DWORD;\r
427         table[1].DefaultData = &bus_globals.dbg_lvl;\r
428         table[1].DefaultLength = sizeof(ULONG);\r
429 \r
430         table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
431         table[2].Name = L"IbalDebugLevel";\r
432         table[2].EntryContext = &g_al_dbg_level;\r
433         table[2].DefaultType = REG_DWORD;\r
434         table[2].DefaultData = &g_al_dbg_level;\r
435         table[2].DefaultLength = sizeof(ULONG);\r
436 \r
437         table[3].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
438         table[3].Name = L"IbalDebugFlags";\r
439         table[3].EntryContext = &g_al_dbg_flags;\r
440         table[3].DefaultType = REG_DWORD;\r
441         table[3].DefaultData = &g_al_dbg_flags;\r
442         table[3].DefaultLength = sizeof(ULONG);\r
443         \r
444 \r
445         table[4].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
446         table[4].Name = L"SmiPollInterval";\r
447         table[4].EntryContext = &g_smi_poll_interval;\r
448         table[4].DefaultType = REG_DWORD;\r
449         table[4].DefaultData = &g_smi_poll_interval;\r
450         table[4].DefaultLength = sizeof(ULONG);\r
451 \r
452         table[5].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
453         table[5].Name = L"IocQueryTimeout";\r
454         table[5].EntryContext = &g_ioc_query_timeout;\r
455         table[5].DefaultType = REG_DWORD;\r
456         table[5].DefaultData = &g_ioc_query_timeout;\r
457         table[5].DefaultLength = sizeof(ULONG);\r
458 \r
459         table[6].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
460         table[6].Name = L"IocQueryRetries";\r
461         table[6].EntryContext = &g_ioc_query_retries;\r
462         table[6].DefaultType = REG_DWORD;\r
463         table[6].DefaultData = &g_ioc_query_retries;\r
464         table[6].DefaultLength = sizeof(ULONG);\r
465 \r
466         table[7].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
467         table[7].Name = L"IocPollInterval";\r
468         table[7].EntryContext = &g_ioc_poll_interval;\r
469         table[7].DefaultType = REG_DWORD;\r
470         table[7].DefaultData = &g_ioc_poll_interval;\r
471         table[7].DefaultLength = sizeof(ULONG);\r
472 \r
473         table[8].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
474         table[8].Name = L"PartitionKey";\r
475         table[8].EntryContext = &pkeyString;\r
476         table[8].DefaultType  = REG_SZ;\r
477         table[8].DefaultData  = &empty_string;\r
478         table[8].DefaultLength = 0;\r
479 \r
480         /* Have at it! */\r
481         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
482                 param_path.Buffer, table, NULL, NULL );\r
483         if (NT_SUCCESS(status))\r
484         {\r
485                         if( !NT_SUCCESS(__build_pkeys_per_port(&pkeyString)))\r
486                                 BUS_TRACE(BUS_DBG_ERROR ,\r
487                                                  ("Failed to build pkey configuration\n"));\r
488         }\r
489 #if DBG\r
490         if( g_al_dbg_flags & AL_DBG_ERR )\r
491                 g_al_dbg_flags |= CL_DBG_ERROR;\r
492 \r
493 //      bus_globals.dbg_lvl |= BUS_DBG_DRV | BUS_DBG_PNP;\r
494 #endif\r
495 \r
496         BUS_TRACE(BUS_DBG_DRV ,\r
497                         ("debug level %d debug flags 0x%.8x\n",\r
498                         g_al_dbg_level,\r
499                         g_al_dbg_flags));\r
500 \r
501         cl_free( pkeyString.Buffer );\r
502         cl_free( param_path.Buffer );\r
503         BUS_EXIT( BUS_DBG_DRV );\r
504         return status;\r
505 }\r
506 \r
507 \r
508 static NTSTATUS\r
509 bus_drv_open(\r
510         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
511         IN                              IRP                                                     *p_irp )\r
512 {\r
513         BUS_ENTER( BUS_DBG_DRV );\r
514 \r
515         UNUSED_PARAM( p_dev_obj );\r
516 \r
517         CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );\r
518 \r
519         /* We always succeed file handles creation. */\r
520         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
521         p_irp->IoStatus.Information = 0;\r
522         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
523 \r
524         BUS_EXIT( BUS_DBG_DRV );\r
525         return STATUS_SUCCESS;\r
526 }\r
527 \r
528 \r
529 static NTSTATUS\r
530 bus_drv_cleanup(\r
531         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
532         IN                              IRP                                                     *p_irp )\r
533 {\r
534         NTSTATUS                        status;\r
535 \r
536         BUS_ENTER( BUS_DBG_DRV );\r
537 \r
538         UNUSED_PARAM( p_dev_obj );\r
539 \r
540         CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );\r
541 \r
542         /*\r
543          * Note that we don't acquire the remove and stop lock on close to allow\r
544          * applications to close the device when the locks are already held.\r
545          */\r
546         status = cl_to_ntstatus( al_dev_close( p_irp ) );\r
547 \r
548         /* Complete the IRP. */\r
549         p_irp->IoStatus.Status = status;\r
550         p_irp->IoStatus.Information = 0;\r
551         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
552 \r
553         BUS_EXIT( BUS_DBG_DRV );\r
554         return status;\r
555 }\r
556 \r
557 \r
558 static NTSTATUS\r
559 bus_drv_close(\r
560         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
561         IN                              IRP                                                     *p_irp )\r
562 {\r
563         UNUSED_PARAM( p_dev_obj );\r
564 \r
565         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
566         p_irp->IoStatus.Information = 0;\r
567         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
568 \r
569         return STATUS_SUCCESS;\r
570 }\r
571 \r
572 \r
573 static NTSTATUS\r
574 bus_drv_ioctl(\r
575         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
576         IN                              IRP                                                     *p_irp )\r
577 {\r
578         NTSTATUS                        status;\r
579         bus_fdo_ext_t           *p_ext;\r
580         PIO_STACK_LOCATION      p_io_stack;\r
581 \r
582         BUS_ENTER( BUS_DBG_DRV );\r
583 \r
584         /* Get the extension. */\r
585         p_ext = p_dev_obj->DeviceExtension;\r
586 \r
587         /* Get the stack location. */\r
588         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
589 \r
590         /* Acquire the stop lock. */\r
591         status = IoAcquireRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );\r
592         if( !NT_SUCCESS( status ) )\r
593         {\r
594                 p_irp->IoStatus.Status = status;\r
595                 p_irp->IoStatus.Information = 0;\r
596                 IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
597                 BUS_EXIT( BUS_DBG_DRV );\r
598                 return status;\r
599         }\r
600 \r
601         /* Acquire the remove lock. */\r
602         status = IoAcquireRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
603         if( !NT_SUCCESS( status ) )\r
604         {\r
605                 IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );\r
606                 p_irp->IoStatus.Status = status;\r
607                 p_irp->IoStatus.Information = 0;\r
608                 IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
609                 BUS_EXIT( BUS_DBG_DRV );\r
610                 return status;\r
611         }\r
612         \r
613         status = cl_to_ntstatus( al_dev_ioctl( p_irp ) );\r
614         \r
615         /* Only pass down if not handled and not PDO device. */\r
616         if( status == STATUS_INVALID_DEVICE_REQUEST && p_ext->cl_ext.p_next_do )\r
617         {\r
618                 IoSkipCurrentIrpStackLocation( p_irp );\r
619                 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
620         }\r
621 \r
622         /* Release the remove and stop locks. */\r
623         IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
624         IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );\r
625 \r
626         BUS_EXIT( BUS_DBG_DRV );\r
627         return status;\r
628 }\r
629 \r
630 cl_status_t\r
631 bus_add_pkey(cl_ioctl_handle_t                  h_ioctl)\r
632 {\r
633         cl_status_t                             status;\r
634         pkey_array_t                            *pkeys;\r
635         PIO_STACK_LOCATION                      pIoStack;\r
636 \r
637         BUS_ENTER( BUS_DBG_DRV );\r
638 \r
639         pIoStack = IoGetCurrentIrpStackLocation(h_ioctl);\r
640         if ( (! h_ioctl->AssociatedIrp.SystemBuffer) || \r
641                  pIoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof (pkey_array_t))\r
642     {\r
643                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
644                         ("Invalid parameters.\n") );\r
645                 return CL_INVALID_PARAMETER;\r
646         }\r
647 \r
648         pkeys =  (pkey_array_t*)h_ioctl->AssociatedIrp.SystemBuffer;\r
649 \r
650         /* create additional pdo */\r
651         status = port_mgr_pkey_add(pkeys);\r
652         if (! NT_SUCCESS(status))\r
653         {\r
654                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
655                         ("port_mgr_pkey_add returned %08x.\n", status) );\r
656         }\r
657 \r
658         BUS_EXIT( BUS_DBG_DRV );\r
659         return status;\r
660 }\r
661 \r
662 cl_status_t\r
663 bus_rem_pkey(cl_ioctl_handle_t                  h_ioctl)\r
664 {\r
665         cl_status_t                             status;\r
666         pkey_array_t                            *pkeys;\r
667         PIO_STACK_LOCATION                      pIoStack;\r
668 \r
669         BUS_ENTER( BUS_DBG_DRV );\r
670 \r
671         pIoStack = IoGetCurrentIrpStackLocation(h_ioctl);\r
672         if ( (! h_ioctl->AssociatedIrp.SystemBuffer) || \r
673                  pIoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof (pkey_array_t))\r
674     {\r
675                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
676                         ("Invalid parameters.\n") );\r
677                 return CL_INVALID_PARAMETER;\r
678         }\r
679 \r
680         pkeys =  (pkey_array_t*)h_ioctl->AssociatedIrp.SystemBuffer;\r
681 \r
682         /* removes pdo */\r
683         status = port_mgr_pkey_rem(pkeys);\r
684         if (! NT_SUCCESS(status))\r
685         {\r
686                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
687                         ("port_mgr_pkey_rem returned %08x.\n", status) );\r
688         }\r
689 \r
690         BUS_EXIT( BUS_DBG_DRV );\r
691         return status;\r
692 }\r
693 static NTSTATUS\r
694 bus_drv_sysctl(\r
695         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
696         IN                              IRP                                                     *p_irp )\r
697 {\r
698         NTSTATUS                status;\r
699         bus_fdo_ext_t   *p_ext;\r
700 \r
701         BUS_ENTER( BUS_DBG_DRV );\r
702 \r
703         CL_ASSERT( p_dev_obj );\r
704         CL_ASSERT( p_irp );\r
705 \r
706         p_ext = p_dev_obj->DeviceExtension;\r
707 \r
708         if( p_ext->cl_ext.p_next_do )\r
709         {\r
710                 IoSkipCurrentIrpStackLocation( p_irp );\r
711                 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
712         }\r
713         else\r
714         {\r
715                 status = p_irp->IoStatus.Status;\r
716                 IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
717         }\r
718 \r
719         BUS_EXIT( BUS_DBG_DRV );\r
720         return status;\r
721 }\r
722 \r
723 \r
724 static void\r
725 bus_drv_unload(\r
726         IN                              DRIVER_OBJECT                           *p_driver_obj )\r
727 {\r
728         pkey_conf_t *cur_conf,*tmp;\r
729         UNICODE_STRING           dos_name;\r
730         UNUSED_PARAM( p_driver_obj );\r
731 \r
732         BUS_ENTER( BUS_DBG_DRV );\r
733         \r
734         RtlInitUnicodeString( &dos_name, L"\\DosDevices\\Global\\ibal" );\r
735         IoDeleteSymbolicLink( &dos_name );\r
736         cur_conf = bus_globals.p_pkey_conf;\r
737         while(cur_conf)\r
738         {\r
739                 tmp = cur_conf;\r
740                 cur_conf = cur_conf->next_conf;\r
741                 cl_free(tmp);\r
742         }\r
743         CL_DEINIT;\r
744 \r
745 #if defined(EVENT_TRACING)\r
746         WPP_CLEANUP(p_driver_obj);\r
747 #endif\r
748 \r
749         BUS_EXIT( BUS_DBG_DRV );\r
750         \r
751 }\r
752 \r
753 \r
754 NTSTATUS\r
755 DriverEntry(\r
756         IN                              DRIVER_OBJECT                           *p_driver_obj,\r
757         IN                              UNICODE_STRING                          *p_registry_path )\r
758 {\r
759         NTSTATUS                status;\r
760 \r
761         BUS_ENTER( BUS_DBG_DRV );\r
762 \r
763 #if defined(EVENT_TRACING)\r
764         WPP_INIT_TRACING(p_driver_obj ,p_registry_path);\r
765 #endif\r
766 \r
767         status = CL_INIT;\r
768         if( !NT_SUCCESS(status) )\r
769         {\r
770                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
771                         ("cl_init returned %08X.\n", status) );\r
772                 return status;\r
773         }\r
774 \r
775         /* Store the driver object pointer in the global parameters. */\r
776         bus_globals.p_driver_obj = p_driver_obj;\r
777 \r
778         /* Get the registry values. */\r
779         status = __read_registry( p_registry_path );\r
780         if( !NT_SUCCESS(status) )\r
781         {\r
782                 CL_DEINIT;\r
783                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
784                         ("__read_registry returned %08x.\n", status) );\r
785                 return status;\r
786         }\r
787 \r
788         /* Setup the entry points. */\r
789         p_driver_obj->MajorFunction[IRP_MJ_CREATE] = bus_drv_open;\r
790         p_driver_obj->MajorFunction[IRP_MJ_CLEANUP] = bus_drv_cleanup;\r
791         p_driver_obj->MajorFunction[IRP_MJ_CLOSE] = bus_drv_close;\r
792         p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;\r
793         p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;\r
794         p_driver_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = bus_drv_ioctl;\r
795         p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = bus_drv_sysctl;\r
796         p_driver_obj->DriverUnload = bus_drv_unload;\r
797         p_driver_obj->DriverExtension->AddDevice = bus_add_device;\r
798 \r
799         // Mutex to synchronize multiple threads creating & deleting \r
800         // control deviceobjects. \r
801 \r
802         KeInitializeEvent(&g_ControlEvent, SynchronizationEvent, TRUE);\r
803         g_bfi_InstanceCount = 0;\r
804         memset(  __out_bcount(sizeof(g_bus_filters)) (void*)g_bus_filters, 0,\r
805                         sizeof(g_bus_filters) );\r
806 \r
807         BUS_EXIT( BUS_DBG_DRV );\r
808         return STATUS_SUCCESS;\r
809 }\r