/*
 * Copyright (c) 2015 Intel Corporation
 *
 * 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.
 */
/**
 * @file common dynamic irq/exception-relation functions for IA-32 arch
 */

#include <nanokernel.h>
#include <arch/cpu.h>
#include <nano_private.h>

#if ALL_DYN_STUBS > 0

/**
 * @brief Allocate dynamic interrupt stub
 *
 * @param sp Pointer to integer tracking stub allocation
 * @param limit Max number of stubs to allow
 * @return index of the first available element of the STUB array or -1
 *          if all elements are used
 */
int _stub_alloc(unsigned int *sp, unsigned int limit)
{
	int rv, key;

	key = irq_lock();
	if (*sp == limit) {
		rv = -1;
	} else {
		rv = (*sp)++;
	}
	irq_unlock(key);

	return rv;
}

/**
 * @brief Get the memory address of an unused dynamic IRQ or exception stub
 *
 * We generate at build time a set of dynamic stubs which push
 * a stub index onto the stack for use as an argument by
 * common handling code. These don't each have individual labels,
 * but it's possible to compute an offset to any particular one
 *
 * @param stub_idx Stub number to fetch the corresponding stub function
 * @param base_ptr Memory location in ROM where stubs begin
 * @return Pointer to the stub code to install into the IDT
 */
void *_get_dynamic_stub(int stub_idx, void *base_ptr)
{
	uint32_t offset;

	/*
	 * Because we want the sizes of the stubs to be consisent and minimized,
	 * stubs are grouped into blocks, each containing a push and subsequent
	 * 2-byte jump instruction to the end of the block, which then contains
	 * a larger jump instruction to common dynamic IRQ handling code
	 */
	offset = (stub_idx * DYN_STUB_SIZE) + ((stub_idx / DYN_STUB_PER_BLOCK) *
					       DYN_STUB_JMP_SIZE);

	return (void *)((uint32_t)base_ptr + offset);
}


/**
 * @brief Map an IRQ/exception vector back to the corresponding stub index
 *
 * This is used to fetch a reference to a stub when all we have is the IRQ
 * vector.
 *
 * @param IRQ vector as installed in the IDT
 * @return stub index
 */
uint8_t _stub_idx_from_vector(int vector)
{
	IDT_ENTRY *idt_entry;
	uint8_t *stub_addr;

	/*
	 * We need to do a reverse map from the vector number to the stub
	 * index. Look in the IDT for the provided vector and find the memory
	 * address of the handler function, which should be one of
	 * the dynamic stubs
	 */
	idt_entry = (IDT_ENTRY *)(_idt_base_address + (vector << 3));
	stub_addr = (uint8_t *)((uint32_t)idt_entry->offset_low +
		     ((uint32_t)idt_entry->offset_high << 16));

	/*
	 * Return the specific byte in the handler code which contains
	 * the stub index, the argument to the initial push operation
	 */
	return stub_addr[DYN_STUB_IDX_OFFSET];
}

#endif /* ALL_DYN_STUBS */

