Структура и инициализация контроллера прерываний Intel 8259A
(Схема взята из руководства Intel)
Прерывания на входных линиях прерываний IR, проходят через несколько регистров.
INTERRUPT REQUEST REGISTER (IRR)
IRR используется для хранения всех уровней прерываний, требующих обработки.
IN-SERVICE REGISTER (ISR)
ISR хранит все уровни прерываний, о которых было сообщено процессору и которые находятся в процессе обработки процессором.
INTERRUPT MASK REGISTER (IMR)
IMR хранит биты, маскирующие линии прерываний. IMR работает применяется к IRR. Маскирование линии с высоким приоритетом не влияет на линии прерываний IR с более низким приоритетом.
PRIORITY RESOLVER
Логический блок, определяющий приоритеты битов выставленных в IRR. Бит с наивысшим приоритетом выбиратся и копируется в ISR при получении запроса от процессора через линию INTA
INT (INTERRUPT)
Выходная линия, идущая непосредственно на контакт процессора. Через неё процессор уведомляется о поступлении прерывания.
INTA (INTERRUPT ACKNOWLEDGE)
INTA входная линия, идущая от процессора к контроллеру прерываний. Процессор выставляет эту линию, после получения запроса на прерывание от контроллера, когда становится готов к обработке прерывания. INTA заставляет контроллер прерываний произвести выдачу в шину данных информации о векторе прерывания. Формат данных зависит от системного режима (mPM) of the 8259A.
A0
Сигнал на этой линии используется для определения какие регистры или управляющие слова хочет записать или прочитать процессор. Данная линия выставлена или сброшена в зависимости от того какой порт ввода-вывода процессора используется для записи или чтения контроллера прерываний.
Для программирования контроллера прерываний используются 2 порта ввода-вывода. Так как контроллеров два: master и slave, для них используются 4-ре порта. Таблица взята отсюда.
| Chip — Purpose | I/O port |
|---|---|
| Master PIC — Command | 0x0020 |
| Master PIC — Data | 0x0021 |
| Slave PIC — Command | 0x00A0 |
| Slave PIC — Data | 0x00A1 |
Если A0=0, значит этот байт пишется/читается через командный порт (0x20 для Master), A0=1, значит что байт пишется через порт данных (0x21 для Master).
Каскадное соединение
При каскадном соединении, выходные линии запроса прерывания от slave подключается на входные линии запроса прерывания master. Когда мастер получает запрос на прерывание от slave, он выставляет в свою очередь запрос прерывания процессору. Процессор делает ACK (выставляет INTA), мастер укажет через каскадные линии какому slave неободимо отвечать на запрос от процессора.
Команда подтверждения завершения обработки прерывания EOI должна быть выдана дважды. Один раз для мастера и один раз для slave.
Программирование
Контроллер прерываний 8259A программируется 2-мя типами коммандных слов
- Initialization Command Words (ICWs) — перед нормальной работой контроллер прерываний должен быть инициализирован (в зависимости от нужного режима) 2-4 байтной последовательностью.
- Operation Command Words (OCWs) — Командные слова, посылаемые в процессе работы. Могут посылаться когда угодно после инициализации.
Инициализация контроллера
Документация к контроллеру говорит вот что:
Whenever a command is issued with A0 = 0 and D4 = 1, this is interpreted as Initialization Command Word 1 (ICW1). ICW1 starts the intiitalization sequence during which the following automatically occur
ICW1
(Картинка взята из руководства Intel)
Картинка с изображением ICW1 слегка вводит в ступор. На картинке изображено 9 ячеек: D0-D7 и A0.
Перекрестный просмотр различных источников даёт следующее.
A0 — означает адресную шину с первой картинки. А D4 — четвертую линию в шине данных. В то же время из вышеприведенных ссылок известно, что программное общение процессора с контроллером в IBM PC Compatible системе происходит через порты вывода 0x20 и 0x21. Т.о. A0=0, выглядящая как лишний бит в ICW1 означает, что слово ICW1 пишется в контроллер через порт 0x20. D0-D7 соответствуют просто битам данных отсылаемым через порт.
Т.о. для всех картинок из руководства по контроллеру там, где указано A0=0, значит этот байт пишется через порт 0x20, а там, где указано A0=1, это значит что байт пишется через порт 0x21.
В других источниках порт 0x20 называют командным, а порт 0x21 портом данных.
Так как контроллеров два: master и slave, для них используются 4-ре порта. Таблица взята отсюда.
| Chip — Purpose | I/O port |
|---|---|
| Master PIC — Command | 0x0020 |
| Master PIC — Data | 0x0021 |
| Slave PIC — Command | 0x00A0 |
| Slave PIC — Data | 0x00A1 |
При инициализации контроллера происходят следующие вещи:
- Стирается Interrupt Mask Register
- Линии прерываний IR7 присваивается приоритет 7.
- The slave mode address is set to 7
- Special Mask Mode is cleared and Status Read is set to IRR.
- Если IC4 = 0, тогда все функции указываемые в ICW4 устанавливаются в 0 (Non-Buffered mode*, no auto-EOI, MCS-80, 85 system)
*Замечание: Поле Master/Slave в слове ICW4 используется только в случае buffered mode. BUF = 1
Пример инициализации контроллера, взятый отсюда
В примере в ICW1 единичные биты только D0 и D4. Это означает, что мы инициализируем Cascade Mode, в команде инициализации присутствует ICW4, Call address interval — по-умолчанию 8 байт, Edge Triggered mode. Биты D5-D7 нулевые поскольку мы работаем в режиме 8086/8088.
Разбираемся дальше. Смотрим второе инициализационное слово:
ICW2

Для ICW2 A0=1, это означает, что ICW2 должен писаться через порт данных. Для master — 0x21, для slave контроллера — 0xa1.
Биты D3-D7 содержат номер вектора прерываний, на который настраивается нулевая линия контроллера. Т.о. задается соответствие входных линий прерываний и номеров векторов прерываний.
Смотрим в примере выше.
Видим, что в примере настраиваются номера прерываний 0x20-0x27 для входных линий master-контроллера и 0x28-0x2f для входных линий slave контроллера.
Получается, что в ICW2 просто содержится базовый вектор прерывания для линии номер 0 контроллера прерываний. Соотвественно вектор для линии 1 будет на единицу больше, для линии два на две, и т.д. Последние три бита должны быть нулевыми. Это означает, что базовый вектор прерывания должен быть кратным 8. Еще это значение называют смещением векторов прерываний.
Именно это и говорит osdev.org
- Смещение векторов прерываний должно делиться на 8, так как 8259A использует младшие биты для конкретного вектора прерывания (0..7).
- Единственный способ изменить смещение векторов прерываний для контроллера 8259A — переинициализировать его.
- Если вы планируете вернуться в реальный режим из защищенного режим (для любых нужд), вы должны восстановить его предшествующую конфигурацию
В 8086 системе A15-A11 используются в старших битах номера вектора прерывания. 8259A устанавливает младшие биты в соответствии с вектором прерывания. A10-A5 игнорируются. ADI (Address Interval) тоже не применяется.
ICW3
Это слово читается, если только в системе более одного контроллера 8259A и используется каскадирование. (В системах на базе Intel это всегда справедливо на сегодняшний день).
(Иллюстрация из документации Intel)
Слово ICW3 будет загружено в slave register. Функции этого регистра:
-
В режиме master (либо когда SP = 1 или в buffered mode когда M/S = 1 в ICW4) 1-ца указывается для каждой входной линии прерываний на которую подключен slave контроллер. Мастер будет выдавать 1й байт данных процессору и давать slave контроллеру через каскадные линии команду на выдачу второго байта данных в шину данных.


В данном случае для master указывается, что slave подключен к линии номер 2. Для slave тоже самое. Документация на i8259 в этом месте просто ужасна.
ICW4

SFNM: If SFNM = 1 the special fully nested mode is programmed.
BUF: Если BUF = 1, включается buffered mode. В buffered mode SP/EN контакт становится enable output контактом, а master/slave указывается с помощью M/S.
M/S: Если BUF = 1: M/S = 1 выставляется для master, M/S = 0 для slave. Если BUF = 0, M/S игнорируется.
AEOI: If AEOI = 1 включается режим автоматического подтверждения прерываний.
mPM: Microprocessor mode: mPM = 0 включает режим MCS-80, для 8086 mPM = 1.
Снова возвращаемся к примеру
Подробное описание инициализации контроллера прерываний смотреть здесь
Кроме посылки последовательности слов ICW1-ICW4 необходимо настроить режим обслуживания сигнала прерывания на входных IRQ линиях:
Помимо собственно инициализации контроллеров, необходимо указать, какие линии IRQ будут обслуживаться по уровню сигнала, а какие — по его фронту. Это осуществляется записью нужных значений в регистры ELCR (порты 4D0h и 4D1h для ведущего и ведомого контроллеров соответственно). Пять линий — IRQ0, IRQ1, IRQ2, IRQ8 и IRQ13 — всегда программируются на реакцию по фронту сигнала; соответствующие им биты регистров ELCR должны быть равны нулю. Остальные линии могут программироваться на реакцию как по фронту, так и по уровню. Последняя возможность используется для тех линий, которые разделяются несколькими устройствами. Если программист не конфигурирует самостоятельно устройства, поддерживающие технологию Plug and Play, а значит, не управляет назначением устройствам различных линий IRQ, загрузку необходимых значений в регистры ELCR выполняет BIOS.
Режимы контроллера прерываний
- Fully Nested mode
- Special Fully Nested mode
- Nonspecific Rotating
- Specific Rotating
- Special Mask
- Polling
Fully Nested Mode
Этот режим включается после инициализации по умолчанию. Приоритеты прерываний отсортированы по приоритету от 0-го (0-го наивысшего) до 7-го. Когда прерывание подтверждается процессором, запрос с наивысшим приоритетом определяется и его вектор помещается в шину данных. Дополнительно устанавливается бит IS0-7 в Interrupt Service Register. Этот бит остается выставленным до тех пор, пока процессор не выдаст End of Interrupt (EOI) команду по завершению выполнения процедуры обработчика прерывания. Eсли установлен AEOI (Automatic End of Interrupt) бит, тогда бит IS0-7 будет оставаться выставленным, пока процессор не сбросит сигнал на acknoledge контакте INTA. Пока бит IS выставлен, все дальнейшие прерывания с тем же или меньшим приоритетом запрещены, а прерывавния с более высоким приоритетом сгенерируют запрос прерывания.
IR0 имеет наивысший приоритет, IR7 — низший. Приоритеты могут быть изменены в «rotating priority mode».
The Special Fully Nested Mode
Этот режим используется на больших системах с применением каскадного соединения и приоритеты должны конвертироваться внутри каждого slave контроллера. В этом режиме для master программируется Fully Nested mode. Режим Specival Fully Nested Mode подобен обычному «Fully Nested Mode» за исключением:
- Когда запрос на прерывание от определённого slave контроллера обрабатывается, тогда этот slave не блокируется от блока priority логики master-a, и если внутри slave возникнут прерывания с более высоким приоритетом, тогда мастер инициирует запрос на прерывание процессору. В нормальном nested mode slave маскируется при обработке запроса и более высоко приоритетные прерывания от slave блокируются.
- При выходе из обработчика прерывания, программное обеспечение должно проверить было ли обработанное прерывание от slave. Это делается посылкой non-specific End of Interrupt (EOI) команды на slave и затем чтением его In-Service регистра и проверкой на нуль. Если регистр пуст (0), non-specific EOI должен быть отослан и на master. Если не нуль, тогда EOI не нужно отсылать на мастер.
Краткое summary
В посте дан обзор структуры, работы и инициализации контроллера прерываний 8259A на основе документации на контроллер прерываний и других источников. Надеюсь некоторые сделанные здесь замечания помогут пониманию оригинального руководства.
Ввод-вывод
Программирование контроллера прерываний i8259А
Большая популярность применения этой микросхемы в качестве диспетчера аппаратных прерываний в компьютерах на базе микропроцессоров Intel объясняется наличием большого количества различных режимов ее работы, что позволяет сделать подсистему прерываний достаточно гибкой и эффективной. Действительно, если посмотреть на развитие аппаратной части компьютеров, начиная, например, с i8088/8086, то видно, что менялись самые разные компоненты, но подсистема прерываний, основанная на микросхеме i8259А, так и осталась неизменной.
В процессе загрузки компьютера и в дальнейшем во время работы контроллер прерываний настраивается на работу в одном из четырех режимов:
- FNM (Fully Nested Mode) — режим вложенных прерываний. В этом режиме каждому входу (уровню) irq0. irq7 присваивается фиксированное значение приоритета, причем уровень irq0 имеет наивысший приоритет, а irq7 — наименьший. Приоритетность прерываний определяет их право на прерывание обработки менее приоритетного прерывания более приоритетным (при условии, конечно, что IF = 1).
- ARM (Automatic Rotation Mode) — режим циклической обработки прерываний. В этом режиме значения приоритетов уровней прерываний также линейно упорядочены, но уже не фиксированным образом, а изменяются после обработки очередного прерывания по следующему принципу: значению приоритета последнего обслуженного прерывания присваивается наименьшее значение. Следующий по порядку уровень прерывания получает наивысшее значение, и поэтому при одновременном приходе запросов на прерывания от нескольких источников преимущество будет иметь этот уровень. Это дает возможность обеспечить «равноправие» при обработке прерываний.
- SRM (Specific Rotation Mode) — режим адресуемых приоритетов. Этот режим можно рассматривать как вариант режима ARM. В режиме SRM программист или система самостоятельно могут назначить уровень прерывания с наивысшим приоритетом.
- PM (Polling Mode) — режим опроса. Этот режим запрещает контроллеру автоматически прерывать работу микропроцессора при появлении прерывания от некоторого внешнего устройства. Для того чтобы микропроцессор смог узнать о наличии того или иного запроса на прерывание, он должен сам обратиться к i8259А для получения содержимого IRR, проанализировать его и далее действовать по своему алгоритму. Данный режим моделирует так называемую опросную дисциплину обработки прерываний. Мы упоминали о ней в начале урока. Согласно этому подходу, инициатором обработки прерывания становится не само прерывание, как при векторной дисциплине, а микропроцессор, причем в определяемые им (точнее, операционной системой, выполняемой на нем) моменты времени.
Программирование контроллера прерываний осуществляется через адресное пространство ввода-вывода посредством двух 8-битовых портов с адресами 20h и 21h. Управление контроллером осуществляется путем посылки в определенной последовательности в эти порты специальных приказов двух типов:
- ICW (Initialization Control Word) — управляющее слово инициализации. Всего имеются четыре таких слова с жесткой внутренней структурой — ICW1. ICW4. Эти слова предназначены для задания режима работы контроллера. Количество этих слов (4) определено количеством режимов (см. выше).
- OCW (Operation Control Word) — операционное управляющее слово. Таких слов всего три, и они несут информационную нагрузку для определенных выше режимов работы контроллера прерываний. Обычно их обозначают OCW1. OCW3.
Как вы уже, наверное, успели понять, процесс программирования контроллера жестко регламентирован. Поэтому рассмотрим вначале формат приказов управления, а затем их практическое применение.
Первое.ICW1 — определить особенности последовательности приказов
Состояние битов этого приказа (табл ниже) определяет особенности в последовательности приказов при инициализации контроллера. Данный приказ посылается в порт 20h.

Второе. ICW2 — определение базового адреса
Настало время прояснить еще один принципиальный момент, до этого времени сознательно замалчиваемый. Он связан с принципом определения числового диапазона адресов векторов прерываний для аппаратных прерываний, замкнутых на контроллер прерываний. В реальном режиме работы микропроцессора для хранения указателей (векторов) на процедуры-обработчики прерываний используется специальная область памяти — таблица векторов прерываний. Эта таблица начинается с нулевого адреса оперативной памяти и занимает 1 Кбайт. Среди векторов есть, конечно, и вектора, указывающие на процедуры-обработчики тех прерываний, которые замкнуты на контроллер. Эти вектора располагаются в таблице последовательно, одной группой, и их нумерация начинается с некоторого номера вектора, называемого базовым. Приказ ICW2 (табл. 15.2) позволяет задать номер этого базового вектора для контроллера прерываний в соответствии с тем номером, который назначен соответствующему вектору в таблице векторов прерываний. В реальном режиме работы микропроцессора BIOS в процессе начальной загрузки системы инициализируется ведущий контроллер значением 08h, а ведомый — значением 70h. Теперь понятно, почему обработчику прерываний от таймера соответствует номер вектора 08h в таблице векторов прерываний, хотя физически он замкнут на уровень 0 контроллера i8259A. При желании мы вполне можем изменить значение базового номера на любой не используемый в системе номер, к примеру — 90h. Также следует учитывать, что некорректная установка нового номера этим приказом может полностью нарушить работу всей системы.
Данный приказ посылается в порт 21h.

Как видно, для задания номера базового вектора используются биты с 3 по 7 приказа ICW2. Объяснить это можно тем, что на контроллер замыкаются 8 источников прерываний. Выше мы отметили, что номера векторов, соответствующих прерываниям, замкнутых на контроллер, имеют последовательные номера, начиная с базового. Так, для контроллера, инициализированного значением базового номера 08h, номера векторов в таблице векторов прерываний будут 08h, 09h, 0ah, 0bh и т. д. Отсюда и получается, что для задания базового номера биты 0. 2 использовать нельзя, так как они применяются для формирования адресов векторов прерываний следующих после базового уровней.
Третье. ICW3 — связь контроллеров
Этот приказ предназначен для связи контроллеров в системе с несколькими контроллерами прерываний.
Вариант работы с одной микросхемой i8259А, позволяющий обрабатывать запросы от 8 источников, использовался в ранних системах на базе микропроцессоров i8088/86 (в архитектуре XT). Но i8259А позволяет организовать так называемое каскадное соединение этих микросхем, при котором выход INT одной микросхемы подается на вход одного из уровней irq другой микросхемы (см. рис. 15.1). Это позволяет организовать обработку запросов от большего числа источников. При этом один контроллер является ведущим, а другой — ведомым (тот, который подключен ко входу irq ведущего). Ниже мы разберемся с каскадированием более подробно. Сейчас отметим, что формат приказа ICW3 зависит от того, какой контроллер инициализируется — ведущий (табл. 15.3) или ведомый (табл. 15.4). При инициализации ведущего контроллера ICW3M сообщает, к каким его входам irq подсоединены ведомые контроллеры. Соответственно, при инициализации ведомого контроллера нужна другая форма этого приказа, которая несет информацию о том, к какому входу ведущего подключен данный ведомый контроллер.
Приказ ICW3 посылается в порт 21h.

Четвёртое. ICW4 — дополнительные особенности обработки прерываний
Этот приказ (см. таблицу ниже) определяет дополнительные особенности обработки прерываний контроллером i8259А. Данный приказ посылается в порт 21h.

Таким образом, приказы инициализации задают контроллеру режимы работы в условиях вложенных прерываний. Если требуется конкретизировать порядок обработки для отдельных уровней прерываний, необходимо использовать специальные операционные управляющие слова — OCW, назначение и форматы которых мы рассмотрим ниже.
Контроллер прерываний 8259A
Здесь приводятся описание аппаратной части контроллера прерываний 8259A, команд контроллера и макросов для программирования на ассемблере.
Описание аппаратуры (кроме PS/2 устройств) и команд контроллера прерываний взято из книги «Руководство по архитектуре IBM PС AT» / Ж.К. Голенкова, А.В. Заболоцкий, М.Л. Мархасин и др.; Под общ. ред. М.Л. Мархасина. — Минск: ООО «Консул», 1992. — 949 c.: ил.
Авторская часть состоит в разработке макросов для работы с контроллером. Сами тексты макросов приведены в irq.def.
Оглавление
Описание подсистемы аппаратных прерываний
В архитектуре IBM AT все запросы на аппаратные прерывания из системной шины поступают через два контроллера прерываний (КП) 8259A на вход процессора (ЦП) INTR. Процессор подаёт через выход INTA сигнал на подтверждение прерывания и получает по локальной шине D0–D7 от КП номер вектора прерывания. После чего, он приостанавливает исполнение текущей программы и начинает обрабатывать прерывание. Обработчик прерывания, выполнив заданную последовательность действий, посылает в КП команду окончания обработки прерывания.
Контроллер прерываний (8259A) имеет следующие регистры
- IMR регистр масок; установленные биты указывают, какие номера прерываний запретить обрабатывать;
- IRR регистр запросов на прерывание, содержит номера поступивших запросов на прерывание, бит соответствующему запросу сбрасывается после подтверждения прерывания (IMR на IRR не влияет);
- ISR регистр обслуживаемых прерываний, указывает номера обслуживаемых прерываний.
Прерывания от отдельных устройств можно запретить, устанавливая в регистре масок IMR контроллера, соответствующие им биты. Запретить прерывания от всех устройств можно очисткой бита IF в регистре флагов центрального процессора.
Контроллер прерываний может воспринимать запросы на прерывания от устройств как по уровню, так и по фронту сигнала. Это программируется в процедуре настройки контроллера прерываний.
Когда устройство подаёт запрос на прерывание, в регистре запросов на прерывание IRR устанавливается соответствующий ему бит. Если в регистре обслуживаемых прерываний ISR нет необслуженных прерываний с бóльшим приоритетом, и прерывание от данного устройства незамаскировано, то выдаётся запрос на вход INTR ЦП. После получения подтверждения прерывания от ЦП по входу INTA в ISR устанавливается соответствующий ему бит. Сброс бита в ISR осуществляется подачей в КП соответствующей команды из ЦП обработчиком прерывания.
Микросхема 8259A позволяет подключать к себе до восьми устройств. Чтобы расширить количество обрабатываемых прерываний, в IBM PC/AT контроллеры прерываний включены каскадом. Один из КП играет роль ведущего (Master), а второй — ведомого (Slave). Выход INTR ведомого контроллера подключён к одному из входов ведущего, а выход INTR ведущего — к соответствующему входу ЦП (см. структуру подключений). Получив от ЦП подтверждение прерывания (по общей для обоих КП шине INTA), если оно относится в ведомому КП, ведущий по локальной шине cas0–cas2 сообщает ведомому, что ведомый должен выдавать вектор прерываний на шину D0–D7.
Перед использованием контроллеров прерываний необходимо выполнить их настройку вначале ведущего КП, а затем ведомого. В процессе настройки ИС 8259A ведущего КП нужно, в частности, указать к каким его входам подключены ведомые КП, а ИС 8259A ведомого — к какому входу ведущего КП она подключена. К ИС 8259A, настроенной как ведущий КП, может подключаться до восьми ведомых ИС 8259A (в IBM PC используется только один), что в принципе позволяет обрабатывать до 64 запросов прерываний. После того, как ведущий КП передаёт в ЦП запрос на прерывание от ведомого КП и получает подтверждение, он выдаёт на локальную шину cas0–cas2 номер входа, к которому подключён ведомый контроллер. Ведомый контроллер отслеживает состояние входов на шине cas0–cas2, и когда обнаруживает свой номер, обрабатывает подтверждение своего запроса прерывания.

Порты, используемые для обращений к контроллерам прерываний.
- 020h — Первый порт ведущего контроллера прерываний;
- 021h — Второй порт ведущего контроллера прерываний;
- 0A0h — Первый порт подчинённого контроллера прерываний;
- 0A1h — Второй порт подчинённого контроллера прерываний.
Из первого порта можно прочитать регистры ISR и IRR. А из второго — IMR.
При загрузке ЭВМ BIOS настраивает контроллеры прерываний так, что ведущий выдаёт номера векторов прерываний в диапазоне от 08h до 0fh, а ведомый — в диапазоне от 70h до 77h.
Команды контроллера делятся на: команды настройки (ICW) и рабочие команды (OCW). Вначале рассмотрим команды настройки (командные слова ICW1, ICW2, ICW3 и ICW4). Слово ICW1 начинает процесс настройки КП. Оно задаёт по фронту или по уровню сигнала на входе КП нужно генерировать запрос на прерывание; работает ли контроллер в каскадном режиме (Master или Slave) или самостоятельно, а также имеется ли слово ICW4.
Бит A0 в команде задаётся адресом порта в который она посылается.

Слово ICW1 должно выводиться в порт 20h для ведущего контроллера и в порт 0A0h для ведомого
Слово ICW2 указывает первый номер вектора прерываний, с которого генерируются все остальные. Этот номер должен быть кратен восьми. Векторы располагаются подряд, начиная с указанного, соответствующего IRQ0, и кончая «указанный+7», соответствующим вектору IRQ7.

Слово ICW2 должно выводиться в порт 21h для ведущего контроллера или в порт 0A1h для ведомого.

Слово ICW3 должно выводиться в порт 21h для ведущего контроллера в порт 0A1h для ведомого.

В полновложенном режиме пока установлен бит в ISR, все последующие запросы с тем же или более низким приоритетом не вызывают выработку сигнала INTR для ЦП. При этом возможен следующий случай. Когда ведомый КП получает запрос на прерывание, он выдаёт сигнал на вход IRQ2 ведущего. Ведущий КП подаёт его на вход ЦП и устанавливает соответствующий бит в своём ISR. Когда ведомый КП получает запрос на прерывание с более высоким приоритетом, он снова выдаёт запрос на вход IRQ2 в ведущий КП, но в ISR ведущего КП бит, соответствующий IRQ2, уже установлен. Поэтому ведущий КП запрос на прерывание не выдаст. Преодолеть это можно, запрограммировав ведущий КП на использование специального полновложенного режима.
В специальном полновложенном режиме игнорируются только запросы на прерывание с более низким приоритетом.
// Буферный режим — ? (о нём нет сведений) //
В обычном режиме КП после подтверждения прерывания по входу INTA ждёт команду EOI, после которой осуществляется сброс одного из битов в ISR, соответствующего подтверждённому прерыванию. Установкой AEOI КП можно настроить на автоматический сброс соответствующего бита ISR после получения сигнала INTA. Заметим, что при этом, запрос на прерывание с меньшим приоритетом может поступить до того, как ЦП обработает запрос на прерывание с бóльшим приоритетом. Более того, возможен случай, когда следующий запрос на k-ое прерывание происходит до того как был обработан предыдущий запрос на то же k-ое прерывание. Такой случай называется «сверхвложением».
Слово ICW4 должно выводиться в порт 21h ведущего КП и в порт 0A1h ведомого.
Разряд A0 определяется по номеру порта процессора в который производится запись команды.
Порядок настройки контроллера прерываний

Чтобы изменить одно из ICWn, нужно перепрограммировать всю последовательность.
Регистр маски
Регистр IMR доступен для чтения всегда, ISR и IRR — только после выдачи соответствующих команд.
Теперь рассмотрим рабочие команды (OCW1, OCW2 и OCW3).
Командное слово OCW1
Для управления регистром маски IMR контроллера прерываний используется командное слово OCW1
Команда OCW1 маскирует отдельные запросы на прерывания. Единичные значения битов указывают, что поступающие запросы на прерывание с соответствующими им номерами игнорируются.
Порт, в который Слово OCW1 должно выводиться в порт 21h ведущего КП и 0A1h ведомого.

Макрос IRQMaskN macro MS, N, SCRV устанавливает, сбрасывает, инвертирует или тестирует один бит регистра маски прерываний контроллера.
- MS — указывает контроллер, к которому ведётся обращение (должно быть master или slave);
- N — номер проверяемого бита;
- SRCV — указывает, что нужно сделать с битом регистра маски:
- S — установить соответствующий бит маскирования канала прерывания;
- C — инвертировать соответствующий бит маскирования канала прерывания;
- R — сбросить соответствующий бит маскирования канала прерывания;
- <пусто> — проверить соответствующий бит маскирования канала прерывания, загрузив его в разряд CF регистра флагов ЦП (если бит N установлен, то CF=1).
Макрос IRQMaskMANY macro MS, msk, SCRV устанавливает, сбрасывает или инвертирует биты регистра маски прерываний контроллера, которые в переменной msk имеют единичное значение.
- MS — указывает контроллер, к которому ведётся обращение (должно быть master или slave)
- msk — маска изменяемых битов (единичное значение указывает, что бит должен быть изменён).
- SRCW — указывает, что нужно сделать с битами регистра маски:
- S — установить соответствующие биты маскирования канала прерывания;
- C — инвертировать соответствующие биты маскирования канала прерывания;
- R — сбросить соответствующие биты маскирования канала прерывания.
Макрос IRQMaskALL MS, msk записывает в регистр масок контроллера прерываний байт.
- MS — указывает контроллер, к которому ведётся обращение (должно быть master или slave )
- msk — новое значение регистра масок.
Командное слово OCW2
R=1 — управляет операциями, связанными с ротацией приоритетов; SL=1 — указывает, что команда относится к конкретному прерыванию, а не к последнему, подтверждённому на обслуживание (специальное в смысле заданное); EOI=1 — окончание прерывания (сброс разряда в ISR); L0-L2 — номер запроса на прерывание, для которого выполняется команда, используется совместно с SL=1. Изменение уровней приоритетов вступает в силу только по завершении обработки прерывания (после команды EOI, например).
Когда уровни приоритетов не изменяются, достаточно обычного EOI, когда используются команды ротации приоритетов в обработчике прерываний, нужно использовать специальную команду EOI, явно указывая номер завершаемого прерывания. На использование автоматического завершения прерывания можно программировать контроллер только тогда, когда частота прерываний не очень велика, иначе может возникнуть ситуация сверхвложения (когда одно и то же прерывание вызывается на столько часто, что обработчик не успевает его отработать, при этом оно блокирует вызов всех остальных, и может возникнуть переполнение стека). Если производится ротация приоритетов прерываний, во время обработки прерывания, то приоритеты будут только после окончания обработки (выдачи команды EOI). Т. е. если после ротации приоритетов если, вдруг оказался запрос с более высоким приоритетом, чем у обрабатываемого, то оно обрабатываться не будет до тех пор, пока текущий обработчик прерываний не выдаст команду EOI.
Все возможные варианты расположения уровней приоритетов при ротации
Вход
микросхемыСтатус уровня
приоритетаIRQ0 7 6 5 4 3 2 1 0 IRQ1 0 7 6 5 4 3 2 1 IRQ2 1 0 7 6 5 4 3 2 IRQ3 2 1 0 7 6 5 4 3 IRQ4 3 2 1 0 7 6 5 4 IRQ5 4 3 2 1 0 7 6 5 IRQ6 5 4 3 2 1 0 7 6 IRQ7 6 5 4 3 2 1 0 7 Слово OCW2 должно выводиться в порт 20h для ведущего КП и в порт 0A0h для ведомого.
Для окончания обработки запроса на прерывание служит макрос
_IRQeoi MS, IRQN
- MS — master (вместо него можно указать 1) или slave (можно указать 0).
- IRQN — номер канала прерывания, для которого выполняется команда. Необязателен. Если не указывать, то подразумевается последнее подтверждённое на обслуживание прерывание.
Команда OCW3 используется для выдачи различных режимов и команд в 8259A. OCW3 имеет две функции:
- Выдаёт состояния прерываний
- Управляет маскированием прерываний
- RR=1 — выполняется команда чтения регистра;
- RIS=0 — читать IRR; RIS=1 — читать ISR;
- ESMM=1 — включается или выключается режим специального маскирования;
- SMM=1 — включить; SMM=0 — выключить;
- P — выдаётся команда опроса.
Режим опроса необходим, когда устройства имеют общую программу-обработчик прерываний, а также при количестве запросов больше 64. Инициатором опроса является команда, посылающая слово OCW3, по которой микропроцессор блокирует свой вход INTR и подготавливает цепи в КП (контроллере прерываний), необходимые для опроса. Затем в контроллер передаётся команда чтения порта 20h (для ведущего) или A0h (для ведомого КП), по которой по наиболее приоритетному запросу устанавливается соответствующий разряд ISR и сбрасывается одноимённый разряд IRR) и на шину X выдаётся слово опроса прерываний, структура которого следующая

По полученной информации программа либо перейдёт на программу-обработчик приоритетного прерывания, либо ликвидирует следы обслуживаемого прерывания командой EOI. При необходимости операции опроса может повторяться до тех пор, пока разряд I (D7) не станет равным нулю.
Слово OCW3 выводится в порт 20h ведущего контроллера и в порт 0A0h ведомого контроллера.
Следующий макрос устанавливает режим опроса.
IRQSetRA MS, Reg, SM
- MS — master или slave;
- Reg — регистр, который потом можно будет прочитать (IRR или ISR), можно опустить, тогда не будет меняться читаемый регистр;
- SM — изменить состояние специальной маски (SSM/установить или RSM/сбросить), можно не указывать, тогда состояние специального маскирования меняться не будет.
Макрос IRQResetRA MS, Reg, SM сбрасывает режим опроса, а также может изменить состояние специального маскирования и читаемый регистр (IRR или ISR)
- MS — master или slave;
- Reg — регистр, который потом можно будет прочитать (IRR или ISR), можно опустить, тогда не будет меняться читаемый регистр;
- SM — изменить состояние специальной маски (SSM/установить или RSM/сбросить), можно не указывать, тогда состояние специального маскирования меняться не будет.
Макрос IRQSRARead MS, Reg, IntFNOCHANGE устанавливает режим опроса и читает регистр КП. MS — master или slave. Reg — регистр, который потом можно будет прочитать (IRR или ISR), можно опустить, тогда не будет меняться читаемый регистр. Параметр IntFNOCHANGE — если указан (любое значение), то регистр флагов не сохраняется.
Т. к. в процессе чтения регистра может быть выработано прерывание, которое, в свою очередь, может попытаться прочитать другой регистр контроллера, что в свою очередь может привести к чтению первым обработчиком неправильного регистра, то лучше на время выполнения операции чтения запретить прерывания (вставить команду cli перед IRQSRARead).
- MS — master или slave;
- Reg — регистр, который потом можно будет прочитать (IRR или ISR), можно опустить, тогда читаемый регистр не будет меняться;
- IntFNOCHANGE — Любое значение. Указывает, что не нужно сохранять регистр флагов.
Если запрос на прерывание снимается со входа до того, как он будет разрешён в IMR, то прерывание не вырабатывается.
Возможны следующие режимы работы контроллера
- полновложенный (игнорируются все запросы на прерывание с меньшим или равным приоритетом)
- специальный режим полного вложения (игнорируются все запросы на прерывание с меньшим приоритетом, это, например, может использоваться в тех случаях когда нужно обеспечить режим полного вложения для устройств, подключённых к ведомому контроллеру, для чего запрограммировать нужно только ведущий контроллер).
- когда требуется обеспечить возможность обработки прерываний с приоритетом неравным текущему, можно использовать режим специального маскирования.
Последовательность действий при использовании специального маскирования

При обработке прерываний от подчинённого контроллера необходимо выработать подтверждения для ведущего и ведомого контроллеров. Если при этом используется специальные режим полного вложения, то после посылки EOI в ведомый контроллер необходимо прочитать ISR и проверить, все ли биты в нём сброшены (определить обслужены ли все прерывания), если — да, то послать EOI в ведущий контроллер и выйти, если нет — просто выйти.
Для окончания обработки прерывания в специальном полновложенном режиме на подчинённых контроллерах используется макрос _IRQeoiSFNM IRQN . IRQN — необязательный параметр, указывает номер завершаемого прерывания. Если не указывать, то будет завершено последнее подтверждённое на обслуживание.
Макросы высокого уровня
Список устройств, подключённых к контроллерам прерываний, имена устройств указываются в макросах окончания обработки прерывания (IRQ_EOI), маскирования и размаскирования прерываний (IRQ_Des и IRQ_En)
Имена устройств для макросов «высокого уровня»
Timer — таймер, канал 0 KBD — клавиатура (выходной буфер полон) IRQSlave — каскад контроллера прерываний 2 Serial2 — последовательный порт 2 Serial1 — последовательный порт 1 Parallel2 — параллельный порт 2 FDD — контроллер накопителя на гибких дисках Parallel1 — параллельный порт 1 RTC — часы реального времени PS2Mouse — мышь PS/2 * Math — исключение математического сопроцессора HDDIDE1 — контроллер жёстких дисков 1 HDDIDE2 — контроллер жёстких дисков 2 * * — устройства, не присутствовавшие в 286, 386, 486 компьютерах. Примечание: .IRQSpecialFNM — переменная указывает, используется ли специальный полновложенный режим. Служит для указания генерируемого кода для обработки окончания прерывания, полученного от ведомого контроллера. Переменная вступает в силу после макроса настройки контроллера InitATIRQ. Если настройка контроллера не выполняется, то её можно установить явно. Если .IRQSpecialFNM не определена то IRQ_EOI для подчинённого контроллера генерируется так, если бы был настроен специальный режим полного вложения.
Стандартная инициализация контроллеров прерываний осуществляется с помощью макроса IRQ_Ini IRQ0Int1, IRQ0Int2, SpecFNM
- SpecFNM — указывает, следует ли использовать специальный полновложенный режим
- IRQ0Int1, IRQ0Int2 — номера прерываний первого и второго контроллера Макрос формирует переменную .IRQSpecialFNM, указывающую, следует ли использовать в последующих командах IRQ_EOI при обслуживании прерываний от ведомого контроллера последовательность команд, написанную для специального полновложенного режима или нет.
Если векторы прерываний задаются не константами, а регистрами, то правильность задаваемых номеров не выполняется.
Стандартное завершение прерывания выполняется макросом IRQ_EOI IRQName. В этом макросе неявно используется переменная .IRQSpecialFNM.
Маскировать прерывание можно макросом IRQ_Des IRQName, а размаскировать — IRQ_En IRQName. Здесь IRQName — одно из имён устройств, помещённое в начале файла.