Keyboard handler working, IRQ not firing

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
synthetix
Posts: 15
Joined: Sun Jan 28, 2007 8:45 am
Location: Somewhere in the infinite dimension universe that my vast imagination is.

Keyboard handler working, IRQ not firing

Post by synthetix »

I'm in the early stage (0.1alpha) of the development of my OS, a microkernel axed
on modularity and extendability (the first full release should be 0.3beta. Up to now, it looks more like a monolithic kernel, for the development and the function testing phase).

So far, I've got IDT, GDT, exceptions, IRQs, and the PIT working. However, I now have the following problem: the keyboard won't work. I believe in an IRQ firing or dispatching problem, as calling the function manually shows it works.

Here is the code for the keyboard:

Code: Select all

/* Keyboard base driver */

#include <CoreKernel/SystemMgr-ck/SystemMgr-ck.h>
#include <SysCore/SC_io.h>
#include "KeyboardBase.h"
#include "KeyboardUSMap.h"
#include <libSystem/TermPCCons/TermPCCons.h>


unsigned char KbdStatus = 0;

void InputKbdIRQInstall() {
	TermTextPrint("\t* Input manager: Installing keyboard handler\n",WHITE,BLACK);
	SysIRQHandlerRegister(1,InputKbdIRQHandler);
} 

void InputKbdIRQHandler(struct SSSysRegs_s *dummyp) {
	unsigned char KbdScancode = 0;
	TermTextPrint("* Input manager/Keyboard: Acquiring scancode\n", WHITE,BLACK);
	KbdScancode = SC_IOPortRead(0x60);
	if (KbdScancode & 0x80) {
		switch (BaseKbdMap[KbdScancode]) {
				case 160:
					KbdStatus - 128;
					break;
				case 161:
					KbdStatus - 64;
					break;
			}
	}
	else {
		TermTextPrint("* Input manager/Keyboard: Checking for special scancodes\n",WHITE,BLACK);
		if ((BaseKbdMap[KbdScancode] >= 160) && (BaseKbdMap[KbdScancode] <= 168)) {
			switch (BaseKbdMap[KbdScancode]) {
				case 160: // Shift
					KbdStatus | 128;
					break;
				case 161: // Alt
					KbdStatus | 64;
					break;
			}
		}
		else {
			TermTextPrint("Printing key on terminal\n",WHITE,BLACK);
			if (KbdStatus & 0x80) {
				TermCharPut(BaseKbdShiftMap[KbdScancode],WHITE,BLACK);
			}
			else {
				TermCharPut(BaseKbdMap[KbdScancode],WHITE,BLACK);
			}
		}
	}
}
KeyboardBase.h:

Code: Select all

/* Keyboard base driver header */

extern void InputKbdIRQInstall(void);
extern void InputKbdIRQHandler(struct SSSysRegs_s *dummyp);
SystemMgrIRQ.c:

Code: Select all

/* System manager IRQ routines */

#include "SystemMgr-ck.h" 
#include <SysCore/SC_io.h>


void *SysIRQHandler[16] = {
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0
};

void SysIRQHandlerRegister(unsigned char IntNum, void (*IRQHandler)(struct SSSysRegs_s *regsp)) {
SysIRQHandler[IntNum] = IRQHandler;
}

void SysIRQHandlerUnregister(unsigned char IntNum) {
SysIRQHandler[IntNum] = 0;
}

void SysIRQRemap() {

SC_IOPortWrite(0x20, 0x11);
SC_IOPortWrite(0xA0, 0x11);
SC_IOPortWrite(0x21, 0x20);
SC_IOPortWrite(0xA1, 0x28);
SC_IOPortWrite(0x21, 0x04);
SC_IOPortWrite(0xA1, 0x02);
SC_IOPortWrite(0x21, 0x01);
SC_IOPortWrite(0xA1, 0x01);
SC_IOPortWrite(0x21, 0x0);
SC_IOPortWrite(0xA1, 0x0);
}

void SysIRQInstall() {

SysIRQRemap();
SysIDTEntrySet(32, (unsigned)SysIRQ0, 0x08, 0);
SysIDTEntrySet(33, (unsigned)SysIRQ1, 0x08, 0);
SysIDTEntrySet(34, (unsigned)SysIRQ2, 0x08, 0);
SysIDTEntrySet(35, (unsigned)SysIRQ3, 0x08, 0);
SysIDTEntrySet(36, (unsigned)SysIRQ4, 0x08, 0);
SysIDTEntrySet(37, (unsigned)SysIRQ5, 0x08, 0);
SysIDTEntrySet(38, (unsigned)SysIRQ6, 0x08, 0);
SysIDTEntrySet(39, (unsigned)SysIRQ7, 0x08, 0);
SysIDTEntrySet(40, (unsigned)SysIRQ8, 0x08, 0);
SysIDTEntrySet(41, (unsigned)SysIRQ9, 0x08, 0);
SysIDTEntrySet(42, (unsigned)SysIRQ10, 0x08, 0);
SysIDTEntrySet(43, (unsigned)SysIRQ11, 0x08, 0);
SysIDTEntrySet(44, (unsigned)SysIRQ12, 0x08, 0);
SysIDTEntrySet(45, (unsigned)SysIRQ13, 0x08, 0);
SysIDTEntrySet(46, (unsigned)SysIRQ14, 0x08, 0);
SysIDTEntrySet(47, (unsigned)SysIRQ15, 0x08, 0);
}

void SysIRQDispatcher(struct SSSysRegs_s *regsp) {

void (*CurrentIRQHandler)(struct SSSysRegs_s *regsp);

CurrentIRQHandler = SysIRQHandler[(regsp->int_no - 32)];

if (CurrentIRQHandler) {
	CurrentIRQHandler(regsp);
}

if ((regsp->int_no >= 40) && (regsp->int_no <= 47)) {
	SC_IOPortWrite(0xA0,0x20);
}

SC_IOPortWrite(0x20,0x20);
}

SC_io.c:

Code: Select all

/* SC_IO.c */

unsigned char SC_IOPortRead(unsigned short port) {
    unsigned char rv;
    __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (port));
    return rv;
}

void SC_IOPortWrite(unsigned short port, unsigned char value) {
__asm__ __volatile__ ("outb %1, %0" : : "dN" (port), "a" (value));
}
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Post by mathematician »

One thing I notice is that there does not seem to be an assembly language IRET instruction worked into the C source code anywhere. What comes of trying to write isr's in C I suppose.
Otter
Member
Member
Posts: 75
Joined: Sun Dec 31, 2006 11:56 am
Location: Germany

Post by Otter »

Well, his code is not complete 'cause for example the source for SysIRQ0 is missing. I think it's in an extern assembler module, calls SysIRQDispatcher and then it uses the iret-instruction.

I admit that I've not readed your code completely but I don't see that you enable the keyboard irq. You have to unmask the irq.

[edit]
try this at the end of InputKbdIRQInstalll:

Code: Select all

SC_IOPortWrite(0x21, 0xFD); // 0xFD = 11111101b ( mask all except irq 1)
[/edit]
synthetix
Posts: 15
Joined: Sun Jan 28, 2007 8:45 am
Location: Somewhere in the infinite dimension universe that my vast imagination is.

Post by synthetix »

mathematician, I forgot to say that my IRQ stubs are in assembly
Otter, I tried your piece of code, and it did not work.

I attached an archive with my os files: just use ./syscompile (bash) to compile things and get a new system.bin

I use GRUB as bootloader
Attachments
SyntheSys.tar.bz2
(9.96 KiB) Downloaded 37 times
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

You say that your IRQ stubs are in assembly. In my OS, the IRQ stubs call a special handler (_irq_handler) after pushing their IRQ number onto the stack. _irq_handler is a C function (irq_handler) that then takes this number and executes the necessary function (ie. irq_list[irq_num](regs)). Once this finishes, it returns back to the IRQ handler which then returns to the assembly code where the iret instruction is called.

I hope this helps.
Otter
Member
Member
Posts: 75
Joined: Sun Dec 31, 2006 11:56 am
Location: Germany

Post by Otter »

Well ...
I looked through your code, played a bit with it, that's what I've found out so far:
1) You don't need the "cli" in SysIRQ0, SysIRQ1 and so on ... you should not do that.
2) Your IRQs DO fire, SysIRQ1 is called whenever you press a key.
3) The "push byte 1", you should use "push dword 1"
Your dispatcher don't work. I did not find the exact error yet cause I've no time any more but I think that should help. Maybe I look at it later.
synthetix
Posts: 15
Joined: Sun Jan 28, 2007 8:45 am
Location: Somewhere in the infinite dimension universe that my vast imagination is.

All IRQs working

Post by synthetix »

Thanks Otter, fixing things and sending back new infos.

I'll try to check the dispatcher, but what buzzes me is that the PIT works perfectly.

edit:

I checked the dispatcher and it's ok. The error is in bootpm.S
When the SysIRQ* fires, it pushes it's interrupt number as the error code.

The keyboard now works !

Thanks Otter, mathematician and pcmattman. I'll mention your names in the big help mention of my (future) credits file.
Post Reply