/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "astlpc.c"

#ifdef pr_fmt
#undef pr_fmt
#define pr_fmt(x) "test: " x
#endif

#include "libmctp-astlpc.h"
#include "libmctp-log.h"
#include "container_of.h"

#ifdef NDEBUG
#undef NDEBUG
#endif

#define RX_BUFFER_DATA	0x100 + 4 + 4

#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct mctp_binding_astlpc_mmio {
	struct mctp_binding_astlpc astlpc;
	bool bmc;

	uint8_t (*kcs)[2];

	size_t lpc_size;
	uint8_t *lpc;
};

#define binding_to_mmio(b) \
	container_of(b, struct mctp_binding_astlpc_mmio, astlpc)

static int mctp_astlpc_mmio_kcs_read(void *data,
				     enum mctp_binding_astlpc_kcs_reg reg,
				     uint8_t *val)
{
	struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);

	*val = (*mmio->kcs)[reg];

	mctp_prdebug("%s: 0x%hhx from %s", __func__, *val, reg ? "status" : "data");

	if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
		uint8_t flag = mmio->bmc ? KCS_STATUS_IBF : KCS_STATUS_OBF;
		(*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] &= ~flag;
	}

	return 0;
}

static int mctp_astlpc_mmio_kcs_write(void *data,
				      enum mctp_binding_astlpc_kcs_reg reg,
				      uint8_t val)
{
	struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
	uint8_t *regp;

	assert(reg == MCTP_ASTLPC_KCS_REG_DATA ||
	       reg == MCTP_ASTLPC_KCS_REG_STATUS);

	if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
		uint8_t flag = mmio->bmc ? KCS_STATUS_OBF : KCS_STATUS_IBF;
		(*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] |= flag;
	}

	regp = &(*mmio->kcs)[reg];
	if (reg == MCTP_ASTLPC_KCS_REG_STATUS)
		*regp = (val & ~0xbU) | (val & *regp & 1);
	else
		*regp = val;

	mctp_prdebug("%s: 0x%hhx to %s", __func__, val, reg ? "status" : "data");

	return 0;
}
int mctp_astlpc_mmio_lpc_read(void *data, void *buf, long offset, size_t len)
{
	struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);

	mctp_prdebug("%s: %zu bytes from 0x%lx", __func__, len, offset);

	assert(offset >= 0L);
	assert(offset + len < mmio->lpc_size);

	memcpy(buf, mmio->lpc + offset, len);

	return 0;
}

int mctp_astlpc_mmio_lpc_write(void *data, void *buf, long offset, size_t len)
{
	struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);

	mctp_prdebug("%s: %zu bytes to 0x%lx", __func__, len, offset);

	assert(offset >= 0L);
	assert(offset + len < mmio->lpc_size);

	memcpy(mmio->lpc + offset, buf, len);

	return 0;
}

#define __unused __attribute__((unused))

static void rx_message(uint8_t eid __unused, void *data __unused, void *msg,
		       size_t len)
{
	uint8_t type;

	type = *(uint8_t *)msg;

	mctp_prdebug("MCTP message received: len %zd, type %d",
			len, type);
}

static const struct mctp_binding_astlpc_ops mctp_binding_astlpc_mmio_ops = {
	.kcs_read = mctp_astlpc_mmio_kcs_read,
	.kcs_write = mctp_astlpc_mmio_kcs_write,
	.lpc_read = mctp_astlpc_mmio_lpc_read,
	.lpc_write = mctp_astlpc_mmio_lpc_write,
};

struct astlpc_endpoint {
	struct mctp_binding_astlpc_mmio mmio;
	struct mctp_binding_astlpc *astlpc;
	struct mctp *mctp;
};

static void endpoint_init(struct astlpc_endpoint *ep, mctp_eid_t eid,
			  uint8_t mode, uint8_t (*kcs)[2], void *lpc_mem,
			  size_t lpc_size)
{
	/*
	 * Configure the direction of the KCS interface so we know whether to
	 * set or clear IBF or OBF on writes or reads.
	 */
	ep->mmio.bmc = (mode == MCTP_BINDING_ASTLPC_MODE_BMC);

	ep->mctp = mctp_init();
	assert(ep->mctp);

	mctp_set_rx_all(ep->mctp, rx_message, NULL);

	/* Inject KCS registers */
	ep->mmio.kcs = kcs;

	/* Inject the heap allocation as the LPC mapping */
	ep->mmio.lpc_size = lpc_size;
	ep->mmio.lpc = lpc_mem;

	/* Initialise the binding */
	ep->astlpc = mctp_astlpc_init(mode, MCTP_BTU, NULL,
				      &mctp_binding_astlpc_mmio_ops, &ep->mmio);

	mctp_register_bus(ep->mctp, &ep->astlpc->binding, eid);
}

static void endpoint_destroy(struct astlpc_endpoint *ep)
{
	mctp_astlpc_destroy(ep->astlpc);
	mctp_destroy(ep->mctp);
}

int main(void)
{
	uint8_t msg[2 * MCTP_BTU];
	struct astlpc_endpoint bmc, host;
	size_t lpc_size;
	uint8_t kcs[2] = { 0 };
	void *lpc_mem;
	int rc;

	/* Test harness initialisation */

	memset(&msg[0], 0x5a, MCTP_BTU);
	memset(&msg[MCTP_BTU], 0xa5, MCTP_BTU);

	lpc_size = 1 * 1024 * 1024;
	lpc_mem = calloc(1, lpc_size);
	assert(lpc_mem);

	mctp_set_log_stdio(MCTP_LOG_DEBUG);

	/* BMC initialisation */
	endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs, lpc_mem,
		      lpc_size);

	/* Verify the BMC binding was initialised */
	assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_BMC_READY);

	/* Host initialisation */
	endpoint_init(&host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &kcs, lpc_mem,
		      lpc_size);

	/* Host sends channel init command */
	assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
	assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x00);

	/* BMC receives host channel init request */
	mctp_astlpc_poll(bmc.astlpc);

	/* BMC sends init response */
	assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
	assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
	assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0xff);

	/* Host dequeues data */
	mctp_astlpc_poll(host.astlpc);

	/* BMC sends a message */
	rc = mctp_message_tx(bmc.mctp, 9, msg, sizeof(msg));
	assert(rc == 0);
	assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
	assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);

	/* Verify it's the packet we expect */
	assert(!memcmp(lpc_mem + RX_BUFFER_DATA, &msg[0], MCTP_BTU));

	/* Host receives a packet */
	mctp_astlpc_poll(host.astlpc);

	/* Host returns Rx area ownership to BMC */
	assert(!(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF));
	assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x02);
	assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);

	/* BMC dequeues ownership hand-over and sends the queued packet */
	rc = mctp_astlpc_poll(bmc.astlpc);
	assert(rc == 0);

	/* Host receives a message */
	assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
	assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);

	/* Verify it's the packet we expect */
	assert(!memcmp(lpc_mem + RX_BUFFER_DATA, &msg[MCTP_BTU], MCTP_BTU));

	endpoint_destroy(&bmc);
	endpoint_destroy(&host);
	free(lpc_mem);

	return 0;
}
