For some reason, IRQ 6 never hits in my Qemu, Bochs, VMWare, or VirtualBox emulators. Do I need some type of virtual Floppy Drive or something? Here is my IRq6 handler:
void i86_flpy_irq (struct regs *r) {
//! irq fired
_FloppyDiskIRQ = 1;
printf("IRQ 6 HIT");
}
It never says "IRQ 6 HIT", and not only that, in my install function for my irq6 where I call in kernel:
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);
}
As you can see, I call a function that resets the Floppy Drive controller. Let's look at that function:
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 );
}
You can see above, I wait for an IRQ to finish by checking if _FloppyDiskIRQ
is 1, which I set when it hits. I have also taken note of this common bug. The code never passes that while()
loop since an IRQ6 never fires. Is there a reason for this? How do I fix it so an IRQ 6 can fire? I'm thinking I have to add something to my emulator (like I added a virtual hard drive for my ATA controller).
I also tested by printing the IRQ's that fire which are only 0,1,12 as of now (no 6) ...
extern "C" void irq_handler(struct regs *r)
{
/* This is a blank function pointer */
regs_func handler;
/* Find out if we have a custom handler to run for this
* IRQ, and then finally, run it */
handler = irq_routines[r->int_no];
if (handler)
{
handler(r);
}
printf("%d,",r->int_no);
//irq_taskmanager->Schedule((CPUState*)r);
/* If the IDT entry that was invoked was greater than 40
* (meaning IRQ8 - 15), then we need to send an EOI to
* the slave controller */
if (r->int_no >= 8)
{
p8b_irq.out(0x20,0xA0);
}
/* In either case, we need to send an EOI to the master
* interrupt controller too */
p8b_irq.out(0x20, 0x20);
}
Full source code: https://github.com/amanuel2/OS_MIRROR