2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
3 * Copyright (c) 2006 Mellanox Technologies. All rights reserved.
\r
5 * This software is available to you under the OpenIB.org BSD license
\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
12 * - Redistributions of source code must retain the above
\r
13 * copyright notice, this list of conditions and the following
\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
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
35 * Provides the driver entry points for the InfiniBand Bus Driver.
\r
38 #include <complib/cl_types.h>
\r
39 #include "bus_driver.h"
\r
40 #include "bus_pnp.h"
\r
43 #include "al_debug.h"
\r
44 #include <complib/cl_init.h>
\r
45 #include "iba/ipoib_ifc.h"
\r
47 #if defined(EVENT_TRACING)
\r
51 #include "bus_driver.tmh"
\r
55 #define DEFAULT_NODE_DESC "Mellanox Windows® Host"
\r
57 #define DEFAULT_NODE_DESC "OpenIB Windows® Host"
\r
62 char node_desc[IB_NODE_DESCRIPTION_SIZE];
\r
64 bus_globals_t bus_globals = {
\r
74 __read_machine_name( void );
\r
78 IN UNICODE_STRING* const p_Param_Path );
\r
82 IN DEVICE_OBJECT *p_dev_obj,
\r
87 IN DEVICE_OBJECT *p_dev_obj,
\r
92 IN DEVICE_OBJECT *p_dev_obj,
\r
97 IN DEVICE_OBJECT *p_dev_obj,
\r
100 /***f* InfiniBand Bus Driver/bus_drv_sysctl
\r
105 * Entry point for handling WMI IRPs.
\r
111 IN DEVICE_OBJECT *p_dev_obj,
\r
117 IN DRIVER_OBJECT *p_driver_obj );
\r
121 IN DRIVER_OBJECT *p_driver_obj,
\r
122 IN UNICODE_STRING *p_registry_path );
\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
138 __read_machine_name( void )
\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
147 BUS_ENTER( BUS_DBG_DRV );
\r
149 /* Get the host name. */
\r
150 RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" );
\r
151 RtlInitUnicodeString( &hostNameW, NULL );
\r
154 * Clear the table. This clears all the query callback pointers,
\r
155 * and sets up the terminating table entry.
\r
157 cl_memclr( table, sizeof(table) );
\r
158 cl_memclr( node_desc, sizeof(node_desc) );
\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
169 status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL,
\r
170 hostNamePath.Buffer, table, NULL, NULL );
\r
171 if( NT_SUCCESS( status ) )
\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
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
187 BUS_EXIT( BUS_DBG_DRV );
\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
205 BUS_ENTER( BUS_DBG_DRV );
\r
207 CL_ASSERT(cur_pkey);
\r
210 cur_pkey->pkey_num = 0;
\r
213 for (i = 0; (i < str_len) && (cur_pkey->pkey_num < MAX_NUM_PKEY) ; i++)
\r
218 if( (str[i] != ',') && (str[i] != '\0'))
\r
222 BUS_TRACE(BUS_DBG_ERROR ,
\r
223 ("Incorrect format of pkey value\n") );
\r
226 pkey_str[j] = str[i];
\r
231 pkey_str[j] = '\0';
\r
232 status = RtlCharToInteger(&pkey_str[2],16,&tmp_val);
\r
233 if(! NT_SUCCESS(status))
\r
235 BUS_TRACE(BUS_DBG_ERROR ,
\r
236 ("Failed to convert, status = 0x%08X\n",status) );
\r
239 cur_pkey->pkey_array[cur_pkey->pkey_num++] = (uint16_t)tmp_val;
\r
243 BUS_EXIT( BUS_DBG_DRV );
\r
247 static void _free_static_iodevices()
\r
249 child_device_info_list_t *pDevList, *pDevList1;
\r
251 pDevList = bus_globals.p_device_list;
\r
255 pDevList1 = pDevList->next_device_info;
\r
257 pDevList = pDevList1;
\r
263 NTSTATUS _Create_Static_Devices(PUNICODE_STRING p_param_path)
\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
274 #define BUF_SIZE 256 /* use hard-coded size to make it simple*/
\r
276 cl_memclr( table, sizeof(table) );
\r
279 key_path_buffer = cl_zalloc(BUF_SIZE*sizeof(WCHAR)*3);
\r
281 if(!key_path_buffer)
\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
288 key_value_buffer = key_path_buffer + BUF_SIZE;
\r
289 static_child_name = key_value_buffer + BUF_SIZE;
\r
291 RtlInitUnicodeString( &keyPath, NULL );
\r
292 keyPath.MaximumLength = BUF_SIZE*sizeof(WCHAR);
\r
293 keyPath.Buffer = key_path_buffer;
\r
295 RtlInitUnicodeString( &keyValue, NULL );
\r
296 keyValue.MaximumLength = BUF_SIZE*sizeof(WCHAR);
\r
297 keyValue.Buffer = key_value_buffer;
\r
299 RtlInitUnicodeString( &child_name, NULL );
\r
300 child_name.MaximumLength = BUF_SIZE*sizeof(WCHAR);
\r
301 child_name.Buffer = static_child_name;
\r
304 RtlCopyUnicodeString( &keyPath, p_param_path );
\r
306 RtlInitUnicodeString(&defaultKeyValue, L"IPoIB\0\0");
\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
316 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
317 keyPath.Buffer, table, NULL, NULL );
\r
319 if(NT_SUCCESS(status))
\r
322 child_device_info_list_t *pPrevList, *pNewDevList;
\r
324 curChild = static_child_name;
\r
325 pPrevList = bus_globals.p_device_list;
\r
328 RtlCopyUnicodeString(&keyPath, p_param_path);
\r
329 RtlAppendUnicodeToString(&keyPath, L"\\");
\r
330 RtlAppendUnicodeToString(&keyPath, curChild);
\r
332 pNewDevList = cl_zalloc(sizeof(child_device_info_list_t));
\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
339 pNewDevList->next_device_info = NULL;
\r
341 if(pPrevList == NULL)
\r
343 bus_globals.p_device_list = pNewDevList;
\r
346 pPrevList->next_device_info = pNewDevList;
\r
349 pPrevList = pNewDevList;
\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
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
365 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
366 keyPath.Buffer, table, NULL, NULL );
\r
367 if(!NT_SUCCESS(status))
\r
369 BUS_TRACE(BUS_DBG_ERROR ,("Failed to read DeviceId.\n") );
\r
370 goto _Create_Static_Devices_exit;
\r
372 pNewDevList->io_device_info.device_id_size = keyValue.Length + sizeof(WCHAR);
\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
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
388 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
389 keyPath.Buffer, table, NULL, NULL );
\r
390 if(!NT_SUCCESS(status))
\r
392 BUS_TRACE(BUS_DBG_ERROR ,("Failed to read HardwareId.\n") );
\r
393 goto _Create_Static_Devices_exit;
\r
395 pNewDevList->io_device_info.hardware_id_size = keyValue.Length + 2*sizeof(WCHAR);
\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
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
411 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
412 keyPath.Buffer, table, NULL, NULL );
\r
413 if(!NT_SUCCESS(status))
\r
415 BUS_TRACE(BUS_DBG_ERROR ,("Failed to read CompatibleId.\n") );
\r
416 goto _Create_Static_Devices_exit;
\r
418 pNewDevList->io_device_info.compatible_id_size = keyValue.Length + 2*sizeof(WCHAR); //2 null
\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
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
434 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
435 keyPath.Buffer, table, NULL, NULL );
\r
436 if(!NT_SUCCESS(status))
\r
438 BUS_TRACE(BUS_DBG_ERROR ,("Failed to read Description.\n") );
\r
439 goto _Create_Static_Devices_exit;
\r
442 pNewDevList->io_device_info.description_size = keyValue.Length + sizeof(WCHAR);
\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
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
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
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
470 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
471 keyPath.Buffer, table, NULL, NULL );
\r
472 if(!NT_SUCCESS(status))
\r
474 BUS_TRACE(BUS_DBG_ERROR ,("Failed to read PartitionKey.\n") );
\r
475 goto _Create_Static_Devices_exit;
\r
478 while(*curChild) curChild++;
\r
483 _Create_Static_Devices_exit:
\r
484 if(key_path_buffer)
\r
486 cl_free(key_path_buffer);
\r
489 if(!NT_SUCCESS(status))
\r
491 _free_static_iodevices();
\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
504 if (! *pp_cur_conf)
\r
505 pp_cur_conf = &bus_globals.p_pkey_conf;
\r
507 pp_cur_conf = &((*pp_cur_conf)->next_conf);
\r
509 *pp_cur_conf = cl_zalloc( sizeof( pkey_conf_t ) );
\r
510 if (!(*pp_cur_conf) )
\r
512 BUS_TRACE(BUS_DBG_ERROR ,
\r
513 ("Failed to allocate pkey configuration\n") );
\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
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
528 guid_str[1 + guid_str_len/2] = tmp_char;
\r
529 (*pp_cur_conf)->pkeys_per_port.port_guid = tmp_val;
\r
531 status = RtlCharToInteger(&guid_str[1 + guid_str_len/2],16,(PULONG)&tmp_val);
\r
532 if(! NT_SUCCESS(status))
\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
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
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
550 ************************************************************************/
\r
552 __build_pkeys_per_port(IN const UNICODE_STRING *str)
\r
555 ANSI_STRING ansi_str;
\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
563 status = RtlUnicodeStringToAnsiString(&ansi_str,str,TRUE);
\r
564 if(! NT_SUCCESS(status))
\r
566 BUS_TRACE(BUS_DBG_ERROR ,
\r
567 ("RtlUnicodeStringToAnsiString returned 0x%.8x\n", status) );
\r
571 port_guid_found = FALSE;
\r
573 for ( i = 0; i < ansi_str.MaximumLength; i++)
\r
575 if(! port_guid_found)
\r
577 if(ansi_str.Buffer[i] == ':')
\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
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
589 RtlZeroMemory(tmp_guid,sizeof(tmp_guid));
\r
595 tmp_guid[j] = ansi_str.Buffer[i];
\r
603 p_start = &ansi_str.Buffer[i];
\r
605 if(ansi_str.Buffer[i] == ';')
\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
611 ansi_str.Buffer[i] = ';';
\r
613 port_guid_found = FALSE;
\r
617 RtlFreeAnsiString(&ansi_str);
\r
618 return STATUS_SUCCESS;
\r
623 IN UNICODE_STRING* const p_registry_path )
\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
632 BUS_ENTER( BUS_DBG_DRV );
\r
634 __read_machine_name();
\r
636 RtlInitUnicodeString( &empty_string,NULL);
\r
637 RtlInitUnicodeString( ¶m_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
643 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
644 ("Failed to allocate parameters path buffer.\n") );
\r
645 return STATUS_INSUFFICIENT_RESOURCES;
\r
648 RtlAppendUnicodeStringToString( ¶m_path, p_registry_path );
\r
649 RtlAppendUnicodeToString( ¶m_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
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
662 * Clear the table. This clears all the query callback pointers,
\r
663 * and sets up the terminating table entry.
\r
665 cl_memclr( table, sizeof(table) );
\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
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
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
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
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
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
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
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
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
733 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
734 param_path.Buffer, table, NULL, NULL );
\r
735 if (NT_SUCCESS(status))
\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
741 if(!NT_SUCCESS(_Create_Static_Devices(¶m_path))){
\r
742 BUS_TRACE(BUS_DBG_ERROR ,
\r
743 ("Failed to create devices\n"));
\r
747 if( g_al_dbg_flags & AL_DBG_ERR )
\r
748 g_al_dbg_flags |= CL_DBG_ERROR;
\r
750 // bus_globals.dbg_lvl |= BUS_DBG_DRV | BUS_DBG_PNP;
\r
753 BUS_TRACE(BUS_DBG_DRV ,
\r
754 ("debug level %d debug flags 0x%.8x\n",
\r
758 cl_free( pkeyString.Buffer );
\r
759 cl_free( param_path.Buffer );
\r
760 BUS_EXIT( BUS_DBG_DRV );
\r
767 IN DEVICE_OBJECT *p_dev_obj,
\r
770 BUS_ENTER( BUS_DBG_DRV );
\r
772 UNUSED_PARAM( p_dev_obj );
\r
774 CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
\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
781 BUS_EXIT( BUS_DBG_DRV );
\r
782 return STATUS_SUCCESS;
\r
788 IN DEVICE_OBJECT *p_dev_obj,
\r
793 BUS_ENTER( BUS_DBG_DRV );
\r
795 UNUSED_PARAM( p_dev_obj );
\r
797 CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
\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
803 status = cl_to_ntstatus( al_dev_close( p_irp ) );
\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
810 BUS_EXIT( BUS_DBG_DRV );
\r
817 IN DEVICE_OBJECT *p_dev_obj,
\r
820 UNUSED_PARAM( p_dev_obj );
\r
822 p_irp->IoStatus.Status = STATUS_SUCCESS;
\r
823 p_irp->IoStatus.Information = 0;
\r
824 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
826 return STATUS_SUCCESS;
\r
832 IN DEVICE_OBJECT *p_dev_obj,
\r
836 bus_fdo_ext_t *p_ext;
\r
837 PIO_STACK_LOCATION p_io_stack;
\r
839 BUS_ENTER( BUS_DBG_DRV );
\r
841 /* Get the extension. */
\r
842 p_ext = p_dev_obj->DeviceExtension;
\r
844 /* Get the stack location. */
\r
845 p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
\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
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
858 /* Acquire the remove lock. */
\r
859 status = IoAcquireRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
\r
860 if( !NT_SUCCESS( status ) )
\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
870 status = cl_to_ntstatus( al_dev_ioctl( p_irp ) );
\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
875 IoSkipCurrentIrpStackLocation( p_irp );
\r
876 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );
\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
883 BUS_EXIT( BUS_DBG_DRV );
\r
888 bus_add_pkey(cl_ioctl_handle_t h_ioctl)
\r
890 cl_status_t status;
\r
891 pkey_array_t *pkeys;
\r
892 PIO_STACK_LOCATION pIoStack;
\r
894 BUS_ENTER( BUS_DBG_DRV );
\r
896 pIoStack = IoGetCurrentIrpStackLocation(h_ioctl);
\r
897 if ( (! h_ioctl->AssociatedIrp.SystemBuffer) ||
\r
898 pIoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof (pkey_array_t))
\r
900 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
901 ("Invalid parameters.\n") );
\r
902 return CL_INVALID_PARAMETER;
\r
905 pkeys = (pkey_array_t*)h_ioctl->AssociatedIrp.SystemBuffer;
\r
907 /* create additional pdo */
\r
908 status = port_mgr_pkey_add(pkeys);
\r
909 if (! NT_SUCCESS(status))
\r
911 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
912 ("port_mgr_pkey_add returned %08x.\n", status) );
\r
915 BUS_EXIT( BUS_DBG_DRV );
\r
920 bus_rem_pkey(cl_ioctl_handle_t h_ioctl)
\r
922 cl_status_t status;
\r
923 pkey_array_t *pkeys;
\r
924 PIO_STACK_LOCATION pIoStack;
\r
926 BUS_ENTER( BUS_DBG_DRV );
\r
928 pIoStack = IoGetCurrentIrpStackLocation(h_ioctl);
\r
929 if ( (! h_ioctl->AssociatedIrp.SystemBuffer) ||
\r
930 pIoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof (pkey_array_t))
\r
932 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
933 ("Invalid parameters.\n") );
\r
934 return CL_INVALID_PARAMETER;
\r
937 pkeys = (pkey_array_t*)h_ioctl->AssociatedIrp.SystemBuffer;
\r
940 status = port_mgr_pkey_rem(pkeys);
\r
941 if (! NT_SUCCESS(status))
\r
943 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
944 ("port_mgr_pkey_rem returned %08x.\n", status) );
\r
947 BUS_EXIT( BUS_DBG_DRV );
\r
952 IN DEVICE_OBJECT *p_dev_obj,
\r
956 bus_fdo_ext_t *p_ext;
\r
958 BUS_ENTER( BUS_DBG_DRV );
\r
960 CL_ASSERT( p_dev_obj );
\r
961 CL_ASSERT( p_irp );
\r
963 p_ext = p_dev_obj->DeviceExtension;
\r
965 if( p_ext->cl_ext.p_next_do )
\r
967 IoSkipCurrentIrpStackLocation( p_irp );
\r
968 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );
\r
972 status = p_irp->IoStatus.Status;
\r
973 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
976 BUS_EXIT( BUS_DBG_DRV );
\r
983 IN DRIVER_OBJECT *p_driver_obj )
\r
985 pkey_conf_t *cur_conf,*tmp;
\r
986 UNICODE_STRING dos_name;
\r
987 UNUSED_PARAM( p_driver_obj );
\r
989 BUS_ENTER( BUS_DBG_DRV );
\r
991 RtlInitUnicodeString( &dos_name, L"\\DosDevices\\Global\\ibal" );
\r
992 IoDeleteSymbolicLink( &dos_name );
\r
993 cur_conf = bus_globals.p_pkey_conf;
\r
997 cur_conf = cur_conf->next_conf;
\r
1001 _free_static_iodevices();
\r
1006 #if defined(EVENT_TRACING)
\r
1007 WPP_CLEANUP(p_driver_obj);
\r
1010 BUS_EXIT( BUS_DBG_DRV );
\r
1017 IN DRIVER_OBJECT *p_driver_obj,
\r
1018 IN UNICODE_STRING *p_registry_path )
\r
1022 BUS_ENTER( BUS_DBG_DRV );
\r
1024 #if defined(EVENT_TRACING)
\r
1025 WPP_INIT_TRACING(p_driver_obj ,p_registry_path);
\r
1029 if( !NT_SUCCESS(status) )
\r
1031 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
1032 ("cl_init returned %08X.\n", status) );
\r
1036 /* Store the driver object pointer in the global parameters. */
\r
1037 bus_globals.p_driver_obj = p_driver_obj;
\r
1039 /* Get the registry values. */
\r
1040 status = __read_registry( p_registry_path );
\r
1041 if( !NT_SUCCESS(status) )
\r
1044 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
1045 ("__read_registry returned %08x.\n", status) );
\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
1060 // Mutex to synchronize multiple threads creating & deleting
\r
1061 // control deviceobjects.
\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
1068 BUS_EXIT( BUS_DBG_DRV );
\r
1069 return STATUS_SUCCESS;
\r