/* * irq.h — пользовательский обработчик кадрового прерывания (IM 2). * * Sprinter шлёт вектор 0xFF от трёх источников: кадр (50 Гц), * клавиатура (бит 0 порта 0x19), CBL/COVOX (бит 7 порта 0xFE). * irq_install() перехватывает IM2-таблицу и зовёт handler ТОЛЬКО на * кадровых прерываниях; после него (и на всех прочих источниках) * управление всегда передаётся штатному обработчику DSS — клавиатура, * SYSTIME и курсор мыши продолжают работать. irq_remove() * восстанавливает всё как было (и вызывается атоматически из exit). * * ТРЕБОВАНИЕ ПАМЯТИ: код и данные программы должны быть в W2 * (0x8000-0xBFFF) — режимы tiny и big. В small/huge (CODE в W1) * irq_install вернёт -1/EINVAL: во время прерывания W1 может быть * перемаплен. Дизайн: docs/im2_isr_design.md. * * Правила для handler'а (вызывается ~50 раз/с, все регистры * сохраняются снаружи): * МОЖНО: volatile-глобалы, арифметика, короткая работа (<1 мс); * НЕЛЬЗЯ: ESTEX/BIOS-вызовы (printf/malloc/файлы), gfx_* и любой * своп W1/W3, акселератор, banked-функции, longjmp наружу. */ #ifndef IRQ_H #define IRQ_H typedef void (*isr_t)(void); /* Установить обработчик кадрового прерывания. * 0 — OK; -1 + errno: EBUSY (уже установлен), EINVAL (код/данные * не в W2 — неподходящий memory mode). */ int irq_install(isr_t handler); /* Снять обработчик и вернуть IM2-таблицу DSS. Безопасно звать * повторно; вызывается автоматически при exit(). */ void irq_remove(void); /* Скобки для доступа main-кода к данным, разделяемым с ISR. */ #define IRQ_DISABLE() __asm__("di") #define IRQ_ENABLE() __asm__("ei") #endif