#include "clib.h"
#include "globals.h"
#include "i386.h"
#include "systab.h"
#include "sched.h"
#include "paging.h"
#include "globals.h"
#include "vm86.h"
#include "phmem.h"


extern void _irq_0(void);
extern void _irq_1(void);
extern void _irq_2(void);
extern void _irq_3(void);
extern void _irq_4(void);
extern void _irq_5(void);
extern void _irq_6(void);
extern void _irq_7(void);
extern void _irq_8(void);
extern void _irq_9(void);
extern void _irq_a(void);
extern void _irq_b(void);
extern void _irq_c(void);
extern void _irq_d(void);
extern void _irq_e(void);
extern void _irq_f(void);

static
void (*irq[16])(void) = {
_irq_0, _irq_1, _irq_2, _irq_3, _irq_4, _irq_5, _irq_6, _irq_7,
_irq_8, _irq_9, _irq_a, _irq_b, _irq_c, _irq_d, _irq_e, _irq_f };

static
tss_t *irqtss[16];

void irq_handler(int irqno) _fastcall;

void irq_handler(int irqno)
{
	tss_t* tss;
        tss = sel2tss(irqtss[irqno]->backlink);
#if 0

         kprintf("IRQ %x in task %s\n",irqno, tss->name);
	 if (irqno == 1) {
                char c;
	 	asm("inb $0x60,%%al":"=eax"(c):);
                if (c==1) exit(5);
         }
#endif


        if (tss->eflags & F_VM) {
        	/* IRQ per un task V86 */
        	execute_vm86_irq(tss, irqno);
        } else {
        	/* IRQ per un qualsiasi altro task */
                task_signal(tss, SIGIRQ(irqno));
        }
}


void irq_setup(void)
{
	int i;
        gate_t g;
        char buf[6];

        for (i = 0; i < 0x0f; i++) {
        	sprintf(buf,"IRQ%02x",i);
                irqtss[i] = alloc_tss(NULL, buf);
                ASSERT(irqtss[i] != NULL);
                irqtss[i]->eip = irq[i];
                irqtss[i]->cs = KERNEL_CS;
                irqtss[i]->ss = irqtss[i]->ds = irqtss[i]->es = KERNEL_DS;
//                irqtss[i]->esp = (dword)valloc(2) + 8192;
                irqtss[i]->esp = (dword)alloc_free_page() + 4096;
                irqtss[i]->cr3 = tss_kernel.cr3;

        	set_gate(&g, irqtss[i]->tss_sel, 0, GT_PRESENT + GT_TASKGATE);
                set_idt_gate(0xf0+i, &g);
        }
}