Использование подпрограмм службы прерываний на пассивном уровне
Начиная с Windows 8 драйвер может использовать подпрограмму Io Подключение InterruptEx для регистрации подпрограммы прерываний на пассивном уровне (ISR). При возникновении связанного прерывания обработчик прерываний ядра планирует выполнение этой подпрограммы в IRQL = PASSIVE_LEVEL. IsR может потребоваться запустить на пассивном уровне, если он может получить доступ к регистрам оборудования устройства только через запросы ввода-вывода. IsR пассивного уровня может синхронно отправлять запрос ввода-вывода на устройство и блокировать до завершения запроса.
Регистрация isR пассивного уровня
Входной параметр Io Подключение InterruptEx — это указатель на структуру IO_CONNECT_INTERRUPT_PARAMETERS. Чтобы зарегистрировать isR пассивного уровня, задайте для элемента версии этой структуры значение CONNECT_FULLY_SPECIFIED или CONNECT_LINE_BASED. Если версия = CONNECT_FULLY_SPECIFIED, установите для элемента Irql значение PASSIVE_LEVEL, элемент SynchronizeIrql имеет значение PASSIVE_LEVEL, а элемент SpinLock имеет значение NULL. Если версия = CONNECT_LINE_BASED, задайте SynchronizeIrql = PASSIVE_LEVEL и SpinLock = NULL.
Если объект прерывания указывает isR пассивного уровня, подпрограмма KeSynchronizeExecution использует объект события синхронизации ядра вместо блокировки спина для синхронизации выполнения подпрограммы SynchCritSection с ISR.
Этот объект события выделяется подпрограммой Io Подключение InterruptEx в вызове, который регистрирует isR пассивного уровня. Вызывающий объект не должен предоставлять блокировку спина в этом вызове. (То есть вызывающий объект должен задать Элемент SpinLock структуры IO_CONNECT_INTERRUPT_PARAMETERS значение NULL, если ISR выполняется на пассивном уровне.) В противном случае Io Подключение InterruptEx завершается ошибкой и возвращает состояние ошибки STATUS_INVALID_PARAMETER.
Подпрограммы KeAcquireInterruptSpinLock и KeReleaseInterruptSpinLock вызывают ошибку проверка, если ISR для предоставленного объекта прерывания выполняется в IRQL = PASSIVE_LEVEL.
Устройства, требующие обработки прерываний на пассивном уровне
Для устройства, сопоставленного с памятью, которое сигнализирует об запросе прерывания на уровне, isR устройства обычно вызывается в DIRQL из обработчика перехвата прерываний ядра. IsR управляет регистрами оборудования на устройстве, чтобы отключить прерывание.
Однако может потребоваться запустить ISR на IRQL = PASSIVE_LEVEL если связанное устройство сигнализирует об запросе прерывания на уровне, но аппаратные регистры устройства не могут быть доступны непосредственно из ISR, вызываемого в DIRQL из обработчика прерываний ядра. Например, регистры устройств могут не сопоставляться с памятью, или ISR может временно блокироваться во время доступа к регистрации.
Начиная с Windows 8 драйвер может зарегистрировать isR пассивного уровня. При возникновении прерывания обработчик перехвата прерываний ядра планирует запуск ISR в IRQL = PASSIVE_LEVEL. Перед возвратом обработчика необходимо замолчать прерывание в контроллере прерывания (или контроллере GPIO). Если устройство сигнализирует о прерывании, активировав границы, обработчик очищает прерывание в контроллере прерываний. Если устройство сигнализирует об прерывании на уровне, обработчик временно маскирует прерывание в контроллере прерывания; После запуска ISR ядро распаковывает прерывание.
Пример
Пример устройства, для которых может потребоваться isR пассивного уровня, — это устройство датчика, подключенное к последовательной шине с низкой мощностью, например IІC. Начиная с Windows 8 поддержка I²C и других простых периферийных автобусов (SPBS) обеспечивается расширением платформы SPB (SpbCx).
Чтобы получить доступ к регистрам устройства датчика, подключенного к IІC, драйвер датчика отправляет устройство датчика запрос ввода-вывода, который совместно обрабатывается SpbCx и драйвером контроллера для шины. Чтобы выполнить запрошенную операцию, контроллер SPB должен последовательно передавать данные через шину. Эта передача относительно медленна и не может выполняться в течение ограничений времени isR, выполняющегося в DIRQL. Однако isR пассивного уровня может отправлять запрос ввода-вывода синхронно, а затем блокировать до завершения запроса.
IsR пассивного уровня в этом примере может быть заблокирован в течение более длительного времени, если контроллер шины I²C отключен, когда ISR отправляет запрос ввода-вывода на прерывание устройства. В этом случае контроллер должен завершить переход к состоянию питания D0, прежде чем он сможет передать данные через шину.
В отличие от шины, такой как PCI, шина I²C в этом примере не предоставляет никаких средств, предназначенных для передачи запросов прерываний от периферийных устройств процессору. Вместо этого устройство датчика может сигнализировать о прерывании на устройстве контроллера GPIO, которое затем передает запрос прерывания процессору. Дополнительные сведения см. в статье о прерываниях GPIO.
Как правило, аппаратные регистры контроллера GPIO сопоставляются с памятью и могут быть доступны в DIRQL обработчиком перехвата прерываний ядра. Когда устройство датчика вызывает прерывание, обработчик должен замолчать прерывание, управляя битами прерываний в регистрах контроллера GPIO.
Для прерывания, активированного на уровне, обработчик прерываний ядра маскирует запрос прерывания на пин-коде GPIO, а затем планирует, чтобы ISR устройства датчика выполнялся на пассивном уровне. IsR должен очистить запрос прерывания с устройства датчика. После возврата ISR ядро распаковывает запрос прерывания на пин-коде GPIO.
Для прерывания, активированного краем, обработчик ловушки ядра очищает запрос прерывания на пин-коде GPIO, а затем планирует, чтобы ISR устройства датчика выполнялся на пассивном уровне.
Рабочие подпрограммы
В вызове Io Подключение InterruptEx драйвер имеет возможность разделить обработку прерывания между пассивным уровнем ISR и рабочей подпрограммой. Как правило, ISR должен выполнять начальную обработку прерывания (например, замолчать прерывание на уровне), а также отложить дополнительную обработку рабочей роли. Хотя и ISR, и рабочая роль выполняются на пассивном уровне, ISR выполняется относительно высокоприоритетно и может отложить другие высокоприоритетные задачи. Эти задачи могут включать isR пассивного уровня для новых прерываний.
В редких случаях прерывание может потребовать так мало обработки, что isR пассивного уровня может выполнять всю обработку прерывания, и не требуется никаких рабочих процедур.
Сведения об использовании isR пассивного уровня в драйверах KMDF см. в разделе "Поддержка прерываний пассивного уровня".