#include <sys/queue.h>
#include "doscmd.h"

struct callback {
	LIST_ENTRY(callback) chain;
	u_long vec;
	callback_t func;
	char *name;
};

LIST_HEAD(cbhead , callback) cbhead[127];

#define	CBHASH(x)	(((x) * 17) % 127)

void
register_callback(u_long vec, callback_t func, char *name)
{
	struct cbhead *head;
	struct callback *elm;

	elm = malloc(sizeof(struct callback));
	elm->vec = vec;
	elm->func = func;
	elm->name = name;

	head = &cbhead[CBHASH(vec)];
	LIST_INSERT_HEAD(head, elm, chain);
}

callback_t
find_callback(u_long vec)
{
	struct cbhead *head;
	struct callback *elm;

	head = &cbhead[CBHASH(vec)];
	for (elm = head->lh_first; elm; elm = elm->chain.le_next)
		if (elm->vec == vec)
			break;
	if (elm) {
		debug(D_TRAPS, "callback %s\n", elm->name);
		return (elm->func);
	} else
		return ((callback_t)0);
}

u_long trampoline_rover = 0xF1000000;
u_char softint_trampoline[] = {
	0xf4,	/* HLT */
	0xca,	/* RETF 2 */
	2,
	0,
};
u_char hardint_trampoline[] = {
	0xf4,	/* HLT */
	0xcf,	/* IRET */
};
u_char null_trampoline[] = {
	0xcf,	/* IRET */
};

u_long
insert_generic_trampoline(size_t len, u_char *p)
{
	u_char *q;
	u_long where;

	where = trampoline_rover;
	q = (u_char *)VECPTR(where);
	memcpy(q, p, len);
	trampoline_rover += len;
	return (where);
}

u_long
insert_softint_trampoline(void)
{

	return (insert_generic_trampoline(
	    sizeof(softint_trampoline), softint_trampoline));
}

u_long
insert_hardint_trampoline(void)
{

	return (insert_generic_trampoline(
	    sizeof(hardint_trampoline), hardint_trampoline));
}

u_long
insert_null_trampoline(void)
{

	return (insert_generic_trampoline(
	    sizeof(null_trampoline), null_trampoline));
}
