/*
 * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <stddef.h>

#include <platform_def.h>

#include <drivers/io/io_driver.h>
#include <drivers/io/io_storage.h>

/* Storage for a fixed maximum number of IO entities, definable by platform */
static io_entity_t entity_pool[MAX_IO_HANDLES];

/* Simple way of tracking used storage - each entry is NULL or a pointer to an
 * entity */
static io_entity_t *entity_map[MAX_IO_HANDLES];

/* Track number of allocated entities */
static unsigned int entity_count;

/* Array of fixed maximum of registered devices, definable by platform */
static const io_dev_info_t *devices[MAX_IO_DEVICES];

/* Number of currently registered devices */
static unsigned int dev_count;

/* Extra validation functions only used when asserts are enabled */
#if ENABLE_ASSERTIONS

/* Return a boolean value indicating whether a device connector is valid */
static int is_valid_dev_connector(const io_dev_connector_t *dev_con)
{
	int result = (dev_con != NULL) && (dev_con->dev_open != NULL);
	return result;
}


/* Return a boolean value indicating whether a device handle is valid */
static int is_valid_dev(const uintptr_t dev_handle)
{
	const io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
	int result = (dev != NULL) && (dev->funcs != NULL) &&
			(dev->funcs->type != NULL) &&
			(dev->funcs->type() < IO_TYPE_MAX);
	return result;
}


/* Return a boolean value indicating whether an IO entity is valid */
static int is_valid_entity(const uintptr_t handle)
{
	const io_entity_t *entity = (io_entity_t *)handle;
	int result = (entity != NULL) &&
			(is_valid_dev((uintptr_t)entity->dev_handle));
	return result;
}


/* Return a boolean value indicating whether a seek mode is valid */
static int is_valid_seek_mode(io_seek_mode_t mode)
{
	return ((mode != IO_SEEK_INVALID) && (mode < IO_SEEK_MAX));
}

#endif /* ENABLE_ASSERTIONS */
/* End of extra validation functions only used when asserts are enabled */


/* Open a connection to a specific device */
static int dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
		io_dev_info_t **dev_info)
{
	int result;
	assert(dev_info != NULL);
	assert(is_valid_dev_connector(dev_con));

	result = dev_con->dev_open(dev_spec, dev_info);
	return result;
}


/* Set a handle to track an entity */
static void set_handle(uintptr_t *handle, io_entity_t *entity)
{
	assert(handle != NULL);
	*handle = (uintptr_t)entity;
}


/* Locate an entity in the pool, specified by address */
static int find_first_entity(const io_entity_t *entity, unsigned int *index_out)
{
	int result = -ENOENT;
	for (unsigned int index = 0; index < MAX_IO_HANDLES; ++index) {
		if (entity_map[index] == entity) {
			result = 0;
			*index_out = index;
			break;
		}
	}
	return result;
}


/* Allocate an entity from the pool and return a pointer to it */
static int allocate_entity(io_entity_t **entity)
{
	int result = -ENOMEM;
	assert(entity != NULL);

	if (entity_count < MAX_IO_HANDLES) {
		unsigned int index = 0;
		result = find_first_entity(NULL, &index);
		assert(result == 0);
		*entity = entity_map[index] = &entity_pool[index];
		++entity_count;
	}

	return result;
}


/* Release an entity back to the pool */
static int free_entity(const io_entity_t *entity)
{
	int result;
	unsigned int index = 0;
	assert(entity != NULL);

	result = find_first_entity(entity, &index);
	if (result ==  0) {
		entity_map[index] = NULL;
		--entity_count;
	}

	return result;
}


/* Exported API */

/* Register a device driver */
int io_register_device(const io_dev_info_t *dev_info)
{
	int result = -ENOMEM;
	assert(dev_info != NULL);

	if (dev_count < MAX_IO_DEVICES) {
		devices[dev_count] = dev_info;
		dev_count++;
		result = 0;
	}

	return result;
}


/* Open a connection to an IO device */
int io_dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
		uintptr_t *handle)
{
	int result;
	assert(handle != NULL);

	result = dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
	return result;
}


/* Initialise an IO device explicitly - to permit lazy initialisation or
 * re-initialisation */
int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params)
{
	int result = 0;
	assert(dev_handle != (uintptr_t)NULL);
	assert(is_valid_dev(dev_handle));

	io_dev_info_t *dev = (io_dev_info_t *)dev_handle;

	/* Absence of registered function implies NOP here */
	if (dev->funcs->dev_init != NULL) {
		result = dev->funcs->dev_init(dev, init_params);
	}

	return result;
}


/* TODO: Consider whether an explicit "shutdown" API should be included */

/* Close a connection to a device */
int io_dev_close(uintptr_t dev_handle)
{
	int result = 0;
	assert(dev_handle != (uintptr_t)NULL);
	assert(is_valid_dev(dev_handle));

	io_dev_info_t *dev = (io_dev_info_t *)dev_handle;

	/* Absence of registered function implies NOP here */
	if (dev->funcs->dev_close != NULL) {
		result = dev->funcs->dev_close(dev);
	}

	return result;
}


/* Synchronous operations */


/* Open an IO entity */
int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle)
{
	int result;
	assert((spec != (uintptr_t)NULL) && (handle != NULL));
	assert(is_valid_dev(dev_handle));

	io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
	io_entity_t *entity;

	result = allocate_entity(&entity);

	if (result == 0) {
		assert(dev->funcs->open != NULL);
		result = dev->funcs->open(dev, spec, entity);

		if (result == 0) {
			entity->dev_handle = dev;
			set_handle(handle, entity);
		} else
			free_entity(entity);
	}
	return result;
}


/* Seek to a specific position in an IO entity */
int io_seek(uintptr_t handle, io_seek_mode_t mode, ssize_t offset)
{
	int result = -ENODEV;
	assert(is_valid_entity(handle) && is_valid_seek_mode(mode));

	io_entity_t *entity = (io_entity_t *)handle;

	io_dev_info_t *dev = entity->dev_handle;

	if (dev->funcs->seek != NULL)
		result = dev->funcs->seek(entity, mode, offset);

	return result;
}


/* Determine the length of an IO entity */
int io_size(uintptr_t handle, size_t *length)
{
	int result = -ENODEV;
	assert(is_valid_entity(handle) && (length != NULL));

	io_entity_t *entity = (io_entity_t *)handle;

	io_dev_info_t *dev = entity->dev_handle;

	if (dev->funcs->size != NULL)
		result = dev->funcs->size(entity, length);

	return result;
}


/* Read data from an IO entity */
int io_read(uintptr_t handle,
		uintptr_t buffer,
		size_t length,
		size_t *length_read)
{
	int result = -ENODEV;
	assert(is_valid_entity(handle));

	io_entity_t *entity = (io_entity_t *)handle;

	io_dev_info_t *dev = entity->dev_handle;

	if (dev->funcs->read != NULL)
		result = dev->funcs->read(entity, buffer, length, length_read);

	return result;
}


/* Write data to an IO entity */
int io_write(uintptr_t handle,
		const uintptr_t buffer,
		size_t length,
		size_t *length_written)
{
	int result = -ENODEV;
	assert(is_valid_entity(handle));

	io_entity_t *entity = (io_entity_t *)handle;

	io_dev_info_t *dev = entity->dev_handle;

	if (dev->funcs->write != NULL) {
		result = dev->funcs->write(entity, buffer, length,
				length_written);
	}

	return result;
}


/* Close an IO entity */
int io_close(uintptr_t handle)
{
	int result = 0;
	assert(is_valid_entity(handle));

	io_entity_t *entity = (io_entity_t *)handle;

	io_dev_info_t *dev = entity->dev_handle;

	/* Absence of registered function implies NOP here */
	if (dev->funcs->close != NULL)
		result = dev->funcs->close(entity);

	/* Ignore improbable free_entity failure */
	(void)free_entity(entity);

	return result;
}
