GUID_DEVICE_RESET_INTERFACE_STANDARD 작업
GUID_DEVICE_RESET_INTERFACE_STANDARD 인터페이스는 함수 드라이버가 오작동하는 디바이스를 다시 설정 및 복구하는 표준 방법을 정의합니다.
이 인터페이스를 통해 두 가지 유형의 디바이스 재설정을 사용할 수 있습니다.
함수 수준 디바이스 재설정. 이 경우 초기화 작업은 특정 디바이스로 제한되며 다른 디바이스에는 표시되지 않습니다. 디바이스는 재설정을 통해 버스에 계속 연결되고 다시 설정 후 유효한 상태(초기 상태)로 돌아갑니다. 이러한 유형의 재설정은 시스템에 미치는 영향이 가장 적습니다.
- 이러한 유형의 재설정은 버스 드라이버 또는 ACPI 펌웨어에서 구현할 수 있습니다. 버스 사양이 요구 사항을 충족하는 대역 내 재설정 메커니즘을 정의하는 경우 버스 드라이버는 함수 수준 재설정을 구현할 수 있습니다. ACPI 펌웨어는 필요에 따라 자체 구현을 사용하여 버스 드라이버 정의 함수 수준 재설정을 재정의할 수 있습니다.
플랫폼 수준 디바이스 재설정. 이 경우 재설정 작업을 수행하면 디바이스가 버스에서 누락된 것으로 보고됩니다. 초기화 작업은 특정 디바이스 및 동일한 전원 레일 또는 리셋 라인을 통해 연결된 다른 모든 디바이스에 영향을 줍니다. 이러한 유형의 재설정은 시스템에 가장 큰 영향을 미칩니다. OS는 영향을 받는 모든 디바이스의 스택을 분해하고 다시 빌드하여 모든 것이 빈 상태에서 다시 시작되도록 합니다.
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 받으면 디바이스를 안전하게 제거할 수 있도록 성공을 반환해야 합니다. 그러나 디바이스가 메모리 버퍼에 쓰는 루프에 갇혀 있는 경우와 같이 디바이스를 안전하게 중지할 수 없는 경우가 있을 수 있습니다. 이러한 경우 드라이버는 IRP_MN_QUERY_REMOVE_DEVICE STATUS_DEVICE_HUNG 반환해야 합니다. PnP 관리자는 IRP_MN_QUERY_REMOVE_DEVICE 및 IRP_MN_REMOVE_DEVICE 프로세스를 계속하지만 특정 스택은 IRP_MN_REMOVE_DEVICE 받지 않습니다. 대신 디바이스 스택은 디바이스가 다시 설정된 후 IRP_MN_SURPRISE_REMOVAL 받습니다.
이러한 IRP에 대한 자세한 내용은 다음을 참조하세요.
IRP_MN_QUERY_REMOVE_DEVICE 요청 처리
필터 드라이버에서 디바이스 재설정 인터페이스 지원
필터 드라이버는 GUID_DEVICE_RESET_INTERFACE_STANDARD 인터페이스 형식의 IRP_MN_QUERY_INTERFACE IRP를 가로챌 수 있습니다. 이렇게 하면 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 펌웨어: 함수 수준 재설정
함수 수준 디바이스 재설정을 지원하려면 디바이스 scope 내에 정의된 _RST 메서드가 있어야 합니다. 있는 경우 이 메서드는 해당 디바이스에 대한 버스 드라이버의 함수 수준 디바이스 재설정 구현(있는 경우)을 재정의합니다. 실행되면 _RST 메서드는 해당 디바이스만 다시 설정해야 하며 다른 디바이스에는 영향을 미치지 않아야 합니다. 또한 디바이스는 버스에 연결되어 있어야 합니다.
ACPI 펌웨어: 플랫폼 수준 재설정
플랫폼 수준 디바이스 재설정을 지원하기 위해 다음 두 가지 옵션이 있습니다.
ACPI 펌웨어는 _RST 메서드를 구현하는 PowerResource를 정의할 수 있으며, 이 재설정 방법의 영향을 받는 모든 디바이스는 Device scope 정의된 _PRR 개체를 통해 이 PowerResource를 참조할 수 있습니다.
디바이스는 _PR3 개체를 선언할 수 있습니다. 이 경우 ACPI 드라이버는 D3cold 파워 사이클링을 사용하여 재설정을 수행하고 디바이스 간의 다시 설정 종속성은 _PR3 개체에서 결정됩니다.
device scope _PRR 개체가 있는 경우 ACPI 드라이버는 참조된 PowerResource의 _RST 메서드를 사용하여 재설정을 수행합니다. _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)
}
- Asl.exe 같은 ASL 컴파일러를 사용하여 테스트 ASL 파일을 AML로 컴파일합니다. WDK(Windows 드라이버 키트)에 포함된 실행 파일입니다.
Asl <test>.asl
위의 명령은 SSDT.aml을 생성합니다.
SSDT.aml의 이름을 acpitabl.dat로 바꿉니다.
테스트 시스템의 %systemroot%\system32에 acpitabl.dat를 복사합니다.
테스트 시스템에서 테스트 서명을 사용하도록 설정합니다.
bcdedit /set testsigning on
테스트 시스템을 다시 부팅합니다.
테이블이 로드되었는지 확인합니다. Windows 디버거에서 다음 명령을 사용합니다.
- !acpicache
- SSDT 테이블의 dt _DESCRIPTION_HEADER 주소
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