You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
4.3 KiB
198 lines
4.3 KiB
/*++
|
|
|
|
Copyright (c) 1996-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dispatch.c
|
|
|
|
Abstract:
|
|
|
|
This module contains dispatch code for PCI.SYS.
|
|
|
|
Author:
|
|
|
|
Ken Reneris (kenr) 4-Dec-1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "pcip.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, PciLocalDeviceUsage)
|
|
#pragma alloc_text(PAGE, PciPdoDeviceUsage)
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
PciLocalDeviceUsage (
|
|
IN PPCI_POWER_STATE PowerState,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION irpSp;
|
|
PLONG Addend;
|
|
LONG Increment;
|
|
LONG Junk;
|
|
|
|
PAGED_CODE();
|
|
|
|
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
Increment = irpSp->Parameters.UsageNotification.InPath ? 1 : -1;
|
|
switch (irpSp->Parameters.UsageNotification.Type) {
|
|
case DeviceUsageTypePaging: Addend = &PowerState->Paging; break;
|
|
case DeviceUsageTypeHibernation: Addend = &PowerState->Hibernate; break;
|
|
case DeviceUsageTypeDumpFile: Addend = &PowerState->CrashDump; break;
|
|
default:
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
Junk = InterlockedExchangeAdd (Addend, Increment);
|
|
|
|
#if DBG
|
|
|
|
if (Increment == -1) {
|
|
PCI_ASSERT(Junk > 0);
|
|
}
|
|
|
|
#endif
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PciPdoDeviceUsage (
|
|
IN PPCI_PDO_EXTENSION pdoExtension,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PDEVICE_OBJECT ParentFdo;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
PIO_STACK_LOCATION NewIrpSp;
|
|
PIRP NewIrp;
|
|
KEVENT Event;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
IO_STATUS_BLOCK LocalIoStatus;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Do we have a parent that we must notify?
|
|
//
|
|
if (pdoExtension->ParentFdoExtension != NULL &&
|
|
pdoExtension->ParentFdoExtension->PhysicalDeviceObject != NULL) {
|
|
|
|
//
|
|
// Get a referenced object to the parent
|
|
//
|
|
ParentFdo = IoGetAttachedDeviceReference(
|
|
pdoExtension->ParentFdoExtension->PhysicalDeviceObject
|
|
);
|
|
if (ParentFdo == NULL) {
|
|
|
|
Status = STATUS_NO_SUCH_DEVICE;
|
|
goto PciPdoDeviceUsageExit;
|
|
|
|
}
|
|
|
|
//
|
|
// Initialize the event to wait on
|
|
//
|
|
KeInitializeEvent( &Event, SynchronizationEvent, FALSE );
|
|
|
|
//
|
|
// Build an Irp
|
|
//
|
|
NewIrp = IoBuildSynchronousFsdRequest(
|
|
IRP_MJ_PNP,
|
|
ParentFdo,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
&Event,
|
|
&LocalIoStatus
|
|
);
|
|
if (NewIrp == NULL) {
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
ObDereferenceObject( ParentFdo );
|
|
goto PciPdoDeviceUsageExit;
|
|
|
|
}
|
|
|
|
//
|
|
// Get the top of the stacks
|
|
//
|
|
NewIrpSp = IoGetNextIrpStackLocation( NewIrp );
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
//
|
|
// Set the top of stack
|
|
//
|
|
*NewIrpSp = *IrpSp;
|
|
|
|
//
|
|
// Clear any completion routines from the new stack
|
|
//
|
|
IoSetCompletionRoutine(
|
|
NewIrp,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
FALSE,
|
|
FALSE
|
|
);
|
|
|
|
NewIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
//
|
|
// Send the request down
|
|
//
|
|
Status = IoCallDriver( ParentFdo, NewIrp );
|
|
if (Status == STATUS_PENDING) {
|
|
|
|
//
|
|
// Wait for the request to be done
|
|
//
|
|
KeWaitForSingleObject(
|
|
&Event,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL
|
|
);
|
|
Status = LocalIoStatus.Status;
|
|
|
|
}
|
|
|
|
//
|
|
// Deference the target
|
|
//
|
|
ObDereferenceObject( ParentFdo );
|
|
|
|
}
|
|
|
|
|
|
PciPdoDeviceUsageExit:
|
|
|
|
//
|
|
// If we succeeded, then apply the usages locally
|
|
//
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// Apply the usage locally
|
|
//
|
|
|
|
Status = PciLocalDeviceUsage(&pdoExtension->PowerState, Irp);
|
|
|
|
}
|
|
|
|
//
|
|
// Done
|
|
//
|
|
return Status;
|
|
}
|