【问题标题】:Sending enable interrupts (0xF4) command to ps2 keyboard results in system crash. OSDEV向 ps2 键盘发送启用中断 (0xF4) 命令会导致系统崩溃。操作系统开发
【发布时间】:2021-11-02 15:07:41
【问题描述】:

我刚刚完成了 IDT 的初始化并开始了 ps2 的工作。我得到了 ps2 控制器初始化程序,现在我想在第一个 ps2 端口或键盘中启用中断。这是我初始化 ps2 控制器的代码:


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;
}

我按照 OSDev wiki 上的教程来初始化 ps2 控制器。

现在我尝试使用 0xf4 命令在键盘上启用扫描:

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;
}

请注意,writeToFirstPS2Port 和其他 ps2 函数确实具有适当的 controllerWait 函数,可确保数据端口是可写/可读的。

我在加载我的 idt 之后执行 sti 之前调用此代码:

    idt_flush(&currentIDT);

    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");

这也是我的 IRQ 处理程序:

void irq1_handler(interrupt_frame_t *frame)
{
    inb(0x60);
    default_irq_handler(frame);
}

我认为键盘控制器需要我在发送另一个中断之前读取 0x60 端口,所以我认为这可能会有所帮助。

使用这段代码会发生什么。我成功初始化了IDT,然后调用了initializePS2,它返回0,表示它成功了。之后,我开始了 initKeyboard 调用,它甚至不返回,更不用说成功了。当我将命令发送到键盘时,系统崩溃了。我正在使用 qemu 运行它,我首先认为这是一个三重错误,所以我添加了 -d int 以查看引发了哪些异常,但在系统自行关闭之前似乎没有引发异常。

这里是项目的github链接:

https://github.com/Danyy427/NEWOSDEV/tree/master/new%2064%20bit

文件位于 src/Kernel/Hardware/PS2 和 .../Hardware/Keyboard

IDT 在 src/Kernel/IDT 下

感谢任何帮助。谢谢。

【问题讨论】:

  • 如果您还没有,使用 -no-reboot-no-shutdown 选项运行 qemu 可能会有所帮助,这样您就可以使用 gdb 或qemu 监视器(例如-monitor stdio)。
  • @sj95126 哦抱歉忘了提。我确实使用-no-reboot 运行它,这就是我了解到-d int 没有任何例外。我不知道-no-shutdown

标签: c osdev ps2


【解决方案1】:

首先在您的中断处理程序上添加中断属性:

 void __attribute__((interrupt)) Irq1Handler(interrupt_frame* frame);

这将导致编译器从堆栈中获取参数,而不是使用 __cdecl 调用约定获取它们。并且还执行 iret(中断返回)而不是正常的 ret(返回)。在编译中断文件“-mgeneral-regs-only”时,还要向 gcc 添加一个参数。这将阻止编译器使用 sse 寄存器并生成警告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 2019-08-10
    • 2017-11-05
    • 2021-10-24
    • 2019-07-12
    • 2013-04-01
    • 2012-03-19
    相关资源
    最近更新 更多