Page 1 of 1

Programming the Floppy Disk Controller

Posted: Fri Apr 04, 2008 10:36 am
by AlfaOmega08
I've just finished to program my fdc driver.
When I've tested it, it has worked on bochs (and I started jumping for the happiness), then on VMWare.

Here's the problem.
On VMWare it's like the interrupt never arrives. This happends on Resetting the fdc:

Code: Select all

void Floppy::Reset(Bit32u base, char drive) {
	outportb(base + FLOPPY_DOR, 0x00, true);	//Disable the controller
	outportb(base + FLOPPY_RSR, 0x00, true);	//Rate: 500Kb/s
	outportb(base + FLOPPY_DOR, 0x0C, true);	//Enable the controller

	cpu.waitForInterrupt(38);  //IT FREEZES HERE!!!

	{
		int st0, cyl;
		CheckInterrupt(base, &st0, &cyl);
	}

	outportb(base + FLOPPY_CCR, 0x00, true);
	ConfigureDrive(base);
	CalibrateDrive(base, drive);
}
the "true" at the end of some outportb stands for "inportb(80)" so there is a little delay...

Does anyone know why it doesn't work?

Thanks

Posted: Fri Apr 04, 2008 1:35 pm
by AJ
Hi,

Is the interrupt on the VM happening so fast that it happens before you get to:

Code: Select all

cpu.waitForInterrupt(38);



I have had a similar problem in a virtual environment before, where the hardware fires the interrupt instantaneously.

Cheers,
Adam

Posted: Fri Apr 04, 2008 1:47 pm
by lukem95
have the ISR print a message, so you know its worked

Posted: Fri Apr 04, 2008 10:10 pm
by Ready4Dis
And, you could also implement a timeout, so when you are waiting it will return (and not just freeze), but displaying something to screen in the interrupt (Even if it's just writing a byte to the screen directly) will help determine if this is indeed your problem. Typically when I am waiting for an interrupt, I set the waiting flag BEFORE I send the command to the periferal, that way when I call my wait for interrupt, if the interrupt happens before my call to wait, the flag saying that it has triggered is already set and it immediately returns. Much nicer than missing interrupts and waiting for a timeout, then checking status to see what happened. So, it'd go something like this:

Code: Select all

volatile u32 IntTriggered[256]; //For interrupts

void Int38(void)
{
  IntTriggered[38] = 1;
}

void SetupIntWait(u32 which)
{
 IntTriggered[which] = 0;
}

u8 WaitInt(u32 which, u64 Timeout)
{
 Timeout+= GetCurrentMS();
  while (!IntTriggered[which] && Timeout > GetCurrentMS());
  return IntTriggered; //Return our status 1 = int triggered, 0 = timeout
}

void Floppy::Reset(Bit32u base, char drive) {
/* New */
   SetupIntWait(38);

   outportb(base + FLOPPY_DOR, 0x00, true);   //Disable the controller 
   outportb(base + FLOPPY_RSR, 0x00, true);   //Rate: 500Kb/s 
   outportb(base + FLOPPY_DOR, 0x0C, true);   //Enable the controller 

/* New */
   if (WaitInt(38,1000)) //Up to 1 second (1,000 ms)
   { 
      int st0, cyl; 
      CheckInterrupt(base, &st0, &cyl); 
   }
   else //Interrupt never fired, and timed out... problems
   {
      return; //Possibly an error code, or print to screen here!
   }

   outportb(base + FLOPPY_CCR, 0x00, true); 
   ConfigureDrive(base); 
   CalibrateDrive(base, drive); 
}