I am learning to develop a small os, it now can initialise GDT, IDT, display some text at screen, I am now trying to get keyboard interrupt, the example code I got from 30days diy OS by OSASK on day6 harib03e works. But my implementation not working, source code is at https://github.com/Lewis-Liu-1/myos/tree/main/day6/daye.
From web search, I realise I only load GDT, IDT, load kernel, not configuring keyboard, to enable PS/2 interrupt somehow. But I don't know how to do that.
my keyboard interrupt not working when run with qemu
Re: my keyboard interrupt not working when run with qemu
I guess you have remapped the pic right ?
The wiki has the answers, however here is the code to unmask keyboard interrupts :
To handle the interrupt, you must first read the keypress value from the 0x60 port : "inb 0x60".
When you are about to return from the interrupt you must signal EOI to the pic (End of interrupt) to the master, call this function at the end :
The wiki has the answers, however here is the code to unmask keyboard interrupts :
Code: Select all
#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 init_ps2_keyboard(){
OutPortB(PIC1_DATA,0b11111000);
OutPortB(PIC2_DATA,0b11101111);
}
When you are about to return from the interrupt you must signal EOI to the pic (End of interrupt) to the master, call this function at the end :
Code: Select all
void pic_end_master(){
OutPortB(PIC1_COMMAND,PIC_EOI);
}
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: my keyboard interrupt not working when run with qemu
When you initialize the IDT, you also initialize the PIC. Initializing the PIC causes the PIC to lose any pending interrupts. If there is a pending PS/2 interrupt when you initialize the PIC, the PS/2 controller will be waiting for you to acknowledge the interrupt by reading port 0x60, but the PIC won't deliver the interrupt.yyiu002 wrote:From web search, I realise I only load GDT, IDT, load kernel, not configuring keyboard, to enable PS/2 interrupt somehow. But I don't know how to do that.
Try reading port 0x60 after you initialize the PIC.
The PIC has an auto-EOI mode.devc1 wrote:When you are about to return from the interrupt you must signal EOI to the pic
Re: my keyboard interrupt not working when run with qemu
Thanks all for your help.
I tried not initialise GDT, seems working, like following:
initialise GDT will set code and data to new location, does it mean I have to move code to those location, before initialise IDT?
I also saw following code:
previous pat is "1*8", this time selector is "2*8", why?
I tried not initialise GDT, seems working, like following:
Code: Select all
#define ADR_IDT 0x0026f800
#define LIMIT_IDT 0x000007ff
#define ADR_GDT 0x00270000
#define LIMIT_GDT 0x0000ffff
#define ADR_BOTPAK 0x00280000
#define LIMIT_BOTPAK 0x0007ffff
#define AR_DATA32_RW 0x4092
#define AR_CODE32_ER 0x409a
#define AR_INTGATE32 0x008e
void init_gdt_idt(void)
{
struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) ADR_IDT;
int i;
#if 0
for (i = 0; i <= LIMIT_GDT / 8; i++) {
set_segmdesc(gdt + i, 0, 0, 0);
}
set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, AR_DATA32_RW);
set_segmdesc(gdt + 2, LIMIT_BOTPAK, ADR_BOTPAK, AR_CODE32_ER);
load_gdtr(LIMIT_GDT, ADR_GDT);
#endif
/* IDT�̏����� */
for (i = 0; i <= LIMIT_IDT / 8; i++) {
set_gatedesc(idt + i, 0, 0, 0);
}
load_idtr2(LIMIT_IDT, ADR_IDT);
set_gatedesc(idt + 0x21, (int) asm_inthandler21, 1 * 8, AR_INTGATE32);
set_gatedesc(idt + 0x27, (int) asm_inthandler27, 1 * 8, AR_INTGATE32);
set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 1 * 8, AR_INTGATE32);
initialize_pic();
io_sti();
}
I also saw following code:
Code: Select all
set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32);
set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);
Re: my keyboard interrupt not working when run with qemu
Continue my question.
at entry.S I have a called LGDT instruction, which loads GDT tables etc. Therefore at above function init_gdt_idt, initialise GDT is not necessary anymore.
Initialise GDT twice will cause issues, why?
at entry.S I have a called LGDT instruction, which loads GDT tables etc. Therefore at above function init_gdt_idt, initialise GDT is not necessary anymore.
Initialise GDT twice will cause issues, why?
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: my keyboard interrupt not working when run with qemu
You should set the base to 0 and the limit to 0xFFFFFFFF for your code and data segments.yyiu002 wrote:initialise GDT will set code and data to new location, does it mean I have to move code to those location, before initialise IDT?
That's the code segment selector. The correct selector depends on where you put the code segment in your GDT.yyiu002 wrote:previous pat is "1*8", this time selector is "2*8", why?
You didn't set the base to 0 and the limit to 0xFFFFFFFF.yyiu002 wrote:Initialise GDT twice will cause issues, why?