/*
 * Copyright (C) 2012 CERN (www.cern.ch)
 * Author: Alessandro Rubini <rubini@gnudd.com>
 *
 * Released according to the GNU GPL, version 2 or any later version.
 *
 * This work is part of the White Rabbit project, a research effort led
 * by CERN, the European Institute for Nuclear Research.
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/fmc.h>

static int fmc_check_version(unsigned long version, const char *name)
{
	if (__FMC_MAJOR(version) != FMC_MAJOR) {
		pr_err("%s: \"%s\" has wrong major (has %li, expected %i)\n",
		       __func__, name, __FMC_MAJOR(version), FMC_MAJOR);
		return -EINVAL;
	}

	if (__FMC_MINOR(version) != FMC_MINOR)
		pr_info("%s: \"%s\" has wrong minor (has %li, expected %i)\n",
		       __func__, name, __FMC_MINOR(version), FMC_MINOR);
	return 0;
}

static int fmc_uevent(struct device *dev, struct kobj_uevent_env *env)
{
	/* struct fmc_device *fdev = to_fmc_device(dev); */

	/* FIXME: The MODALIAS */
	add_uevent_var(env, "MODALIAS=%s", "fmc");
	return 0;
}

static int fmc_probe(struct device *dev)
{
	struct fmc_driver *fdrv = to_fmc_driver(dev->driver);
	struct fmc_device *fdev = to_fmc_device(dev);

	return fdrv->probe(fdev);
}

static int fmc_remove(struct device *dev)
{
	struct fmc_driver *fdrv = to_fmc_driver(dev->driver);
	struct fmc_device *fdev = to_fmc_device(dev);

	return fdrv->remove(fdev);
}

static void fmc_shutdown(struct device *dev)
{
	/* not implemented but mandatory */
}

static struct bus_type fmc_bus_type = {
	.name = "fmc",
	.match = fmc_match,
	.uevent = fmc_uevent,
	.probe = fmc_probe,
	.remove = fmc_remove,
	.shutdown = fmc_shutdown,
};

static void fmc_release(struct device *dev)
{
	struct fmc_device *fmc = container_of(dev, struct fmc_device, dev);

	kfree(fmc);
}

/*
 * The eeprom is exported in sysfs, through a binary attribute
 */

static ssize_t fmc_read_eeprom(struct file *file, struct kobject *kobj,
			   struct bin_attribute *bin_attr,
			   char *buf, loff_t off, size_t count)
{
	struct device *dev;
	struct fmc_device *fmc;
	int eelen;

	dev = container_of(kobj, struct device, kobj);
	fmc = container_of(dev, struct fmc_device, dev);
	eelen = fmc->eeprom_len;
	if (off > eelen)
		return -ESPIPE;
	if (off == eelen)
		return 0; /* EOF */
	if (off + count > eelen)
		count = eelen - off;
	memcpy(buf, fmc->eeprom + off, count);
	return count;
}

static ssize_t fmc_write_eeprom(struct file *file, struct kobject *kobj,
				struct bin_attribute *bin_attr,
				char *buf, loff_t off, size_t count)
{
	struct device *dev;
	struct fmc_device *fmc;

	dev = container_of(kobj, struct device, kobj);
	fmc = container_of(dev, struct fmc_device, dev);
	return fmc->op->write_ee(fmc, off, buf, count);
}

static struct bin_attribute fmc_eeprom_attr = {
	.attr = { .name = "eeprom", .mode = S_IRUGO | S_IWUSR, },
	.size = 8192, /* more or less standard */
	.read = fmc_read_eeprom,
	.write = fmc_write_eeprom,
};

/*
 * Functions for client modules follow
 */

int fmc_driver_register(struct fmc_driver *drv)
{
	if (fmc_check_version(drv->version, drv->driver.name))
		return -EINVAL;
	drv->driver.bus = &fmc_bus_type;
	return driver_register(&drv->driver);
}
EXPORT_SYMBOL(fmc_driver_register);

void fmc_driver_unregister(struct fmc_driver *drv)
{
	driver_unregister(&drv->driver);
}
EXPORT_SYMBOL(fmc_driver_unregister);

/*
 * When a device set is registered, all eeproms must be read
 * and all FRUs must be parsed
 */
int fmc_device_register_n(struct fmc_device **devs, int n)
{
	struct fmc_device *fmc, **devarray;
	uint32_t device_id;
	int i, ret = 0;

	if (n < 1)
		return 0;

	/* Check the version of the first data structure (function prints) */
	if (fmc_check_version(devs[0]->version, devs[0]->carrier_name))
		return -EINVAL;

	devarray = kmemdup(devs, n * sizeof(*devs), GFP_KERNEL);
	if (!devarray)
		return -ENOMEM;

	/* Make all other checks before continuing, for all devices */
	for (i = 0; i < n; i++) {
		fmc = devarray[i];
		if (!fmc->hwdev) {
			pr_err("%s: device nr. %i has no hwdev pointer\n",
			       __func__, i);
			ret = -EINVAL;
			break;
		}
		if (fmc->flags & FMC_DEVICE_NO_MEZZANINE) {
			dev_info(fmc->hwdev, "absent mezzanine in slot %d\n",
				 fmc->slot_id);
			continue;
		}
		if (!fmc->eeprom) {
			dev_err(fmc->hwdev, "no eeprom provided for slot %i\n",
				fmc->slot_id);
			ret = -EINVAL;
		}
		if (!fmc->eeprom_addr) {
			dev_err(fmc->hwdev, "no eeprom_addr for slot %i\n",
				fmc->slot_id);
			ret = -EINVAL;
		}
		if (!fmc->carrier_name || !fmc->carrier_data ||
		    !fmc->device_id) {
			dev_err(fmc->hwdev,
				"deivce nr %i: carrier name, "
				"data or dev_id not set\n", i);
			ret = -EINVAL;
		}
		if (ret)
			break;

	}
	if (ret) {
		kfree(devarray);
		return ret;
	}

	/* Validation is ok. Now init and register the devices */
	for (i = 0; i < n; i++) {
		fmc = devarray[i];

		fmc->nr_slots = n; /* each slot must know how many are there */
		fmc->devarray = devarray;

		device_initialize(&fmc->dev);
		fmc->dev.release = fmc_release;
		fmc->dev.parent = fmc->hwdev;

		/* Fill the identification stuff (may fail) */
		fmc_fill_id_info(fmc);

		fmc->dev.bus = &fmc_bus_type;

		/* Name from mezzanine info or carrier info. Or 0,1,2.. */
		device_id = fmc->device_id;
		if (!fmc->mezzanine_name)
			dev_set_name(&fmc->dev, "fmc-%04x", device_id);
		else
			dev_set_name(&fmc->dev, "%s-%04x", fmc->mezzanine_name,
				     device_id);
		ret = device_add(&fmc->dev);
		if (ret < 0) {
			dev_err(fmc->hwdev, "Slot %i: Failed in registering "
				"\"%s\"\n", fmc->slot_id, fmc->dev.kobj.name);
			goto out;
		}
		ret = sysfs_create_bin_file(&fmc->dev.kobj, &fmc_eeprom_attr);
		if (ret < 0) {
			dev_err(&fmc->dev, "Failed in registering eeprom\n");
			goto out1;
		}
		/* This device went well, give information to the user */
		fmc_dump_eeprom(fmc);
		fmc_dump_sdb(fmc);
	}
	return 0;

out1:
	device_del(&fmc->dev);
out:
	fmc_free_id_info(fmc);
	put_device(&fmc->dev);

	kfree(devarray);
	for (i--; i >= 0; i--) {
		sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
		device_del(&devs[i]->dev);
		fmc_free_id_info(devs[i]);
		put_device(&devs[i]->dev);
	}
	return ret;

}
EXPORT_SYMBOL(fmc_device_register_n);

int fmc_device_register(struct fmc_device *fmc)
{
	return fmc_device_register_n(&fmc, 1);
}
EXPORT_SYMBOL(fmc_device_register);

void fmc_device_unregister_n(struct fmc_device **devs, int n)
{
	int i;

	if (n < 1)
		return;

	/* Free devarray first, not used by the later loop */
	kfree(devs[0]->devarray);

	for (i = 0; i < n; i++) {
		sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
		device_del(&devs[i]->dev);
		fmc_free_id_info(devs[i]);
		put_device(&devs[i]->dev);
	}
}
EXPORT_SYMBOL(fmc_device_unregister_n);

void fmc_device_unregister(struct fmc_device *fmc)
{
	fmc_device_unregister_n(&fmc, 1);
}
EXPORT_SYMBOL(fmc_device_unregister);

/* Init and exit are trivial */
static int fmc_init(void)
{
	return bus_register(&fmc_bus_type);
}

static void fmc_exit(void)
{
	bus_unregister(&fmc_bus_type);
}

module_init(fmc_init);
module_exit(fmc_exit);

MODULE_LICENSE("GPL");
