Программируемый контроллер прерываний (Programmable Interrupt Controller, PIC) отвечает за приём запросов прерываний от различных устройств, их хранение в ожидании обработки, выделение наиболее приоритетного из одновременно присутствующих запросов и выдачу его вектора в процессор, когда последний пожелает обработать прерывание. Слово «программируемый» в названии контроллера означает, что режимы его работы устанавливаются программно, а не являются жёстко «зашитыми».
История[]
Система прерываний микропроцессора 8086 принципиально не отличалась от таковой у его «идейного» предшественника — 8-разрядного 8080. Запросы прерываний от устройств по линиям IRQ (Interrupt Request) поступают в контроллер прерываний, который и выполняет их обработку. Участие самого процессора в обслуживании запросов прерываний минимально: он лишь следит за появлением общего сигнала запроса прерывания, поступающего от контроллера, а при его появлении и при условии, что прерывания не запрещены (флаг IF установлен), обрабатывает прерывание, получая его вектор от контроллера. Все остальные функции — хранение запросов, ожидающих обработки, маскирование некоторых из них, выделение наиболее приоритетного из незамаскированных запросов, формирование вектора прерывания (т.е. фактически адреса программы обработки прерывания) для конкретного запроса — выполняет контроллер прерываний. Такой подход позволял упростить сам процессор, но требовал применения для обработки прерываний дополнительной микросхемы контроллера.
В первом IBM PC, а также в появившемся несколько позже IBM PC/XT применялась одна микросхема программируемого контроллера прерываний типа 8259 (советский аналог К1810ВН59). Она имела восемь входных линий запросов прерываний (IRQ0–IRQ7) и была рассчитана на работу как с процессором 8080, так и 8086/8088: выбор конкретного типа процессора выполнялся при инициализации контроллера.
Создавая IBM PC/AT, фирма IBM решила удвоить количество линий запросов прерываний и применила два контроллера типа 8259, соединив их каскадно. Ведущий контроллер прерываний обслуживал запросы прерываний по линиям IRQ0–IRQ7, ведомый — по линиям IRQ8–IRQ15. Выходная линия запроса прерывания ведомого контроллера поступала на одну из входных линий (IRQ2) ведущего; для подключения внешних устройств использовались все восемь входных линий ведомого контроллера и семь (IRQ0, IRQ1 и IRQ3–IRQ7) ведущего, что в сумме давало 15 линий.
Такая схема обработки прерывания стала стандартной. Однако она имеет целый ряд недостатков, важнейшими из которых являются нехватка линий запросов прерываний (15 штук современному компьютеру не хватает) и неспособность работать в многопроцессорной системе. Последнее особенно актуальным стало с появлением многоядерных процессоров, ведь каждое ядро с точки зрения программиста является отдельным процессором. Эти проблемы были в общем решены путём разработки усовершенствованного программируемого контроллера прерываний (APIC), однако в целях совместимости традиционный PIC по-прежнему поддерживается и используется старыми операционными системами, не умеющими работать с APIC. Следует заметить, что современные варианты PIC, входящие, как правило, в микросхему южного моста чипсета системной платы, поддерживают лишь часть возможных режимов исходной пары контроллеров 8259. Так, по очевидным причинам выброшена возможность работы PIC с микропроцессором 8080. В последующих разделах будут описаны только те возможности контроллера прерываний, которые присутствуют в его современных реализациях.
Принципы работы[]
Источники запросов прерываний[]
Традиционная система прерываний ПК включает 16 линий запросов прерываний, из которых одна (IRQ2) используется для каскадного соединения контроллеров и поэтому никогда не вызывает. Часть из линий IRQ имеет стандартное назначение, другая может использоваться произвольными устройствами. Ниже приведён список всех линий IRQ и возможных источников запросов прерываний для них
- IRQ0 — программируемый интервальный таймер или высокоточный таймер событий №0;
- IRQ1 — клавиатура PS/2;
- IRQ2 — запрос прерывания от ведомого контроллера прерываний;
- IRQ3 — произвольное устройство (в IBM PC/AT — последовательный порт COM2 и COM4);
- IRQ4 — произвольное устройство (в IBM PC/AT — последовательный порт COM1 и COM3);
- IRQ5 — произвольное устройство (в IBM PC/AT — параллельный порт LPT2);
- IRQ6 — произвольное устройство (в IBM PC/AT — контроллер гибких дисков);
- IRQ7 — произвольное устройство (в IBM PC/AT — параллельный порт LPT1);
- IRQ8 — часы реального времени или высокоточный таймер событий №1;
- IRQ9 — произвольное устройство;
- IRQ10 — произвольное устройство;
- IRQ11 — произвольное устройство или высокоточный таймер событий №2;
- IRQ12 — произвольное устройство, обычно мышь PS/2, либо высокоточный таймер событий №3;
- IRQ13 — ошибка арифметического сопроцессора;
- IRQ14 — произвольное устройство, обычно первый контроллер ATA (или контроллер Serial ATA в режиме совместимости);
- IRQ15 — произвольное устройство, обычно второй контроллер ATA (или контроллер Serial ATA в режиме совместимости).
Устройства, способные вырабатывать запросы прерываний, традиционно подключались к компьютеру по шине ISA. Эта шина в настоящее время употребляется только в некоторых промышленных компьютерах, а в обычных ПК исчезла, будучи частично заменённой своим упрощённым вариантом — шиной LPC. К последней подключен ограниченный набор устройств, например, контроллер интерфейса PS/2, большинство же устройств подключается к современным шинам — PCI и её более поздним вариантам. В связи с этим была предусмотрена возможность отображения прерываний, вырабатываемых устройствами, подключенными к PCI, на линии IRQ традиционного контроллера прерываний. «Разруливание» (Steering) прерываний PCI и их отображение на линии IRQ выполняется через регистры управления маршрутизацией PIRQx (PIRQx Route Control Registers). Подробнее об этом говорится в разделе Управление прерываниями.
Общая схема обработки прерывания[]
Перед началом работы контроллер прерываний должен быть инициализирован посылкой в него группы командных слов инициализации (ICW). Поскольку контроллер прерываний IBM PC/AT состоял из двух микросхем 8259 и эта схема эмулируется всеми современными ПК, при инициализации необходимо выдать соответствующие ICW и ведущему, и ведомому контроллерам. Подробнее последовательность инициализации описана ниже, в подразделе «Инициализация контроллера прерываний».
После завершения инициализации контроллеры начинают обрабатывать поступающие запросы прерываний. Общий алгоритм их обработки применительно к одной микросхеме 8259 следующий.
Запросы поступают по восьми линиям IRQ, причём в зависимости от установленного режима запросом может считаться либо наличие на линии IRQ высокого уровня, либо положительный перепад сигнала на этой линии (т.е. переход с низкого уровня в высокий). В оригинальном контроллере 8259 способ фиксации запроса — по уровню (Level Mode) или по положительному перепаду (Edge Mode) сигнала IRQ — устанавливался для всей микросхемы в целом, однако в современных компьютерах от этого отказались, введя специальные регистры, с помощью которых для каждой линии IRQ метод обнаружения запроса указывается индивидуально. Подробнее об этом будет говориться в описании регистров PIC, а также в подразделе «Фиксация запросов прерываний и разделение линий IRQ».
Обнаруженные запросы запоминаются в регистре запросов прерываний — IRR (Interrupt Request Register). Каждый бит этого регистра соответствует одной линии IRQ. Бит IRR равен 1, если был получен запрос от соответствующей линии, и 0, если запроса по этой линии не поступало.
Отдельные линии IRQ могут быть замаскированы с помощью регистра маскирования прерываний — IMR (Interrupt Mask Register). Установка какого-либо бита этого регистра маскирует запросы по соответствующей линии IRQ: они принимаются и фиксируются в IRR обычным образом, но их обработка не выполняется до тех пор, пока соответствующий бит в IMR не будет сброшен.
Третьим и последним внутренним регистром контроллера является регистр обслуживаемых прерываний ISR (Interrupt Service Register). Когда контроллер прерываний обрабатывает прерывание и выдаёт процессору его вектор, соответствующий ему бит в ISR устанавливается, а в IRR сбрасывается. Установка некоторого разряда ISR в общем случае блокирует обработку новых прерываний, поступающих по той же линии IRQ, а также всех прерываний с меньшим приоритетом. Сброс разрядов ISR выполняется по командам процессора, которыми он уведомляет контроллер прерываний, что обработка того или иного прерывания завершена (подпробнее об этом говорится в подразделе «Окончание обработки прерывания»). Таким образом, IRR показывает, какие прерывания ожидают обработки, а ISR — какие обрабатываются в настоящий момент.
Контроллер прерываний постоянно анализирует наличие незамаскированных запросов прерываний, т.е. единичных битов IRR, не замаскированных единичными битами IMR и ISR. Если имеется хотя бы один незамаскированный запрос, контроллер выдаёт сигнал на свой выход запроса прерывания (INTR) и ожидает поступления сигнала подтверждения прерывания (INTA), получив который, выдаёт вектор наиболее приоритетного из имеющихся незамаскированных запросов, сбрасывает соответствующий ему бит IRR и устанавливает бит ISR, после чего продолжает принимать и обслуживать запросы (технически вектор прерывания выдаётся по второму сигналу INTA, однако для программиста точный протокол обмена между контроллером прерываний и процессором роли не играет, поэтому детально здесь не описывается).
Обработка прерываний при каскадном соединении контроллеров[]
Как уже говорилось, контроллер прерываний ПК состоит из двух микросхем 8259, соединённых каскадно. Этот факт вносит в вышеописанный алгоритм обработки прерываний некоторые коррективы.
Запросы по линиям IRQ0, IRQ1 и IRQ3–IRQ7, поступающие на соответствующие входы ведущего контроллера, обслуживаются точно так, как описано выше. Запросы, поступающие по линиям IRQ8–IRQ15 на входы ведомого контроллера, обслуживаются им тоже как описано выше, т.е. ведомый контроллер анализирует наличие незамаскированных запросов по этим линиям, и если хотя бы один такой запрос имеется, он выдаёт сигнал INTR. Однако этот сигнал поступает не прямо на процессор, а на вход IRQ2 ведущего контроллера. Когда последний обнаруживает, что самый приоритетный из имеющихся у него незамаскированных запросов поступил по линии IRQ2, т.е. от ведомого контроллера, он, как обычно, выдаёт процессору сигнал INTR, однако, когда от процессора приходит ответ INTA, не выдаёт вектор прерывания сам, а позволяет сделать это ведомому контроллеру, хотя при этом сбрасывает 2-й разряд своего регистра IRR и устанавливает тот же разряд регистра ISR, т.е. отмечает тот факт, что запрос прерывания по линии IRQ2 был передан процессору на обработку. Ведомый контроллер выдаёт вектор, соответствующий наиболее приоритетному из имеющихся у него незамаскированных запросов IRQ8–IRQ15. Таким образом, вектор прерывания IRQ2 процессору никогда не выдаётся.
Подключение ведомого контроллера к одному из входов ведущего влечёт за собой два особых эффекта. Во-первых, установка 2-го разряда регистра IMR ведущего контроллера блокирует все прерывания от ведомого. Во-вторых, в обычном режиме работы контроллера, называемом режимом полной вложенности (см. ниже), установка 2-го разряда ISR блокирует последующие прерывания от этой линии (а значит, от всего ведомого контроллера) до тех пор, пока обработка уже произошедшего прерывания не будет завершена. Чтобы не допускать такой блокировки, можно использовать специальный режим полной вложенности, также описанный ниже.
Потеря прерываний[]
Неприятной особенностью контроллеров 8259 является возможность потери прерывания. Такое может произойти, если запросом прерывания считается не положительный перепад, а поддерживаемый на линии IRQ высокий уровень сигнала (подробнее об этом говорится в подразделе «Фиксация запросов прерываний и разделение линий IRQ»). Если контроллер прерывания выдал процессору сигнал INTR и в этот момент сигнал запроса на линии IRQ был сброшен, контроллер не будет знать, какой вектор выдать процессору в ответ на сигнал INTA. Отменить начавшуюся процедуру прерывания невозможно, поэтому контроллер выдаёт вектор, соответствующий линии IRQ7, однако 7-й бит в регистре ISR не устанавливает.
Не совсем понятной является ситуация с потерей прерывания ведомого контроллера. Судя по описанию южного моста Intel ICH10, ведомый контроллер успевает снять свой сигнал INTR до момента, когда ему необходимо будет выдать вектор, что приводит к неожиданной для ведущего контроллера пропаже сигнала IRQ2. Последний отреагирует на такое событие описанным выше образом и выдаст вектор прерывания для IRQ7, не устанавливая седьмой разряд ISR.
В связи с возможностью потери прерывания обработчик IRQ7 должен предпринимать ряд специальных мер. Во-первых, обработчики прерываний не могут быть вызваны повторно до тех пор, пока соответствующие им разряды ISR не будут сброшены (см. подраздел «Окончание обработки прерывания»), однако это не относится к обработчику IRQ7. Он может быть вызван для обработки реального прерывания по этой линии, что сопровождается установкой седьмого разряда ISR ведущего контроллера прерываний, а потом может быть вызван опять из-за потери прерывания. Таким образом, обработчик IRQ7 должен отслеживать собственную активность и при обнаружении своего повторного вызова до окончания обработки предыдущего прерывания делать вывод, что причиной этого вызова послужила потеря какого-то прерывания. Во-вторых, обработчик IRQ7, обнаружив свой первый вызов, должен проверить состояние седьмого бита ISR ведущего контроллера: если этот разряд сброшен, это также свидетельствует о потере прерывания. Лишь в том случае, когда обработчик IRQ7 вызывается впервые и обнаруживает, что седьмой разряд ISR установлен, он имеет дело с реальным прерыванием по линии IRQ7.
Приоритеты прерываний[]
После инициализации приоритет линий запросов прерываний ведущего контроллера последовательно убывает от IRQ0 (наибольший приоритет) до IRQ7 (наименьший приоритет), а у ведомого — от IRQ8 до IRQ15. Поскольку выход INTR ведомого контроллера подключен ко входу IRQ2 ведущего, линии IRQ8–IRQ15 имеют приоритеты ниже, чем приоритет линии IRQ1, но выше, чем приоритет линии IRQ3.
При необходимости приоритеты линий запросов прерываний могут быть изменены, причём настройка приоритетов для линий IRQ0–IRQ7 и IRQ8–IRQ15 выполняется отдельно, поскольку каждая из этих групп линий обслуживается своим контроллером. Микросхема 8259 предусматривает два механизма изменения приоритетов: установка дна приоритетов и вращение приоритетов. Оба механизма управляются с помощью управляющего слова операций 2 (OCW2), формат которого подробно будет описан в соответствующем подразделе.
Установка дна приоритетов выполняется с помощью OCW2, имеющего двоичный код 11000nnn, где nnn — номер линии IRQ данного контроллера, которая будет иметь низший приоритет. Например, OCW2 11000100, выданное ведущему контроллеру, сделает самой низкоприоритетной линией IRQ4, а ведомому контроллеру — IRQ12. Самыми высокоприоритетными линиями в этом случае будут IRQ5 и IRQ13 соответственно.
Вращение приоритетов может применяться, например, в ситуации, когда все устройства, подключенные к контроллеру прерываний, должны быть равноприоритетными. В этом случае, заканчивая обработку прерывания от какой-либо линии, т.е. сбрасывая связанный с ней бит ISR, контроллер прерываний одновременно объявляет эту линию самой низкоприоритетной (меняет положение дна приоритетов, присваивая ему номер этой линии). Благодаря этому появление нового запроса по этой же линии уже не сможет помешать обработке запросов от других линий. В наихудшем случае запрос по любой линии должен будет пропустить вперёд семь других запросов, прежде чем будет гарантированно обработан. В случае применения механизма с фиксированными приоритетами это не гарантируется: слишком часто возникающий высокоприоритетный запрос способен заблокировать обработку менее приоритетных, хотя такая ситуация возникает обычно при неисправностях аппаратуры.
Обычный и специальный режимы полной вложенности прерываний[]
В обычном режиме полной вложенности прерываний (Fully-Nested Mode) установка какого-либо разряда регистра ISR блокирует все последующие прерывания по той же и менее приоритетным линиям IRQ. Таким образом, более приоритетное прерывание может прервать обработку менее приоритетного, но не наоборот. При этом обычно предполагается, что обработка прерываний будет заканчиваться в порядке, обратном их возникновению: первым будет полностью обслужено самое приоритетное прерывание, потом следующее за ним и так далее до самого низкоприоритетного, т.е. будет обеспечена полная вложенность прерываний. На самом деле заканчивать обработку можно в произвольном порядке, о чём подробнее говорится в подразделе «Окончание обработки прерывания».
Поскольку ведомый контроллер прерываний подключается к линии IRQ2 ведущего контроллера, любое прерывание от ведомого контроллера блокирует все прочие прерывания от него, даже более высокоприоритетные, поскольку в начале его обработки будет установлен не только бит ISR ведомого контроллера, соответствующий данной линии IRQ, но и 2-й разряд ISR ведущего контроллера. Чтобы избежать такой блокировки, при инициализации ведущего контроллера следует указать использование режима специальной полной вложенности (Special Fully-Nested Mode). В этом режиме бит ISR ведущего контроллера, соответствующий линии, к которой подсоединён ведомый контроллер (IRQ2 в случае ПК), устанавливается как обычно, но блокирует лишь запросы прерываний по менее приоритетным линиям IRQ, не затрагивая ту линию, к которой относится.
Применение режима специальной полной вложенности необходимо учитывать в процедуре окончания обработки прерывания, о чём будет сказано в соответствующем подразделе.
Режим программного опроса[]
Режим программного опроса (Poll Mode) предназначен для чисто программного получения и обработки запросов прерываний. Для его организации внешние прерывания процессора должны быть запрещены путём сброса флага IF.
Чтобы проверить наличие незамаскированного запроса прерывания, программа выдаёт контроллеру управляющее слово операций 3 (OCW3), в котором установлен 2-й разряд (бит программного опроса). Получив такую команду, контроллер прерываний, если имеются незамаскированные запросы прерываний, выбирает самый приоритетный из них, сбрасывает соответствующий ему разряд IRR и устанавливает разряд ISR, после чего запоминает номер линии IRQ для этого запроса. Когда процессор впервые после выдачи OCW3 произведёт чтение из контроллера прерываний, ему будет возвращён байт, старший бит которого будет содержать единицу, если на момент выдачи OCW3 имелся незамаскированный запрос прерыания, и нуль в противном случае. Если запрос прерывания был, младшие три бита этого байта будут содержать код линии IRQ, по которой поступил данный запрос.
Окончание обработки прерывания[]
Как уже указывалось, при передаче прерывания на обработку контроллер прерывания сбрасывает соответствующий бит регистра IRR и устанавливает бит в ISR. Последний блокирует все прерывания с таким же и более низким приоритетом, поэтому при окончании обработки прерывания он должен быть сброшен. Это выполняется с помощью команды окончания обработки прерывания (End of Interrupt, EOI). Контроллер прерываний поддерживает несколько разновидностей EOI.
Наиболее часто применяется команда неспецифического окончания обработки прерывания (Non-Specific EOI). Заканчивая обработку прерывания, программа выдаёт контроллеру прерываний OCW2, в котором задана эта команда. Контроллер, получив такую команду, сбрасывает самый приоритетный из установленных разрядов ISR. Когда контроллер находится в режиме специального маскирования (он будет описан ниже, в подразделе «Маскирование прерываний»), команда неспецифического EOI не сбрасывает бит ISR, для которого установлен соответствующий разряд IMR. Таким образом, команда неспецифического EOI предназначена для систем, поддерживающих полную вложенность прерываний.
Если прерывание пришло от ведомого контроллера, необходимо сбросить соответствующий разряд ISR не только в нём, но и в ведущем контроллере. Если используется режим обычной полной вложенности, это достигается выдачей команды неспецифического EOI в оба контроллера. Однако в режиме специальной полной вложенности сбрасывать бит ISR ведущего контроллера надо только в том случае, если никаких других прерываний от ведомого контроллера в это время не обрабатывается. Это достигнается посылкой команды неспецифического EOI ведомому контроллеру, чтением его регистра ISR и посылкой такой же команды ведущему контроллеру, если окажется, что ISR ведомого контроллера содержит только нули.
Имеется возможность сбросить произвольный разряд ISR, что бывает необходимо, когда полная вложенность прерываний не поддерживается. Для этого предназначена команда специфического EOI (Specific EOI), в которой указывается номер линии IRQ, для которой необходимо сбросить разряд ISR.
Помимо программной выдачи команды EOI, контроллер прерываний поддерживает режим автоматического EOI (Automatic EOI). Это означает, что при выдаче вектора прерывания для какой-либо линии IRQ соответствующий ей разряд IRR сбрасывается, но установки соответствующего разряда ISR не происходит. Использование этого режима требует большой осторожности и чревато проблемами. В частности, теряется возможность определить, не произошла ли потеря прерывания, поскольку такая проверка основана на анализе содержимого ISR.
Маскирование прерываний[]
Как уже говорилось, любая линия IRQ может быть замаскирована путём установки соответствующего разряда регистра IMR. Это выполняется с помощью посылки управляющего слова операций 1 (OCW1), которое представляет собой новое содержимое IMR. Поскольку обычно требуется установить или сбросить только один разряд этого регистра, не затрагивая остальные, в любой момент содержимое IMR может быть прочитано.
Своеобразной маской прерываний является регистр ISR. Каждый установленный в нём разряд блокирует все прерывания от соответствующей ему и менее приоритетных линий IRQ. Исключением является второй разряд ISR ведущего контроллера, работающего в режиме специальной полной вложенности. Поскольку к IRQ2 подключено не обычное устройство, а ведомый контроллер прерывания, в режиме специальной полной вложенности установка второго бита ISR ведущего контроллера не блокирует линию IRQ2.
Маскирование прерываний с помощью ISR облегчает написание обработчиков: за исключением случая потери прерывания (см. выше), можно быть уверенным, что никакой обработчик не будет прерван сигналом такого же или более низкого приоритета до тех пор, пока он не выдаст команду EOI. Однако иногда такой подход неэффективен или неприемлем. Например, обработка некоторого высокоприоритетного прерывания может занимать длительное время, однако длительный запрет менее приоритетных прерываний нежелателен. Такую проблему можно решить несколькими путями, в том числе используя режим специального маскирования (Special Mask Mode), предоставляемый контроллером прерываний.
Этот режим активизируется и отменяется с помощью битов 6 и 5 третьего управляющего слова операций (OCW3). Когда он активен, содержимое регистра ISR не маскирует запросы прерываний, и единственной маской является регистр IMR. Благодаря этому обработчик прерывания, получив управление, может установить соответствующий ему бит IMR, после чего разрешить прерывания процессора (установив флаг IF), что обеспечит быструю реакцию на незамаскированные с помощью IMR прерывания и в то же время не допустит прерывания уже выполняющегося обработчика новым запросом по той же линии IRQ.
Фиксация запросов прерываний и разделение линий IRQ[]
Как уже отмечалось, в качестве запросов прерываний могут рассматриваться либо положительные перепады линий IRQ, либо наличие на этих линиях высокого уровня. Режим определения запросов — по фронту или по уровню — для оригинального контроллера 8259 устанавливался при его инициализации, причём все линии IRQ, подключенные к одному контроллеру, должны были использовать один и тот же режим. Однако на ПК весьма быстро возможности контроллера прерываний в этой области были расширены. Были введены два регистра ELCR (Edge/Level Control Register) — по одному для ведущего и ведомого контроллеров. Если какой-либо разряд ELCR был равен единице, запросом прерывания IRQ считался высокий уровень на соответствующей линии IRQ; если же разряд ELCR был равен нулю, запросом прерывания считался положительный перепад на этой линии IRQ.
Некоторые линии IRQ, связанные со стандартными источниками прерывания, не могут быть запрограммированы на восприятие уровня сигнала как запроса прерывания и всегда реагируют на положительный перепад; для этих линий соответствующие разряды регистров ELCR должны быть равны нулю. В число таких линий входят:
- IRQ0 — прерывание от программируемого интервального таймера 8254;
- IRQ1 — прерывание от клавиатуры PS/2;
- IRQ2 — каскадный запрос прерывания от ведомого контроллера прерываний;
- IRQ8 — прерывание от часов реального времени;
- IRQ13 — прерывание по ошибке арифметического сопроцессора.
В режиме обнаружения прерываний по фронту сигнала положительный перепад на линии IRQ вызывает установку соответствующего ей разряда регистра IRR, который остаётся установленным до тех пор, пока прерывание не будет обслужено. В режиме обнаружения прерываний по уровню сигнала соответствующие разряды IRR повторяют значения соответствующих линий IRQ: пока на линии присутствует высокий уровень, разряд IRR равен единице, когда высокий уровень сменяется низким, разряд IRR сбрасывается. Кроме того, начало обработки прерывания, определяемого по уровню сигнала, не вызывает сброса соответствующего разряда IRR, а лишь установку бита ISR; сброс IRR произойдёт лишь тогда, когда будет сброшен запрос прерывания на линии IRQ. Это обстоятельство может вызвать потерю прерываний (см. выше), но одновременно позволяет использовать одну и ту же линию IRQ нескольким устройствам сразу.
Разделение одной линии IRQ между несколькими устройствами достигнается тем, что все эти устройства при возникновении запроса прерывания выдают на линию IRQ высокий уровень сигнала и удерживают его до тех пор, пока запрос прерывания не обработан. Благодаря этому соответствующий разряд IRR будет установлен до тех пор, пока хотя бы у одного устройства имеется необработанный запрос прерывания. Обработчик прерывания должен проанализировать состояние всех устройств, подключенных к данной линии IRQ, чтобы определить, какие именно из них запросили прерывание. Такой подход усложняет и замедляет обработку прерываний, но снимает ограничение на число устройств, накладываемое малым числом линий IRQ у традиционного контроллера прерываний ПК.
Программирование контроллера прерываний[]
Для программного доступа к ведущему контроллеру прерываний используются порты 20h и 21h, к ведомому — A0h и A1h. Для сохранения программной совместимости с IBM PC/AT эти порты имеют «псевдонимы» — адреса 24h/25h, 28h/29h, 2Ch/2Dh, 30h/31h, 34h/35h, 38h/39h и 3Ch/3Dh для ведущего контроллера и A4h/A5h, A8h/A9h, ACh/ADh, B0h/B1h, B4h/B5h, B8h/B9h и BCh/BDh для ведомого. Эти порты являются многофункциональными. При инициализации контроллера первое командное слово инициализации записывается в порт 20h/A0h, остальные три слова — в порт 21h/A1h. В процессе обычной работы в порт 21h/A1h записывается управляющее слово операций 1 (OCW1), которое задаёт содержимое регистра маски IMR; чтение из этого порта вызывает считывание содержимого IMR. В порт 20h/A0h записываются 2-е и 3-е управляющие слова операций (OCW2 и OCW3); его чтение обеспечивает доступ к содержимому регистров ISR и IRR либо выполняет чтение вектора прерывания в режиме программного опроса в зависимости от того, какой функции были заданы последним записанным OCW3.
Помимо портов, управляющих контроллерами, имеются ещё два порта, обеспечивающие считывание и запись регистров ELCR ведущего и ведомого контроллеров. Эти порты имеют адреса 4D0h и 4D1h соответственно.
Примеры программирования контроллера прерываний можно увидеть здесь.
Инициализация контроллера прерываний[]
Оригинальный контроллер прерываний 8259 мог работать с двумя процессорными архитектурами (8080 и 8086), обеспечивал увеличение количества линий IRQ путём каскадного соединения контроллеров и поддерживал множество режимов работы, что определяло разнообразие вариантов его инициализации. В контроллерах, реализуемых ради совместимости в современных чипсетах, большинство этих режимов отсутствует, а схема включения самих контроллеров строго фиксирована. Всё это вызвало резкое уменьшение числа вариантов последовательностей инициализации. Теперь в каждый контроллер должно быть записано четыре командных слова инициализации (Initialization Command Words, ICW1–ICW4), большинство битов которых имеют строго определённые значения.
Первое командное слово инициализации для ведущего контроллера записывается в порт 20h, для ведомого — в порт A0h, остальные слова — в порты 21h и A1h соответственно. После окончания последовательности инициализации регистры ISR и IMR обоих контроллеров будут сброшены, наименьший приоритет будет назначен линиям IRQ7 и IRQ15, режим специального маскирования будет отменён и будет разрешено чтение регистра IRR.
ICW1 всегда равно 11h.
Старшие пять разрядов ICW2 задают базовый вектор прерывания для данного контроллера; младшие три разряда должны быть равны нулю. Когда происходит прерывание, контроллер прерывания объединяет пять старших разрядов, заданных в ICW2, с закодированным в трёх младших разрядах номером линии запроса прерывания, обслуживаемой в данный момент, и выдаёт полученный байт как вектор прерывания. Таким образом, для линий IRQ0 и IRQ8 вектор прерывания будет равен значению ICW2, записанному в ведущий и ведомый контроллер прерывания соответственно, для IRQ1 и IRQ9 вектор будет на единицу больше этого значения и т.д.
ICW3 для ведущего контроллера прерывания указывает, к каким линиям IRQ подключены ведомые контроллеры. На ПК оно всегда должно быть равно 04h, поскольку единственный ведомый контроллер подключен к IRQ2.
Для ведомого контроллера ICW3 задаёт номер соответствующей ему линии IRQ ведущего контроллера. На ПК оно всегда равно 02h.
ICW4 настраивает некоторые режимы работы контроллеров. Его разряды имеют следующее назначение:
- биты 7:5 должны быть равны нулю;
- бит 4 определяет режим вложенности. Когда он равен нулю, используется обычный режим полной вложенности, когда единице — специальный режим полной вложенности. Последний имеет смысл только для ведущего контроллера;
- биты 3:2 должны быть равны нулю;
- бит 1 определяет режим окончания обработки прерывания. Когда он равен нулю, используется программная отправка команды EOI, когда равен единице — автоматическое окончание обработки прерывания;
- бит 0 всегда должен быть равен единице.
Помимо собственно инициализации контроллеров, необходимо указать, какие линии IRQ будут обслуживаться по уровню сигнала, а какие — по его фронту. Это осуществляется записью нужных значений в регистры ELCR (порты 4D0h и 4D1h для ведущего и ведомого контроллеров соответственно). Пять линий — IRQ0, IRQ1, IRQ2, IRQ8 и IRQ13 — всегда программируются на реакцию по фронту сигнала; соответствующие им биты регистров ELCR должны быть равны нулю. Остальные линии могут программироваться на реакцию как по фронту, так и по уровню. Последняя возможность используется для тех линий, которые разделяются несколькими устройствами. Если программист не конфигурирует самостоятельно устройства, поддерживающие технологию Plug and Play, а значит, не управляет назначением устройствам различных линий IRQ, загрузку необходимых значений в регистры ELCR выполняет BIOS. Подробнее об этом говорится в разделах Управление прерываниями, Plug and Play и PCI.
Управляющее слово операций 1 (OCW1)[]
Управляющее слово операций 1 (Operational Control Word 1, OCW1) устанавливает маску прерываний, храняющуюся в регистре IMR. Для записи OCW1 служит порт 21h в ведущем и A1h в ведомом контроллерах прерываний. Установленный разряд запрещает прерывания от соответствующей линии IRQ, сброшенный — разрешает.
Ранее записанное OCW1 может быть прочитано из того же порта.
Управляющее слово операций 2 (OCW2)[]
Управляющее слово операций 2 (Operational Control Word 2, OCW2) используется для выдачи команды окончания обработки прерывания (EOI), выполнения вращения и установки дна приоритетов. Оно записывается в порт 20h для ведущего и A0h для ведомого контроллеров. Назначение разрядов OCW2 следующее.
Разряды | Назначение |
7:5 | Код команды:
|
4:3 | Указывают, что это слово является OCW2. Должны быть равны нулю |
2:0 | В командах 011, 110 и 111 задают номер линии IRQ контроллера, к которой относится команда |
Управляющее слово операций 3 (OCW3)[]
Управляющее слово операций 3 (Operational Control Word 3, OCW3) используется для активизации и отмены режима специального маскирования и режима опроса, а также для выбора регистра, содержимое которого может быть прочитано через порт 20h/A0h. Оно записывается в порт 20h для ведущего и A0h для ведомого контроллеров. Назначение разрядов OCW3 следующее.
Разряды | Назначение |
7 | Должен быть равен нулю |
6:5 | Управление режимом специального маскирования:
|
4:3 | Указывают, что это слово является OCW3. Должны быть равны 01 |
2 | Режим опроса. Чтобы активизировать режим опроса, в этот разряд необходимо записать единицу, после чего считать код вектора прерывания из порта 20h/A0h. После чтения вектора режим опроса автоматически отменяется |
1:0 | Выбор считываемого регистра:
|
Основные источники информации[]
1] Intel 8259A PROGRAMMABLE INTERRUPT CONTROLLER (8259A/8259A-2)
файл: pic8259.pdf; Зеркало.
2] Intel® 82801EB I/O Controller Hub 5 (ICH5) / Intel® 82801ER I/O Controller Hub 5 R (ICH5R) Datasheet
Файл: 25251601.pdf; Зеркало:
3] 82371AB PCI-TO-ISA / IDE XCELERATOR (PIIX4)
Файл: 290562.pdf Зеркало.
4] Ю. С. Лукач, А. Е. Сибиряков Архитектура ввода-вывода персональных ЭВМ IBM PC.