Предыдущая глава УПРАВЛЕНИЕ УСТРОЙСТВАМИ С ПРЕРЫВАНИЯМИ Следующий раздел

21.1. Контроллер прерываний

При асинхронном вводе-выводе с прерываниями драйвер ожидает завершения текущей операции ввода-вывода пассивно, не занимая для этого ЦП. Поэтому программа, сделавшая запрос на ввод-вывод, может выполнять в это же время (то есть параллельно) какую-то другую свою работу на ЦП. При завершении операции ввода-вывода ИУ выдает в ЦП сигнал прерывания.

Прерывания от ИУ относятся к маскируемым внешним аппаратным прерываниям (см. п.19.1). В большинстве ВС сигналы таких прерываний поступают не сразу в ЦП, а сначала в программируемый контроллер прерываний. Данный контроллер упорядочивает поступление сигналов внешних прерываний в ЦП, освобождая его от необходимости наводить порядок среди этих сигналов. Далее речь будет идти о программируемом контроллере прерываний i8259A.

Контроллер i8259A имеет 8 входов – IRQ0, IRQ1IRQ7, позволяющих принимать запросы на прерывание от восьми ИУ:

    IRQ0 – таймер;

    IRQ1 – клавиатура;

    IRQ2 – второй контроллер прерываний;

    IRQ3 – последовательный порт COM2;

    IRQ4 – последовательный порт COM1;

    IRQ5 – параллельный порт LPT2;

    IRQ6 – гибкий диск;

    IRQ7 – параллельный порт LPT1.

Данные входы имеют приоритеты: чем меньше номер входа, тем приоритет выше. Поэтому самыми приоритетными являются сигналы прерываний от таймера. Приоритет сигнала используется контроллером прерываний для определения возможности направления этого сигнала в ЦП. При этом если в контроллер одновременно поступили несколько сигналов прерываний, то из них в ЦП будет отправлен тот сигнал, приоритет которого выше.

Кроме того, если ЦП уже занят обработкой какого-то прерывания, то новый сигнал будет отправлен контроллером прерываний только в том случае, если его приоритет выше, чем у того прерывания, обработчик которого выполняется на ЦП. (Вспомним, что для того, чтобы новое прерывание действительно прервало обработку старого прерывания, дополнительно требуется, чтобы в начале обработчика старого прерывания стояла команда sti.)

Номер прерывания, соответствующий конкретному ИУ, можно определить следующим образом: к базовому номеру, соответствующему контроллеру прерываний (8), следует прибавить номер входа в этот контроллер. Например, номер прерывания от клавиатуры: N = 8 + 1 = 9.

Как и любое ИУ, контроллер прерываний имеет порты, которые используются программами (драйверами) для управления им. Эти порты имеют адреса 20h и 21h. Порт 21h используется, в частности, для маскирования (то есть для запрета) прерываний от устройств требуемого типа. Для этого требуется записать единицу в тот бит порта, который соответствует номеру входа для устройства. Например, следующие две команды выполняют маскирование прерываний от клавиатуры:

 

mov   al, 00000010b                       ; Вход для клавиатуры - IRQ1

out    21h, al

 

В конце обработчика внешних прерываний следует разрешить обработку прерываний с более низкими приоритетами. Для этого достаточно выполнить две команды:

 

mov   al, 20h                                   ; Число 20h используется для двух

out    20h, al                                    ;      разных величин

 

Существуют другие команды управления контроллером прерываний, позволяющие размаскировать прерывания от любого ИУ (независимо от маскирования в ЦП), а также изменять приоритеты ИУ. Аналогичные команды используются и для управления вторым (ведомым) контроллером прерываний.

Ведомый контроллер подсоединяется к входу IRQ2 ведущего контроллера. Поэтому ИУ, обслуживаемые ведомым контроллером, выдают сигналы прерываний с приоритетами, расположенными между приоритетами клавиатуры и последовательного порта COM2. Для управления ведомым контроллером используются порты A0h и A1h, аналогичные портам 20h и 21h для ведущего контроллера. Базовый номер прерываний, соответствующий ведомому контроллеру прерываний, равен 70h.

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

    IRQ13 – математический сопроцессор;

    IRQ14 – жесткий магнитный диск.

 


Предыдущая глава В начало Следующий раздел