2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
3 * Copyright (c) 1996-2003 Intel Corporation. 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
30 * $Id: al.c 1611 2006-08-20 14:48:55Z sleybo $
\r
33 #include "precomp.h"
\r
34 #include <initguid.h>
\r
35 #include <wdmguid.h>
\r
36 #include <rdma\verbs.h>
\r
38 #if defined(EVENT_TRACING)
\r
48 * UVP name does not include file extension. For debug builds, UAL
\r
49 * will append "d.dll". For release builds, UAL will append ".dll"
\r
51 char mlnx_uvp_lib_name[MAX_LIB_NAME] = {"mlx4u"};
\r
53 static int __get_dev_info(PFDO_DEVICE_DATA p_fdo, __be64 *node_guid, u32 *hw_id)
\r
55 struct ib_device_attr device_attr;
\r
56 struct ib_device *p_ibdev = p_fdo->bus_ib_ifc.p_ibdev;
\r
59 HCA_ENTER( HCA_DBG_PNP );
\r
60 if ( hca_is_livefish(p_fdo) ) {
\r
61 *node_guid = cl_hton64((uint64_t)(ULONG_PTR)p_ibdev);
\r
62 p_ibdev->node_guid = *node_guid;
\r
67 err = (p_ibdev->query_device)( p_ibdev, &device_attr );
\r
71 *node_guid = p_ibdev->node_guid;
\r
72 *hw_id = device_attr.hw_ver;
\r
73 HCA_EXIT( HCA_DBG_PNP );
\r
77 #ifndef USE_WDM_FRAMEWORK
\r
79 static ci_interface_t*
\r
81 IN PFDO_DEVICE_DATA const p_fdo )
\r
83 ci_interface_t *pIfc;
\r
85 HCA_ENTER( HCA_DBG_PNP );
\r
88 (ci_interface_t*)ExAllocatePoolWithTag( PagedPool, sizeof(ci_interface_t), MT_TAG_KERNEL );
\r
91 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
92 ("Failed to allocate ci_interface_t (%d bytes).\n",
\r
93 sizeof(ci_interface_t)));
\r
97 setup_ci_interface( p_fdo->hca.guid, !!hca_is_livefish(p_fdo), pIfc );
\r
99 pIfc->p_hca_obj = &p_fdo->hca;
\r
100 pIfc->vend_id = (uint32_t)p_fdo->bus_ib_ifc.pdev->ven_id;
\r
101 pIfc->dev_id = (uint16_t)p_fdo->bus_ib_ifc.pdev->dev_id;
\r
102 pIfc->dev_revision = (uint16_t)p_fdo->hca.hw_ver;
\r
104 HCA_EXIT( HCA_DBG_PNP );
\r
109 __unmap_hca_memory(
\r
110 IN PFDO_DEVICE_DATA const p_fdo )
\r
112 struct pci_dev *pdev = p_fdo->bus_ib_ifc.pdev;
\r
115 HCA_ENTER( HCA_DBG_PNP );
\r
117 for( i = 0; i < HCA_BAR_TYPE_MAX; i++ ) {
\r
118 if (pdev->bar[i].virt) {
\r
119 MmUnmapIoSpace( pdev->bar[i].virt, pdev->bar[i].size );
\r
120 cl_memclr( &pdev->bar[i], sizeof(hca_bar_t) );
\r
124 HCA_EXIT( HCA_DBG_PNP );
\r
127 /* release the resources, allocated in hca_start */
\r
129 __hca_release_resources(
\r
130 IN WDFDEVICE Device )
\r
132 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
134 HCA_ENTER( HCA_DBG_PNP );
\r
136 switch( p_fdo->state )
\r
140 mlnx_hca_remove( &p_fdo->hca );
\r
143 __unmap_hca_memory( p_fdo );
\r
145 p_fdo->state = HCA_ADDED;
\r
147 HCA_EXIT( HCA_DBG_PNP );
\r
152 IN DEVICE_OBJECT* p_dev_obj )
\r
154 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
156 HCA_ENTER( HCA_DBG_PNP );
\r
158 cl_atomic_inc( &p_fdo->n_hca_ifc_ref );
\r
159 ObReferenceObject( p_dev_obj );
\r
161 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
162 ("MLX4_HCA: CA_guid %I64x, hca_ifc_ref %d\n",
\r
163 p_fdo->hca.guid, p_fdo->n_hca_ifc_ref) );
\r
165 HCA_EXIT( HCA_DBG_PNP );
\r
170 IN DEVICE_OBJECT* p_dev_obj )
\r
172 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
174 HCA_ENTER( HCA_DBG_PNP );
\r
176 cl_atomic_dec( &p_fdo->n_hca_ifc_ref );
\r
177 ObDereferenceObject( p_dev_obj );
\r
179 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
180 ("MLX4_HCA: CA_guid %I64x, hca_ifc_ref %d\n",
\r
181 p_fdo->hca.guid, p_fdo->n_hca_ifc_ref) );
\r
183 HCA_EXIT( HCA_DBG_PNP );
\r
190 IN WDFDEVICE Device,
\r
191 IN WDF_POWER_DEVICE_STATE PreviousState
\r
195 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
197 HCA_ENTER( HCA_DBG_PNP );
\r
198 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceD0Entry: PreviousState 0x%x\n", PreviousState));
\r
199 // start card (needed after Hibernation or standby)
\r
200 if (PreviousState > WdfPowerDeviceD0) {
\r
201 /* get MLX4_BUS IB interface */
\r
202 if ( !p_fdo->bus_ib_ifc_taken ) {
\r
203 status = WdfFdoQueryForInterface( Device, &MLX4_BUS_IB_INTERFACE_GUID,
\r
204 (PINTERFACE)&p_fdo->bus_ib_ifc, sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL );
\r
205 if( !NT_SUCCESS( status ) ) {
\r
206 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
\r
209 p_fdo->bus_ib_ifc_taken = TRUE;
\r
210 p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
\r
213 HCA_EXIT( HCA_DBG_PNP );
\r
214 return STATUS_SUCCESS;
\r
219 IN WDFDEVICE Device,
\r
220 IN WDF_POWER_DEVICE_STATE TargetState
\r
224 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
226 HCA_ENTER( HCA_DBG_PNP );
\r
228 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceD0Exit: TargetState 0x%x\n", TargetState));
\r
230 switch (TargetState) {
\r
231 case WdfPowerDeviceD1: /* hopefully, it is STANDBY state */
\r
232 case WdfPowerDeviceD2: /* hopefully, it is STANDBY state */
\r
233 case WdfPowerDeviceD3: /* hopefully, it is STANDBY state */
\r
234 case WdfPowerDevicePrepareForHibernation:
\r
235 if (atomic_read(&p_fdo->usecnt)) {
\r
236 status = STATUS_UNSUCCESSFUL;
\r
239 /* Fall through. */
\r
241 status = STATUS_SUCCESS;
\r
245 if (TargetState > WdfPowerDeviceD0) {
\r
246 if(p_fdo->bus_ib_ifc_taken) {
\r
247 PINTERFACE p_ifc = (PINTERFACE)&p_fdo->bus_ib_ifc;
\r
248 p_ifc->InterfaceDereference( p_ifc->Context );
\r
249 p_fdo->bus_ib_ifc_taken = FALSE;
\r
253 HCA_EXIT( HCA_DBG_PNP );
\r
258 EvtDevicePrepareHardware(
\r
259 IN WDFDEVICE Device,
\r
260 IN WDFCMRESLIST ResourcesRaw,
\r
261 IN WDFCMRESLIST ResourcesTranslated
\r
266 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
267 BUS_INTERFACE_STANDARD bus_pci_ifc;
\r
268 ci_interface_t *p_hca_ifc;
\r
269 RDMA_INTERFACE_VERBS rdma_ifc, *p_ifc = &rdma_ifc;
\r
270 WDF_QUERY_INTERFACE_CONFIG qiConfig;
\r
272 UNUSED_PARAM(ResourcesRaw);
\r
273 UNUSED_PARAM(ResourcesTranslated);
\r
275 HCA_ENTER( HCA_DBG_PNP );
\r
277 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtPrepareHardware: \n"));
\r
279 /* get PCI BUS interface */
\r
280 status = WdfFdoQueryForInterface( Device, &GUID_BUS_INTERFACE_STANDARD,
\r
281 (PINTERFACE)&bus_pci_ifc, sizeof(BUS_INTERFACE_STANDARD), 1, NULL );
\r
282 if( !NT_SUCCESS( status ) ) {
\r
283 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting PCI BUS interface failed: status=0x%x\n", status));
\r
286 RtlCopyMemory( &p_fdo->bus_pci_ifc, &bus_pci_ifc, sizeof(BUS_INTERFACE_STANDARD) );
\r
287 p_fdo->bus_pci_ifc_taken = TRUE;
\r
289 /* get MLX4_BUS IB interface */
\r
290 if ( !p_fdo->bus_ib_ifc_taken ) {
\r
291 status = WdfFdoQueryForInterface( Device, &MLX4_BUS_IB_INTERFACE_GUID,
\r
292 (PINTERFACE)&p_fdo->bus_ib_ifc, sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL );
\r
293 if( !NT_SUCCESS( status ) ) {
\r
294 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
\r
297 p_fdo->bus_ib_ifc_taken = TRUE;
\r
298 p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
\r
301 InitializeListHead(&p_fdo->hca.event_list);
\r
302 KeInitializeSpinLock(&p_fdo->hca.event_list_lock);
\r
304 /* get node GUID */
\r
305 err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );
\r
308 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,
\r
309 ("can't get guid - ib_query_device() failed (%08X)\n", err ));
\r
310 //TODO: no cleanup on error
\r
311 return STATUS_INSUFFICIENT_RESOURCES;
\r
315 mlnx_hca_insert( &p_fdo->hca );
\r
317 /* Allocate and populate our HCA interface structure. */
\r
318 p_hca_ifc = __alloc_hca_ifc( p_fdo );
\r
320 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("__alloc_hca_ifc failed.\n"));
\r
321 return STATUS_NO_MEMORY;
\r
324 /* fill interface fields */
\r
325 p_ifc->InterfaceHeader.Size = sizeof(RDMA_INTERFACE_VERBS);
\r
326 p_ifc->InterfaceHeader.Version = VerbsVersion(VERBS_MAJOR_VER, VERBS_MINOR_VER);
\r
327 p_ifc->InterfaceHeader.Context = p_fdo->p_dev_obj;
\r
328 p_ifc->InterfaceHeader.InterfaceReference = __ref_ifc;
\r
329 p_ifc->InterfaceHeader.InterfaceDereference = __deref_ifc;
\r
330 p_ifc->Verbs = *p_hca_ifc;
\r
331 ExFreePool( p_hca_ifc );
\r
333 /* create an upper interface */
\r
334 WDF_QUERY_INTERFACE_CONFIG_INIT( &qiConfig, (PINTERFACE)p_ifc,
\r
335 &GUID_RDMA_INTERFACE_VERBS, NULL);
\r
337 status = WdfDeviceAddQueryInterface( Device, &qiConfig );
\r
338 if (!NT_SUCCESS(status)) {
\r
339 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("WdfDeviceAddQueryInterface failed %#x\n", status));
\r
344 * Change the state since the PnP callback can happen
\r
345 * before the callback returns.
\r
347 p_fdo->state = HCA_STARTED;
\r
349 HCA_EXIT( HCA_DBG_PNP );
\r
350 return STATUS_SUCCESS;
\r
355 EvtDeviceReleaseHardware(
\r
356 IN WDFDEVICE Device,
\r
357 IN WDFCMRESLIST ResourcesTranslated
\r
360 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
362 UNUSED_PARAM(ResourcesTranslated);
\r
364 HCA_ENTER( HCA_DBG_PNP );
\r
366 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceReleaseHardware: FdoData=0x%p\n", p_fdo));
\r
368 // release IBBUS resources
\r
369 __hca_release_resources(Device);
\r
371 // release MLX4_BUS resources
\r
372 if(p_fdo->bus_ib_ifc_taken) {
\r
373 PINTERFACE p_ifc = (PINTERFACE)&p_fdo->bus_ib_ifc;
\r
374 p_ifc->InterfaceDereference( p_ifc->Context );
\r
375 p_fdo->bus_ib_ifc_taken = FALSE;
\r
378 // release PCI BUS resources
\r
379 if(p_fdo->bus_pci_ifc_taken) {
\r
380 PINTERFACE p_ifc = (PINTERFACE)&p_fdo->bus_pci_ifc;
\r
381 p_ifc->InterfaceDereference( p_ifc->Context );
\r
382 p_fdo->bus_pci_ifc_taken = FALSE;
\r
385 HCA_EXIT( HCA_DBG_PNP );
\r
386 return STATUS_SUCCESS;
\r
390 EvtDeviceQueryRemove(
\r
391 IN WDFDEVICE Device
\r
394 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
395 HCA_ENTER( HCA_DBG_PNP );
\r
396 if (atomic_read(&p_fdo->usecnt)) {
\r
397 cl_dbg_out( "MLX4_HCA: Can't get unloaded. %d applications are still in work\n", p_fdo->usecnt);
\r
398 return STATUS_UNSUCCESSFUL;
\r
400 HCA_EXIT( HCA_DBG_PNP );
\r
401 return STATUS_SUCCESS;
\r
406 EvtDriverDeviceAdd(
\r
407 IN WDFDRIVER Driver,
\r
408 IN PWDFDEVICE_INIT DeviceInit
\r
411 Routine Description:
\r
413 EvtDriverDeviceAdd is called by the framework in response to AddDevice
\r
414 call from the PnP manager. We create and initialize a device object to
\r
415 represent a new instance of mxe bus.
\r
419 Driver - Handle to a framework driver object created in DriverEntry
\r
421 DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
\r
429 WDF_OBJECT_ATTRIBUTES attributes;
\r
432 PFDO_DEVICE_DATA p_fdo;
\r
433 WDF_PNPPOWER_EVENT_CALLBACKS Callbacks;
\r
435 UNREFERENCED_PARAMETER(Driver);
\r
439 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDriverDeviceAdd: 0x%p\n", Driver));
\r
441 // register PnP & Power stuff
\r
443 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);
\r
444 Callbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;
\r
445 Callbacks.EvtDeviceReleaseHardware = EvtDeviceReleaseHardware;
\r
446 Callbacks.EvtDeviceQueryRemove = EvtDeviceQueryRemove;
\r
447 Callbacks.EvtDeviceD0Entry = EvtDeviceD0Entry;
\r
448 Callbacks.EvtDeviceD0Exit = EvtDeviceD0Exit;
\r
450 WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInit, &Callbacks );
\r
453 // Initialize all the properties specific to the device.
\r
454 // Framework has default values for the one that are not
\r
455 // set explicitly here. So please read the doc and make sure
\r
456 // you are okay with the defaults.
\r
458 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_INFINIBAND);
\r
459 WdfDeviceInitSetExclusive(DeviceInit, FALSE);
\r
462 // Initialize attributes structure to specify size and accessor function
\r
463 // for storing device context.
\r
465 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FDO_DEVICE_DATA);
\r
468 // Create a framework device object. In response to this call, framework
\r
469 // creates a WDM deviceobject.
\r
471 status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
\r
472 if (!NT_SUCCESS(status)) {
\r
473 HCA_PRINT(TRACE_LEVEL_VERBOSE, HCA_DBG_PNP, ("EvtDriverDeviceAdd: WdfDeviceCreate failed with 0x%x\n", status));
\r
478 // Init device context.
\r
480 p_fdo = FdoGetData(device);
\r
481 RtlZeroMemory(p_fdo, sizeof(FDO_DEVICE_DATA));
\r
482 p_fdo->FdoDevice = device;
\r
483 p_fdo->p_dev_obj = WdfDeviceWdmGetDeviceObject( device );
\r
484 spin_lock_init( &p_fdo->uctx_lock );
\r
485 cl_qlist_init( &p_fdo->uctx_list );
\r
486 atomic_set(&p_fdo->usecnt, 0);
\r
487 p_fdo->state = HCA_ADDED;
\r
492 status = WmiRegistration(device);
\r
493 if (!NT_SUCCESS(status)) {
\r
497 status = STATUS_SUCCESS;
\r
500 HCA_EXIT( HCA_DBG_PNP );
\r
507 IN WDFDRIVER Driver
\r
510 HCA_ENTER( HCA_DBG_PNP );
\r
512 UNUSED_PARAM( Driver );
\r
514 HCA_EXIT( HCA_DBG_PNP );
\r
515 #if defined(EVENT_TRACING)
\r
516 WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver));
\r
522 IN PDRIVER_OBJECT DriverObject,
\r
523 IN PUNICODE_STRING RegistryPath
\r
526 Routine Description:
\r
528 Initialize the call backs structure of Driver Framework.
\r
532 DriverObject - pointer to the driver object
\r
534 RegistryPath - pointer to a unicode string representing the path,
\r
535 to driver-specific key in the registry.
\r
543 WDF_DRIVER_CONFIG config;
\r
547 #if defined(EVENT_TRACING)
\r
548 WPP_INIT_TRACING(DriverObject, RegistryPath);
\r
551 // global initializations
\r
552 g.DebugPrintLevel = TRACE_LEVEL_VERBOSE;
\r
553 g.DebugPrintFlags = 0xffff;
\r
554 HCA_ENTER( HCA_DBG_PNP );
\r
556 status = mlnx_hcas_init();
\r
557 if( status != STATUS_SUCCESS ) {
\r
558 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,
\r
559 ("mlnx_hcas_init returned %#x.\n", status));
\r
564 // Initiialize driver config to control the attributes that
\r
565 // are global to the driver. Note that framework by default
\r
566 // provides a driver unload routine. If you create any resources
\r
567 // in the DriverEntry and want to be cleaned in driver unload,
\r
568 // you can override that by specifing one in the Config structure.
\r
571 WDF_DRIVER_CONFIG_INIT(
\r
572 &config, EvtDriverDeviceAdd );
\r
573 config.EvtDriverUnload = EvtDriverUnload;
\r
576 // Create a framework driver object to represent our driver.
\r
578 status = WdfDriverCreate(DriverObject,
\r
579 RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,
\r
580 &config, &hDriver);
\r
582 if (!NT_SUCCESS(status)) {
\r
583 HCA_PRINT(TRACE_LEVEL_VERBOSE, HCA_DBG_PNP, ("WdfDriverCreate failed with status 0x%x\n", status));
\r
588 // read registry parameters
\r
591 DECLARE_CONST_UNICODE_STRING(valueName0, L"DebugLevel");
\r
592 DECLARE_CONST_UNICODE_STRING(valueName1, L"DebugFlags");
\r
594 WDFKEY hKey = NULL;
\r
596 status = WdfDriverOpenParametersRegistryKey( hDriver,
\r
597 STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &hKey );
\r
599 if (NT_SUCCESS (status)) {
\r
601 status = WdfRegistryQueryULong(hKey, &valueName0, &value);
\r
602 if (NT_SUCCESS (status)) g.DebugPrintLevel = value;
\r
604 status = WdfRegistryQueryULong(hKey, &valueName1, &value);
\r
605 if (NT_SUCCESS (status)) g.DebugPrintFlags = value;
\r
607 WdfRegistryClose(hKey);
\r
610 // we don't matter the failure in the work with Registry
\r
611 status = STATUS_SUCCESS;
\r
615 HCA_PRINT( TRACE_LEVEL_INFORMATION,HCA_DBG_PNP ,
\r
616 ("exit status %#x.\n", status));
\r
617 HCA_EXIT( HCA_DBG_PNP );
\r
625 UNICODE_STRING g_param_path;
\r
626 static cl_vfptr_pnp_po_t vfptrHcaPnp;
\r
630 IN PDRIVER_OBJECT p_driver_obj,
\r
631 IN PUNICODE_STRING p_registry_path );
\r
635 IN UNICODE_STRING* const p_Param_Path );
\r
639 IN PDRIVER_OBJECT p_driver_obj );
\r
643 IN PDEVICE_OBJECT p_dev_obj,
\r
648 IN PDRIVER_OBJECT pDriverObj,
\r
649 IN PDEVICE_OBJECT pPdo );
\r
653 IN DEVICE_OBJECT* const p_dev_obj,
\r
654 IN IRP* const p_irp,
\r
655 OUT cl_irp_action_t* const p_action );
\r
659 IN DEVICE_OBJECT* const p_dev_obj,
\r
660 IN IRP* const p_irp,
\r
661 OUT cl_irp_action_t* const p_action );
\r
665 IN DEVICE_OBJECT* const p_dev_obj,
\r
666 IN IRP* const p_irp,
\r
667 OUT cl_irp_action_t* const p_action );
\r
671 IN DEVICE_OBJECT* const p_dev_obj,
\r
672 IN IRP* const p_irp,
\r
673 OUT cl_irp_action_t* const p_action );
\r
677 IN DEVICE_OBJECT* const p_dev_obj,
\r
678 IN IRP* const p_irp,
\r
679 OUT cl_irp_action_t* const p_action );
\r
682 hca_release_resources(
\r
683 IN DEVICE_OBJECT* const p_dev_obj );
\r
687 IN DEVICE_OBJECT* const p_dev_obj,
\r
688 IN IRP* const p_irp,
\r
689 OUT cl_irp_action_t* const p_action );
\r
692 hca_surprise_remove(
\r
693 IN DEVICE_OBJECT* const p_dev_obj,
\r
694 IN IRP* const p_irp,
\r
695 OUT cl_irp_action_t* const p_action );
\r
698 hca_query_capabilities(
\r
699 IN DEVICE_OBJECT* const p_dev_obj,
\r
700 IN IRP* const p_irp,
\r
701 OUT cl_irp_action_t* const p_action );
\r
704 hca_query_interface(
\r
705 IN DEVICE_OBJECT* const p_dev_obj,
\r
706 IN IRP* const p_irp,
\r
707 OUT cl_irp_action_t* const p_action );
\r
710 hca_query_pnp_state(
\r
711 IN DEVICE_OBJECT* const p_dev_obj,
\r
712 IN IRP* const p_irp,
\r
713 OUT cl_irp_action_t* const p_action );
\r
716 hca_query_bus_relations(
\r
717 IN DEVICE_OBJECT* const p_dev_obj,
\r
718 IN IRP* const p_irp,
\r
719 OUT cl_irp_action_t* const p_action );
\r
722 hca_query_removal_relations(
\r
723 IN DEVICE_OBJECT* const p_dev_obj,
\r
724 IN IRP* const p_irp,
\r
725 OUT cl_irp_action_t* const p_action );
\r
729 IN DEVICE_OBJECT* const p_dev_obj,
\r
730 IN IRP* const p_irp,
\r
731 OUT cl_irp_action_t* const p_action );
\r
735 IN DEVICE_OBJECT* const p_dev_obj,
\r
736 IN IRP* const p_irp,
\r
737 OUT cl_irp_action_t* const p_action );
\r
739 static ci_interface_t*
\r
741 IN FDO_DEVICE_DATA* const p_fdo );
\r
744 __get_ci_interface(
\r
745 IN DEVICE_OBJECT* const p_dev_obj );
\r
752 IN PDRIVER_OBJECT pDriverObj,
\r
753 IN PDEVICE_OBJECT pPdo )
\r
756 DEVICE_OBJECT *p_dev_obj, *pNextDevObj;
\r
757 PFDO_DEVICE_DATA p_fdo;
\r
759 HCA_ENTER(HCA_DBG_PNP);
\r
762 * Create the device so that we have a device extension to store stuff in.
\r
764 status = IoCreateDevice( pDriverObj, sizeof(FDO_DEVICE_DATA),
\r
765 NULL, FILE_DEVICE_INFINIBAND, FILE_DEVICE_SECURE_OPEN,
\r
766 FALSE, &p_dev_obj );
\r
767 if( !NT_SUCCESS( status ) )
\r
769 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
770 ("IoCreateDevice returned 0x%08X.\n", status));
\r
774 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
775 cl_memclr( p_fdo, sizeof(FDO_DEVICE_DATA) );
\r
776 cl_spinlock_init( &p_fdo->uctx_lock );
\r
777 cl_qlist_init( &p_fdo->uctx_list );
\r
778 atomic_set(&p_fdo->usecnt, 0);
\r
780 /* Attach to the device stack. */
\r
781 pNextDevObj = IoAttachDeviceToDeviceStack( p_dev_obj, pPdo );
\r
784 //cl_event_destroy( &p_fdo->mutex );
\r
785 IoDeleteDevice( p_dev_obj );
\r
786 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
787 ("IoAttachDeviceToDeviceStack failed.\n"));
\r
788 return STATUS_NO_SUCH_DEVICE;
\r
791 /* Inititalize the complib extension. */
\r
792 cl_init_pnp_po_ext( p_dev_obj, pNextDevObj, pPdo, CL_DBG_PNP | CL_DBG_ERROR,
\r
793 &vfptrHcaPnp, NULL );
\r
795 p_fdo->state = HCA_ADDED;
\r
797 HCA_EXIT(HCA_DBG_PNP);
\r
803 IN PINTERFACE p_ifc )
\r
805 HCA_ENTER( HCA_DBG_PNP );
\r
806 p_ifc->InterfaceDereference( p_ifc->Context );
\r
807 HCA_EXIT( HCA_DBG_PNP );
\r
810 /* Forwards the request to the HCA's PDO. */
\r
813 IN DEVICE_OBJECT* const pDevObj,
\r
814 IN const GUID* const pGuid,
\r
817 IN OUT PVOID InterfaceSpecificData,
\r
818 OUT PINTERFACE pBusIfc )
\r
822 IO_STATUS_BLOCK ioStatus;
\r
823 IO_STACK_LOCATION *pIoStack;
\r
824 DEVICE_OBJECT *pDev;
\r
827 HCA_ENTER( HCA_DBG_PNP );
\r
829 CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
\r
831 pDev = IoGetAttachedDeviceReference( pDevObj );
\r
833 KeInitializeEvent( &event, NotificationEvent, FALSE );
\r
835 /* Build the IRP for the HCA. */
\r
836 pIrp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, pDev,
\r
837 NULL, 0, NULL, &event, &ioStatus );
\r
840 ObDereferenceObject( pDev );
\r
841 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
842 ("IoBuildSynchronousFsdRequest failed.\n"));
\r
843 return STATUS_INSUFFICIENT_RESOURCES;
\r
846 /* Copy the request query parameters. */
\r
847 pIoStack = IoGetNextIrpStackLocation( pIrp );
\r
848 pIoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
\r
849 pIoStack->Parameters.QueryInterface.Size = size;
\r
850 pIoStack->Parameters.QueryInterface.Version = Version;
\r
851 pIoStack->Parameters.QueryInterface.InterfaceType = pGuid;
\r
852 pIoStack->Parameters.QueryInterface.Interface = (INTERFACE*)pBusIfc;
\r
853 pIoStack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;
\r
855 pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
\r
857 /* Send the IRP. */
\r
858 status = IoCallDriver( pDev, pIrp );
\r
859 if( status == STATUS_PENDING )
\r
861 KeWaitForSingleObject( &event, Executive, KernelMode,
\r
864 status = ioStatus.Status;
\r
866 ObDereferenceObject( pDev );
\r
868 HCA_EXIT( HCA_DBG_PNP );
\r
872 static ci_interface_t*
\r
874 IN PFDO_DEVICE_DATA const p_fdo )
\r
876 ci_interface_t *pIfc;
\r
878 HCA_ENTER( HCA_DBG_PNP );
\r
880 pIfc = (ci_interface_t*)ExAllocatePoolWithTag( PagedPool,
\r
881 sizeof(ci_interface_t), MT_TAG_KERNEL );
\r
884 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
885 ("Failed to allocate ci_interface_t (%d bytes).\n",
\r
886 sizeof(ci_interface_t)));
\r
890 setup_ci_interface( p_fdo->hca.guid, !!hca_is_livefish(p_fdo), pIfc );
\r
892 pIfc->p_hca_obj = &p_fdo->hca;
\r
893 pIfc->vend_id = (uint32_t)p_fdo->bus_ib_ifc.pdev->ven_id;
\r
894 pIfc->dev_id = (uint16_t)p_fdo->bus_ib_ifc.pdev->dev_id;
\r
895 pIfc->dev_revision = (uint16_t)p_fdo->hca.hw_ver;
\r
897 HCA_EXIT( HCA_DBG_PNP );
\r
902 __unmap_hca_memory(
\r
903 IN PFDO_DEVICE_DATA const p_fdo )
\r
905 struct pci_dev *pdev = p_fdo->bus_ib_ifc.pdev;
\r
908 HCA_ENTER( HCA_DBG_PNP );
\r
911 for( i = 0; i < HCA_BAR_TYPE_MAX; i++ ) {
\r
912 if (pdev->bar[i].virt) {
\r
913 MmUnmapIoSpace( pdev->bar[i].virt, pdev->bar[i].size );
\r
914 cl_memclr( &pdev->bar[i], sizeof(hca_bar_t) );
\r
918 HCA_EXIT( HCA_DBG_PNP );
\r
922 /* release the resources, allocated in hca_start */
\r
924 __hca_release_resources(
\r
925 IN DEVICE_OBJECT* const p_dev_obj )
\r
927 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
929 HCA_ENTER( HCA_DBG_PNP );
\r
931 switch( p_fdo->state )
\r
935 mlnx_hca_remove( &p_fdo->hca );
\r
938 if (p_fdo->al_sym_name.Buffer) {
\r
939 ExFreePool( p_fdo->al_sym_name.Buffer );
\r
940 p_fdo->al_sym_name.Buffer = NULL;
\r
943 if( p_fdo->pnp_target_entry )
\r
945 ASSERT( p_fdo->pnp_ifc_entry );
\r
946 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
947 p_fdo->pnp_target_entry = NULL;
\r
950 if( p_fdo->pnp_ifc_entry ) {
\r
951 IoUnregisterPlugPlayNotification( p_fdo->pnp_ifc_entry );
\r
952 p_fdo->pnp_ifc_entry = NULL;
\r
955 if( p_fdo->p_al_file_obj ) {
\r
956 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
957 p_fdo->p_al_file_obj = NULL;
\r
960 // release MLX4_BUS resources
\r
961 if(p_fdo->bus_ib_ifc_taken) {
\r
962 p_fdo->bus_ib_ifc_taken = FALSE;
\r
963 __put_ifc( (PINTERFACE)&p_fdo->bus_ib_ifc );
\r
966 // release PCI BUS resources
\r
967 if(p_fdo->bus_pci_ifc_taken) {
\r
968 p_fdo->bus_pci_ifc_taken = FALSE;
\r
969 __put_ifc( (PINTERFACE)&p_fdo->bus_pci_ifc );
\r
972 __unmap_hca_memory( p_fdo );
\r
974 p_fdo->state = HCA_ADDED;
\r
976 HCA_EXIT( HCA_DBG_PNP );
\r
981 hca_release_resources(
\r
982 IN DEVICE_OBJECT* const p_dev_obj )
\r
984 PFDO_DEVICE_DATA p_fdo;
\r
985 POWER_STATE powerState;
\r
987 HCA_ENTER( HCA_DBG_PNP );
\r
989 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
991 /* release all the resources, allocated in hca_start */
\r
992 __hca_release_resources(p_dev_obj);
\r
994 /* Notify the power manager that the device is powered down. */
\r
995 p_fdo->DevicePowerState = PowerDeviceD3;
\r
996 powerState.DeviceState = PowerDeviceD3;
\r
997 powerState = PoSetPowerState ( p_fdo->cl_ext.p_self_do, DevicePowerState, powerState );
\r
999 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
1000 ("PoSetPowerState: old state %d, new state to %d\n",
\r
1001 powerState.DeviceState, p_fdo->DevicePowerState ));
\r
1003 /* Clear the PnP state in case we get restarted. */
\r
1004 p_fdo->pnpState = 0;
\r
1006 HCA_EXIT( HCA_DBG_PNP );
\r
1011 IN DEVICE_OBJECT* const p_dev_obj,
\r
1012 IN IRP* const p_irp,
\r
1013 OUT cl_irp_action_t* const p_action )
\r
1017 PFDO_DEVICE_DATA p_fdo;
\r
1018 IO_STACK_LOCATION *pIoStack;
\r
1019 POWER_STATE powerState;
\r
1020 BUS_INTERFACE_STANDARD bus_pci_ifc;
\r
1022 HCA_ENTER( HCA_DBG_PNP );
\r
1024 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1026 /* Handled on the way up. */
\r
1027 status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
1028 if( !NT_SUCCESS( status ) )
\r
1030 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1031 ("Lower drivers failed IRP_MN_START_DEVICE (%#x).\n", status));
\r
1035 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1037 /* get PCI BUS interface */
\r
1038 status = __get_ifc( p_dev_obj, &GUID_BUS_INTERFACE_STANDARD,
\r
1039 sizeof(BUS_INTERFACE_STANDARD), 1, NULL, (PINTERFACE)&bus_pci_ifc);
\r
1040 if( !NT_SUCCESS( status ) ) {
\r
1041 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting PCI BUS interface failed: status=0x%x\n", status));
\r
1044 RtlCopyMemory( &p_fdo->bus_pci_ifc, &bus_pci_ifc, sizeof(BUS_INTERFACE_STANDARD) );
\r
1045 p_fdo->bus_pci_ifc_taken = TRUE;
\r
1047 /* get MLX4_BUS IB interface */
\r
1048 status = __get_ifc( p_dev_obj, &MLX4_BUS_IB_INTERFACE_GUID,
\r
1049 sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL, (PINTERFACE)&p_fdo->bus_ib_ifc);
\r
1050 if( !NT_SUCCESS( status ) ) {
\r
1051 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
\r
1054 p_fdo->bus_ib_ifc_taken = TRUE;
\r
1055 p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
\r
1057 InitializeListHead(&p_fdo->hca.event_list);
\r
1058 KeInitializeSpinLock(&p_fdo->hca.event_list_lock);
\r
1060 /* get node GUID */
\r
1061 err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );
\r
1064 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,
\r
1065 ("can't get guid - ib_query_device() failed (%08X)\n", err ));
\r
1066 //TODO: no cleanup on error
\r
1067 return STATUS_INSUFFICIENT_RESOURCES;
\r
1071 mlnx_hca_insert( &p_fdo->hca );
\r
1074 * Change the state since the PnP callback can happen
\r
1075 * before the callback returns.
\r
1077 p_fdo->state = HCA_STARTED;
\r
1079 /* We get started fully powered. */
\r
1080 p_fdo->DevicePowerState = PowerDeviceD0;
\r
1081 powerState.DeviceState = PowerDeviceD0;
\r
1082 powerState = PoSetPowerState ( p_fdo->cl_ext.p_self_do, DevicePowerState, powerState );
\r
1083 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
1084 ("PoSetPowerState: old state %d, new state to %d\n",
\r
1085 powerState.DeviceState, p_fdo->DevicePowerState ));
\r
1088 HCA_EXIT( HCA_DBG_PNP );
\r
1094 IN DEVICE_OBJECT* const p_dev_obj,
\r
1095 IN IRP* const p_irp,
\r
1096 OUT cl_irp_action_t* const p_action )
\r
1098 /* All kernel clients will get notified through the device hierarchy. */
\r
1100 /* TODO: set a flag to fail creation of any new IB resources. */
\r
1101 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1107 IN DEVICE_OBJECT* const p_dev_obj,
\r
1108 IN IRP* const p_irp,
\r
1109 OUT cl_irp_action_t* const p_action )
\r
1112 * Must disable everything. Complib framework will
\r
1113 * call ReleaseResources handler.
\r
1115 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1121 IN DEVICE_OBJECT* const p_dev_obj,
\r
1122 IN IRP* const p_irp,
\r
1123 OUT cl_irp_action_t* const p_action )
\r
1125 /* Handled on the way up. */
\r
1126 return cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
1132 IN DEVICE_OBJECT* const p_dev_obj,
\r
1133 IN IRP* const p_irp,
\r
1134 OUT cl_irp_action_t* const p_action )
\r
1136 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1137 if (atomic_read(&p_fdo->usecnt)) {
\r
1138 cl_dbg_out( "MTHCA: Can't get unloaded. %d applications are still in work\n", p_fdo->usecnt);
\r
1139 p_irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
\r
1140 return cl_irp_complete( p_dev_obj, p_irp, p_action );
\r
1142 /* TODO: set a flag to fail creation of any new IB resources. */
\r
1143 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1148 hca_cancel_remove(
\r
1149 IN DEVICE_OBJECT* const p_dev_obj,
\r
1150 IN IRP* const p_irp,
\r
1151 OUT cl_irp_action_t* const p_action )
\r
1153 /* Handled on the way up. */
\r
1154 return cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
1159 hca_surprise_remove(
\r
1160 IN DEVICE_OBJECT* const p_dev_obj,
\r
1161 IN IRP* const p_irp,
\r
1162 OUT cl_irp_action_t* const p_action )
\r
1165 * TODO: Set state so that all further requests
\r
1166 * automatically succeed/fail as needed.
\r
1168 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1173 hca_query_capabilities(
\r
1174 IN DEVICE_OBJECT* const p_dev_obj,
\r
1175 IN IRP* const p_irp,
\r
1176 OUT cl_irp_action_t* const p_action )
\r
1179 PFDO_DEVICE_DATA p_fdo;
\r
1180 IO_STACK_LOCATION *pIoStack;
\r
1181 DEVICE_CAPABILITIES *pCaps;
\r
1183 HCA_ENTER( HCA_DBG_PNP );
\r
1185 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1187 /* Process on the way up. */
\r
1188 status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
1189 if( !NT_SUCCESS( status ) )
\r
1191 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1192 ("cl_do_sync_pnp returned %08X.\n", status));
\r
1196 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1197 pCaps = pIoStack->Parameters.DeviceCapabilities.Capabilities;
\r
1200 * Store the device power mapping into our extension since we're
\r
1201 * the power policy owner. The mapping is used when handling
\r
1202 * IRP_MN_SET_POWER IRPs.
\r
1205 p_fdo->DevicePower, pCaps->DeviceState, sizeof(p_fdo->DevicePower) );
\r
1207 if( pCaps->DeviceD1 )
\r
1209 HCA_PRINT( TRACE_LEVEL_WARNING ,HCA_DBG_PNP,
\r
1210 ("WARNING: Device reports support for DeviceD1 power state.\n"));
\r
1211 pCaps->DeviceD1 = FALSE;
\r
1214 if( pCaps->DeviceD2 )
\r
1216 HCA_PRINT( TRACE_LEVEL_WARNING,HCA_DBG_PNP,
\r
1217 ("WARNING: Device reports support for DeviceD2 power state.\n"));
\r
1218 pCaps->DeviceD2 = FALSE;
\r
1221 if( pCaps->SystemWake != PowerSystemUnspecified )
\r
1223 HCA_PRINT( TRACE_LEVEL_WARNING ,HCA_DBG_PNP,
\r
1224 ("WARNING: Device reports support for system wake.\n"));
\r
1225 pCaps->SystemWake = PowerSystemUnspecified;
\r
1228 if( pCaps->DeviceWake != PowerDeviceUnspecified )
\r
1230 HCA_PRINT( TRACE_LEVEL_WARNING, HCA_DBG_PNP,
\r
1231 ("WARNING: Device reports support for device wake.\n"));
\r
1232 pCaps->DeviceWake = PowerDeviceUnspecified;
\r
1235 HCA_EXIT( HCA_DBG_PNP );
\r
1241 IN DEVICE_OBJECT* p_dev_obj )
\r
1243 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1245 HCA_ENTER( HCA_DBG_PNP );
\r
1247 cl_atomic_inc( &p_fdo->n_hca_ifc_ref );
\r
1248 ObReferenceObject( p_dev_obj );
\r
1250 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1251 ("MLX4_HCA: CA_guid %I64x, hca_ifc_ref %d\n",
\r
1252 p_fdo->hca.guid, p_fdo->n_hca_ifc_ref) );
\r
1254 HCA_EXIT( HCA_DBG_PNP );
\r
1259 IN DEVICE_OBJECT* p_dev_obj )
\r
1261 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1263 HCA_ENTER( HCA_DBG_PNP );
\r
1265 cl_atomic_dec( &p_fdo->n_hca_ifc_ref );
\r
1266 ObDereferenceObject( p_dev_obj );
\r
1268 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1269 ("MLX4_HCA: CA_guid %I64x, hca_ifc_ref %d\n",
\r
1270 p_fdo->hca.guid, p_fdo->n_hca_ifc_ref) );
\r
1272 HCA_EXIT( HCA_DBG_PNP );
\r
1277 IN DEVICE_OBJECT* const p_dev_obj,
\r
1278 IN IO_STACK_LOCATION* const p_io_stack )
\r
1280 RDMA_INTERFACE_VERBS *p_ifc;
\r
1281 PFDO_DEVICE_DATA p_fdo;
\r
1282 ci_interface_t *p_hca_ifc;
\r
1286 HCA_ENTER( HCA_DBG_PNP );
\r
1288 version = VerbsVersionMajor(p_io_stack->Parameters.QueryInterface.Version);
\r
1289 if( version > VERBS_MAJOR_VER )
\r
1291 status = STATUS_NOT_SUPPORTED;
\r
1295 if( p_io_stack->Parameters.QueryInterface.Size < sizeof(RDMA_INTERFACE_VERBS) )
\r
1297 status = STATUS_BUFFER_TOO_SMALL;
\r
1301 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1302 p_hca_ifc = __alloc_hca_ifc( p_fdo );
\r
1305 status = STATUS_NO_MEMORY;
\r
1309 p_ifc = (RDMA_INTERFACE_VERBS *) p_io_stack->Parameters.QueryInterface.Interface;
\r
1311 p_ifc->InterfaceHeader.Size = sizeof(RDMA_INTERFACE_VERBS);
\r
1312 p_ifc->InterfaceHeader.Version = VerbsVersion(VERBS_MAJOR_VER, VERBS_MINOR_VER);
\r
1313 p_ifc->InterfaceHeader.Context = p_dev_obj;
\r
1314 p_ifc->InterfaceHeader.InterfaceReference = __ref_ifc;
\r
1315 p_ifc->InterfaceHeader.InterfaceDereference = __deref_ifc;
\r
1316 p_ifc->Verbs = *p_hca_ifc;
\r
1318 /* take the reference before returning. */
\r
1319 __ref_ifc( p_dev_obj );
\r
1321 ExFreePool( p_hca_ifc );
\r
1322 status = STATUS_SUCCESS;
\r
1325 HCA_EXIT( HCA_DBG_PNP );
\r
1331 hca_query_interface(
\r
1332 IN DEVICE_OBJECT* const p_dev_obj,
\r
1333 IN IRP* const p_irp,
\r
1334 OUT cl_irp_action_t* const p_action )
\r
1337 IO_STACK_LOCATION *p_io_stack;
\r
1339 HCA_ENTER( HCA_DBG_PNP );
\r
1341 #pragma warning( push, 3 )
\r
1343 #pragma warning( pop )
\r
1345 p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
\r
1347 /* Compare requested GUID with our supported interface GUIDs. */
\r
1348 if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,
\r
1349 &GUID_RDMA_INTERFACE_VERBS ) )
\r
1351 status = __query_ci_ifc( p_dev_obj, p_io_stack );
\r
1352 if( !NT_SUCCESS( status ) )
\r
1354 *p_action = IrpComplete;
\r
1358 *p_action = IrpSkip;
\r
1363 status = p_irp->IoStatus.Status;
\r
1364 *p_action = IrpSkip;
\r
1367 HCA_EXIT( HCA_DBG_PNP );
\r
1373 hca_query_pnp_state(
\r
1374 IN DEVICE_OBJECT* const p_dev_obj,
\r
1375 IN IRP* const p_irp,
\r
1376 OUT cl_irp_action_t* const p_action )
\r
1378 PFDO_DEVICE_DATA p_fdo;
\r
1380 HCA_ENTER( HCA_DBG_PNP );
\r
1382 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1384 p_irp->IoStatus.Information |= p_fdo->pnpState;
\r
1386 *p_action = IrpSkip;
\r
1388 HCA_EXIT( HCA_DBG_PNP );
\r
1389 return STATUS_SUCCESS;;
\r
1394 IN DEVICE_OBJECT* const p_dev_obj,
\r
1395 IN IRP* const p_irp,
\r
1396 OUT cl_irp_action_t* const p_action )
\r
1398 NTSTATUS status = STATUS_SUCCESS;
\r
1399 IO_STACK_LOCATION *pIoStack;
\r
1401 HCA_ENTER(HCA_DBG_PO);
\r
1403 UNUSED_PARAM( p_dev_obj );
\r
1405 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1407 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
1408 ("QUERY_POWER for FDO %p: type %s, state %d, action %d, IRQL %d, IRP %p\n",
\r
1410 (pIoStack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",
\r
1411 pIoStack->Parameters.Power.State.DeviceState,
\r
1412 pIoStack->Parameters.Power.ShutdownType, KeGetCurrentIrql(), p_irp ));
\r
1414 switch( pIoStack->Parameters.Power.Type )
\r
1416 case SystemPowerState:
\r
1417 /* Fail any requests to hibernate or sleep the system. */
\r
1418 switch( pIoStack->Parameters.Power.State.SystemState )
\r
1420 case PowerSystemSleeping1: // STANDBY support
\r
1421 case PowerSystemSleeping2: // STANDBY support
\r
1422 case PowerSystemSleeping3: // STANDBY support
\r
1423 case PowerSystemHibernate:
\r
1425 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1426 if (atomic_read(&p_fdo->usecnt))
\r
1427 status = STATUS_UNSUCCESSFUL;
\r
1431 case PowerSystemWorking:
\r
1432 case PowerSystemShutdown:
\r
1436 status = STATUS_NOT_SUPPORTED;
\r
1440 case DevicePowerState:
\r
1441 /* Fail any query for low power states. */
\r
1442 switch( pIoStack->Parameters.Power.State.DeviceState )
\r
1444 case PowerDeviceD0:
\r
1445 case PowerDeviceD3:
\r
1446 /* We only support fully powered or off power states. */
\r
1450 status = STATUS_NOT_SUPPORTED;
\r
1455 if( status == STATUS_SUCCESS )
\r
1456 *p_action = IrpSkip;
\r
1458 *p_action = IrpComplete;
\r
1460 HCA_EXIT( HCA_DBG_PO );
\r
1466 __RequestPowerCompletion(
\r
1467 IN DEVICE_OBJECT *p_dev_obj,
\r
1468 IN UCHAR minorFunction,
\r
1469 IN POWER_STATE powerState,
\r
1471 IN IO_STATUS_BLOCK *pIoStatus )
\r
1474 cl_pnp_po_ext_t *p_fdo;
\r
1476 HCA_ENTER( HCA_DBG_PO );
\r
1478 UNUSED_PARAM( minorFunction );
\r
1479 UNUSED_PARAM( powerState );
\r
1481 p_irp = (IRP*)context;
\r
1482 p_fdo = (cl_pnp_po_ext_t*)p_dev_obj->DeviceExtension;
\r
1484 /* Propagate the device IRP status to the system IRP status. */
\r
1485 p_irp->IoStatus.Status = pIoStatus->Status;
\r
1487 /* Continue Power IRP processing. */
\r
1488 PoStartNextPowerIrp( p_irp );
\r
1489 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
1490 IoReleaseRemoveLock( &p_fdo->remove_lock, p_irp );
\r
1491 HCA_EXIT( HCA_DBG_PO );
\r
1495 /*NOTE: Completion routines must NEVER be pageable. */
\r
1497 __SystemPowerCompletion(
\r
1498 IN DEVICE_OBJECT *p_dev_obj,
\r
1500 IN void *context )
\r
1503 POWER_STATE state;
\r
1504 PFDO_DEVICE_DATA p_fdo;
\r
1505 IO_STACK_LOCATION *pIoStack;
\r
1507 HCA_ENTER( HCA_DBG_PO );
\r
1509 UNUSED_PARAM( context );
\r
1511 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1512 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1514 if( !NT_SUCCESS( p_irp->IoStatus.Status ) )
\r
1516 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
1517 ("IRP_MN_SET_POWER for system failed by lower driver with %08x.\n",
\r
1518 p_irp->IoStatus.Status));
\r
1519 status = STATUS_SUCCESS;
\r
1520 PoStartNextPowerIrp( p_irp );
\r
1524 state.DeviceState =
\r
1525 p_fdo->DevicePower[pIoStack->Parameters.Power.State.SystemState];
\r
1528 * Send a device power IRP to our devnode. Using our device object will
\r
1529 * only work on win2k and other NT based systems.
\r
1531 status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,
\r
1532 __RequestPowerCompletion, p_irp, NULL );
\r
1534 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
1535 ("PoRequestPowerIrp: SET_POWER 'PowerDeviceD%d', status %#x\n",
\r
1536 state.DeviceState - 1, status ));
\r
1538 if( status != STATUS_PENDING ) {
\r
1539 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
1540 ("PoRequestPowerIrp returned %08x.\n", status));
\r
1541 p_irp->IoStatus.Status = status; /* Propagate the failure. */
\r
1542 PoStartNextPowerIrp( p_irp );
\r
1543 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
1547 status = STATUS_MORE_PROCESSING_REQUIRED;
\r
1551 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
1553 HCA_EXIT( HCA_DBG_PO );
\r
1558 /* Work item callback to handle DevicePowerD0 IRPs at passive level. */
\r
1560 __DevicePowerUpCompletionWorkItem(
\r
1561 IN DEVICE_OBJECT* p_dev_obj,
\r
1562 IN void* context )
\r
1566 IO_STACK_LOCATION *pIoStack;
\r
1567 PFDO_DEVICE_DATA p_fdo;
\r
1569 POWER_STATE powerState;
\r
1571 HCA_ENTER( HCA_DBG_PO );
\r
1573 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1574 p_irp = (IRP*)context;
\r
1575 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1577 IoFreeWorkItem( p_fdo->pPoWorkItem );
\r
1578 p_fdo->pPoWorkItem = NULL;
\r
1580 /* restart the HCA */
\r
1581 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
1582 ("***** Restart the HCA, IRQL %d\n", KeGetCurrentIrql()));
\r
1584 /* get MLX4_BUS IB interface */
\r
1585 status = __get_ifc( p_dev_obj, &MLX4_BUS_IB_INTERFACE_GUID,
\r
1586 sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL, (PINTERFACE)&p_fdo->bus_ib_ifc);
\r
1587 if( !NT_SUCCESS( status ) ) {
\r
1588 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
\r
1591 p_fdo->bus_ib_ifc_taken = TRUE;
\r
1592 p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
\r
1594 /* get node GUID */
\r
1595 err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );
\r
1598 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,
\r
1599 ("can't get guid - ib_query_device() failed (%08X)\n", err ));
\r
1600 //TODO: no cleanup on error
\r
1604 p_fdo->DevicePowerState = pIoStack->Parameters.Power.State.DeviceState;
\r
1605 powerState = PoSetPowerState( p_dev_obj, DevicePowerState,
\r
1606 pIoStack->Parameters.Power.State );
\r
1608 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
1609 ("PoSetPowerState: old state %d, new state to %d\n",
\r
1610 powerState.DeviceState, p_fdo->DevicePowerState ));
\r
1615 /* Flag device as having failed. */
\r
1616 p_fdo->pnpState |= PNP_DEVICE_FAILED;
\r
1617 IoInvalidateDeviceState( p_fdo->cl_ext.p_pdo );
\r
1619 PoStartNextPowerIrp( p_irp );
\r
1620 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
1621 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
1622 HCA_EXIT( HCA_DBG_PO );
\r
1625 /*NOTE: Completion routines must NEVER be pageable. */
\r
1627 __DevicePowerUpCompletion(
\r
1628 IN DEVICE_OBJECT *p_dev_obj,
\r
1630 IN void *context )
\r
1632 NTSTATUS status = STATUS_SUCCESS;
\r
1633 PFDO_DEVICE_DATA p_fdo;
\r
1634 IO_STACK_LOCATION *pIoStack;
\r
1636 HCA_ENTER( HCA_DBG_PO );
\r
1638 UNUSED_PARAM( context );
\r
1640 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1641 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1643 if( !NT_SUCCESS( p_irp->IoStatus.Status ) ) {
\r
1644 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
1645 ("IRP_MN_SET_POWER for device failed by lower driver with %08x.\n",
\r
1646 p_irp->IoStatus.Status));
\r
1647 status = STATUS_SUCCESS;
\r
1648 PoStartNextPowerIrp( p_irp );
\r
1652 /* Process in a work item - mthca_start blocks. */
\r
1653 ASSERT( !p_fdo->pPoWorkItem );
\r
1654 p_fdo->pPoWorkItem = IoAllocateWorkItem( p_dev_obj );
\r
1655 if( !p_fdo->pPoWorkItem ) {
\r
1656 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
1657 ("Failed to allocate work item.\n" ));
\r
1658 status = STATUS_SUCCESS;
\r
1659 p_fdo->pnpState |= PNP_DEVICE_FAILED;
\r
1660 IoInvalidateDeviceState( p_fdo->cl_ext.p_pdo );
\r
1661 PoStartNextPowerIrp( p_irp );
\r
1665 /* Process in work item callback. */
\r
1666 IoMarkIrpPending( p_irp );
\r
1667 IoQueueWorkItem( p_fdo->pPoWorkItem,
\r
1668 __DevicePowerUpCompletionWorkItem, DelayedWorkQueue, p_irp );
\r
1669 status = STATUS_MORE_PROCESSING_REQUIRED;
\r
1673 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
1675 HCA_EXIT( HCA_DBG_PO );
\r
1679 static NTSTATUS __DevicePowerDownWorkItemCompletion(
\r
1680 IN DEVICE_OBJECT *p_dev_obj,
\r
1682 IN void *context )
\r
1684 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1685 UNUSED_PARAM( context );
\r
1687 HCA_ENTER( HCA_DBG_PO );
\r
1689 PoStartNextPowerIrp( p_irp );
\r
1690 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
1692 HCA_EXIT( HCA_DBG_PO );
\r
1693 return STATUS_SUCCESS;
\r
1696 /* Work item callback to handle DevicePowerD3 IRPs at passive level. */
\r
1698 __DevicePowerDownWorkItem(
\r
1699 IN DEVICE_OBJECT* p_dev_obj,
\r
1700 IN void* context )
\r
1702 IO_STACK_LOCATION *pIoStack;
\r
1703 PFDO_DEVICE_DATA p_fdo;
\r
1705 POWER_STATE powerState;
\r
1707 HCA_ENTER( HCA_DBG_PO );
\r
1709 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1710 p_irp = (IRP*)context;
\r
1711 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1713 IoFreeWorkItem( p_fdo->pPoWorkItem );
\r
1714 p_fdo->pPoWorkItem = NULL;
\r
1716 p_fdo->DevicePowerState = pIoStack->Parameters.Power.State.DeviceState;
\r
1717 powerState = PoSetPowerState( p_dev_obj, DevicePowerState,
\r
1718 pIoStack->Parameters.Power.State );
\r
1720 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
1721 ("PoSetPowerState: old state %d, new state to %d, IRQL %d\n",
\r
1722 powerState.DeviceState, p_fdo->DevicePowerState, KeGetCurrentIrql() ));
\r
1724 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
1725 ("***** Remove the HCA \n"));
\r
1727 // release MLX4_BUS resources
\r
1728 if(p_fdo->bus_ib_ifc_taken) {
\r
1729 p_fdo->bus_ib_ifc_taken = FALSE;
\r
1730 __put_ifc( (PINTERFACE)&p_fdo->bus_ib_ifc );
\r
1733 IoCopyCurrentIrpStackLocationToNext( p_irp );
\r
1734 #pragma warning( push, 3 )
\r
1735 IoSetCompletionRoutine( p_irp, __DevicePowerDownWorkItemCompletion,
\r
1736 NULL, TRUE, TRUE, TRUE );
\r
1737 #pragma warning( pop )
\r
1738 PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
1740 HCA_EXIT( HCA_DBG_PO );
\r
1746 IN DEVICE_OBJECT* const p_dev_obj,
\r
1747 IN IRP* const p_irp,
\r
1748 OUT cl_irp_action_t* const p_action )
\r
1751 IO_STACK_LOCATION *pIoStack;
\r
1752 PFDO_DEVICE_DATA p_fdo;
\r
1754 HCA_ENTER( HCA_DBG_PO );
\r
1756 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1757 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1759 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
1760 ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d, IRQL %d \n",
\r
1762 (pIoStack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",
\r
1763 pIoStack->Parameters.Power.State.DeviceState,
\r
1764 pIoStack->Parameters.Power.ShutdownType, KeGetCurrentIrql() ));
\r
1766 switch( pIoStack->Parameters.Power.Type )
\r
1768 case SystemPowerState:
\r
1769 p_fdo->SystemPowerState = pIoStack->Parameters.Power.State.SystemState;
\r
1772 * Process on the way up the stack. We cannot block since the
\r
1773 * power dispatch function can be called at elevated IRQL if the
\r
1774 * device is in a paging/hibernation/crash dump path.
\r
1776 IoMarkIrpPending( p_irp );
\r
1777 IoCopyCurrentIrpStackLocationToNext( p_irp );
\r
1778 #pragma warning( push, 3 )
\r
1779 IoSetCompletionRoutine( p_irp, __SystemPowerCompletion, NULL,
\r
1780 TRUE, TRUE, TRUE );
\r
1781 #pragma warning( pop )
\r
1782 PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
1784 *p_action = IrpDoNothing;
\r
1785 status = STATUS_PENDING;
\r
1788 case DevicePowerState:
\r
1789 IoMarkIrpPending( p_irp );
\r
1790 if( pIoStack->Parameters.Power.State.DeviceState == PowerDeviceD0 &&
\r
1791 p_fdo->SystemPowerState == PowerSystemWorking)
\r
1793 /* If we're already powered up, just pass down. */
\r
1794 if( p_fdo->DevicePowerState == PowerDeviceD0 )
\r
1796 status = STATUS_SUCCESS;
\r
1797 *p_action = IrpIgnore;
\r
1801 /* Process in I/O completion callback. */
\r
1802 IoCopyCurrentIrpStackLocationToNext( p_irp );
\r
1803 #pragma warning( push, 3 )
\r
1804 IoSetCompletionRoutine( p_irp, __DevicePowerUpCompletion, NULL,
\r
1805 TRUE, TRUE, TRUE );
\r
1806 #pragma warning( pop )
\r
1807 PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
1810 { /* power down */
\r
1812 /* Process in a work item - deregister_ca and HcaDeinit block. */
\r
1813 ASSERT( !p_fdo->pPoWorkItem );
\r
1814 p_fdo->pPoWorkItem = IoAllocateWorkItem( p_dev_obj );
\r
1815 if( !p_fdo->pPoWorkItem )
\r
1817 status = STATUS_INSUFFICIENT_RESOURCES;
\r
1821 /* Process in work item callback. */
\r
1823 p_fdo->pPoWorkItem, __DevicePowerDownWorkItem, DelayedWorkQueue, p_irp );
\r
1825 *p_action = IrpDoNothing;
\r
1826 status = STATUS_PENDING;
\r
1830 /* Pass down and let the PDO driver handle it. */
\r
1831 *p_action = IrpIgnore;
\r
1832 status = STATUS_SUCCESS;
\r
1836 if( !NT_SUCCESS( status ) )
\r
1837 *p_action = IrpComplete;
\r
1839 HCA_EXIT( HCA_DBG_PNP );
\r
1844 hca_init_vfptr( void )
\r
1846 vfptrHcaPnp.identity = "MLX4_HCA driver";
\r
1847 vfptrHcaPnp.pfn_start = hca_start;
\r
1848 vfptrHcaPnp.pfn_query_stop = hca_query_stop;
\r
1849 vfptrHcaPnp.pfn_stop = hca_stop;
\r
1850 vfptrHcaPnp.pfn_cancel_stop = hca_cancel_stop;
\r
1851 vfptrHcaPnp.pfn_query_remove = hca_query_remove;
\r
1852 vfptrHcaPnp.pfn_release_resources = hca_release_resources;
\r
1853 vfptrHcaPnp.pfn_remove = cl_do_remove;
\r
1854 vfptrHcaPnp.pfn_cancel_remove = hca_cancel_remove;
\r
1855 vfptrHcaPnp.pfn_surprise_remove = hca_surprise_remove;
\r
1856 vfptrHcaPnp.pfn_query_capabilities = hca_query_capabilities;
\r
1857 vfptrHcaPnp.pfn_query_pnp_state = hca_query_pnp_state;
\r
1858 vfptrHcaPnp.pfn_filter_res_req = cl_irp_skip;
\r
1859 vfptrHcaPnp.pfn_dev_usage_notification = cl_do_sync_pnp;
\r
1860 vfptrHcaPnp.pfn_query_bus_relations = cl_irp_ignore;
\r
1861 vfptrHcaPnp.pfn_query_ejection_relations = cl_irp_ignore;
\r
1862 vfptrHcaPnp.pfn_query_removal_relations = cl_irp_ignore;
\r
1863 vfptrHcaPnp.pfn_query_target_relations = cl_irp_ignore;
\r
1864 vfptrHcaPnp.pfn_unknown = cl_irp_ignore;
\r
1865 vfptrHcaPnp.pfn_query_resources = cl_irp_ignore;
\r
1866 vfptrHcaPnp.pfn_query_res_req = cl_irp_ignore;
\r
1867 vfptrHcaPnp.pfn_query_bus_info = cl_irp_ignore;
\r
1868 vfptrHcaPnp.pfn_query_interface = hca_query_interface;
\r
1869 vfptrHcaPnp.pfn_read_config = cl_irp_ignore;
\r
1870 vfptrHcaPnp.pfn_write_config = cl_irp_ignore;
\r
1871 vfptrHcaPnp.pfn_eject = cl_irp_ignore;
\r
1872 vfptrHcaPnp.pfn_set_lock = cl_irp_ignore;
\r
1873 vfptrHcaPnp.pfn_query_power = hca_query_power;
\r
1874 vfptrHcaPnp.pfn_set_power = hca_set_power;
\r
1875 vfptrHcaPnp.pfn_power_sequence = cl_irp_ignore;
\r
1876 vfptrHcaPnp.pfn_wait_wake = cl_irp_ignore;
\r
1881 IN UNICODE_STRING* const p_registry_path )
\r
1884 /* Remember the terminating entry in the table below. */
\r
1885 RTL_QUERY_REGISTRY_TABLE table[3];
\r
1887 HCA_ENTER( HCA_DBG_PNP );
\r
1889 RtlInitUnicodeString( &g_param_path, NULL );
\r
1890 g_param_path.MaximumLength = p_registry_path->Length +
\r
1891 sizeof(L"\\Parameters");
\r
1892 g_param_path.Buffer = cl_zalloc( g_param_path.MaximumLength );
\r
1893 if( !g_param_path.Buffer )
\r
1895 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1896 ("Failed to allocate parameters path buffer.\n"));
\r
1897 return STATUS_INSUFFICIENT_RESOURCES;
\r
1900 RtlAppendUnicodeStringToString( &g_param_path, p_registry_path );
\r
1901 RtlAppendUnicodeToString( &g_param_path, L"\\Parameters" );
\r
1904 * Clear the table. This clears all the query callback pointers,
\r
1905 * and sets up the terminating table entry.
\r
1907 cl_memclr( table, sizeof(table) );
\r
1909 /* Setup the table entries. */
\r
1910 table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
1911 table[0].Name = L"DebugLevel";
\r
1912 table[0].EntryContext = &g.DebugPrintLevel;
\r
1913 table[0].DefaultType = REG_DWORD;
\r
1914 table[0].DefaultData = &g.DebugPrintLevel;
\r
1915 table[0].DefaultLength = sizeof(ULONG);
\r
1918 table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
1919 table[1].Name = L"DebugFlags";
\r
1920 table[1].EntryContext = &g.DebugPrintFlags;
\r
1921 table[1].DefaultType = REG_DWORD;
\r
1922 table[1].DefaultData = &g.DebugPrintFlags;
\r
1923 table[1].DefaultLength = sizeof(ULONG);
\r
1927 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
1928 g_param_path.Buffer, table, NULL, NULL );
\r
1930 HCA_EXIT( HCA_DBG_PNP );
\r
1936 IN PDRIVER_OBJECT p_driver_obj )
\r
1938 HCA_ENTER( HCA_DBG_PNP );
\r
1940 UNUSED_PARAM( p_driver_obj );
\r
1942 cl_free( g_param_path.Buffer );
\r
1944 HCA_EXIT( HCA_DBG_PNP );
\r
1945 #if defined(EVENT_TRACING)
\r
1946 WPP_CLEANUP(p_driver_obj);
\r
1953 IN PDEVICE_OBJECT p_dev_obj,
\r
1957 PFDO_DEVICE_DATA p_fdo;
\r
1959 HCA_ENTER( HCA_DBG_PNP );
\r
1961 p_fdo = p_dev_obj->DeviceExtension;
\r
1963 IoSkipCurrentIrpStackLocation( p_irp );
\r
1964 status = IoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
1966 HCA_EXIT( HCA_DBG_PNP );
\r
1973 IN PDRIVER_OBJECT p_driver_obj,
\r
1974 IN PUNICODE_STRING p_registry_path )
\r
1977 #if defined(EVENT_TRACING)
\r
1978 WPP_INIT_TRACING(p_driver_obj ,p_registry_path);
\r
1980 // global initializations
\r
1981 g.DebugPrintLevel = TRACE_LEVEL_VERBOSE;
\r
1982 g.DebugPrintFlags = 0xffff;
\r
1984 HCA_ENTER( HCA_DBG_PNP );
\r
1986 status = mlnx_hcas_init();
\r
1987 if( status != STATUS_SUCCESS ) {
\r
1988 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,
\r
1989 ("mlnx_hcas_init returned %#x.\n", status));
\r
1993 status = __read_registry( p_registry_path );
\r
1994 if( !NT_SUCCESS( status ) )
\r
1996 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1997 ("__read_registry_path returned 0x%X.\n", status));
\r
2001 /*leo: init function table */
\r
2004 p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;
\r
2005 p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;
\r
2006 p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = hca_sysctl;
\r
2007 p_driver_obj->DriverUnload = hca_drv_unload;
\r
2008 p_driver_obj->DriverExtension->AddDevice = hca_add_device;
\r
2011 HCA_EXIT( HCA_DBG_PNP );
\r
2012 return STATUS_SUCCESS;
\r