Passive-Level 인터럽트 서비스 루틴 사용

Windows 8 시작하여 드라이버는 IoConnectInterruptEx 루틴을 사용하여 수동 수준 ISR(InterruptService 루틴)을 등록할 수 있습니다. 연결된 인터럽트 발생 시 커널의 인터럽트 트랩 처리기는 이 루틴이 IRQL = PASSIVE_LEVEL 실행되도록 예약합니다. ISR은 I/O 요청을 통해서만 디바이스의 하드웨어 레지스터에 액세스할 수 있는 경우 수동 수준에서 실행해야 할 수 있습니다. 수동 수준 ISR은 디바이스에 I/O 요청을 동기적으로 보내고 요청이 완료될 때까지 차단할 수 있습니다.

Passive-Level ISR 등록

IoConnectInterruptEx에 대한 입력 매개 변수는 IO_CONNECT_INTERRUPT_PARAMETERS 구조체에 대한 포인터입니다. 수동 수준 ISR을 등록하려면 이 구조체의 Version 멤버를 CONNECT_FULLY_SPECIFIED 또는 CONNECT_LINE_BASED 설정합니다. Version = CONNECT_FULLY_SPECIFIED 경우 Irql 멤버를 PASSIVE_LEVEL, SynchronizeIrql 멤버를 PASSIVE_LEVEL, SpinLock 멤버를 NULL로 설정합니다. 버전 = CONNECT_LINE_BASED 경우 SynchronizeIrql = PASSIVE_LEVEL 및 SpinLock = NULL을 설정합니다.

인터럽트 개체가 수동 수준 ISR을 지정하는 경우 KeSynchronizeExecution 루틴은 스핀 잠금 대신 커널 동기화 이벤트 개체를 사용하여 SynchCritSection 루틴의 실행을 ISR과 동기화합니다.

이 이벤트 개체는 수동 수준 ISR을 등록하는 호출에서 IoConnectInterruptEx 루틴에 의해 할당됩니다. 호출자는 이 호출에서 스핀 잠금을 제공하지 않아야 합니다. 즉, ISR이 수동 수준에서 실행되는 경우 호출자는 IO_CONNECT_INTERRUPT_PARAMETERS 구조체의 SpinLock 멤버를 NULL로 설정해야 합니다. 그렇지 않으면 IoConnectInterruptEx가 실패하고 오류 상태 STATUS_INVALID_PARAMETER 반환합니다.

제공된 인터럽트 개체에 대한 ISR이 IRQL = PASSIVE_LEVEL 실행되는 경우 KeAcquireInterruptSpinLockKeReleaseInterruptSpinLock 루틴으로 인해 버그 검사 발생합니다.

Passive-Level 인터럽트 처리가 필요한 디바이스

수준 트리거 인터럽트 요청을 알리는 메모리 매핑 디바이스의 경우 디바이스의 ISR은 일반적으로 커널의 인터럽트 트랩 처리기 내에서 DIRQL에서 호출됩니다. ISR은 디바이스의 하드웨어 레지스터를 조작하여 인터럽트 해제합니다.

그러나 연결된 디바이스가 수준 트리거 인터럽트 요청을 알리지만 디바이스의 하드웨어 레지스터는 커널의 인터럽트 트랩 처리기 내에서 DIRQL에서 호출되는 ISR에서 직접 액세스할 수 없는 경우 IRQL = PASSIVE_LEVEL 실행해야 할 수 있습니다. 예를 들어 디바이스 레지스터가 메모리 매핑되지 않거나 등록 액세스 중에 ISR이 일시적으로 차단될 수 있습니다.

Windows 8 드라이버가 수동 수준 ISR을 등록할 수 있습니다. 인터럽트 발생 시 커널의 인터럽트 트랩 처리기는 ISR이 IRQL = PASSIVE_LEVEL 실행되도록 예약합니다. 처리기가 반환되기 전에 인터럽트 컨트롤러(또는 GPIO 컨트롤러)에서 인터럽트 대기해야 합니다. 디바이스가 에지 트리거 인터럽트를 알리는 경우 처리기는 인터럽트 컨트롤러에서 인터럽트를 지웁니다. 디바이스가 수준 트리거 인터럽트 신호를 받으면 처리기는 인터럽트 컨트롤러의 인터럽트 를 일시적으로 마스킹합니다. ISR이 실행되면 커널이 인터럽트 마스크를 해제합니다.

예제

수동 수준 ISR이 필요할 수 있는 디바이스의 예는 I²C와 같은 저전력 직렬 버스에 연결된 센서 디바이스입니다. Windows 8 시작하여 SPB 프레임워크 확장(SpbCx)에서 I²C 및 기타 간단한 SPB(주변 버스)에 대한 지원을 제공합니다.

I²C 연결 센서 디바이스의 레지스터에 액세스하기 위해 센서 드라이버는 SpbCx와 버스용 컨트롤러 드라이버가 공동으로 처리하는 I/O 요청을 센서 디바이스에 보냅니다. 요청된 작업을 수행하려면 SPB 컨트롤러가 버스를 통해 데이터를 직렬로 전송해야 합니다. 이 전송은 비교적 느리며 DIRQL에서 실행되는 ISR의 시간 제약 조건 내에서 수행할 수 없습니다. 그러나 수동 수준 ISR은 I/O 요청을 동기적으로 보낸 다음 요청이 완료될 때까지 차단할 수 있습니다.

이 예제의 수동 수준 ISR은 ISR이 인터럽트 디바이스에 I/O 요청을 보낼 때 I²C 버스 컨트롤러가 꺼져 있는 경우 더 오랫동안 차단될 수 있습니다. 이 경우 컨트롤러는 버스를 통해 데이터를 전송하기 전에 D0 전원 상태로의 전환을 완료해야 합니다.

PCI와 같은 버스와 달리 이 예제의 I²C 버스는 주변 장치에서 프로세서로 인터럽트 요청을 전달하는 버스별 수단을 제공하지 않습니다. 대신 센서 디바이스는 GPIO 컨트롤러 디바이스의 핀에 인터럽트를 신호로 표시한 다음 인터럽트 요청을 프로세서에 릴레이할 수 있습니다. 자세한 내용은 GPIO 인터럽트 를 참조하세요.

일반적으로 GPIO 컨트롤러의 하드웨어 레지스터는 메모리 매핑되며 커널의 인터럽트 트랩 처리기를 통해 DIRQL에서 액세스할 수 있습니다. 센서 디바이스에서 인터럽트를 발생시키는 경우 처리기는 GPIO 컨트롤러의 레지스터에서 인터럽트 비트를 조작하여 인터럽트를 무음으로 처리해야 합니다.

수준 트리거 인터럽트의 경우 커널의 인터럽트 트랩 처리기는 GPIO 핀에서 인터럽트 요청을 마스킹한 다음 센서 디바이스의 ISR이 수동 수준에서 실행되도록 예약합니다. ISR은 센서 디바이스에서 인터럽트 요청을 지워야 합니다. ISR이 반환되면 커널은 GPIO 핀에서 인터럽트 요청의 마스크를 해제합니다.

에지 트리거 인터럽트의 경우 커널의 트랩 처리기는 GPIO 핀에서 인터럽트 요청을 지우고 센서 디바이스의 ISR이 수동 수준에서 실행되도록 예약합니다.

작업자 루틴

IoConnectInterruptEx 호출에서 드라이버는 수동 수준 ISR과 작업자 루틴 간에 인터럽트 처리를 분할하는 옵션이 있습니다. 일반적으로 ISR은 인터럽트 초기 처리(예: 수준 트리거 인터럽트 무음)를 수행하고 작업자에 대한 추가 처리를 연기해야 합니다. ISR과 작업자는 모두 수동 수준에서 실행되지만 ISR은 상대적으로 높은 우선 순위로 실행되며 다른 높은 우선 순위 작업을 지연할 수 있습니다. 이러한 작업에는 새 인터럽트용 수동 수준 ISR이 포함될 수 있습니다.

드문 경우이지만 인터럽트 처리가 너무 적어서 수동 수준 ISR이 인터럽트 처리를 모두 수행할 수 있으며 작업자 루틴이 필요하지 않을 수 있습니다.

KMDF 드라이버에서 수동 수준 ISR을 사용하는 방법에 대한 자세한 내용은 Passive-Level 인터럽트 지원을 참조하세요.