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
59 /* pkey array to be read */
\r
60 pkey_array_t g_pkeys;
\r
62 char node_desc[IB_NODE_DESCRIPTION_SIZE];
\r
64 bus_globals_t bus_globals = {
\r
72 __read_machine_name( void );
\r
76 IN UNICODE_STRING* const p_Param_Path );
\r
80 IN DEVICE_OBJECT *p_dev_obj,
\r
85 IN DEVICE_OBJECT *p_dev_obj,
\r
90 IN DEVICE_OBJECT *p_dev_obj,
\r
95 IN DEVICE_OBJECT *p_dev_obj,
\r
98 /***f* InfiniBand Bus Driver/bus_drv_sysctl
\r
103 * Entry point for handling WMI IRPs.
\r
109 IN DEVICE_OBJECT *p_dev_obj,
\r
115 IN DRIVER_OBJECT *p_driver_obj );
\r
119 IN DRIVER_OBJECT *p_driver_obj,
\r
120 IN UNICODE_STRING *p_registry_path );
\r
123 #ifdef ALLOC_PRAGMA
\r
124 #pragma alloc_text (INIT, DriverEntry)
\r
125 #pragma alloc_text (INIT, __read_machine_name)
\r
126 #pragma alloc_text (INIT, __read_registry)
\r
127 #pragma alloc_text (PAGE, bus_drv_unload)
\r
128 #pragma alloc_text (PAGE, bus_drv_open)
\r
129 #pragma alloc_text (PAGE, bus_drv_close)
\r
130 #pragma alloc_text (PAGE, bus_drv_ioctl)
\r
131 #pragma alloc_text (PAGE_PNP, bus_drv_sysctl)
\r
136 __read_machine_name( void )
\r
139 /* Remember the terminating entry in the table below. */
\r
140 RTL_QUERY_REGISTRY_TABLE table[2];
\r
141 UNICODE_STRING hostNamePath;
\r
142 UNICODE_STRING hostNameW;
\r
143 ANSI_STRING hostName;
\r
145 BUS_ENTER( BUS_DBG_DRV );
\r
147 /* Get the host name. */
\r
148 RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" );
\r
149 RtlInitUnicodeString( &hostNameW, NULL );
\r
152 * Clear the table. This clears all the query callback pointers,
\r
153 * and sets up the terminating table entry.
\r
155 cl_memclr( table, sizeof(table) );
\r
156 cl_memclr( node_desc, sizeof(node_desc) );
\r
158 /* Setup the table entries. */
\r
159 table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
\r
160 table[0].Name = L"ComputerName";
\r
161 table[0].EntryContext = &hostNameW;
\r
162 table[0].DefaultType = REG_SZ;
\r
163 table[0].DefaultData = &hostNameW;
\r
164 table[0].DefaultLength = 0;
\r
167 status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL,
\r
168 hostNamePath.Buffer, table, NULL, NULL );
\r
169 if( NT_SUCCESS( status ) )
\r
171 /* Convert the UNICODE host name to UTF-8 (ASCII). */
\r
172 hostName.Length = 0;
\r
173 hostName.MaximumLength = sizeof(node_desc);
\r
174 hostName.Buffer = node_desc;
\r
175 status = RtlUnicodeStringToAnsiString( &hostName, &hostNameW, FALSE );
\r
176 RtlFreeUnicodeString( &hostNameW );
\r
180 BUS_TRACE(BUS_DBG_ERROR , ("Failed to get host name.\n") );
\r
181 /* Use the default name... */
\r
182 RtlStringCbCopyNA( node_desc, sizeof(node_desc),
\r
183 DEFAULT_NODE_DESC, sizeof(DEFAULT_NODE_DESC) );
\r
186 /************************************************************************************
\r
187 * name : __prepare_pKey_array
\r
188 * parses registry string and exrtacts pkey value(s) from it.
\r
189 * pkey pattern is 0xABCD
\r
190 * input : UNICODE_STRING *str
\r
191 * output: pkey_array
\r
192 * return: uint16_t number of pkey(s) found
\r
193 *************************************************************************************/
\r
194 static uint16_t __prepare_pKey_array(IN const UNICODE_STRING *str, OUT uint16_t *pkey_array)
\r
196 uint16_t i, num_pKeys, cur_pkey_length;
\r
198 ANSI_STRING ansi_str;
\r
199 static const uint16_t PATTERN_LENGTH = 6;
\r
200 BUS_ENTER( BUS_DBG_DRV );
\r
202 CL_ASSERT(pkey_array);
\r
206 cur_pkey_length = 0;
\r
208 status = RtlUnicodeStringToAnsiString(&ansi_str,str,TRUE);
\r
209 if(! NT_SUCCESS(status))
\r
211 BUS_TRACE(BUS_DBG_ERROR ,
\r
212 ("RtlUnicodeStringToAnsiString returned 0x%.8x\n", status) );
\r
216 for (i = 0; (i < ansi_str.MaximumLength) && (num_pKeys < MAX_NUM_PKEY) ; i++)
\r
218 switch(ansi_str.Buffer[i])
\r
222 if (((i+1) < ansi_str.Length) && ( ( ansi_str.Buffer[i+1] == 'x') || ( ansi_str.Buffer[i+1] == 'X')))
\r
226 pkey_array[num_pKeys] = \
\r
227 (pkey_array[num_pKeys] << 4)| 0;
\r
237 if(cur_pkey_length == PATTERN_LENGTH)
\r
239 cur_pkey_length = 0;
\r
246 pkey_array[num_pKeys] = \
\r
247 (pkey_array[num_pKeys] << 4)| 0xA;
\r
253 pkey_array[num_pKeys] = \
\r
254 (pkey_array[num_pKeys] << 4)| 0xB;
\r
260 pkey_array[num_pKeys] = \
\r
261 (pkey_array[num_pKeys] << 4)| 0xC;
\r
267 pkey_array[num_pKeys] = \
\r
268 (pkey_array[num_pKeys] << 4)| 0xD;
\r
274 pkey_array[num_pKeys] = \
\r
275 (pkey_array[num_pKeys] << 4)| 0xE;
\r
281 pkey_array[num_pKeys] = \
\r
282 (pkey_array[num_pKeys] << 4)| 0xF;
\r
295 pkey_array[num_pKeys] = \
\r
296 (pkey_array[num_pKeys] << 4)| (ansi_str.Buffer[i] - '0');
\r
301 if(cur_pkey_length == PATTERN_LENGTH)
\r
303 cur_pkey_length = 0;
\r
308 RtlFreeAnsiString(&ansi_str);
\r
319 RtlFreeAnsiString(&ansi_str);
\r
320 BUS_EXIT( BUS_DBG_DRV );
\r
325 IN UNICODE_STRING* const p_registry_path )
\r
328 /* Remember the terminating entry in the table below. */
\r
329 RTL_QUERY_REGISTRY_TABLE table[10];
\r
330 UNICODE_STRING param_path;
\r
331 UNICODE_STRING pkeyString;
\r
332 UNICODE_STRING empty_string;
\r
334 BUS_ENTER( BUS_DBG_DRV );
\r
336 __read_machine_name();
\r
338 RtlInitUnicodeString( &empty_string,NULL);
\r
339 RtlInitUnicodeString( ¶m_path, NULL );
\r
340 param_path.MaximumLength = p_registry_path->Length +
\r
341 sizeof(L"\\Parameters");
\r
342 param_path.Buffer = cl_zalloc( param_path.MaximumLength );
\r
343 if( !param_path.Buffer )
\r
345 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
346 ("Failed to allocate parameters path buffer.\n") );
\r
347 return STATUS_INSUFFICIENT_RESOURCES;
\r
350 RtlAppendUnicodeStringToString( ¶m_path, p_registry_path );
\r
351 RtlAppendUnicodeToString( ¶m_path, L"\\Parameters" );
\r
352 RtlInitUnicodeString( &pkeyString, NULL );
\r
353 pkeyString.MaximumLength = 1024*sizeof(WCHAR);
\r
354 pkeyString.Buffer = cl_zalloc( pkeyString.MaximumLength );
\r
355 if( !pkeyString.Buffer )
\r
357 cl_free(param_path.Buffer);
\r
358 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
359 ("Failed to allocate parameters path pkeyString.\n") );
\r
360 return STATUS_INSUFFICIENT_RESOURCES;
\r
363 cl_memclr(&g_pkeys,sizeof(pkey_array_t));
\r
366 * Clear the table. This clears all the query callback pointers,
\r
367 * and sets up the terminating table entry.
\r
369 cl_memclr( table, sizeof(table) );
\r
371 /* Setup the table entries. */
\r
372 table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
373 table[0].Name = L"ReportPortNIC";
\r
374 table[0].EntryContext = &bus_globals.b_report_port_nic;
\r
375 table[0].DefaultType = REG_DWORD;
\r
376 table[0].DefaultData = &bus_globals.b_report_port_nic;
\r
377 table[0].DefaultLength = sizeof(ULONG);
\r
379 table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
380 table[1].Name = L"DebugFlags";
\r
381 table[1].EntryContext = &bus_globals.dbg_lvl;
\r
382 table[1].DefaultType = REG_DWORD;
\r
383 table[1].DefaultData = &bus_globals.dbg_lvl;
\r
384 table[1].DefaultLength = sizeof(ULONG);
\r
386 table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
387 table[2].Name = L"IbalDebugLevel";
\r
388 table[2].EntryContext = &g_al_dbg_level;
\r
389 table[2].DefaultType = REG_DWORD;
\r
390 table[2].DefaultData = &g_al_dbg_level;
\r
391 table[2].DefaultLength = sizeof(ULONG);
\r
393 table[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
394 table[3].Name = L"IbalDebugFlags";
\r
395 table[3].EntryContext = &g_al_dbg_flags;
\r
396 table[3].DefaultType = REG_DWORD;
\r
397 table[3].DefaultData = &g_al_dbg_flags;
\r
398 table[3].DefaultLength = sizeof(ULONG);
\r
401 table[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
402 table[4].Name = L"SmiPollInterval";
\r
403 table[4].EntryContext = &g_smi_poll_interval;
\r
404 table[4].DefaultType = REG_DWORD;
\r
405 table[4].DefaultData = &g_smi_poll_interval;
\r
406 table[4].DefaultLength = sizeof(ULONG);
\r
408 table[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
409 table[5].Name = L"IocQueryTimeout";
\r
410 table[5].EntryContext = &g_ioc_query_timeout;
\r
411 table[5].DefaultType = REG_DWORD;
\r
412 table[5].DefaultData = &g_ioc_query_timeout;
\r
413 table[5].DefaultLength = sizeof(ULONG);
\r
415 table[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
416 table[6].Name = L"IocQueryRetries";
\r
417 table[6].EntryContext = &g_ioc_query_retries;
\r
418 table[6].DefaultType = REG_DWORD;
\r
419 table[6].DefaultData = &g_ioc_query_retries;
\r
420 table[6].DefaultLength = sizeof(ULONG);
\r
422 table[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
423 table[7].Name = L"IocPollInterval";
\r
424 table[7].EntryContext = &g_ioc_poll_interval;
\r
425 table[7].DefaultType = REG_DWORD;
\r
426 table[7].DefaultData = &g_ioc_poll_interval;
\r
427 table[7].DefaultLength = sizeof(ULONG);
\r
429 table[8].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
430 table[8].Name = L"PartitionKey";
\r
431 table[8].EntryContext = &pkeyString;
\r
432 table[8].DefaultType = REG_SZ;
\r
433 table[8].DefaultData = &empty_string;
\r
434 table[8].DefaultLength = 0;
\r
436 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
437 param_path.Buffer, table, NULL, NULL );
\r
438 if (NT_SUCCESS(status))
\r
439 g_pkeys.pkey_num = __prepare_pKey_array(&pkeyString, (uint16_t*)g_pkeys.pkey_array);
\r
441 if( g_al_dbg_flags & AL_DBG_ERR )
\r
442 g_al_dbg_flags |= CL_DBG_ERROR;
\r
445 BUS_TRACE(BUS_DBG_DRV ,
\r
446 ("debug level %d debug flags 0x%.8x\n",
\r
450 cl_free( pkeyString.Buffer );
\r
451 cl_free( param_path.Buffer );
\r
452 BUS_EXIT( BUS_DBG_DRV );
\r
459 IN DEVICE_OBJECT *p_dev_obj,
\r
462 BUS_ENTER( BUS_DBG_DRV );
\r
464 UNUSED_PARAM( p_dev_obj );
\r
466 CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
\r
468 /* We always succeed file handles creation. */
\r
469 p_irp->IoStatus.Status = STATUS_SUCCESS;
\r
470 p_irp->IoStatus.Information = 0;
\r
471 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
473 BUS_EXIT( BUS_DBG_DRV );
\r
474 return STATUS_SUCCESS;
\r
480 IN DEVICE_OBJECT *p_dev_obj,
\r
485 BUS_ENTER( BUS_DBG_DRV );
\r
487 UNUSED_PARAM( p_dev_obj );
\r
489 CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
\r
492 * Note that we don't acquire the remove and stop lock on close to allow
\r
493 * applications to close the device when the locks are already held.
\r
495 status = cl_to_ntstatus( al_dev_close( p_irp ) );
\r
497 /* Complete the IRP. */
\r
498 p_irp->IoStatus.Status = status;
\r
499 p_irp->IoStatus.Information = 0;
\r
500 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
502 BUS_EXIT( BUS_DBG_DRV );
\r
509 IN DEVICE_OBJECT *p_dev_obj,
\r
512 UNUSED_PARAM( p_dev_obj );
\r
514 p_irp->IoStatus.Status = STATUS_SUCCESS;
\r
515 p_irp->IoStatus.Information = 0;
\r
516 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
518 return STATUS_SUCCESS;
\r
524 IN DEVICE_OBJECT *p_dev_obj,
\r
528 bus_fdo_ext_t *p_ext;
\r
529 PIO_STACK_LOCATION p_io_stack;
\r
531 BUS_ENTER( BUS_DBG_DRV );
\r
533 /* Get the extension. */
\r
534 p_ext = p_dev_obj->DeviceExtension;
\r
536 /* Get the stack location. */
\r
537 p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
\r
539 /* Acquire the stop lock. */
\r
540 status = IoAcquireRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );
\r
541 if( !NT_SUCCESS( status ) )
\r
543 p_irp->IoStatus.Status = status;
\r
544 p_irp->IoStatus.Information = 0;
\r
545 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
546 BUS_EXIT( BUS_DBG_DRV );
\r
550 /* Acquire the remove lock. */
\r
551 status = IoAcquireRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
\r
552 if( !NT_SUCCESS( status ) )
\r
554 IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );
\r
555 p_irp->IoStatus.Status = status;
\r
556 p_irp->IoStatus.Information = 0;
\r
557 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
558 BUS_EXIT( BUS_DBG_DRV );
\r
562 status = cl_to_ntstatus( al_dev_ioctl( p_irp ) );
\r
564 /* Only pass down if not handled and not PDO device. */
\r
565 if( status == STATUS_INVALID_DEVICE_REQUEST && p_ext->cl_ext.p_next_do )
\r
567 IoSkipCurrentIrpStackLocation( p_irp );
\r
568 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );
\r
571 /* Release the remove and stop locks. */
\r
572 IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
\r
573 IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );
\r
575 BUS_EXIT( BUS_DBG_DRV );
\r
580 bus_add_pkey(cl_ioctl_handle_t h_ioctl)
\r
582 cl_status_t status;
\r
583 pkey_array_t *pkeys;
\r
584 PIO_STACK_LOCATION pIoStack;
\r
586 BUS_ENTER( BUS_DBG_DRV );
\r
588 pIoStack = IoGetCurrentIrpStackLocation(h_ioctl);
\r
589 if ( (! h_ioctl->AssociatedIrp.SystemBuffer) ||
\r
590 pIoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof (pkey_array_t))
\r
592 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
593 ("Invalid parameters.\n") );
\r
594 return CL_INVALID_PARAMETER;
\r
597 pkeys = (pkey_array_t*)h_ioctl->AssociatedIrp.SystemBuffer;
\r
599 /* create additional pdo */
\r
600 status = port_mgr_pkey_add(pkeys);
\r
601 if (! NT_SUCCESS(status))
\r
603 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
604 ("port_mgr_pkey_add returned %08x.\n", status) );
\r
607 BUS_EXIT( BUS_DBG_DRV );
\r
613 IN DEVICE_OBJECT *p_dev_obj,
\r
617 bus_fdo_ext_t *p_ext;
\r
619 BUS_ENTER( BUS_DBG_DRV );
\r
621 CL_ASSERT( p_dev_obj );
\r
622 CL_ASSERT( p_irp );
\r
624 p_ext = p_dev_obj->DeviceExtension;
\r
626 if( p_ext->cl_ext.p_next_do )
\r
628 IoSkipCurrentIrpStackLocation( p_irp );
\r
629 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );
\r
633 status = p_irp->IoStatus.Status;
\r
634 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
637 BUS_EXIT( BUS_DBG_DRV );
\r
644 IN DRIVER_OBJECT *p_driver_obj )
\r
646 UNICODE_STRING dos_name;
\r
647 UNUSED_PARAM( p_driver_obj );
\r
649 BUS_ENTER( BUS_DBG_DRV );
\r
651 RtlInitUnicodeString( &dos_name, L"\\DosDevices\\Global\\ibal" );
\r
652 IoDeleteSymbolicLink( &dos_name );
\r
656 #if defined(EVENT_TRACING)
\r
657 WPP_CLEANUP(p_driver_obj);
\r
660 BUS_EXIT( BUS_DBG_DRV );
\r
667 IN DRIVER_OBJECT *p_driver_obj,
\r
668 IN UNICODE_STRING *p_registry_path )
\r
672 BUS_ENTER( BUS_DBG_DRV );
\r
674 #if defined(EVENT_TRACING)
\r
675 WPP_INIT_TRACING(p_driver_obj ,p_registry_path);
\r
679 if( !NT_SUCCESS(status) )
\r
681 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
682 ("cl_init returned %08X.\n", status) );
\r
686 /* Store the driver object pointer in the global parameters. */
\r
687 bus_globals.p_driver_obj = p_driver_obj;
\r
689 /* Get the registry values. */
\r
690 status = __read_registry( p_registry_path );
\r
691 if( !NT_SUCCESS(status) )
\r
694 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
695 ("__read_registry returned %08x.\n", status) );
\r
699 /* Setup the entry points. */
\r
700 p_driver_obj->MajorFunction[IRP_MJ_CREATE] = bus_drv_open;
\r
701 p_driver_obj->MajorFunction[IRP_MJ_CLEANUP] = bus_drv_cleanup;
\r
702 p_driver_obj->MajorFunction[IRP_MJ_CLOSE] = bus_drv_close;
\r
703 p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;
\r
704 p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;
\r
705 p_driver_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = bus_drv_ioctl;
\r
706 p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = bus_drv_sysctl;
\r
707 p_driver_obj->DriverUnload = bus_drv_unload;
\r
708 p_driver_obj->DriverExtension->AddDevice = bus_add_device;
\r
710 BUS_EXIT( BUS_DBG_DRV );
\r
711 return STATUS_SUCCESS;
\r