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
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
61 char node_desc[IB_NODE_DESCRIPTION_SIZE];
\r
63 bus_globals_t bus_globals = {
\r
71 __read_machine_name( void );
\r
75 IN UNICODE_STRING* const p_Param_Path );
\r
79 IN DEVICE_OBJECT *p_dev_obj,
\r
84 IN DEVICE_OBJECT *p_dev_obj,
\r
89 IN DEVICE_OBJECT *p_dev_obj,
\r
94 IN DEVICE_OBJECT *p_dev_obj,
\r
97 /***f* InfiniBand Bus Driver/bus_drv_sysctl
\r
102 * Entry point for handling WMI IRPs.
\r
108 IN DEVICE_OBJECT *p_dev_obj,
\r
114 IN DRIVER_OBJECT *p_driver_obj );
\r
118 IN DRIVER_OBJECT *p_driver_obj,
\r
119 IN UNICODE_STRING *p_registry_path );
\r
122 #ifdef ALLOC_PRAGMA
\r
123 #pragma alloc_text (INIT, DriverEntry)
\r
124 #pragma alloc_text (INIT, __read_machine_name)
\r
125 #pragma alloc_text (INIT, __read_registry)
\r
126 #pragma alloc_text (PAGE, bus_drv_unload)
\r
127 #pragma alloc_text (PAGE, bus_drv_open)
\r
128 #pragma alloc_text (PAGE, bus_drv_close)
\r
129 #pragma alloc_text (PAGE, bus_drv_ioctl)
\r
130 #pragma alloc_text (PAGE_PNP, bus_drv_sysctl)
\r
135 __read_machine_name( void )
\r
138 /* Remember the terminating entry in the table below. */
\r
139 RTL_QUERY_REGISTRY_TABLE table[2];
\r
140 UNICODE_STRING hostNamePath;
\r
141 UNICODE_STRING hostNameW;
\r
142 ANSI_STRING hostName;
\r
144 BUS_ENTER( BUS_DBG_DRV );
\r
146 /* Get the host name. */
\r
147 RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" );
\r
148 RtlInitUnicodeString( &hostNameW, NULL );
\r
151 * Clear the table. This clears all the query callback pointers,
\r
152 * and sets up the terminating table entry.
\r
154 cl_memclr( table, sizeof(table) );
\r
155 cl_memclr( node_desc, sizeof(node_desc) );
\r
157 /* Setup the table entries. */
\r
158 table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
\r
159 table[0].Name = L"ComputerName";
\r
160 table[0].EntryContext = &hostNameW;
\r
161 table[0].DefaultType = REG_SZ;
\r
162 table[0].DefaultData = &hostNameW;
\r
163 table[0].DefaultLength = 0;
\r
166 status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL,
\r
167 hostNamePath.Buffer, table, NULL, NULL );
\r
168 if( NT_SUCCESS( status ) )
\r
170 /* Convert the UNICODE host name to UTF-8 (ASCII). */
\r
171 hostName.Length = 0;
\r
172 hostName.MaximumLength = sizeof(node_desc);
\r
173 hostName.Buffer = node_desc;
\r
174 status = RtlUnicodeStringToAnsiString( &hostName, &hostNameW, FALSE );
\r
175 RtlFreeUnicodeString( &hostNameW );
\r
179 BUS_TRACE(BUS_DBG_ERROR , ("Failed to get host name.\n") );
\r
180 /* Use the default name... */
\r
181 RtlStringCbCopyNA( node_desc, sizeof(node_desc),
\r
182 DEFAULT_NODE_DESC, sizeof(DEFAULT_NODE_DESC) );
\r
185 BUS_ENTER( BUS_DBG_DRV );
\r
191 IN UNICODE_STRING* const p_registry_path )
\r
194 /* Remember the terminating entry in the table below. */
\r
195 RTL_QUERY_REGISTRY_TABLE table[9];
\r
196 UNICODE_STRING param_path;
\r
198 BUS_ENTER( BUS_DBG_DRV );
\r
200 __read_machine_name();
\r
202 RtlInitUnicodeString( ¶m_path, NULL );
\r
203 param_path.MaximumLength = p_registry_path->Length +
\r
204 sizeof(L"\\Parameters");
\r
205 param_path.Buffer = cl_zalloc( param_path.MaximumLength );
\r
206 if( !param_path.Buffer )
\r
208 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
209 ("Failed to allocate parameters path buffer.\n") );
\r
210 return STATUS_INSUFFICIENT_RESOURCES;
\r
213 RtlAppendUnicodeStringToString( ¶m_path, p_registry_path );
\r
214 RtlAppendUnicodeToString( ¶m_path, L"\\Parameters" );
\r
217 * Clear the table. This clears all the query callback pointers,
\r
218 * and sets up the terminating table entry.
\r
220 cl_memclr( table, sizeof(table) );
\r
222 /* Setup the table entries. */
\r
223 table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
224 table[0].Name = L"ReportPortNIC";
\r
225 table[0].EntryContext = &bus_globals.b_report_port_nic;
\r
226 table[0].DefaultType = REG_DWORD;
\r
227 table[0].DefaultData = &bus_globals.b_report_port_nic;
\r
228 table[0].DefaultLength = sizeof(ULONG);
\r
230 table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
231 table[1].Name = L"DebugFlags";
\r
232 table[1].EntryContext = &bus_globals.dbg_lvl;
\r
233 table[1].DefaultType = REG_DWORD;
\r
234 table[1].DefaultData = &bus_globals.dbg_lvl;
\r
235 table[1].DefaultLength = sizeof(ULONG);
\r
237 table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
238 table[2].Name = L"IbalDebugLevel";
\r
239 table[2].EntryContext = &g_al_dbg_level;
\r
240 table[2].DefaultType = REG_DWORD;
\r
241 table[2].DefaultData = &g_al_dbg_level;
\r
242 table[2].DefaultLength = sizeof(ULONG);
\r
244 table[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
245 table[3].Name = L"IbalDebugFlags";
\r
246 table[3].EntryContext = &g_al_dbg_flags;
\r
247 table[3].DefaultType = REG_DWORD;
\r
248 table[3].DefaultData = &g_al_dbg_flags;
\r
249 table[3].DefaultLength = sizeof(ULONG);
\r
252 table[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
253 table[4].Name = L"SmiPollInterval";
\r
254 table[4].EntryContext = &g_smi_poll_interval;
\r
255 table[4].DefaultType = REG_DWORD;
\r
256 table[4].DefaultData = &g_smi_poll_interval;
\r
257 table[4].DefaultLength = sizeof(ULONG);
\r
259 table[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
260 table[5].Name = L"IocQueryTimeout";
\r
261 table[5].EntryContext = &g_ioc_query_timeout;
\r
262 table[5].DefaultType = REG_DWORD;
\r
263 table[5].DefaultData = &g_ioc_query_timeout;
\r
264 table[5].DefaultLength = sizeof(ULONG);
\r
266 table[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
267 table[6].Name = L"IocQueryRetries";
\r
268 table[6].EntryContext = &g_ioc_query_retries;
\r
269 table[6].DefaultType = REG_DWORD;
\r
270 table[6].DefaultData = &g_ioc_query_retries;
\r
271 table[6].DefaultLength = sizeof(ULONG);
\r
273 table[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
274 table[7].Name = L"IocPollInterval";
\r
275 table[7].EntryContext = &g_ioc_poll_interval;
\r
276 table[7].DefaultType = REG_DWORD;
\r
277 table[7].DefaultData = &g_ioc_poll_interval;
\r
278 table[7].DefaultLength = sizeof(ULONG);
\r
281 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
282 param_path.Buffer, table, NULL, NULL );
\r
285 if( g_al_dbg_flags & AL_DBG_ERR )
\r
286 g_al_dbg_flags |= CL_DBG_ERROR;
\r
289 BUS_TRACE(BUS_DBG_DRV ,
\r
290 ("debug level %d debug flags 0x%.8x\n",
\r
294 cl_free( param_path.Buffer );
\r
295 BUS_EXIT( BUS_DBG_DRV );
\r
302 IN DEVICE_OBJECT *p_dev_obj,
\r
305 BUS_ENTER( BUS_DBG_DRV );
\r
307 UNUSED_PARAM( p_dev_obj );
\r
309 CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
\r
311 /* We always succeed file handles creation. */
\r
312 p_irp->IoStatus.Status = STATUS_SUCCESS;
\r
313 p_irp->IoStatus.Information = 0;
\r
314 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
316 BUS_EXIT( BUS_DBG_DRV );
\r
317 return STATUS_SUCCESS;
\r
323 IN DEVICE_OBJECT *p_dev_obj,
\r
328 BUS_ENTER( BUS_DBG_DRV );
\r
330 UNUSED_PARAM( p_dev_obj );
\r
332 CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
\r
335 * Note that we don't acquire the remove and stop lock on close to allow
\r
336 * applications to close the device when the locks are already held.
\r
338 status = cl_to_ntstatus( al_dev_close( p_irp ) );
\r
340 /* Complete the IRP. */
\r
341 p_irp->IoStatus.Status = status;
\r
342 p_irp->IoStatus.Information = 0;
\r
343 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
345 BUS_EXIT( BUS_DBG_DRV );
\r
352 IN DEVICE_OBJECT *p_dev_obj,
\r
355 UNUSED_PARAM( p_dev_obj );
\r
357 p_irp->IoStatus.Status = STATUS_SUCCESS;
\r
358 p_irp->IoStatus.Information = 0;
\r
359 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
361 return STATUS_SUCCESS;
\r
367 IN DEVICE_OBJECT *p_dev_obj,
\r
371 bus_fdo_ext_t *p_ext;
\r
372 PIO_STACK_LOCATION p_io_stack;
\r
374 BUS_ENTER( BUS_DBG_DRV );
\r
376 /* Get the extension. */
\r
377 p_ext = p_dev_obj->DeviceExtension;
\r
379 /* Get the stack location. */
\r
380 p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
\r
382 /* Acquire the stop lock. */
\r
383 status = IoAcquireRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );
\r
384 if( !NT_SUCCESS( status ) )
\r
386 p_irp->IoStatus.Status = status;
\r
387 p_irp->IoStatus.Information = 0;
\r
388 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
389 BUS_EXIT( BUS_DBG_DRV );
\r
393 /* Acquire the remove lock. */
\r
394 status = IoAcquireRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
\r
395 if( !NT_SUCCESS( status ) )
\r
397 IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );
\r
398 p_irp->IoStatus.Status = status;
\r
399 p_irp->IoStatus.Information = 0;
\r
400 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
401 BUS_EXIT( BUS_DBG_DRV );
\r
405 status = cl_to_ntstatus( al_dev_ioctl( p_irp ) );
\r
407 /* Only pass down if not handled and not PDO device. */
\r
408 if( status == STATUS_INVALID_DEVICE_REQUEST && p_ext->cl_ext.p_next_do )
\r
410 IoSkipCurrentIrpStackLocation( p_irp );
\r
411 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );
\r
414 /* Release the remove and stop locks. */
\r
415 IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
\r
416 IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );
\r
418 BUS_EXIT( BUS_DBG_DRV );
\r
425 IN DEVICE_OBJECT *p_dev_obj,
\r
429 bus_fdo_ext_t *p_ext;
\r
431 BUS_ENTER( BUS_DBG_DRV );
\r
433 CL_ASSERT( p_dev_obj );
\r
434 CL_ASSERT( p_irp );
\r
436 p_ext = p_dev_obj->DeviceExtension;
\r
438 if( p_ext->cl_ext.p_next_do )
\r
440 IoSkipCurrentIrpStackLocation( p_irp );
\r
441 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );
\r
445 status = p_irp->IoStatus.Status;
\r
446 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
449 BUS_EXIT( BUS_DBG_DRV );
\r
456 IN DRIVER_OBJECT *p_driver_obj )
\r
458 BUS_ENTER( BUS_DBG_DRV );
\r
460 UNUSED_PARAM( p_driver_obj );
\r
464 #if defined(EVENT_TRACING)
\r
465 WPP_CLEANUP(p_driver_obj);
\r
468 BUS_EXIT( BUS_DBG_DRV );
\r
475 IN DRIVER_OBJECT *p_driver_obj,
\r
476 IN UNICODE_STRING *p_registry_path )
\r
480 BUS_ENTER( BUS_DBG_DRV );
\r
482 #if defined(EVENT_TRACING)
\r
483 WPP_INIT_TRACING(p_driver_obj ,p_registry_path);
\r
487 if( !NT_SUCCESS(status) )
\r
489 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
490 ("cl_init returned %08X.\n", status) );
\r
494 /* Store the driver object pointer in the global parameters. */
\r
495 bus_globals.p_driver_obj = p_driver_obj;
\r
497 /* Get the registry values. */
\r
498 status = __read_registry( p_registry_path );
\r
499 if( !NT_SUCCESS(status) )
\r
502 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
503 ("__read_registry returned %08x.\n", status) );
\r
507 /* Setup the entry points. */
\r
508 p_driver_obj->MajorFunction[IRP_MJ_CREATE] = bus_drv_open;
\r
509 p_driver_obj->MajorFunction[IRP_MJ_CLEANUP] = bus_drv_cleanup;
\r
510 p_driver_obj->MajorFunction[IRP_MJ_CLOSE] = bus_drv_close;
\r
511 p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;
\r
512 p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;
\r
513 p_driver_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = bus_drv_ioctl;
\r
514 p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = bus_drv_sysctl;
\r
515 p_driver_obj->DriverUnload = bus_drv_unload;
\r
516 p_driver_obj->DriverExtension->AddDevice = bus_add_device;
\r
518 BUS_EXIT( BUS_DBG_DRV );
\r
519 return STATUS_SUCCESS;
\r