IoConnectInterruptEx의 CONNECT_FULLY_SPECIFIED 버전 사용
드라이버는 CONNECT_FULLY_SPECIFIED 버전의 IoConnectInterruptEx 를 사용하여 특정 인터럽트에 대한 InterruptService 루틴을 등록할 수 있습니다. 드라이버는 Windows Vista부터 CONNECT_FULLY_SPECIFIED 버전을 사용할 수 있습니다. 드라이버는 Iointex.lib 라이브러리에 연결하여 Windows 2000, Windows XP 및 Windows Server 2003의 CONNECT_FULLY_SPECIFIED 버전을 사용할 수 있습니다. 자세한 내용은 Windows Vista 이전의 IoConnectInterruptEx 사용을 참조하세요.
드라이버는 Parameters-Version>에 대한 CONNECT_FULLY_SPECIFIED 값을 지정하고 Parameters-FullySpecified>의 멤버를 사용하여 작업의 다른 매개 변수를 지정합니다.
Parameters-FullySpecified.PhysicalDeviceObject>는 ISR이 서비스하는 디바이스에 대한 PDO를 지정합니다.
Parameters-FullySpecified.ServiceRoutine> 은 InterruptService 루틴을 가리키고 Parameters-FullySpecified>는 을 가리킵니다. ServiceContext는 시스템이 InterruptService에 ServiceContext 매개 변수로 전달하는 값을 지정합니다. 드라이버는 이를 사용하여 컨텍스트 정보를 전달할 수 있습니다. 컨텍스트 정보를 전달하는 방법에 대한 자세한 내용은 ISR 컨텍스트 정보 제공을 참조하세요.
드라이버는 Parameters-FullySpecified.InterruptObject>에서 PKINTERRUPT 변수에 대한 포인터를 제공합니다. IoConnectInterruptEx 루틴은 ISR을 제거할 때 사용할 수 있는 인터럽트의 인터럽트 개체를 가리키도록 이 변수를 설정합니다.
드라이버는 필요에 따라 ISR과 동기화할 때 사용할 시스템의 Parameters-FullySpecified.SpinLock>에서 스핀 잠금을 지정할 수 있습니다. 대부분의 드라이버는 시스템이 드라이버를 대신하여 스핀 잠금을 할당할 수 있도록 NULL 을 지정할 수 있습니다. ISR과 동기화하는 방법에 대한 자세한 내용은 디바이스 데이터에 대한 액세스 동기화를 참조하세요.
드라이버는 Parameters-FullySpecified>의 다른 멤버에서 인터럽트 키 속성을 지정해야 합니다. 시스템은 드라이버에 IRP_MN_START_DEVICE IRP를 보낼 때 CM_PARTIAL_RESOURCE_DESCRIPTOR 구조의 배열에 필요한 정보를 제공합니다.
시스템은 CmResourceTypeInterrupt와 동일한 Type 멤버가 있는 CM_PARTIAL_RESOURCE_DESCRIPTOR 구조체를 인터럽트할 때마다 를 제공합니다. 메시지 신호 인터럽트인 경우 Flags 멤버의 CM_RESOURCE_INTERRUPT_MESSAGE 비트가 설정됩니다. 그렇지 않으면 지워집니다.
CM_PARTIAL_RESOURCE_DESCRIPTORu.Interrupt 멤버는 줄 기반 인터럽트에 대한 설명을 포함하고 u.MessageInterrupt.Translated 멤버는 메시지 신호 인터럽트에 대한 설명을 포함합니다. 다음 표에서는 CM_PARTIAL_RESOURCE_DESCRIPTOR 구조에서 두 유형의 인터럽트 모두에 대해 Parameters-FullySpecified>의 멤버를 설정하는 데 필요한 정보를 찾는 위치를 나타냅니다. 자세한 내용은 테이블 뒤에 있는 코드 예제를 참조하세요.
멤버 | 줄 기반 인터럽트 | 메시지 신호 인터럽트 |
---|---|---|
ShareVector |
ShareDisposition |
ShareDisposition |
벡터 |
u.Interrupt.Vector |
u.MessageInterrupt.Translated.Vector |
Irql |
u.Interrupt.Level |
u.MessageInterrupt.Translated.Level |
InterruptMode |
플래그 & CM_RESOURCE_INTERRUPT_LATCHED |
플래그 & CM_RESOURCE_INTERRUPT_LATCHED |
ProcessorEnableMask |
u.Interrupt.Affinity |
u.MessageInterrupt.Translated.Affinity |
드라이버는 Windows Vista 이상 버전의 Windows에서 메시지 신호 인터럽트용 CM_PARTIAL_RESOURCE_DESCRIPTOR 구조만 받습니다.
다음 코드 예제에서는 CONNECT_FULLY_SPECIFIED 사용하여 InterruptService 루틴을 등록하는 방법을 보여 줍니다.
IO_CONNECT_INTERRUPT_PARAMETERS params;
// deviceExtension is a pointer to the driver's device extension.
// deviceExtension->IntObj is a PKINTERRUPT.
// deviceInterruptService is a pointer to the driver's InterruptService routine.
// IntResource is a CM_PARTIAL_RESOURCE_DESCRIPTOR structure of either type CmResourceTypeInterrupt or CmResourceTypeMessageInterrupt.
// PhysicalDeviceObject is a pointer to the device's PDO.
// ServiceContext is a pointer to driver-specified context for the ISR.
RtlZeroMemory( ¶ms, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS) );
params.Version = CONNECT_FULLY_SPECIFIED;
params.FullySpecified.PhysicalDeviceObject = PhysicalDeviceObject;
params.FullySpecified.InterruptObject = &devExt->IntObj;
params.FullySpecified.ServiceRoutine = deviceInterruptService;
params.FullySpecified.ServiceContext = ServiceContext;
params.FullySpecified.FloatingSave = FALSE;
params.FullySpecified.SpinLock = NULL;
if (IntResource->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
// The resource is for a message-signaled interrupt. Use the u.MessageInterrupt.Translated member of IntResource.
params.FullySpecified.Vector = IntResource->u.MessageInterrupt.Translated.Vector;
params.FullySpecified.Irql = (KIRQL)IntResource->u.MessageInterrupt.Translated.Level;
params.FullySpecified.SynchronizeIrql = (KIRQL)IntResource->u.MessageInterrupt.Translated.Level;
params.FullySpecified.ProcessorEnableMask = IntResource->u.MessageInterrupt.Translated.Affinity;
} else {
// The resource is for a line-based interrupt. Use the u.Interrupt member of IntResource.
params.FullySpecified.Vector = IntResource->u.Interrupt.Vector;
params.FullySpecified.Irql = (KIRQL)IntResource->u.Interrupt.Level;
params.FullySpecified.SynchronizeIrql = (KIRQL)IntResource->u.Interrupt.Level;
params.FullySpecified.ProcessorEnableMask = IntResource->u.Interrupt.Affinity;
}
params.FullySpecified.InterruptMode = (IntResource->Flags & CM_RESOURCE_INTERRUPT_LATCHED ? Latched : LevelSensitive);
params.FullySpecified.ShareVector = (BOOLEAN)(IntResource->ShareDisposition == CmResourceShareShared);
status = IoConnectInterruptEx(¶ms);
if (!NT_SUCCESS(status)) {
...
}