Всем доброго вечера! Ещё не работал с прерываниями, но уже пора бы. Прерывания нумеруются от 0 до 255 (всего 256 штук). Таблица векторов прерываний должна храниться в регистре IDR. Это всё понятно. Вот сами прерывания: Решил я сегодня почитать про клавиатуру. И оказалось что она может попросить процессор уделить ей немного времени (причём по приоритету не на последнем месте): И тут я не понял! Там прерывания, тут прерывания - объясните. Этот нижний список ничем не совпадает с верхним. Какое же тогда прерывание получает процессор от клавиатуры? Что за
s3dworld Процессор может прерываться. Так вот различают программные и аппаратные прерывания. Аппаратные в свою очередь делятся на внешние и внутренние. Так вот для обработке прерываний в процессоре есть таблица прерываний на которую ссылается регистр IDR. Так вот первые 0-31 прерываний жестко соотнесены с внутренними аппаратными прерываниями процессора. Они у тебя записаны в 1 таблице. Они возникают в случае ошибок. Деления на ноль доступ за приделы лимита сегмента отсутствия страницы. Переполнения стека. и тд. А есть внешние прерывания которые поступают в процессор по линии #INTR. Поступают они от внешнего контроллера прерывания. Процессор по приходу сигнала делает запрос у контроллера прерываний чтобы получить номер прерывания. Так вот вторая таблица это номера ног в системе из двух внешних контролеров прерываний 8259А. Эти номера складываются с базой и получается номер вектора прерывания из таблицей IDT. Базу ты должен записать сам в 8259А. Система прерываний. Система прерываний стара и поэтому очень запутана. Источниками прерываний являются устройства эти устройства располагаются на шинах PCI и ISA. Во времена шины ISA каждое устройство цеплялось на свою линию IRQ( Interupt ReQuest) , а она в свою очередь шла на контроллер прерываний 8259А. Оттуда выходил сигнал по линии INTR на процессор или на другой контроллер прерываний. С выходом PCI все усложнилась. Шина PCI имела только 4 линии прерываний на все устройства. С вводам мультипроцессорных систем все еще больше усложнилось появилась системная меж процессорная шина. И появился еще один контролер APIC. Вернее два один внутри каждого процессора Local APIC, а второй I/O APIC на чипсете. PIC - PROGRAMMABLE INTERRUPT CONTROLLER Программируемый контроллер прерываний - ПКП Или также известный как 8259А Контроллер этот появился так давно, что совместим с процессорами 8080/8085 . Так как современные компьютеры их не используют. То нас больше интересует его работа в режиме совместимости с 8086/8088. Поэтому будет описана только часть относящаяся к нему. Контроллер имеет 8 линий IRQ. Этого мало, поэтому была разработана возможность каскадного подключения контроллеров. Когда к видящему Master контроллеру подключались, ведомые Slave контроллеры. Теоретически возможно, что мы имеем один ведущей и восемь подчиненных. Но в стандартном компьютере всего два - первый ведущий и второй ведомый. Первый контроллер прерываний 8259А использует порты 20h-21h, второй 8259А использует 0A0h-0A1h Второй контроллер сидит на IRQ2 первого контроллера. Стандартное назначение прерываний следующее. Согласно документации на Award BIOS и ряда других спецификаций. Код (Text): +-----+-------+----------------------------------------+ | INT | IRQ | Назначение | +-----+-------+----------------------------------------+ | 08h | IRQ0 | Системный таймер (канал 0 8253/8254) | +-----+-------+----------------------------------------+ | 09h | IRQ1 | Клавиатура | +-----+-------+----------------------------------------+ | 0Ah | IRQ2 | Каскадное подключение #2 8259A | +-----+-------+----------------------------------------+ | 0Bh | IRQ3 | COM2 | +-----+-------+----------------------------------------+ | 0Ch | IRQ4 | COM1 | +-----+-------+----------------------------------------+ | 0Dh | IRQ5 | LPT2 | +-----+-------+----------------------------------------+ | 0Eh | IRQ6 | FDC(Floppy Disk Controller) | +-----+-------+----------------------------------------+ | 0Fh | IRQ7 | LPT1 | +-----+-------+----------------------------------------+ +-----+-------+----------------------------------------+ | 70h | IRQ8 | Real time clock | +-----+-------+----------------------------------------+ | 71h | IRQ9 | Резерв, используется PCI | +-----+-------+----------------------------------------+ | 72h | IRQ10| Резерв, используется PCI | +-----+-------+----------------------------------------+ | 73h | IRQ11| Резерв, используется PCI | +-----+-------+----------------------------------------+ | 74h | IRQ12| Мышь PS/2, Резерв, используется PCI | +-----+-------+----------------------------------------+ | 75h | IRQ13| 80387 математический сопроцессор | +-----+-------+----------------------------------------+ | 76h | IRQ14| Первичный канал IDE HDD | +-----+-------+----------------------------------------+ | 77h | IRQ15| Вторичный канал IDE HDD | +-----+-------+----------------------------------------+ Шина ISA рассчитано на активацию прерывание фронтом. Поэтому на одном прерывании может сидеть одно устройство. Для того чтобы не лазить по спецификациям была придумана технология PnP она позволяет определить на каком прерывании сидит устройство. И не просто определять, но и задавать его программно. Раньше для этого были перемычки. PnP так же позволяет получить информацию о ресурсах устройств. Контроллер PIC содержит следующие регистры. Регистр запроса на прерывание (Interrupt Request Register, IRR) доступ к которым осуществляется через входы IR0 - IR7 контроллера. Бит этого регистра устанавливается в 1 если был выбран режим запуска фронтом и происходит перепад напряжения от низкого к высокому. Или если был выбран режим запуска уровнем то устанавливается в 1 при высоком уровне. Этот бит устанавливается в 1 или сбрасывается в 0, даже если соответствующее прерывание было замаскировано. Он будет сброшен, как только поступит цикл запроса прерывания INTERRUPT ACKNOWLEDGE. Регистр обрабатываемых запросов, (In-Service Register, ISR) описывает в битах 0 - 7 номер прерывания которое (0 - 7) в данный момент обрабатывается. Эти биты устанавливаются и соответствующие ему IRR очищаются когда поступит цикл запроса прерывания INTERRUPT ACKNOWLEDGE. Этот бит будет сброшен как только будет получена команда подтверждение конца прерывания(End of Interrupt Command - EOI) Регистр маскирования запроса на прерывания (Interrupt Mask Register, IMR) описывает,какие номера прерывания в настоящий момент замаскированы. Единичное значение бита в IMR указывает на то, какое прерывание при появлении запроса в IRR будет заблокировано. При этом INTR не генерируется. Программирование контроллера осуществляется с помощью команд. Initialization Command Words (ICW1- ICW4) Командные слова для инициализации. Operation Command Words (OCW1- OCW3) Командные слова для действий. Перед началом работы процессор должен инициировать контроллер. Последовательностью из 2-4 команд ICW. После инициализации можно отправлять OCW. Команды инициализации подаются одна за другой. Сначала ICW1 затем ICW2 если был выбран каскадный режим, то подается ICW3 и если был запрошен то ICW4. Формат команд 9битный. 8 бит сама команда, а 9 бит это бит с шины адреса, он задается номером порта. Четный порт соответствует 0, а нечетный 1. Формат ICW1 следующий: Бит 0 говорит о том, будет ли послан ICW 4 или нет БИТ 1=0 говорит о каскадном подключение контроллеров именно такой способ используется в современной архитектуре. Если он установлен в 0 то нужно будет посылать ICW3 иначе нет. БИТ 2 используется в режиме 80/85 Бит 3 определяет по какому состоянию линий будет срабатывать триггер Бит 4 =1 означает началу инициализации, посылку ICW1 БИТ 5-7 используются в режиме 80/85 Код (Text): A0 7 6 5 4 3 2 1 0 +----+----+----+----+----+----+----+----+----+ | 0 | -- | -- | -- | 1 |LTIM| ADI|SNGL| IC4| +----+----+----+----+----+-+--+-+--+-+--+-+--+ | | | | | | | +-> 1=будет вывод ICW4 | | | 0=не будет | | +------> 1=один контроллер | | 0=каскад | +-----------> игнорируются в режиме 86/88 +----------------> 0=запуск запросов фронтом 1=запуск запросов уровнем Формат ICW2 следующий, это номер начального вектора прерывания. Биты 0-2 должны быть 0. При приходе прерывания. Номер линии, на которую пришло прерывание, складывается с этим числом. И выставляется на шину адреса. Код (Text): A0 7 6 5 4 3 2 1 0 +----+----+----+----+----+----+----+----+----+ | 1 | T7 | T6 | T5 | T4 | T3 | 0 | 0 | 0 | +----+----+----+----+----+----+----+----+----+ Формат ICW3 различаются для ведущего и ведомого. У ведущего каждый бит говорит к какой линии подключен ведомы контроллер. Если у нас 2 ведущих контроллера и они подключены к с 7 и 6 контроллеру то будет равно 11000000b = 0E0h. В настоящей системе только один ведомый контроллер, подключенный ко второй линии 00000100b = 04h Код (Text): A0 7 6 5 4 3 2 1 0 +----+----+----+----+----+----+----+----+----+ | 1 | S7 | S6 | S5 | S4 | S3 | S2 | S1 | S0 | +----+----+----+----+----+----+----+----+----+ Ведущий. У ведомого это просто номер, линии по который он подключен к ведущему контроллеру. Т.е для реальной системы это вторая линия 2 Код (Text): A0 7 6 5 4 3 2 1 0 +----+----+----+----+----+----+----+----+----+ | 1 | 0 | 0 | 0 | 0 | 0 |ID2 |ID1 |ID0 | +----+----+----+----+----+----+----+----+----+ Ведомый. Последнее слово инициализации (ICW4) имеет следующий формат: Код (Text): A0 7 6 5 4 3 2 1 0 +----+----+----+----+----+----+----+----+----+ | 1 | 0 | 0 | 0 |SFNM| BUF| M/S|AEOI| mPM| +----+----+----+----+-+--+-+--+-+--+-+--+-+--+ | | | | | | | | | +---> 1=8086/8088 | | | | 0=8080/8085 | | | +--------> 1=AEOI | | | 0=EOI | | +-------------> 1=ведущий | | 0=ведомый | | (только при BUF=1) | +------------------> 1= режим буферизации | 0= режим без буферизации +-----------------------> 1=специальный вложенный режим БИТ 0 (mPM) определяет режим совместимости с 86/88 или 80/85 в нашем случи он равен 1 БИТ 1 (AEOI) если равен 1, то контроллер будет автоматически сбрасывать ISR бит. А если равен 0, то обработчик прерывания сам должен его сбрасывать при помощи OCW. Бит 2 (M/S) игнорируется, если бит 3 (BUF) = 0. При наличии одного контроллера и BUF = 1 устанавливается в 1. При наличии каскада должен быть равен 1 только для ведущего контроллера. Бит 4 (SFNM) устанавливает специальный вложенный режим, применяемый при каскадировании для определения приоритетов запросов от разных контроллеров (Special Fully Nested Mode) Значение по умолчанию для ICW4. Intel выпускает чипсеты, где значение по умолчанию 01. Хотя когда-то раньше, когда контроллер не входил в чипсет и был предназначен для 80/85, значение по умолчанию было 00. Если не было запроса на ввод ICW4, то используется значение по умолчание. Управляющее слово OCW1 Код (Text): A0 7 6 5 4 3 2 1 0 +----+----+----+----+----+----+----+----+----+ | 1 | M7 | M6 | M5 | M4 | M3 | M2 | M1 | M0 | +----+----+----+----+----+----+----+----+----+ Установленный в 1 бит маскирует соответствующее прерывание. Это значит, что пришедшее прерывание не будет обрабатываться. Управляющее слово OCW2 Код (Text): A0 7 6 5 4 3 2 1 0 +----+----+----+----+----+----+----+----+----+ | 0 | R | SL | EOI| 0 | 0 | L2 | L1 | L0 | +----+----+----+----+----+----+----+----+----+ Бит 4-3 позволяет отличить OCW2 от OCW3 R,SL,EOI задают один из режимов 000 = Rotate in Auto EOI Mode (Clear) 001 = Non-specific EOI command 010 = No Operation 011 =* Specific EOI Command 100 = Rotate in Auto EOI Mode (Set) 101 = Rotate on Non-Specific EOI Command 110 = * Set Priority Command 111 = * Rotate on Specific EOI Command * Используются L0 – L2 По завершению прерывания нужно вызвать EOI. PIC работает следующем образом. Когда выставляется сигнал на линию, контроллер получив сигнал вырабатывает запрос на прерывание по линии INTR- interrupt request сигнал. Процессор отвечает по линии INTA - INTERRUPT ACKNOWLEDGE . Контроллер замораживает состояние прерываний при помощи ISR. Процессор подает второй INTA и теперь уже контроллер отправляет данные на шину данных. Это номер прерывания. Начальный адрес записанный в контроллер плюс номер линии на которую поступило прерывание. Если имеется каскадное подключение. А такое подключение, как мы знаем, имеется. То ведущий контроллер выставляет ID на линии CAS0-2. Ведомый сравнивает его со своим ID ,который он получил по ICW3. И при втором запросе INTA ведомый выставляет номер прерывания на шину адреса. Пример программирования PIC. В защищенном режиме процессора прерывания от процессора занимают вектора с 0 по 13h и c 14h по 1Fh зарезервированы. Так что аппаратные прерывания надо подвинуть. Код (Text): MOV DX, 20h // Ведущий MOV AH, 20h //Номер начального прерывания для ведущего контроллера 08 стандартное для реального режима MOV AL,11h //ICW1 бит 0=1 сигнализирует, что будет послан ICW4 OUT DX,AL MOV AL,AH //ICW2 - начальный номера прерываний биты 2-0=0. INC DX OUT DX,AL MOV AL,4 //ICW3 ведущий 00000100 - ведомый подключен ко второй линии OUT DX,AL MOV AL,1 //ICW4 режим 86/88 OUT DX,AL MOV DX, 0A0h // Ведомый MOV AH, 28h //Номер начального прерывания для ведомого контроллера 70h стандартное для реального режима MOV AL,11h //ICW1 бит 0=1 сигнализирует, что будет послан ICW4 OUT DX,AL MOV AL,AH //ICW2 - начальный номера прерываний биты 2-0=0. INC DX OUT DX,AL MOV AL,2 //ICW3 ведомый, ведомый подключен ко второй линии ведущего OUT DX,AL MOV AL,1 //ICW4 режим 86/88 OUT DX,AL Шина PCI При появлении прерывании на шине PCI, сигнал преобразовывается c линий PIRQ в линию IRQ на контроллер прерываний. Тот выставляет INTR. Процессор, получив сигнал, генерирует ответ. Для этого на шине PCI выставляется специальный запрос - interrupt acknowledge cycle. Этот запрос распространяется по всей шине PCI в результате чего он доходит до контроллера прерываний. Контроллер прерываний находится на ISA(LPC) шине. Поэтому мост между PCI и ISA генерирует два сигнала INTA и получает ответ от контроллера прерываний, шина PCI передает ответ процессору, номер прерывания. Прекращается acknowledge cycle. Но такой подход не порадовал разработчиков. И был придуман второй способ посылки прерываний. Message Signaled Interrupt (MSI) сообщение сигнализирующее прерывание. Устройство пишет сообщение по определенном адресу, определенного формата. Это сообщение сигнализирует о прерывании. Это позволяет избежать задержек связанных с interrupt acknowledge cycle. Шина PCI устроена следующем образом. У нее 4 провода для прерываний И каждая карта имеет 4 вывода PIRQA# PIRQB# PIRQC# PIRQD#. Линии эти устроены, так что они циклически сдвигаются, при переходи от 1 устройства ко второму. Тем самым первое устройство подсоединю к линии A второе к B третье к С и четверное к D пятое к A и т.д. Устройств больше чем линий, тем самым на одной линии сидит несколько устройств. Когда устройству нужно прерывание оно выставляет логическую 1. Шина PCI позволяет совместно использовать прерывания. Вопрос как тогда отелить чье именно прерывание пришло? Ответ прост каждое устройство должно быть снабжено дополнительным битом. Обработчики прерываний сидящие на одном прерывании по очереди проверяют, а их ли это устройство вызвало прерывания. До появления спецификации PCI 2.3 это дело было железо зависимым. С появлением же добавили бит в PCI CFG регистр Device Status бит 3 interrupt status Только чтение. Выставление бита Interrupt Disable не приводит к сбросу interrupt status Так как провода просто соединены. То они тем самым выполняют роль логического И. Контроллер прерываний срабатывает в отличии от шины ISA не по перепаду из 0 в 1 (фронту). А по уровню – выставленному значению 1 . Если он видит 1 то срабатывает и будет срабатывать пока устройство не снимет прерывание. Поэтому ISA прерывания не должны пересекаться с прерываниями PCI. Для этого в PCI BIOS и в $PIR предусмотрено поле которое показывает доступные IRQ для PCI. Простая посылка EOI сбрасывает только триггер в контроллере и не меняет состояние линии поэтому контроллер должен тут же сработать еще раз. Поэтому чтобы такого не было нужно запретить прерывания. Это можно сделать одним из способов. Замаскировать прерывания на контроллере прерывания, но это приведет также к маскированию и других устройств висящих на этом же прерывании. Второй способ запретить прерывания на самом устройстве . В PCI 2.3 добавили в регистр Command бит 10 Interrupt Disable Этот бит запрещает прерывание по INTx#. Значение 0 разрешает сигнал по INTx# . А значение 1 запрещает сигнал по линии INTx# . После перезагрузки бит равен 0. INTx# это тоже самое что PIRQx# где x – A-D На самом деле если включен режим PIC , то линя PIRQx# преобразуется в IRQ. Если включен, I/O APIC линии не переназначаются они напрямую идут к контактам 16-19(IRQ16-19) а он уже волн сменить номер вектора. Это преобразование называется IRQ Routing. Номера какой линии PIRQ преобразуется в какой номер IRQ задается. Запрограммировать его можно одним из 3 способов: ACPI, PCI BIOS, через порты ввода вывода. Последний способ это железо зависимый способ. В мосту PCI -to –ISA выставляются соответствующие биты. ACPI – это тема для отдельной статьи или даже книге. Майкрософт ввела спецификацию PCI IRQ Routing Table Specification. Согласно этой спецификации PCI BIOS должен быть снабжен таблицей, которая описывает маршрутизацию. Эта таблица аналогична данным получаемым через функцию PCI BIOS GetIRQRoutingTable. А для перепрограммирования в PCI BIOS есть функция SetPCIHardwareInterrupt.
Вот рисунок к вышеприведённой статье. Увы прочитав её мне так и не стало ясно как из 512 линий IRQ мы выходим на 256 обработчиков прерываний, какая линия IRQ с каким дескриптором в IDT связана. Есть ли какие нибудь функции для просмотра этого или команды в WinDbg. Команда !PIC отображает 16 IRQ, а !ioapic вообще не понятно что, что только добавляет каши в голову.
От куда число 512, для выбора - байт-же? итого 256. А вообще, векторы обработчиков находятся не только в IDT, но и в MMIO apic. Сейчас платы строится уже на Serial PCE-Express, а пар-шина PCI (с линейными IRQ) уже уходит в прошлое. Устройства PCIe сигнализируют о прерываниях через MSI, хотя могут и стандартным способом, если чипсет не поддерживает. Режим задаётся в конфигурационном пространстве устройства (функции) PCI. Сейчас Local-APIC имеет свою область памяти в верхних адресах, с фиксированной базой 0xFEE00000. ЦП расценивает любое обращение в эту/18-метровую область как запрос на прерывание MSI, а ОС должна контролировать этот регион от случайных вторжений. (кстати, поэтому 32-битная винда не видит больше 3.5 гигов озу, ОС просто затеняет системные регионы от юзера): Для запроса прерывания, драйвер устройства PCI посылает процу сообщение MSI. Эта мессага представляет собой обычную запись д'ворда в определённую ячейку MMIO. Адрес ячейки и шаблон сообщения записываются в конфиг/регистры девайса на этапе его конфигурирования, PCI-регистры называются Message_Address/Data соответственно (см.описание в манах IA32/64 vol.3 - Programming Guide). Поддерживающее MSI устройство определяется в конфиг/пространстве полем MSI_CapID (должно быть =5), там-же задаются и ресурсы устройству: В модели MSI устройство отправляет сообщение своему драйверу, записывая конкретный адрес памяти. Это действие генерит прерывание в LocalAPIC, после чего Win вызывает ISR с тушкой сообщения и адресом, в который была отправлена мессага. Устройство MSI может отправлять до 32-х различных типов сообщений, определяя конкретное событие (в MSI-X их увеличили вообще до 2048). Этим MSI отличается от линейных прерываний, которые способны передавать только (!)одно событие, а какое именно - драйвер должен определять перебором. Поскольку MSI основана на прямом взаимодействии с памятью (и контент доставляется вместе с прерыванием), необходимость в линиях IRQ отпадает, а значит их потолок ограничивает только число векторов прерываний в системе, а не физических линий IRQ APIC. Из-за огромного кол-ва прерываний MSI, это фактически сводит на нет любое преимущество обмена по INT, т.к. данные прямиком доставляются в соответствующий ISR. -------------------------------- ..стандартную-же модель ioAPIC, достаточно внятно описал Pavia постом выше, а я лишь добавлю несколько слов. Под номера линейных IRQ выделяется 1-байт, возможное кол-во 256. Физических линий гораздо меньше (24 у одного apic i82093, но могут соединяться каскадно), поэтому девайсам приходится делить линии по-братски - на некоторых висят по 5-6 устройств. Скачай программу PCIScope, она выводит исчерпывающую инфу о девайсах, в частности пространстве MMIO с полным описание регистров PCI всех устройств. Советую.. IDT - это 1 сегмент с лимитом 7FFh (32-бит система). В ней всего 256 записей, для каждого прерывания свой дескриптор 8-байт. Вот как видит её отладчик Syser.. Он не разделяет шлюзы прерываний и ловушек, хотя шлюз-задачи удостоился от отладчика личной метки (Task). При генерации прерывания происходит следующее.. Из регистра IDTR извлекается база IDT, в которой по номеру прерывания определяется его дескриптор. Если бит Present(Р) в найденном дескрипторе сброшен, значит данное прерывание не обрабатывается системой - в этом случае GP#. Если Р=1, то проверяется RPL запросившей прерывание задачи, он должен быть меньше\равно DPL дескриптора прерывания, иначе опять GP#. Для исключений и аппаратных прерываний этот пункт игнорируется. Если всё ОК, то стек переключается и в стеке-обработчика сохраняется указатель на стек прерванной задачи SS:ESP, ну и адрес возврата: Код (Text): >> cpu 0 GDT Base=8003F000 Limit=03FF IDT Base=8003F400 Limit=07FF TSS Selector=0028 Base=80042000 Limit=20AB LDT Selector=0000 Base=00000000 Limit=FF394D44 >> idt IDTBase = 8003F400 Limit = 7FF ----------------------------------------------------------------- Int Type Sel : Offset Attributes Module 0000 IntG32 0008:804DF360 DPL=0 P ntoskrnl 000E IntG32 0008:F200A5C0(0008:804E167E) DPL=0 P Syser(ntoskrnl) 0013 IntG32 0008:804E1CAC(0008:804E18F3) DPL=0 P ntoskrnl(ntoskrnl) 001F IntG32 0008:80712FD0(0008:804E18F3) DPL=0 P hal(ntoskrnl) 0020 Reserved 0008:00000000 DPL=0 NP ...... 0029 Reserved 0008:00000000 DPL=0 NP 00FC IntG32 0008:804DE4BB DPL=0 P ntoskrnl 00FD IntG32 0008:80713464(0008:804DE4C2) DPL=0 P hal(ntoskrnl) 00FE IntG32 0008:80713604(0008:804DE4C9) DPL=0 P hal(ntoskrnl) 00FF IntG32 0008:804DE4D0 DPL=0 P ntoskrnl 0002 TaskG 0058:0000113E(0008:804DF5C6) DPL=0 P (ntoskrnl) 0008 TaskG 0050:00001198(0008:804E06AD) DPL=0 P (ntoskrnl) 0012 TaskG 00A0:804E18F3 DPL=0 P ntoskrnl ....User DPL=3.............. 0001 IntG32 0008:804DF4DB DPL=3 P ntoskrnl 0003 IntG32 0008:804DF8AD DPL=3 P ntoskrnl 0004 IntG32 0008:804DFA30 DPL=3 P ntoskrnl 002A IntG32 0008:804DEBA2 DPL=3 P ntoskrnl 002B IntG32 0008:804DECA5 DPL=3 P ntoskrnl 002C IntG32 0008:804DEE44 DPL=3 P ntoskrnl 002D IntG32 0008:F7ABCF96(0008:804DF78C) DPL=3 P SDbgMsg(ntoskrnl) 002E IntG32 0008:804DE631 DPL=3 P ntoskrnl 002C IntG32 0008:804DEE44 DPL=3 P ntoskrnl 002D IntG32 0008:F7ABCF96(0008:804DF78C) DPL=3 P SDbgMsg(ntoskrnl) Кроме того, в сегменте TSS имеется 32-байтная карта перенаправления 'INT redirection bit-map'. Она позволяет перенаправлять: 32*8(бит)=256 юзерских прерываний. Одно прерывание - 1 бит, который отображается на соответствующий дескриптор в таблице(IDT). Если бит в битмапе =1, то управление передаётся через дескриптор(IDT) обработчику Р-моды. Если бит нуль, запрос перенаправляется в таблицу векторов R-моды 0:0. Этот битмап ввели для режима V86: Код (Text): >> tss TR = 0028 BASE = 80042000 LIMIT = 20AB CR3 = 17CEF000 SS:ESP(0)=0010:F5D58DE0 SS:ESP(1)=4338:D0685000 SS:ESP(2)=C483:FFFF33B5 I/O permission map.....: BASE = 20AC, SIZE = 0 INT redirection bit-map: BASE = 80042068, SIZE = 32 0 1 2 3 4 5 6 7 - 8 9 A B C D E F ------------------------------------ 0x80042068 0400 0 0 1 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0x8004206A 0018 0 0 0 0 0 0 0 0 - 0 0 0 1 1 0 0 0 1 0x8004206C 1800 0 0 0 1 1 0 0 0 - 0 0 0 0 0 0 0 0 2 0x8004206E 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 3 ~ ~ ~ ~ ~ ~ ~ ~ ~ 0x80042084 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 E 0x80042086 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 F
Железки слишком сложны что бы самому понять как они устроены и написать обслуживающий код. Сейчас так не делается, это чёрный ящик к которому предоставляется драйвер от производителя. По тому же апик - есть системные доки(IA), но думаю их смысла нет даже открывать, это предназначено для разрабов железа. Но не для прикладного прог-ния. Эти железки очень сложны и изменяются с каждой реализацией, описание лишь условно.