X86 IRQ 6软盘控制器中断未触发

X86 IRQ 6软盘控制器中断未触发,x86,g++,osdev,irq,floppy,X86,G++,Osdev,Irq,Floppy,出于某种原因,IRQ 6在我的Qemu、Bochs、VMWare或VirtualBox模拟器中从未出现过。我需要某种类型的虚拟软驱还是什么?以下是我的IRq6处理程序: void i86_flpy_irq (struct regs *r) { //! irq fired _FloppyDiskIRQ = 1; printf("IRQ 6 HIT"); } 它从来没有说“irq6命中”,不仅如此,在我为irq6安装的函数中,我在内核中调用: void flpydsk_i

出于某种原因,IRQ 6在我的Qemu、Bochs、VMWare或VirtualBox模拟器中从未出现过。我需要某种类型的虚拟软驱还是什么?以下是我的IRq6处理程序:

void  i86_flpy_irq (struct regs *r) {
    //! irq fired
    _FloppyDiskIRQ = 1;
    printf("IRQ 6 HIT");
}
它从来没有说“irq6命中”,不仅如此,在我为irq6安装的函数中,我在内核中调用:

void flpydsk_install (int irq) {

    //! install irq handler
    install_handler_irq (irq, i86_flpy_irq);

    //! initialize the DMA for FDC
    flpydsk_initialize_dma ();

    //! reset the fdc
    flpydsk_reset ();

    //! set drive information
    //flpydsk_drive_data (13, 1, 0xf, true);
}
如您所见,我调用了一个函数来重置软驱控制器。让我们看看这个函数:

void flpydsk_reset () {

    uint32_t st0, cyl;
    _FloppyDiskIRQ = 0;
    //! reset the controller
    flpydsk_disable_controller ();
    flpydsk_enable_controller ();
    //flpydsk_wait_irq ();
    printf("STARTED WAITING");
    while(_FloppyDiskIRQ == 0);
        _FloppyDiskIRQ = 0;
    printf("ENDED WAITING FOR IRQ");

    //! send CHECK_INT/SENSE INTERRUPT command to all drives
    for (int i=0; i<4; i++)
        flpydsk_check_int (&st0,&cyl);

    //! transfer speed 500kb/s
    flpydsk_write_ccr (0);

    //! pass mechanical drive info. steprate=3ms, unload time=240ms, load time=16ms
    flpydsk_drive_data (3,16,240,true);

    //! calibrate the disk
    flpydsk_calibrate ( _CurrentDrive );
}

完整源代码:

问题与您显示的代码无关。如果您使用QEMU和GDB来调试或使用其内部调试器进行BOCHS调试,并允许代码一直运行到无限循环,那么您可能会发现问题的根本原因是什么

主要的问题不是虚拟或真实的硬件有缺陷。你的内核有一个bug。如果您已为硬件设备(本例中为软盘控制器)正确启用IRQ,但未获得预期中断,则可能存在以下情况:

  • 您将错误的中断处理程序连接到IRQ
  • 您尚未启用您在PIC上期望的IRQ
  • 您尚未在CPU上启用中断
  • 在设备(软盘控制器)上启用中断的代码不正确
调试器会告诉您的关键信息是,在达到
flpydsk_reset
时,EFLAGS中的中断启用标志已清除。这意味着CPU不接受外部中断。如果不小心关闭了中断启用标志,或者您从未将其打开,则会发生这种情况

第二,您是否注意到,在等待软盘中断时,您的鼠标指针没有移动,计时器也没有更新?这与软盘中断(IRQ 6)没有被触发的原因相同

快速浏览一下
kernel.c++
文件就会发现问题:

   isr.install_isrs();
   irq.install_irqs();
   Timer timer;
   timer.install_timer();
   KBD kbd;

   kbd.install_kbd_driver();

   MOUSE mouse;
   mouse.install_mouse_driver();

   flpydsk_install(6);
   __asm__ __volatile__ ("sti");
您安装了许多驱动程序(键盘/鼠标等),但在到达此代码段之前CPU收到CLI指令的状态下启动。您的
flpydisk\u install
功能最终要求启用中断,但在调用
flpydisk\u install
后,您发出STI指令。在您在
flpydsk_reset
之前发出STI之前,您将一直处于无限循环中,等待不会发生的中断

一个快速修复方法是执行
\uuuuuasm\uuuuuuuuuuuuuuuuuuuvolatile\uuuuuuuuu(“sti”)flpydsk\u install
前的code>。我可能会对8259A PIC上的中断进行编码,因为每个需要中断的设备都需要中断

带有快速修复的修订代码如下所示:

   isr.install_isrs();
   irq.install_irqs();
   Timer timer;
   timer.install_timer();
   KBD kbd;

   kbd.install_kbd_driver();

   MOUSE mouse;
   mouse.install_mouse_driver();

   __asm__ __volatile__ ("sti");
   flpydsk_install(6);
既然STI启用了对CPU的中断,那么应该触发IRQ6及其中断处理程序,从而允许
flpydsk_reset
退出其循环


虚拟盒软盘控制器 一旦您使用STI启用CPU中断,VirtualBox将要求您向虚拟机添加软盘控制器。您不一定需要虚拟软盘,至少需要软盘控制器。如果没有虚拟软盘控制器,通过端口向不存在的硬件发送命令将无法启用IRQ6

我相信默认情况下,BOCHS和QEMU将模拟软盘控制器,即使虚拟机中没有安装虚拟软盘


使用内核设置QEMU调试 由于您的文件
BoneOS.bin
构建为ELF可执行文件,并且由于您的代码不会在模式(实模式或64位长模式)之间切换,因此设置调试相当容易。您的
Makefile
有一个用于QEMU的
start debug
配方。我已将其修改为以下内容:

start-debug:
        qemu-system-i386 -S -s -kernel BoneOS.bin -m 1G -serial file:qemu-serial.log \
            -serial stdio -usb -device usb-host,hostbus=2,hostaddr=1 -no-reboot &
        gdb BoneOS.bin \
            -ex 'target remote localhost:1234' \
            -ex 'break kernelMain' \
            -ex 'layout src' \
            -ex 'layout reg' \
            -ex 'continue'
第一个QEMU命令设置QEMU在启动时停止,并等待与GDB的远程连接。第二个命令将GDB连接到QEMU,在<代码> KelnMeNe/code >(主C++入口点到您的代码)上中断,显示源代码和寄存器。调试符号来自
BoneOS.bin

从那时起,您可以查看有关实际使用GDB调试器的一般教程

如果已安装DDD包,则可以使用图形调试器。它可以通过以下方式启动:

start-debug:
        qemu-system-i386 -S -s -kernel BoneOS.bin -m 1G -serial file:qemu-serial.log \
            -serial stdio -usb -device usb-host,hostbus=2,hostaddr=1 -no-reboot &
        ddd BoneOS.bin \
            --eval-command="target remote localhost:1234" \
            --eval-command="break kernelMain"

通过调整Codeblocks项目的调试器选项,可以使用Codeblocks进行远程QEMU调试。

我也面临同样的问题。我通过在每次中断服务执行后重新映射/重新初始化PIC来解决这个问题。 我认为这是一个糟糕的解决方案,但目前它起了作用。 我的问题是,我在键盘中断后调用软盘读取例程,而没有向PIC发送EOI(中断结束)命令。 因此,在调用软盘读取例程之前发送EOI解决了这个问题。
您是否找到了更好的解决方案?

针对否定此问题并以不清楚为由结束此问题的人?这怎么不清楚?很明显,我在问为什么
IRQ6从不触发,我该如何修复?
它怎么能比这更清晰?Stackoverflow不是我以前试过指出的调试服务。@MichaelPetch我从来没有要求调试。。我只是问我需要在我的虚拟机中启用什么才能启动IRQ 6。。如果这不是一个有效的问题,为什么还要先使用osdev标签呢?这对我来说是一个100%的好问题。@MichaelPetch我已经在那里看了一百万遍了times@MichaelPetch哦,是的,我忘了接受anwser。。真的,谢谢。我现在在做文件管理。。完全是我自己的计划。大部分时间我都在聊天室,如果你想在聊天室聊天,请随意;)对不起,我刚来。。看到你的回答。。。谢谢你终于意识到这是一个好问题。我稍后会回到这个答案上来和你谈谈。。我要参加toMichael的考试Bochs上是否有调试文件或任何对osdev有好处的调试器?(请不要客气
start-debug:
        qemu-system-i386 -S -s -kernel BoneOS.bin -m 1G -serial file:qemu-serial.log \
            -serial stdio -usb -device usb-host,hostbus=2,hostaddr=1 -no-reboot &
        ddd BoneOS.bin \
            --eval-command="target remote localhost:1234" \
            --eval-command="break kernelMain"