/*
 * All Rights Reserved (C) 2021-2025
 * Exoligent SARL (Colombes, France)
 * Website: www.exoligent.com
 * Author : Maxime Coroyer <maxime.coroyer@exoligent.com>
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>     // memset()
#include <stdint.h>     // uint8_t, ...
#include <fcntl.h>      // open()
#include <unistd.h>     // close()

#include "common.h"

void dev_info_print(struct pwrfip_dev_infos *dev_infos)
{
    int i;
    struct pwrfip_version ver;

    if (!dev_infos)
        return;

    ver.raw = dev_infos->drv_version;
    _print(app, info, "   index        : %d\n", dev_infos->index);
    _print(app, info, "   fsn          : 0x%" PRIx64 "\n", dev_infos->fsn);
    _print(app, info, "   vid          : 0x%04x\n", dev_infos->vid);
    _print(app, info, "   did          : 0x%04x\n", dev_infos->did);
    _print(app, info, "   ssvid        : 0x%04x\n", dev_infos->ssvid);
    _print(app, info, "   ssdid        : 0x%04x\n", dev_infos->ssdid);
    _print(app, info, "   bar_cnt      : %d\n", dev_infos->bar_cnt);
    for (i = 0; i < dev_infos->bar_cnt; ++i) {
        _print(app, info, "   bar_bsz[%d]   : %d\n", i, dev_infos->bar_bsz[i]);
        _print(app, info, "   bar_base[%d]  : 0x%08x\n", i, dev_infos->bar_base[i]);
    }
    _print(app, info, "   irq_number   : %d\n", dev_infos->irq_number);
    _print(app, info, "   drv_version  : %d.%d.%d\n",
        ver.info.major, ver.info.minor, ver.info.patch);
}

void dev_show_all()
{
    int dev_cnt, i;
    struct pwrfip_dev_infos dev_infos[MAX_FA_BOARD];

    memset(&dev_infos, 0, MAX_FA_BOARD * sizeof(struct pwrfip_dev_infos));
    if (pwrfip_device_list_get(&dev_infos[0], &dev_cnt)) {
        _print(app, err, "cannot list devices: %s\n",
            pwrfip_strerror(errno));
        return;
    }
    _print(app, info, "boards detected: %d\n", dev_cnt);
    /* print infos for each boards */
    for (i = 0; i < dev_cnt; ++i) {
        _print(app, info, "** board %d:\n", i + 1);
        dev_info_print(&dev_infos[i]);
    }
}

int dev_open(int dev_idx, struct tst_session *sess)
{
    struct pwrfip_dev_infos infos;

    if (dev_idx < 1) {
        errno = EINVAL;
        return -1;
    }

    /* open device */
    sess->dev = pwrfip_device_open(dev_idx);
    if (!sess->dev) {
        _print(app, err, "cannot open device: %s\n",
            pwrfip_strerror(errno));
        return -1;
    }
    // /* reset device */
    // if (pwrfip_device_reset(sess->dev) < 0) {
    //     _print(app, err, "cannot reset device: %s\n",
    //         pwrfip_strerror(errno));
    //     goto fail1;
    // }
    memset(&infos, 0, sizeof(struct pwrfip_dev_infos));
    if (pwrfip_device_infos_get(sess->dev, &infos)) {
        _print(app, err, "cannot retrieve device infos: %s\n",
            pwrfip_strerror(errno));
        goto fail1;
    }
    _print(app, info, "[fip] device info\n");
    dev_info_print(&infos);
    return 0;

fail1:
    dev_close(sess);
    return -1;
}

int dev_close(struct tst_session *sess)
{
    return pwrfip_device_close(sess->dev);
}