I know that on this wiki are a lot of articles about interrupts. But i read all of these.
I've got problem with Interrupts. When I write keyboard driver IRQ1 didn't work, so I write a test software interrupt 0x50 (what simply prints on screen 'INT50' - and it works, but not return.
I write exception handlers to get information about this error. And when I call
Code: Select all
int 0x50
IRQ don't work form beggining - it don't calls at all.
My interrupts API:
Code: Select all
#define _set_gate(gate_addr,type,dpl,addr) \
__asm__ __volatile__("movw %%dx,%%ax\n\t" \
"movw %0,%%dx\n\t" \
"movl %%eax,%1\n\t" \
"movl %%edx,%2\n\t" \
: :"i"((short)(0x8000+(dpl<<13)+(type<<8))), \
"o"(*((char *)(gate_addr))), \
"o"(*(4+(char *)(gate_addr))), \
"d"((char *)(addr)),"a"(0x00080000)) \
#define PIC1 0x20 /* IO base address for master PIC */
#define PIC2 0xA0 /* IO base address for slave PIC */
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
#define PIC_EOI 0x20 /* End-of-interrupt command code */
void intSetGate(int n, void* p)
{
_set_gate(&mosIDT[n], 14, 0, p);
}
void intSetTrapGate(int n, void* p)
{
_set_gate(&mosIDT[n], 15, 0, p);
}
void intSetSystemGate(int n, void* p)
{
_set_gate(&mosIDT[n], 15, 3, p);
}
static unsigned int cached_irq_mask = 0xffff;
#define __byte(x,y) (((unsigned char *)&(y))[x])
#define cached_21 (__byte(0,cached_irq_mask))
#define cached_A1 (__byte(1,cached_irq_mask))
void intDisableIRQ(unsigned int irq) // disables IRQ
{
unsigned int mask = 1 << irq;
cached_irq_mask |= mask;
if (irq & 8)
{
outb(cached_A1,0xA1);
} else {
outb(cached_21,0x21);
}
}
void intEnableIRQ(unsigned int irq) // enables IRQ
{
unsigned int mask = ~(1 << irq);
cached_irq_mask &= mask;
if (irq & 8) {
mosWritePort(cached_A1,0xA1);
} else {
mosWritePort(cached_21,0x21);
}
}
#define PIC1 0x20
#define PIC2 0xA0
#define ICW1 0x11
#define ICW4 0x01
void intInit(int pic1, int pic2) // initializes PIC (code from this wiki)
{
/* send ICW1 */
outb(PIC1, ICW1);
outb(PIC2, ICW1);
/* send ICW2 */
outb(PIC1 + 1, pic1); /* remap */
outb(PIC2 + 1, pic2); /* pics */
/* send ICW3 */
outb(PIC1 + 1, 4); /* IRQ2 -> connection to slave */
outb(PIC2 + 1, 2);
/* send ICW4 */
outb(PIC1 + 1, ICW4);
outb(PIC2 + 1, ICW4);
/* disable all IRQs */
outb(PIC1 + 1, 0xFF);
}
void intEOI(unsigned int irq) // send EOI to the PIC (code form this wiki)
{
if(irq >= 8)
outb(PIC2_COMMAND,PIC_EOI);
outb(PIC1_COMMAND,PIC_EOI);
}
Code: Select all
; This is only wrappers
; IRQ 1 - keyboard interrupt
irq1:
pushad
call doIrq1
popad
iret
; int 0x50 - system test call
int50:
pushad
call doInt50
popad
iret
Code: Select all
#define ASMCALL extern "C"
ASMCALL void doInt50() // 0x50 - system test
{
mosWriteString("INT50");
}
// call on system startup after intInit()
void sysintInit()
{
intSetSystemGate(0x50, ASHANDLER(int50));
}
//...
// in keyboard driver
ASMCALL void doIrq1() // keyboard interrupt
{
//...
mosWriteString("IRQ1");
intEOI(1);
}
ASMCALL void irq1();
bool mosInitKbd() // call after intInit()
{
//...
intSetGate(0x21, (void*)irq1); // set interrupt handler into valid address
intEnableIRQ(1);
return true;
}