Как определить прерывания, специфичные для устройства на x86?
Вопрос
В руководстве разработчиков программного обеспечения Intel говорится, что векторы прерываний 32–255 обычно определяются пользователем для внешних устройств ввода-вывода.На уроке системного программирования мне нужно разработать простой драйвер устройства.Мой вопрос: как я могу определить конкретный вектор прерывания, который будет использоваться для конкретного устройства?Это делается через биос?
Примечание:мы разрабатываем простую операционную систему, поэтому моя ситуация достаточно специфична, однако в конечном итоге мне нужно понять, как все это происходит в системе x86.В настоящее время наша система настроена так, что несколько векторов прерываний с номером выше 32 назначаются таким устройствам, как последовательный порт и клавиатура.При чтении таблицы данных контроллера ввода-вывода Intel 82801EB ICH5, в частности раздела, касающегося PIC 8259, говорится, что IRQ15 является вторичным каналом IDE.Как это в конечном итоге будет помещено в стек как вектор прерывания?
Возможно, я просто настолько сбит с толку, что этот вопрос не имеет смысла, поэтому заранее прошу прощения.
РЕДАКТИРОВАТЬ:Итак, наш класс системного программирования имеет очень простую ОС, в которой есть процедуры ядра для установки ISR для обработки определенных прерываний с учетом номера вектора.На нашем занятии в прошлой четверти профессор дал нам заголовочный файл, в котором клавиатура определялась как векторный номер 0x2c или что-то подобное.Я пытаюсь выяснить, как сопоставить прерывания основного и/или вторичного канала IDE с различными ISR, используя наши процедуры ядра.На данный момент все неиспользуемые векторы прерываний имеют обработчик по умолчанию, который будет печатать сообщения в случае возникновения прерывания, поэтому прерывания IDE в данный момент даже не включены, однако это другой вопрос.
Решение 5
Что ж, кажется, я нашел ответ в нашем коде поддержки, в частности, в процедуре инициализации PIC.В следующем коде строки IRQ отображаются со смещением 20h и 28h в IDT для ведущего и ведомого PIC соответственно.
/*
ICW2: master offset of 20 in the IDT, slave offset of 28
*/
__outb( PIC_MASTER_IMR_PORT, 0x20 );
__outb( PIC_SLAVE_IMR_PORT, 0x28 );
Это означает, что клавиатура была сопоставлена с вектором номер 2c, а первичный и вторичный каналы будут сопоставлены с 2e и 2f соответственно.Некоторые из вас, вероятно, могли бы дать мне лучшие ответы, если бы я задал вопрос лучше, но я все равно ценю помощь!
В таблице 45 таблицы данных 82801EB ICH5 подробно описаны линии IRQ 8259, и в моей ОС ведущий просто загружается со смещением 20h, а ведомый — 28h.
Спасибо!
Другие советы
Вы можете запрограммировать PIC (программируемый контроллер прерываний) для сопоставления IRQ определенных устройств.
На платформе x86 есть два PIC, которые соединены последовательно и выдают IRQ0-IRQ17.IRQ0-7 управляется 8259, а IRQ8-15 — вторым 8259.Первый сигнализирует ЦП и является ведущим, а второй (ведомый) сигнализирует первому.
IDT (таблица дескрипторов прерываний) сопоставляет прерывания с адресами ISR (процедур обслуживания прерываний).Прерывания могут быть вызваны напрямую с помощью инструкции INT (программные ловушки).
Например, чтобы вызвать прерывание 0x80, выполните INT 0x80
.
Чтобы обработать 0x80, mov [0x80*4], int_80_handler
.Предполагая 32-битную архитектуру, адрес int_80_handler
функция теперь хранится в 0x80-м месте в IDT.
Вы найдете это полезным:
http://en.wikipedia.org/wiki/Intel_8259
http://en.wikipedia.org/wiki/Interrupt_Handler
http://en.wikipedia.org/wiki/Прерывание
http://en.wikipedia.org/wiki/Interrupt_descriptor_table
Прошло много времени с тех пор, как я имел дело с этим материалом, поэтому это может быть отключено:Напомню, что контроллер прерываний ПК имеет 15 линий IRQ.Они сопоставляются с конкретными соседними векторами прерываний x86.Таким образом, когда периферийное устройство запускает линию IRQ, PIC прерывает работу ЦП и сообщает, к какому вектору перейти, как если бы была выполнена соответствующая инструкция INT.Некоторые IRQ жестко запрограммированы на определенных периферийных устройствах, но я считаю, что устройства PCI договариваются с ОС о IRQ и некоторых других ресурсах (как и устаревшие устройства ISA PnP).
Я не понимаю, что вы имеете в виду под «Как это в конечном итоге будет помещено в стек как вектор прерывания?»
Устройство может получить прерывание двумя способами:
Используйте механизм Plug and Play или Pci.Если вы это сделаете, BIOS вызовет ваше периферийное устройство и запросит требования к ресурсам.После этого ваш драйвер может перечислить устройства Plug-and-Play, выполнить поиск поддерживаемого устройства и получить аппаратное прерывание от устройства.
Как это делалось в первые дни:Просто используйте одно прерывание.Добавьте к устройству DIP-переключатель, который позволит пользователю выбирать между различными прерываниями.Распределение ресурсов теперь находится в руках пользователей.Пользователь также каким-то образом передаст номер прерывания драйверу во время загрузки.
Теперь как перехватить прерывание:Это зависит от ОС и режима, в котором работает x86.Для голой, голой системы вы можете запросить IDT (таблицу дескрипторов прерываний) с помощью специальной инструкции.Получив этот IDT, вы можете получить адрес и вставить адрес обработчика IRQ в правильный слот.Что касается реального режима, я больше не знаю, как это делается.
Если у вас работает хотя бы небольшая ОС реального времени или что-то похожее на ОС, вполне вероятно, что уже существует функция ядра, которая делает всю тяжелую работу за вас.
Насколько я помню, в начале области памяти есть таблица векторов, указывающая на подпрограмму, которую следует вызывать при возникновении определенного прерывания.Возможно, я здесь нахожусь на слишком низком уровне (старый программист на ассемблере x86), но на базовом уровне вы устанавливаете свой вектор в эту таблицу, а затем вызываете вашу подпрограмму.У меня нет с собой никаких старых справочных материалов, поэтому я не могу дать вам конкретные рекомендации, но я был бы удивлен, если бы официальный метод работал вне BIOS.
Я уверен, что в наши дни графических интерфейсов существуют другие, более подходящие методы, которые позволяют совместно использовать прерывания и все такое хорошее.
РЕДАКТИРОВАТЬ:Не обращайте на это внимания, я только что увидел, что вы смотрите на прерывания 16 и выше, которые находятся за пределами аппаратных прерываний.Я отошел от этого уровня программирования до того, как в этом пространстве появилось что-то интересное, поэтому я имел дело только с первыми 15 IRQ (16-е — каскад между контроллерами).Оставлю, вдруг кому-то будет интересно :)
INT 21h / AH=25h - установить вектор прерывания;вход:AL = номер прерывания.DS:DX -> новый обработчик прерываний.