SOURCES= \\r
mthca_log.mc \\r
hca.rc \\r
- pcidrv.c \\r
+ mthca_kmdf.c \\r
+ wmi.c \\r
mthca_log.c \\r
\\r
..\hca_utils.c \\r
mthca_uar.c \\r
\r
\r
-INCLUDES=\\r
+INCLUDES=$(INCLUDES);\\r
..; \\r
$(TRUNK)\inc; \\r
- $(TRUNK)\inc\kernel;\r
+ $(TRUNK)\inc\kernel; \\r
+ $(TARGETPATH)\*;\r
\r
C_DEFINES=$(C_DEFINES) -DDRIVER -DDEPRECATE_DDK_FUNCTIONS -D__LITTLE_ENDIAN\r
\r
\r
NTTARGETFILE0=$(OBJ_PATH)\$(O)\$(INF_NAME).bmf\r
\r
-NTTARGETFILES=$(OBJ_PATH)\$(O)\$(INF_NAME).inf\r
-\r
MISCFILES=$(NTTARGETFILES)\r
\r
+NTTARGETFILES=$(OBJ_PATH)\$(O)\$(INF_NAME).inf\r
+\r
#LINKER_FLAGS=/MAP \r
\r
!IFDEF ENABLE_EVENT_TRACING\r
# -func:HCA_PRINT_EV(LEVEL,FLAGS,(MSG,...)) \\r
\r
MSC_OPTIMIZATION=/Oi\r
-MSC_WARNING_LEVEL= /W4\r
+# ignore volatile ignored warning @ line 318 in mt_atmoic.h\r
+MSC_WARNING_LEVEL= /W4 /wd4197 /wd4324 /wd4201\r
#include <oib_ver.h>\r
\r
#define VER_FILETYPE VFT_DRV\r
-#define VER_FILESUBTYPE VFT2_UNKNOWN\r
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM\r
#ifdef DBG\r
-#define VER_FILEDESCRIPTION_STR "HCA Driver WDF-KMDF (checked)"\r
+#define VER_FILEDESCRIPTION_STR "WDF-KMDF HCA Driver (checked)"\r
#else\r
-#define VER_FILEDESCRIPTION_STR "HCA Driver WDF-KMDF"\r
+#define VER_FILEDESCRIPTION_STR "WDF-KMDF HCA Driver"\r
#endif\r
#define VER_INTERNALNAME_STR "mthca.sys"\r
#define VER_ORIGINALFILENAME_STR "mthca.sys"\r
-#include <common.ver>\r
+\r
+#include "common.ver"\r
\r
#include <mthca_log.rc>\r
+\r
+mthcaWMI MOFDATA mthca.bmf\r
+\r
#ifndef _HCA_DEBUG_H_\r
#define _HCA_DEBUG_H_\r
\r
+#include <ntstrsafe.h>\r
+#include <trace.h>\r
\r
extern uint32_t g_mthca_dbg_level;\r
extern uint32_t g_mthca_dbg_flags;\r
extern WCHAR g_wlog_buf[ MAX_LOG_BUF_LEN ]; \r
extern UCHAR g_slog_buf[ MAX_LOG_BUF_LEN ]; \r
\r
-static void _build_str( const char * format, ... )\r
+static inline void __build_str( const char *format, ... )\r
{\r
va_list p_arg;\r
va_start(p_arg, format);\r
- vsprintf((char *)g_slog_buf , format , p_arg);\r
- swprintf(g_wlog_buf, L"%S", g_slog_buf);\r
+ RtlStringCbVPrintfA((char*)g_slog_buf, MAX_LOG_BUF_LEN, format , p_arg);\r
+ RtlStringCbPrintfW(g_wlog_buf, MAX_LOG_BUF_LEN, L"%S", g_slog_buf);\r
va_end(p_arg);\r
}\r
\r
case TRACE_LEVEL_WARNING: event_id = EVENT_MTHCA_ANY_WARN; break; \\r
default: event_id = EVENT_MTHCA_ANY_INFO; break; \\r
} \\r
- _build_str _msg_; \\r
+ __build_str _msg_; \\r
WriteEventLogEntryStr( _obj_, (ULONG)event_id, 0, 0, g_wlog_buf, 0, 0 ); \\r
}\r
\r
#define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps\r
*/\r
uint32_t g_mthca_dbg_level = TRACE_LEVEL_INFORMATION;\r
-uint32_t g_mthca_dbg_flags= 0xffff;\r
+uint32_t g_mthca_dbg_flags= 0xffff | DBG_PNP;\r
WCHAR g_wlog_buf[ MAX_LOG_BUF_LEN ];\r
UCHAR g_slog_buf[ MAX_LOG_BUF_LEN ];\r
uint32_t g_skip_tavor_reset=0; /* skip reset for Tavor cards */\r
-uint32_t g_disable_tavor_reset=1; /* disable Tavor reset for the next driver load */\r
+uint32_t g_disable_tavor_reset=1; /* disable Tavor reset for the next driver load */\r
uint32_t g_tune_pci=0; /* 0 - skip tuning PCI configuration space of HCAs */\r
uint32_t g_processor_affinity = 0;\r
uint32_t g_max_DPC_time_us = 10000;\r
uint32_t g_profile_qp_num = 0;\r
uint32_t g_profile_rd_out = 0xffffffff;\r
\r
-UNICODE_STRING g_param_path;\r
+UNICODE_STRING g_param_path;\r
\r
\r
/*\r
HCA_EXIT( HCA_DBG_DEV );\r
}\r
\r
-static void\r
-hca_drv_unload(\r
- IN PDRIVER_OBJECT p_driver_obj )\r
+void\r
+hca_drv_unload( IN PDRIVER_OBJECT p_driver_obj )\r
{\r
HCA_ENTER( HCA_DBG_DEV );\r
\r
#include "hca_data.h"\r
#include "mt_l2w.h"\r
#include "hca_debug.h"\r
+#include "trace.h"\r
\r
\r
#include "hca_pnp.h"\r
} hca_bar_t;\r
\r
\r
+//\r
+// The WDF driver context extenstion contains global data to the KMDF driver.\r
+//\r
+typedef struct _DRIVER_CONTEXT {\r
+\r
+ // WDFLOOKASIDE RecvLookaside; TBD\r
+ PDRIVER_OBJECT DrvObj; // top-level/DriverEntry driver object\r
+\r
+} DRIVER_CONTEXT, * PDRIVER_CONTEXT;\r
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DRIVER_CONTEXT, GetDriverContext)\r
+\r
typedef struct _hca_dev_ext\r
{\r
/* -------------------------------------------------\r
* PNP DATA \r
* ------------------------------------------------ */\r
- cl_pnp_po_ext_t cl_ext; /* COMPLIB PnP object */\r
- void * pnp_ifc_entry; /* Notification entry for PnP interface events. */\r
- void * pnp_target_entry; /* Notification entry for PnP target events. */\r
- PNP_DEVICE_STATE pnpState; /* state for PnP Manager */\r
+ cl_pnp_po_ext_t cl_ext; /* COMPLIB PnP object */\r
+ void *pnp_ifc_entry;/* Notification entry for PnP interface events. */\r
+ void *pnp_target_entry;/* Notification entry for PnP target events. */\r
+ PNP_DEVICE_STATE pnpState; /* state for PnP Manager */\r
\r
/* -------------------------------------------------\r
* POWER MANAGER DATA \r
/* -------------------------------------------------\r
* IB_AL DATA \r
* ------------------------------------------------ */\r
- ib_ci_ifc_t ci_ifc; /* Interface for the lower edge of the IB_AL device. */\r
- hca_reg_state_t state; /* State for tracking registration with AL */\r
- DEVICE_OBJECT * p_al_dev; /* IB_AL FDO */\r
- FILE_OBJECT * p_al_file_obj; /* IB_AL file object */\r
- UNICODE_STRING al_sym_name; /* IB_AL symbolic name */\r
+ ib_ci_ifc_t ci_ifc; /* IB_AL device: lower edge Interface */\r
+ hca_reg_state_t state;/* State for tracking registration with AL */\r
+ DEVICE_OBJECT * p_al_dev; /* IB_AL FDO */\r
+ FILE_OBJECT * p_al_file_obj; /* IB_AL file object */\r
+ UNICODE_STRING al_sym_name; /* IB_AL symbolic name */\r
\r
/* -------------------------------------------------\r
* LOW LEVEL DRIVER' DATA \r
* ------------------------------------------------ */\r
- mlnx_hca_t hca;\r
- atomic32_t usecnt; /* the number of working applications*/\r
- cl_spinlock_t uctx_lock; // spinlock for the below chain\r
- cl_qlist_t uctx_list; // chain of user contexts\r
+ mlnx_hca_t hca;\r
+ atomic32_t usecnt; /* the number of working applications*/\r
+ cl_spinlock_t uctx_lock; // spinlock for the below chain\r
+ cl_qlist_t uctx_list; // chain of user contexts\r
\r
/* -------------------------------------------------\r
* OS DATA \r
* ------------------------------------------------ */\r
- hca_bar_t bar[HCA_BAR_TYPE_MAX]; /* HCA memory bars */\r
- CM_PARTIAL_RESOURCE_DESCRIPTOR interruptInfo; /* HCA interrupt resources */\r
- PKINTERRUPT int_obj; /* HCA interrupt object */\r
- spinlock_t isr_lock; /* lock for the ISR */\r
- ULONG bus_number; /* HCA's bus number */\r
- BUS_INTERFACE_STANDARD hcaBusIfc; /* PCI bus interface */\r
+ hca_bar_t bar[HCA_BAR_TYPE_MAX]; /* HCA memory bars */\r
+ CM_PARTIAL_RESOURCE_DESCRIPTOR interruptInfo; /* HCA interrupt resource */\r
+ PKINTERRUPT int_obj; /* HCA interrupt object */\r
+ spinlock_t isr_lock; /* lock for the ISR */\r
+ ULONG bus_number; /* HCA's bus number */\r
+ BUS_INTERFACE_STANDARD hcaBusIfc; /* PCI bus interface */\r
\r
/* -------------------------------------------------\r
* VARIABLES \r
* ------------------------------------------------ */\r
- DMA_ADAPTER * p_dma_adapter; /* HCA adapter object */\r
- ULONG n_map_regs; /* num of allocated adapter map registers */\r
- PCI_COMMON_CONFIG hcaConfig; /* saved HCA PCI configuration header */\r
- int hca_hidden; /* flag: when set - no attached DDR memory */\r
+ DMA_ADAPTER *p_dma_adapter; /* HCA adapter object */\r
+ ULONG n_map_regs; /* num of allocated adapter map registers */\r
+ PCI_COMMON_CONFIG hcaConfig; /* saved HCA PCI configuration header */\r
+ int hca_hidden; /* flag: when set - no attached DDR memory */\r
WDFDEVICE WdfDevice; \r
\r
} hca_dev_ext_t, FDO_DATA, *PFDO_DATA;\r
\r
#define _DRIVER_NAME_ "mthca"\r
\r
+typedef struct _MTHCA_WMI_STD_DATA {\r
+\r
+ // TBD... XXX ?\r
+ UINT64 HcaGUID;\r
+ UINT64 Port0GUID;\r
+ UINT64 Port1GUID;\r
+\r
+} MTHCA_WMI_STD_DATA, * PMTHCA_WMI_STD_DATA;\r
+\r
+\r
+//\r
+// KMDF Function prototypes\r
+//\r
+\r
+EVT_WDF_DRIVER_DEVICE_ADD HcaEvtDeviceAdd;\r
+\r
+EVT_WDF_OBJECT_CONTEXT_CLEANUP HcaEvtDriverContextCleanup;\r
+EVT_WDF_DEVICE_CONTEXT_CLEANUP HcaEvtDeviceContextCleanup;\r
+\r
+EVT_WDF_DEVICE_D0_ENTRY HcaEvtDeviceD0Entry;\r
+EVT_WDF_DEVICE_D0_EXIT HcaEvtDeviceD0Exit;\r
+EVT_WDF_DEVICE_PREPARE_HARDWARE HcaEvtDevicePrepareHardware;\r
+EVT_WDF_DEVICE_RELEASE_HARDWARE HcaEvtDeviceReleaseHardware;\r
+\r
+EVT_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP HcaEvtDeviceSelfManagedIoCleanup;\r
+EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT HcaEvtDeviceSelfManagedIoInit;\r
+EVT_WDF_DEVICE_SELF_MANAGED_IO_SUSPEND HcaEvtDeviceSelfManagedIoSuspend;\r
+EVT_WDF_DEVICE_SELF_MANAGED_IO_RESTART HcaEvtDeviceSelfManagedIoRestart;\r
+\r
+EVT_WDF_DEVICE_SURPRISE_REMOVAL HcaEvtDeviceSurpriseRemoval;\r
+\r
+EVT_WDF_DEVICE_ARM_WAKE_FROM_S0 HcaEvtDeviceWakeArmS0;\r
+EVT_WDF_DEVICE_ARM_WAKE_FROM_SX HcaEvtDeviceWakeArmSx;\r
+EVT_WDF_DEVICE_DISARM_WAKE_FROM_S0 HcaEvtDeviceWakeDisarmS0;\r
+EVT_WDF_DEVICE_DISARM_WAKE_FROM_SX HcaEvtDeviceWakeDisarmSx;\r
+EVT_WDF_DEVICE_WAKE_FROM_S0_TRIGGERED HcaEvtDeviceWakeTriggeredS0;\r
+EVT_WDF_DEVICE_WAKE_FROM_SX_TRIGGERED HcaEvtDeviceWakeTriggeredSx;\r
+EVT_WDF_DEVICE_D0_ENTRY_POST_INTERRUPTS_ENABLED HcaEvtDeviceD0EntryPostInterruptsEnabled;\r
+EVT_WDF_DEVICE_D0_EXIT_PRE_INTERRUPTS_DISABLED HcaEvtDeviceD0ExitPreInterruptsDisabled;\r
+\r
+EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL HcaEvtIoDeviceControl;\r
+\r
+NTSTATUS\r
+HcaReturnResources (\r
+ IN OUT PFDO_DATA FdoData\r
+ );\r
+\r
+NTSTATUS\r
+HcaSetPowerPolicy(\r
+ IN PFDO_DATA FdoData\r
+ );\r
+\r
+NTSTATUS\r
+HcaQueuePassiveLevelCallback(\r
+ IN PFDO_DATA FdoData,\r
+ IN PFN_WDF_WORKITEM CallbackFunction,\r
+ IN PVOID Context1,\r
+ IN PVOID Context2\r
+ );\r
+\r
+BOOLEAN\r
+HcaReadRegistryValue(\r
+ __in PFDO_DATA FdoData,\r
+ __in PWCHAR Name,\r
+ __out PULONG Value\r
+ );\r
+\r
+BOOLEAN\r
+HcaWriteRegistryValue(\r
+ __in PFDO_DATA FdoData,\r
+ __in PWCHAR Name,\r
+ __in ULONG Value\r
+ );\r
+\r
+\r
+NTSTATUS\r
+HcaWmiRegistration(\r
+ WDFDEVICE hDevice\r
+);\r
+\r
+PCHAR\r
+DbgDevicePowerString(\r
+ IN WDF_POWER_DEVICE_STATE Type\r
+ );\r
+\r
+\r
+BOOLEAN\r
+HcaReadFdoRegistryKeyValue(\r
+ __in PWDFDEVICE_INIT DeviceInit,\r
+ __in PWCHAR Name,\r
+ __out PULONG Value\r
+ );\r
\r
#endif /* !defined( _HCA_DRIVER_H_ ) */\r
IN PDEVICE_OBJECT pPdo,\r
IN PDEVICE_OBJECT p_dev_obj )\r
{\r
- NTSTATUS status;\r
- DEVICE_OBJECT *pNextDevObj;\r
- hca_dev_ext_t *p_ext;\r
+ NTSTATUS status=STATUS_SUCCESS;\r
+ DEVICE_OBJECT *pNextDevObj;\r
+ hca_dev_ext_t *p_ext;\r
\r
- HCA_ENTER(HCA_DBG_PNP);\r
+ UNREFERENCED_PARAMETER(pDriverObj);\r
\r
+ HCA_ENTER(HCA_DBG_PNP);\r
#if 0\r
/*\r
* Create the device so that we have a device extension to store stuff in.\r
}\r
#endif\r
\r
+// XXX fixup pNextDevObj... STAN\r
+ pNextDevObj = NULL;\r
+\r
/* Inititalize the complib extension. */\r
- cl_init_pnp_po_ext( p_dev_obj, pNextDevObj, pPdo, 0,\r
- &vfptrHcaPnp, NULL );\r
+ cl_init_pnp_po_ext( p_dev_obj, pNextDevObj, pPdo, 0, &vfptrHcaPnp, NULL );\r
\r
p_ext->state = HCA_ADDED;\r
\r
HCA_EXIT(HCA_DBG_PNP);\r
+\r
return status;\r
}\r
\r
NTSTATUS
hca_add_device(
IN PDRIVER_OBJECT pDriverObj,
- IN PDEVICE_OBJECT pPdo );
+ IN PDEVICE_OBJECT pPdo,
+ IN PDEVICE_OBJECT p_dev_obj );
#endif
_LNG=$(LANGUAGE)\r
-_INX=..\r
+_INX=.\r
STAMP=stampinf -f $@ -a $(_BUILDARCH) -k $(KMDF_VERSION_MAJOR).$(KMDF_VERSION_MINOR)\r
\r
\r
-$(OBJ_PATH)\$(O)\$(INF_NAME).inf: $(INF_NAME).inx \r
- copy $(_INX)\$(@B).inx $@\r
+$(OBJ_PATH)\$(O)\$(INF_NAME).inf: $(_INX)\$(INF_NAME).inx \r
+ copy $(_INX)\$(INF_NAME).inx $@\r
$(STAMP)\r
\r
-mofcomp: $(OBJ_PATH)\$(O)\mthca.bmf\r
\r
$(OBJ_PATH)\$(O)\mthca.bmf: mthca.mof\r
- mofcomp -B:$(OBJ_PATH)\$(O)\mthca.bmf mthca.mof\r
- wmimofck $(OBJ_PATH)\$(O)\mthca.bmf\r
-\r
-\r
-\r
-\r
+ mofcomp -B:$@ mthca.mof\r
+ wmimofck $@\r
+ wmimofck -m -h$(OBJ_PATH)\$O\mthcaMof.h -w$(OBJ_PATH)\$(O)\htm $@\r
\r
\r
char buf[IB_DEVICE_NAME_MAX];
struct ib_device *device;
int i;
+ NTSTATUS status;
inuse = (long *) get_zeroed_page(GFP_KERNEL);
if (!inuse)
continue;
if (i < 0 || i >= PAGE_SIZE * 8)
continue;
- snprintf(buf, sizeof(buf)-1, name, i);
+ status = RtlStringCchPrintfA( buf, sizeof(buf)-1, name, i );
buf[sizeof(buf)-1] = '\0';
if (!strncmp(buf, device->name, IB_DEVICE_NAME_MAX))
set_bit(i, inuse);
i = find_first_zero_bit((const unsigned long *)inuse, PAGE_SIZE * 8);
free_page(inuse);
- snprintf(buf, sizeof(buf)-1, name, i);
+ status = RtlStringCchPrintfA( buf, sizeof(buf)-1, name, i );
buf[sizeof(buf)-1] = '\0';
if (__ib_device_get_by_name(buf))
\r
[Dynamic, Provider("WMIProv"),\r
WMI,\r
- Description("PCIDRV Device Information"),\r
- guid("{20E35E40-7179-4f89-A28C-12ED5A3CAAA5}"),\r
+ Description("mthca driver information"),\r
+ guid("{BBA21300-6DD3-11d2-B844-00C04FAD5171}"),\r
locale("MS\\0x409")]\r
-class PciDeviceInformation\r
+class MthcaDeviceInformation\r
{\r
[key, read]\r
- string InstanceName;\r
- [read] boolean Active;\r
+ string InstanceName;\r
+\r
+ [read]\r
+ boolean Active;\r
+\r
+ [WmiDataId(1),\r
+ read,\r
+ Description("Number of errors that occurred on this device")]\r
+ uint32 ErrorCount;\r
+\r
+ [WmiDataId(2),\r
+ read,\r
+ write,\r
+ Description("DebugPrintLevel property indicates the debug output level")]\r
+ uint32 DebugPrintLevel;\r
+\r
+ [WmiDataId(3),\r
+ read,\r
+ write,\r
+ Description("DebugPrintFlags property indicates the debug output level")]\r
+ uint32 DebugPrintFlags;\r
+\r
+ [WmiDataId(4),\r
+ read,\r
+ Description("The HCA Model Name.")]\r
+ string ModelName;\r
+\r
+};\r
+\r
+\r
+[WMI, Dynamic, Provider("WMIProv"),\r
+ guid("{01CDAFF1-C901-45b4-B359-B5542725E29C}"),\r
+ locale("MS\\0x409"),\r
+ WmiExpense(1),\r
+ Description("Notify HCA Arrival")]\r
+class MthcaNotifyDeviceArrival : WMIEvent\r
+{\r
+ [key, read]\r
+ string InstanceName;\r
+\r
+ [read]\r
+ boolean Active;\r
+\r
+ [read,\r
+ Description("Device Model Name"),\r
+ WmiDataId(1)]\r
+ string ModelName;\r
+};\r
+\r
+\r
+[WMI,\r
+ Dynamic,\r
+ Provider("WmiProv"),\r
+ Locale("MS\\0x409"),\r
+ Description("WMI method") : amended,\r
+ guid("CAAE7D9F-ACF7-4737-A4E9-01C29D3FE194")]\r
+class MthcaControl\r
+{\r
+ [key, read]\r
+ string InstanceName;\r
+\r
+ [read]\r
+ boolean Active;\r
\r
[WmiDataId(1),\r
read,\r
write,\r
- Description("Current Mac Address of the NIC.")]\r
- uint64 MacAddress;\r
+ Description("MTHCA Control Property")]\r
+ uint32 ControlValue;\r
+\r
+ [Implemented, WmiMethodId(1)]\r
+ void MthcaControl1([in] uint32 InData,\r
+ [out] uint32 OutData);\r
+\r
+ [Implemented, WmiMethodId(2)]\r
+ void MthcaControl2([in] uint32 InData1,\r
+ [in] uint32 InData2,\r
+ [out] uint32 OutData);\r
+\r
+ [Implemented, WmiMethodId(3)]\r
+ void MthcaControl3([in] uint32 InData1,\r
+ [in] uint32 InData2,\r
+ [out] uint32 OutData1,\r
+ [out] uint32 OutData2);\r
+\r
};\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id$\r
+ */\r
+\r
+/*++\r
+Copyright (c) Microsoft Corporation. All rights reserved.\r
+\r
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY\r
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR\r
+ PURPOSE.\r
+\r
+Module Name:\r
+\r
+ PciDrv.c\r
+\r
+Abstract:\r
+\r
+ The WDM interfaces in this sample are derrived from the PciDrv KMDF samples\r
+ function driver (e100 NIC). mthca interfaces have been merged.\r
+ Goal is to provide a skeleton KMDF wrapper around the existing mthca driver\r
+ as a starting point in the migrate to a full KMDF driver enviroment.\r
+\r
+Environment:\r
+\r
+ Kernel mode\r
+\r
+--*/\r
+\r
+#include "hca_driver.h"\r
+#include "pcidrv.h"\r
+#include "trace.h"\r
+\r
+#include <ntstrsafe.h>\r
+#include <ntintsafe.h>\r
+#include <initguid.h>\r
+\r
+#include "public.h"\r
+\r
+DRIVER_INITIALIZE DriverEntry;\r
+\r
+NTSTATUS\r
+HcaEntry(\r
+ IN PDRIVER_OBJECT p_driver_obj,\r
+ IN PUNICODE_STRING p_registry_path );\r
+\r
+NTSTATUS HcaAllocateSoftwareResources(PFDO_DATA fdoData);\r
+NTSTATUS HcaFreeSoftwareResources(PFDO_DATA fdoData);\r
+VOID HcaEvtDeviceSelfManagedIoCleanup( IN WDFDEVICE Device );\r
+NTSTATUS HcaEvtDeviceSelfManagedIoSuspend( IN WDFDEVICE Device );\r
+\r
+#if defined(EVENT_TRACING)\r
+//\r
+// The trace message header (.tmh) file must be included in a source file\r
+// before any WPP macro calls and after defining a WPP_CONTROL_GUIDS\r
+// macro (defined in toaster.h). During the compilation, WPP scans the source\r
+// files for DoTraceMessage() calls and builds a .tmh file which stores a unique\r
+// data GUID for each message, the text resource string for each message,\r
+// and the data types of the variables passed in for each message. This file\r
+// is automatically generated and used during post-processing.\r
+//\r
+#include "pcidrv.tmh"\r
+#endif\r
+\r
+#ifdef ALLOC_PRAGMA\r
+#pragma alloc_text (INIT, DriverEntry)\r
+#pragma alloc_text (PAGE, HcaEvtDeviceAdd)\r
+#pragma alloc_text (PAGE, HcaEvtDeviceContextCleanup)\r
+#pragma alloc_text (PAGE, HcaEvtDevicePrepareHardware)\r
+#pragma alloc_text (PAGE, HcaEvtDeviceReleaseHardware)\r
+#pragma alloc_text (PAGE, HcaReadRegistryValue)\r
+#pragma alloc_text (PAGE, HcaWriteRegistryValue)\r
+#pragma alloc_text (PAGE, HcaEvtDriverContextCleanup)\r
+#pragma alloc_text (PAGE, HcaEvtDeviceSelfManagedIoCleanup)\r
+#pragma alloc_text (PAGE, HcaEvtDeviceSelfManagedIoSuspend)\r
+#pragma alloc_text (PAGE, HcaEvtDeviceWakeArmS0)\r
+#pragma alloc_text (PAGE, HcaEvtDeviceWakeDisarmS0)\r
+#pragma alloc_text (PAGE, HcaEvtDeviceWakeTriggeredS0)\r
+#pragma alloc_text (PAGE, HcaEvtDeviceWakeArmSx)\r
+#pragma alloc_text (PAGE, HcaSetPowerPolicy)\r
+#pragma alloc_text (PAGE, HcaReadFdoRegistryKeyValue)\r
+#endif\r
+\r
+\r
+#define PARAMATER_NAME_LEN 80\r
+\r
+__inline\r
+BOOLEAN\r
+IsPoMgmtSupported(\r
+ IN PFDO_DATA FdoData\r
+ )\r
+{\r
+#if 1\r
+ return TRUE;\r
+#else\r
+ if (FdoData->RevsionID >= E100_82559_A_STEP\r
+ /*&& FdoData->RevsionID <= E100_82559_C_STEP*/)\r
+ {\r
+ return TRUE;\r
+ }\r
+ else\r
+ {\r
+ return FALSE;\r
+ }\r
+#endif\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Installable driver initialization entry point.\r
+ This entry point is called directly by the I/O system.\r
+\r
+Arguments:\r
+\r
+ DriverObject - pointer to the driver object\r
+\r
+ RegistryPath - pointer to a unicode string representing the path,\r
+ to driver-specific key in the registry.\r
+\r
+Return Value:\r
+\r
+ STATUS_SUCCESS if successful,\r
+ STATUS_UNSUCCESSFUL otherwise.\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+DriverEntry (\r
+ IN PDRIVER_OBJECT DriverObject,\r
+ IN PUNICODE_STRING RegistryPath )\r
+{\r
+ NTSTATUS status = STATUS_SUCCESS;\r
+ WDF_DRIVER_CONFIG config;\r
+ WDF_OBJECT_ATTRIBUTES attrib;\r
+ WDFDRIVER driver;\r
+// PDRIVER_CONTEXT driverContext;\r
+\r
+ //\r
+ // Initialize WPP Tracing\r
+ //\r
+#if defined(EVENT_TRACING)\r
+ WPP_INIT_TRACING( DriverObject, RegistryPath );\r
+#endif\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,\r
+ "mthca - KM Driver Framework Edition \n");\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,\r
+ "Built %s %s\n", __DATE__, __TIME__);\r
+\r
+// WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attrib, DRIVER_CONTEXT);\r
+\r
+ //\r
+ // Register a cleanup callback so that we can call WPP_CLEANUP when\r
+ // the framework driver object is deleted during driver unload.\r
+ //\r
+ attrib.EvtCleanupCallback = HcaEvtDriverContextCleanup;\r
+\r
+ //\r
+ // Initialize the Driver Config structure..\r
+ //\r
+ WDF_DRIVER_CONFIG_INIT(&config, HcaEvtDeviceAdd);\r
+\r
+ //\r
+ // Create a WDFDRIVER object.\r
+ //\r
+ status = WdfDriverCreate(DriverObject,\r
+ RegistryPath,\r
+ &attrib,\r
+ &config,\r
+ &driver);\r
+\r
+ if (!NT_SUCCESS(status)) {\r
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,\r
+ "WdfDriverCreate failed with status %!STATUS!\n", status);\r
+ //\r
+ // Cleanup tracing here because DriverContextCleanup will not be called\r
+ // as we have failed to create WDFDRIVER object itself.\r
+ // Please note that if your return failure from DriverEntry after the\r
+ // WDFDRIVER object is created successfully, you don't have to\r
+ // call WPP cleanup because in those cases DriverContextCleanup\r
+ // will be executed when the framework deletes the DriverObject.\r
+ //\r
+#if defined(EVENT_TRACING)\r
+ WPP_CLEANUP(DriverObject);\r
+#endif\r
+ return status;\r
+ }\r
+\r
+#if 0\r
+ driverContext = GetDriverContext(driver);\r
+ //\r
+ // Create a driver wide lookside list used for allocating memory for the\r
+ // MP_RFD structure for all device instances (if there are multiple present).\r
+ //\r
+ status = WdfLookasideListCreate(WDF_NO_OBJECT_ATTRIBUTES, // LookAsideAttributes\r
+ sizeof(MP_RFD),\r
+ NonPagedPool,\r
+ WDF_NO_OBJECT_ATTRIBUTES, // MemoryAttributes\r
+ PCIDRV_POOL_TAG,\r
+ &driverContext->RecvLookaside\r
+ );\r
+ if (!NT_SUCCESS(status)) {\r
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,\r
+ "Couldn't allocate lookaside list status %!STATUS!\n", status);\r
+ return status;\r
+ }\r
+#endif\r
+ if (!NT_SUCCESS(status))\r
+ return status;\r
+\r
+ return HcaEntry( DriverObject, RegistryPath );\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+\r
+ EvtDeviceAdd is called by the framework in response to AddDevice\r
+ call from the PnP manager.\r
+\r
+Arguments:\r
+\r
+ Driver - Handle to a framework driver object created in DriverEntry\r
+\r
+ DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.\r
+\r
+Return Value:\r
+\r
+ NTSTATUS\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+HcaEvtDeviceAdd(\r
+ IN WDFDRIVER Driver,\r
+ IN PWDFDEVICE_INIT DeviceInit )\r
+{\r
+ NTSTATUS status = STATUS_SUCCESS;\r
+ WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;\r
+ WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks;\r
+ WDF_OBJECT_ATTRIBUTES fdoAttributes;\r
+ WDFDEVICE device;\r
+ PFDO_DATA fdoData = NULL;\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "-->HcaEvtDeviceAdd routine. Driver: 0x%p\n", Driver);\r
+\r
+ //\r
+ // I/O type is Buffered by default. If required to use something else,\r
+ // call WdfDeviceInitSetIoType with the appropriate type.\r
+ //\r
+ WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);\r
+\r
+ //\r
+ // Zero out the PnpPowerCallbacks structure.\r
+ //\r
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);\r
+\r
+ //\r
+ // Set Callbacks for any of the functions we are interested in.\r
+ // If no callback is set, Framework will take the default action\r
+ // by itself. This sample provides many of the possible callbacks,\r
+ // mostly because it's a fairly complex sample that drives full-featured\r
+ // hardware. Drivers derived from this sample will often be able to\r
+ // provide only some of these.\r
+ //\r
+\r
+ //\r
+ // These callback is invoked to tear down all the driver-managed state\r
+ // that is set up in this function. Many times, this callback won't do\r
+ // much of anything, since many of the things that are set up here will\r
+ // have their lifetimes automatically managed by the Framework.\r
+ //\r
+\r
+ //\r
+ // These two callbacks set up and tear down hardware state,\r
+ // specifically that which only has to be done once.\r
+ //\r
+\r
+ pnpPowerCallbacks.EvtDevicePrepareHardware = HcaEvtDevicePrepareHardware;\r
+ pnpPowerCallbacks.EvtDeviceReleaseHardware = HcaEvtDeviceReleaseHardware;\r
+\r
+ //\r
+ // These two callbacks set up and tear down hardware state that must be\r
+ // done every time the device moves in and out of the D0-working state.\r
+ //\r
+\r
+ pnpPowerCallbacks.EvtDeviceD0Entry = HcaEvtDeviceD0Entry;\r
+ pnpPowerCallbacks.EvtDeviceD0Exit = HcaEvtDeviceD0Exit;\r
+\r
+ //\r
+ // These next two callbacks are for doing work at PASSIVE_LEVEL (low IRQL)\r
+ // after all the interrupts are connected and before they are disconnected.\r
+ //\r
+ // Some drivers need to do device initialization and tear-down while the\r
+ // interrupt is connected. (This is a problem for these devices, since\r
+ // it opens them up to taking interrupts before they are actually ready\r
+ // to handle them, or to taking them after they have torn down too much\r
+ // to be able to handle them.) While this hardware design pattern is to\r
+ // be discouraged, it is possible to handle it by doing device init and\r
+ // tear down in these routines rather than in EvtDeviceD0Entry and\r
+ // EvtDeviceD0Exit.\r
+ //\r
+ // In this sample these callbacks don't do anything.\r
+ //\r
+\r
+ pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled =\r
+ HcaEvtDeviceD0EntryPostInterruptsEnabled;\r
+ pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled =\r
+ HcaEvtDeviceD0ExitPreInterruptsDisabled;\r
+\r
+ //\r
+ // This next group of five callbacks allow a driver to become involved in\r
+ // starting and stopping operations within a driver as the driver moves\r
+ // through various PnP/Power states. These functions are not necessary\r
+ // if the Framework is managing all the device's queues and there is no\r
+ // activity going on that isn't queue-based. This sample provides these\r
+ // callbacks because it uses watchdog timer to monitor whether the device\r
+ // is working or not and it needs to start and stop the timer when the\r
+ // device is started or removed. It cannot start and stop the timers in the\r
+ // D0Entry and D0Exit callbacks because if the device is surprise-removed,\r
+ // D0Exit will not be called.\r
+ //\r
+ pnpPowerCallbacks.EvtDeviceSelfManagedIoInit =\r
+ HcaEvtDeviceSelfManagedIoInit;\r
+ pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup =\r
+ HcaEvtDeviceSelfManagedIoCleanup;\r
+ pnpPowerCallbacks.EvtDeviceSelfManagedIoSuspend =\r
+ HcaEvtDeviceSelfManagedIoSuspend;\r
+ pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart =\r
+ HcaEvtDeviceSelfManagedIoRestart;\r
+\r
+ //\r
+ // Register the PnP and power callbacks. Power policy related callbacks will\r
+ // be registered later.\r
+ //\r
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);\r
+\r
+ //\r
+ // Init the power policy callbacks\r
+ //\r
+ WDF_POWER_POLICY_EVENT_CALLBACKS_INIT(&powerPolicyCallbacks);\r
+\r
+ //\r
+ // This group of three callbacks allows this sample driver to manage\r
+ // arming the device for wake from the S0 state. Networking devices can\r
+ // optionally be put into a low-power state when there is no networking\r
+ // cable plugged into them. This sample implements this feature.\r
+ //\r
+ powerPolicyCallbacks.EvtDeviceArmWakeFromS0 = HcaEvtDeviceWakeArmS0;\r
+ powerPolicyCallbacks.EvtDeviceDisarmWakeFromS0 = HcaEvtDeviceWakeDisarmS0;\r
+ powerPolicyCallbacks.EvtDeviceWakeFromS0Triggered =\r
+ HcaEvtDeviceWakeTriggeredS0;\r
+\r
+ //\r
+ // This group of three callbacks allows the device to be armed for wake\r
+ // from Sx (S1, S2, S3 or S4.) Networking devices can optionally be put\r
+ // into a state where a packet sent to them will cause the device's wake\r
+ // signal to be triggered, which causes the machine to wake, moving back\r
+ // into the S0 state.\r
+ //\r
+\r
+ powerPolicyCallbacks.EvtDeviceArmWakeFromSx = HcaEvtDeviceWakeArmSx;\r
+ powerPolicyCallbacks.EvtDeviceDisarmWakeFromSx = HcaEvtDeviceWakeDisarmSx;\r
+ powerPolicyCallbacks.EvtDeviceWakeFromSxTriggered =\r
+ HcaEvtDeviceWakeTriggeredSx;\r
+\r
+ WdfDeviceInitSetDeviceType( DeviceInit,\r
+ FILE_DEVICE_INFINIBAND|FILE_DEVICE_SECURE_OPEN );\r
+\r
+ WdfDeviceInitSetExclusive(DeviceInit, TRUE);\r
+ //\r
+ // Register the power policy callbacks.\r
+ //\r
+ WdfDeviceInitSetPowerPolicyEventCallbacks(DeviceInit,&powerPolicyCallbacks);\r
+\r
+ // Since we are the function driver, we are now the power policy owner\r
+ // for the device according to the default framework rule. We will register\r
+ // our power policy callbacks after finding the wakeup capability of the\r
+ // device.\r
+\r
+\r
+ // Specify the context type and size for the device we are about to create.\r
+\r
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DATA);\r
+\r
+\r
+ // ContextCleanup will be called by the framework when it deletes the\r
+ // device. So you can defer freeing any resources allocated to Cleanup\r
+ // callback in the event AddDevice returns any error after the device is\r
+ // created.\r
+\r
+ fdoAttributes.EvtCleanupCallback = HcaEvtDeviceContextCleanup;\r
+\r
+ status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);\r
+\r
+ if ( !NT_SUCCESS(status)) {\r
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
+ "WdfDeviceInitialize failed %!STATUS!\n", status);\r
+ return status;\r
+ }\r
+\r
+ //\r
+ // Device creation is complete.\r
+ // Get the DeviceExtension and initialize it.\r
+ //\r
+ fdoData = FdoGetData(device);\r
+ fdoData->WdfDevice = device;\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n",\r
+ WdfDeviceWdmGetPhysicalDevice (device),\r
+ WdfDeviceWdmGetDeviceObject (device),\r
+ WdfDeviceWdmGetAttachedDevice(device),\r
+ fdoData);\r
+\r
+ status = hca_add_device( WdfDriverWdmGetDriverObject(device), // DRIVER OBJ\r
+ WdfDeviceWdmGetPhysicalDevice(device), // PDO\r
+ WdfDeviceWdmGetAttachedDevice(device) );// DEV OBJ\r
+ //\r
+ // Initialize the device extension and allocate all the software resources\r
+ //\r
+ status = HcaAllocateSoftwareResources(fdoData);\r
+ if (!NT_SUCCESS (status)){\r
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
+ "HcaAllocateSoftwareResources failed: %!STATUS!\n",\r
+ status);\r
+ return status;\r
+ }\r
+\r
+ //\r
+ // If we own the power policy and if our device supports wait-wake then we\r
+ // will set our power-policy and update S0-Idle policy.\r
+ //\r
+ if(IsPoMgmtSupported(fdoData) )\r
+ {\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "Device has wait-wake capability\n");\r
+ status = HcaSetPowerPolicy(fdoData);\r
+ if (!NT_SUCCESS (status)) {\r
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
+ "HcaSetPowerPolicy failed %!STATUS!\n", status);\r
+ return status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Tell the Framework that this device will need an interface so that\r
+ // application can interact with it.\r
+ //\r
+ status = WdfDeviceCreateDeviceInterface(\r
+ device,\r
+ (LPGUID) &GUID_DEVINTERFACE_RDMA_IO,\r
+ NULL );\r
+\r
+ if (!NT_SUCCESS (status)) {\r
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
+ "WdfDeviceCreateDeviceInterface failed %!STATUS!\n",status);\r
+ return status;\r
+ }\r
+\r
+ status = HcaWmiRegistration(device);\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- HcaEvtDeviceAdd \n");\r
+\r
+ return status;\r
+}\r
+\r
+VOID\r
+HcaEvtDeviceContextCleanup (\r
+ WDFDEVICE Device\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceContextCleanup event callback cleans up anything done in\r
+ EvtDeviceAdd, except those things that are automatically cleaned\r
+ up by the Framework.\r
+\r
+ In the case of this sample, everything is automatically handled. In a\r
+ driver derived from this sample, it's quite likely that this function could\r
+ be deleted.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a framework device object.\r
+\r
+Return Value:\r
+\r
+ VOID\r
+\r
+--*/\r
+{\r
+ PFDO_DATA fdoData = NULL;\r
+ NTSTATUS status;\r
+\r
+ PAGED_CODE();\r
+\r
+ fdoData = FdoGetData(Device);\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceContextCleanup\n");\r
+\r
+ status = HcaFreeSoftwareResources(fdoData);\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceContextCleanup\n");\r
+\r
+}\r
+\r
+NTSTATUS\r
+HcaEvtDevicePrepareHardware (\r
+ WDFDEVICE Device,\r
+ WDFCMRESLIST Resources,\r
+ WDFCMRESLIST ResourcesTranslated\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceStart event callback performs operations that are necessary\r
+ to make the driver's device operational. The framework calls the driver's\r
+ EvtDeviceStart callback when the PnP manager sends an IRP_MN_START_DEVICE\r
+ request to the driver stack.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a framework device object.\r
+\r
+ Resources - Handle to a collection of framework resource objects.\r
+ This collection identifies the raw (bus-relative) hardware\r
+ resources that have been assigned to the device.\r
+\r
+ ResourcesTranslated - Handle to a collection of framework resource objects.\r
+ This collection identifies the translated (system-physical)\r
+ hardware resources that have been assigned to the device.\r
+ The resources appear from the CPU's point of view.\r
+ Use this list of resources to map I/O space and\r
+ device-accessible memory into virtual address space\r
+\r
+Return Value:\r
+\r
+ WDF status code\r
+\r
+--*/\r
+{\r
+ NTSTATUS status = STATUS_SUCCESS;\r
+ PFDO_DATA fdoData = NULL;\r
+\r
+ UNREFERENCED_PARAMETER(Resources);\r
+ UNREFERENCED_PARAMETER(ResourcesTranslated);\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDevicePrepareHardware\n");\r
+\r
+ fdoData = FdoGetData(Device);\r
+\r
+#if 0\r
+ status = NICMapHWResources(fdoData, ResourcesTranslated);\r
+ if (!NT_SUCCESS (status)){\r
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
+ "NICMapHWResources failed: %!STATUS!\n", status);\r
+ return status;\r
+ }\r
+#endif\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDevicePrepareHardware\n");\r
+\r
+ return status;\r
+\r
+}\r
+\r
+NTSTATUS\r
+HcaEvtDeviceReleaseHardware(\r
+ IN WDFDEVICE Device,\r
+ IN WDFCMRESLIST ResourcesTranslated\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceReleaseHardware is called by the framework whenever the PnP manager\r
+ is revoking ownership of our resources. This may be in response to either\r
+ IRP_MN_STOP_DEVICE or IRP_MN_REMOVE_DEVICE. The callback is made before\r
+ passing down the IRP to the lower driver.\r
+\r
+ In this callback, do anything necessary to free those resources.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a framework device object.\r
+\r
+ ResourcesTranslated - Handle to a collection of framework resource objects.\r
+ This collection identifies the translated (system-physical)\r
+ hardware resources that have been assigned to the device.\r
+ The resources appear from the CPU's point of view.\r
+ Use this list of resources to map I/O space and\r
+ device-accessible memory into virtual address space\r
+\r
+Return Value:\r
+\r
+ NTSTATUS - Failures will be logged, but not acted on.\r
+\r
+--*/\r
+{\r
+ PFDO_DATA fdoData = NULL;\r
+\r
+ UNREFERENCED_PARAMETER(ResourcesTranslated);\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceReleaseHardware\n");\r
+\r
+ fdoData = FdoGetData(Device);\r
+\r
+#if 0\r
+ //\r
+ // Unmap any I/O ports. Disconnecting from the interrupt will be done\r
+ // automatically by the framework.\r
+ //\r
+ NICUnmapHWResources(fdoData);\r
+#endif\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceReleaseHardware\n");\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+NTSTATUS\r
+HcaEvtDeviceD0Entry(\r
+ IN WDFDEVICE Device,\r
+ IN WDF_POWER_DEVICE_STATE PreviousState\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceD0Entry event callback must perform any operations that are\r
+ necessary before the specified device is used. It will be called every\r
+ time the hardware needs to be (re-)initialized. This includes after\r
+ IRP_MN_START_DEVICE, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE,\r
+ IRP_MN_SET_POWER-D0.\r
+\r
+ This function is not marked pageable because this function is in the\r
+ device power up path. When a function is marked pagable and the code\r
+ section is paged out, it will generate a page fault which could impact\r
+ the fast resume behavior because the client driver will have to wait\r
+ until the system drivers can service this page fault.\r
+\r
+ This function runs at PASSIVE_LEVEL, even though it is not paged. A\r
+ driver can optionally make this function pageable if DO_POWER_PAGABLE\r
+ is set. Even if DO_POWER_PAGABLE isn't set, this function still runs\r
+ at PASSIVE_LEVEL. In this case, though, the function absolutely must\r
+ not do anything that will cause a page fault.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a framework device object.\r
+\r
+ PreviousState - Device power state which the device was in most recently.\r
+ If the device is being newly started, this will be\r
+ PowerDeviceUnspecified.\r
+\r
+Return Value:\r
+\r
+ NTSTATUS\r
+\r
+--*/\r
+{\r
+ PFDO_DATA fdoData;\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,\r
+ "-->HcaEvtDeviceD0Entry - coming from %s\n",\r
+ DbgDevicePowerString(PreviousState));\r
+\r
+ fdoData = FdoGetData(Device);\r
+\r
+ ASSERT(PowerDeviceD0 != PreviousState);\r
+\r
+ fdoData->DevicePowerState = PowerDeviceD0;\r
+\r
+ if(IsPoMgmtSupported(fdoData)){\r
+\r
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_POWER,\r
+ "Entering fully on state\n");\r
+#ifdef XXX\r
+ MPSetPowerD0 (fdoData);\r
+#endif\r
+ }\r
+\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--HcaEvtDeviceD0Entry\n");\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+NTSTATUS\r
+HcaEvtDeviceD0Exit(\r
+ IN WDFDEVICE Device,\r
+ IN WDF_POWER_DEVICE_STATE TargetState\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This routine undoes anything done in EvtDeviceD0Entry. It is called\r
+ whenever the device leaves the D0 state, which happens when the device is\r
+ stopped, when it is removed, and when it is powered off.\r
+\r
+ The device is still in D0 when this callback is invoked, which means that\r
+ the driver can still touch hardware in this routine.\r
+\r
+ Note that interrupts have already been disabled by the time that this\r
+ callback is invoked.\r
+\r
+ EvtDeviceD0Exit event callback must perform any operations that are\r
+ necessary before the specified device is moved out of the D0 state. If the\r
+ driver needs to save hardware state before the device is powered down, then\r
+ that should be done here.\r
+\r
+ This function runs at PASSIVE_LEVEL, though it is generally not paged. A\r
+ driver can optionally make this function pageable if DO_POWER_PAGABLE is set.\r
+\r
+ Even if DO_POWER_PAGABLE isn't set, this function still runs at\r
+ PASSIVE_LEVEL. In this case, though, the function absolutely must not do\r
+ anything that will cause a page fault.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a framework device object.\r
+\r
+ TargetState - Device power state which the device will be put in once this\r
+ callback is complete.\r
+\r
+Return Value:\r
+\r
+ Success implies that the device can be used. Failure will result in the\r
+ device stack being torn down.\r
+\r
+--*/\r
+{\r
+ PFDO_DATA fdoData;\r
+\r
+ UNREFERENCED_PARAMETER(Device);\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,\r
+ "-->HcaEvtDeviceD0Exit - moving to %s\n",\r
+ DbgDevicePowerString(TargetState));\r
+\r
+ fdoData = FdoGetData(Device);\r
+\r
+ fdoData->DevicePowerState = TargetState;\r
+\r
+ switch (TargetState) {\r
+ case WdfPowerDeviceD1:\r
+ case WdfPowerDeviceD2:\r
+ case WdfPowerDeviceD3:\r
+\r
+ if(IsPoMgmtSupported(fdoData)){\r
+\r
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_POWER,\r
+ "Entering a deeper sleep state\n");\r
+#ifdef XXX\r
+ MPSetPowerLow (fdoData, TargetState);\r
+#endif\r
+ }\r
+ break;\r
+\r
+ case WdfPowerDevicePrepareForHibernation:\r
+\r
+ //\r
+ // Fill in any code to save hardware state here. Do not put in any\r
+ // code to shut the device off. If this device cannot support being\r
+ // in the paging path (or being a parent or grandparent of a paging\r
+ // path device) then this whole case can be deleted.\r
+ //\r
+ ASSERT(FALSE); // This driver shouldn't get this.\r
+ break;\r
+\r
+ case WdfPowerDeviceD3Final:\r
+ //\r
+ // Reset and put the device into a known initial state we're shutting\r
+ // down for the last time.\r
+ //\r
+#if 0\r
+ NICShutdown(fdoData);\r
+#endif\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--HcaEvtDeviceD0Exit\n");\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+NTSTATUS\r
+HcaEvtDeviceSelfManagedIoInit(\r
+ IN WDFDEVICE Device\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ HcaEvtDeviceSelfManagedIoInit is called by the Framework when the device\r
+ enters the D0 state. Its job is to start any I/O-related actions that the\r
+ Framework isn't managing. This might include releasing queues that are not\r
+ power-managed, that is, the Framework is not automatically holding and releasing\r
+ them across PnP/Power transitions. (The default behavior for WDFQUEUE is\r
+ auto-managed, so most queues don't need to be dealt with here.) This might\r
+ also include setting up non-queue-based actions.\r
+\r
+ If you allow the Framework to manage most or all of your queues, then when\r
+ you build a driver from this sample, you can probably delete this function.\r
+\r
+ In this driver, the SelfManagedIo callbacks are used to implement a watchdog timer.\r
+\r
+ This function is not marked pagable because this function is in the\r
+ device power up path. When a function is marked pagable and the code\r
+ section is paged out, it will generate a page fault which could impact\r
+ the fast resume behavior because the client driver will have to wait\r
+ until the system drivers can service this page fault.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a framework device object.\r
+\r
+Return Value:\r
+\r
+ NTSTATUS - Failures will result in the device stack being torn down.\r
+\r
+--*/\r
+{\r
+ PFDO_DATA fdoData = NULL;\r
+ NTSTATUS status;\r
+// WDF_TIMER_CONFIG wdfTimerConfig;\r
+// WDF_OBJECT_ATTRIBUTES timerAttributes;\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceSelfManagedIoInit\n");\r
+\r
+ fdoData = FdoGetData(Device);\r
+\r
+#if 0\r
+ // To minimize init-time, create a timer DPC to do link detection.\r
+ // This DPC will also be used to check for hardware hang.\r
+ //\r
+ WDF_TIMER_CONFIG_INIT(&wdfTimerConfig, NICWatchDogEvtTimerFunc);\r
+\r
+ WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes);\r
+ timerAttributes.ParentObject = fdoData->WdfDevice;\r
+\r
+ status = WdfTimerCreate(\r
+ &wdfTimerConfig,\r
+ &timerAttributes,\r
+ &fdoData->WatchDogTimer\r
+ );\r
+\r
+ if(!NT_SUCCESS(status) ) {\r
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
+ "Error: WdfTimerCreate create failed 0x%x\n", status);\r
+ return status;\r
+ }\r
+\r
+ NICStartWatchDogTimer(fdoData);\r
+#endif\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceSelfManagedIoInit\n");\r
+\r
+ return status;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceSelfManagedIoSuspend is called by the Framework before the device\r
+ leaves the D0 state. Its job is to stop any I/O-related actions that the\r
+ Framework isn't managing, and which cannot be handled when the device\r
+ hardware isn't available. In general, this means reversing anything that\r
+ was done in EvtDeviceSelfManagedIoStart.\r
+\r
+ If you allow the Framework to manage most or all of your queues, then when\r
+ you build a driver from this sample, you can probably delete this function.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a framework device object.\r
+\r
+Return Value:\r
+\r
+ NTSTATUS - Failures will result in the device stack being torn down.\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+HcaEvtDeviceSelfManagedIoSuspend( IN WDFDEVICE Device )\r
+{\r
+ PFDO_DATA fdoData = NULL;\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceSelfManagedIoSuspend\n");\r
+\r
+ fdoData = FdoGetData(Device);\r
+\r
+#if 0\r
+ //\r
+ // Stop the watchdog timer and wait for DPC to run to completion if\r
+ // it's already fired.\r
+ //\r
+ WdfTimerStop(fdoData->WatchDogTimer, TRUE);\r
+#endif\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceSelfManagedIoSuspend\n");\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+NTSTATUS\r
+HcaEvtDeviceSelfManagedIoRestart(\r
+ IN WDFDEVICE Device\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceSelfManagedIoRestart is called by the Framework before the device\r
+ is restarted for one of the following reasons:\r
+ a) the PnP resources were rebalanced (framework received\r
+ query-stop and stop IRPS )\r
+ b) the device resumed from a low power state to D0.\r
+\r
+ This function is not marked pagable because this function is in the\r
+ device power up path. When a function is marked pagable and the code\r
+ section is paged out, it will generate a page fault which could impact\r
+ the fast resume behavior because the client driver will have to wait\r
+ until the system drivers can service this page fault.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a framework device object.\r
+\r
+Return Value:\r
+\r
+ NTSTATUS - Failure will cause the device stack to be torn down.\r
+\r
+--*/\r
+{\r
+ PFDO_DATA fdoData;\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceSelfManagedIoRestart\n");\r
+\r
+ fdoData = FdoGetData(Device);\r
+\r
+ //\r
+ // Restart the watchdog timer.\r
+ //\r
+#if 0\r
+ NICStartWatchDogTimer(fdoData);\r
+#endif\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceSelfManagedIoRestart\n");\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceSelfManagedIoCleanup is called by the Framework when the device is\r
+ being torn down, either in response to the WDM IRP_MN_REMOVE_DEVICE\r
+ It will be called only once. Its job is to stop all outstanding I/O in the driver\r
+ that the Framework is not managing.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a framework device object.\r
+\r
+Return Value:\r
+\r
+ None\r
+\r
+--*/\r
+\r
+VOID\r
+HcaEvtDeviceSelfManagedIoCleanup( IN WDFDEVICE Device )\r
+{\r
+ PFDO_DATA fdoData = NULL;\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceSelfManagedIoCleanup\n");\r
+\r
+ fdoData = FdoGetData(Device);\r
+\r
+#if 0\r
+ if(fdoData->WatchDogTimer) {\r
+ WdfObjectDelete(fdoData->WatchDogTimer);\r
+ }\r
+#endif\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceSelfManagedIoCleanup\n");\r
+}\r
+\r
+\r
+VOID\r
+HcaEvtIoDeviceControl(\r
+ IN WDFQUEUE Queue,\r
+ IN WDFREQUEST Request,\r
+ IN size_t OutputBufferLength,\r
+ IN size_t InputBufferLength,\r
+ IN ULONG IoControlCode\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This event is called when the framework receives IRP_MJ_DEVICE_CONTROL\r
+ requests from the system.\r
+\r
+Arguments:\r
+\r
+ Queue - Handle to the framework queue object that is associated\r
+ with the I/O request.\r
+ Request - Handle to a framework request object.\r
+\r
+ OutputBufferLength - length of the request's output buffer,\r
+ if an output buffer is available.\r
+ InputBufferLength - length of the request's input buffer,\r
+ if an input buffer is available.\r
+\r
+ IoControlCode - the driver-defined or system-defined I/O control code\r
+ (IOCTL) that is associated with the request.\r
+Return Value:\r
+\r
+ VOID\r
+\r
+--*/\r
+{\r
+ NTSTATUS status= STATUS_SUCCESS;\r
+ PFDO_DATA fdoData = NULL;\r
+ WDFDEVICE hDevice;\r
+ WDF_REQUEST_PARAMETERS params;\r
+\r
+ UNREFERENCED_PARAMETER(OutputBufferLength);\r
+ UNREFERENCED_PARAMETER(InputBufferLength);\r
+\r
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS,\r
+ "HcaEvtIoDeviceControl called %p\n", Request);\r
+\r
+ hDevice = WdfIoQueueGetDevice(Queue);\r
+ fdoData = FdoGetData(hDevice);\r
+\r
+ WDF_REQUEST_PARAMETERS_INIT(¶ms);\r
+\r
+ WdfRequestGetParameters(\r
+ Request,\r
+ ¶ms\r
+ );\r
+\r
+ switch (IoControlCode)\r
+ {\r
+#if 0\r
+ case IOCTL_NDISPROT_QUERY_OID_VALUE:\r
+\r
+ ASSERT((IoControlCode & 0x3) == METHOD_BUFFERED);\r
+\r
+ NICHandleQueryOidRequest(\r
+ Queue,\r
+ Request,\r
+ ¶ms\r
+ );\r
+ break;\r
+\r
+ case IOCTL_NDISPROT_SET_OID_VALUE:\r
+\r
+ ASSERT((IoControlCode & 0x3) == METHOD_BUFFERED);\r
+\r
+ NICHandleSetOidRequest(\r
+ Queue,\r
+ Request,\r
+ ¶ms\r
+ );\r
+\r
+ break;\r
+\r
+ case IOCTL_NDISPROT_INDICATE_STATUS:\r
+\r
+ status = WdfRequestForwardToIoQueue(Request,\r
+ fdoData->PendingIoctlQueue);\r
+ if(!NT_SUCCESS(status)){\r
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS,\r
+ "WdfRequestForwardToIoQueue failed 0x%x\n", status);\r
+ WdfRequestComplete(Request, status);\r
+ break;\r
+ }\r
+\r
+ break;\r
+#endif\r
+ default:\r
+ ASSERTMSG(FALSE, "Invalid IOCTL request\n");\r
+ WdfRequestComplete(Request, STATUS_INVALID_DEVICE_REQUEST);\r
+ break;\r
+ }\r
+\r
+ return status;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceWakeArmS0 is called when the Framework arms the device for\r
+ wake in the S0 state. If there is any device-specific initialization\r
+ that needs to be done to arm internal wake signals, or to route internal\r
+ interrupt signals to the wake logic, it should be done here. The device\r
+ will be moved out of the D0 state soon after this callback is invoked.\r
+\r
+ In this sample, wake from S0 involves waking on packet arrival, as does\r
+ wake from Sx. A more common NIC implementation might wake on cable\r
+ insertion.\r
+\r
+ This function is pageable and it will run at PASSIVE_LEVEL.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a Framework device object.\r
+\r
+Return Value:\r
+\r
+ NTSTATUS - Failure will result in the device remaining in the D0 state.\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+HcaEvtDeviceWakeArmS0( IN WDFDEVICE Device )\r
+{\r
+ NTSTATUS status;\r
+ PFDO_DATA fdoData;\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceWakeArmS0\n");\r
+\r
+ fdoData = FdoGetData(Device);\r
+\r
+ //\r
+ // Add pattern before sending wait-wake\r
+ //\r
+#if 0\r
+ status = NICConfigureForWakeUp(fdoData, TRUE);\r
+#endif\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceWakeArmS0 %x\n", status);\r
+\r
+ return status;\r
+}\r
+\r
+NTSTATUS\r
+HcaEvtDeviceWakeArmSx(\r
+ IN WDFDEVICE Device\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceWakeArmSx is called when the Framework arms the device for\r
+ wake from the S1, S2, S3 or S4 states. If there is any device-specific\r
+ initialization that needs to be done to arm internal wake signals, or to\r
+ route internal interrupt signals to the wake logic, it should be done here.\r
+ The device will be moved out of the D0 state soon after this callback is\r
+ invoked.\r
+\r
+ In this sample, wake from Sx involves arming for wake on packet arrival.\r
+ Cable insertion should not be enabled, as nobody would want their machine\r
+ to wake up simply because they plugged the cable in.\r
+\r
+ This function runs at PASSIVE_LEVEL. Whether it is pageable or not depends\r
+ on whether the device has set DO_POWER_PAGABLE.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a Framework device object.\r
+\r
+Return Value:\r
+\r
+ NTSTATUS - Failure will result in the device not being armed for wake\r
+ while the system is in Sx.\r
+\r
+--*/\r
+{\r
+ NTSTATUS status;\r
+ PFDO_DATA fdoData;\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceWakeArmSx\n");\r
+\r
+ fdoData = FdoGetData(Device);\r
+ //\r
+ // Add pattern before sending wait-wake\r
+ //\r
+#if 0\r
+ status = NICConfigureForWakeUp(fdoData, TRUE);\r
+#endif\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceWakeArmSx %x\n", status);\r
+\r
+ return status;\r
+}\r
+\r
+VOID\r
+HcaEvtDeviceWakeDisarmS0(\r
+ IN WDFDEVICE Device\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceWakeDisarmS0 reverses anything done in EvtDeviceWakeArmS0.\r
+\r
+ This function is pageable and it will run at PASSIVE_LEVEL.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a Framework device object.\r
+\r
+Return Value:\r
+\r
+ VOID.\r
+\r
+--*/\r
+{\r
+ NTSTATUS status;\r
+ PFDO_DATA fdoData;\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceWakeDisarmS0\n");\r
+\r
+ fdoData = FdoGetData(Device);\r
+#if 0\r
+ status = NICConfigureForWakeUp(fdoData, FALSE);\r
+#endif\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceWakeDisarmS0 %x\n", status);\r
+\r
+ return ;\r
+}\r
+\r
+VOID\r
+HcaEvtDeviceWakeDisarmSx(\r
+ IN WDFDEVICE Device\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceWakeDisarmSx reverses anything done in EvtDeviceWakeArmSx.\r
+\r
+ This function is not marked pageable because this function is in the\r
+ device power up path. When a function is marked pagable and the code\r
+ section is paged out, it will generate a page fault which could impact\r
+ the fast resume behavior because the client driver will have to wait\r
+ until the system drivers can service this page fault.\r
+\r
+ This function runs at PASSIVE_LEVEL, even though it is not paged. A\r
+ driver can optionally make this function pageable if DO_POWER_PAGABLE\r
+ is set. Even if DO_POWER_PAGABLE isn't set, this function still runs\r
+ at PASSIVE_LEVEL. In this case, though, the function absolutely must\r
+ not do anything that will cause a page fault.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a Framework device object.\r
+\r
+Return Value:\r
+\r
+ VOID\r
+\r
+--*/\r
+{\r
+ NTSTATUS status;\r
+ PFDO_DATA fdoData;\r
+\r
+ UNREFERENCED_PARAMETER(Device);\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceWakeDisarmSx\n");\r
+\r
+ fdoData = FdoGetData(Device);\r
+#if 0\r
+ status = NICConfigureForWakeUp(fdoData, FALSE);\r
+#endif\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceWakeDisarmSx %x\n", status);\r
+\r
+ return;\r
+}\r
+\r
+VOID\r
+HcaEvtDeviceWakeTriggeredS0(\r
+ IN WDFDEVICE Device\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceWakeTriggeredS0 will be called whenever the device triggers its\r
+ wake signal after being armed for wake from S0.\r
+\r
+ This function is pageable and runs at PASSIVE_LEVEL.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a Framework device object.\r
+\r
+Return Value:\r
+\r
+ VOID\r
+\r
+--*/\r
+{\r
+ UNREFERENCED_PARAMETER(Device);\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceWakeTriggeredS0\n");\r
+\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceWakeTriggeredS0\n");\r
+}\r
+\r
+VOID\r
+HcaEvtDeviceWakeTriggeredSx(\r
+ IN WDFDEVICE Device\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ EvtDeviceWakeTriggeredSx will be called whenever the device triggers its\r
+ wake signal after being armed for wake from Sx.\r
+\r
+ This function is not marked pageable because this function is in the\r
+ device power up path. When a function is marked pagable and the code\r
+ section is paged out, it will generate a page fault which could impact\r
+ the fast resume behavior because the client driver will have to wait\r
+ until the system drivers can service this page fault.\r
+\r
+ This function runs at PASSIVE_LEVEL, even though it is not paged. A\r
+ driver can optionally make this function pageable if DO_POWER_PAGABLE\r
+ is set. Even if DO_POWER_PAGABLE isn't set, this function still runs\r
+ at PASSIVE_LEVEL. In this case, though, the function absolutely must\r
+ not do anything that will cause a page fault.\r
+\r
+Arguments:\r
+\r
+ Device - Handle to a Framework device object.\r
+\r
+Return Value:\r
+\r
+ VOID\r
+\r
+--*/\r
+{\r
+ UNREFERENCED_PARAMETER(Device);\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaEvtDeviceWakeTriggeredSx");\r
+\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaEvtDeviceWakeTriggeredSx");\r
+\r
+ return;\r
+}\r
+\r
+\r
+/*++\r
+ Routine Description:\r
+\r
+ This routine is used to queue workitems so that the callback\r
+ functions can be executed at PASSIVE_LEVEL in the conext of\r
+ a system thread.\r
+\r
+Arguments:\r
+\r
+ FdoData - pointer to a device extenion.\r
+\r
+ CallbackFunction - Function to invoke when at PASSIVE_LEVEL.\r
+\r
+ Context1 & 2 - Meaning of the context values depends on the\r
+ callback function.\r
+\r
+Return Value:\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+HcaQueuePassiveLevelCallback(\r
+ IN PFDO_DATA FdoData,\r
+ IN PFN_WDF_WORKITEM CallbackFunction,\r
+ IN PVOID Context1,\r
+ IN PVOID Context2 )\r
+{\r
+ NTSTATUS status = STATUS_SUCCESS;\r
+ PWORKER_ITEM_CONTEXT context;\r
+ WDF_OBJECT_ATTRIBUTES attributes;\r
+ WDF_WORKITEM_CONFIG workitemConfig;\r
+ WDFWORKITEM hWorkItem;\r
+\r
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, WORKER_ITEM_CONTEXT);\r
+\r
+ attributes.ParentObject = FdoData->WdfDevice;\r
+\r
+ WDF_WORKITEM_CONFIG_INIT(&workitemConfig, CallbackFunction);\r
+\r
+ status = WdfWorkItemCreate( &workitemConfig,\r
+ &attributes,\r
+ &hWorkItem);\r
+\r
+ if (!NT_SUCCESS(status)) {\r
+ return status;\r
+ }\r
+\r
+ context = GetWorkItemContext(hWorkItem);\r
+\r
+ context->FdoData = FdoData;\r
+ context->Argument1 = Context1;\r
+ context->Argument2 = Context2;\r
+\r
+ //\r
+ // Execute this work item.\r
+ //\r
+ WdfWorkItemEnqueue(hWorkItem);\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+BOOLEAN\r
+HcaReadRegistryValue(\r
+ __in PFDO_DATA FdoData,\r
+ __in PWCHAR Name,\r
+ __out PULONG Value\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Can be used to read any REG_DWORD registry value stored\r
+ under Device Parameter.\r
+\r
+Arguments:\r
+\r
+ FdoData - pointer to the device extension\r
+ Name - Name of the registry value\r
+ Value -\r
+\r
+\r
+Return Value:\r
+\r
+ TRUE if successful\r
+ FALSE if not present/error in reading registry\r
+\r
+--*/\r
+{\r
+ WDFKEY hKey = NULL;\r
+ NTSTATUS status;\r
+ BOOLEAN retValue = FALSE;\r
+ UNICODE_STRING valueName;\r
+\r
+\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,\r
+ "-->HcaReadRegistryValue \n");\r
+\r
+ *Value = 0;\r
+\r
+ status = WdfDeviceOpenRegistryKey(FdoData->WdfDevice,\r
+ PLUGPLAY_REGKEY_DEVICE,\r
+ STANDARD_RIGHTS_ALL,\r
+ WDF_NO_OBJECT_ATTRIBUTES,\r
+ &hKey);\r
+\r
+ if (NT_SUCCESS (status)) {\r
+\r
+ RtlInitUnicodeString(&valueName,Name);\r
+\r
+ status = WdfRegistryQueryULong( hKey,\r
+ &valueName,\r
+ Value );\r
+\r
+ if (NT_SUCCESS (status)) {\r
+ retValue = TRUE;\r
+ }\r
+\r
+ WdfRegistryClose(hKey);\r
+ }\r
+\r
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,\r
+ "<--HcaReadRegistryValue %ws %d \n", Name, *Value);\r
+\r
+ return retValue;\r
+}\r
+\r
+BOOLEAN\r
+HcaWriteRegistryValue(\r
+ __in PFDO_DATA FdoData,\r
+ __in PWCHAR Name,\r
+ __in ULONG Value\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Can be used to write any REG_DWORD registry value stored\r
+ under Device Parameter.\r
+\r
+Arguments:\r
+\r
+\r
+Return Value:\r
+\r
+ TRUE - if write is successful\r
+ FALSE - otherwise\r
+\r
+--*/\r
+{\r
+ WDFKEY hKey = NULL;\r
+ NTSTATUS status;\r
+ BOOLEAN retValue = FALSE;\r
+ UNICODE_STRING valueName;\r
+\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,\r
+ "Entered HcaWriteRegistryValue\n");\r
+\r
+ //\r
+ // write the value out to the registry\r
+ //\r
+ status = WdfDeviceOpenRegistryKey(FdoData->WdfDevice,\r
+ PLUGPLAY_REGKEY_DEVICE,\r
+ STANDARD_RIGHTS_ALL,\r
+ WDF_NO_OBJECT_ATTRIBUTES,\r
+ &hKey);\r
+\r
+ if (NT_SUCCESS (status)) {\r
+\r
+ RtlInitUnicodeString(&valueName,Name);\r
+\r
+ status = WdfRegistryAssignULong (hKey,\r
+ &valueName,\r
+ Value );\r
+\r
+ if (NT_SUCCESS (status)) {\r
+ retValue = TRUE;\r
+ }\r
+\r
+ WdfRegistryClose(hKey);\r
+ }\r
+\r
+ return retValue;\r
+\r
+}\r
+\r
+#define PARAMATER_NAME_LEN 80\r
+\r
+BOOLEAN\r
+HcaReadFdoRegistryKeyValue(\r
+ __in PWDFDEVICE_INIT DeviceInit,\r
+ __in PWCHAR Name,\r
+ __out PULONG Value\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Can be used to read any REG_DWORD registry value stored\r
+ under Device Parameter.\r
+\r
+Arguments:\r
+\r
+ FdoData - pointer to the device extension\r
+ Name - Name of the registry value\r
+ Value -\r
+\r
+\r
+Return Value:\r
+\r
+ TRUE if successful\r
+ FALSE if not present/error in reading registry\r
+\r
+--*/\r
+{\r
+ WDFKEY hKey = NULL;\r
+ NTSTATUS status;\r
+ BOOLEAN retValue = FALSE;\r
+ UNICODE_STRING valueName;\r
+\r
+ PAGED_CODE();\r
+\r
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP,\r
+ "-->HcaReadFdoRegistryKeyValue\n");\r
+\r
+ *Value = 0;\r
+\r
+ status = WdfFdoInitOpenRegistryKey(DeviceInit,\r
+ PLUGPLAY_REGKEY_DEVICE,\r
+ STANDARD_RIGHTS_ALL,\r
+ WDF_NO_OBJECT_ATTRIBUTES,\r
+ &hKey);\r
+\r
+ if (NT_SUCCESS (status)) {\r
+\r
+ RtlInitUnicodeString(&valueName,Name);\r
+\r
+ status = WdfRegistryQueryULong (hKey,\r
+ &valueName,\r
+ Value);\r
+\r
+ if (NT_SUCCESS (status)) {\r
+ retValue = TRUE;\r
+ }\r
+\r
+ WdfRegistryClose(hKey);\r
+ }\r
+\r
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP,\r
+ "<--HcaReadFdoRegistryKeyValue %ws %d \n",\r
+ Name, *Value);\r
+\r
+ return retValue;\r
+}\r
+\r
+VOID\r
+HcaEvtDriverContextCleanup(\r
+ IN WDFDRIVER Driver\r
+ )\r
+/*++\r
+Routine Description:\r
+\r
+ Free all the resources allocated in DriverEntry.\r
+\r
+Arguments:\r
+\r
+ Driver - handle to a WDF Driver object.\r
+\r
+Return Value:\r
+\r
+ VOID.\r
+\r
+--*/\r
+{\r
+ UNREFERENCED_PARAMETER(Driver);\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,\r
+ "--> HcaEvtDriverContextCleanup\n");\r
+ PAGED_CODE ();\r
+\r
+ // Stop WPP Tracing\r
+ //\r
+ WPP_CLEANUP( WdfDriverWdmGetDriverObject( Driver ) );\r
+\r
+}\r
+\r
+NTSTATUS\r
+HcaSetPowerPolicy(\r
+ IN PFDO_DATA FdoData\r
+ )\r
+{\r
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;\r
+ WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;\r
+ NTSTATUS status = STATUS_SUCCESS;\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "--> HcaSetPowerPolicy\n");\r
+\r
+ PAGED_CODE();\r
+\r
+ //\r
+ // Init the idle policy structure.\r
+ //\r
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCanWakeFromS0);\r
+ idleSettings.IdleTimeout = 10000; // 10-sec\r
+\r
+ status = WdfDeviceAssignS0IdleSettings(FdoData->WdfDevice, &idleSettings);\r
+ if ( !NT_SUCCESS(status)) {\r
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
+ "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n", status);\r
+ return status;\r
+ }\r
+\r
+ //\r
+ // Init wait-wake policy structure.\r
+ //\r
+ WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);\r
+\r
+ status = WdfDeviceAssignSxWakeSettings(FdoData->WdfDevice, &wakeSettings);\r
+ if (!NT_SUCCESS(status)) {\r
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
+ "WdfDeviceAssignSxWakeSettings failed %x\n", status);\r
+ return status;\r
+ }\r
+\r
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+ "<-- HcaSetPowerPolicy\n");\r
+\r
+ return status;\r
+}\r
+\r
+PCHAR\r
+DbgDevicePowerString(\r
+ IN WDF_POWER_DEVICE_STATE Type\r
+ )\r
+/*++\r
+\r
+Updated Routine Description:\r
+ DbgDevicePowerString does not change in this stage of the function driver.\r
+\r
+--*/\r
+{\r
+ switch (Type)\r
+ {\r
+ case WdfPowerDeviceInvalid:\r
+ return "WdfPowerDeviceInvalid";\r
+ case WdfPowerDeviceD0:\r
+ return "WdfPowerDeviceD0";\r
+ case PowerDeviceD1:\r
+ return "WdfPowerDeviceD1";\r
+ case WdfPowerDeviceD2:\r
+ return "WdfPowerDeviceD2";\r
+ case WdfPowerDeviceD3:\r
+ return "WdfPowerDeviceD3";\r
+ case WdfPowerDeviceD3Final:\r
+ return "WdfPowerDeviceD3Final";\r
+ case WdfPowerDevicePrepareForHibernation:\r
+ return "WdfPowerDevicePrepareForHibernation";\r
+ case WdfPowerDeviceMaximum:\r
+ return "PowerDeviceMaximum";\r
+ default:\r
+ return "UnKnown Device Power State";\r
+ }\r
+}\r
+\r
+\r
+#if !defined(EVENT_TRACING)\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Debug print for the sample driver.\r
+\r
+Arguments:\r
+\r
+ TraceEventsLevel - print level between 0 and 3, with 3 the most verbose\r
+\r
+Return Value:\r
+\r
+ None.\r
+\r
+ --*/\r
+\r
+VOID\r
+TraceEvents (\r
+ IN ULONG TraceEventsLevel,\r
+ IN ULONG TraceEventsFlag,\r
+ IN PCCHAR DebugMessage,\r
+ ... )\r
+ {\r
+#if 1 // always for starters... DBG\r
+\r
+#define TEMP_BUFFER_SIZE 512\r
+ va_list list;\r
+ CHAR debugMessageBuffer[TEMP_BUFFER_SIZE];\r
+ NTSTATUS status;\r
+\r
+ va_start(list, DebugMessage);\r
+\r
+ if (DebugMessage) {\r
+\r
+ //\r
+ // Using new safe string functions instead of _vsnprintf.\r
+ // This function takes care of NULL terminating if the message\r
+ // is longer than the buffer.\r
+ //\r
+ status = RtlStringCbVPrintfA( debugMessageBuffer,\r
+ sizeof(debugMessageBuffer),\r
+ DebugMessage,\r
+ list );\r
+ if(!NT_SUCCESS(status)) {\r
+\r
+ DbgPrint (_DRIVER_NAME_": RtlStringCbVPrintfA failed %x\n",\r
+ status);\r
+ return;\r
+ }\r
+ if (TraceEventsLevel <= TRACE_LEVEL_INFORMATION ||\r
+ (TraceEventsLevel <= g_mthca_dbg_level &&\r
+ ((TraceEventsFlag & g_mthca_dbg_flags) == TraceEventsFlag))) {\r
+ DbgPrint(debugMessageBuffer);\r
+ }\r
+ }\r
+ va_end(list);\r
+\r
+ return;\r
+#else\r
+ UNREFERENCED_PARAMETER(TraceEventsLevel);\r
+ UNREFERENCED_PARAMETER(TraceEventsFlag);\r
+ UNREFERENCED_PARAMETER(DebugMessage);\r
+#endif\r
+}\r
+\r
+#endif\r
+\r
dev->mr_table.tavor_fmr.mpt_base =
ioremap(dev->mr_table.mpt_base,
- (1 << i) * sizeof (struct mthca_mpt_entry),
+ (1ULL << i) * sizeof (struct mthca_mpt_entry),
&dev->mr_table.tavor_fmr.mpt_base_size);
if (!dev->mr_table.tavor_fmr.mpt_base) {
--- /dev/null
+/*++\r
+ Copyright (c) Microsoft Corporation. All rights reserved.\r
+\r
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY\r
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR\r
+ PURPOSE.\r
+\r
+Module Name:\r
+\r
+ public.h\r
+\r
+Abstract:\r
+\r
+ This module contains the common declarations shared by driver\r
+ and user applications.\r
+\r
+Environment:\r
+\r
+ user and kernel\r
+\r
+--*/\r
+\r
+//\r
+// Define an Interface Guid for toaster device class.\r
+// This GUID is used to register (IoRegisterDeviceInterface)\r
+// an instance of an interface so that user application\r
+// can control the toaster device.\r
+//\r
+\r
+DEFINE_GUID (GUID_DEVINTERFACE_RDMA_IO,\r
+ 0xb74cfec2, 0x9366, 0x454a, 0xba, 0x71, 0x7c, 0x27, 0xb5, 0x14, 0x70, 0xa4);\r
+// {B74CFEC2-9366-454a-BA71-7C27B51470A4}\r
+\r
+//\r
+// Define a WMI GUID to get toaster device info.\r
+//\r
+\r
+DEFINE_GUID (PCIDRV_WMI_STD_DATA_GUID,\r
+ 0x20e35e40, 0x7179, 0x4f89, 0xa2, 0x8c, 0x12, 0xed, 0x5a, 0x3c, 0xaa, 0xa5);\r
+\r
+// {20E35E40-7179-4f89-A28C-12ED5A3CAAA5}\r
+\r
+//\r
+// GUID definition are required to be outside of header inclusion pragma to avoid\r
+// error during precompiled headers.\r
+//\r
+\r
next->ee_nds = cl_hton32(size);
for (scatter = (void *) (next + 1);
- (void *) scatter < (void *) ((u8*)next + (1 << qp->rq.wqe_shift));
+ (void *) scatter < (void *) ((u8*)next + (1ULL << qp->rq.wqe_shift));
++scatter)
scatter->lkey = cl_hton32(MTHCA_INVAL_LKEY);
}
*wqe_to_link(wqe) = i < srq->max - 1 ? i + 1 : -1;
for (scatter = (struct mthca_data_seg *)(wqe + sizeof (struct mthca_next_seg));
- (void *) scatter < (void*)(wqe + (1 << srq->wqe_shift));
+ (void *) scatter < (void*)(wqe + (1ULL << srq->wqe_shift));
++scatter)
scatter->lkey = cl_hton32(MTHCA_INVAL_LKEY);
}
* the FW max_sg value returned.
*/
return min( (uint32_t)dev->limits.max_sg,
- ((1 << (fls(dev->limits.max_desc_sz) - 1)) -
+ ((1ULL << (fls(dev->limits.max_desc_sz) - 1)) -
sizeof (struct mthca_next_seg)) /
sizeof (struct mthca_data_seg));
}
+++ /dev/null
-/*\r
- * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
- * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id$\r
- */\r
-\r
-/*++\r
-Copyright (c) Microsoft Corporation. All rights reserved.\r
-\r
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY\r
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\r
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR\r
- PURPOSE.\r
-\r
-Module Name:\r
-\r
- PciDrv.c\r
-\r
-Abstract:\r
-\r
- The WDM interfaces in this sample are derrived from the PciDrv KMDF samples\r
- function driver (e100 NIC). mthca interfaces have been merged.\r
- Goal is to provide a skeleton KMDF wrapper around the existing mthca driver\r
- as a starting point in the migrate to a full KMDF driver enviroment.\r
-\r
-Environment:\r
-\r
- Kernel mode\r
-\r
---*/\r
-\r
-#include "hca_driver.h"\r
-#include "pcidrv.h"\r
-#include "trace.h"\r
-\r
-#include <ntstrsafe.h>\r
-#include <ntintsafe.h>\r
-#include <initguid.h>\r
-\r
-#include "public.h"\r
-\r
-DRIVER_INITIALIZE DriverEntry;\r
-\r
-NTSTATUS\r
-HcaEntry(\r
- IN PDRIVER_OBJECT p_driver_obj,\r
- IN PUNICODE_STRING p_registry_path );\r
-\r
-NTSTATUS HcaAllocateSoftwareResources(PFDO_DATA fdoData);\r
-NTSTATUS HcaFreeSoftwareResources(PFDO_DATA fdoData);\r
-VOID HcaEvtDeviceSelfManagedIoCleanup( IN WDFDEVICE Device );\r
-NTSTATUS HcaEvtDeviceSelfManagedIoSuspend( IN WDFDEVICE Device );\r
-\r
-#if defined(EVENT_TRACING)\r
-//\r
-// The trace message header (.tmh) file must be included in a source file\r
-// before any WPP macro calls and after defining a WPP_CONTROL_GUIDS\r
-// macro (defined in toaster.h). During the compilation, WPP scans the source\r
-// files for DoTraceMessage() calls and builds a .tmh file which stores a unique\r
-// data GUID for each message, the text resource string for each message,\r
-// and the data types of the variables passed in for each message. This file\r
-// is automatically generated and used during post-processing.\r
-//\r
-#include "pcidrv.tmh"\r
-#endif\r
-\r
-#ifdef ALLOC_PRAGMA\r
-#pragma alloc_text (INIT, DriverEntry)\r
-#pragma alloc_text (PAGE, HcaEvtDeviceAdd)\r
-#pragma alloc_text (PAGE, HcaEvtDeviceContextCleanup)\r
-#pragma alloc_text (PAGE, HcaEvtDevicePrepareHardware)\r
-#pragma alloc_text (PAGE, HcaEvtDeviceReleaseHardware)\r
-#pragma alloc_text (PAGE, HcaReadRegistryValue)\r
-#pragma alloc_text (PAGE, HcaWriteRegistryValue)\r
-#pragma alloc_text (PAGE, HcaEvtDriverContextCleanup)\r
-#pragma alloc_text (PAGE, HcaEvtDeviceSelfManagedIoCleanup)\r
-#pragma alloc_text (PAGE, HcaEvtDeviceSelfManagedIoSuspend)\r
-#pragma alloc_text (PAGE, HcaEvtDeviceWakeArmS0)\r
-#pragma alloc_text (PAGE, HcaEvtDeviceWakeDisarmS0)\r
-#pragma alloc_text (PAGE, HcaEvtDeviceWakeTriggeredS0)\r
-#pragma alloc_text (PAGE, HcaEvtDeviceWakeArmSx)\r
-#pragma alloc_text (PAGE, HcaSetPowerPolicy)\r
-#pragma alloc_text (PAGE, HcaReadFdoRegistryKeyValue)\r
-#endif\r
-\r
-\r
-#define PARAMATER_NAME_LEN 80\r
-\r
-__inline\r
-BOOLEAN\r
-IsPoMgmtSupported(\r
- IN PFDO_DATA FdoData\r
- )\r
-{\r
-#if 1\r
- return TRUE;\r
-#else\r
- if (FdoData->RevsionID >= E100_82559_A_STEP\r
- /*&& FdoData->RevsionID <= E100_82559_C_STEP*/)\r
- {\r
- return TRUE;\r
- }\r
- else\r
- {\r
- return FALSE;\r
- }\r
-#endif\r
-}\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Installable driver initialization entry point.\r
- This entry point is called directly by the I/O system.\r
-\r
-Arguments:\r
-\r
- DriverObject - pointer to the driver object\r
-\r
- RegistryPath - pointer to a unicode string representing the path,\r
- to driver-specific key in the registry.\r
-\r
-Return Value:\r
-\r
- STATUS_SUCCESS if successful,\r
- STATUS_UNSUCCESSFUL otherwise.\r
-\r
---*/\r
-\r
-NTSTATUS\r
-DriverEntry (\r
- IN PDRIVER_OBJECT DriverObject,\r
- IN PUNICODE_STRING RegistryPath )\r
-{\r
- NTSTATUS status = STATUS_SUCCESS;\r
- WDF_DRIVER_CONFIG config;\r
- WDF_OBJECT_ATTRIBUTES attrib;\r
- WDFDRIVER driver;\r
-// PDRIVER_CONTEXT driverContext;\r
-\r
- //\r
- // Initialize WPP Tracing\r
- //\r
-#if defined(EVENT_TRACING)\r
- WPP_INIT_TRACING( DriverObject, RegistryPath );\r
-#endif\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,\r
- "mthca - KM Driver Framework Edition \n");\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,\r
- "Built %s %s\n", __DATE__, __TIME__);\r
-\r
-// WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attrib, DRIVER_CONTEXT);\r
-\r
- //\r
- // Register a cleanup callback so that we can call WPP_CLEANUP when\r
- // the framework driver object is deleted during driver unload.\r
- //\r
- attrib.EvtCleanupCallback = HcaEvtDriverContextCleanup;\r
-\r
- //\r
- // Initialize the Driver Config structure..\r
- //\r
- WDF_DRIVER_CONFIG_INIT(&config, HcaEvtDeviceAdd);\r
-\r
- //\r
- // Create a WDFDRIVER object.\r
- //\r
- status = WdfDriverCreate(DriverObject,\r
- RegistryPath,\r
- &attrib,\r
- &config,\r
- &driver);\r
-\r
- if (!NT_SUCCESS(status)) {\r
- TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,\r
- "WdfDriverCreate failed with status %!STATUS!\n", status);\r
- //\r
- // Cleanup tracing here because DriverContextCleanup will not be called\r
- // as we have failed to create WDFDRIVER object itself.\r
- // Please note that if your return failure from DriverEntry after the\r
- // WDFDRIVER object is created successfully, you don't have to\r
- // call WPP cleanup because in those cases DriverContextCleanup\r
- // will be executed when the framework deletes the DriverObject.\r
- //\r
-#if defined(EVENT_TRACING)\r
- WPP_CLEANUP(DriverObject);\r
-#endif\r
- return status;\r
- }\r
-\r
-#if 0\r
- driverContext = GetDriverContext(driver);\r
- //\r
- // Create a driver wide lookside list used for allocating memory for the\r
- // MP_RFD structure for all device instances (if there are multiple present).\r
- //\r
- status = WdfLookasideListCreate(WDF_NO_OBJECT_ATTRIBUTES, // LookAsideAttributes\r
- sizeof(MP_RFD),\r
- NonPagedPool,\r
- WDF_NO_OBJECT_ATTRIBUTES, // MemoryAttributes\r
- PCIDRV_POOL_TAG,\r
- &driverContext->RecvLookaside\r
- );\r
- if (!NT_SUCCESS(status)) {\r
- TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,\r
- "Couldn't allocate lookaside list status %!STATUS!\n", status);\r
- return status;\r
- }\r
-#endif\r
- if (!NT_SUCCESS(status))\r
- return status;\r
-\r
- return HcaEntry( DriverObject, RegistryPath );\r
-}\r
-\r
-\r
-/*++\r
-Routine Description:\r
-\r
- EvtDeviceAdd is called by the framework in response to AddDevice\r
- call from the PnP manager.\r
-\r
-Arguments:\r
-\r
- Driver - Handle to a framework driver object created in DriverEntry\r
-\r
- DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.\r
-\r
-Return Value:\r
-\r
- NTSTATUS\r
-\r
---*/\r
-\r
-NTSTATUS\r
-HcaEvtDeviceAdd(\r
- IN WDFDRIVER Driver,\r
- IN PWDFDEVICE_INIT DeviceInit )\r
-{\r
- NTSTATUS status = STATUS_SUCCESS;\r
- WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;\r
- WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks;\r
- WDF_OBJECT_ATTRIBUTES fdoAttributes;\r
- WDFDEVICE device;\r
- PFDO_DATA fdoData = NULL;\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "-->HcaEvtDeviceAdd routine. Driver: 0x%p\n", Driver);\r
-\r
- //\r
- // I/O type is Buffered by default. If required to use something else,\r
- // call WdfDeviceInitSetIoType with the appropriate type.\r
- //\r
- WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);\r
-\r
- //\r
- // Zero out the PnpPowerCallbacks structure.\r
- //\r
- WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);\r
-\r
- //\r
- // Set Callbacks for any of the functions we are interested in.\r
- // If no callback is set, Framework will take the default action\r
- // by itself. This sample provides many of the possible callbacks,\r
- // mostly because it's a fairly complex sample that drives full-featured\r
- // hardware. Drivers derived from this sample will often be able to\r
- // provide only some of these.\r
- //\r
-\r
- //\r
- // These callback is invoked to tear down all the driver-managed state\r
- // that is set up in this function. Many times, this callback won't do\r
- // much of anything, since many of the things that are set up here will\r
- // have their lifetimes automatically managed by the Framework.\r
- //\r
-\r
- //\r
- // These two callbacks set up and tear down hardware state,\r
- // specifically that which only has to be done once.\r
- //\r
-\r
- pnpPowerCallbacks.EvtDevicePrepareHardware = HcaEvtDevicePrepareHardware;\r
- pnpPowerCallbacks.EvtDeviceReleaseHardware = HcaEvtDeviceReleaseHardware;\r
-\r
- //\r
- // These two callbacks set up and tear down hardware state that must be\r
- // done every time the device moves in and out of the D0-working state.\r
- //\r
-\r
- pnpPowerCallbacks.EvtDeviceD0Entry = HcaEvtDeviceD0Entry;\r
- pnpPowerCallbacks.EvtDeviceD0Exit = HcaEvtDeviceD0Exit;\r
-\r
- //\r
- // These next two callbacks are for doing work at PASSIVE_LEVEL (low IRQL)\r
- // after all the interrupts are connected and before they are disconnected.\r
- //\r
- // Some drivers need to do device initialization and tear-down while the\r
- // interrupt is connected. (This is a problem for these devices, since\r
- // it opens them up to taking interrupts before they are actually ready\r
- // to handle them, or to taking them after they have torn down too much\r
- // to be able to handle them.) While this hardware design pattern is to\r
- // be discouraged, it is possible to handle it by doing device init and\r
- // tear down in these routines rather than in EvtDeviceD0Entry and\r
- // EvtDeviceD0Exit.\r
- //\r
- // In this sample these callbacks don't do anything.\r
- //\r
-\r
- pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled =\r
- HcaEvtDeviceD0EntryPostInterruptsEnabled;\r
- pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled =\r
- HcaEvtDeviceD0ExitPreInterruptsDisabled;\r
-\r
- //\r
- // This next group of five callbacks allow a driver to become involved in\r
- // starting and stopping operations within a driver as the driver moves\r
- // through various PnP/Power states. These functions are not necessary\r
- // if the Framework is managing all the device's queues and there is no\r
- // activity going on that isn't queue-based. This sample provides these\r
- // callbacks because it uses watchdog timer to monitor whether the device\r
- // is working or not and it needs to start and stop the timer when the\r
- // device is started or removed. It cannot start and stop the timers in the\r
- // D0Entry and D0Exit callbacks because if the device is surprise-removed,\r
- // D0Exit will not be called.\r
- //\r
- pnpPowerCallbacks.EvtDeviceSelfManagedIoInit =\r
- HcaEvtDeviceSelfManagedIoInit;\r
- pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup =\r
- HcaEvtDeviceSelfManagedIoCleanup;\r
- pnpPowerCallbacks.EvtDeviceSelfManagedIoSuspend =\r
- HcaEvtDeviceSelfManagedIoSuspend;\r
- pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart =\r
- HcaEvtDeviceSelfManagedIoRestart;\r
-\r
- //\r
- // Register the PnP and power callbacks. Power policy related callbacks will\r
- // be registered later.\r
- //\r
- WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);\r
-\r
- //\r
- // Init the power policy callbacks\r
- //\r
- WDF_POWER_POLICY_EVENT_CALLBACKS_INIT(&powerPolicyCallbacks);\r
-\r
- //\r
- // This group of three callbacks allows this sample driver to manage\r
- // arming the device for wake from the S0 state. Networking devices can\r
- // optionally be put into a low-power state when there is no networking\r
- // cable plugged into them. This sample implements this feature.\r
- //\r
- powerPolicyCallbacks.EvtDeviceArmWakeFromS0 = HcaEvtDeviceWakeArmS0;\r
- powerPolicyCallbacks.EvtDeviceDisarmWakeFromS0 = HcaEvtDeviceWakeDisarmS0;\r
- powerPolicyCallbacks.EvtDeviceWakeFromS0Triggered =\r
- HcaEvtDeviceWakeTriggeredS0;\r
-\r
- //\r
- // This group of three callbacks allows the device to be armed for wake\r
- // from Sx (S1, S2, S3 or S4.) Networking devices can optionally be put\r
- // into a state where a packet sent to them will cause the device's wake\r
- // signal to be triggered, which causes the machine to wake, moving back\r
- // into the S0 state.\r
- //\r
-\r
- powerPolicyCallbacks.EvtDeviceArmWakeFromSx = HcaEvtDeviceWakeArmSx;\r
- powerPolicyCallbacks.EvtDeviceDisarmWakeFromSx = HcaEvtDeviceWakeDisarmSx;\r
- powerPolicyCallbacks.EvtDeviceWakeFromSxTriggered =\r
- HcaEvtDeviceWakeTriggeredSx;\r
-\r
- WdfDeviceInitSetDeviceType( DeviceInit,\r
- FILE_DEVICE_INFINIBAND|FILE_DEVICE_SECURE_OPEN );\r
-\r
- WdfDeviceInitSetExclusive(DeviceInit, TRUE);\r
- //\r
- // Register the power policy callbacks.\r
- //\r
- WdfDeviceInitSetPowerPolicyEventCallbacks(DeviceInit,&powerPolicyCallbacks);\r
-\r
- // Since we are the function driver, we are now the power policy owner\r
- // for the device according to the default framework rule. We will register\r
- // our power policy callbacks after finding the wakeup capability of the\r
- // device.\r
-\r
-\r
- // Specify the context type and size for the device we are about to create.\r
-\r
- WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DATA);\r
-\r
-\r
- // ContextCleanup will be called by the framework when it deletes the\r
- // device. So you can defer freeing any resources allocated to Cleanup\r
- // callback in the event AddDevice returns any error after the device is\r
- // created.\r
-\r
- fdoAttributes.EvtCleanupCallback = HcaEvtDeviceContextCleanup;\r
-\r
- status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);\r
-\r
- if ( !NT_SUCCESS(status)) {\r
- TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
- "WdfDeviceInitialize failed %!STATUS!\n", status);\r
- return status;\r
- }\r
-\r
- //\r
- // Device creation is complete.\r
- // Get the DeviceExtension and initialize it.\r
- //\r
- fdoData = FdoGetData(device);\r
- fdoData->WdfDevice = device;\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n",\r
- WdfDeviceWdmGetPhysicalDevice (device),\r
- WdfDeviceWdmGetDeviceObject (device),\r
- WdfDeviceWdmGetAttachedDevice(device),\r
- fdoData);\r
-\r
- status = hca_add_device( WdfDriverWdmGetDriverObject(device), // DRIVER OBJ\r
- WdfDeviceWdmGetPhysicalDevice(device), // PDO\r
- WdfDeviceWdmGetAttachedDevice(device) );// DEV OBJ\r
- //\r
- // Initialize the device extension and allocate all the software resources\r
- //\r
- status = HcaAllocateSoftwareResources(fdoData);\r
- if (!NT_SUCCESS (status)){\r
- TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
- "HcaAllocateSoftwareResources failed: %!STATUS!\n",\r
- status);\r
- return status;\r
- }\r
-\r
- //\r
- // If we own the power policy and if our device supports wait-wake then we\r
- // will set our power-policy and update S0-Idle policy.\r
- //\r
- if(IsPoMgmtSupported(fdoData) )\r
- {\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "Device has wait-wake capability\n");\r
- status = HcaSetPowerPolicy(fdoData);\r
- if (!NT_SUCCESS (status)) {\r
- TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
- "HcaSetPowerPolicy failed %!STATUS!\n", status);\r
- return status;\r
- }\r
- }\r
-\r
- //\r
- // Tell the Framework that this device will need an interface so that\r
- // application can interact with it.\r
- //\r
- status = WdfDeviceCreateDeviceInterface(\r
- device,\r
- (LPGUID) &GUID_DEVINTERFACE_RDMA_IO,\r
- NULL );\r
-\r
- if (!NT_SUCCESS (status)) {\r
- TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
- "WdfDeviceCreateDeviceInterface failed %!STATUS!\n",status);\r
- return status;\r
- }\r
-\r
- status = HcaWmiRegistration(device);\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- HcaEvtDeviceAdd \n");\r
-\r
- return status;\r
-}\r
-\r
-VOID\r
-HcaEvtDeviceContextCleanup (\r
- WDFDEVICE Device\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceContextCleanup event callback cleans up anything done in\r
- EvtDeviceAdd, except those things that are automatically cleaned\r
- up by the Framework.\r
-\r
- In the case of this sample, everything is automatically handled. In a\r
- driver derived from this sample, it's quite likely that this function could\r
- be deleted.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a framework device object.\r
-\r
-Return Value:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- PFDO_DATA fdoData = NULL;\r
- NTSTATUS status;\r
-\r
- PAGED_CODE();\r
-\r
- fdoData = FdoGetData(Device);\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceContextCleanup\n");\r
-\r
- status = HcaFreeSoftwareResources(fdoData);\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceContextCleanup\n");\r
-\r
-}\r
-\r
-NTSTATUS\r
-HcaEvtDevicePrepareHardware (\r
- WDFDEVICE Device,\r
- WDFCMRESLIST Resources,\r
- WDFCMRESLIST ResourcesTranslated\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceStart event callback performs operations that are necessary\r
- to make the driver's device operational. The framework calls the driver's\r
- EvtDeviceStart callback when the PnP manager sends an IRP_MN_START_DEVICE\r
- request to the driver stack.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a framework device object.\r
-\r
- Resources - Handle to a collection of framework resource objects.\r
- This collection identifies the raw (bus-relative) hardware\r
- resources that have been assigned to the device.\r
-\r
- ResourcesTranslated - Handle to a collection of framework resource objects.\r
- This collection identifies the translated (system-physical)\r
- hardware resources that have been assigned to the device.\r
- The resources appear from the CPU's point of view.\r
- Use this list of resources to map I/O space and\r
- device-accessible memory into virtual address space\r
-\r
-Return Value:\r
-\r
- WDF status code\r
-\r
---*/\r
-{\r
- NTSTATUS status = STATUS_SUCCESS;\r
- PFDO_DATA fdoData = NULL;\r
-\r
- UNREFERENCED_PARAMETER(Resources);\r
- UNREFERENCED_PARAMETER(ResourcesTranslated);\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDevicePrepareHardware\n");\r
-\r
- fdoData = FdoGetData(Device);\r
-\r
-#if 0\r
- status = NICMapHWResources(fdoData, ResourcesTranslated);\r
- if (!NT_SUCCESS (status)){\r
- TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
- "NICMapHWResources failed: %!STATUS!\n", status);\r
- return status;\r
- }\r
-#endif\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDevicePrepareHardware\n");\r
-\r
- return status;\r
-\r
-}\r
-\r
-NTSTATUS\r
-HcaEvtDeviceReleaseHardware(\r
- IN WDFDEVICE Device,\r
- IN WDFCMRESLIST ResourcesTranslated\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceReleaseHardware is called by the framework whenever the PnP manager\r
- is revoking ownership of our resources. This may be in response to either\r
- IRP_MN_STOP_DEVICE or IRP_MN_REMOVE_DEVICE. The callback is made before\r
- passing down the IRP to the lower driver.\r
-\r
- In this callback, do anything necessary to free those resources.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a framework device object.\r
-\r
- ResourcesTranslated - Handle to a collection of framework resource objects.\r
- This collection identifies the translated (system-physical)\r
- hardware resources that have been assigned to the device.\r
- The resources appear from the CPU's point of view.\r
- Use this list of resources to map I/O space and\r
- device-accessible memory into virtual address space\r
-\r
-Return Value:\r
-\r
- NTSTATUS - Failures will be logged, but not acted on.\r
-\r
---*/\r
-{\r
- PFDO_DATA fdoData = NULL;\r
-\r
- UNREFERENCED_PARAMETER(ResourcesTranslated);\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceReleaseHardware\n");\r
-\r
- fdoData = FdoGetData(Device);\r
-\r
-#if 0\r
- //\r
- // Unmap any I/O ports. Disconnecting from the interrupt will be done\r
- // automatically by the framework.\r
- //\r
- NICUnmapHWResources(fdoData);\r
-#endif\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceReleaseHardware\n");\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-NTSTATUS\r
-HcaEvtDeviceD0Entry(\r
- IN WDFDEVICE Device,\r
- IN WDF_POWER_DEVICE_STATE PreviousState\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceD0Entry event callback must perform any operations that are\r
- necessary before the specified device is used. It will be called every\r
- time the hardware needs to be (re-)initialized. This includes after\r
- IRP_MN_START_DEVICE, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE,\r
- IRP_MN_SET_POWER-D0.\r
-\r
- This function is not marked pageable because this function is in the\r
- device power up path. When a function is marked pagable and the code\r
- section is paged out, it will generate a page fault which could impact\r
- the fast resume behavior because the client driver will have to wait\r
- until the system drivers can service this page fault.\r
-\r
- This function runs at PASSIVE_LEVEL, even though it is not paged. A\r
- driver can optionally make this function pageable if DO_POWER_PAGABLE\r
- is set. Even if DO_POWER_PAGABLE isn't set, this function still runs\r
- at PASSIVE_LEVEL. In this case, though, the function absolutely must\r
- not do anything that will cause a page fault.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a framework device object.\r
-\r
- PreviousState - Device power state which the device was in most recently.\r
- If the device is being newly started, this will be\r
- PowerDeviceUnspecified.\r
-\r
-Return Value:\r
-\r
- NTSTATUS\r
-\r
---*/\r
-{\r
- PFDO_DATA fdoData;\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,\r
- "-->HcaEvtDeviceD0Entry - coming from %s\n",\r
- DbgDevicePowerString(PreviousState));\r
-\r
- fdoData = FdoGetData(Device);\r
-\r
- ASSERT(PowerDeviceD0 != PreviousState);\r
-\r
- fdoData->DevicePowerState = PowerDeviceD0;\r
-\r
- if(IsPoMgmtSupported(fdoData)){\r
-\r
- TraceEvents(TRACE_LEVEL_VERBOSE, DBG_POWER,\r
- "Entering fully on state\n");\r
-#ifdef XXX\r
- MPSetPowerD0 (fdoData);\r
-#endif\r
- }\r
-\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--HcaEvtDeviceD0Entry\n");\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-NTSTATUS\r
-HcaEvtDeviceD0Exit(\r
- IN WDFDEVICE Device,\r
- IN WDF_POWER_DEVICE_STATE TargetState\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This routine undoes anything done in EvtDeviceD0Entry. It is called\r
- whenever the device leaves the D0 state, which happens when the device is\r
- stopped, when it is removed, and when it is powered off.\r
-\r
- The device is still in D0 when this callback is invoked, which means that\r
- the driver can still touch hardware in this routine.\r
-\r
- Note that interrupts have already been disabled by the time that this\r
- callback is invoked.\r
-\r
- EvtDeviceD0Exit event callback must perform any operations that are\r
- necessary before the specified device is moved out of the D0 state. If the\r
- driver needs to save hardware state before the device is powered down, then\r
- that should be done here.\r
-\r
- This function runs at PASSIVE_LEVEL, though it is generally not paged. A\r
- driver can optionally make this function pageable if DO_POWER_PAGABLE is set.\r
-\r
- Even if DO_POWER_PAGABLE isn't set, this function still runs at\r
- PASSIVE_LEVEL. In this case, though, the function absolutely must not do\r
- anything that will cause a page fault.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a framework device object.\r
-\r
- TargetState - Device power state which the device will be put in once this\r
- callback is complete.\r
-\r
-Return Value:\r
-\r
- Success implies that the device can be used. Failure will result in the\r
- device stack being torn down.\r
-\r
---*/\r
-{\r
- PFDO_DATA fdoData;\r
-\r
- UNREFERENCED_PARAMETER(Device);\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,\r
- "-->HcaEvtDeviceD0Exit - moving to %s\n",\r
- DbgDevicePowerString(TargetState));\r
-\r
- fdoData = FdoGetData(Device);\r
-\r
- fdoData->DevicePowerState = TargetState;\r
-\r
- switch (TargetState) {\r
- case WdfPowerDeviceD1:\r
- case WdfPowerDeviceD2:\r
- case WdfPowerDeviceD3:\r
-\r
- if(IsPoMgmtSupported(fdoData)){\r
-\r
- TraceEvents(TRACE_LEVEL_VERBOSE, DBG_POWER,\r
- "Entering a deeper sleep state\n");\r
-#ifdef XXX\r
- MPSetPowerLow (fdoData, TargetState);\r
-#endif\r
- }\r
- break;\r
-\r
- case WdfPowerDevicePrepareForHibernation:\r
-\r
- //\r
- // Fill in any code to save hardware state here. Do not put in any\r
- // code to shut the device off. If this device cannot support being\r
- // in the paging path (or being a parent or grandparent of a paging\r
- // path device) then this whole case can be deleted.\r
- //\r
- ASSERT(FALSE); // This driver shouldn't get this.\r
- break;\r
-\r
- case WdfPowerDeviceD3Final:\r
- //\r
- // Reset and put the device into a known initial state we're shutting\r
- // down for the last time.\r
- //\r
-#if 0\r
- NICShutdown(fdoData);\r
-#endif\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--HcaEvtDeviceD0Exit\n");\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-NTSTATUS\r
-HcaEvtDeviceSelfManagedIoInit(\r
- IN WDFDEVICE Device\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- HcaEvtDeviceSelfManagedIoInit is called by the Framework when the device\r
- enters the D0 state. Its job is to start any I/O-related actions that the\r
- Framework isn't managing. This might include releasing queues that are not\r
- power-managed, that is, the Framework is not automatically holding and releasing\r
- them across PnP/Power transitions. (The default behavior for WDFQUEUE is\r
- auto-managed, so most queues don't need to be dealt with here.) This might\r
- also include setting up non-queue-based actions.\r
-\r
- If you allow the Framework to manage most or all of your queues, then when\r
- you build a driver from this sample, you can probably delete this function.\r
-\r
- In this driver, the SelfManagedIo callbacks are used to implement a watchdog timer.\r
-\r
- This function is not marked pagable because this function is in the\r
- device power up path. When a function is marked pagable and the code\r
- section is paged out, it will generate a page fault which could impact\r
- the fast resume behavior because the client driver will have to wait\r
- until the system drivers can service this page fault.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a framework device object.\r
-\r
-Return Value:\r
-\r
- NTSTATUS - Failures will result in the device stack being torn down.\r
-\r
---*/\r
-{\r
- PFDO_DATA fdoData = NULL;\r
- NTSTATUS status;\r
-// WDF_TIMER_CONFIG wdfTimerConfig;\r
-// WDF_OBJECT_ATTRIBUTES timerAttributes;\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceSelfManagedIoInit\n");\r
-\r
- fdoData = FdoGetData(Device);\r
-\r
-#if 0\r
- // To minimize init-time, create a timer DPC to do link detection.\r
- // This DPC will also be used to check for hardware hang.\r
- //\r
- WDF_TIMER_CONFIG_INIT(&wdfTimerConfig, NICWatchDogEvtTimerFunc);\r
-\r
- WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes);\r
- timerAttributes.ParentObject = fdoData->WdfDevice;\r
-\r
- status = WdfTimerCreate(\r
- &wdfTimerConfig,\r
- &timerAttributes,\r
- &fdoData->WatchDogTimer\r
- );\r
-\r
- if(!NT_SUCCESS(status) ) {\r
- TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
- "Error: WdfTimerCreate create failed 0x%x\n", status);\r
- return status;\r
- }\r
-\r
- NICStartWatchDogTimer(fdoData);\r
-#endif\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceSelfManagedIoInit\n");\r
-\r
- return status;\r
-}\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceSelfManagedIoSuspend is called by the Framework before the device\r
- leaves the D0 state. Its job is to stop any I/O-related actions that the\r
- Framework isn't managing, and which cannot be handled when the device\r
- hardware isn't available. In general, this means reversing anything that\r
- was done in EvtDeviceSelfManagedIoStart.\r
-\r
- If you allow the Framework to manage most or all of your queues, then when\r
- you build a driver from this sample, you can probably delete this function.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a framework device object.\r
-\r
-Return Value:\r
-\r
- NTSTATUS - Failures will result in the device stack being torn down.\r
-\r
---*/\r
-\r
-NTSTATUS\r
-HcaEvtDeviceSelfManagedIoSuspend( IN WDFDEVICE Device )\r
-{\r
- PFDO_DATA fdoData = NULL;\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceSelfManagedIoSuspend\n");\r
-\r
- fdoData = FdoGetData(Device);\r
-\r
-#if 0\r
- //\r
- // Stop the watchdog timer and wait for DPC to run to completion if\r
- // it's already fired.\r
- //\r
- WdfTimerStop(fdoData->WatchDogTimer, TRUE);\r
-#endif\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceSelfManagedIoSuspend\n");\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-NTSTATUS\r
-HcaEvtDeviceSelfManagedIoRestart(\r
- IN WDFDEVICE Device\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceSelfManagedIoRestart is called by the Framework before the device\r
- is restarted for one of the following reasons:\r
- a) the PnP resources were rebalanced (framework received\r
- query-stop and stop IRPS )\r
- b) the device resumed from a low power state to D0.\r
-\r
- This function is not marked pagable because this function is in the\r
- device power up path. When a function is marked pagable and the code\r
- section is paged out, it will generate a page fault which could impact\r
- the fast resume behavior because the client driver will have to wait\r
- until the system drivers can service this page fault.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a framework device object.\r
-\r
-Return Value:\r
-\r
- NTSTATUS - Failure will cause the device stack to be torn down.\r
-\r
---*/\r
-{\r
- PFDO_DATA fdoData;\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceSelfManagedIoRestart\n");\r
-\r
- fdoData = FdoGetData(Device);\r
-\r
- //\r
- // Restart the watchdog timer.\r
- //\r
-#if 0\r
- NICStartWatchDogTimer(fdoData);\r
-#endif\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceSelfManagedIoRestart\n");\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceSelfManagedIoCleanup is called by the Framework when the device is\r
- being torn down, either in response to the WDM IRP_MN_REMOVE_DEVICE\r
- It will be called only once. Its job is to stop all outstanding I/O in the driver\r
- that the Framework is not managing.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a framework device object.\r
-\r
-Return Value:\r
-\r
- None\r
-\r
---*/\r
-\r
-VOID\r
-HcaEvtDeviceSelfManagedIoCleanup( IN WDFDEVICE Device )\r
-{\r
- PFDO_DATA fdoData = NULL;\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceSelfManagedIoCleanup\n");\r
-\r
- fdoData = FdoGetData(Device);\r
-\r
-#if 0\r
- if(fdoData->WatchDogTimer) {\r
- WdfObjectDelete(fdoData->WatchDogTimer);\r
- }\r
-#endif\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceSelfManagedIoCleanup\n");\r
-}\r
-\r
-\r
-VOID\r
-HcaEvtIoDeviceControl(\r
- IN WDFQUEUE Queue,\r
- IN WDFREQUEST Request,\r
- IN size_t OutputBufferLength,\r
- IN size_t InputBufferLength,\r
- IN ULONG IoControlCode\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This event is called when the framework receives IRP_MJ_DEVICE_CONTROL\r
- requests from the system.\r
-\r
-Arguments:\r
-\r
- Queue - Handle to the framework queue object that is associated\r
- with the I/O request.\r
- Request - Handle to a framework request object.\r
-\r
- OutputBufferLength - length of the request's output buffer,\r
- if an output buffer is available.\r
- InputBufferLength - length of the request's input buffer,\r
- if an input buffer is available.\r
-\r
- IoControlCode - the driver-defined or system-defined I/O control code\r
- (IOCTL) that is associated with the request.\r
-Return Value:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- NTSTATUS status= STATUS_SUCCESS;\r
- PFDO_DATA fdoData = NULL;\r
- WDFDEVICE hDevice;\r
- WDF_REQUEST_PARAMETERS params;\r
-\r
- UNREFERENCED_PARAMETER(OutputBufferLength);\r
- UNREFERENCED_PARAMETER(InputBufferLength);\r
-\r
- TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS,\r
- "HcaEvtIoDeviceControl called %p\n", Request);\r
-\r
- hDevice = WdfIoQueueGetDevice(Queue);\r
- fdoData = FdoGetData(hDevice);\r
-\r
- WDF_REQUEST_PARAMETERS_INIT(¶ms);\r
-\r
- WdfRequestGetParameters(\r
- Request,\r
- ¶ms\r
- );\r
-\r
- switch (IoControlCode)\r
- {\r
-#if 0\r
- case IOCTL_NDISPROT_QUERY_OID_VALUE:\r
-\r
- ASSERT((IoControlCode & 0x3) == METHOD_BUFFERED);\r
-\r
- NICHandleQueryOidRequest(\r
- Queue,\r
- Request,\r
- ¶ms\r
- );\r
- break;\r
-\r
- case IOCTL_NDISPROT_SET_OID_VALUE:\r
-\r
- ASSERT((IoControlCode & 0x3) == METHOD_BUFFERED);\r
-\r
- NICHandleSetOidRequest(\r
- Queue,\r
- Request,\r
- ¶ms\r
- );\r
-\r
- break;\r
-\r
- case IOCTL_NDISPROT_INDICATE_STATUS:\r
-\r
- status = WdfRequestForwardToIoQueue(Request,\r
- fdoData->PendingIoctlQueue);\r
- if(!NT_SUCCESS(status)){\r
- TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS,\r
- "WdfRequestForwardToIoQueue failed 0x%x\n", status);\r
- WdfRequestComplete(Request, status);\r
- break;\r
- }\r
-\r
- break;\r
-#endif\r
- default:\r
- ASSERTMSG(FALSE, "Invalid IOCTL request\n");\r
- WdfRequestComplete(Request, STATUS_INVALID_DEVICE_REQUEST);\r
- break;\r
- }\r
-\r
- return status;\r
-}\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceWakeArmS0 is called when the Framework arms the device for\r
- wake in the S0 state. If there is any device-specific initialization\r
- that needs to be done to arm internal wake signals, or to route internal\r
- interrupt signals to the wake logic, it should be done here. The device\r
- will be moved out of the D0 state soon after this callback is invoked.\r
-\r
- In this sample, wake from S0 involves waking on packet arrival, as does\r
- wake from Sx. A more common NIC implementation might wake on cable\r
- insertion.\r
-\r
- This function is pageable and it will run at PASSIVE_LEVEL.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a Framework device object.\r
-\r
-Return Value:\r
-\r
- NTSTATUS - Failure will result in the device remaining in the D0 state.\r
-\r
---*/\r
-\r
-NTSTATUS\r
-HcaEvtDeviceWakeArmS0( IN WDFDEVICE Device )\r
-{\r
- NTSTATUS status;\r
- PFDO_DATA fdoData;\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceWakeArmS0\n");\r
-\r
- fdoData = FdoGetData(Device);\r
-\r
- //\r
- // Add pattern before sending wait-wake\r
- //\r
-#if 0\r
- status = NICConfigureForWakeUp(fdoData, TRUE);\r
-#endif\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceWakeArmS0 %x\n", status);\r
-\r
- return status;\r
-}\r
-\r
-NTSTATUS\r
-HcaEvtDeviceWakeArmSx(\r
- IN WDFDEVICE Device\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceWakeArmSx is called when the Framework arms the device for\r
- wake from the S1, S2, S3 or S4 states. If there is any device-specific\r
- initialization that needs to be done to arm internal wake signals, or to\r
- route internal interrupt signals to the wake logic, it should be done here.\r
- The device will be moved out of the D0 state soon after this callback is\r
- invoked.\r
-\r
- In this sample, wake from Sx involves arming for wake on packet arrival.\r
- Cable insertion should not be enabled, as nobody would want their machine\r
- to wake up simply because they plugged the cable in.\r
-\r
- This function runs at PASSIVE_LEVEL. Whether it is pageable or not depends\r
- on whether the device has set DO_POWER_PAGABLE.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a Framework device object.\r
-\r
-Return Value:\r
-\r
- NTSTATUS - Failure will result in the device not being armed for wake\r
- while the system is in Sx.\r
-\r
---*/\r
-{\r
- NTSTATUS status;\r
- PFDO_DATA fdoData;\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceWakeArmSx\n");\r
-\r
- fdoData = FdoGetData(Device);\r
- //\r
- // Add pattern before sending wait-wake\r
- //\r
-#if 0\r
- status = NICConfigureForWakeUp(fdoData, TRUE);\r
-#endif\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceWakeArmSx %x\n", status);\r
-\r
- return status;\r
-}\r
-\r
-VOID\r
-HcaEvtDeviceWakeDisarmS0(\r
- IN WDFDEVICE Device\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceWakeDisarmS0 reverses anything done in EvtDeviceWakeArmS0.\r
-\r
- This function is pageable and it will run at PASSIVE_LEVEL.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a Framework device object.\r
-\r
-Return Value:\r
-\r
- VOID.\r
-\r
---*/\r
-{\r
- NTSTATUS status;\r
- PFDO_DATA fdoData;\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceWakeDisarmS0\n");\r
-\r
- fdoData = FdoGetData(Device);\r
-#if 0\r
- status = NICConfigureForWakeUp(fdoData, FALSE);\r
-#endif\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceWakeDisarmS0 %x\n", status);\r
-\r
- return ;\r
-}\r
-\r
-VOID\r
-HcaEvtDeviceWakeDisarmSx(\r
- IN WDFDEVICE Device\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceWakeDisarmSx reverses anything done in EvtDeviceWakeArmSx.\r
-\r
- This function is not marked pageable because this function is in the\r
- device power up path. When a function is marked pagable and the code\r
- section is paged out, it will generate a page fault which could impact\r
- the fast resume behavior because the client driver will have to wait\r
- until the system drivers can service this page fault.\r
-\r
- This function runs at PASSIVE_LEVEL, even though it is not paged. A\r
- driver can optionally make this function pageable if DO_POWER_PAGABLE\r
- is set. Even if DO_POWER_PAGABLE isn't set, this function still runs\r
- at PASSIVE_LEVEL. In this case, though, the function absolutely must\r
- not do anything that will cause a page fault.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a Framework device object.\r
-\r
-Return Value:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- NTSTATUS status;\r
- PFDO_DATA fdoData;\r
-\r
- UNREFERENCED_PARAMETER(Device);\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceWakeDisarmSx\n");\r
-\r
- fdoData = FdoGetData(Device);\r
-#if 0\r
- status = NICConfigureForWakeUp(fdoData, FALSE);\r
-#endif\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceWakeDisarmSx %x\n", status);\r
-\r
- return;\r
-}\r
-\r
-VOID\r
-HcaEvtDeviceWakeTriggeredS0(\r
- IN WDFDEVICE Device\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceWakeTriggeredS0 will be called whenever the device triggers its\r
- wake signal after being armed for wake from S0.\r
-\r
- This function is pageable and runs at PASSIVE_LEVEL.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a Framework device object.\r
-\r
-Return Value:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- UNREFERENCED_PARAMETER(Device);\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceWakeTriggeredS0\n");\r
-\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceWakeTriggeredS0\n");\r
-}\r
-\r
-VOID\r
-HcaEvtDeviceWakeTriggeredSx(\r
- IN WDFDEVICE Device\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- EvtDeviceWakeTriggeredSx will be called whenever the device triggers its\r
- wake signal after being armed for wake from Sx.\r
-\r
- This function is not marked pageable because this function is in the\r
- device power up path. When a function is marked pagable and the code\r
- section is paged out, it will generate a page fault which could impact\r
- the fast resume behavior because the client driver will have to wait\r
- until the system drivers can service this page fault.\r
-\r
- This function runs at PASSIVE_LEVEL, even though it is not paged. A\r
- driver can optionally make this function pageable if DO_POWER_PAGABLE\r
- is set. Even if DO_POWER_PAGABLE isn't set, this function still runs\r
- at PASSIVE_LEVEL. In this case, though, the function absolutely must\r
- not do anything that will cause a page fault.\r
-\r
-Arguments:\r
-\r
- Device - Handle to a Framework device object.\r
-\r
-Return Value:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- UNREFERENCED_PARAMETER(Device);\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaEvtDeviceWakeTriggeredSx");\r
-\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaEvtDeviceWakeTriggeredSx");\r
-\r
- return;\r
-}\r
-\r
-\r
-/*++\r
- Routine Description:\r
-\r
- This routine is used to queue workitems so that the callback\r
- functions can be executed at PASSIVE_LEVEL in the conext of\r
- a system thread.\r
-\r
-Arguments:\r
-\r
- FdoData - pointer to a device extenion.\r
-\r
- CallbackFunction - Function to invoke when at PASSIVE_LEVEL.\r
-\r
- Context1 & 2 - Meaning of the context values depends on the\r
- callback function.\r
-\r
-Return Value:\r
-\r
---*/\r
-\r
-NTSTATUS\r
-HcaQueuePassiveLevelCallback(\r
- IN PFDO_DATA FdoData,\r
- IN PFN_WDF_WORKITEM CallbackFunction,\r
- IN PVOID Context1,\r
- IN PVOID Context2 )\r
-{\r
- NTSTATUS status = STATUS_SUCCESS;\r
- PWORKER_ITEM_CONTEXT context;\r
- WDF_OBJECT_ATTRIBUTES attributes;\r
- WDF_WORKITEM_CONFIG workitemConfig;\r
- WDFWORKITEM hWorkItem;\r
-\r
- WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, WORKER_ITEM_CONTEXT);\r
-\r
- attributes.ParentObject = FdoData->WdfDevice;\r
-\r
- WDF_WORKITEM_CONFIG_INIT(&workitemConfig, CallbackFunction);\r
-\r
- status = WdfWorkItemCreate( &workitemConfig,\r
- &attributes,\r
- &hWorkItem);\r
-\r
- if (!NT_SUCCESS(status)) {\r
- return status;\r
- }\r
-\r
- context = GetWorkItemContext(hWorkItem);\r
-\r
- context->FdoData = FdoData;\r
- context->Argument1 = Context1;\r
- context->Argument2 = Context2;\r
-\r
- //\r
- // Execute this work item.\r
- //\r
- WdfWorkItemEnqueue(hWorkItem);\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-BOOLEAN\r
-HcaReadRegistryValue(\r
- __in PFDO_DATA FdoData,\r
- __in PWCHAR Name,\r
- __out PULONG Value\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Can be used to read any REG_DWORD registry value stored\r
- under Device Parameter.\r
-\r
-Arguments:\r
-\r
- FdoData - pointer to the device extension\r
- Name - Name of the registry value\r
- Value -\r
-\r
-\r
-Return Value:\r
-\r
- TRUE if successful\r
- FALSE if not present/error in reading registry\r
-\r
---*/\r
-{\r
- WDFKEY hKey = NULL;\r
- NTSTATUS status;\r
- BOOLEAN retValue = FALSE;\r
- UNICODE_STRING valueName;\r
-\r
-\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,\r
- "-->HcaReadRegistryValue \n");\r
-\r
- *Value = 0;\r
-\r
- status = WdfDeviceOpenRegistryKey(FdoData->WdfDevice,\r
- PLUGPLAY_REGKEY_DEVICE,\r
- STANDARD_RIGHTS_ALL,\r
- WDF_NO_OBJECT_ATTRIBUTES,\r
- &hKey);\r
-\r
- if (NT_SUCCESS (status)) {\r
-\r
- RtlInitUnicodeString(&valueName,Name);\r
-\r
- status = WdfRegistryQueryULong( hKey,\r
- &valueName,\r
- Value );\r
-\r
- if (NT_SUCCESS (status)) {\r
- retValue = TRUE;\r
- }\r
-\r
- WdfRegistryClose(hKey);\r
- }\r
-\r
- TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,\r
- "<--HcaReadRegistryValue %ws %d \n", Name, *Value);\r
-\r
- return retValue;\r
-}\r
-\r
-BOOLEAN\r
-HcaWriteRegistryValue(\r
- __in PFDO_DATA FdoData,\r
- __in PWCHAR Name,\r
- __in ULONG Value\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Can be used to write any REG_DWORD registry value stored\r
- under Device Parameter.\r
-\r
-Arguments:\r
-\r
-\r
-Return Value:\r
-\r
- TRUE - if write is successful\r
- FALSE - otherwise\r
-\r
---*/\r
-{\r
- WDFKEY hKey = NULL;\r
- NTSTATUS status;\r
- BOOLEAN retValue = FALSE;\r
- UNICODE_STRING valueName;\r
-\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,\r
- "Entered HcaWriteRegistryValue\n");\r
-\r
- //\r
- // write the value out to the registry\r
- //\r
- status = WdfDeviceOpenRegistryKey(FdoData->WdfDevice,\r
- PLUGPLAY_REGKEY_DEVICE,\r
- STANDARD_RIGHTS_ALL,\r
- WDF_NO_OBJECT_ATTRIBUTES,\r
- &hKey);\r
-\r
- if (NT_SUCCESS (status)) {\r
-\r
- RtlInitUnicodeString(&valueName,Name);\r
-\r
- status = WdfRegistryAssignULong (hKey,\r
- &valueName,\r
- Value );\r
-\r
- if (NT_SUCCESS (status)) {\r
- retValue = TRUE;\r
- }\r
-\r
- WdfRegistryClose(hKey);\r
- }\r
-\r
- return retValue;\r
-\r
-}\r
-\r
-#define PARAMATER_NAME_LEN 80\r
-\r
-BOOLEAN\r
-HcaReadFdoRegistryKeyValue(\r
- __in PWDFDEVICE_INIT DeviceInit,\r
- __in PWCHAR Name,\r
- __out PULONG Value\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Can be used to read any REG_DWORD registry value stored\r
- under Device Parameter.\r
-\r
-Arguments:\r
-\r
- FdoData - pointer to the device extension\r
- Name - Name of the registry value\r
- Value -\r
-\r
-\r
-Return Value:\r
-\r
- TRUE if successful\r
- FALSE if not present/error in reading registry\r
-\r
---*/\r
-{\r
- WDFKEY hKey = NULL;\r
- NTSTATUS status;\r
- BOOLEAN retValue = FALSE;\r
- UNICODE_STRING valueName;\r
-\r
- PAGED_CODE();\r
-\r
- TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP,\r
- "-->HcaReadFdoRegistryKeyValue\n");\r
-\r
- *Value = 0;\r
-\r
- status = WdfFdoInitOpenRegistryKey(DeviceInit,\r
- PLUGPLAY_REGKEY_DEVICE,\r
- STANDARD_RIGHTS_ALL,\r
- WDF_NO_OBJECT_ATTRIBUTES,\r
- &hKey);\r
-\r
- if (NT_SUCCESS (status)) {\r
-\r
- RtlInitUnicodeString(&valueName,Name);\r
-\r
- status = WdfRegistryQueryULong (hKey,\r
- &valueName,\r
- Value);\r
-\r
- if (NT_SUCCESS (status)) {\r
- retValue = TRUE;\r
- }\r
-\r
- WdfRegistryClose(hKey);\r
- }\r
-\r
- TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP,\r
- "<--HcaReadFdoRegistryKeyValue %ws %d \n",\r
- Name, *Value);\r
-\r
- return retValue;\r
-}\r
-\r
-VOID\r
-HcaEvtDriverContextCleanup(\r
- IN WDFDRIVER Driver\r
- )\r
-/*++\r
-Routine Description:\r
-\r
- Free all the resources allocated in DriverEntry.\r
-\r
-Arguments:\r
-\r
- Driver - handle to a WDF Driver object.\r
-\r
-Return Value:\r
-\r
- VOID.\r
-\r
---*/\r
-{\r
- UNREFERENCED_PARAMETER(Driver);\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,\r
- "--> HcaEvtDriverContextCleanup\n");\r
- PAGED_CODE ();\r
-\r
- // Stop WPP Tracing\r
- //\r
- WPP_CLEANUP( WdfDriverWdmGetDriverObject( Driver ) );\r
-\r
-}\r
-\r
-NTSTATUS\r
-HcaSetPowerPolicy(\r
- IN PFDO_DATA FdoData\r
- )\r
-{\r
- WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;\r
- WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;\r
- NTSTATUS status = STATUS_SUCCESS;\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "--> HcaSetPowerPolicy\n");\r
-\r
- PAGED_CODE();\r
-\r
- //\r
- // Init the idle policy structure.\r
- //\r
- WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCanWakeFromS0);\r
- idleSettings.IdleTimeout = 10000; // 10-sec\r
-\r
- status = WdfDeviceAssignS0IdleSettings(FdoData->WdfDevice, &idleSettings);\r
- if ( !NT_SUCCESS(status)) {\r
- TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
- "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n", status);\r
- return status;\r
- }\r
-\r
- //\r
- // Init wait-wake policy structure.\r
- //\r
- WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);\r
-\r
- status = WdfDeviceAssignSxWakeSettings(FdoData->WdfDevice, &wakeSettings);\r
- if (!NT_SUCCESS(status)) {\r
- TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,\r
- "WdfDeviceAssignSxWakeSettings failed %x\n", status);\r
- return status;\r
- }\r
-\r
- TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
- "<-- HcaSetPowerPolicy\n");\r
-\r
- return status;\r
-}\r
-\r
-PCHAR\r
-DbgDevicePowerString(\r
- IN WDF_POWER_DEVICE_STATE Type\r
- )\r
-/*++\r
-\r
-Updated Routine Description:\r
- DbgDevicePowerString does not change in this stage of the function driver.\r
-\r
---*/\r
-{\r
- switch (Type)\r
- {\r
- case WdfPowerDeviceInvalid:\r
- return "WdfPowerDeviceInvalid";\r
- case WdfPowerDeviceD0:\r
- return "WdfPowerDeviceD0";\r
- case PowerDeviceD1:\r
- return "WdfPowerDeviceD1";\r
- case WdfPowerDeviceD2:\r
- return "WdfPowerDeviceD2";\r
- case WdfPowerDeviceD3:\r
- return "WdfPowerDeviceD3";\r
- case WdfPowerDeviceD3Final:\r
- return "WdfPowerDeviceD3Final";\r
- case WdfPowerDevicePrepareForHibernation:\r
- return "WdfPowerDevicePrepareForHibernation";\r
- case WdfPowerDeviceMaximum:\r
- return "PowerDeviceMaximum";\r
- default:\r
- return "UnKnown Device Power State";\r
- }\r
-}\r
-\r
-\r
-#if !defined(EVENT_TRACING)\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Debug print for the sample driver.\r
-\r
-Arguments:\r
-\r
- TraceEventsLevel - print level between 0 and 3, with 3 the most verbose\r
-\r
-Return Value:\r
-\r
- None.\r
-\r
- --*/\r
-\r
-VOID\r
-TraceEvents (\r
- IN ULONG TraceEventsLevel,\r
- IN ULONG TraceEventsFlag,\r
- IN PCCHAR DebugMessage,\r
- ... )\r
- {\r
-#if 1 // always for starters... DBG\r
-\r
-#define TEMP_BUFFER_SIZE 512\r
- va_list list;\r
- CHAR debugMessageBuffer[TEMP_BUFFER_SIZE];\r
- NTSTATUS status;\r
-\r
- va_start(list, DebugMessage);\r
-\r
- if (DebugMessage) {\r
-\r
- //\r
- // Using new safe string functions instead of _vsnprintf.\r
- // This function takes care of NULL terminating if the message\r
- // is longer than the buffer.\r
- //\r
- status = RtlStringCbVPrintfA( debugMessageBuffer,\r
- sizeof(debugMessageBuffer),\r
- DebugMessage,\r
- list );\r
- if(!NT_SUCCESS(status)) {\r
-\r
- DbgPrint (_DRIVER_NAME_": RtlStringCbVPrintfA failed %x\n",\r
- status);\r
- return;\r
- }\r
- if (TraceEventsLevel <= TRACE_LEVEL_INFORMATION ||\r
- (TraceEventsLevel <= g_mthca_dbg_level &&\r
- ((TraceEventsFlag & g_mthca_dbg_flags) == TraceEventsFlag))) {\r
- DbgPrint(debugMessageBuffer);\r
- }\r
- }\r
- va_end(list);\r
-\r
- return;\r
-#else\r
- UNREFERENCED_PARAMETER(TraceEventsLevel);\r
- UNREFERENCED_PARAMETER(TraceEventsFlag);\r
- UNREFERENCED_PARAMETER(DebugMessage);\r
-#endif\r
-}\r
-\r
-#endif\r
-\r
+++ /dev/null
-/*++\r
- Copyright (c) Microsoft Corporation. All rights reserved.\r
-\r
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY\r
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\r
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR\r
- PURPOSE.\r
-\r
-Module Name:\r
-\r
- public.h\r
-\r
-Abstract:\r
-\r
- This module contains the common declarations shared by driver\r
- and user applications.\r
-\r
-Environment:\r
-\r
- user and kernel\r
-\r
---*/\r
-\r
-//\r
-// Define an Interface Guid for toaster device class.\r
-// This GUID is used to register (IoRegisterDeviceInterface)\r
-// an instance of an interface so that user application\r
-// can control the toaster device.\r
-//\r
-\r
-DEFINE_GUID (GUID_DEVINTERFACE_RDMA_IO,\r
- 0xb74cfec2, 0x9366, 0x454a, 0xba, 0x71, 0x7c, 0x27, 0xb5, 0x14, 0x70, 0xa4);\r
-// {B74CFEC2-9366-454a-BA71-7C27B51470A4}\r
-\r
-//\r
-// Define a WMI GUID to get toaster device info.\r
-//\r
-\r
-DEFINE_GUID (PCIDRV_WMI_STD_DATA_GUID,\r
- 0x20e35e40, 0x7179, 0x4f89, 0xa2, 0x8c, 0x12, 0xed, 0x5a, 0x3c, 0xaa, 0xa5);\r
-\r
-// {20E35E40-7179-4f89-A28C-12ED5A3CAAA5}\r
-\r
-//\r
-// GUID definition are required to be outside of header inclusion pragma to avoid\r
-// error during precompiled headers.\r
-//\r
-\r
\r
--*/\r
\r
+#if !defined(__TRACE_H__)\r
+#define __TRACE_H__ 1\r
+\r
#include <evntrace.h> // For TRACE_LEVEL definitions\r
\r
#if !defined(EVENT_TRACING)\r
\r
#endif\r
\r
+#endif /* !defined(__TRACE_H__) */\r
\r
--*/\r
\r
\r
-#include "precomp.h"\r
+#include "hca_driver.h"\r
+\r
+#include <wmilib.h>\r
+#include <wmistr.h>\r
+\r
+#include "mthca_public.h"\r
+#include "mthcaMof.h"\r
\r
#if defined(EVENT_TRACING)\r
#include "wmi.tmh"\r
#endif\r
\r
+#define MOFRESOURCENAME L"mthcaWMI"\r
+\r
+#define MthcaDeviceInformation_SIZE FIELD_OFFSET(MthcaDeviceInformation, VariableData)\r
+\r
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MthcaDeviceInformation, mthcaWmiGetData)\r
\r
-#define MOFRESOURCENAME L"PciDrvWMI"\r
\r
NTSTATUS\r
EvtWmiDeviceInfoQueryInstance(\r
__in_bcount(InBufferSize) PVOID InBuffer\r
);\r
\r
+NTSTATUS\r
+HcaWmiRegistration( WDFDEVICE Device );\r
+\r
+\r
#ifdef ALLOC_PRAGMA\r
-#pragma alloc_text(PAGE, PciDrvWmiRegistration)\r
#pragma alloc_text(PAGE, EvtWmiDeviceInfoQueryInstance)\r
#pragma alloc_text(PAGE, EvtWmiDeviceInfoSetInstance)\r
+#pragma alloc_text(PAGE, HcaWmiRegistration)\r
#endif\r
\r
-NTSTATUS\r
-PciDrvWmiRegistration(\r
- WDFDEVICE Device\r
- )\r
+\r
/*++\r
Routine Description\r
\r
instance of the device\r
\r
--*/\r
+\r
+NTSTATUS\r
+HcaWmiRegistration( WDFDEVICE Device )\r
{\r
WDF_WMI_PROVIDER_CONFIG providerConfig;\r
WDF_WMI_INSTANCE_CONFIG instanceConfig;\r
return status;\r
}\r
\r
- WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &PCIDRV_WMI_STD_DATA_GUID);\r
- providerConfig.MinInstanceBufferSize = sizeof(PCIDRV_WMI_STD_DATA);\r
+ WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &MTHCA_WMI_STD_DATA_GUID);\r
+ providerConfig.MinInstanceBufferSize = sizeof(MTHCA_WMI_STD_DATA);\r
\r
WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig);\r
instanceConfig.Register = TRUE;\r
__in WDFWMIINSTANCE WmiInstance,\r
__in ULONG OutBufferSize,\r
__out_bcount_part(OutBufferSize, *BufferUsed) PVOID OutBuffer,\r
- __out PULONG BufferUsed\r
- )\r
+ __out PULONG BufferUsed )\r
{\r
PFDO_DATA fdoData;\r
\r
\r
fdoData = FdoGetData(WdfWmiInstanceGetDevice(WmiInstance));\r
\r
- //\r
- // No need to check OutBufferSize since MinInstanceBufferSize was set when we\r
- // created the instance\r
- //\r
- RtlZeroMemory(OutBuffer, OutBufferSize);\r
- RtlCopyMemory(OutBuffer, fdoData->CurrentAddress, sizeof(fdoData->CurrentAddress));\r
+ // Since the minimum buffer size required for querying the instance data wa\r
+ // already specified during the WMI instance setup, the Framework will make\r
+ // sure that the incoming buffer size is large enough for this instance\r
+ // query. There is no need to check the size of the given buffer again.\r
+ // The instance information can be copied directly to the given buffer.\r
\r
- *BufferUsed = sizeof(fdoData->CurrentAddress);\r
+ RtlZeroMemory(OutBuffer, OutBufferSize);\r
+ RtlCopyMemory(OutBuffer,\r
+ mthcaWmiGetData(WmiInstance),\r
+ MthcaDeviceInformation_SIZE);\r
+ *BufferUsed = MthcaDeviceInformation_SIZE;\r
\r
return STATUS_SUCCESS;\r
}\r
fdoData = FdoGetData(WdfWmiInstanceGetDevice(WmiInstance));\r
\r
//\r
- // No need to check InBufferSize since MinInstanceBufferSize was set when we\r
- // created the instance\r
+ // We will update only writable elements.\r
//\r
- ASSERT(InBufferSize >= sizeof(fdoData->CurrentAddress));\r
+ g_mthca_dbg_level = mthcaWmiGetData(WmiInstance)->DebugPrintLevel =\r
+ ((PMthcaDeviceInformation)InBuffer)->DebugPrintLevel;\r
+\r
+ g_mthca_dbg_flags = mthcaWmiGetData(WmiInstance)->DebugPrintFlags =\r
+ ((PMthcaDeviceInformation)InBuffer)->DebugPrintLevel;\r
\r
- RtlCopyMemory(fdoData->CurrentAddress, InBuffer, sizeof(fdoData->CurrentAddress));\r
\r
return STATUS_SUCCESS;\r
}\r