My FDC driver wont send me an interrupt

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

My FDC driver wont send me an interrupt

Post by lukem95 »

I have tried implementing a decent FDC driver using the resources on the wiki (mainly mystrans tutorial).

But i can't even reset the FDC as it wont send an interrupt, i even waited 10 minutes for one (whilst doing something else... im not THAT sad).

Code: Select all


static volatile int floppy_base = 0x03f0;
static volatile int floppy_number_drives;
static volatile int floppy_recieved_int = 1;
static volatile int floppy_motor_ticks = 0;
static volatile int floppy_motor_state = 0; 

//Floppy Registers
enum floppy_registers {
   FLOPPY_DOR  = 2,  // digital output register
   FLOPPY_MSR  = 4,  // master status register, read only
   FLOPPY_FIFO = 5,  // data FIFO, in DMA operation for commands
   FLOPPY_CCR  = 7   // configuration control register, write only
}; 

//Floppy Commands
enum floppy_commands {
   FLOPPY_CMD_SPECIFY = 3,            // SPECIFY
   FLOPPY_CMD_WRITE_DATA = 5,         // WRITE DATA
   FLOPPY_CMD_READ_DATA = 6,          // READ DATA
   FLOPPY_CMD_RECALIBRATE = 7,        // RECALIBRATE
   FLOPPY_CMD_SENSE_INTERRUPT = 8,    // SENSE INTERRUPT
   FLOPPY_CMD_SEEK = 15,              // SEEK
}; 

//Floppy Motor States
enum { floppy_motor_off = 0, floppy_motor_on, floppy_motor_wait }; 

int initialise_floppy_driver()
{
      outb(0x70, 0x10);
      unsigned char drives = inb(0x71);
      int a,b;
      a = drives >> 4;
      b = drives & 0xf;
      
      //Check how many floppy drives are installed
      if(a != 4)
      //None. dont waste our time
           return 1;
      if(b != 4)
           floppy_number_drives = 1;
      else
           floppy_number_drives = 2;
           
      kprintf("We got %d Floppy(s)!\n",floppy_number_drives);
      
      //Init to primary floppy
      floppy_base = 0x03f0;
      
      register_interrupt_handler(6, &floppy_handler);
      kprintf("IRQ6 set up\n");

      floppy_reset(floppy_base);
      
      return 0;
}

void floppy_wait_for_interrupt()
{
     floppy_recieved_int = 1;
     while(floppy_recieved_int);
     return;
}



int floppy_reset(int base) 
{
    outb((base + FLOPPY_DOR), 0x00); // disable controller
    timer_wait(2);                   // 20 microsecond wait
    outb((base + FLOPPY_DOR), 0x0C); // enable controller
    
    kprintf("waiting for interrupt..\n");
    floppy_wait_for_interrupt(); // sleep until interrupt occurs
    kprintf("we g0tz in interrupt from FDC.\n");
    
    int st0, cyl; // These value must be read, but can be ignored
    floppy_check_interrupt(base, &st0, &cyl);
    
    // set transfer speed 500kb/s
    outb((base + FLOPPY_CCR), 0x00);

    // These value are for 1.44mb floppy
    floppy_write_cmd(base, FLOPPY_CMD_SPECIFY);
    floppy_write_cmd(base, 0xdf); /* steprate = 3ms, unload time = 240ms */
    floppy_write_cmd(base, 0x02); /* load time = 16ms, no-DMA = 0 */

    // This is incase of failure
    kprintf("lets calibrate the FDC\n");
    if(floppy_calibrate(base)) return -1;
    kprintf("braaap\n");
    return 0;
}

... The rest of the code is the same
sorry about the length of that snippet, most of the code is the same as in the tutorial, but i thought it would be easier all in one place, rather than having to check back all the time.

the random kprintf's are to see where the code gets to.

it just waits for the interrupt and it never arrives =\

oh... i also get

Code: Select all

00017031251d[FDD  ] write access to port 03f2, value=00
00017031251d[FDD  ] DMA and interrupt capabilities disabled
00017031251d[FDD  ] io_write: digital output register
00017031251d[FDD  ]   motor on, drive1 = 0
00017031251d[FDD  ]   motor on, drive0 = 0
00017031251d[FDD  ]   dma_and_interrupt_enable=00
00017031251d[FDD  ]   normal_operation=00
00017031251d[FDD  ]   drive_select=00
00017507829d[FDD  ] write access to port 03f2, value=0c
00017507829d[FDD  ] io_write: digital output register
00017507829d[FDD  ]   motor on, drive1 = 0
00017507829d[FDD  ]   motor on, drive0 = 0
00017507829d[FDD  ]   dma_and_interrupt_enable=08
00017507829d[FDD  ]   normal_operation=04
00017507829d[FDD  ]   drive_select=00
00017508329i[FDD  ] controller reset in software
from bochs. This says that it has been successfully been reset, and the other data looks right, but i don't receive an interrupt.
~ Lukem95 [ Cake ]
Release: 0.08b
Image
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

^_^ i got it working, but there are no interrupts fired at all during my code, i just put a one second wait where an interrupt should be and it seems to work ok now.

im still curious as to why it didnt fire the int though...
~ Lukem95 [ Cake ]
Release: 0.08b
Image
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

I had this once in Bochs too but never really tried to figure it out. Thinking about it, though, I wonder if the interrupt is triggered instantly (with Bochs being an emulator rather than real hardware)?

In this case, the interrupt fires before you enter your wait loop and the FD driver thinks that an interrupt never came.

Cheers,
Adam
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

thats an interesting thought, ill try it on actual hardware.

i shouldv done it last night, but i have no floppy on my dev pc, so i have to make an .iso, burn to cd and then boot that into a pc with a floppy and try it there.

this is a lot of effort on a windows box lol. i really should get a linux dev box, but i dont have space for a desktop in my room, and i can't afford to buy a new pc.
~ Lukem95 [ Cake ]
Release: 0.08b
Image
User avatar
JoeKayzA
Member
Member
Posts: 79
Joined: Wed Aug 24, 2005 11:00 pm
Location: Graz/Austria

Post by JoeKayzA »

As mentioned already, it is likely that bochs fires the interrupt immediately after you re-enable the fdc. A more reliable way to handle the interrupt would be to initialize floppy_received_int to zero, have your ISR increment the value each time it is called, and let your wait_for_interrupt() function loop until the value becomes non-zero (and decrement afterwards). This way, you would recognize the interrupt anyway.
Post Reply