PersCom — Компьютерная Энциклопедия Компьютерная Энциклопедия

Натяжные потолки с установкой. Ваш новыи потолок натяжные потолки pro100-potolok.ru.

PCI и PCI-X

Прерывания PCI: INTx#, PME#, MSI и SERR#

Аппаратные прерывания в PC-совместимых компьютерах

Устройства PCI имеют возможность сигнализации об асинхронных событиях с помощью прерываний. На шине PCI возможны четыре типа сигнализации прерываний:

  • традиционная проводная сигнализация по линиям INTx;
  • проводная сигнализация событий управления энергопотреблением по линии PME#;
  • сигнализация с помощью сообщений — MSI;
  • сигнализация фатальной ошибки по линии SERR#.

В данной главе рассматриваются все эти типы сигнализации, а также общая картина поддержки аппаратных прерываний в PC-совместимых компьютерах. 

Аппаратные прерывания в PC-совместимых компьютерах

Аппаратные прерывания обеспечивают реакцию процессора на события, происходящие асинхронно по отношению к исполняемому программному коду. Напомним, что аппаратные прерывания делятся на маскируемые и немаскируемые. Процессор x86 по сигналу прерывания приостанавливает выполнение текущего потока инструкций, сохраняя в стеке состояние (флаги и адрес возврата), и выполняет процедуру обработки прерывания. Конкретная процедура обработки выбирается из таблицы прерываний по вектору прерывания — однобайтному номеру элемента в данной таблице. Вектор прерывания доводится до процессора разными способами: для немаскируемого прерывания он фиксирован, для маскируемых прерываний его сообщает специальный контроллер прерываний. Кроме аппаратных прерываний у процессоров x86 имеются также внутренние прерывания — исключения (exceptions), связанные с особыми случаями выполнения инструкций, и программные прерывания. Для исключений вектор определяется самим особым условием, и под исключения фирмой Intel зарезервированы первые 32 вектора (0–31 или 00–1Fh). В программных прерываниях номер вектора содержится в самой инструкции (программные прерывания — это лишь специфический способ вызова процедур по номеру, с предварительным сохранением в стеке регистра флагов). Все эти прерывания используют один и тот же набор из 256 возможных векторов. Исторически сложилось так, что векторы, используемые для аппаратных прерываний, пересекаются с векторами исключений и векторами для программных прерываний, используемых для вызовов сервисов BIOS и DOS. Таким образом, для ряда номеров векторов процедура, на которую ссылается таблица прерываний, должна в начале содержать программный код, определяющий, по какому поводу она вызвана: из-за исключения, аппаратного прерывания или же для вызова какого-то системного сервиса. Таким образом, процедура, собственно и обеспечивающая реакцию процессора на то самое асинхронное событие, будет вызвана только после ряда действий по идентификации источника прерываний. Здесь еще заметим, что один и тот же вектор прерывания может использоваться и несколькими периферийными устройствами — это так называемое разделяемое использование прерываний, которое подробно обсуждается ниже.

Вызов процедуры обслуживания прерываний в реальном и защищенном режимах процессора существенно различается:

  • в реальном режиме таблица прерываний содержит 4-байтные дальние указатели (сегмент и смещение) на соответствующие процедуры, которые вызываются дальним вызовом (Call Far с предварительным сохранением флагов). Размер (256 × 4 байт) и положение таблицы (начинается с адреса 0) фиксированы;
  • в защищенном режиме (и в его частном случае — режиме V86) таблица содержит 8-байтные дескрипторы прерываний, которые могут быть шлюзами прерываний (Interrupt Gate), ловушек (Trap Gate) или задач (Task Gate). Размер таблицы может быть уменьшен (максимальный — 256 × 8 байт), положение таблицы может меняться (определяется содержимым регистра IDT процессора). Код обработчика прерываний должен быть не менее привилегированным, чем код прерываемой задачи (иначе сработает исключение защиты). По этой причине обработчики прерываний должны работать на уровне ядра ОС (на нулевом уровне привилегий). Смена уровня привилегии при вызове обработчика приводит к дополнительным затратам времени на переопределение стека. Прерывания, вызывающие переключение задач (через Task Gate), расходуют значительноевремя на переключение контекста — выгрузку регистров процессора в сегмент состояния старой задачи и их загрузку из сегмента состояния новой.

Номера векторов, используемых для аппаратных прерываний в операционных системах защищенного режима, отличаются от номеров, используемых в ОС реального режима, чтобы исключить их конфликты с векторами, используемыми для исключений процессора.

На немаскируемое прерывание (NMI — Non-Maskable Interrrupt) процессор реагирует всегда (если обслуживание предыдущего NMI завершено); этому прерыванию соответствует фиксированный вектор 2. Немаскируемые прерывания в PC используются для сигнализации о фатальных аппаратных ошибках. Сигнал на линию NMI приходит от схем контроля памяти (четности или ECC), от линий контроля шины ISA (IOCHK) и шины PCI (SERR#). Сигнал NMI блокируется до входа процессора установкой в 1 бита 7 порта 070h, отдельные источники разрешаются и идентифицируются битами порта 061h:

  • бит 2 R/W — ERP — разрешение контроля ОЗУ и сигнала SERR# шины PCI;
  • бит 3 R/W — EIC — разрешение контроля шины ISA;
  • бит 6 R — IOCHK — ошибка контроля на шине ISA (сигнал IOCHK#);
  • бит 7 R — PCK — ошибка четности ОЗУ или сигнал SERR# на шине PCI.

Реакция процессора на маскируемые прерывания может быть задержана сбросом его внутреннего флага IF (инструкция CLI запрещает прерывания, STI — разрешает). Маскируемые прерывания используются для сигнализации о событиях в устройствах. По возникновении события, требующего реакции, адаптер (контроллер) устройства формирует запрос прерывания, который поступает на вход контроллера прерываний. Задача контроллера прерываний — довести до процессора запрос прерывания и сообщить вектор, по которому выбирается программная процедура обработки прерываний.

Процедура обработки прерывания от устройства должна выполнить действия по обслуживанию данного устройства, включая сброс его запроса для обеспечения возможности реакции на следующие события, и послать команды завершения в контроллер прерываний. Вызывая процедуру обработки, процессор автоматически сохраняет в стеке значение всех флагов и сбрасывает флаг IF, что запрещает маскируемые прерывания. При возврате из этой процедуры (по инструкции IRET) процессор восстанавливает сохраненные флаги, в том числе и установленный (до прерывания) IF, что снова разрешает прерывания. Если во время работы обработчика прерываний требуется реакция на иные прерывания (более приоритетные), то в обработчике должна присутствовать инструкция STI. Особенно это касается длинных обработчиков; здесь инструкция STI должна вводиться как можно раньше, сразу после критической (не допускающей прерываний) секции. Следующие прерывания того же или более низкого уровня приоритета контроллер прерываний будет обслуживать только после получения команды завершения прерывания EOI (End Of Interrupt).

В IBM PC-совместимых компьютерах применяется два основных типа контроллеров прерываний:

  • PIC (Peripheral Interrupt Controller) — периферийный контроллер прерываний, программно совместимый с «историческим» контроллером 8259A, применявшимся еще в первых моделях IBM PC. Со времен IBM PC/AT применяется связка из пары каскадно соединенных PIC, позволяющая обслуживать до 15 линий запросов прерываний;
  • APIC (Advanced Peripheral Interrupt Controller) — усовершенствованный периферийный контроллер прерываний, введенный для поддержки мультипроцессорных систем в компьютеры на базе процессоров 4–5 поколений (486 и Pentium) и используемый поныне для более поздних моделей процессоров. Кроме поддержки мультипроцессорных конфигураций современный APIC позволяет увеличивать число доступных линий прерываний и обрабатывать запросы прерываний от устройств PCI, посылаемые через механизм сообщений (MSI). Компьютер, оснащенный контроллером APIC, обязательно имеет возможность функционировать и в режиме, совместимом со стандартной связкой пары PIC. Этот режим включается по аппаратному сбросу (и включению питания), что позволяет использовать старые ОС и приложения MS DOS, «не знающие» APIC и мультипроцессирования.

Традиционная схема формирования запросов прерываний с использованием пары PIC изображена на рисунке ниже.

На входы контроллеров прерываний поступают запросы от системных устройств (клавиатура, системный таймер, CMOS-таймер, сопроцессор), периферийных контроллеров системной платы и карт расширения. Традиционно все линии запросов, не занятые перечисленными устройствами, присутствуют на всех слотах шины ISA/ EISA. Эти линии обозначаются как IRQx и имеют общепринятое назначение (см. таблицу ниже). Часть этих линий отдается в распоряжение шины PCI. В таблице отражены и приоритеты прерываний — запросы расположены в порядке их убывания. Номера векторов, соответствующих линиям запросов контроллеров, система приоритетов и некоторые другие параметры задаются программно при инициализации контроллеров. Эти основные настройки остаются традиционными для обеспечения совместимости с программным обеспечением, но различаются для ОС реального и защищенного режимов. Так, например, в ОС Windows базовые векторы для ведущего и ведомого контроллеров — 50h и 58h соответственно.

Имя (номер1) Вектор2 Вектор3 Контроллер/маска Описание
NMI 02h
 

 

 
IRQ0 08h 50h
 
#1/1h
 
Контроль канала, четность памяти (в XT — сопроцессор)
 
IRQ1 09h 51h
 
#1/2h
 
Клавиатура
 
IRQ2 0Ah 52h
 
#1/4h
 
XT — резерв, AT — недоступно (подключается каскад IRQ8–IRQ15)
 
IRQ8 70h
 
58h
 
#2/1h
 
CMOS RTC — часы реального времени
 
IRQ9 71h
 
59h
 
#2/2h
 
Резерв
 
IRQ10 72h
 
5Ah
 
#2/4h
 
Резерв
 
IRQ11 73h
 
5Bh
 
#2/8h
 
Резерв
 
IRQ12 74h
 
5Ch
 
#2/10h
 
PS/2-Mouse (резерв)
 
IRQ13 75h
 
5Dh
 
#2/20h
 
Математический сопроцессор
 
IRQ14 76h
 
5Eh
 
#2/40h
 
HDC — контроллер НЖМД
 
IRQ15 77h
 
5Fh
 
#2/80h
 
Резерв
 
IRQ3 0Bh
 
52h
 
#1/4h
 
COM2, COM4
 
IRQ4 0Ch
 
53h
 
#1/10h
 
COM1, COM3
 
IRQ5I 0Dh
 
54h
 
#1/20h
 
XT — HDC, AT — LPT2, Sound (резерв)
 
IRQ6 0Eh
 
55h
 
#1/40h
 
FDC — контроллер НГМД
 
IRQ7 0Fh
 
56h
 
#1/80h
 
LPT1 — принтер
 

*1 Запросы прерываний 0, 1, 8 и 13 на шины расширения не выводятся.
*2 Указаны номера векторов при работе в реальном режиме процессора.
*3 Указаны номера векторов при работе в ОС Windows.

Каждому устройству, для поддержки работы которого требуются прерывания, должен быть назначен свой номер прерывания. Назначения номеров прерываний выполняются с двух сторон: во-первых, адаптер, нуждающийся в прерываниях, должен быть сконфигурирован на использование конкретной линии шины (джамперами или программно). Во-вторых, программное обеспечение, поддерживающее данный адаптер, должно быть проинформировано о номере используемого вектора. В процессе назначения прерываний может участвовать система PnP для шин ISA и PCI, для распределения линий запросов между шинами служат специальные параметры CMOS Setup. Современные ОС имеют возможность изменить назначение запросов относительно распределения, сделанного через CMOS Setup.

После того как произведено конфигурирование системы прерываний (проинициализирован контроллер прерываний, устройствам назначены линии запросов и установлены указатели на процедуры обработки), отработка маскируемых аппаратных прерываний происходит следующим образом:

  • устройство по событию прерывания возбуждает назначенную ему линию запроса прерывания;
  • контроллер принимает сигналы запросов от источников прерываний (сигналы IRQx) и при наличии незамаскированного запроса подает сигнал общего запроса прерывания (сигнал INTR) процессору x86;
  • процессор, реагируя на запрос (когда прерывания флагом IF разрешены), сохраняет в стеке содержимое регистра флагов и адрес возврата, после чего формирует шинный цикл INTA (Interrupt Acknowledge, подтверждение прерывания), который доводится до контроллера прерываний;
  • в момент получения сигнала INTA контроллер прерываний фиксирует состояние своих входов запросов — к этому моменту их состояние могло измениться: могли появиться новые запросы или пропасть запрос от «нетерпеливого» устройства. Контроллер анализирует поступившие запросы в соответствии с запрограммированной схемой приоритетов и посылает процессору вектор прерывания, соответствующий самому приоритетному незамаскированному запросу, присутствующему на входе контроллера в момент подачи шинной команды INTA. При этом контроллер выполняет и некоторые действия в соответствии с установленной приоритетной политикой, учитывающие, какой именно вектор был послан (какой из запросов пошел на обслуживание);
  • получив вектор прерывания, процессор по его номеру вызывает соответствующую процедуру обработки прерывания. Если данный вектор прерывания используется не только для аппаратных прерываний, но и для исключений и/или программных прерываний, то процедура в первую очередь должна определить, к какому из этих типов относится данное событие. Для этого процедура может обратиться к контроллеру PIC (прочитать регистр ISR) и проанализировать состояние регистров процессора. Дальнейшие шаги рассматриваются для случая, когда обнаружено аппаратное прерывание;
  • процедура обработки прерывания должна идентифицировать источник прерывания — определить устройство, его вызвавшее. В случае разделяемого использования несколькими устройствами данного номера запроса (следовательно, и вектора) идентифицировать источник прерывания можно только последовательными обращениями к регистрам каждого из этих устройств. При этом следует учитывать возможность поступления запросов от нескольких устройств одновременно или в процессе обработки прерывания от одного из них;
  • процедура должна обслужить устройство-источник прерывания — выполнить «полезные» действия, связанные с событием, о котором и сигнализировало устройство. Это обслуживание должно обеспечить и снятие сигнала запроса прерывания от данного устройства. В случае разделяемых прерываний источников может быть и несколько, и все они требуют обслуживания;
  • если обработка прерывания занимает значительное время, в течение которого требуется реакция системы на более приоритетные запросы, то после критической секции в обработчик включают инструкцию STI, устанавливающую флаг разрешения прерываний (IF) в процессоре. С этого момента возможны вложенные прерывания, прерывающие работу данного обработчика другой, более приоритетной процедурой;
  • процедура обработки прерывания должна послать контроллеру команду завершения обработки прерывания EOI (End Of Interrupt), по которой контроллер разрешит последующий прием сигнала с обслуженного входа и менее приоритетных. Это должно быть сделано после снятия сигнала прерывания от обслуженных устройств, иначе контроллер после EOI пошлет повторный запрос. Обработчик прерывания, для которого запрос поступил от ведомого контроллера, должен послать EOI как ведомому, так и ведущему контроллеру. Участок обработчика, начинающийся от подачи команды EOI до завершения (инструкции IRET), должен быть непрерываемым, то есть он является критической секцией. Если обработчик разрешал вложенные прерывания, то перед подачей команды EOI должна присутствовать инструкция CLI, запрещающая прерывания;
  • завершается обработка прерывания инструкцией IRET, по которой процессор возвращается к выполнению прерванного потока инструкций, предварительно извлекая из стека содержимое регистра флагов. При этом аппаратные прерывания снова окажутся разрешенными.

Эта последовательность описана применительно к обычному контроллеру прерываний (PIC), в системах с APIC меняется способ доставки вектора прерывания от контроллера к процессору, а в прерываниях MSI меняется способ доставки сигнала от устройства к контроллеру APIC. Эти нюансы описаны в последующих разделах.



Традиционный контроллер прерываний — PIC

Контроллер прерываний (PIC) 8259A является периферийным устройством, которое связано с процессором через системную шину. По этой шине процессор может обращаться к регистрам контроллера, программируя его режимы и управляя им, а также получать от контроллера 8-битный вектор прерывания, для чего в интерфейсе системной шины процессора имеется специальная команда подтверждения прерывания (INTA). Контроллер 8259A имеет 8 входов запросов от источников и один выход общего запроса. Каждому из входов соответствует свой вектор; программированием регистров контроллера задается номер вектора для входа 0, остальным входам соответствуют последующие номера векторов. Каждый вход может быть программно замаскирован — тогда он не будет вызывать сигнал общего запроса. Контроллер занимает два адреса в пространстве ввода/вывода, программное обращение по этим адресам обеспечивает выполнение следующих функций:

  • управление режимами работы контроллера;
  • управление приоритетами и масками запросов;
  • идентификацию запросов прерывания без вырабатывания общего запроса — обслуживание прерываний по опросу (полинг). 

В контроллере имеется три регистра: IRR, IMR и ISR. С каждым входом запроса в контроллере связано по одному биту каждого из этих регистров; бит 0 каждого из этих регистров относится к входу 0, бит 1 — к входу 1, бит 7 — ко входу 7. Регистры имеют следующие назначения:

  • IRR (Interrupt Request Register) — регистр запросов прерываний, в котором бит устанавливается при обнаружении сигнала прерывания на соответствующем входе, независимо от маски;
  • IMR (Interrupt Mask Register) — регистр масок прерываний. Единичное значение бита означает замаскированность данного входа — по запросу с замаскированного входа общий запрос прерывания не генерируется;
  • ISR (Interrupt Service Register) — регистр обслуживаемого прерывания. Во время цикла подтверждения (INTA) в регистре устанавливается бит, соответствующий наиболее приоритетному запросу и, соответственно, формируемому вектору прерывания. В этот же момент обнуляется соответствующий бит запроса в регистре IRR. Бит в ISR обнуляется по получении контроллером команды EOI, а в режиме автоматического подтверждения (по команде AEOI) он обнуляется сразу после передачи вектора прерывания.

Контроллер прерываний позволяет программировать свои входы на чувствительность к уровню или перепаду сигнала:

  • чувствительность к уровню (level sensitive) означает, что контроллер прерываний вырабатывает запрос прерывания процессора по факту обнаружения определенного уровня на входе IRQx. Если к моменту завершения обработки этого запроса (после записи команды EOI в регистр контроллера прерываний) контроллер снова обнаруживает активный уровень на том же входе DRQx, то он снова сформирует запрос на прерывание процессора;
  • чувствительность к перепаду (edge sensitive) означает, что контроллер прерываний вырабатывает запрос прерывания процессора только по факту обнаружения перепада (на ISA — положительного) на входе IRQx. Повторно запрос по этому входу возможен только по следующему такому же перепаду, то есть сигнал предварительно должен вернуться в исходное состояние.

В любом случае сигнал запроса аппаратного прерывания IRQx должен удерживаться генерирующей его схемой, по крайней мере, до цикла подтверждения прерывания процессором — именно в этот момент PIC определяет самый приоритетный незамаскированный запрос и по нему формирует вектор. Если к этому моменту запрос будет снят, источник прерывания корректно идентифицирован не будет и контроллер сообщит ложный вектор прерывания (spurious interrupt), соответствующий его входу с максимальным номером (IRQ7 для первого контроллера и IRQ15 для второго). Обычно периферийные устройства строят так, что сигнал запроса сбрасывается при обращении программы обслуживания прерывания к соответствующим регистрам адаптера, так что ложных прерываний возникать не должно.

Стандартный PIC позволяет управлять чувствительностью только для всех входов одновременно. В шине ISA и системной периферии (таймеры, контроллер клавиатуры) прерывание сигнализируется положительным перепадом сигнала на линии запроса, так что традиционно контроллеры PIC программируют на чувствительность к перепаду. Более поздние модификации PIC, применяемые в системах с шиной EISA и ISA с поддержкой PnP, а также новые контроллеры APIC при работе в PIC-совместимом режиме позволяют управлять чувствительностью для каждого входа индивидуально.

Один PIC 8259A позволяет обслуживать 8 запросов прерываний; в PC/AT применяется каскадное соединение двух контроллеров, один из которых является ведущим, другой — ведомым. Ведущий контроллер 8259A#1 обслуживает запросы 0, 1, 3–7; его выход подключается к входу запроса прерываний процессора. К его входу 2 подключен ведомый контроллер 8259A#2, который обслуживает запросы 8–15. При этом поддерживается вложенность приоритетов — запросы 8–15 со своим рядом убывающих приоритетов вклиниваются между запросами 1 и 3 ведущего контроллера, приоритеты запросов которого также убывают с ростом номера. В XT каскадирование не применялось и один контроллер 8259A обслуживал все 8 линий запросов.

Контроллер 8259A позволяет работать с запросами в различных режимах:

  • Fully Nested Mode — режим полной вложенности приоритетов; каждому входу (уровню) запросов назначается свой приоритет (самый приоритетный — вход 0). В момент подтверждения прерывания контроллер устанавливает в регистре ISR бит, соответствующий самому приоритетному запросу на данный момент (и переданному вектору прерывания), и до его сброса игнорирует последующие запросы с данного входа и менее приоритетные запросы;
  • Special Fully Nested Mode — специальный режим полной вложенности, используемый в ведущем контроллере при каскадном соединении. В этом режиме ведущий контроллер не блокирует запрос от входа, к которому подключен ведомый контроллер. Это позволяет ведомому контроллеру сигнализировать о запросе, более приоритетном, чем предыдущий. В конце процедуры обработки ведомому контроллеру посылается неспецифический EOI, после чего считывается его ISR. Если в ISR ни один бит не установлен, то неспецифический EOI посылается и ведущему контроллеру, что позволит ему обслуживать и менее приоритетные входы. Если же в ISR ведомого контроллера есть ненулевые биты, то ведущий контроллер снова подаст общий запрос прерывания, и на его подтверждение ведомый пошлет соответствующий вектор. Упоминаний о проверке на 0 значения ISR вторичного контроллера до подачи EOI первичному применительно к PC автору не встречалось. Очевидно, что в ней нет необходимости, если не используется ротация приоритетов: если у вторичного контроллера есть еще не обслуженные запросы, то они будут обслужены в соответствии со своим приоритетом (до IRQ3…IRQ7);
  • Automatic Rotation Mode — режим автоматической ротации приоритетов позволяет организовать равноприоритетное обслуживание всех запросов. В этом режиме уровень, запрос от которого пошел на обслуживание, получает низший приоритет. Ротация приоритетов организуется подачей команд OCW2 с кодом операции 101 или 100;
  • Specific Rotation Mode — режим специфицированной ротации: командой OCW2 с кодом операции 111 или 110 указанному уровню устанавливается низший приоритет;
  • Poll Mode — режим опроса, в котором общий запрос INTR не вырабатывается. По команде Poll, посылаемой через OCW3, контроллер фиксирует самый проритетный запрос. Последующее считывание из регистра контроллера даст байт, в котором бит 7 указывает на наличие запроса, а в битах [2:0] содержится номер самого приоритетного запроса;
  • Normal EOI — нормальный режим завершения, в котором бит ISR сбрасывается явной командой EOI, посылаемой контроллеру в конце исполнения обработчика прерывания. Обычно используется команда неспецифического EOI (код 20h), по которой сбрасывается бит ISR, соответствующий самому приоритетному из обслуживаемых запросов. Возможна команда и специфического EOI, которая сбрасывает в ISR бит, указанный в данной команде. Бит для замаскированного запроса таким способом сброшен быть не может;
  • Auto EOI — автоматическая генерация неспецифического EOI контроллером в конце цикла подтверждения прерывания. Этот режим применим лишь в случаях, когда не требуется поддержка вложенности прерываний, и только для ведущего контроллера.

Контроллер 8259A своими 8-битными регистрами приписывается к пространству ввода/вывода и занимает 2 смежных адреса. Обмен с регистрами контроллеров должен производиться только однобайтными операциями ввода/вывода. В современных PC-совместимых компьютерах контроллеры имеют и дополнительные регистры (ELCR). Положение регистров в пространстве ввода/вывода приведено в таблице ниже.

Адрес 8259A#1  Адрес  8259A#2 Назначение Тип
020h
0A0h
Подача команд ICW1, OCW2, OCW3 WO

 

 
Чтение регистров IRR, ISR или данных полинга (в зависимости от OCW3) RO
 
021h
 
0A1h
 
Подача команд ICW2, ICW3, ICW4, OCW1
 
WO
 

 

 
Обращение к регистру IMR
 
RW
 
4D0h 4D1h Обращение к регистру ELCR
 
RW
 

Контроллер имеет два режима работы: режим инициализации и операционный. После сброса контроллер инициализируется последовательностью команд ICW1– ICW4 (Initialization Command Words) длиной до 4 байт, после чего переходит в операционный режим. В операционном режиме (Operation Mode)контроллер воспринимает команды управления OCW1–OCW3 (Operation Control Words). В операционном режиме он может быть и реинициализирован, признаком начала инициализации является единичное значение бита 4 в байте, записываемом по адресу 020h (0A0h). Назначение команд и регистров контроллера прерываний приведено ниже

Команда инициализации ICW1 (запись по адресу 020h или 0A0h) служит для конфигурирования контроллера:

  • биты [7:5]: 0 (в PC не используются);
  • бит 4:1 — признак команды инициализации (в командах управления он нулевой);
  • бит 3 — чувствительность линий запроса: 0 — прерывание по перепаду, 1 — прерывание по уровню. В современных контроллерах игнорируется, в них используется отдельный регистр ELCR, управляющий чувствительностью каждого из входов;
  • бит 2 = 0 (в PC не используется);
  • бит 1:0 — каскадное включение пары контроллеров, 1 — одиночный контроллер;
  • бит 0:1 — признак использования ICW4.

Команда инициализации ICW2 (запись по адресу 021h или 0A1h) задает номер вектора, генерируемого данным контроллером для входа 0. Биты [2:0] должны иметь нулевые значения.

Команда инициализации ICW3 (запись по адресу 021h или 0A1h) используется только для каскадного включения:

  • для ведущего контроллера (Master, 8259A#1) биты [0:7] указывают на наличие ведомых контроллеров на линиях IRQ0–IRQ7 соответственно. В AT ICW3 = 04h (ведомый на IRQ2);
  • для ведомого контроллера (Slave, 8259A#2) биты [2:0] содержат номер входа ведущего контроллера, к которому он подключен, биты [7:3] сброшены. В AT ICW3 = 02h (подключен к IRQ2 ведущего).

Команда инициализации ICW4 (запись по адресу 021h или 0A1h) задает режим работы контроллера, его применение обязательно при начальной инициализации:

  • биты [7:5]: 0 — не используются;
  • бит 4 — SFNM (Special Fully Nested Mode): 1 — специальный режим полной вложенности разрешен, 0 — запрещен;
  • бит 3 — BUF (Buffered): 1 — признак буферизованности шины;
  • бит 2 — M/S (Master/Slave), положение в каскаде: 1 — ведущий, 0 — ведомый. В современных контроллерах не используется (сброшен);
  • бит 1 — AEOI (Auto End Of Interrupt): 1 — разрешение автоматического завершения прерывания, 0 — нормальный режим (требует подачи EOI);
  • бит 0 — тип используемого процессора: 1 — 8086/8088 и далее, 0 — 8080.

Команда управления OCW1 (запись по адресу 021h или 0A1h) задает маски запросов, единичное значение бита означает маскирование запроса. Биты [0:7]определяют маски запросов для IRQ0–IRQ7 (8259#1) или IRQ8–IRQ15 (8259#2).

Команда управления OCW2 (запись по адресу 020h или 0A0h) — завершение обслуживания прерывания (команда EOI), управление приоритетом:

  • биты [7:5] задают код операции (в операциях, помеченных звездочкой, используется поле LLL в битах 2–0):
  •       -001 — неспецифический EOI;
  •       -011* — специфический EOI для запроса LLL;
  •       -101 — неспецифический EOI с ротацией приоритета;
  •       -100 — установка ротации приоритета в режиме AEOI;
  •       -000 — сброс ротации приоритета в режиме AEOI;
  •       -111* — специфический EOI с ротацией приоритета (установкой низшего приоритета для заданного уровня);
  •       -110* — установка низшего приоритета для заданного уровня;
  •       -010 — нет операции.
  • биты [4:3]: 00 — признак OCW2;
  • биты [2:0] — поле LLL — номер уровня, к которому относится команда (только для команд, помеченных звездочкой).

Команда управления OCW3 (запись по адресу 020h или 0A0h) — оперативное управление контроллером:

  • бит 7:0 — не используется;
  • биты [6:5] — режим специального маскирования (в PC не используется): 11 — установить, 10 — сбросить, 00, 01 — не изменять;
  • биты [4:3]: 01 — признак OCW3;
  • бит 2 — признак команды опроса (полинга). После команды полинга на последующую команду чтения порта 020h или 0A0h контроллер ответит байтом, кодирующим запрос прерывания с максимальным приоритетом. Для PC полинг обычно не используется (бит 2 — нулевой), а контроллер передает вектор прерывания по команде INTA;
  • биты [1:0] — управление чтением регистров при операциях ввода по адресу 020h или 0A0h:
  •       -10 — чтение IRR — регистра запросов;
  •       -11 — чтение ISR — регистра обслуживаемого прерывания;
  •       -00, 01 — не изменять выбор регистра.

Регистры ELCR, имеющиеся в современных компьютерах, позволяют селективно управлять чувствительностью входов. В этих регистрах каждый бит отвечает за режим своего входа запроса: 0 — чувствительность к положительному перепаду, 1 — чувствительность к высокому уровню. Для входов IRQ0, 1, 2, 8 и 13 (таймер, клавиатура, вторичный контроллер прерываний, часы и исключение сопроцессора), допускается чувствительность только к перепаду (соответствующие биты должны быть нулевыми, но чипсет может их и игнорировать). Линии запросов прерывания от PCI по пути ко входам инвертируются, так как на них запрос сигнализируется низким уровнем.

В IBM PC/XT/AT используется специальный режим вложенных прерываний с фиксированным приоритетом и автоматическим неспецифическим завершением; типовые байты инициализации и управления приведены в следующей таблице. После инициализации (процедурой POST и при загрузке ОС) все неиспользуемые входы контроллеров замаскированы (на запросы прерываний реагировать не будут), а их векторы прерываний указывают на «заглушку» — процедуру с единственной инструкцией IRET. Для подключения обработчика прерывания от устройства первым делом следует загрузить обработчик в память и установить указатель на него в таблице прерываний. Далее следует размаскировать соответствующий ему вход в контроллере прерываний, для чего выполняется чтение регистра маски (адрес 21h для 8259A#1, A1h для 8259A#2), обнуление соответствующего бита и запись в регистр нового значения маски. Если обработчик прерывания удаляется из памяти, предварительно должен быть замаскирован соответствующий ему вход контроллера. Все изменения в таблице прерываний должны выполняться при замаскированных прерываниях, чтобы избежать попытки использования вектора в процессе его модификации (это приведет к «вылету» программы — вызову по некорректному адресу).
 

Каждая процедура обработки аппаратного прерывания должна завершаться командой неспецифического EOI — посылкой OCW2 = 20h контроллеру:

Байт 8259A#1 8259A#2
ICW1 10h 10h
ICW2 08h 70h
ICW3 04h 02h
ICW4 1Fh 1Bh
OCW3 0Ah 0Ah

 

На современных системных платах функции контроллеров прерываний возлагаются на чипсет, который может иметь и более гибкие возможности управления, чем пара контроллеров 8259A. Процедура инициализации контроллеров может и отличаться от традиционной, но ею занимается тест POST, который «знает» особенности системной платы. Однако в операционном режиме всегда сохраняется программная совместимость с 8259A.



«Продвинутый» контроллер прерываний — APIC

Контроллер APIC в первую очередь предназначен для симметричных мультипроцесорных систем (SMP), описанных в документе Intel «MultiProcessor Specification» (MPS), в Сети доступна версия 1.4, 1997 год. Здесь симметрия рассматривается в двух аспектах:

  • симметрия памяти — все процессоры пользуются общей памятью, работают с одной копией ОС;
  • симметрия ввода/вывода — все процессоры разделяют общие устройства ввода/вывода и общие контроллеры прерываний.

Система может быть симметричной по памяти, но асимметричной по прерываниям от ввода/вывода, если для них используется выделенный процессор. В x86 симметрию по прерываниям обеспечивает APIC. Система с APIC состоит из локальных контроллеров, установленных в процессорах, и контроллеров прерываний от ввода/вывода (одного или нескольких). Все контроллеры APIC соединены между собой локальной шиной, по которой они обмениваются друг с другом сообщениями. Задача каждого локального контроллера (Local APIC) — трансляция сообщений, принятых по локальной шине, в сигналы, вызывающие все аппаратные прерывания своего процессора — маскируемые (INTR), немаскируемые (NMI) и прерывания системного обслуживания (SMI). Кроме того, локальные APIC позволяют каждому процессору генерировать прерывания для других процессоров. Локальный контроллер имеет внутренний интервальный таймер, позволяющий вырабатывать прерывания через программируемый интервал времени. Контроллер прерываний от ввода/вывода (I/O APIC) преобразует запросы аппаратных прерываний от устройств в сообщения протокола локальной шины APIC. В мультипроцессорном режиме он отвечает за распределение прерываний по процессорам, для чего может использоваться статическое или динамическое распределение. В случае статического распределения для каждого номера прерывания указывается номер процессора, который его обслуживает. В случае динамического распределения каждое прерывание направляется наименее приоритетному в данный момент процессору. Этот же контроллер отвечает за распространение сигналов о системных событиях (NMI, INIT, SMI) и межпроцессорных прерываний. Прерывания в мультипроцессорных системах подробно рассмотрены в документе «Intel Architecture Software Developer’s Manual Volume 3: System Programming Guide», доступном на сайте http://www.intel.com. Здесь же ограничимся описаниями возможностей, предоставляемыми для сигнализации прерываний ввода/вывода контроллерами APIC. Контроллер I/O APIC является частью чипсета системной платы, например, он входит в хабы ICH2 и ICH3 чипсетов Intel. В специфкации MPS определено три режима обработки прерываний: 

  • режим PIC (PIC Mode) — эмуляция пары PIC 8259A с традиционной передачей сигналов прерывания одному процессору (загрузочному, BSP Bootstrap Processor) по линиям INTR и NMI;
  • режим «виртуальных проводов» (Virtual Wire Mode) — то же, но с подачей сигналов прерывания по локальной шине APIC. При этом I/O APIC может работать совместно с PIC 8259A, обеспечивая дополнительные возможности (в частности, дополнительные входы запросов прерываний);
  • симметричный режим (Symmetric I/O Mode) — сообщения о прерываниях от устройств генерирует APIC; прерывания могут доставляться любому процессору; каждый вход запроса индивидуально программируется с помощью таблицы перенаправления прерываний (I/O Redirection Table).

Первые два режима обеспечивают полную совместимость с системой прерываний PC/AT, с программной точки зрения они эквивалентны, различия лежат в области схемотехники. По аппаратному сбросу (и включении питания) система начинает работать в одном из этих режимов. Когда система подготовится к переходу в MP-режим, APIC переводится в симметричный режим и активизирует таблицу перенаправлений прерываний (предварительно программно инициализированную).

В MP-системе присутствует таблица описаний ее компонентов; к прерываниям в этой таблице относятся описатели всех I/O APIC, а также описатели назначений всех используемых источников прерываний, связанных с I/O APIC и локальными APIC. В описателе назначения для каждого источника прерываний указывается:

  • тип прерывания: векторное с передачей вектора через APIC, векторное с внешней передачей вектора (от PIC 8259A), NMI или SMI;
  • полярность сигнала и его тип (уровень или перепад);
  • идентификатор шины, на которой расположен источник;
  • идентификатор запроса на этой шине;
  • идентификатор и номер входа APIC, к которому подключен данный запрос.

Согласно MPS, для симметричных систем допустимы векторы в диапазоне 10h — FEh. Уровень приоритета прерывания определяется номером его вектора, деленным на 16. Самый приоритетный уровень — нулевой.

Выделение для сообщений APIC отдельной локальной шины позволяет освободить системную шину процессора от трафика, связанного с обслуживанием прерываний (подачи подтверждений прерываний для получения вектора). В современных процессорах используется локальная шина, состоящая из трех сигнальных линий: PICD[1:0] — двунаправленная шина данных и PICCLK — сигнал синхронизации (тактовая частота). Протокол шины обеспечивает распределенный механизм арбитража: в любой момент времени каждый APIC (локальный и I/O APIC) имеет уникальное значение приоритета арбитража (0–15), которое динамически меняется после успешной передачи сообщения. При попытке одновременного начала передачи сообщения несколькими APIC после фазы арбитража остается единственный победитель. Получатель сообщения подтверждает успешный прием; в случае неудачи сообщение передается повторно (обеспечивается надежная доставка). Сообщения, передаваемые по локальной шине APIC, программно-невидимы; реализация и протокол шины могут быть изменены производителями процессоров и чипсетов системных плат, но это не отразится на ПО.

Контроллер I/O APIC позволяет вырабатывать значительное число запросов прерываний; каждому запросу соответствует свой элемент в таблице перенаправлений, находящейся в APIC. Каждый элемент определяет способ реакции на свой запрос, вектор прерывания и процессор (процессоры) назначения, которые должны его обработать. С запросами связаны индивидуальные входы INTINn; определенный уровень или перепад сигнала на этих входах вызывает соответствующие запросы. Чувствительность и вектор (следовательно, и приоритет) для каждого запроса программируется индивидуально. Более совершенные модели I/O APIC позволяют вызывать прерывание и записью номера входа в регистр контроллера, что, например, используются для поддержки прерываний MSI на шине PCI. При этом возможна и экономия сигнальных входов: APIC может иметь входы INTINn не для всех номеров запросов, посылаемых через запись в этот регистр. Однако число запросов всегда ограничивается размером таблицы перенаправлений. Регистры контроллеров APIC отображаются на пространство памяти. Все локальные контроллеры APIC используют один и тот же диапазон адресов (по умолчанию базовый адрес FEE0 0000h) — к их регистрам обращаются только программы, исполняемые на их же процессорах, и эти обращения не выводятся на системную шину. Контроллеры I/O APIC доступны всем процессорам, по умолчанию базовый адрес первого I/O APIC — FEC0 0000h, базовые адреса остальных контроллеров (если таковые имеются) назначаются последовательно с шагом 1000h. Часть регистров адресуется непосредственно, большая часть регистров, включая и таблицу перенаправлений, адресуется косвенно.

Таблица. Непосредственно адресуемые регистры APIC

Адрес Размер, бит Тип Назначение
FEC0_0000h 8 R/W Index Register, индекс для доступа к косвенно адресуемым регистрам
FEC0_0010h 32 R/W Data Register, данные для обращений к косвенно адресуемым регистрам
FECO_0020h 8 WO IRQ Pin Assertion Register, регистр программной установки запросов прерываний (запись числа 0–23 эквивалентна подаче сигнала на соответствующий вход INTINn)
FECO_0040h 8 WO EOI Register — регистр завершения прерываний для входов, чувствительных к уровню. Запись байта — вектора прерывания — вызывает сброс бита Remote_IRR для всех входов, которым назначен данный вектор (аналогичное действие IOAPIC выполняет по сообщению EOI, полученному по локальной шине)

 

Таблица. Косвенно-адресуемые регистры APIC

Адрес Размер, бит Тип Назначение
00h 32 R/W ID (биты 24:27) — идентификатор (физический номер), программно назначаемый данному APIC. Остальные биты — резерв
01h 32 RO Version — версия (возможности IOAPIC): биты 23:16 — максимальный номер элемента в таблице перенаправления; бит 15 (PRQ) — признак наличия регистра программной установки запросов прерываний; биты 7:0 — номер версии; остальные биты — резерв
02h 32 RO Arbitration ID (биты 24:27) — текущее значение приоритета арбитража. Остальные биты — резерв
03h 32 R/W Boot Configuration — конфигурация: бит 0 — DT (Delivery Type), управление механизмом доставки сообщений: 0 — через локальную шину APIC, 1 — через сообщения по системной шине (режим I/O(x)APIC)
03-0Fh   RO Резерв
10-11h 64 R/W Redirection Table 0 — первый элемент таблицы перенаправления
..... ..... ..... .....
3E-3Fh 64 R/W Redirection Table 23 — последний элемент таблицы перенаправления
40-FFh   RO Резерв

 

Таблица. Формат элемента таблицы перенаправлений

Биты Назначение
63:56 Destination (R/W), идентификатор назначения. Если используется физическая адресация (бит 11 = 0), то биты [59:56] задают идентификатор локального APIC (биты 63:59 должны быть нулевыми). При логической адресации (бит 11 = 1) биты [63:56] задают логический адрес набора процессоров
55:17 Резерв (нули)
16 Mask (R/W) — маска запроса: 1 — прерывание замаскировано (но запрос не сбрасывается)
15 Trigger Mode (R/W) — чувствительность входа: 0 — к перепаду, 1 — к уровню
14 Remote IRR (R/W), удаленное подтверждение запроса прерывания (только для линий, чувствительных к уровню). Устанавливается, когда локальный APIC принимает этот запрос от IOAPIC; сбрасывается, когда IOAPIC получает команду EOI с соответствующим номером вектора
13 Interrupt Input Pin Polarity (R/W), полярность сигнала запроса: 0 — активный уровень высокий, 1 — низкий
12 Delivery Status (RO), состояние доставки: 0 — нет активности, 1 — запрос пришел, но по шине APIC еще не доставлен адресату
11 Destination Mode (R/W), адресация сообщения: 0 — физическая (по APIC ID), 1 — логическая (по идентификатору набора процессоров)
10:8 Delivery Mode (R/W) — режим доставки
7:0 Vector (R/W) — вектор прерывания

 

Таблица. Режимы доставки сообщений

Режим Описание
000 Доставка сигнала на входы INTR процессора (или группы) в соответствии с адресатом назначения
001 Доставка сигнала на вход INTR одного процессора из адресованной группы, выполняющего самую низкоприоритетную задачу. Если несколько процессоров выполняют задачи с одинаково низким приоритетом, сообщение получит тот, чей APIC выиграет в этот момент арбитраж на локальной шине
010 SMI/PMI (System Management Interrupt, Power Management Interrupt), прерывание системного управления и системы управления энергопотреблением, только для входов, чувствительных к перепаду. Вектор игнорируется (но должен быть нулевым)
011 Резерв
100 NMI, немаскируемое прерывание, доставляется на входы NMI всех адресованных процессоров. Должно использоваться для входов, чувствительных к перепаду
101 INIT, «мягкая» инициализация всех адресованных процессоров. Должна использоваться для входов, чувствительных к перепаду
110 Резерв
111 ExtINT, внешнее прерывание, вектор которого доставляется от внешнего контроллера PIC по команде INTA. Доставляется на входы INTR всех адресованных процессоров. Должно использоваться для входов, чувствительных к перепаду

Кроме использования последовательной локальной шины есть и иной вариант доставки сообщений к локальным APIC, использущий обращения к пространству памяти. Для этого локальные APIC настраиваются на отслеживание операций записи по определенным адресам. Источник сообщений выполняет операцию записи в пространство памяти, в которой и адрес и данные несут информацию о событии прерывания (см. следующую таблицу). В качестве источника сообщений может выступать расширенный контроллер, называемый I/O(x)APIC. Вышеупомянутый хаб ICH3 имеет возможность работы в режиме I/O(x)APIC.

 

Таблица. Формат сообщения о прерывании, передаваемого по системной шине

Бит Назначение
Назначение бит адреса
31:20 Всегда FEEh
19:12 Destination ID, идентификатор получателя, аналогично битам 63:56 элемента таблицы перенаправлений
11:4 Резерв (0)
3 Redirection Hint, признак перенаправления: 0 — сообщение доставляется агенту (процессору), идентификатор которого указан в битах 19:12; 1 — сообщение доставляется агенту с минимальным приоритетом прерываний
2 Destination Mode, режим назначения, используется только при единичном признаке перенаправления. Если биты 2 и 3 имеют единичное значение, то сообщение направляется по логическому идентификатору группы процессоров
1:0 Всегда 00
31:16 Всегда 0000
15 Trigger Mode, режим чувствительности: 1 — уровень, 0 — перепад
14 Delivery Status, признак для прерываний по уровню: 1 — установка активного уровня, 0 — снятие (для прерываний по перепаду всегда 1)
13:12 Всегда 00
11 Destination Mode, режим назначения: 1 — логический, 0 — физический
10:8 Delivery Mode, режим доставки
7:0 Вектор прерывания

 

 



Проблема разделяемых прерываний

Линии запросов прерываний в компьютере, насыщенном периферийными устройствами, являются самым дефицитным ресурсом, поэтому приходится использовать эти линии совместно, то есть применять разделяемые прерывания между несколькими устройствами (shared interrupts). Для шины PCI с аппаратной точки зрения проблема разделения прерываний решена — здесь активным уровнем запроса является низкий, и контроллер прерываний чувствителен к уровню, а не перепаду. Для шины ISA с ее запросами прерываний по положительному перепаду разделяемость прерываний невозможна. Исключения составляют системные платы и устройства с поддержкой ISA PnP, которые можно заставить работать и по низкому уровню.

После успешного решения аппаратной задачи обеспечения разделяемости линий запроса возникает задача идентификации источника каждого прерывания, чтобы запустить выполнение соответствующей процедуры обработки. Желательно, чтобы эта задача решалась средствами ОС и с минимальными потерями времени.

В первых версиях PCI (до PCI 2.2 включительно) не было общепринятого способа программной индикации и запрета прерываний. К сожалению, в конфигурационных регистрах не нашлось стандартного места для бита, индицирующего введение запроса прерывания данным устройством, — тогда бы в прерываниях для PCI не было бы проблем с унификацией поддержки разделяемых прерываний. В каждом устройстве для работы с прерываниями используются свои специфические биты операционных регистров, относящихся к пространству памяти или ввода/вывода (иногда и к конфигурационному). При этом определить, является ли данное устройство в текущий момент источником прерывания, может только его обработчик прерывания (ISR, Interrupt Service Routine), входящий в драйвер данного устройства. Таким образом, у ОС нет иной возможности диспетчеризации разделяемых прерываний, кроме как выстроить их ISR-ы в цепочку. За расторопность и корректность ISR отвечает его разработчик. В PCI 2.3 наконец-то появился фиксированный бит (Interrupt Status) в регистре состояния конфигурационного пространства устройства (функции), по которому ОС может определить источник разделяемого прерывания и вызвать только его ISR. Однако упоминание о поддержке PCI 2.3 в описаниях устройств и операционных систем встречается не часто.

Обработчики прерываний устройств должны вести себя корректно, учитывая возможность попадания в цепочку обработчиков разделяемого прерывания. В процессе обработки прерывания очередной обработчик в цепочке чтением известного ему регистра своего устройства должен определить, не это ли устройство вызвало прерывание. Если это, то обработчик должен выполнить необходимые действия и сбросить сигнал запроса прерывания от своего устройства, после чего передать управление следующему обработчику в цепочке; в противном случае он просто передает управление следующему обработчику. Встречается типичная ошибка обработчика прерываний: прочитав регистр состояния устройства и не обнаружив признака запроса, драйвер «на всякий случай» выполняет сброс всех источников запроса (а то и сброс всего устройства). Эту ошибку порождает незадачливый разработчик драйвера, не учитывающий возможности разделяемости прерываний и не доверяющий разработчикам аппаратных средств. Увидев в процессе отладки эту неожиданную ситуацию (прерывание вызвано, а источник не виден), он ее «учитывает» введением вредного фрагмента программного кода. Вредность заключается в том, что с момента чтения регистра устройства (не давшего признака запроса) и до выполнения этого ненужного сброса в устройстве может возникнуть запрос прерывания, который будет «вслепую» сброшен и, следовательно, потерян.

Однако и при корректности обработчиков, выстроенных в цепочку, разделяемые прерывания для разнотипных устройств в общем случае работоспособными считать нельзя — возможны потери прерываний от устройств, требующих быстрой реакции. Это может происходить, если обработчик такого устройства окажется в конце цепочки, а предшествующие ему обработчики окажутся «нерасторопными» (не самым быстрым способом обнаружат, что прерывание — чужое). Поведение системы в такой ситуации может меняться в зависимости от порядка загрузки драйверов. Для нескольких однотипных устройств (например, сетевых адаптеров на однотипных микросхемах контроллеров), пользующихся одним драйвером, разделяемые прерывания работают вполне успешно.

Проявления конфликтов по прерываниям могут быть разнообразными. Сетевая карта не сможет принимать кадры из сети или будет их иногда терять (при этом она может их успешно посылать). У устройств хранения доступ к данным будет поразительно медленным (иногда можно минутами ожидать, например, появления информации о файлах и каталогах) или вообще невозможным. Звуковые карты будут молчать или «заикаться», на видеопроигрывателях изображение будет дергаться и т. д. Конфликты могут приводить и к внезапным перезагрузкам компьютера, например по приходу кадра из сети или сигналу от модема. Спасением от бед разделяемости может быть перестановка карт PCI в подходящий слот, в котором конфликты не наблюдаются (это может и не означать, что их нет). Однако попадаются «подарки разработчиков» интегрированных плат, у которых из нескольких слотов PCI неразделяемая линия прерывания есть только у одного (а то и нет вообще). Такие недуги без скальпеля и паяльника, как правило, не лечатся. Более радикальный способ — переход на сигнализацию прерываний через сообщения — MSI.



Традиционные прерывания PCI — INTx#

Для устройств PCI выделяется четыре проводных линии запросов (IRQX, IRQY, IRQZ, IRQW), соединяемых с контактами INTA#, INTB#, INTC# и INTD# всех слотов PCI с циклическим смещением цепей. Соответствие линий INTx# и входов IRQ для устройства любой шины PCI приведено в таблице ниже. Мосты PCI просто электрически соединяют одноименные линии INTx своих первичных и вторичных шин. В системах с APIC, в которых число входов запросов увеличено до 24, дополнительные 8 входов могут использоваться периферийными устройствами, установленными на системной плате. На слотах PCI остаются доступными лишь четыре обычные линии запросов. 

 

Таблица. Коммутация запросов прерываний для устройств PCI

Контакт слота Вход коммутатора запроса для устройства с номером:
0, 4, 8, … 28 1, 5, 9, … 29 2, 6, 10, … 30 3, 7, 11, … 31
INTA# IRQW IRQX IRQY IRQZ
INTB# IRQX IRQY IRQZ IRQW
INTC# IRQY IRQZ IRQW IRQX
INTD# IRQZ IRQW IRQX IRQY

Устройство PCI вводит сигнал прерывания низким уровнем (выходом с открытым коллектором или стоком) на выбранную линию INTx#. Этот сигнал должен удерживаться до тех пор, пока программный драйвер, вызванный по прерыванию, не сбросит запрос прерывания, обратившись по шине к данному устройству. Если после этого контроллер прерываний снова обнаруживает низкий уровень на линии запроса, это означает, что запрос на ту же линию ввело другое устройство, разделяющее данную линию с первым, и оно тоже требует обслуживания. 

Заметим, что распространение сигнала прерывания не синхронизируется с передачей данных. Возможна ситуация, когда активное устройство, выполнив пересылку данных в память, посылает сигнал прерывания, оповещающий об этом событии. Однако записи, отосланные устройством, могут задержаться в мостах (если шина слишком загружена), и процессор начнет обрабатывать прерывание, еще не получив всех этих данных. Чтобы гарантировать целостность данных, программа ISR первым делом должна выполнить чтение какого-либо регистра своего устройства — чтение «из-за моста» принудит все мосты к выгрузке всех буферов отправленных записей.

Линии запросов от слотов PCI и PCI-устройств системной платы коммутируются на входы контроллеров прерываний относительно произвольно. Конфигурационное ПО может определить и указать занятые линии запросов и номер входа контроллера прерываний обращением к конфигурационному пространству устройства. Программный драйвер, прочитав конфигурационные регистры, тоже может определить эти параметры для того, чтобы установить обработчик прерываний на нужный вектор и при обслуживании сбрасывать запрос с требуемой линии.

Каждая функция устройства PCI может задействовать свою линию запроса прерывания, но его обработчик прерывания должен быть готовым к ее разделению (совместному использованию) с другими устройствами. Если устройству требуется только одна линия запроса, то оно должно занимать линию INTA#, если две — INTA# и INTB#, и т. д. С учетом циклического сдвига линий запроса это правило позволяет установить в 4 соседних слота 4 простых устройства, и каждое из них будет занимать отдельную линию запроса прерывания. Если какой-то карте требуется 2 линии, то для монопольного использования прерываний нужно оставить соседний слот свободным. Однако не следует забывать, что PCI-устройства системной платы тоже задействуют прерывания с той же закономерностью (кроме контроллера IDE, который, к счастью, держится особняком). Порт AGP в плане прерываний следует рассматривать наравне со слотом PCI. Таким образом, может оказаться, что монопольные линии прерывания присутствуют далеко не на всех слотах.

Назначение прерываний устройствам (функциям) выполняет процедура POST, и этот процесс управляем лишь частично. Параметрами CMOS Setup (PCI/PNP Configuration) пользователь определяет номера запросов прерываний, доступных шине PCI. В зависимости от версии BIOS это может выглядеть по-разному: либо каждой линии INTA#...INTD# явно назначается свой номер, либо ряд номеров отдается «на откуп» устройствам PCI вместе с устройствами ISA PnP (в противоположность устройствам «Legacy ISA»). В итоге POST определяет соответствие линий INTA#...INTD# номерам запросов контроллера и соответствующим образом программирует коммутатор запросов. По воле пользователя может оказаться так, что не каждой линии запроса шины PCI достается отдельный вход контроллера прерываний. Тогда коммутатор организует объединение нескольких линий запросов PCI на один вход контроллера, то есть разделяемыми станут даже разные линии запросов прерываний для PCI. В самом худшем случае устройствам PCI не достанется ни одного входа контроллера прерываний. Заметим, что BIOS вряд ли отдаст шине PCI прерывания 14 и 15 (их забирает контроллер IDE, если он не отключен), а также 3 и 4 (COM-порты). Новые версии ОС настолько сильно вникают в аппаратную платформу, что позволяют себе (зная чипсет системной платы или пользуясь функциями PCI BIOS) управлять коммутатором запросов прерываний. Эту возможность можно запретить или разрешить, например, в ОС Windows снятием или установкой флажка Использовать управление IRQ (PCI Interrupt Steering) в свойствах шины PCI (Панель управления-Системные устройства-Шина PCI).

Драйвер (или иное ПО), работающий с устройством PCI, определяет номер входа контроллера прерывания, доставшийся устройству (точнее, функции), чтением конфигурационного регистра Interrupt Line. По этому номеру определяется вектор, значение 255 означает, что номер не назначен. Номер входа каждому устройству заносит тест POST. Для этого он считывает регистр Interrupt Pin каждой обнаруженной функции и по номеру устройства (читай: географическому адресу!) определяет, какая из линий INTA#...INTD# (на входе коммутатора запросов) используется. Заметим, что правила, по которым на системной плате определяется соответствие между Interrupt Pin и входными линиями коммутатора запросов в зависимости от номера устройства, строго не регламентированы (деление номера устройства на 4 — это всего лишь рекомендация), но их твердо знает версия BIOS данной системной платы. К этому моменту тест POST уже определил таблицу соответствия этих линий номерам входов; пользуясь этой таблицей, он записывает нужное значение в конфигурационный регистр Interrupt Line. Определить, есть ли еще претенденты на тот же номер прерывания, можно, лишь просмотрев конфигурационные регистры функций всех устройств, обнаруженных на шине (это не так уж сложно сделать, пользуясь функциями PCI BIOS).

В PCI BIOS начиная с версии 2.1 имеются функции определения возможностей и конфигурирования прерываний. Одна из функций возвращает структуру данных, в которой для каждого устройства (на каждой шине) сообщается, с какими входами контроллера прерываний (IRQx) могут быть связаны его линии INTx и с каким именно связаны в данный момент. Также указывается и физический номер слота, в который установлено данное устройство. Кроме того, возвращается и битовая карта, показывающая, какие входы IRQx отводятся исключительно шине PCI (и не используются абонентами других шин). Функция установки для заданного устройства устанавливает связь выбранного сигнала (INTx) с выбранным входом контроллера прерываний (IRQx), то есть программирует коммутатор. Эта функция предназначена для использования только конфигурационным ПО (BIOS, ОС), но никак не драйвером устройства. Тот, кто ею пользуется, сам отвечает за возможные конфликты, за правильное программирование контроллера прерываний (выбранный вход должен быть чувствительным к низкому уровню, а не положительному перепаду), за корректировку информации в конфигурационном пространстве всех затронутых устройств (у которых линии запроса связаны с выбранной линией INTx).