/*
 * Copyright (C) 2022 EXOLIGENT (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 "gw.h"

#define MAX_FA_BOARD 16

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(fip, info, "   index        : %d\n", dev_infos->index);
    _print(fip, info, "   fsn          : 0x%" PRIx64 "\n", dev_infos->fsn);
    _print(fip, info, "   vid          : 0x%04x\n", dev_infos->vid);
    _print(fip, info, "   did          : 0x%04x\n", dev_infos->did);
    _print(fip, info, "   ssvid        : 0x%04x\n", dev_infos->ssvid);
    _print(fip, info, "   ssdid        : 0x%04x\n", dev_infos->ssdid);
    _print(fip, info, "   bar_cnt      : %d\n", dev_infos->bar_cnt);
    for (i = 0; i < dev_infos->bar_cnt; ++i) {
        _print(fip, info, "   bar_bsz[%d]   : %d\n", i, dev_infos->bar_bsz[i]);
        _print(fip, info, "   bar_base[%d]  : 0x%08x\n", i, dev_infos->bar_base[i]);
    }
    _print(fip, info, "   irq_number   : %d\n", dev_infos->irq_number);
    _print(fip, 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(fip, err, "cannot list devices: %s\n",
            pwrfip_strerror(errno));
        return;
    }
    _print(fip, info, "boards detected: %d\n", dev_cnt);
    /* print infos for each boards */
    for (i = 0; i < dev_cnt; ++i) {
        _print(fip, info, "** board %d:\n", i + 1);
        dev_info_print(&dev_infos[i]);
    }
}

int dev_close(struct gateway *gw)
{
    return pwrfip_device_close(gw->fip.dev);
}

int dev_open(struct gateway *gw)
{
    struct pwrfip_dev_infos infos;

    if (gw->fip.dev_idx < 1) {
        errno = EINVAL;
        return -1;
    }

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

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