Problem with software interrupts and IRQs

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.
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Problem with software interrupts and IRQs

Post by kubawal »

Hi!

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
I saw 'INT50' on the screen, but after that my exception handler gives me information about exception 13 (General Protection Fault)
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);
}
My interrupts code:

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;
}
Nable
Member
Member
Posts: 453
Joined: Tue Nov 08, 2011 11:35 am

Re: Problem with software interrupts and IRQs

Post by Nable »

Oh, it looks like you should learn about `enum`, `struct` and `union` - these keywords are very useful for getting rid of ugly defines.
Btw, I see `intInit` function but I don't see where it is called (and with what arguments).
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Problem with software interrupts and IRQs

Post by Combuster »

void intInit(int pic1, int pic2) // initializes PIC (code from this wiki)
Well, I have seen my fair share of problems with people copy-pasting code they don't know what it does, but actually messing up the copy... :lol:

(count the instructions to each of the PIC chips)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: Problem with software interrupts and IRQs

Post by kubawal »

Nable wrote:Btw, I see `intInit` function but I don't see where it is called (and with what arguments).
This is fragment of my function that initializes system:

Code: Select all

intInit(0x20, 0x28); // init PIC
	
	sysintInit(); // init system interrupts (INT 0x50)
	excInit(); // init exceptions (EXC0 - EXC14)

// ...

mosInitKbd(); // initializes kbd (IRQ 1)
Nable wrote:Oh, it looks like you should learn about `enum`, `struct` and `union` - these keywords are very useful for getting rid of ugly defines.
I'm not a begginer in c++. I didn't name this topic 'HELP MY SYSTEM DONT WORK HELP! HELP! HELP!!!!'. I know what is structs, classes, unions, bit enums etc.
I write this topic because i try all ways to fix it (but I must **** up something because otherwise it should works ;) )

PS. I run it into VirtualBox, with GRUB.
PPS. I tested code from tutorial (http://haxite.org/article/view/85-Kurs+ ... B%C4%87+I/), what I using before and it also has not working IRQs
PPPS. in my startup code IDT have definition like this:

Code: Select all

;...
lidt [idt_descr]
;...

; IDT
idt_descr: ; header
dw 256*8-1 
dd mosIDT
GLOBAL mosIDT
mosIDT:
times 256 dd 0,0
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: Problem with software interrupts and IRQs

Post by kubawal »

I find another ISR template:

Code: Select all

pusha
push	eax
push	ds
push	es
push	fs
push	gs

mov    eax, 0x10
mov    ds, ax
mov    es, ax
mov    fs, ax
mov    gs, ax

// do something

pop	gs
pop	fs
pop	es
pop	ds
pop	eax
popa
iret
What is the difference between this code and my code from first post?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Problem with software interrupts and IRQs

Post by Combuster »

kubawal wrote:What is the difference between this code and my code from first post?
- popa/popad (16 or 32 bit push depending on assembler vs always 32-bit push)
- reloading of segment registers - which is a good idea in case userspace broke something.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: Problem with software interrupts and IRQs

Post by kubawal »

But it also not works :)

PS. I try to don't use asm wrappers and use BLACK MAGIC, but VirtualBox machine crashes and I've got MessageBox with Buddy Meditation about error ](*,)
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Problem with software interrupts and IRQs

Post by Combuster »

That's because you asked the wrong question.

Considering you appear to be a novice when it comes to debugging, VirtualBox is a bad help. Run your code in Bochs - most likely you'll get detailed messages regarding how you screwed up. You can even compile bochs with debugger enabled for detailed inspection.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: Problem with software interrupts and IRQs

Post by kubawal »

I completly rewrite my startup code and GDT + IDT support with Bran's tutorial.
Manually called interrupts works, but IRQ's not.
Because keyboard interrupt not works (does it need to set First Port Interrupt in Configuration Byte?) I try to use PIT and IRQ 0. It should simply change character in left-top corner of the console - but it also not works ](*,)
My new code:

Code: Select all

#define PACKED __attribute__((packed))
struct idtEntry
{
    unsigned short baseLow;
    unsigned short sel;  	// selektor jadra      
    unsigned char always0;  // zawsze 0
    unsigned char flags;      
    unsigned short baseHigh;
} PACKED;

struct idtLoad
{
    unsigned short limit;
    unsigned int base;
} PACKED;

idtEntry IDT[256]; // IDT
idtLoad IDTl; // IDT load struct

void intSetEntry(unsigned char num, unsigned long base, unsigned short sel = 0x08, unsigned char flags = 0x8E) // default: kernel code segment, ring 0
{
    /* The interrupt routine's base address */
    IDT[num].baseLow = (base & 0xFFFF);
    IDT[num].baseHigh = (base >> 16) & 0xFFFF;

    IDT[num].sel = sel;
    IDT[num].always0 = 0;
    IDT[num].flags = flags;
}		 
 
void intEnableIRQ(unsigned char IRQline) { // enables IRQ (probably it not works) (code form this wiki)
    WORD port;
    BYTE value;
 
    if(IRQline < 8) {
        port = PIC1_DATA;
    } else {
        port = PIC2_DATA;
        IRQline -= 8;
    }
    value = inb(port) | (1 << IRQline);
    outb(port, value);        
}
 
void intDisableIRQ(unsigned char IRQline) {
    WORD port;
    BYTE value;
 
    if(IRQline < 8) {
        port = PIC1_DATA;
    } else {
        port = PIC2_DATA;
        IRQline -= 8;
    }
    value = inb(port) & ~(1 << IRQline);
    outb(port, value);        
}

void intInit(int pic1, int pic2) // initialozes interrupts
{
	// set IDT load struct params
    IDTl.limit = (sizeof(idtEntry) * 256) - 1;
    IDTl.base = reinterpret_cast<unsigned int>(IDT);
	
	// remap PIC
	
	/* 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);
	
	// zero IDT
	mosSetMemory<idtEntry>(IDT, 256, brute_cast<idtEntry>(0x0000));
	
	// load IDT	
       idtFlush();
}

ASMCALL void idtFlush(); // asm("lidt [IDTl]")

// PIT driver

int taskNum = 0;
typedef void (*pitTask)();
pitTask tasks[10]; // task list to do

DEFWRAP(irq, 0);

DEFHANDLER(Irq, 0)
{
	for(int i = 0; i < taskNum; i++)
		tasks[i]();
	intEOI(0);
}

void numbers() // increments character in left-top
{
	volatile WORD* mem = (WORD*)0xB8000;
	*mem++;
}

void pitInit(unsigned long freq)
{
	taskNum = 0;

// set PIT freq
	freq = 1193180 / freq;
	outb(0x36, 0x43);
	outb(freq&0xff, 0x40);
	outb((freq>>8)&0xff, 0x40);
	
	intSetGate(0x20, ASHANDLER(irq0));
	intEnableIRQ(0);
	
	pitAddTask(numbers);
}

void pitAddTask(pitTask task)
{
	if(taskNum == 10)
		return; // can't add new task
	tasks[taskNum++] = task;
}
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Problem with software interrupts and IRQs

Post by Combuster »

I don't buy your "complete rewrite" as the first bug I mentioned is still present in this code.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: Problem with software interrupts and IRQs

Post by kubawal »

Combuster wrote:the first bug I mentioned is still present in this code
Is that what you mean?
Combuster wrote:(count the instructions to each of the PIC chips)
I don't understand what do you mean. In this code I send messgaes to both PICs...

I try to use another code for PIC remap ( http://www.osdever.net/tutorials/view/b ... t-tutorial ) but it also not works.
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: Problem with software interrupts and IRQs

Post by kubawal »

Can someone to explain this?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Problem with software interrupts and IRQs

Post by Combuster »

I also said you were bad at copy-pasting.
count the instructions to each of the PIC chips
Did you do this for the original version and your version yet?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: Problem with software interrupts and IRQs

Post by kubawal »

Combuster wrote:I also said you were bad at copy-pasting.
No, I'm simply not very good in english :)
What do you mean in 'count the instructions'?
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: Problem with software interrupts and IRQs

Post by kubawal »

kubawal wrote:Can someone to explain this?
Post Reply