DeviceAdd例程:PnP管理器调用AddDevice时框架调用。它要 创建设备对象,一个或多个IO队列和设备GUID接口等。驱动此时注册各种即插即用、电源管理例程以及各种回调函数。驱动此时可以查询任何接口或者获取总线驱动的配置空间信息,但是不能访问硬件的寄存器以及初始化设备。
PCI
NTSTATUS
PLxEvtDeviceAdd(
IN WDFDRIVER Driver,
IN PWDFDEVICE_INIT DeviceInit
)
/*++
Routine Description:
EvtDeviceAdd is called by the framework in response to AddDevice
call from the PnP manager. Here the driver should register all the
PNP, power and Io callbacks, register interfaces and allocate other
software resources required by the device. The driver can query
any interfaces or get the config space information from the bus driver
but cannot access hardware registers or initialize the device.
Arguments:
Return Value:
--*/
{
NTSTATUS status = STATUS_SUCCESS;
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDF_OBJECT_ATTRIBUTES attributes;
WDFDEVICE device;
PDEVICE_EXTENSION devExt = NULL;
UNREFERENCED_PARAMETER( Driver );
// TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> PLxEvtDeviceAdd");
PAGED_CODE();
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.
//
pnpPowerCallbacks.EvtDevicePrepareHardware = PLxEvtDevicePrepareHardware;
pnpPowerCallbacks.EvtDeviceReleaseHardware = PLxEvtDeviceReleaseHardware;
//
// 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 = PLxEvtDeviceD0Entry;
pnpPowerCallbacks.EvtDeviceD0Exit = PLxEvtDeviceD0Exit;
//
// Register the PnP Callbacks..
//
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
//
// Initialize Fdo Attributes.
//
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION);
//
// By opting for SynchronizationScopeDevice, we tell the framework to
// synchronize callbacks events of all the objects directly associated
// with the device. In this driver, we will associate queues and
// and DpcForIsr. By doing that we don't have to worrry about synchronizing
// access to device-context by Io Events and DpcForIsr because they would
// not concurrently ever. Framework will serialize them by using an
// internal device-lock.
//
attributes.SynchronizationScope = WdfSynchronizationScopeDevice;
//
// Create the device
//
status = WdfDeviceCreate( &DeviceInit, &attributes, &device );
if (!NT_SUCCESS(status)) {
//
// Device Initialization failed.
//
/* TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
"DeviceCreate failed %!STATUS!", status);*/
return status;
}
//
// Get the DeviceExtension and initialize it. PLxGetDeviceContext is an inline function
// defined by WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro in the
// private header file. This function will do the type checking and return
// the device context. If you pass a wrong object a wrong object handle
// it will return NULL and assert if run under framework verifier mode.
//
devExt = PLxGetDeviceContext(device);
devExt->Device = device;
/* TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
" AddDevice PDO (0x%p) FDO (0x%p), DevExt (0x%p)",
WdfDeviceWdmGetPhysicalDevice(device),
WdfDeviceWdmGetDeviceObject(device), devExt);*/
//
// Tell the Framework that this device will need an interface
//
// NOTE: See the note in Public.h concerning this GUID value.
//
status = WdfDeviceCreateDeviceInterface( device,
(LPGUID) &GUID_PLX_INTERFACE,
NULL );
if (!NT_SUCCESS(status)) {
/* TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
"<-- DeviceCreateDeviceInterface "
"failed %!STATUS!", status);*/
return status;
}
//
// Set the idle and wait-wake policy for this device.
//
status = PLxSetIdleAndWakeSettings(devExt);
if (!NT_SUCCESS (status)) {
//
// NOTE: The attempt to set the Idle and Wake options
// is a best-effort try. Failure is probably due to
// the non-driver environmentals, such as the system,
// bus or OS indicating that Wake is not supported for
// this case.
// All that being said, it probably not desirable to
// return the failure code as it would cause the
// AddDevice to fail and Idle and Wake are probably not
// "must-have" options.
//
// You must decide for your case whether Idle/Wake are
// "must-have" options...but my guess is probably not.
//
#if 1
status = STATUS_SUCCESS;
#else
return status;
#endif
}
//
// Initalize the Device Extension.
//
status = PLxInitializeDeviceExtension(devExt);
if (!NT_SUCCESS(status)) {
return status;
}
/*TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
"<-- PLxEvtDeviceAdd %!STATUS!", status);
*/
return status;
}
USB
NTSTATUS
UsbSamp_EvtDeviceAdd(
WDFDRIVER Driver,
PWDFDEVICE_INIT DeviceInit
)
/*++
Routine Description:
EvtDeviceAdd is called by the framework in response to AddDevice
call from the PnP manager. We create and initialize a device object to
represent a new instance of the device. All the software resources
should be allocated in this callback.
Arguments:
Driver - Handle to a framework driver object created in DriverEntry
DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
Return Value:
NTSTATUS
--*/
{
WDF_FILEOBJECT_CONFIG fileConfig;
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDF_OBJECT_ATTRIBUTES attributes;
NTSTATUS status;
WDFDEVICE device;
WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
WDF_IO_QUEUE_CONFIG ioQueueConfig;
PDEVICE_CONTEXT pDevContext;
WDFQUEUE queue;
ULONG maximumTransferSize;
UNREFERENCED_PARAMETER(Driver);
UsbSamp_DbgPrint (3, ("UsbSamp_EvtDeviceAdd routine\n"));
PAGED_CODE();
//
// Initialize the pnpPowerCallbacks structure. Callback events for PNP
// and Power are specified here. If you don't supply any callbacks,
// the Framework will take appropriate default actions based on whe