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