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