Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Управление питанием в w2k и wxp  (Прочитано 6676 раз)
0 Пользователей и 1 Гость смотрят эту тему.
ra_
Гость
« : 25-07-2008 05:39 » 

Всем привет!
Начал разбираться с темой управления питанием в WDM-драйвере.
Взял кусок кода power.c, работающий с IRP питания, генерируемый Walter'ом Oney через wdmwiz.awx. То есть тот, где крутится автомат состояний и который должен работать под всеми NT и даже под 9x.
Чуть адаптировал для компиляции, не задевая логику (добавил к DeviceExtension поля и в AddDevice инициализацию, имена переменных поменял).
Проверяю, как работает. А работает странно. Под wxp успешно заходит в спящий режим и выходит, выдавая в ядерный лог:
Код:
12:15:29 - 1.1 is NewIrp in state InitialState
12:15:29 -  1.1 TriageNewIrp
12:15:29 -  1.1 SelectDState
12:15:29 -  1.1 SendDeviceIrp
12:15:29 - 2.1 is NewIrp in state InitialState
12:15:29 -  2.1 TriageNewIrp
12:15:29 -  2.1 QueueStallComplete
12:15:29 -  2.1 DevQueryDown
12:15:29 -  2.1 ForwardMainIrp
12:15:29 - 2.2 is MainIrpComplete in state DevQueryDownPending
12:15:29 -  2.2 DevQueryDownComplete
12:15:29 -  2.2 CompleteMainIrp
12:15:29 -  2.2 DestroyContext
12:15:29 - 1.2 is AsyncNotify in state SubPowerDownPending
12:15:29 -  1.2 SubPowerDownComplete
12:15:29 -  1.2 ForwardMainIrp
12:15:29 - 1.3 is MainIrpComplete in state SysPowerDownPending
12:15:29 -  1.3 SysPowerDownComplete
12:15:29 -  1.3 CompleteMainIrp
12:15:29 -  1.3 DestroyContext
12:15:30 - 3.1 is NewIrp in state InitialState
12:15:30 -  3.1 TriageNewIrp
12:15:30 -  3.1 SelectDState
12:15:30 -  3.1 SendDeviceIrp
12:15:30 - 4.1 is NewIrp in state InitialState
12:15:30 -  4.1 TriageNewIrp
12:15:30 -  4.1 QueueStallComplete
12:15:30 -  4.1 SaveContext
12:15:30 -  4.1 ContextSaveComplete
12:15:30 -  4.1 ForwardMainIrp
12:15:30 - 4.2 is MainIrpComplete in state DevPowerDownPending
12:15:30 -  4.2 CompleteMainIrp
12:15:30 -  4.2 DestroyContext
12:15:30 - 3.2 is AsyncNotify in state SubPowerDownPending
12:15:30 -  3.2 SubPowerDownComplete
12:15:30 -  3.2 ForwardMainIrp
12:15:30 - 3.3 is MainIrpComplete in state SysPowerDownPending
12:15:30 -  3.3 SysPowerDownComplete
12:15:30 -  3.3 CompleteMainIrp
12:15:30 -  3.3 DestroyContext
12:15:45 - 5.1 is NewIrp in state InitialState
12:15:45 -  5.1 TriageNewIrp
12:15:45 -  5.1 ForwardMainIrp
12:15:45 - 5.2 is MainIrpComplete in state SysPowerUpPending
12:15:45 -  5.2 SysPowerUpComplete
12:15:45 -  5.2 SelectDState
12:15:45 -  5.2 SendDeviceIrp
12:15:45 -  5.2 SubPowerUpComplete
12:15:45 -  5.2 CompleteMainIrp
12:15:45 -  5.2 DestroyContext
Где в 12:15:45 - уже успешное пробуждение.

Под w2k, пытаясь зайти в спящий режим, фактически вешает машину. Выключает картинку на мониторе, но вентиляторы и винчестер по-прежнему крутятся. В логе при этом:
Код:
45.75407028 - 1.1 is NewIrp in state InitialState
45.75408936 -  1.1 TriageNewIrp
45.75409317 -  1.1 SelectDState
45.75410461 -  1.1 SendDeviceIrp
45.75411224 - 2.1 is NewIrp in state InitialState
45.75411606 -  2.1 TriageNewIrp
45.75412750 -  2.1 QueueStallComplete
45.75413132 -  2.1 DevQueryDown
45.75413895 -  2.1 ForwardMainIrp
45.75415039 - 2.2 is MainIrpComplete in state DevQueryDownPending
45.75415421 -  2.2 DevQueryDownComplete
45.75416183 -  2.2 CompleteMainIrp
45.75416946 -  2.2 DestroyContext
45.75418091 - 1.2 is AsyncNotify in state SubPowerDownPending
45.75418854 -  1.2 SubPowerDownComplete
45.75419617 -  1.2 ForwardMainIrp
45.75420380 - 1.3 is MainIrpComplete in state SysPowerDownPending
45.75421143 -  1.3 SysPowerDownComplete
45.75421524 -  1.3 CompleteMainIrp
45.75422668 -  1.3 DestroyContext
45.75424957 - 3.1 is NewIrp in state InitialState
45.75425339 -  3.1 TriageNewIrp
45.75426483 -  3.1 SelectDState
45.75426865 -  3.1 SendDeviceIrp
45.75428009 - 4.1 is NewIrp in state InitialState
45.75428391 -  4.1 TriageNewIrp
45.75429153 -  4.1 QueueStallComplete
45.75429916 -  4.1 DevQueryDown
45.75430298 -  4.1 ForwardMainIrp
45.75431442 - 4.2 is MainIrpComplete in state DevQueryDownPending
45.75431824 -  4.2 DevQueryDownComplete
45.75432968 -  4.2 CompleteMainIrp
45.75433350 -  4.2 DestroyContext
45.75434494 - 3.2 is AsyncNotify in state SubPowerDownPending
45.75435257 -  3.2 SubPowerDownComplete
45.75436020 -  3.2 ForwardMainIrp
45.75436783 - 3.3 is MainIrpComplete in state SysPowerDownPending
45.75437546 -  3.3 SysPowerDownComplete
45.75437927 -  3.3 CompleteMainIrp
45.75439072 -  3.3 DestroyContext
Отличаются логи, как можно увидеть, только строками
Код:
28c28,29
< -  4.1 DevQueryDown
---
> -  4.1 SaveContext
> -  4.1 ContextSaveComplete
30,31c31
< - 4.2 is MainIrpComplete in state DevQueryDownPending
< -  4.2 DevQueryDownComplete
---
> - 4.2 is MainIrpComplete in state DevPowerDownPending
, ну и для xp 5.x, касающихся просыпания.

Касался ли кто-нибудь темы управления питанием, и что можете посоветовать для корректной работы под w2k? Возможно, при адаптации кода power.c к своему драйверу чего-то не учёл?..
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 25-07-2008 08:28 » 

имхо для простых устройств - все это не нужно... эти хитрые примочки нужны для того чтобы в зависимости от состояния Windows - ВЫ могли СВОЕ устройство, ТОЛЬКО вам известными командами, корректно усыпить или разбудить.

например я все эти PowerIRP обрабатываю по умолчанию. но тем не менее (не знаю как под 2000) а под XP можно в гибернацию уйти и проснуться.
... вру. сон я запретил там же
Код:
    IOStack = IoGetCurrentIrpStackLocation(Irp);
   
    switch (IOStack->MinorFunction)
    {
    case IRP_MN_WAIT_WAKE: //что то насчет того чтобы разбудить устройства извне... см DDK
//IN Parameters.WaitWake.SystemWake
//Irp->IoStatus.Status = STATUS_SUCCESS; // много разных: STATUS_PENDING, STATUS_INVALID_DEVICE_STATE, STATUS_NOT_SUPPORTED ,STATUS_DEVICE_BUSY ,STATUS_SUCCESS ,STATUS_CANCELED.
status = STATUS_SUCCESS;
break;
    case IRP_MN_POWER_SEQUENCE:
//OUT Parameters.PowerSequence points to a POWER_SEQUENCE
//Irp->IoStatus.Status = STATUS_SUCCESS; // = STATUS_NOT_IMPLEMENTED;//отсутствует поддержка данной функции
status = STATUS_SUCCESS;
break;
    case IRP_MN_SET_POWER:  
//IN Parameters.Power.Type
//IN Parameters.Power.ShutdownType
//OUT Parameters.Power.SystemContext
//Irp->IoStatus.Status = STATUS_SUCCESS; //обязательно! остальные значения недопустимы!!!
newPoState = IOStack->Parameters.Power.State;
status = STATUS_SUCCESS; //обязательно! остальные значения недопустимы!!!
break;
    case IRP_MN_QUERY_POWER:
if (IOStack->Parameters.Power.ShutdownType == PowerActionSleep)
{
    status = STATUS_UNSUCCESSFUL;
    Irp->IoStatus.Status = status;
    PoStartNextPowerIrp(Irp);
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}
        status = STATUS_SUCCESS; //или любое другое?
break;
    default:
status = STATUS_SUCCESS; //обязательно! остальные значения недопустимы!!!
break;
    }

    PoStartNextPowerIrp(Irp);
    IoSkipCurrentIrpStackLocation(Irp);
    status = PoCallDriver(devExt->LowerDevice, Irp);
    return status ;

вот собстно и все А черт его знает...
по идее - периодически надо PoSetPowerState() винде рапортовать... чтоб она знала в каком я состоянии свой девайс держу...
но я подумал - она обойдется)

PS Ony классный мужик) но иногда можно и попроще...)
ЗЗЫ ы вообще вспоминаю под 2000-ным еще возился, корерктно из сна вывести устройство не мог. зависало все в момент просыпания. как я сейчас думаю из за невыключенных прерываний...разбираться времени не было, тогда просто запретил сон)
« Последнее редактирование: 25-07-2008 08:33 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #2 : 25-04-2012 17:17 » 

Да давняя тема!)))
Столкнулся с подобной проблемой!
При выключении или перезагрузки компа на ХР мой драйвер для железяки выкидывает driver_power_state_failure... разобрался что это связано с IRP_MJ_POWER... на накаком этапе не могу отследить ... воспользовался данным примером!)))
Спасибо!
Записан
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #3 : 30-04-2012 11:38 » new

подправил чуток код:
Код: (C++)
static char* Pfcnname[] = {
                "IRP_MN_WAIT_WAKE",
                "IRP_MN_POWER_SEQUENCE",
                "IRP_MN_SET_POWER",
                "IRP_MN_QUERY_POWER",
                };

static char* sysstate[] = {
                        "PowerSystemUnspecified",
                        "PowerSystemWorking",
                        "PowerSystemSleeping1",
                        "PowerSystemSleeping2",
                        "PowerSystemSleeping3",
                        "PowerSystemHibernate",
                        "PowerSystemShutdown",
                        "PowerSystemMaximum",
                        };

static char* devstate[] = {
                        "PowerDeviceUnspecified",
                        "PowerDeviceD0",
                        "PowerDeviceD1",
                        "PowerDeviceD2",
                        "PowerDeviceD3",
                        "PowerDeviceMaximum",
                        };
//...
NTSTATUS DefaultPowerHandler(PDEVICE_OBJECT fdo, PIRP pIrp)
{
    KdPrint(("Forwarded IRP to next lower driver\n"));

    // Must be done while we own the IRP
    PoStartNextPowerIrp(pIrp);

    IoSkipCurrentIrpStackLocation(pIrp);

        return PoCallDriver(((PMDMAI_DEVICE_EXTENSION)fdo->DeviceExtension)->TargetDeviceObject, pIrp);
}

NTSTATUS MDMAIDispatchPower(IN PDEVICE_OBJECT fido, IN PIRP Irp)
{                                                       // DispatchPower
                PAGED_CODE();

                                KdPrint((" MDMAIDispatchPower! \n"));

        PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
        ULONG fcn = stack->MinorFunction;

        if (fcn == IRP_MN_SET_POWER || fcn == IRP_MN_QUERY_POWER)
                {
                ULONG context = stack->Parameters.Power.SystemContext;
                POWER_STATE_TYPE type = stack->Parameters.Power.Type;

                KdPrint((DRIVERNAME " - IRP_MJ_POWER (%s)", Pfcnname[fcn]));
                if (type == SystemPowerState)
                        KdPrint((DRIVERNAME" - SystemPowerState = %s\n", sysstate[stack->Parameters.Power.State.SystemState]));
                else
                        KdPrint((DRIVERNAME" - DevicePowerState = %s\n", devstate[stack->Parameters.Power.State.DeviceState]));
                }
        else if (fcn < arraysize(Pfcnname))
                KdPrint((DRIVERNAME " - IRP_MJ_POWER (%s)\n", Pfcnname[fcn]));
        else
                KdPrint((DRIVERNAME " - IRP_MJ_POWER (%2.2X)\n", fcn));
       
        return DefaultPowerHandler(fido, Irp);
}                                                       // DispatchPower
и заработало... теперь нет синего экрана...
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines