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 "OpenIB Windows® Host"
\r
58 char node_desc[IB_NODE_DESCRIPTION_SIZE];
\r
60 bus_globals_t bus_globals = {
\r
68 __read_machine_name( void );
\r
72 IN UNICODE_STRING* const p_Param_Path );
\r
76 IN DEVICE_OBJECT *p_dev_obj,
\r
81 IN DEVICE_OBJECT *p_dev_obj,
\r
86 IN DEVICE_OBJECT *p_dev_obj,
\r
91 IN DEVICE_OBJECT *p_dev_obj,
\r
94 /***f* InfiniBand Bus Driver/bus_drv_sysctl
\r
99 * Entry point for handling WMI IRPs.
\r
105 IN DEVICE_OBJECT *p_dev_obj,
\r
111 IN DRIVER_OBJECT *p_driver_obj );
\r
115 IN DRIVER_OBJECT *p_driver_obj,
\r
116 IN UNICODE_STRING *p_registry_path );
\r
119 #ifdef ALLOC_PRAGMA
\r
120 #pragma alloc_text (INIT, DriverEntry)
\r
121 #pragma alloc_text (INIT, __read_machine_name)
\r
122 #pragma alloc_text (INIT, __read_registry)
\r
123 #pragma alloc_text (PAGE, bus_drv_unload)
\r
124 #pragma alloc_text (PAGE, bus_drv_open)
\r
125 #pragma alloc_text (PAGE, bus_drv_close)
\r
126 #pragma alloc_text (PAGE, bus_drv_ioctl)
\r
127 #pragma alloc_text (PAGE_PNP, bus_drv_sysctl)
\r
132 __read_machine_name( void )
\r
135 /* Remember the terminating entry in the table below. */
\r
136 RTL_QUERY_REGISTRY_TABLE table[2];
\r
137 UNICODE_STRING hostNamePath;
\r
138 UNICODE_STRING hostNameW;
\r
139 ANSI_STRING hostName;
\r
141 BUS_ENTER( BUS_DBG_DRV );
\r
143 /* Get the host name. */
\r
144 RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" );
\r
145 RtlInitUnicodeString( &hostNameW, NULL );
\r
148 * Clear the table. This clears all the query callback pointers,
\r
149 * and sets up the terminating table entry.
\r
151 cl_memclr( table, sizeof(table) );
\r
152 cl_memclr( node_desc, sizeof(node_desc) );
\r
154 /* Setup the table entries. */
\r
155 table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
\r
156 table[0].Name = L"ComputerName";
\r
157 table[0].EntryContext = &hostNameW;
\r
158 table[0].DefaultType = REG_SZ;
\r
159 table[0].DefaultData = &hostNameW;
\r
160 table[0].DefaultLength = 0;
\r
163 status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL,
\r
164 hostNamePath.Buffer, table, NULL, NULL );
\r
165 if( NT_SUCCESS( status ) )
\r
167 /* Convert the UNICODE host name to UTF-8 (ASCII). */
\r
168 hostName.Length = 0;
\r
169 hostName.MaximumLength = sizeof(node_desc);
\r
170 hostName.Buffer = node_desc;
\r
171 status = RtlUnicodeStringToAnsiString( &hostName, &hostNameW, FALSE );
\r
172 RtlFreeUnicodeString( &hostNameW );
\r
176 BUS_TRACE(BUS_DBG_ERROR , ("Failed to get host name.\n") );
\r
177 /* Use the default name... */
\r
178 RtlStringCbCopyNA( node_desc, sizeof(node_desc),
\r
179 DEFAULT_NODE_DESC, sizeof(DEFAULT_NODE_DESC) );
\r
182 BUS_ENTER( BUS_DBG_DRV );
\r
188 IN UNICODE_STRING* const p_registry_path )
\r
191 /* Remember the terminating entry in the table below. */
\r
192 RTL_QUERY_REGISTRY_TABLE table[9];
\r
193 UNICODE_STRING param_path;
\r
195 BUS_ENTER( BUS_DBG_DRV );
\r
197 __read_machine_name();
\r
199 RtlInitUnicodeString( ¶m_path, NULL );
\r
200 param_path.MaximumLength = p_registry_path->Length +
\r
201 sizeof(L"\\Parameters");
\r
202 param_path.Buffer = cl_zalloc( param_path.MaximumLength );
\r
203 if( !param_path.Buffer )
\r
205 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
206 ("Failed to allocate parameters path buffer.\n") );
\r
207 return STATUS_INSUFFICIENT_RESOURCES;
\r
210 RtlAppendUnicodeStringToString( ¶m_path, p_registry_path );
\r
211 RtlAppendUnicodeToString( ¶m_path, L"\\Parameters" );
\r
214 * Clear the table. This clears all the query callback pointers,
\r
215 * and sets up the terminating table entry.
\r
217 cl_memclr( table, sizeof(table) );
\r
219 /* Setup the table entries. */
\r
220 table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
221 table[0].Name = L"ReportPortNIC";
\r
222 table[0].EntryContext = &bus_globals.b_report_port_nic;
\r
223 table[0].DefaultType = REG_DWORD;
\r
224 table[0].DefaultData = &bus_globals.b_report_port_nic;
\r
225 table[0].DefaultLength = sizeof(ULONG);
\r
227 table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
228 table[1].Name = L"DebugFlags";
\r
229 table[1].EntryContext = &bus_globals.dbg_lvl;
\r
230 table[1].DefaultType = REG_DWORD;
\r
231 table[1].DefaultData = &bus_globals.dbg_lvl;
\r
232 table[1].DefaultLength = sizeof(ULONG);
\r
234 table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
235 table[2].Name = L"IbalDebugLevel";
\r
236 table[2].EntryContext = &g_al_dbg_level;
\r
237 table[2].DefaultType = REG_DWORD;
\r
238 table[2].DefaultData = &g_al_dbg_level;
\r
239 table[2].DefaultLength = sizeof(ULONG);
\r
241 table[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
242 table[3].Name = L"IbalDebugFlags";
\r
243 table[3].EntryContext = &g_al_dbg_flags;
\r
244 table[3].DefaultType = REG_DWORD;
\r
245 table[3].DefaultData = &g_al_dbg_flags;
\r
246 table[3].DefaultLength = sizeof(ULONG);
\r
249 table[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
250 table[4].Name = L"SmiPollInterval";
\r
251 table[4].EntryContext = &g_smi_poll_interval;
\r
252 table[4].DefaultType = REG_DWORD;
\r
253 table[4].DefaultData = &g_smi_poll_interval;
\r
254 table[4].DefaultLength = sizeof(ULONG);
\r
256 table[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
257 table[5].Name = L"IocQueryTimeout";
\r
258 table[5].EntryContext = &g_ioc_query_timeout;
\r
259 table[5].DefaultType = REG_DWORD;
\r
260 table[5].DefaultData = &g_ioc_query_timeout;
\r
261 table[5].DefaultLength = sizeof(ULONG);
\r
263 table[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
264 table[6].Name = L"IocQueryRetries";
\r
265 table[6].EntryContext = &g_ioc_query_retries;
\r
266 table[6].DefaultType = REG_DWORD;
\r
267 table[6].DefaultData = &g_ioc_query_retries;
\r
268 table[6].DefaultLength = sizeof(ULONG);
\r
270 table[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
271 table[7].Name = L"IocPollInterval";
\r
272 table[7].EntryContext = &g_ioc_poll_interval;
\r
273 table[7].DefaultType = REG_DWORD;
\r
274 table[7].DefaultData = &g_ioc_poll_interval;
\r
275 table[7].DefaultLength = sizeof(ULONG);
\r
278 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
279 param_path.Buffer, table, NULL, NULL );
\r
282 if( g_al_dbg_flags & AL_DBG_ERR )
\r
283 g_al_dbg_flags |= CL_DBG_ERROR;
\r
286 BUS_TRACE(BUS_DBG_DRV ,
\r
287 ("debug level %d debug flags 0x%.8x\n",
\r
291 cl_free( param_path.Buffer );
\r
292 BUS_EXIT( BUS_DBG_DRV );
\r
299 IN DEVICE_OBJECT *p_dev_obj,
\r
302 BUS_ENTER( BUS_DBG_DRV );
\r
304 UNUSED_PARAM( p_dev_obj );
\r
306 CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
\r
308 /* We always succeed file handles creation. */
\r
309 p_irp->IoStatus.Status = STATUS_SUCCESS;
\r
310 p_irp->IoStatus.Information = 0;
\r
311 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
313 BUS_EXIT( BUS_DBG_DRV );
\r
314 return STATUS_SUCCESS;
\r
320 IN DEVICE_OBJECT *p_dev_obj,
\r
325 BUS_ENTER( BUS_DBG_DRV );
\r
327 UNUSED_PARAM( p_dev_obj );
\r
329 CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
\r
332 * Note that we don't acquire the remove and stop lock on close to allow
\r
333 * applications to close the device when the locks are already held.
\r
335 status = cl_to_ntstatus( al_dev_close( p_irp ) );
\r
337 /* Complete the IRP. */
\r
338 p_irp->IoStatus.Status = status;
\r
339 p_irp->IoStatus.Information = 0;
\r
340 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
342 BUS_EXIT( BUS_DBG_DRV );
\r
349 IN DEVICE_OBJECT *p_dev_obj,
\r
352 UNUSED_PARAM( p_dev_obj );
\r
354 p_irp->IoStatus.Status = STATUS_SUCCESS;
\r
355 p_irp->IoStatus.Information = 0;
\r
356 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
358 return STATUS_SUCCESS;
\r
364 IN DEVICE_OBJECT *p_dev_obj,
\r
368 bus_fdo_ext_t *p_ext;
\r
369 PIO_STACK_LOCATION p_io_stack;
\r
371 BUS_ENTER( BUS_DBG_DRV );
\r
373 /* Get the extension. */
\r
374 p_ext = p_dev_obj->DeviceExtension;
\r
376 /* Get the stack location. */
\r
377 p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
\r
379 /* Acquire the stop lock. */
\r
380 status = IoAcquireRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );
\r
381 if( !NT_SUCCESS( status ) )
\r
383 p_irp->IoStatus.Status = status;
\r
384 p_irp->IoStatus.Information = 0;
\r
385 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
386 BUS_EXIT( BUS_DBG_DRV );
\r
390 /* Acquire the remove lock. */
\r
391 status = IoAcquireRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
\r
392 if( !NT_SUCCESS( status ) )
\r
394 IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );
\r
395 p_irp->IoStatus.Status = status;
\r
396 p_irp->IoStatus.Information = 0;
\r
397 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
398 BUS_EXIT( BUS_DBG_DRV );
\r
402 status = cl_to_ntstatus( al_dev_ioctl( p_irp ) );
\r
404 /* Only pass down if not handled and not PDO device. */
\r
405 if( status == STATUS_INVALID_DEVICE_REQUEST && p_ext->cl_ext.p_next_do )
\r
407 IoSkipCurrentIrpStackLocation( p_irp );
\r
408 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );
\r
411 /* Release the remove and stop locks. */
\r
412 IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
\r
413 IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );
\r
415 BUS_EXIT( BUS_DBG_DRV );
\r
422 IN DEVICE_OBJECT *p_dev_obj,
\r
426 bus_fdo_ext_t *p_ext;
\r
428 BUS_ENTER( BUS_DBG_DRV );
\r
430 CL_ASSERT( p_dev_obj );
\r
431 CL_ASSERT( p_irp );
\r
433 p_ext = p_dev_obj->DeviceExtension;
\r
435 if( p_ext->cl_ext.p_next_do )
\r
437 IoSkipCurrentIrpStackLocation( p_irp );
\r
438 status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );
\r
442 status = p_irp->IoStatus.Status;
\r
443 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
446 BUS_EXIT( BUS_DBG_DRV );
\r
453 IN DRIVER_OBJECT *p_driver_obj )
\r
455 BUS_ENTER( BUS_DBG_DRV );
\r
457 UNUSED_PARAM( p_driver_obj );
\r
461 #if defined(EVENT_TRACING)
\r
462 WPP_CLEANUP(p_driver_obj);
\r
465 BUS_EXIT( BUS_DBG_DRV );
\r
472 IN DRIVER_OBJECT *p_driver_obj,
\r
473 IN UNICODE_STRING *p_registry_path )
\r
477 BUS_ENTER( BUS_DBG_DRV );
\r
479 #if defined(EVENT_TRACING)
\r
480 WPP_INIT_TRACING(p_driver_obj ,p_registry_path);
\r
484 if( !NT_SUCCESS(status) )
\r
486 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
487 ("cl_init returned %08X.\n", status) );
\r
491 /* Store the driver object pointer in the global parameters. */
\r
492 bus_globals.p_driver_obj = p_driver_obj;
\r
494 /* Get the registry values. */
\r
495 status = __read_registry( p_registry_path );
\r
496 if( !NT_SUCCESS(status) )
\r
499 BUS_TRACE_EXIT( BUS_DBG_ERROR,
\r
500 ("__read_registry returned %08x.\n", status) );
\r
504 /* Setup the entry points. */
\r
505 p_driver_obj->MajorFunction[IRP_MJ_CREATE] = bus_drv_open;
\r
506 p_driver_obj->MajorFunction[IRP_MJ_CLEANUP] = bus_drv_cleanup;
\r
507 p_driver_obj->MajorFunction[IRP_MJ_CLOSE] = bus_drv_close;
\r
508 p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;
\r
509 p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;
\r
510 p_driver_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = bus_drv_ioctl;
\r
511 p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = bus_drv_sysctl;
\r
512 p_driver_obj->DriverUnload = bus_drv_unload;
\r
513 p_driver_obj->DriverExtension->AddDevice = bus_add_device;
\r
515 BUS_EXIT( BUS_DBG_DRV );
\r
516 return STATUS_SUCCESS;
\r