interrupt table doesn't work

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Poseidon

interrupt table doesn't work

Post by Poseidon »

I have made an idt & gdt in c, with the following functions to fill them in:

structures and definitions:

Code: Select all

// structures
typedef struct {
   WORD offset15_0;
   WORD selector;
   WORD DPL;
   WORD offset31_16;
} IDT_t;

typedef struct {
   WORD limit_lo;
   WORD base_lo;
   BYTE base_hi;
   BYTE type;
   BYTE limit_hi;
   BYTE base_vhi;
} GDT_desc_t;

typedef struct {
   GDT_desc_t desc_NULL;
   GDT_desc_t desc_unused;
   GDT_desc_t desc_datasel;
   GDT_desc_t desc_codesel;
} GDT_t;

// definitions
IDT_t IDT[256]; // the IDT-table
GDT_t GDT;
functions:

Code: Select all

void pic_init (address_t pic1, address_t pic2) { // initialize PIC, 0x20 and 0x28 are used
   /* send ICW1 */
   p_outb(PIC1, ICW1);
   p_outb(PIC2, ICW1);

   /* send ICW2 */
   p_outb(PIC1 + 1, pic1);   /* remap */
   p_outb(PIC2 + 1, pic2);   /*  pics */

   /* send ICW3 */
   p_outb(PIC1 + 1, 4);   /* IRQ2 -> connection to slave */
   p_outb(PIC2 + 1, 2);

   /* send ICW4 */
   p_outb(PIC1 + 1, ICW4);
   p_outb(PIC2 + 1, ICW4);

   /* enable keyboard */
        p_outb(0x21,0xfd);
        p_outb(0xa1,0xff);
}


void lidt(void *base, unsigned int limit) { // this one came from this site
   unsigned int i[2];

   i[0] = limit << 16;
   i[1] = (unsigned int) base;
   asm ("lidt (%0)": :"p" (((char *) i)+2));
}

void lgdt(void *base, unsigned int limit) { // for the gdt..not sure this is right
   unsigned int i[2];

   i[0] = limit << 16;
   i[1] = (unsigned int) base;
   asm ("lgdt (%0)": :"p" (((char *) i)+2));
}

void intr_init (void) { // initialize the interrupts
   int i;

   GDT_fill_in(&GDT);      // Fill in GDT

   lgdt(&GDT, sizeof(GDT));
   lidt(&IDT, sizeof(IDT));   // Link the IDT to the CPU

   /* Init the exceptions and the traps */
   for (i = 0; i < 17; i++) set_vector((unsigned int) exception, 0x8E, i);
   for (i = 17; i < 256; i++) set_vector((unsigned int) trap, 0x8E, i);
}


void set_vector (unsigned int addr, unsigned int access_byte, unsigned vect_num) { // set a new isr
   IDT[vect_num].offset15_0 = addr >> 16;
   IDT[vect_num].offset31_16 = addr;

   IDT[vect_num].selector = 0x10;
   IDT[vect_num].DPL = access_byte;
}


void GDT_fill_in (GDT_t *gdt) { // fill in the GDT
   // NULL descriptor
   gdt->desc_NULL.limit_lo =   0;
   gdt->desc_NULL.base_lo =   0;
   gdt->desc_NULL.base_hi =   0;
   gdt->desc_NULL.type =      0;
   gdt->desc_NULL.limit_hi =   0;
   gdt->desc_NULL.base_vhi =   0;

   // unused descriptor
   gdt->desc_unused.limit_lo =   0;
   gdt->desc_unused.base_lo =   0;
   gdt->desc_unused.base_hi =   0;
   gdt->desc_unused.type =      0;
   gdt->desc_unused.limit_hi =   0;
   gdt->desc_unused.base_vhi =   0;

   // Linear Data Selector descriptor
   gdt->desc_datasel.limit_lo =   0xFFFF;
   gdt->desc_datasel.base_lo =   0;
   gdt->desc_datasel.base_hi =   0;
   gdt->desc_datasel.type =   0x92;
   gdt->desc_datasel.limit_hi =   0x0CF;
   gdt->desc_datasel.base_vhi =   0;

   // Linear Code Selector descriptor
   gdt->desc_codesel.limit_lo =   0xFFFF;
   gdt->desc_codesel.base_lo =   0;
   gdt->desc_codesel.base_hi =   0;
   gdt->desc_codesel.type =   0x9A;
   gdt->desc_codesel.limit_hi =   0x0CF;
   gdt->desc_codesel.base_vhi =   0;
}

// this to assign keyboard routine: set_vector((unsigned int) kbd_irq, 0x8E, 0x21);
srry for the amount of code :-[

i just can't find the error.. i would be really really grateful if someone could pick out my mistakes..

thanx in advance
durand
Member
Member
Posts: 193
Joined: Wed Dec 21, 2005 12:00 am
Location: South Africa
Contact:

Re:interrupt table doesn't work

Post by durand »

This is probably not your problem, but if you're using GCC, try adding the "__attribute__ ((packed))" to your structure definitions.

struct BOB {
WORD limit_lo;
BYTE base_hi;
} __attribute__ ((packed));

That way you can be guaranteed that the final structure is 1 WORD + 1 BYTE = 3 BYTES big.

Otherwise, GCC might align the variables so that they fall on a 32-bit boundary to increase the speed of your code. So your 3 BYTE structure would probably end up being a 4 BYTE structure because of the GCC data alignment features.

If you're not using GCC, you might want to check how your compiler aligns the data in it's structures, if at all.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:interrupt table doesn't work

Post by Pype.Clicker »

i don't see wrong things just like this... maybe attribute(packed) will help (just ask the code to display sizeof(struct) and make sure it has expected size to make sure ...)

you may also like to run your code in debugger-enabled BOCHS and use dump_cpu to make sure IDTR and GDTR have been loaded with proper values (a map of your kernel should give you absolute addresses of GDT and IDT, which will make the check up trivial).
Poseidon

Re:interrupt table doesn't work

Post by Poseidon »

didn't test the __attribute__ (packed), but could it be possible that i made a enormous stupid in these definitions?

Code: Select all

typedef unsigned char   BYTE;
typedef unsigned short   WORD;
typedef unsigned int   LONG;
Poseidon

Re:interrupt table doesn't work

Post by Poseidon »

any1? please? :'(
durand
Member
Member
Posts: 193
Joined: Wed Dec 21, 2005 12:00 am
Location: South Africa
Contact:

Re:interrupt table doesn't work

Post by durand »

Like Pype said, you can check that quite easily by printing out the sizeof's...

Code: Select all

typedef unsigned char   BYTE;
typedef unsigned short   WORD;
typedef unsigned int   LONG;

printf("%s%i%s\n","sizeof(BYTE) = ", sizeof(BYTE), " bytes" );
printf("%s%i%s\n","sizeof(WORD) = ", sizeof(WORD), " bytes" );
printf("%s%i%s\n","sizeof(LONG) = ", sizeof(LONG), " bytes" );

and then the sizeof your structs...
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:interrupt table doesn't work

Post by Candy »

Code: Select all

typedef unsigned char   BYTE;
typedef unsigned short   WORD;
typedef unsigned int   LONG;

printf("sizeof(BYTE) = %i bytes\n", sizeof(BYTE));
printf("sizeof(WORD) = %i bytes\n", sizeof(WORD));
printf("sizeof(LONG) = %i bytes\n", sizeof(LONG));
If you were going to replace them by strings anyway... This looks a little nicer.

Using a % in the first line is also possible, include 2 % signs.
Post Reply