3.4. Маскирование аппаратных прерываний
Выше мы использовали команду микропроцессора CLI (функцию Турбо-Си disable) для запрета всех аппаратных прерываний. Но аппаратные прерывания можно запрещать и выборочно. Для этого можно воспользоваться портом 0x21, в который записывается байт - маска аппаратных прерываний. Единица в разряде этого байта соответствует запрету соответствующего аппаратного прерывания, 0 - разрешению прерывания. Соответствие разрядов прерываниям приводится ниже (здесь и далее при поразрядном анализе байтов или слов номер 0 имеет самый младший бит):
0 |
- прерывание таймера; |
1 |
- прерывание клавиатуры; |
2 |
- каскадирование прерываний (только AT); |
3 |
- прерывание асинхронного порта COM2; |
4 |
- прерывание асинхронного порта COM3; |
5 |
- прерывание контроллера жестких дисков (только XT); |
6 |
- прерывание контроллера гибких дисков; |
7 |
- прерывание принтера. |
Приведенный ниже программный пример иллюстрирует выборочное маскирование прерываний. Функция Турбо-Си clock возвращает количество прерываний таймера, поступивших с начала выполнения нашей программы. Первые 10 значений, выводимые на экран, будут последовательно возрастать, показывая нам, что прерывания от таймера поступают. Затем в порт 0x21 записывается код, содержащий единицу в младшем разряде. Следующие 10 значений возвращаемые функцией clock будут неизменны: прерывания от таймера не поступают. Наконец, мы восстанавливаем значение, ранее находившееся в порту 0x21, и видим, что прерывания от таймера поступают вновь.
/*= ПРИМЕР 3.3 =*/
/*======== Маскирование аппаратных прерываний ============*/
#include <dos.h>
#include <time.h>
main() {
unsigned char mask; /* Исходная маска прерываний */
int i;
/* Индикация исходного состояния */
for (i=0; i<10; i++) {
printf("%3d ",clock()); delay(100);
}
printf(" маска=%02x\n",(mask=inportb(0x21)));
/* Запрет прерываний от таймера */
outportb(0x21,mask|0x01);
/* Индикация нового состояния */
for (i=0;i<10;i++) {
printf("%3d ",clock()); delay(100);
}
printf(" маска=%02x\n",inportb(0x21));
/* Восстановление старой маски */
outportb(0x21,mask);
/* Индикация восстановленного состояния */
for (i=0;i<10;i++) {
printf("%3d ",clock()); delay(100);
}
printf(" маска=%02x\n",inportb(0x21));
}
Из текста программы видно, что порт 0x21 доступен и для записи, и для чтения. Таким образом, для корректного запрета выбранного прерывания необходимо прочитать текущее состояние маски прерываний, и занести в него запрещающую единицу при помощи операции "логическое ИЛИ".
Для AT разряд 2 используется для каскадирования второго контроллера прерываний. Доступ к маске второго контроллера - через порт 0xA1. Назначения разрядов второй маски следующие:
0 |
- прерывание часов реального времени; |
1 |
- прерывание контроллера EGA; |
5 |
- прерывание математического сопроцессора; |
6 |
- прерывание контроллера жестких дисков; |
2,3,4,7 |
- зарезервированы. |
