summaryrefslogtreecommitdiffstats
path: root/private/ntos/po/misc.c
blob: 1f5d75283c170c97dbdd615f4fdda2bf00b6a439 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/*++

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
}