/*
 * wnix, a Unix-like operating system for WebAssembly applications.
 * Copyright (C) 2025  Xavier Del Campo Romero
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#include <drv/ps1/rcnt.h>
#include <drv/ps1/rcnt/regs.h>
#include <drv/ps1/event.h>
#include <drv/ps1/irq.h>
#include <drv/ps1/bios.h>
#include <stddef.h>
#include <stdint.h>

int drv_ps1_rcnt_init(const enum drv_ps1_rcnt rcnt, const uint16_t target,
    const union drv_ps1_rcnt_cfg *const cfg, int (*const f)(void))
{
    int class;

    EnterCriticalSection();
    RCNT_TARGET(rcnt)->value = target;
    *RCNT_MODE(rcnt) = *cfg;

    switch (rcnt)
    {
        case DRV_PS1_RCNT0:
            I_MASK->bits.tmr0 = 1;
            class = CLASS_RTC0;
            break;
        case DRV_PS1_RCNT1:
            I_MASK->bits.tmr1 = 1;
            class = CLASS_RTC1;
            break;
        case DRV_PS1_RCNT2:
            I_MASK->bits.tmr2 = 1;
            class = CLASS_RTC2;
            break;
    }

    ExitCriticalSection();

    const int event = drv_ps1_event_open(class, SPEC_INTERRUPTED,
        MODE_EXECUTE, f);

    if (event == -1)
        return -1;

    drv_ps1_event_enable(event);
    return 0;
}
