Работа с GUID_DEVICE_RESET_INTERFACE_STANDARD

Интерфейс GUID_DEVICE_RESET_INTERFACE_STANDARD определяет стандартный способ для драйверов функций попытаться сбросить и восстановить неисправное устройство.

Через этот интерфейс доступны два типа сброса устройства:

  • Сброс устройства на уровне функций. В этом случае операция сброса ограничена определенным устройством и не видна другим устройствам. Устройство остается подключенным к шине на протяжении всего сброса и возвращается в допустимое состояние (начальное состояние) после сброса. Этот тип сброса оказывает наименьшее влияние на систему.

    • Этот тип сброса может быть реализован драйвером шины или встроенным ПО ACPI. Водитель шины может реализовать сброс на уровне функций, если спецификация шины определяет механизм сброса в канале, соответствующий требованию. Встроенное ПО ACPI может при необходимости переопределить сброс на уровне функций, определенный драйвером шины, с помощью собственной реализации.
  • Сброс устройства на уровне платформы. В этом случае операция сброса приводит к сообщению о том, что устройство отсутствует в шине. Операция сброса влияет на определенное устройство и все остальные устройства, подключенные к нему через ту же линию питания или линию сброса. Этот тип сброса оказывает наибольшее влияние на систему. Операционная система будет удалять и перестраивать стеки всех затронутых устройств, чтобы убедиться, что все перезагрузится из пустого состояния.

Начиная с Windows 10, эти записи реестра в HKLM\SYSTEM\CurrentControlSet\Control\Pnp разделе настраивают операцию сброса:

  • DeviceResetRetryInterval: период времени до начала операции сброса. Значение по умолчанию — 3 секунды. Минимальное значение — 100 миллисекунда; Максимальное значение — 30 секунд.

  • DeviceResetMaximumRetries: количество попыток сброса.

Примечание

Интерфейс GUID_DEVICE_RESET_INTERFACE_STANDARD доступен начиная с Windows 10.

Использование интерфейса сброса устройства

Если драйвер функции обнаруживает, что устройство работает неправильно, ему следует сначала попытаться выполнить сброс на уровне функции. Если сброс на уровне функций не устраняет проблему, драйвер может попытаться выполнить сброс на уровне платформы. Однако сброс на уровне платформы следует использовать только в качестве окончательного варианта.

Чтобы запросить этот интерфейс, драйвер устройства отправляет IRP_MN_QUERY_INTERFACE IRP в стек драйверов. Для этого IRP драйвер задает для входного параметра InterfaceType значение GUID_DEVICE_RESET_INTERFACE_STANDARD. При успешном завершении IRP выходной параметр Interface является указателем на структуру DEVICE_RESET_INTERFACE_STANDARD. Эта структура содержит указатель на подпрограмму DeviceReset, которую можно использовать для запроса сброса на уровне функции или платформы.

Поддержка интерфейса сброса устройства в драйверах функций

Для поддержки интерфейса сброса устройства стек устройств должен соответствовать следующим требованиям.

Драйвер функции должен правильно обрабатывать IRP_MN_QUERY_REMOVE_DEVICE, IRP_MN_REMOVE_DEVICE и IRP_MN_SURPRISE_REMOVAL.

В большинстве случаев, когда драйвер получает IRP_MN_QUERY_REMOVE_DEVICE, он должен вернуть успешное завершение, чтобы устройство можно было безопасно удалить. Однако могут быть случаи, когда устройство не может быть безопасно остановлено, например, если устройство зависло в цикле записи в буфер памяти. В таких случаях драйвер должен вернуть STATUS_DEVICE_HUNG в IRP_MN_QUERY_REMOVE_DEVICE. Диспетчер PnP продолжит процесс IRP_MN_QUERY_REMOVE_DEVICE и IRP_MN_REMOVE_DEVICE, но этот конкретный стек не получит IRP_MN_REMOVE_DEVICE. Вместо этого стек устройств получит IRP_MN_SURPRISE_REMOVAL после сброса устройства.

Дополнительные сведения об этих IRP см. в следующих разделах:

Обработка запроса IRP_MN_QUERY_REMOVE_DEVICE

Обработка запроса IRP_MN_REMOVE_DEVICE

Обработка запроса IRP_MN_SURPRISE_REMOVAL

Поддержка интерфейса сброса устройства в драйверах фильтров

Драйверы фильтров могут перехватывать IRP_MN_QUERY_INTERFACE IRP с типом интерфейса GUID_DEVICE_RESET_INTERFACE_STANDARD. Таким образом, они могут продолжать делегировать интерфейсу GUID_DEVICE_RESET_INTERFACE_STANDARD, но выполнять операции, относящиеся к устройству, до или после операции сброса. Кроме того, они могут переопределить интерфейс GUID_DEVICE_RESET_INTERFACE_STANDARD, возвращаемый водителем шины, собственным интерфейсом, чтобы обеспечить собственную операцию сброса.

Поддержка интерфейса сброса устройства в драйверах шины

Драйверы шины, участвующие в процессе сброса устройства (т. е. водители шины, связанные с устройством, которое запрашивает сброс, и драйверы шины, связанные с устройствами, которые отвечают на запрос на сброс), должны соответствовать одному из следующих требований:

  • Будьте способны к горячей замене. Водитель автобуса должен иметь возможность обнаружить устройство, которое удаляется из автобуса без уведомления, и устройство, подключенное к шине.

  • Кроме того, он должен реализовывать интерфейс GUID_REENUMERATE_SELF_INTERFACE_STANDARD. Это имитирует устройство, извлекаемое из шины и подключаемое обратно. Встроенные драйверы шины (например, PCI и SDBUS) поддерживают этот интерфейс. Таким образом, если устройство, которое сбрасывается, использует одну из этих шин, никаких изменений водителя шины не требуется.

Для водителей шины на основе WDF платформа WDF регистрирует интерфейс GUID_REENUMERATE_SELF_INTERFACE_STANDARD от имени водителей. Поэтому регистрировать этот интерфейс для этих драйверов не требуется. Если драйверу шины необходимо выполнить некоторые операции перед повторным перечислением его дочерних устройств, он должен зарегистрироваться для процедуры обратного вызова EvtChildListDeviceReenumerated и выполнить операции в этой подпрограмме. Так как эта подпрограмма обратного вызова может вызываться параллельно для всех PDO, код в ней может потребоваться для защиты от состояний гонки.

Встроенное ПО ACPI: сброс на уровне функций

Для поддержки сброса устройства на уровне функций в область устройства должен быть определен метод _RST. При наличии этот метод переопределит реализацию драйвера шины сброса устройства на уровне функций (при наличии) для этого устройства. При выполнении метод _RST должен сбрасывать только это устройство и не должен влиять на другие устройства. Кроме того, устройство должно оставаться на связи в шине.

Встроенное ПО ACPI: сброс на уровне платформы

Для поддержки сброса устройства на уровне платформы существует два варианта:

  • Встроенное ПО ACPI может определить PowerResource, реализующий метод _RST, и все устройства, затронутые этим методом сброса, могут ссылаться на этот ресурс PowerResource через объект _PRR, определенный в область устройства.

  • Устройство может объявить объект _PR3. В этом случае драйвер ACPI будет использовать цикл питания D3cold для выполнения сброса, а зависимости сброса между устройствами будут определяться из объекта _PR3.

Если объект _PRR существует в область устройства, драйвер ACPI будет использовать метод _RST в упоминаемом PowerResource для выполнения сброса. Если объект _PRR не определен, но определен объект _PR3, драйвер ACPI будет использовать цикличность питания D3cold для сброса. Если ни _PRR, ни объект _PR3 не определен, устройство не поддерживает сброс на уровне платформы, и драйвер ACPI сообщит, что сброс на уровне платформы недоступен.

Проверка встроенного ПО ACPI в тестовой системе

Чтобы протестировать драйвер, поддерживающий сброс и восстановление устройства, выполните следующую процедуру. В этой процедуре предполагается, что вы используете этот пример ASL-файла.

DefinitionBlock("SSDT.AML", "SSDT", 0x01, "XyzOEM", "TestTabl", 0x00001000)
{
   Scope(\_SB_)
      {
       PowerResource(PWFR, 0x5, 0x0)
       {
           Method(_RST, 0x0, NotSerialized)    { }
           
           // Placeholder methods as power resources need _ON, _OFF, _STA.
           Method(_STA, 0x0, NotSerialized)
           {
               Return(0xF)
           }

           Method(_ON_, 0x0, NotSerialized)    { }

           Method(_OFF, 0x0, NotSerialized)    { }

       } // PowerResource()
   } // Scope (\_SB_)

   // Assumes WiFi device is declared under \_SB.XYZ.
   Scope(\_SB_.XYZ.WIFI)
       {

       // Declare PWFR as WiFi reset power rail
       Name(_PRR, Package(One)
           {
               \_SB_.PWFR
           })
       } // Scope (\_SB)
}
  1. Скомпилируйте тестовый ASL-файл в AML с помощью компилятора ASL, например Asl.exe. Исполняемый файл в составе пакета драйверов Windows (WDK).
Asl <test>.asl

Предыдущая команда создает ФАЙЛ SSDT.aml.

  1. Переименуйте SSDT.aml в acpitabl.dat.

  2. Скопируйте файл acpitabl.dat в папку %systemroot%\system32 в тестовой системе.

  3. Включите тестовую подпись в тестовой системе.

bcdedit /set testsigning on
  1. Перезагрузите тестовую систему.

  2. Убедитесь, что таблица загружена. В отладчике Windows используйте следующие команды.

  • !acpicache
  • dt _DESCRIPTION_HEADER адрес таблицы SSDT
0: kd> !acpicache
Dumping cached ACPI tables...
  SSDT @(ffffffffffd03018) Rev: 0x1 Len: 0x000043 TableID: TestTabl
  XSDT @(ffffffffffd05018) Rev: 0x1 Len: 0x000114 TableID: HSW-FFRD
       ...
       ...
 
0: kd> dt _DESCRIPTION_HEADER ffffffffffd03018
ACPI!_DESCRIPTION_HEADER
   +0x000 Signature        : 0x54445353
   +0x004 Length           : 0x43
   +0x008 Revision         : 0x1 ''
   +0x009 Checksum         : 0x37 '7'
   +0x00a OEMID            : [6]  "XyzOEM"
   +0x010 OEMTableID       : [8]  "TestTabl"
   +0x018 OEMRevision      : 0x1000
   +0x01c CreatorID        : [4]  "MSFT"
   +0x020 CreatorRev       : 0x5000000

См. также:

_DEVICE_RESET_INTERFACE_STANDARD