Использование CONNECT_FULLY_SPECIFIED версии IoConnectInterruptEx
Драйвер может использовать CONNECT_FULLY_SPECIFIED версию IoConnectInterruptEx , чтобы зарегистрировать подпрограмму InterruptService для определенного прерывания. Драйвер может использовать версию CONNECT_FULLY_SPECIFIED начиная с Windows Vista. Связываясь с библиотекой Iointex.lib, драйвер может использовать версию CONNECT_FULLY_SPECIFIED в Windows 2000, Windows XP и Windows Server 2003. Дополнительные сведения см. в разделе Использование IoConnectInterruptEx до Windows Vista.
Драйвер задает значение CONNECT_FULLY_SPECIFIED в параметреParameters-Version> и использует члены Parameters-FullySpecified> для указания других параметров операции:
Parameters-FullySpecified.PhysicalDeviceObject> указывает PDO для устройства, которое обслуживает ISR.
Parameters-FullySpecified.ServiceRoutine> указывает на подпрограмму InterruptService, а Parameters-FullySpecified>. ServiceContext указывает значение, которое система передает в качестве параметра ServiceContext в InterruptService. Драйвер может использовать его для передачи контекстных сведений. Дополнительные сведения о передаче сведений о контексте см. в разделе Предоставление сведений о контексте ISR.
Драйвер предоставляет указатель на переменную PKINTERRUPT в Parameters-FullySpecified.InterruptObject>. Подпрограмма IoConnectInterruptEx задает эту переменную так, чтобы она указывала на объект прерывания для прерывания, который можно использовать при удалении ISR.
Драйверы могут при необходимости указать спин-блокировку в Parameters-FullySpecified.SpinLock> для системы, используемой при синхронизации с ISR. Большинство драйверов могут просто указать ЗНАЧЕНИЕ NULL , чтобы система могла выделить спин-блокировку от имени драйвера. Дополнительные сведения о синхронизации с ISR см. в разделе Синхронизация доступа к данным устройства.
Драйвер должен указывать ключевые свойства прерывания в других элементах Parameters-FullySpecified>. Система предоставляет необходимую информацию в массиве структур CM_PARTIAL_RESOURCE_DESCRIPTOR при отправке IRP_MN_START_DEVICE IRP драйверу.
Система предоставляет для каждого прерывания CM_PARTIAL_RESOURCE_DESCRIPTOR структуру с элементом Type , равным CmResourceTypeInterrupt. Для прерывания с сигналом сообщения устанавливается бит CM_RESOURCE_INTERRUPT_MESSAGE элемента Flags ; в противном случае он очищается.
Элемент u.InterruptCM_PARTIAL_RESOURCE_DESCRIPTOR содержит описание прерывания на основе строки, а элемент 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 |
ПрерываниеMode |
& CM_RESOURCE_INTERRUPT_LATCHED флагов |
& CM_RESOURCE_INTERRUPT_LATCHED флагов |
ProcessorEnableMask |
u.Interrupt.Affinity |
u.MessageInterrupt.Translated.Affinity |
Драйвер будет получать CM_PARTIAL_RESOURCE_DESCRIPTOR структуры только для прерываний с сигналом сообщения в Windows Vista и более поздних версиях Windows.
В следующем примере кода показано, как зарегистрировать подпрограмму InterruptService с помощью CONNECT_FULLY_SPECIFIED.
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)) {
...
}