windows-nt/Source/XPSP1/NT/base/busdrv/pci/usage.c

199 lines
4.1 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}