/*
 * Connection Management Procedures (IEC 61883-1) helper functions
 *
 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
 * Licensed under the terms of the GNU General Public License, version 2.
 */

#include <linux/device.h>
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/module.h>
#include <linux/sched.h>
#include "lib.h"
#include "iso-resources.h"
#include "cmp.h"

#define IMPR_SPEED_MASK		0xc0000000
#define IMPR_SPEED_SHIFT	30
#define IMPR_XSPEED_MASK	0x00000060
#define IMPR_XSPEED_SHIFT	5
#define IMPR_PLUGS_MASK		0x0000001f

#define IPCR_ONLINE		0x80000000
#define IPCR_BCAST_CONN		0x40000000
#define IPCR_P2P_CONN_MASK	0x3f000000
#define IPCR_P2P_CONN_SHIFT	24
#define IPCR_CHANNEL_MASK	0x003f0000
#define IPCR_CHANNEL_SHIFT	16

enum bus_reset_handling {
	ABORT_ON_BUS_RESET,
	SUCCEED_ON_BUS_RESET,
};

static __printf(2, 3)
void cmp_error(struct cmp_connection *c, const char *fmt, ...)
{
	va_list va;

	va_start(va, fmt);
	dev_err(&c->resources.unit->device, "%cPCR%u: %pV",
		'i', c->pcr_index, &(struct va_format){ fmt, &va });
	va_end(va);
}

static int pcr_modify(struct cmp_connection *c,
		      __be32 (*modify)(struct cmp_connection *c, __be32 old),
		      int (*check)(struct cmp_connection *c, __be32 pcr),
		      enum bus_reset_handling bus_reset_handling)
{
	__be32 old_arg, buffer[2];
	int err;

	buffer[0] = c->last_pcr_value;
	for (;;) {
		old_arg = buffer[0];
		buffer[1] = modify(c, buffer[0]);

		err = snd_fw_transaction(
				c->resources.unit, TCODE_LOCK_COMPARE_SWAP,
				CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index),
				buffer, 8,
				FW_FIXED_GENERATION | c->resources.generation);

		if (err < 0) {
			if (err == -EAGAIN &&
			    bus_reset_handling == SUCCEED_ON_BUS_RESET)
				err = 0;
			return err;
		}

		if (buffer[0] == old_arg) /* success? */
			break;

		if (check) {
			err = check(c, buffer[0]);
			if (err < 0)
				return err;
		}
	}
	c->last_pcr_value = buffer[1];

	return 0;
}


/**
 * cmp_connection_init - initializes a connection manager
 * @c: the connection manager to initialize
 * @unit: a unit of the target device
 * @ipcr_index: the index of the iPCR on the target device
 */
int cmp_connection_init(struct cmp_connection *c,
			struct fw_unit *unit,
			unsigned int ipcr_index)
{
	__be32 impr_be;
	u32 impr;
	int err;

	err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
				 CSR_REGISTER_BASE + CSR_IMPR,
				 &impr_be, 4, 0);
	if (err < 0)
		return err;
	impr = be32_to_cpu(impr_be);

	if (ipcr_index >= (impr & IMPR_PLUGS_MASK))
		return -EINVAL;

	err = fw_iso_resources_init(&c->resources, unit);
	if (err < 0)
		return err;

	c->connected = false;
	mutex_init(&c->mutex);
	c->last_pcr_value = cpu_to_be32(0x80000000);
	c->pcr_index = ipcr_index;
	c->max_speed = (impr & IMPR_SPEED_MASK) >> IMPR_SPEED_SHIFT;
	if (c->max_speed == SCODE_BETA)
		c->max_speed += (impr & IMPR_XSPEED_MASK) >> IMPR_XSPEED_SHIFT;

	return 0;
}
EXPORT_SYMBOL(cmp_connection_init);

/**
 * cmp_connection_destroy - free connection manager resources
 * @c: the connection manager
 */
void cmp_connection_destroy(struct cmp_connection *c)
{
	WARN_ON(c->connected);
	mutex_destroy(&c->mutex);
	fw_iso_resources_destroy(&c->resources);
}
EXPORT_SYMBOL(cmp_connection_destroy);


static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr)
{
	ipcr &= ~cpu_to_be32(IPCR_BCAST_CONN |
			     IPCR_P2P_CONN_MASK |
			     IPCR_CHANNEL_MASK);
	ipcr |= cpu_to_be32(1 << IPCR_P2P_CONN_SHIFT);
	ipcr |= cpu_to_be32(c->resources.channel << IPCR_CHANNEL_SHIFT);

	return ipcr;
}

static int ipcr_set_check(struct cmp_connection *c, __be32 ipcr)
{
	if (ipcr & cpu_to_be32(IPCR_BCAST_CONN |
			       IPCR_P2P_CONN_MASK)) {
		cmp_error(c, "plug is already in use\n");
		return -EBUSY;
	}
	if (!(ipcr & cpu_to_be32(IPCR_ONLINE))) {
		cmp_error(c, "plug is not on-line\n");
		return -ECONNREFUSED;
	}

	return 0;
}

/**
 * cmp_connection_establish - establish a connection to the target
 * @c: the connection manager
 * @max_payload_bytes: the amount of data (including CIP headers) per packet
 *
 * This function establishes a point-to-point connection from the local
 * computer to the target by allocating isochronous resources (channel and
 * bandwidth) and setting the target's input plug control register.  When this
 * function succeeds, the caller is responsible for starting transmitting
 * packets.
 */
int cmp_connection_establish(struct cmp_connection *c,
			     unsigned int max_payload_bytes)
{
	int err;

	if (WARN_ON(c->connected))
		return -EISCONN;

	c->speed = min(c->max_speed,
		       fw_parent_device(c->resources.unit)->max_speed);

	mutex_lock(&c->mutex);

retry_after_bus_reset:
	err = fw_iso_resources_allocate(&c->resources,
					max_payload_bytes, c->speed);
	if (err < 0)
		goto err_mutex;

	err = pcr_modify(c, ipcr_set_modify, ipcr_set_check,
			 ABORT_ON_BUS_RESET);
	if (err == -EAGAIN) {
		fw_iso_resources_free(&c->resources);
		goto retry_after_bus_reset;
	}
	if (err < 0)
		goto err_resources;

	c->connected = true;

	mutex_unlock(&c->mutex);

	return 0;

err_resources:
	fw_iso_resources_free(&c->resources);
err_mutex:
	mutex_unlock(&c->mutex);

	return err;
}
EXPORT_SYMBOL(cmp_connection_establish);

/**
 * cmp_connection_update - update the connection after a bus reset
 * @c: the connection manager
 *
 * This function must be called from the driver's .update handler to reestablish
 * any connection that might have been active.
 *
 * Returns zero on success, or a negative error code.  On an error, the
 * connection is broken and the caller must stop transmitting iso packets.
 */
int cmp_connection_update(struct cmp_connection *c)
{
	int err;

	mutex_lock(&c->mutex);

	if (!c->connected) {
		mutex_unlock(&c->mutex);
		return 0;
	}

	err = fw_iso_resources_update(&c->resources);
	if (err < 0)
		goto err_unconnect;

	err = pcr_modify(c, ipcr_set_modify, ipcr_set_check,
			 SUCCEED_ON_BUS_RESET);
	if (err < 0)
		goto err_resources;

	mutex_unlock(&c->mutex);

	return 0;

err_resources:
	fw_iso_resources_free(&c->resources);
err_unconnect:
	c->connected = false;
	mutex_unlock(&c->mutex);

	return err;
}
EXPORT_SYMBOL(cmp_connection_update);


static __be32 ipcr_break_modify(struct cmp_connection *c, __be32 ipcr)
{
	return ipcr & ~cpu_to_be32(IPCR_BCAST_CONN | IPCR_P2P_CONN_MASK);
}

/**
 * cmp_connection_break - break the connection to the target
 * @c: the connection manager
 *
 * This function deactives the connection in the target's input plug control
 * register, and frees the isochronous resources of the connection.  Before
 * calling this function, the caller should cease transmitting packets.
 */
void cmp_connection_break(struct cmp_connection *c)
{
	int err;

	mutex_lock(&c->mutex);

	if (!c->connected) {
		mutex_unlock(&c->mutex);
		return;
	}

	err = pcr_modify(c, ipcr_break_modify, NULL, SUCCEED_ON_BUS_RESET);
	if (err < 0)
		cmp_error(c, "plug is still connected\n");

	fw_iso_resources_free(&c->resources);

	c->connected = false;

	mutex_unlock(&c->mutex);
}
EXPORT_SYMBOL(cmp_connection_break);
