problem handling irq code

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
vibhory2j

problem handling irq code

Post by vibhory2j »

hi all,

i learned operating system development from bkerndev. i am having problem understanding this code for implementing irq in operating system.

the code is as follows :

Code: Select all

static unsigned int cached_irq_mask;

#define __byte(x,y)           (((unsigned char *)&(y))[[x]])

#define cached_21               (__byte(0,cached_irq_mask))
#define cached_A1   (__byte(1,cached_irq_mask))

static void irq_delay(unsigned long loops)
{
    unsigned long i, j;
    for (i = 0; i < loops; i++)
   for (j = 0; j < loops; j++)
       do {
       } while (0);

}

void disable_irq(unsigned int irq)
{
    unsigned int mask = 1 << irq;

    cached_irq_mask |= mask;
    if (irq & 8)
   outb(cached_A1, 0xA1);
    else
   outb(cached_21, 0x21);
}

void enable_irq(unsigned int irq)
{
    unsigned int mask = ~(1 << irq);

    cached_irq_mask &= mask;
    if (irq & 8)
   outb(cached_A1, 0xA1);
    else
   outb(cached_21, 0x21);
}


void init_irq(void)
{
    cached_irq_mask = 0xffff;
    
    outb(0xff, 0x21);      /* mask all of 8259A-1 */
    outb(0xff, 0xA1);      /* mask all of 8259A-2 */

    outb_p(0x11, 0x20);      /* ICW1: select 8259A-1 init */
    outb_p(0x20 + 0, 0x21);   /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
    outb_p(0x04, 0x21);      /* 8259A-1 (the master) has a slave on IR2 */
    outb_p(0x03, 0x21);      /* master does Auto EOI */

    outb_p(0x11, 0xA0);      /* ICW1: select 8259A-2 init */
    outb_p(0x20 + 8, 0xA1);   /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
    outb_p(0x02, 0xA1);      /* 8259A-2 is a slave on master's IR2 */
    outb_p(0x01, 0xA1);      /* slave doesn't Auto EOI */

    irq_delay(5000);      /* wait for 8259A to initialize */

    outb(cached_21, 0x21);   /* restore master IRQ mask */
    outb(cached_A1, 0xA1);   /* restore slave IRQ mask */
}
i can understand the basic working like cascading of irq's and mapping of irq' s and all that stuff. can somebody explain me how this code is actually enabling interrupts for hardware requets bacause it is tough for me to figure out seeing the bkerndev code for irq.

i know i may be stupid asking this but i am new to operating system. also after using this code the irq's are not working.
thanks in advance for anay help
paulbarker

Re:problem handling irq code

Post by paulbarker »

An IRQ goes thru the following path (very simplified):

Source ---> PIC ---> CPU

The IRQ can be blocked at the PIC and/or the CPU. enable_irq and disable_irq handler masking and unmasking interrupts on the PIC. For the CPU, the cli and sti instructions are used.

You need to give an sti after calling init_irq, and once all other IRQ handling is ready (like the IDT). Are you doing this?

You also need to call enable_irq with the appropriate arguments to enable a particular IRQ. At least enable IRQ 2, so that the slave PIC can cascade its IRQs to the master.

A more full diagram would be:

Source for IRQ 0-7 -------------------------> MASTER PIC ---> CPU
|
Source for IRQ 8-15 --> SLAVE PIC ---------+

(Please forgive the formatting of the above)

By 'not working' do you mean the interrupts are ignored or causing crashes?
vibhory2j

Re:problem handling irq code

Post by vibhory2j »

thanks paulbarker... i got your concept.
by not working i mean i have encountered both an ignore and crashes (exceptions - invalid opcode fault). and soon as i comment the enable_irq() lines the opcode exception fault disappears and obviously an ignore occurs.

one more strange thing i have seen is that when a exception occurs the output on the screen says "invalid opcode fault". but bochs says it was bad TSS selector.
I have checked the exceptions correct and are working fine.whts is this ???
asmboozer

Re:problem handling irq code

Post by asmboozer »

vibhory2j wrote: hi all,

i learned operating system development from bkerndev. i am having problem understanding this code for implementing irq in operating system.

the code is as follows :

Code: Select all

static unsigned int cached_irq_mask;

#define __byte(x,y)           (((unsigned char *)&(y))[[x]])

#define cached_21               (__byte(0,cached_irq_mask))
#define cached_A1   (__byte(1,cached_irq_mask))

static void irq_delay(unsigned long loops)
{
    unsigned long i, j;
    for (i = 0; i < loops; i++)
   for (j = 0; j < loops; j++)
       do {
       } while (0);

}

void disable_irq(unsigned int irq)
{
    unsigned int mask = 1 << irq;

    cached_irq_mask |= mask;
    if (irq & 8)
   outb(cached_A1, 0xA1);
    else
   outb(cached_21, 0x21);
}

void enable_irq(unsigned int irq)
{
    unsigned int mask = ~(1 << irq);

    cached_irq_mask &= mask;
    if (irq & 8)
   outb(cached_A1, 0xA1);
    else
   outb(cached_21, 0x21);
}


void init_irq(void)
{
    cached_irq_mask = 0xffff;
    
    outb(0xff, 0x21);      /* mask all of 8259A-1 */
    outb(0xff, 0xA1);      /* mask all of 8259A-2 */

    outb_p(0x11, 0x20);      /* ICW1: select 8259A-1 init */
    outb_p(0x20 + 0, 0x21);   /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
    outb_p(0x04, 0x21);      /* 8259A-1 (the master) has a slave on IR2 */
    outb_p(0x03, 0x21);      /* master does Auto EOI */

    outb_p(0x11, 0xA0);      /* ICW1: select 8259A-2 init */
    outb_p(0x20 + 8, 0xA1);   /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
    outb_p(0x02, 0xA1);      /* 8259A-2 is a slave on master's IR2 */
    outb_p(0x01, 0xA1);      /* slave doesn't Auto EOI */

    irq_delay(5000);      /* wait for 8259A to initialize */

    outb(cached_21, 0x21);   /* restore master IRQ mask */
    outb(cached_A1, 0xA1);   /* restore slave IRQ mask */
}
i can understand the basic working like cascading of irq's and mapping of irq' s and all that stuff. can somebody explain me how this code is actually enabling interrupts for hardware requets bacause it is tough for me to figure out seeing the bkerndev code for irq.

i know i may be stupid asking this but i am new to operating system. also after using this code the irq's are not working.
thanks in advance for anay help
I also learned from the tutorial(but the tutorial has no such codes), but finaly, my experiment is ok.
vibhory2j

Re:problem handling irq code

Post by vibhory2j »

correct the code above does not belong to the tutorial . i took it from somewhere else just learn how things works the other way. but the irq's are not working now.

moreoever, i am getting following exceptions now...

invalid TSS fault
invalid opcode fault.

i cant see any such fault in the code. please help me .
thanks in advance for any help
crackers

Re:problem handling irq code

Post by crackers »

vibhory2j wrote: moreoever, i am getting following exceptions now...

invalid TSS fault
invalid opcode fault.

i cant see any such fault in the code. please help me .
thanks in advance for any help
I hope you've set correct segment descriptor in IDT.
vibhory2j

Re:problem handling irq code

Post by vibhory2j »

i have setup a task gate . the code from my idt.c as follows:-

this is function to pass arguments to idt descriptor
void idt_set_gate(uint32 n, uint32 base, uint16 segment, uint16 flags)
{
idt[n].segment = segment;
idt[n].flags = flags;
idt[n].offset15_0 = base & 0xFFFF;
idt[n].offset31_16 = (base >> 16) & 0xFFFF;
}
this is the function to setup a task gate
void set_task_gate(uint32 n, uint16 seg)
{
   idt_set_gate(n, 0, seg, IDT_PRESENT | IDT_TASK | IDT_DPL0);
}
here is a section on idt.h file:
#define IDT_PRESENT 0x8000
#define IDT_TRAP 0x0700
#define IDT_INT 0x0600
#define IDT_TASK 0x0500
#define IDT_32 0x0800

#define IDT_DPL0 0x0000
#define IDT_DPL1 0x2000
#define IDT_DPL2 0x4000
#define IDT_DPL3 0x6000
crackers

Re:problem handling irq code

Post by crackers »

I think this code is ok. You should check your TSS segment desc in GDT. I've no others ideas.
Post Reply