; Файл C:\WORK\ASM\DRV\IRQ_DRV\IRQ.DEF comment~ Контроллер прерываний (КП) Все запросы на аппаратные прерывания из системной шины направляются через два контроллера прерываний (КП) 8259A на вход процессора (ЦП) INTR. Процессор подаёт через выход INTA сигнал на подтверждение прерывания и по- лучает по локальной шине D0-D7 от КП номер вектора прерывания. После чего, он приостанавливает исполнение те- кущей программы и начинает обрабатывать прерывание. Обработчик прерывания, выполнив заданную последова- тельность действий посылает в КП команду окончания обработки прерывания. Контроллер прерываний (8259A) имеет следующие регистры - IMR регистр масок; установленные биты указывают, какие номера прерываний запретить обрабатывать; - IRR регистр запросов на прерывание, содержит номера поступивших запросов на прерывание, бит соответствующему запросу сбрасывается после подтверждения прерывания (IMR на IRR не влияет); - ISR регистр обслуживаемых прерываний, указывает номера обслуживаемых прерываний. Прерывания от отдельных устройств можно запретить, устанавливая в регистре масок IMR контроллера, соот- ветствующие им биты. Запретить прерывания от всех устройств можно очисткой бита IF в регистре флагов ЦП. КП может воспринимать запросы на прерывания от устройств как по уровню, так и по фронту сигнала. Это программи- руется в процедуре настройки КП. Когда устройство подаёт запрос на прерывание, в регистре запросов на прерывание IRR устанавливается соответствующий ему бит. Если в регистре обслуживаемых прерываний ISR нет необслуженных прерываний с б\'ольшим приоритетом, и прерывание от данного устройства незамаскировано, то выдаётся запрос на вход INTR ЦП. После по- лучения подтверждения прерывания от ЦП по входу INTA в ISR устанавливается соответствующий ему бит. Сброс бита в ISR осуществляется подачей в КП соответствующей команды из ЦП обработчиком прерывания. Микросхема 8259A позволяет подключать к себе до восьми устройств. Чтобы расширить количество обрабаты- ваемых прерываний, в IBM PC/AT контроллеры прерываний включены каскадом. Один из КП играет роль ведущего (Master), а второй --- ведомого (Slave). Выход INTR ведомого контроллера подключён к одному из входов ведуще- го, а выход INTR ведущего --- к соответствующему входу ЦП (см. структуру подключений). Получив от ЦП подтверждение прерывания (по общей для обоих КП шине INTA), если оно относится в ведомому КП, ведущий по ло- кальной шине cas0-cas2 сообщает ведомому, что ведомый должен выдавать вектор прерываний на шину D0-D7. Перед использованием контроллеров прерываний необходимо выполнить их настройку вначале ведущего КП, а за- тем ведомого. В процессе настройки ИС 8259A ведущего КП нужно, в частности, указать к каким его входам подключены ведомые КП, а ИС 8259A ведомого -- к какому входу ведущего КП она подключена. К ИС 8259A, настроен- ной как ведущий КП, может подключаться до восьми ведомых ИС 8259A (в IBM PC используется только один), что в принципе позволяет обрабатывать до 64 запросов прерываний. После того, как ведущий КП передаёт в ЦП запрос на прерывание от ведомого КП и получает подтверждение, он выдаёт на локальную шину cas0-cas2 номер входа, к кото- рому подключён ведомый контроллер. Ведомый контроллер отслеживает состояние входов на шине cas0-cas2, и когда обнаруживает свой номер, обрабатывает подтверждение своего запроса прерывания. Структура подключения контроллеров прерываний в IBM AT Шина управления <═╤╤═══════════════════════════════════════════════════╤╤════════════> ││ ││ ││ Шина данных ││ ││ <════════════════════════════════════════════))══════════════> ││ ^ ││ ^ ││ ║ Локальная шина cas0-cas2 ││ ║ ╔═))═════════)═══════════════════════════════════════╗ ││ ║ ║ ││ ║ ║ ││ ║ ║ ││ v ║ ││ v ║ ││ ╔════╤══════╤════╗ ║ ││ ╔════╤══════╤════╗ ║ │└>╢ A0 │D0-D7 │ ║ ║ │└>╢ A0 │D0-D7 │ ║ ║ └─>╢ CS ├──────┤ ║ ║ └─>╢ CS ├──────┤ ║ ║ ╟────┤8259A │irq0╟<──<Канал 0 таймера ║ ╟────┤8259A │irq0╟<──<Часы реального времени (запрос №8) ╟────╢cas0│Master│irq1╟<──<Клавиатура ╟───>╢cas0│Slave │irq1╟<──<Свободно ╟────╢cas1│ │irq2╟<───────────────────────────┐ ╟───>╢cas1│ │irq2╟<──<Свободно ╙────╢cas2│Порт 1│irq3╟<──<Последовательный порт 2 │ ╙───>╢cas2│Порт 1│irq3╟<──<Свободно ╟────┤020h │irq4╟<──<Последовательный порт 1 │ ╟────┤0A0h │irq4╟<──<*Мышь PS/2 (запрос №12) ┌──>╢INTA│ │irq5╟<──<Параллельный порт 2 │ ┌─>╢INTA│ │irq5╟<──<Математич. сопроцессор (запрос №13) │ ║ │Порт 2│irq6╟<──<Гибкий дисковод │ │ ║ │Порт 2│irq6╟<──<Первый контроллер IDE (запрос №14) │ ┌─╢INTR│021h │irq7╟<──<Параллельный порт 1 └───┼──╢INTR│0A1h │irq7╟<──<*Второй контроллер IDE (запрос №15) │ │ ╚════╧══════╧════╝ / │ ╚════╧══════╧════╝ │ │ / │ │ └───> Вход INTR ЦП Каскад │ * -- устройства, не присутствовавшие │ (запрос прерывания) для Slave │ в 286, 386, 486 компьютерах. │ │ Выход INTA ЦП └─────────────────────────────────────────────────────o──< (Подтверждение прерывания) ~ ; Порты, используемые для обращений к контроллерам прерываний. QIRQMaster1 equ 020h ; Первый порт ведущего контроллера прерываний QIRQMaster2 equ 021h ; Второй порт ведущего контроллера прерываний QIRQSlave1 equ 0A0h ; Первый порт подчинённого контроллера прерываний QIRQSlave2 equ 0A1h ; Второй порт подчинённого контроллера прерываний ; Константы номеров запросов прерываний IRQReq_Timer equ 0 ; Прерывание от таймера 0 IRQReq_KBD equ 1 ; Прерывание от клавиатуры IRQReq_IRQSlave equ 2 ; Каскад для Slave IRQReq_Serial2 equ 3 ; Последовательный порт 2 IRQReq_Serial1 equ 4 ; Последовательный порт 1 IRQReq_Parallel2 equ 5 ; Параллельный порт 2 IRQReq_FDD equ 6 ; Гибкий дисковод IRQReq_Parallel1 equ 7 ; Параллельный порт 1 IRQReq_RTC equ 0 ; Часы реального времени (запрос на прерывание #8) IRQReq_PS2Mouse equ 4 ; Прерывание от мыши PS/2 (запрос на прерывание #12)* IRQReq_Math equ 5 ; Математический сопроцессор (запрос на прерывание #13) IRQReq_HDDIDE1 equ 6 ; Жёсткий диск, первый контроллер (запрос на прерывание #14) IRQReq_HDDIDE2 equ 7 ; Жёсткий диск, второй контроллер (запрос на прерывание #15)* ; КП, к которому относится соответствующий номер запроса прерывания IRQReqC_Timer = Yes ; Прерывание от таймера 0 IRQReqC_KBD = Yes ; Прерывание от клавиатуры IRQReqC_IRQNo = Yes ; Каскад для Slave IRQReqC_Serial2 = Yes ; Последовательный порт 2 IRQReqC_Serial1 = Yes ; Последовательный порт 1 IRQReqC_Parallel2 = Yes ; Параллельный порт 2 IRQReqC_FDD = Yes ; Гибкий дисковод IRQReqC_Parallel1 = Yes ; Параллельный порт 1 IRQReqC_RTC = No ; Часы реального времени IRQReqC_PS2Mouse = No ;* Прерывание от мыши PS/2 IRQReqC_Math = No ; Математический сопроцессор IRQReqC_HDDIDE1 = No ; Жёсткий диск, первый контроллер IRQReqC_HDDIDE2 = No ;* Жёсткий диск, второй контроллер ; Адреса векторов прерываний первого и второго контроллеров в реальном режиме. CIRQIntMaster=08h CIRQIntSlave=70h ; Порты, из которых можно прочитать IMR, ISR, IRR: RdISRMaster equ 20h ; (Порт QIRQMaster1) RdISRSlave equ 0A0h ; (Порт QIRQSlave1) RdIRRMaster equ 20h ; (Порт QIRQMaster1) RdIRRSlave equ 0A0h ; (Порт QIRQSlave1) RdIMRMaster equ 21h ; (Порт QIRQMaster2) RdIMRSlave equ 0A1h ; (Порт QIRQSlave2) comment~ Команды контроллера делятся на: команды настройки (ICW) и рабочие команды (OCW). Вначале рассмотрим команды настройки (командные слова ICW1, ICW2, ICW3 и ICW4). Слово ICW1 начинает процесс настройки КП. Оно задаёт по фронту или по уровню сиг- A0 D7 D6 D5 D4 D3 D2 D1 D0 нала на входе КП нужно генерировать запрос ┌──╥──┬──┬──┬──┬────┬──┬────┬───┐ на прерывание; работает ли контроллер в ICW1 │0 ║X │X │X │1 │LTIM│0 │SNGL│IC4│ ┌ каскадном режиме (Master или Slave) или └──╨──┴──┴──┴──┴────┴──┴────┴───┘ │ 1 --- Есть слово ICW4 самостоятельно, а также имеется ли слово │ │ └────┤ 0 --- Нет слова ICW4 ICW4. ┐│ │┌ └ Бит A0 в команде задаётся адресом 1 --- IRQ по уровню ├┘ └┤1 --- одиночный режим работы порта в который она посылается. 0 --- IRQ по фронту │ │0 --- каскадный режим работы ┘ └ ~ ICW1Common equ 00010000b ; Устанавливает биты, характерные для ICW1 ICW1Level equ 00001000b ; Выдавать запрос на прерывание по уровню, а не по фронту ICW1Single equ 00000010b ; Программирует на одиночный режим работы ICW1PrsntICW4 equ 00000001b ; Указывает при программировании, что есть ещё слово ICW4 ; Порт, в который должно выводиться слово ICW1 QIRQicw1Master equ 20h ; для ведущего контроллера (Порт QIRQMaster1) QIRQicw1Slave equ 0A0h ; для ведомого контроллера (Порт QIRQSlave1) ;═══════════════════════════════════════════════════════════════════════════ ;~ Макрос формирует слово ICW1, записываемое в константу ParICW1 (машинный код не генерируется). ; ParICW1 - переменная TASM, в которой возвращается слово ICW1. ; FL - front или level формировать прерывание по фронту или по уровню; ; MSS - Single, Master или Slave один контроллер, главный контроллер или подчинённый контроллер; ; IC4 - наличие слова ICW4, задающего параметры работы контроллера (ICW4, если есть слово, иначе - пусто). _IRQICW1 macro ParICW1, FL, MSS, IC4 ifidni , ; Установить по фронту прерывание ParICW1=ICW1Common ; Установить прерывание по фронту сигнала elseifidni , ParICW1=ICW1Common + ICW1Level ; Установить прерывание по уровню сигнала else .err " Контроллер прерываний: не правильно задан параметр FL" endif ifidni , elseifidni , elseifidni , ; Установить, что контроллер не ведущий и ParICW1=ParICW1 + ICW1Single ; не подчинённый else .err " Контроллер прерываний: не правильно задан параметр Cascade" endif ifidni , ; Указать, будет ли записано слово ICW4 ParICW1=ParICW1 + ICW1PrsntICW4 elseifnb .err " Контроллер прерываний: не правильно задан параметр IC4" endif endm ;═══════════════════════════════════════════════════════════════════════════ comment~ Слово ICW2 указывает первый номер вектора A0 D7 D6 D5 D4 D3 D2 D1 D0 прерываний, с которого генерируются все остальные. ┌──╥──┬──┬──┬──┬──┬──┬──┬──┐ Этот номер должен быть кратен восьми. Векторы рас- │1 ║T7│T6│T5│T4│T3│X │X │X │ полагаются подряд, начиная с указанного, соот- └──╨──┴──┴──┴──┴──┴──┴──┴──┘ ветствующего IRQ0, и кончая "указанный+7", соот- │ │ │ │ │ └──┴───┴─── Не используется ветствующим вектору IRQ7. └──┴──┴──┴──┴── Старшие разряды вектора прерываний ~ ; Порт, в который должно выводиться слово ICW2 QIRQicw2Master equ 21h ; для ведущего контроллера (Порт QIRQMaster2) QIRQicw2Slave equ 0A1h ; для ведомого контроллера (Порт QIRQSlave2) comment~ Слово ICW3 для ведущего контроллера (Master) Слово ICW3 для ведомого контроллера (Slave) A0 D7 D6 D5 D4 D3 D2 D1 D0 ┌ A0 D7 D6 D5 D4 D3 D2 D1 D0 ┌─────────────────┐ ┌──┬──┬──┬──┬──┬──┬──┬──┬──┐ │1 - к соответствующему ┌──╥──┬──┬──┬──┬──┬───┬───┬───┐ │№ Slave в системе│ │1 ║S7│S6│S5│S4│S3│S2│S1│S0│ │ выходу IRQ подключён │1 ║0 │0 │0 │0 │0 │ID2│ID1│ID0│ │0 1 2 3 4 5 6 7 │ └──┴──┴──┴──┴──┴──┴──┴──┴──┘ │ ведомый контроллер └──╨──┴──┴──┴──┴──┴───┴───┴───┘ │──────────────── │ └──┴──┴──┴──┴──┴──┴──┴────┤0 - вывод контроллера не │ │ └───>│0 1 0 1 0 1 0 1 │ │ подключён к ведомому │ └───────>│0 0 1 1 0 0 1 1 │ │ контроллеру └───────────>│0 0 0 0 1 1 1 1 │ └ └─────────────────┘ Порт, в который должно выводиться слово ICW3:~ QIRQicw3Master equ 21h ; для ведущего контроллера (Порт QIRQMaster2) QIRQicw3Slave equ 0A1h ; для ведомого контроллера (Порт QIRQSlave2) comment~ A0 D7 D6 D5 D4 D3 D2 D1 D0 ┌──╥──┬──┬──┬────┬────┬───┬────┬──┐ ICW4 │1 ║0 │0 │0 │SFNM│BUF │M/S│AEOI│1 │ ┌ └──╨──┴──┴──┴────┴────┴───┴────┴──┘ │1 -- автоматически завершать обработку прерываний ┐│ │ │ └────────┤0 -- оканчивать прерывания по команде 1--- специальный полновложенный режим; ├┘ │ │ └ 0 -- полновложенный режим; │ ┌v ── v────────────────────────┐ ┘ │0 X Нет буферного режима │ │1 0 Буферный режим Slave │ │1 1 Буферный режим Master│ └──────────────────────────────┘ В полновложенном режиме пока установлен бит в ISR, все последующие запросы с тем же или более низким приоритетом не вызывают выработку сигнала INTR для ЦП. При этом возможен следующий случай. Когда ведомый КП получает запрос на прерывание, он выдаёт сигнал на вход IRQ2 ведущего. Ведущий КП подаёт его на вход ЦП и ус- танавливает соответствующий бит в своём ISR. Когда ведомый КП получает запрос на прерывание с более высоким приоритетом, он снова выдаёт запрос на вход IRQ2 в ведущий КП, но в ISR ведущего КП бит, соответствующий IRQ2, уже установлен. Поэтому ведущий КП запрос на прерывание не выдаст. Преодолеть это можно, запрограммировав ве- дущий КП на использование специального полновложенного режима. В специальном полновложенном режиме игнорируются только запросы на прерывание с более низким приоритетом. // Буферный режим -- ? (о нём нет сведений) // В обычном режиме КП после подтверждения прерывания по входу INTA ждёт команду EOI, после которой осу- ществляется сброс одного из битов в ISR, соответствующего подтверждённому прерыванию. Установкой AEOI КП можно настроить на автоматический сброс соответствующего бита ISR после получения сигнала INTA. Заметим, что при этом, запрос на прерывание с меньшим приоритетом может поступить до того, как ЦП обработает запрос на прерыва- ние с б\'ольшим приоритетом. Более того, возможен случай, когда следующий запрос на k-ое прерывание происходит до того как был обработан предыдущий запрос на то же k-ое прерывание. Такой случай называется "сверхвложе- нием".~ ICW4Common equ 00000001b ; Устанавливает биты, характерные для ICW4 ICW4AEOI equ 00000010b ; Автоматическое завершение прерываний ICW4BufSlave equ 00001000b ; Буферный режим Slave ICW4BufMaster equ 00001100b ; Буферный режим Master ICW4SFNM equ 00010000b ; Специальный полновложенный режим. ; Порт, в который должно выводиться слово ICW4 QIRQicw4Master equ 21h ; для ведущего контроллера (Порт QIRQMaster2) QIRQicw4Slave equ 0A1h ; для ведомого контроллера (Порт QIRQSlave2) ;═══════════════════════════════════════════════════════════════════════════ ;~ Макрос формирует слово ICW4, записываемое в константу ParICW4 (машинный код не генерируется). ; ParICW4 -- переменная TASM, в которой возвращается слово ICW4. ; Cascade -- Single, Master или Slave один контроллер, главный контроллер или подчинённый контроллер; ; Buffer -- наличие буфера (Buf или пусто); ; AutoEOI -- автоматическое окончание прерываний (AEOI или пусто); ; SpecFNM -- режим специального вложения (SFNM или пусто) _IRQICW4 macro ParICW4, MSS, Buffer, AutoEOI, SpecFNM ; Задаёт слово ICW4 ParICW4=ICW4Common ifidni , ; Следует ли установить буферный режим? ifidni , ParICW4=ParICW4 + ICW4BufMaster elseifidni , ParICW4=ParICW4 + ICW4BufSlave elseifidni , .err "Контроллер прерываний: буферный режим может быть или в режиме Master, или в режиме Slave" else .err "Контроллер прерываний: не правильно задан параметр Cascade" endif endif ifnb ; Установить автоматическое завершение прерываний? errifdifi , "Неправильно задан параметр AEOI" paricw4=ParICW4 + ICW4AEOI endif ifnb ; Установить специальный полновложенный режим? errifdifi , "Неправильно задан параметр SpecFNM" ParICW4=ParICW4 + ICW4SFNM endif endm ;═══════════════════════════════════════════════════════════════════════════ comment~ Разряд A0 определяется по номеру порта процессора в который производится запись команды. ICW1 Master -- в порт 20h. ICW2, ICW3, ICW4 Master -- в порт 21h Slave -- в порт A0h Slave -- в порт A1h Порядок настройки контроллера. Значения слов при типовой настройке Master Slave ┌────────────────┐ │Вывод слова ICW1│ ICW1=11 ICW1=11 └───────┬────────┘ v ┌────────────────┐ │Вывод слова ICW2│ ICW2=08 ICW2=70 └───────┬────────┘ Да v ┌────── SGNL=1 │ │ Нет │ v │ ┌────────────────┐ │ │Вывод слова ICW3│ ICW3=04 ICW3=2 │ │ (Master/Slave) │ │ └───────┬────────┘ └────────>│ Нет v ┌───────IC4=1 │ │ Да │ v │ ┌────────────────┐ │ │Вывод слова ICW4│ ICW4=01 ICW4=1 │ └───────┬────────┘ При необходимости можно └────────>│ настроить специальный v полновложенный режим ┌────────────────┐ │ Конец │ └────────────────┘ Чтобы изменить одно из ICWn нужно перепрограммировать всю последовательность.~ ;═══════════════════════════════════════════════════════════════════════════ ; Макрос настройки одного контроллера; ; MSS - Определяет является ли контроллер ведущим (=Master) ведомым (=Slave) или используется вообще один (=Single) ; FL - Определяет вырабатывать прерывание по фронту (=Front) или по уровню (=level) ; IRQ0Int - число, кратное 8 (адрес первого вектора прерываний) ; CIIRQ - пусто для Singl, для Master, биты с номерами IRQ, к которым подключены Slave, для Slave №IRQ, к ; которому он подключён. ; SpecFNM - "SFNM" установить специальный полновложенный режим или ; "пусто" не устанавливать специального полновложенного режима ; Buffer - Buf или пусто. ; AutoEOI - "AEOI" установить автоматическое завершение прерываний или "пусто" не устанавливать. InitIRQ macro MSS, FL, IRQ0Int, CIIRQ, Buffer, AutoEOI, SpecFNM local irqw, f ; Загрузка ICW1 ;; ifnb ; Если не нужны буферный режим, ;; _IRQICW1 irqw, FL, , ICW4 ; автоматическое завершение прерываний ;; ifnb ; или специальный полновложенный режим, ;; _IRQICW1 irqw, FL, , ICW4 ; то не нужно и слово ICW4, ;; ifnb ; в противном случае оно необходимо ;; _IRQICW1 irqw, FL, , ICW4 ;; else ;; _IRQICW1 irqw, FL, ;; endif ; Но как показывает моя практика, лучше слово ICW4 всё-таки вводить, т. к. в противном случае ; после настройки контроллера, компьютере может зависать (желающие могут проверить) _IRQICW1 irqw, FL, , ICW4 mov al, irqw out QIRQICW1&MSS, al SPDelay ;─────────────────────── ; Загрузка ICW2 ; Загружает "базовый" номер вектора прерываний IsItReg?b IRQ0Int, f if f EQ NO errif (IRQ0Int and 00000111b) NE 0 "Вектор прерывания должен быть кратен 8" endif mov al, IRQ0Int out QIRQicw2&MSS, al SPDelay ;─────────────────────── ; Загрузка ICW3 ; Если это ведущий контроллер, то установить разряды, ifidni , ; соответствующие выводам IRQ, к которым подключены mov al, CIIRQ ; ведомые контроллеры. out QIRQicw3&MSS, al ; elseifidni , ; Если это ведомый контроллер, то установить номер запроса на прерывание ; №IRQ (к какому выводу главного контроллера), к которому он подключён errif CIIRQ GE 8h "Контроллер прерываний: Контроллер прерываний имеет только 8 линий прерываний (IRQ0-IRQ7)" mov al, CIIRQ out QIRQicw3&MSS, al elseifidni , ; В одиночном режиме слово ICW3 вообще не используется %OUT "Контроллер прерываний: Контроллер в одиночном режиме на ПК не используется." else .err "Контроллер прерываний: MMS должен быть Master, Slave или Single" endif SPDelay ;─────────────────────── ; Загрузка ICW4. Установить дополнительные характеристики режима работы контроллера прерываний, если надо. ;; ifnb ;; _IRQICW4 irqw, , Buffer, AutoEOI, SpecFNM ;; mov al, irqw ;; out QIRQicw4&MSS, al ;; elseifnb ;; _IRQICW4 irqw, , Buffer, AutoEOI, SpecFNM ;; mov al, irqw ;; out QIRQicw4&MSS, al ;; elseifnb ;; _IRQICW4 irqw, , Buffer, AutoEOI, SpecFNM ;; mov al, irqw ;; out QIRQicw4&MSS, al ;; endif _IRQICW4 irqw, MSS, Buffer, AutoEOI, SpecFNM mov al, irqw out QIRQicw4&MSS, al endm ;═══════════════════════════════════════════════════════════════════════════ comment~ Регистр IMR доступен для чтения всегда, ISR и IRR -- только после выдачи соответствующих команд. Теперь рассмотрим рабочие команды (OCW1, OCW2 и OCW3). Команда OCW1 маскирует отдельные запросы на прерывания. Единичные 7 6 5 4 3 2 1 0 значения битов указывают, что поступающие запросы на прерывание с ┌──┬──┬──┬──┬──┬──┬──┬──┐ соответствующими им номерами игнорируются. OCW1│M7│M6│M5│M4│M3│M2│M1│M0│ Порт, в который должно выводиться слово OCW1:~ └──┴──┴──┴──┴──┴──┴──┴──┘ QIRQocw1Master equ 21h ; для ведущего контроллера (Порт QIRQMaster2) QIRQocw1Slave equ 0A1h ; для ведомого контроллера (Порт QIRQSlave2) ;═══════════════════════════════════════════════════════════════════════════ ; Устанавливает, сбрасывает, инвертирует или тестирует один бит регистра маски прерываний контроллера. ; MS - указывает контроллер, к которому ведётся обращение (должно быть master или slave); ; SRCV = S -- установить соответствующий бит маскирования канала прерывания ; C -- инвертировать соответствующий бит маскирования канала прерывания ; R -- сбросить соответствующий бит маскирования канала прерывания ; пусто - проверить соответствующий бит маскирования канала прерывания, ; загрузив его в CF (если бит N установлен, то CF=1). ; N -- номер проверяемого бита. IRQMaskN macro MS, N, SCRV in al, RdIMR&MS ; al - маска битов BT&SCRV Eax, N ifnb out QIRQocw1&MS, al endif endm ;────────────────────────────────────────────────────────── ; Устанавливает, сбрасывает или инвертирует биты регистра маски прерываний контроллера, которые в ; переменной msk имеют единичное значение. ; MS - указывает контроллер, к которому ведётся обращение (должно быть master или slave) ; SRCW = S -- установить соответствующие биты маскирования канала прерывания ; C -- инвертировать соответствующие биты маскирования канала прерывания ; R -- сбросить соответствующие биты маскирования канала прерывания ; msk - маска модифицируемых бит (единичное значение указывает, что бит должен быть изменён). IRQMaskMANY macro MS, msk, SCRV in al, RdIMR&MS ; Читает регистр масок ifnb ifidni , ; Если установить биты OR al, msk elseifidni , ; Если инвертировать биты XOR al, msk elseifidn , ; Если сбросить биты and al, not msk else .err "Странный параметр SRCV при обращении к контроллеру прерываний" endif out QIRQocw1&MS, al endif endm ;────────────────────────────────────────────────────────── ; Загружает регистр масок прерываний новым значением ; MS - указывает контроллер, к которому ведётся обращение (должно быть master или slave) ; msk - новое значение регистра масок. IRQMaskALL macro MS, msk ; Устанавливает все биты указанными значениями mov al, msk ; out QIRQocw1&MS, al ; endm ;═══════════════════════════════════════════════════════════════════════════ comment~ Командное слово OCW2 7 6 5 4 3 2 1 0 ┌──┬──┬───┬──┬──┬──┬──┬──┐ │R │SL│EOI│0 │0 │L2│L1│L0│ └──┴──┴───┴──┴──┴──┴──┴──┘ │ │ │ │ │ │ │ │ v v v v v v v v ┌──┬──┬───┬──┬──┬──┬──┬──┬──────────────────────────────────────────────────────────────┐ │0 │0 │1 │0 │0 │X │X │X │Обычное окончание прерывания │ │0 │1 │1 │0 │0 │L2│L1│L0│Специальное окончание прерывания │ │1 │0 │1 │0 │0 │X │X │X │Обычное окончание прерывания, циклический сдвиг приоритета на │ │ │ │ │ │ │ │ │ │ обслуженное прерывание │ │1 │1 │1 │0 │0 │L2│L1│L0│Специальное окончание прерывания, циклический сдвиг приоритета│ │ │ │ │ │ │ │ │ │ на указанное прерывание │ │1 │0 │0 │0 │ 0│X │X │X │Установка триггера циклического приоритета (Исп. при AEOI=1) │ │0 │0 │0 │0 │ 0│X │X │X │Сброс триггера циклического приоритета (Исп. при AEOI=1) │ │1 │1 │0 │0 │0 │L2│L1│L0│Циклический сдвиг приоритета │ │0 │1 │0 │0 │0 │X │X │X │Нет операций (команда NOP) │ └──┴──┴───┴──┴──┴──┴──┴──┴──────────────────────────────────────────────────────────────┘ R=1 -- управляет операциями, связанными с ротацией приоритетов; SL=1 -- указывает, что команда относится к конкретному прерыванию, а не к последнему, подтверждённому на обслуживание (специальное в смысле заданное); EOI=1 -- окончание прерывания (сброс разряда в ISR); L0-L2 -- номер запроса на прерывание, для которого выполняется команда, используется совместно с SL=1 Изменение уровней приоритетов вступает в силу только по завершении обработки прерывания (после команды EOI, например). Когда уровни приоритетов не изменяются, достаточно обычного EOI, Все возможные варианты расположения когда используются команды ротации приоритетов в обработчике прерыва- уровней приоритетов при ротации. ний, нужно использовать специальную команду EOI, явно указывая номер ┌────────────┬─────────────────┐ завершаемого прерывания. На использование автоматического завершения │ Вход │ Статус уровня │ прерывания можно программировать контроллер только тогда, когда часто- │ микросхемы │ приоритета │ та прерываний не очень велика, иначе может возникнуть ситуация ├────────────┼─────────────────┤ сверхвложения (когда одно и то же прерывание вызывается на столько │ IRQ0 │ 7 6 5 4 3 2 1 0 │ часто, что обработчик не успевает его отработать, при этом оно блоки- │ IRQ1 │ 0 7 6 5 4 3 2 1 │ рует вызов всех остальных, и может возникнуть переполнение стека). │ IRQ2 │ 1 0 7 6 5 4 3 2 │ Если производится ротация приоритетов прерываний, во время обработки │ IRQ3 │ 2 1 0 7 6 5 4 3 │ прерывания, то приоритеты будут только после окончания обработки (вы- │ IRQ4 │ 3 2 1 0 7 6 5 4 │ дачи команды EOI). Т. е. если после ротации приоритетов если, вдруг │ IRQ5 │ 4 3 2 1 0 7 6 5 │ оказался запрос с более высоким приоритетом, чем у обрабатываемого, то │ IRQ6 │ 5 4 3 2 1 0 7 6 │ оно обрабатываться не будет до тех пор, пока текущий обработчик преры- │ IRQ7 │ 6 5 4 3 2 1 0 7 │ ваний не выдаст команду EOI. └────────────┴─────────────────┘~ QeIRQeoi equ 00100000b ; Выполнить EOI QeIRQrot equ 10000000b ; Выполнить циклический сдвиг приоритета (ротацию) QeIRQspec equ 01000000b ; Команду выполнять для указанного запроса на прерывание ; Порт, в который должно выводиться слово OCW2 QIRQocw2Master equ 20h ; для ведущего контроллера (Порт QIRQMaster1) QIRQocw2Slave equ 0A0h ; для ведомого контроллера (Порт QIRQSlave1) ;═══════════════════════════════════════════════════════════════════════════ ; Окончание обработки запроса на прерывание ; MS - master (вместо него можно указать 1) или slave (можно указать 0). ; IRQN - номер канала прерывания, для которого выполняется команда. Необязателен. Если не указывать, то ; подразумевается последнее подтверждённое на обслуживание прерывание. _IRQeoi macro MS:req, IRQN ifb mov al, QeIRQeoi else mov al, QeIRQeoi + QeIRQspec + IRQN endif ifidni , out QIRQocw2Master, al elseifidni , out QIRQocw2Slave, al elseif MS EQ 1 out QIRQocw2Master, al elseif MS EQ 0 out QIRQocw2Slave, al else .err Неправильно задан параметр MS endif endm ;═══════════════════════════════════════════════════════════════════════════ comment~ Команда OCW3 Используется для выдачи различных режимов и команд в 8259A. OCW3 имеет две функции: - Выдаёт состояния прерываний - Управляет маскированием прерываний 7 6 5 4 3 2 1 0 ┌──┬────┬───┬──┬──┬──┬──┬───┐ │X │ESMM│SMM│0 │1 │P │RR│RIS│ └──┴────┴───┴──┴──┴──┴──┴───┘ │ │ │ │ │ ┌────────────────────────────────────v───v┐ │ ┌─v──v─────────────────────┐ │Неактивны 0 X │ │ │0 X Не активны │ │Установка специального маскирования 1 1 │ │ │1 0 Разрешение чтения IRR│ │Сброс специального маскирования 1 0 │ │ │1 1 Разрешение чтения ISR│ └─────────────────────────────────────────┘ │ └──────────────────────────┘ ┌─v────────────────────────┐ │1 Установка режима опроса│ │0 Нет режима опроса │ └──────────────────────────┘ RR=1 Выполняется команда чтения регистра │ESMM=1 Включается или выключается режим RIS=0 читать IRR; RIS=1 читать ISR │ специального маскирования │ SMM=1 - включить; SMM=0 - выключить P -- выдаётся команда опроса Режим опроса необходим, когда устройства имеют общую программу-обработчик прерываний, а также при коли- честве запросов больше 64. Инициатором опроса является команда, посылающая слово OCW3, по которой микропроцес- сор блокирует свой вход INTR и подготавливает цепи в КП (контроллере прерываний), необходимые для опроса. Затем в контроллер передаётся команда чтения порта 20h (для ведущего) или A0h (для ведомого КП), по которой по наиболее приоритетному запросу устанавливается соответствующий разряд ISR и сбрасывается одноимённый разряд IRR) и на шину X выдаётся слово опроса прерываний, структура которого следующая D7 D6 D5 D4 D3 D2 D1 D0 ┌──┬──┬──┬──┬──┬──┬──┬──┐ │I │X │X │X │X │W2│W1│W0│ └──┴──┴──┴──┴──┴──┴──┴──┘ ^ ^ ^ ^ │ └───┴──┴──── Код номера приоритетного прерывания, └ 0 -- Нет запроса ожидающего обслуживания 1 -- Есть запрос По полученной информации программа либо перейдёт на программу-обработчик приоритетного прерывания, либо ликвидирует следы обслуживаемого прерывания командой EOI. При необходимости операция опроса может повторяться до тех пор, пока разряд I (D7) не станет равным нулю.~ OCW3Common equ 00001000b ; Устанавливает биты, характерные для OCW3 OCW3ReadISR equ 00000011b ; Разрешить чтение ISR (регистр обслуживаемых прерываний) OCW3ReadIRR equ 00000010b ; Разрешить чтение IRR (регистр запросов на прерывание) CW3SetAsk equ 00000100b ; Установить режим опроса OCW3SetSpecMsk equ 01100000b ; Установка режима специального маскирования OCW3ResetSpecMsk equ 01000000b ; Сброс режима специального маскирования ; Порт, в который должно выводиться слово OCW3 QIRQocw3Master equ 20h ; для ведущего контроллера (Порт QIRQMaster1) QIRQocw3Slave equ 0A0h ; для ведомого контроллера (Порт QIRQSlave1) ;═══════════════════════════════════════════════════════════════════════════ ;~ Внутренний макрос. Участвует в формировании маски слова ICW3 ; Msk -- входная маска ; Reg -- установить регистр для чтения/записи ; =IRR -- установить регистр запросов на прерывание ; ISR -- установить регистр запросов обслуживаемых прерываний ; пусто -- ни чего не менять в установках регистра чтения записи ; SM =SSM установить специальное маскирование ; RSM сбросить специальное маскирование ; пусто -- ни чего не менять в установках специального маскирования IRQOCW3common macro msk, Reg, SM ifnb ; Нужно установить регистр для чтения/записи? ifidni , msk=msk + OCW3ReadIRR elseifidni , msk=msk + OCW3ReadISR else .err "КП: Reg должен быть IRR или ISR или опущен вовсе" endif endif ;────────────────── ifnb ; Нужно изменять состояние специального маскирования? ifidni , msk=msk + OCW3SetSpecMsk elseifidni , msk=msk + OCW3ResetSpecMsk else .err "КП: SM должен быть SSM или RSM" endif endif endm ;─────────────────────────────────────────────────────────────────────────── ; Устанавливает режим опроса ; MS - master или slave; ; Reg -- регистр, который потом можно будет прочитать (IRR или ISR), можно опустить, тогда не будет меняться ; читаемый регистр; ; SM -- изменить состояние специальной маски (SSM/установить или RSM/сбросить), можно не указывать, тогда ; состояние специального маскирования меняться не будет. IRQSetRA macro MS, Reg, SM local msk msk=OCW3Common + OCW3SetAsk IRQOCW3common msk, Reg, SM mov al, msk out QIRQocw3&MS, al endm ;─────────────────────────────────────────────────────────────────────────── ; Сбрасывает режим опроса, а также может изменить состояние специального ; маскирования и читаемый регистр (IRR или ISR) ; MS - master или slave; ; Reg -- регистр, который потом можно будет прочитать (IRR или ISR), можно опустить, тогда не будет меняться ; читаемый регистр; ; SM -- изменить состояние специальной маски (SSM/установить или RSM/сбросить), можно не указывать, тогда ; состояние специального маскирования меняться не будет. IRQResetRA macro MS, Reg, SM local msk msk=OCW3Common IRQOCW3common msk, Reg, SM mov al, msk out QIRQocw3&MS, al endm ;─────────────────────────────────────────────────────────────────────────── ; Устанавливает режим опроса и читает регистр ; MS - master или slave; ; Reg -- регистр, который потом можно будет прочитать (IRR или ISR), можно опустить, тогда не будет меняться ; читаемый регистр; ; IntFNOCHANGE -- Любое значение. Указывает, что не нужно сохранять регистр флагов IRQSRARead macro MS, Reg, IntFNOCHANGE ifb pushf cli endif IRQSetRA MS, Reg in al, Rd&Reg&MS ifb POPF endif endm ; Т. к. в процессе чтения регистра может быть выработано прерывание, которое, в свою очередь, может попытаться ; прочитать другой регистр контроллера, что в свою очередь может привести к чтению первым обработчиком ; не правильного регистра, то лучше на время выполнения операции чтения запретить прерывания. ;─────────────────────────────────────────────────────────────────────────── ; Сбрасывает режим опроса и читает регистр ; MS - master или slave; ; Reg -- регистр, который потом можно будет прочитать (IRR или ISR), можно опустить, тогда не будет меняться ; читаемый регистр; ; IntFNOCHANGE -- Любое значение. Указывает, что не нужно сохранять регистр флагов IRQRRARead macro MS, Reg, IntFNOCHANGE ifb pushf cli endif IRQResetRA MS, Reg in al, Rd&Reg&MS ifb POPF endif endm ;═══════════════════════════════════════════════════════════════════════════ comment~ Если запрос на прерывание снимается со входа до того, как он будет разрешён в IMR, то прерывание не выра- батывается. Возможны следующие режимы работы контроллера - полновложенный (игнорируются все запросы на прерывание с меньшим или равным приоритетом) - специальный режим полного вложения (игнорируются все запросы на прерывание с меньшим приоритетом, это, например, может использоваться в тех случаях, когда нужно обеспечить режим полного вложения для устройств, подключённых к ведомому контроллеру, для чего запрограммировать нужно только ведущий контроллер). - когда требуется обеспечить возможность обработки прерываний с приоритетом неравным текущему, можно ис- пользовать режим специального маскирования. Последовательность действий при использовании специального маскирования начало обработки прерывания │ v ┌───────────────┐ │ STI │ разрешить прерывания └───────┬───────┘ │ Разрешены прерывания с более высоким приоритетом v ┌────────────────────────────────────────────┐ │ Установка разряда IMR, соответствующего │ │ обрабатываемому прерыванию. │ └───────┬────────────────────────────────────┘ v ┌───────────────────┐ │ Установка SMM │ Установка режима специального маскирования └───────┬───────────┘ │ Разрешены прерывания с приоритетом, отличным от обрабатываемого. v . . . │ v ┌───────────────────┐ │ Сброс SMM │ Сброс режима специального маскирования └───────┬───────────┘ v ┌──────────────────────────────────┐ │ Сброс разряда IMR, соответству- │ │ ющего обрабатываемому прерыванию.│ └───────┬──────────────────────────┘ │ Запрещены прерывания с приоритетом, ниже или равным обрабатываемому. v . . . │ v ┌───────────────────┐ │ EOI │ │ IRET │ └───────────────────┘ При обработке прерываний от подчинённого контроллера необходимо выработать подтверждения для ведущего и ведомого контроллеров. Если при этом используется специальные режим полного вложения, то после посылки EOI в ведомый контроллер необходимо прочитать ISR и проверить все ли биты в нём сброшены (определить обслужены ли все прерывания), если -- да, то послать EOI в ведущий контроллер и выйти, если нет -- просто выйти.~ ;─────────────────────────────────────────────────────────────────────────────── ; Окончание обработки прерывания в специальном полновложенном режиме работы. ; Требуется только для обработки на подчинённых контроллерах ; IRQN -- необязательный параметр, указывает номер завершаемого прерывания. Если не указывать, то будет ; завершено последнее подтверждённое на обслуживание _IRQeoiSFNM macro IRQN local ex _IRQeoi Slave, IRQN ; Сбросить обработку текущего прерывания в Slave IRQRRARead Slave, ISR ; Проверить не обрабатываются ли ещё какие-нибудь or al, al ; прерывания Slave jnz ex _IRQeoi Master, IRQReq_IRQSlave ; Если нет, то сбросить Master, иначе выйти ex: endm ;******************************************************************** ;* Макросы высокого уровня * ;******************************************************************** comment~ Список устройств, подключённых к контроллерам прерываний, имена устройств указываются в макросах окончания обработки прерывания (IRQ_EOI), маскирования и размаскирования прерываний (IRQ_Des и IRQ_En) Timer -- таймер, канал 0 Parallel1 -- параллельный порт 1 KBD -- клавиатура (выходной буфер полон) RTC -- часы реального времени IRQSlave -- каскад контроллера прерываний 2 PS2Mouse -- мышь PS/2 * Serial2 -- последовательный порт 2 Math -- исключение математического сопроцессора Serial1 -- последовательный порт 1 HDDIDE1 -- контроллер жёстких дисков 1 Parallel2 -- параллельный порт 2 HDDIDE2 -- контроллер жёстких дисков 2 * FDD -- контроллер накопителя на гибких дисках * -- устройства, не присутствовавшие в 286, 386, 486 компьютерах. Примечание: .IRQSpecialFNM -- переменная указывает, используется ли специальный полновложенный режим. Служит для указания генерируемого кода для обработки окончания прерывания, полученного от ведомого контроллера. Переменная всту- пает в силу после макроса настройки контроллера InitATIRQ. Если настройка контроллера не выполняется, то её можно установить явно. Если .IRQSpecialFNM не определена то IRQ_EOI для подчинённого контроллера генерирует- ся так, если бы был настроен специальный режим полного вложения.~ ;─────────────────────────────────────────────────────────────────────────── ; Стандартная инициализация контроллеров прерываний. ; SpecFNM -- указывает, следует ли использовать специальный полновложенный режим ; IRQ0Int1, IRQ0Int2 -- номера прерываний первого и второго контроллера ; Макрос формирует переменную IRQSpecialFNM, указывающую, следует ли использовать в последующих командах ; IRQ_EOI при обслуживании прерываний от ведомого контроллера последовательность команд, написанную для ; специального полновложенного режима или нет. ; Если векторы прерываний задаются не константами, а регистрами, то правильность задаваемых номеров не выпол- ; няется. IRQ_Ini macro IRQ0Int1, IRQ0Int2, SpecFNM InitIRQ Master, Front, IRQ0Int1, 00000100b, , , SpecFNM InitIRQ Slave, Front, IRQ0Int2, 2 ifb .IRQSpecialFNM=No else .IRQSpecialFNM=Yes endif endm ;─────────────────────────────────────────────────────────────────────────── ; Стандартное завершение прерывания ; IRQName -- одно из имён устройств, помещённое в начале файла. ; В этом макросе неявно используется переменная IRQSpecialFNM. IRQ_EOI macro IRQName if IRQReqC_&IRQName EQ No ifdef .IRQSpecialFNM if .IRQSpecialFNM EQ No _IRQeoi IRQReqC_&IRQName, IRQReq_&IRQName else _IRQeoiSFNM IRQReq_&IRQName endif else _IRQeoiSFNM IRQReq_&IRQName endif else _IRQeoi IRQReqC_&IRQName, IRQReq_&IRQName endif endm ;─────────────────────────────────────────────────────────────────────────── ; Маскировать (IRQ_Des) и размаскировать (IRQ_En) прерывание ; IRQName -- одно из имён устройств, помещённое в начале файла. IRQ_Des macro IRQName if IRQReqC_&IRQName EQ Yes IRQMaskN Master, IRQReq_&IRQName, S else IRQMaskN Slave, IRQReq_&IRQName, S endif endm IRQ_En macro IRQName if IRQReqC_&IRQName EQ Yes IRQMaskN Master, IRQReq_&IRQName, R else IRQMaskN Slave, IRQReq_&IRQName, R endif endm ; Конец файла IRQ.DEF ;╗╗n*.MAC8Б