/*
 * irq_chain_add — добавить обработчик кадрового прерывания в цепочку.
 * Возврат 0 / -1+errno: EINVAL (handler==NULL, или данные не в W2 —
 * из _irq_table_ref), ENOMEM (все IRQ_CHAIN_MAX слотов заняты).
 *
 * Первый слот захватывает IM2-таблицу (_irq_table_ref).  Порядок вызова
 * хендлеров = порядок индексов; после remove/add взаимный порядок НЕ
 * гарантирован — хендлеры обязаны быть независимы (см. irq.h).
 */

#include <errno.h>
#include "_irq.h"

int irq_chain_add(isr_t handler)
{
    if (!handler) { errno = EINVAL; return -1; }

    uint8_t i;
    for (i = 0; i < IRQ_CHAIN_MAX; i++)
        if (!_irq_chain[i]) break;
    if (i == IRQ_CHAIN_MAX) { errno = ENOMEM; return -1; }

    /* Первый обработчик — захватить таблицу и включить IM2.  Делаем ДО
     * записи слота: при неудаче (EINVAL в small) состояние не тронуто.
     * Пока слот не выставлен, chain_n==0 → трамплин на кадре просто
     * чейнит к DSS. */
    if (_irq_chain_n == 0)
        if (_irq_table_ref() != 0)
            return -1;

    IRQ_DISABLE();
    _irq_chain[i] = handler;
    _irq_chain_n++;
    IRQ_ENABLE();
    return 0;
}
