summaryrefslogblamecommitdiffstats
path: root/private/ntos/po/misc.c
blob: 1f5d75283c170c97dbdd615f4fdda2bf00b6a439 (plain) (tree)





















































































































































































































































































                                                                                        
/*++

Copyright (c) 1990  Microsoft Corporation

Module Name:

    misc.c

Abstract:

    This module implements the power management

Author:

    Ken Reneris (kenr) 19-July-1994

Revision History:

--*/


#include "pop.h"


#ifdef ALLOC_PRAGMA

#ifdef _PNP_POWER_
#pragma alloc_text(PAGE,PoInitializeDeviceObject)
#endif

#pragma alloc_text(PAGE,PoSetPowerManagementEnable)
#endif

#ifdef _PNP_POWER_

VOID
PoInitializeDeviceObject (
    IN PDEVICE_OBJECT   DeviceObject
    )
{
    PDEVOBJ_EXTENSION       DeviceObjectExt;

    DeviceObjectExt = DeviceObject->DeviceObjectExtension;
    DeviceObjectExt->CurrentPowerState = PowerUp;
    DeviceObjectExt->PendingPowerState = PowerUp;
    DeviceObjectExt->PowerControlNeeded = TRUE;
    DeviceObjectExt->UseAsyncPowerUp    = TRUE;

    KeInitializeDeviceQueue (&DeviceObjectExt->DeviceHoldingQueue);

    PopLockDeviceList (FALSE);

    //
    // Add to global list of all device objects
    //

    InsertTailList (&PopDeviceList, &DeviceObjectExt->AllDeviceObjects);
    PopUnlockDeviceList ();
}



VOID
PoRunDownDeviceObject (
    IN PDEVICE_OBJECT   DeviceObject
    )
{
    KIRQL   OldIrql;
    PDEVOBJ_EXTENSION    DeviceObjectExt;

    DeviceObjectExt = (PDEVOBJ_EXTENSION) DeviceObject->DeviceObjectExtension;

    //
    // Lock power management devicelist and state information
    //

    PopLockDeviceList (FALSE);
    PopLockStateDatabase (&OldIrql);

    //
    // If in IdleScan list, remove it
    //

    if (DeviceObjectExt->IdleList.Flink) {
        RemoveEntryList (&DeviceObjectExt->IdleList);
    }

    //
    // Verify not busy
    //

    ASSERT (DeviceObjectExt->CurrentSetPowerIrp == NULL);
    ASSERT (IsListEmpty (&DeviceObjectExt->DeviceHoldingQueue.DeviceListHead));

    //
    // If in PowerState change remove it
    //

    if (DeviceObjectExt->PowerStateChange.Flink) {

        //
        // Requent setting state to current state.  That will
        // remove it from the list.
        //

        PopRequestPowerChange (
            DeviceObjectExt,
            DeviceObjectExt->CurrentPowerState,
            DeviceObjectExt->CurrentDevicePowerState
        );

        ASSERT (DeviceObjectExt->PowerStateChange.Flink);
    }

    //
    // Remove from global list of all device objects
    //

    RemoveEntryList (&DeviceObjectExt->AllDeviceObjects);

    //
    // Unlock device list and state information
    //

    PopUnlockStateDatabase (OldIrql);
    PopUnlockDeviceList ();
}


VOID
PoSetPowerManagementEnable (
    IN BOOLEAN          Enable
    )
{
    PoEnabled = Enable;

    if (Enable) {
        KeSetTimer (&PopIdleScanTimer, PopIdleScanTime, &PopIdleScanDpc);
    }
}


POBJECT_NAME_INFORMATION
PopGetDeviceName (
    PDEVICE_OBJECT              DeviceObject
    )
/*++

Routine Description:

    Utility function to lookup the device object's name.  If the
    device objects name can't be found, then the driver objects
    name is looked up.

--*/
{
    POBJECT_NAME_INFORMATION    ObjectName;
    NTSTATUS                    Status;
    ULONG                       ObjectNameSize, NewSize;

    if (KeGetCurrentIrql() >= DISPATCH_LEVEL) {
        return NULL;
    }

    ObjectName = (POBJECT_NAME_INFORMATION)
        ExAllocatePool (PagedPool, sizeof (OBJECT_NAME_INFORMATION) + 100);
    ObjectNameSize = sizeof (OBJECT_NAME_INFORMATION);
    if (!ObjectName) {
        return NULL;
    }

    //
    // Get the name of the device object
    //

    for (; ;) {
        NewSize = 0;
        Status = ObQueryNameString (
                    DeviceObject,
                    ObjectName,
                    ObjectNameSize,
                    &NewSize
                    );

        if (NewSize <= ObjectNameSize) {
            break;
        }

        ExFreePool (ObjectName);
        ObjectName = (POBJECT_NAME_INFORMATION) ExAllocatePool (PagedPool, NewSize);
        ObjectNameSize = NewSize;
        if (!ObjectName) {
            break;
        }
    }

    //
    // If no device object name, get the driver object name
    //

    if (NT_SUCCESS(Status)  &&  !ObjectName->Name.Length) {
        for (; ;) {
            NewSize = 0;
            Status = ObQueryNameString (
                        DeviceObject->DriverObject,
                        ObjectName,
                        ObjectNameSize,
                        &NewSize
                        );

            if (NewSize <= ObjectNameSize) {
                break;
            }

            ExFreePool (ObjectName);
            ObjectName = (POBJECT_NAME_INFORMATION) ExAllocatePool (PagedPool, NewSize);
            ObjectNameSize = NewSize;
            if (!ObjectName) {
                break;
            }
        }
    }

    if (!ObjectName) {
        return NULL;
    }

    if (!NT_SUCCESS(Status) ||  !ObjectName->Name.Length) {
        ExFreePool (ObjectName);
        return NULL;
    }

    return ObjectName;
}

#if DBG
PUCHAR
PopPowerState (
    POWER_STATE PowerState
    )
{
    PUCHAR  p;

    switch (PowerState) {
        case PowerUnspecified:  p = "PowerUnspecified";     break;
        case PowerUp:           p = "PowerUp";              break;
        case PowerQuery:        p = "PowerQuery";           break;
        case PowerStandby:      p = "PowerStandby";         break;
        case PowerSuspend:      p = "PowerSuspend";         break;
        case PowerHibernate:    p = "PowerHibernate";       break;
        case PowerDown:         p = "PowerDown";            break;
        case PowerDownRemove:   p = "PowerDownRemove";      break;
        default:                p = "INVALID POWER STATE";  break;
    }

    return p;
}
#endif

#endif // _PNP_POWER_

ULONG
PoQueryPowerSequence (
    VOID
    )
{

#ifndef _PNP_POWER_

    return 1;

#else

    ASSERT (PoPowerSequence);
    return PoPowerSequence;

#endif
}