?? pcie.c
字號:
/*++
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:
Pci9656.c
Abstract:
This is a generic WDF sample driver for PCIE PCI9656RDK-Lite reference
adapter. It illustrates how to use the WDF DmaObject to perform
Scatter/Gather DMA operations.
Environment:
Kernel mode
--*/
#include "precomp.h"
//
// 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 by the WPP preprocessor.
//
#include "PCIE.tmh"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, PCIEEvtDeviceAdd)
#pragma alloc_text (PAGE, PCIEEvtDevicePrepareHardware)
#pragma alloc_text (PAGE, PCIEEvtDeviceReleaseHardware)
#pragma alloc_text (PAGE, PCIEEvtDeviceD0Exit)
#pragma alloc_text (PAGE, PCIEEvtDriverContextCleanup)
#pragma alloc_text (PAGE, PCIESetIdleAndWakeSettings)
#endif
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
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:
NTSTATUS - if the status value is not STATUS_SUCCESS,
the driver will get unloaded immediately.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
WDF_DRIVER_CONFIG config;
WDF_OBJECT_ATTRIBUTES attributes;
//
// Initialize WDF WPP tracing.
//
WPP_INIT_TRACING( DriverObject, RegistryPath );
//
// TraceEvents function is mapped to DoTraceMessage provided by
// WPP by using a directive in the sources file.
//
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
"PCI Express Sample - Driver Framework Edition.");
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
"Built %s %s", __DATE__, __TIME__);
//
// Initialize the Driver Config structure.
//
WDF_DRIVER_CONFIG_INIT( &config, PCIEEvtDeviceAdd );
//
// Register a cleanup callback so that we can call WPP_CLEANUP when
// the framework driver object is deleted during driver unload.
//
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.EvtCleanupCallback = PCIEEvtDriverContextCleanup;
status = WdfDriverCreate( DriverObject,
RegistryPath,
&attributes,
&config,
WDF_NO_HANDLE);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
"WdfDriverCreate failed with status %!STATUS!", 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.
//
WPP_CLEANUP(DriverObject);
}
return status;
}
NTSTATUS
PCIEEvtDeviceAdd(
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, "--> PCIEEvtDeviceAdd");
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 = PCIEEvtDevicePrepareHardware;
pnpPowerCallbacks.EvtDeviceReleaseHardware = PCIEEvtDeviceReleaseHardware;
//
// 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 = PCIEEvtDeviceD0Entry;
pnpPowerCallbacks.EvtDeviceD0Exit = PCIEEvtDeviceD0Exit;
//
// 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. PCIEGetDeviceContext 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 = PCIEGetDeviceContext(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_PCIE_INTERFACE,
NULL );
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
"<-- DeviceCreateDeviceInterface "
"failed %!STATUS!", status);
KdPrint( ("PCIE: driverentry - step 19: status = %x", status) );
return status;
}
//
// Set the idle and wait-wake policy for this device.
//
status = PCIESetIdleAndWakeSettings(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 = PCIEInitializeDeviceExtension(devExt);
if (!NT_SUCCESS(status)) {
return status;
}
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
"<-- PCIEEvtDeviceAdd %!STATUS!", status);
return status;
}
NTSTATUS
PCIEEvtDevicePrepareHardware (
WDFDEVICE Device,
WDFCMRESLIST Resources,
WDFCMRESLIST ResourcesTranslated
)
/*++
Routine Description:
Performs whatever initialization is needed to setup the device, setting up
a DMA channel or mapping any I/O port resources. This will only be called
as a device starts or restarts, not every time the device moves into the D0
state. Consequently, most hardware initialization belongs elsewhere.
Arguments:
Device - A handle to the WDFDEVICE
Resources - The raw PnP resources associated with the device. Most of the
time, these aren't useful for a PCI device.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -