📄 d12.c
字号:
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
D12.c
Abstract:
USB device driver for Philips D12 USB test board
Environment:
kernel mode only
Notes:
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.
Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
Revision History:
5-4-96 : created
--*/
#define DRIVER
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "D12.h"
#include "d12irp.h"
#include "guid829.h"
//
// Global pointer to Driver Object
//
PDRIVER_OBJECT D12_DriverObject;
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
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 ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
D12_KdPrint (("D12TEST.SYS: entering (D12) DriverEntry\n"));
D12_DriverObject = DriverObject;
//
// Create dispatch points for device control, create, close.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] = D12_Create;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = D12_Close;
DriverObject->DriverUnload = D12_Unload;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = D12_ProcessIOCTL;
DriverObject->MajorFunction[IRP_MJ_WRITE] = D12_Write;
DriverObject->MajorFunction[IRP_MJ_READ] = D12_Read;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] =
DriverObject->MajorFunction[IRP_MJ_PNP] = D12_Dispatch;
DriverObject->MajorFunction[IRP_MJ_POWER] = D12_ProcessPowerIrp;
DriverObject->DriverExtension->AddDevice = D12_PnPAddDevice;
D12_KdPrint (("D12TEST.SYS: exiting (D12) DriverEntry (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
D12_PoRequestCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
This routine is called when the port driver completes an IRP.
Arguments:
DeviceObject - Pointer to the device object for the class device.
Context - Driver defined context.
Return Value:
The function value is the final status from the operation.
--*/
{
PIRP irp;
PDEVICE_EXTENSION deviceExtension;
PDEVICE_OBJECT deviceObject = Context;
NTSTATUS ntStatus;
deviceExtension = deviceObject->DeviceExtension;
irp = deviceExtension->PowerIrp;
ntStatus = IoStatus->Status;
D12_KdPrint(("'D12_PoRequestCompletion\n"));
IoCopyCurrentIrpStackLocationToNext(irp);
PoStartNextPowerIrp(irp);
PoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
D12_DecrementIoCount(deviceObject);
return ntStatus;
}
NTSTATUS
D12_PowerIrp_Complete(
IN PDEVICE_OBJECT NullDeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This routine is called when the port driver completes an IRP.
Arguments:
DeviceObject - Pointer to the device object for the class device.
Irp - Irp completed.
Context - Driver defined context.
Return Value:
The function value is the final status from the operation.
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
D12_KdPrint(("D12TEST.SYS: enter D12_PowerIrp_Complete\n"));
deviceObject = (PDEVICE_OBJECT) Context;
deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
// BUGBUG
// kenray sez we should be calling IoMarkIrpPending
// from our completion routine.
//
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
ASSERT(irpStack->MajorFunction == IRP_MJ_POWER);
ASSERT(irpStack->MinorFunction == IRP_MN_SET_POWER);
ASSERT(irpStack->Parameters.Power.Type==DevicePowerState);
ASSERT(irpStack->Parameters.Power.State.DeviceState==PowerDeviceD0);
deviceExtension->CurrentDevicePowerState = PowerDeviceD0;
KdPrint(("D12TEST.SYS: enter D0 complete\n"));
Irp->IoStatus.Status = ntStatus;
D12_DecrementIoCount(deviceObject);
return ntStatus;
}
NTSTATUS
D12_SetDevicePowerState(
IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_POWER_STATE DeviceState,
IN PBOOLEAN HookIt
)
/*++
Routine Description:
Arguments:
DeviceObject - Pointer to the device object for the class device.
Irp - Irp completed.
DeviceState - Device specific power state to set the device in to.
Return Value:
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
switch (DeviceState) {
case PowerDeviceD3:
//
// device will be going OFF, save any state now.
//
D12_KdPrint(("D12TEST.SYS: PowerDeviceD3 (OFF)\n"));
KdPrint(("D12: PM power off\n"));
deviceExtension->CurrentDevicePowerState = DeviceState;
break;
case PowerDeviceD1:
case PowerDeviceD2:
//
// power states D1,D2 translate to USB suspend
D12_KdPrint(("D12TEST.SYS: PowerDeviceD1/D2 (SUSPEND)\n"));
KdPrint(("D12: device entered D%d\n", DeviceState-1));
deviceExtension->CurrentDevicePowerState = DeviceState;
break;
case PowerDeviceD0:
D12_KdPrint(("D12TEST.SYS: PowerDeviceD0 (ON)\n"));
//
// finish the rest in the completion routine
//
*HookIt = TRUE;
// pass on to PDO
break;
default:
D12_KdPrint(("D12TEST.SYS: Bogus DeviceState = %x\n", DeviceState));
}
return ntStatus;
}
NTSTATUS
D12_DeferIrpCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This routine is called when the port driver completes an IRP.
Arguments:
DeviceObject - Pointer to the device object for the class device.
Irp - Irp completed.
Context - Driver defined context.
Return Value:
The function value is the final status from the operation.
--*/
{
PKEVENT event = Context;
KeSetEvent(event,
1,
FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
D12_QueryCapabilities(
IN PDEVICE_OBJECT PdoDeviceObject,
IN PDEVICE_CAPABILITIES DeviceCapabilities
)
/*++
Routine Description:
This routine reads or write config space.
Arguments:
DeviceObject - Physical DeviceObject for this USB controller.
Return Value:
None.
--*/
{
PIO_STACK_LOCATION nextStack;
PIRP irp;
NTSTATUS ntStatus;
KEVENT event;
PAGED_CODE();
irp = IoAllocateIrp(PdoDeviceObject->StackSize, FALSE);
if (!irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
nextStack = IoGetNextIrpStackLocation(irp);
ASSERT(nextStack != NULL);
nextStack->MajorFunction= IRP_MJ_PNP;
nextStack->MinorFunction= IRP_MN_QUERY_CAPABILITIES;
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine(irp,
D12_DeferIrpCompletion,
&event,
TRUE,
TRUE,
TRUE);
//BUGBUG this is different from the latest version of busdd.doc
nextStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
ntStatus = IoCallDriver(PdoDeviceObject,
irp);
D12_KdPrint(("D12TEST.SYS: ntStatus from IoCallDriver to PCI = 0x%x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
// wait for irp to complete
TRAP(); // first time we hit this
KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
}
#if DBG
if (!NT_SUCCESS(ntStatus)) {
// failed? this is probably a bug
D12_KdPrint(("D12TEST.SYS: QueryCapabilities failed, why?\n"));
}
#endif
IoFreeIrp(irp);
return STATUS_SUCCESS;
}
NTSTATUS
D12_ProcessPowerIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Process the Power IRPs sent to the PDO for this device.
Arguments:
DeviceObject - pointer to a hcd device object (FDO)
Irp - pointer to an I/O Request Packet
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
BOOLEAN hookIt = FALSE;
D12_KdPrint(("D12TEST.SYS: IRP_MJ_POWER\n"));
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation (Irp);
D12_IncrementIoCount(DeviceObject);
switch (irpStack->MinorFunction) {
case IRP_MN_WAIT_WAKE:
D12_KdPrint(("D12TEST.SYS: IRP_MN_WAIT_WAKE\n"));
//
// someone is enabling us for wakeup
//
TRAP(); // never seen this before?
// pass this on to our PDO
break;
case IRP_MN_SET_POWER:
{
switch (irpStack->Parameters.Power.Type) {
case SystemPowerState:
//
// find the device power state equivalent to the given system state
//
{
POWER_STATE powerState;
D12_KdPrint(("D12TEST.SYS: Set Power, SystemPowerState (%d)\n",
irpStack->Parameters.Power.State.SystemState));
if (irpStack->Parameters.Power.State.SystemState ==
PowerSystemWorking) {
powerState.DeviceState = PowerDeviceD0;
} else if (/* deviceExtension->EnabledForWakeup*/FALSE) {
// BUGBUG for now act as if we are always enabled for wakeup
D12_KdPrint(("D12TEST.SYS: D12 always enabled for wakeup\n"));
powerState.DeviceState =
deviceExtension->DeviceCapabilities.DeviceState[
irpStack->Parameters.Power.State.SystemState];
} else {
//
// wakeup not enabled, just go in to the 'OFF' state.
//
powerState.DeviceState = PowerDeviceD3;
} //irpStack->Parameters.Power.State.SystemState
//
// are we already in this state?
//
if (powerState.DeviceState !=
deviceExtension->CurrentDevicePowerState) {
// No,
// request that we be put into this state
deviceExtension->PowerIrp = Irp;
ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
IRP_MN_SET_POWER,
powerState,
D12_PoRequestCompletion,
DeviceObject,
NULL);
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -