199 lines
4.1 KiB
C
199 lines
4.1 KiB
C
/*++
|
||
|
||
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) {
|
||
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;
|
||
}
|