/*
 * 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/sio/ops.h>
#include <drv/ps1/sio/regs.h>
#include <drv/ps1/sio/routines.h>
#include <drv/ps1/sio/types.h>
#include <drv/ps1/irq.h>
#include <drv/ps1/bios.h>
#include <drv/event.h>
#include <kprintf.h>
#include <sys/types.h>

static int read_fifo(char *buf, size_t n)
{
    int ret = 0;
    struct drv_ps1_sio *const s = &drv_ps1_sio;
    struct sio_fifo *const f = &s->rx;

    I_MASK->bits.sio = 0;
    SIO_CTRL->bits.rts = 0;

    while (n)
    {
        if (f->pend == f->proc)
            break;

        size_t m = f->proc + 1;

        if (m >= sizeof f->buf)
            m = 0;

        *buf++ = f->buf[f->proc = m];
        n--;
        ret++;
    }

    SIO_CTRL->bits.rts = 1;
    I_MASK->bits.sio = 1;
    return ret;
}

int drv_ps1_sio_read_nb(struct drv_port *const p, void *const buf,
    const size_t n)
{
    return read_fifo(buf, n);
}
