/*++
Copyright (c) 1991, 1992, 1993 - 1997 Microsoft Corporation
Module Name:
pnp.c
Abstract:
This module contains the code that handles the plug and play
IRPs for the serial driver.
Environment:
Kernel mode
--*/
#include "precomp.h"
#include <initguid.h>
#include <ntddser.h>
#include <stdlib.h>
#if defined(EVENT_TRACING)
#include "pnp.tmh"
#endif
static const PHYSICAL_ADDRESS SerialPhysicalZero = {0};
static const SUPPORTED_BAUD_RATES SupportedBaudRates[] = {
{75, SERIAL_BAUD_075},
{110, SERIAL_BAUD_110},
{135, SERIAL_BAUD_134_5},
{150, SERIAL_BAUD_150},
{300, SERIAL_BAUD_300},
{600, SERIAL_BAUD_600},
{1200, SERIAL_BAUD_1200},
{1800, SERIAL_BAUD_1800},
{2400, SERIAL_BAUD_2400},
{4800, SERIAL_BAUD_4800},
{7200, SERIAL_BAUD_7200},
{9600, SERIAL_BAUD_9600},
{14400, SERIAL_BAUD_14400},
{19200, SERIAL_BAUD_19200},
{38400, SERIAL_BAUD_38400},
{56000, SERIAL_BAUD_56K},
{57600, SERIAL_BAUD_57600},
{115200, SERIAL_BAUD_115200},
{128000, SERIAL_BAUD_128K},
{SERIAL_BAUD_INVALID, SERIAL_BAUD_USER}
};
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGESRP0, SerialEvtDeviceAdd)
#pragma alloc_text(PAGESRP0, SerialEvtPrepareHardware)
#pragma alloc_text(PAGESRP0, SerialEvtReleaseHardware)
#pragma alloc_text(PAGESRP0, SerialEvtDeviceD0ExitPreInterruptsDisabled)
#pragma alloc_text(PAGESRP0, SerialMapHWResources)
#pragma alloc_text(PAGESRP0, SerialUnmapHWResources)
#pragma alloc_text(PAGESRP0, SerialEvtDeviceContextCleanup)
#pragma alloc_text(PAGESRP0, SerialDoExternalNaming)
#pragma alloc_text(PAGESRP0, SerialReportMaxBaudRate)
#pragma alloc_text(PAGESRP0, SerialUndoExternalNaming)
#pragma alloc_text(PAGESRP0, SerialInitController)
#pragma alloc_text(PAGESRP0, SerialGetMappedAddress)
#pragma alloc_text(PAGESRP0, SerialSetPowerPolicy)
#pragma alloc_text(PAGESRP0, SerialReadSymName)
#endif // ALLOC_PRAGMA
NTSTATUS
SerialEvtDeviceAdd(
IN WDFDRIVER Driver,
IN PWDFDEVICE_INIT DeviceInit
)
/*++
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 status;
PSERIAL_DEVICE_EXTENSION pDevExt;
static ULONG currentInstance = 0;
WDF_FILEOBJECT_CONFIG fileobjectConfig;
WDFDEVICE device;
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_IO_QUEUE_CONFIG queueConfig;
WDFQUEUE defaultqueue;
ULONG isMulti;
PULONG countSoFar;
WDF_INTERRUPT_CONFIG interruptConfig;
PSERIAL_INTERRUPT_CONTEXT interruptContext;
ULONG relinquishPowerPolicy;
DECLARE_UNICODE_STRING_SIZE(deviceName, DEVICE_OBJECT_NAME_LENGTH);
PAGED_CODE();
SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "-->SerialEvtDeviceAdd\n");
status = RtlUnicodeStringPrintf(&deviceName, L"%ws%d",
L"\\Device\\Serial",
currentInstance++);
if (!NT_SUCCESS(status)) {
return status;
}
status = WdfDeviceInitAssignName(DeviceInit,& deviceName);
if (!NT_SUCCESS(status)) {
return status;
}
WdfDeviceInitSetExclusive(DeviceInit, TRUE);
WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_SERIAL_PORT);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT);
WdfDeviceInitSetRequestAttributes(DeviceInit, &attributes);
//
// 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. These next two callbacks set up and tear down hardware state,
// specifically that which only has to be done once.
//
pnpPowerCallbacks.EvtDevicePrepareHardware = SerialEvtPrepareHardware;
pnpPowerCallbacks.EvtDeviceReleaseHardware = SerialEvtReleaseHardware;
//
// 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 = SerialEvtDeviceD0Entry;
pnpPowerCallbacks.EvtDeviceD0Exit = SerialEvtDeviceD0Exit;
//
// Specify the callback for monitoring when the device's interrupt are
// enabled or about to be disabled.
//
pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = SerialEvtDeviceD0EntryPostInterruptsEnabled;
pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = SerialEvtDeviceD0ExitPreInterruptsDisabled;
//
// Register the PnP and power callbacks.
//
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
if ( !NT_SUCCESS(status)) {
SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP,
"WdfDeviceInitSetPnpPowerEventCallbacks failed %!STATUS!\n",
status);
return status;
}
//
// Find out if we own power policy
//
SerialGetFdoRegistryKeyValue( DeviceInit,
L"SerialRelinquishPowerPolicy",
&relinquishPowerPolicy );
if(relinquishPowerPolicy) {
//
// FDO's are assumed to be power policy owner by default. So tell
// the framework explicitly to relinquish the power policy ownership.
//
SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP,
"RelinquishPowerPolicy due to registry settings\n");
WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE);
}
//
// For Windows XP and below, we will register for the WDM Preprocess callback
// for IRP_MJ_CREATE. This is done because, the Serenum filter doesn't handle
// creates that are marked pending. Since framework always marks the IRP pending,
// we are registering this WDM preprocess handler so that we can bypass the
// framework and handle the create and close ourself. This workaround is need
// only if you intend to install the Serenum as an upper filter.
//
if (RtlIsNtDdiVersionAvailable(NTDDI_VISTA) == FALSE) {
status = WdfDeviceInitAssignWdmIrpPreprocessCallback(
DeviceInit,
SerialWdmDeviceFileCreate,
IRP_MJ_CREATE,
NULL, // pointer minor function table
0); // number of entries in the table
if (!NT_SUCCESS(status)) {
SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP,
"WdfDeviceInitAssignWdmIrpPreprocessCallback failed %!STATUS!\n",
status);
return status;
}
status = WdfDeviceInitAssignWdmIrpPreprocessCallback(
DeviceInit,
SerialWdmFileClose,
IRP_MJ_CLOSE,
NULL, // pointer minor function table
0); /
- 1
- 2
前往页