I have just finished initializing the IDT and started the ps2 stuff. I got the ps2 controller initializer and now I want to enable the interrupts in the first ps2 port or the keyboard. Here is my code for initializing the ps2 controller:
uint8_t initPS2()
{
// Start by disabling devices
disableFirstPS2Port();
disableSecondPS2Port();
// Flush the input buffer
inb(PS2DATA);
// Set the state of the status register.
outb(PS2COMMAND, 0x20);
uint8_t status = inb(PS2DATA);
uint8_t dual0 = status & 0b00100000 == 0b00100000; // if dual = 0, there is no second channel
status |= 0b01000011;
outb(PS2COMMAND, 0x60);
outb(PS2DATA, status);
// Perform self test
outb(PS2COMMAND, 0xAA);
uint8_t response = inb(PS2DATA);
if (response == 0xFC)
return 0xFC;
outb(PS2COMMAND, 0x60);
outb(PS2DATA, status);
// test dual channel controller
uint8_t dual = 0xFF;
if (dual0 == 1)
{
outb(PS2COMMAND, 0xAE);
outb(PS2COMMAND, 0x20);
status = inb(PS2DATA);
uint8_t dual1 = status & 0b00100000 == 0b00100000;
// if dual1 == 0, dual channel exists
outb(PS2COMMAND, 0xAD);
dual = !dual1;
}
else
{
dual = 0;
}
// Perform interface tests
outb(PS2COMMAND, 0xAB);
uint8_t responseIT1 = inb(PS2DATA);
uint8_t responseIT2;
if (dual == 1)
{
outb(PS2COMMAND, 0xA9);
responseIT2 = inb(PS2DATA);
}
if (responseIT1 != 0x0)
return responseIT1;
if (responseIT2 != 0x0 && dual == 1)
return responseIT2;
// Enable devices
enableFirstPS2Port();
if (dual == 1)
enableSecondPS2Port();
writeToFirstPS2Port(0xFF);
response = readPS2DataPort();
if (response == 0xFC)
return 0xFC;
writeToSecondPS2Port(0xFF);
response = readPS2DataPort();
if (response == 0xFC)
return 0xFC;
return 0;
}
I follow the tutorial on OSDev wiki for initializing the ps2 controller.
Now I try to enable scanning on the keyboard with the 0xf4 command:
uint8_t commandKeyboard(unsigned char byt)
{
writeToFirstPS2Port(byt);
uint8_t response = readPS2DataPort();
if (response == 0xFE)
{
writeToFirstPS2Port(byt);
response = readPS2DataPort();
if (response == 0xFE)
{
writeToFirstPS2Port(byt);
response = readPS2DataPort();
}
}
return response;
}
uint8_t initKeyboard()
{
uint8_t res = commandKeyboard(0xF4);
return res;
}
Note that the writeToFirstPS2Port
and likewise other ps2 function do have a proper controllerWait function which makes sure that the data port is writable/readable.
I call this code before doing sti
after I load my idt:
idt_flush(¤tIDT);
uint8_t ps2init = initPS2();
printk("PS2 Initalized, returned with 0x%x\n", ps2init);
while (1)
;
uint8_t keyboardinit = initKeyboard();
printk("PS2 Initalized, returned with 0x%x\n", keyboardinit);
outb(PIC1_DATA, 0);
outb(PIC2_DATA, 0);
//int d = 5 / 0;
asm volatile("sti");
Also here is my IRQ Handler:
void irq1_handler(interrupt_frame_t *frame)
{
inb(0x60);
default_irq_handler(frame);
}
I think the keyboard controller required for me to read 0x60 port before sending another interrupt so I thought that may help.
With this code here is what happens. I successfully initialize the IDT and then call the initializePS2 which returns with 0, meaning it succeeded. After that I start the initKeyboard call which doesn't even return let alone succeed. When I send the command to the keyboard, the system crashes. I am running this using qemu and I first thought this was a triple fault so I added -d int
to see what kind of exceptions were raised but it seems that no exception is raised before the system closes itself.
Here is the github link to the project:
https://github.com/Danyy427/NEWOSDEV/tree/master/new%2064%20bit
The files are under src/Kernel/Hardware/PS2 and .../Hardware/Keyboard
The IDT is under src/Kernel/IDT
Any help is appreciated. Thank you.