#include
#include
#define IDT_NUM 256
static idt_entry_t idt[IDT_NUM];
static void idt_load()
{
idt_ptr_t ptr;
/* Setup IDT descriptor. */
ptr.limit = (IDT_NUM * sizeof(idt_entry_t)) - 1;
ptr.base = (uint32_t) &idt;
/* Load IDT. */
load_idt(&ptr);
}
static void idt_set_entry(uint16_t vector, uint8_t flags, addr_t isr)
{
idt[vector].offset_low = isr & 0xffff;
idt[vector].segment = KERNEL_CS_SEL;
idt[vector].reserved = 0;
idt[vector].flags = flags;
idt[vector].offset_high = (isr >> 16) & 0xffff;
}
/*All IRQs disabled initially except cascade*/
static uint32_t irq_mask = 0xFFFB;
struct intr_vector_t
{
pintr_t intr_service;
void *parm;
char msg[64];
};
static int null_intr(int intr_no, void *arg, struct pt_regs *regs);
static struct intr_vector_t intr_vector[MAX_HANDLED_INTR] =
{
/*0X00*/ {null_intr, NULL, "Division By Zero Exception"},
/*0X01*/ {null_intr, NULL, "Debug Exception"},
/*0X02*/ {null_intr, NULL, "Non Maskable Interrupt Exception"},
/*0X03*/ {null_intr, NULL, "Breakpoint Exception"},
/*0X04*/ {null_intr, NULL, "Into Detected Overflow Exception"},
/*0X05*/ {null_intr, NULL, "Out of Bounds Exception"},
/*0X06*/ {null_intr, NULL, "Invalid Opcode Exception"},
/*0X07*/ {null_intr, NULL, "No Coprocessor Exception"},
/*0X08*/ {null_intr, NULL, "Double Fault Exception"},
/*0X09*/ {null_intr, NULL, "Coprocessor Segment Overrun Exception"},
/*0X0A*/ {null_intr, NULL, "Bad TSS Exception"},
/*0X0B*/ {null_intr, NULL, "Segment Not Present Exception"},
/*0X0C*/ {null_intr, NULL, "Stack Fault Exception"},
/*0X0D*/ {null_intr, NULL, "General Protection Fault Exception"},
/*0X0E*/ {null_intr, NULL, "Page Fault Exception"},
/*0X0F*/ {null_intr, NULL, "Unknown Interrupt Exception"},
/*0X10*/ {null_intr, NULL, "Coprocessor Fault Exception"},
/*0X11*/ {null_intr, NULL, "Alignment Check Exception"},
/*0X12*/ {null_intr, NULL, "Machine Check Exception"},
/*0X13*/ {null_intr, NULL, "Reserved Exceptions 0X13"},
/*0X14*/ {null_intr, NULL, "Reserved Exceptions 0X14"},
/*0X15*/ {null_intr, NULL, "Reserved Exceptions 0X15"},
/*0X16*/ {null_intr, NULL, "Reserved Exceptions 0X16"},
/*0X17*/ {null_intr, NULL, "Reserved Exceptions 0X17"},
/*0X18*/ {null_intr, NULL, "Reserved Exceptions 0X18"},
/*0X19*/ {null_intr, NULL, "Reserved Exceptions 0X19"},
/*0X1A*/ {null_intr, NULL, "Reserved Exceptions 0X1A"},
/*0X1B*/ {null_intr, NULL, "Reserved Exceptions 0X1B"},
/*0X1C*/ {null_intr, NULL, "Reserved Exceptions 0X1C"},
/*0X1D*/ {null_intr, NULL, "Reserved Exceptions 0X1D"},
/*0X1E*/ {null_intr, NULL, "Reserved Exceptions 0X1E"},
/*0X1F*/ {null_intr, NULL, "Reserved Exceptions 0X1F"},
/*0X20*/ {null_intr, NULL, "Reserved Exceptions 0X20"},
/*0X21*/ {null_intr, NULL, "Reserved Exceptions 0X21"},
/*0X22*/ {null_intr, NULL, "Reserved Exceptions 0X22"},
/*0X23*/ {null_intr, NULL, "Reserved Exceptions 0X23"},
/*0X24*/ {null_intr, NULL, "Reserved Exceptions 0X24"},
/*0X25*/ {null_intr, NULL, "Reserved Exceptions 0X25"},
/*0X26*/ {null_intr, NULL, "Reserved Exceptions 0X26"},
/*0X27*/ {null_intr, NULL, "Reserved Exceptions 0X27"},
/*0X28*/ {null_intr, NULL, "Reserved Exceptions 0X28"},
/*0X29*/ {null_intr, NULL, "Reserved Exceptions 0X29"},
/*0X2A*/ {null_intr, NULL, "Reserved Exceptions 0X2A"},
/*0X2B*/ {null_intr, NULL, "Reserved Exceptions 0X2B"},
/*0X2C*/ {null_intr, NULL, "Reserved Exceptions 0X2C"},
/*0X2D*/ {null_intr, NULL, "Reserved Exceptions 0X2D"},
/*0X2E*/ {null_intr, NULL, "Reserved Exceptions 0X2E"},
/*0X2F*/ {null_intr, NULL, "Reserved Exceptions 0X2F"},
};
static int null_intr(int intr_no, void *arg, struct pt_regs *regs)
{
KPRINTF("intr %x : ", intr_no);
KPRINTF("%s\n", intr_vector[intr_no].msg);
halt();
return 0;
}
void irq_attach(int intr_no, pintr_t func , void *parm, char *msg)
{
KPRINTF("irq_attach intr[%d][%s]\n", intr_no, msg);
if(intr_no>=(sizeof(intr_vector)/sizeof(struct intr_vector_t)) || (intr_no < 0))
{
KPRINTF("irq_attach error intr[%d][%s]\n", intr_no, msg);
return;
}
if(intr_vector[intr_no].intr_service != null_intr)
{
KPRINTF("irq_attach error exits intr[%d][%s]\n", intr_no, msg);
return;
}
intr_vector[intr_no].intr_service = func;
intr_vector[intr_no].parm = parm;
strncpy(intr_vector[intr_no].msg, msg, sizeof(intr_vector[intr_no].msg) - 1);
}
#define PORT_8259M 0x20
#define PORT_8259S 0xA0
#define EOI_8259M() outb(PORT_8259M, 0x20)
#define EOI_8259S() outb(PORT_8259S, 0x20)
void intr_handler(struct pt_regs *regs)
{
int irq_retval;
int irq = regs->int_no;
if(irq
{
if (irq>0X1F)
{
if ((irq - 0x20) & 8) /*Slave ?*/
EOI_8259S(); /*Non specific EOI to slave*/
EOI_8259M(); /*Non specific EOI to master*/
}
irq_retval = intr_vector[irq].intr_service(irq, intr_vector[irq].parm, regs);
if(irq_retval != 0)
{
dump_regs(regs);
KPRINTF("%s,[%d] return error\n", intr_vector[irq].msg, irq_retval);
}
}
else
{
dump_regs(regs);
KPRINTF("INTR ERROR HLT ......[%x] ", irq);
halt();
}
}
static void setup_PIC(uint8_t master_vector, uint8_t slave_vector)
{
outb_p(PORT_8259M, 0x11); /*start 8259 initialization(edge)*/
outb_p(PORT_8259M+1, master_vector); /*master base h/w vector = master_vector*/
outb_p(PORT_8259M+1, 0x04); /*Chain to slave (IRQ2)*/
outb_p(PORT_8259M+1, 0x01); /*finish 8259 initialization*/
outb_p(PORT_8259S, 0x11);
outb_p(PORT_8259S+1, slave_vector); /*slave base h/w vector = slave_vector*/
outb_p(PORT_8259S+1, 0x02); /*Slave cascade on IRQ2*/
outb_p(PORT_8259S+1, 0x01);
outb_p(PORT_8259M+1, 0xfb); /*Mask all except IRQ2 (cascade) 11111011*/
outb_p(PORT_8259S+1, 0xff); /*Mask all*/
}
void enable_irq(unsigned int irq)
{
irq_mask &= ~(1 << irq);
if (irq >= 8)
irq_mask &= ~(1 << 2);
outb(PORT_8259M+1, irq_mask & 0xFF);
outb(PORT_8259S+1, (irq_mask >> 8) & 0xFF);
}
void disable_irq(unsigned int irq)
{
irq_mask |= (1 << irq);
if ((irq_mask & 0xFF00) == 0xFF00)
irq_mask |= (1 << 2);
outb(PORT_8259M+1, irq_mask & 0xFF);
outb(PORT_8259S+1, (irq_mask >> 8) & 0xFF);
}
static void idt_init()
{
KPRINTF("idt_init\n");
extern void* wrappers[];
memset(idt, 0, sizeof(idt));
idt_load();
int i;
for(i=0; i
idt_set_entry(i, IDT_TRAP_GATE, (addr_t)wrappers[i]);
//idt_set_entry(0x90, IDT_SYS_GATE, (addr_t) i144);
setup_PIC(IRQBASE, IRQBASE+8);/*setup PIC*/
}
INITFUNC(idt_init, INIT_IDT);