/*
 * Copyright (c) 2013-2014 Wind River Systems, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @brief Task IRQ kernel services
 *
 * This module manages the interrupt functionality between a task level device
 * driver and the kernel.
 *
 * A task level device driver allocates a specific task IRQ object by providing
 * an IRQ and priority level; the registration process allocates an interrupt
 * vector, sets up an ISR, and enables the associated interrupt. When an
 * interrupt occurs, the ISR handler signals an event specific to the IRQ object.
 * The task level device driver tests/waits on this event number to determine
 * if/when the interrupt has occurred. As the ISR also disables the interrupt, the
 * task level device driver subsequently make a request to have the interrupt
 * enabled again.
 *
 * These routines perform error checking to ensure that an IRQ object can only be
 * allocated by a single task, and that subsequent operations on that IRQ object
 * are only performed by that task. This checking is necessary to ensure that
 * a task cannot impact the operation of an IRQ object it does not own.
 *
 */

#if (CONFIG_MAX_NUM_TASK_IRQS > 0)

#include <nano_private.h>
#include <microkernel.h>
#include <micro_private.h>
#include <misc/__assert.h>

#define MAX_TASK_IRQS CONFIG_MAX_NUM_TASK_IRQS

#define INVALID_TASK -1

/* task IRQ object registration request */

struct irq_obj_reg_arg {
	kirq_t irq_obj;   /* IRQ object identifier */
	uint32_t irq;  /* IRQ of device */
	ktask_t task_id; /* requesting task */
};

/* task IRQ object type */

struct task_irq_info {
	ktask_t task_id;  /* task ID of task IRQ object's owner */
	uint32_t irq;    /* IRQ used by task IRQ object */
	kevent_t event;  /* event number assigned to task IRQ object */
	uint32_t vector; /* interrupt vector assigned to task IRQ object */
};

/* task IRQ object array */

static struct task_irq_info task_irq_object[MAX_TASK_IRQS] = {
	[0 ...(MAX_TASK_IRQS - 1)].task_id = INVALID_TASK
};

/* array of event id used by task IRQ objects */
extern const kevent_t _TaskIrqEvt_objIds[];

/**
 *
 * @brief ISR for task IRQ objects
 *
 * This ISR handles interrupts generated by registered task IRQ objects.
 *
 * The ISR triggers an event signal specified by the event number associated
 * with a particular task IRQ object; the interrupt for the task IRQ object
 * is then disabled. The parameter provided to the ISR is a structure that
 * contains information about the objects's vector, IRQ, and event number.
 *
 * This ISR does not facilitate an int acknowledgment as it presumes that an
 * End of Interrupt (EOI) routine is provided by the interrupt controller that
 * is being used.
 *
 * @param parameter Pointer to task IRQ object
 *
 * @return N/A
 */
static void task_irq_int_handler(void *parameter)
{
	struct task_irq_info *irq_obj_ptr = parameter;

	isr_event_send(irq_obj_ptr->event);
	irq_disable(irq_obj_ptr->irq);
}

/**
 *
 * @brief Re-enable a task IRQ object's interrupt
 *
 * This re-enables the interrupt for a task IRQ object.
 * @param irq_obj IRQ object identifier
 *
 * @return N/A
 */
void task_irq_ack(kirq_t irq_obj)
{
	__ASSERT(irq_obj < MAX_TASK_IRQS, "Invalid IRQ object");
	__ASSERT(task_irq_object[irq_obj].task_id == task_id_get(),
			 "Incorrect Task ID");

	irq_enable(task_irq_object[irq_obj].irq);
}

int task_irq_wait(kirq_t irq_obj, int32_t timeout)
{
	__ASSERT(irq_obj < MAX_TASK_IRQS, "Invalid IRQ object");
	__ASSERT(task_irq_object[irq_obj].task_id == task_id_get(),
			 "Incorrect Task ID");

	return task_event_recv(task_irq_object[irq_obj].event, timeout);
}

/**
 *
 * @brief Allocate a task IRQ object
 *
 * This routine allocates a task IRQ object to a task.
 * @param arg Pointer to registration request arguments
 *
 * @return ptr to allocated task IRQ object if successful, NULL if not
 */
static int _k_task_irq_alloc(void *arg)
{
	struct irq_obj_reg_arg *argp = (struct irq_obj_reg_arg *)arg;
	struct task_irq_info *irq_obj_ptr; /* ptr to task IRQ object */
	int curr_irq_obj;	/* IRQ object loop counter */

	/* Fail if the requested IRQ object is already in use */

	if (task_irq_object[argp->irq_obj].task_id != INVALID_TASK) {
		return (int)NULL;
	}

	/* Fail if the requested IRQ is already in use */

	for (curr_irq_obj = 0; curr_irq_obj < MAX_TASK_IRQS; curr_irq_obj++) {
		if ((task_irq_object[curr_irq_obj].irq == argp->irq) &&
		    (task_irq_object[curr_irq_obj].task_id != INVALID_TASK)) {
			return (int)NULL;
		}
	}

	/* Take ownership of specified IRQ object */

	irq_obj_ptr = &task_irq_object[argp->irq_obj];
	irq_obj_ptr->task_id = argp->task_id;
	irq_obj_ptr->irq = argp->irq;
	irq_obj_ptr->event = _TaskIrqEvt_objIds[argp->irq_obj];
	irq_obj_ptr->vector = INVALID_VECTOR;

	return (int)irq_obj_ptr;
}


uint32_t task_irq_alloc(kirq_t irq_obj,	uint32_t irq, uint32_t priority,
			uint32_t flags)
{
	struct irq_obj_reg_arg arg;  /* IRQ object registration request arguments */
	struct task_irq_info *irq_obj_ptr; /* ptr to task IRQ object */

	/* Allocate the desired IRQ object and IRQ */

	arg.irq_obj = irq_obj;
	arg.irq = irq;
	arg.task_id = task_id_get();

	irq_obj_ptr = (struct task_irq_info *)task_offload_to_fiber(_k_task_irq_alloc,
						     (void *)&arg);
	if (irq_obj_ptr == NULL) {
		return INVALID_VECTOR;
	}

	irq_obj_ptr->vector = irq_connect_dynamic(
		irq, priority, task_irq_int_handler, (void *)irq_obj_ptr,
		flags);
	irq_enable(irq);

	return irq_obj_ptr->vector;
}


#endif /* (CONFIG_MAX_NUM_TASK_IRQS > 0) */
