Floppy seek and recalibration problem

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
ces_mohab
Member
Member
Posts: 77
Joined: Wed Oct 18, 2006 3:08 am

Floppy seek and recalibration problem

Post by ces_mohab »

Hello!
When I wrote my floppy driver I wrote reset function which call recalibrate.
Recalibrate send 0x07 command followed by 0 drive 0 and wait infinitely for an interupt. I tried to use seek which also send seek comand followed by some parameters and also wait infinitely for interupt. when I make recalibrate before reset it works. Can any body know the reson.

Code: Select all

//! Flag for interupt
/*! When a floppy interupt occurs this flag is set */
static int done_int = 0 ;
 
//! floppy interupt handeler
void fdc_handler( struct regs *r )
{
    done_int = 1 ;
    printf("FD INT\n") ;
}

//! Install floppy interupt handeler
void fdc_install()
{
    /* Installs 'floppy_handler' to IRQ6 */
    irq_install_handler(6, floppy_handler);
}

//! Read byte from intel 82077AA floppy device controller chip
iobyte_t fdc_read_byte( floppy_dr_t* floppy )
{
    //initialize timeout counter
    int timeout = 0 ;
    // loop untill we timeout
    while( timeout++ < FLOPPY_TIMEOUT  )
    {
       // read main status register
      msr_t msr = in_port_byte( floppy->base + FLOPPY_MSR );
      // loop untill ready status and FIFO direction is outward
      if( CHECKREAD(msr) )
         // return data byte from FIFO
          return in_port_byte( floppy->base + FLOPPY_DATA ); 
      in_port_byte( 0x80 );      // delay
    }
    return -1 ;   
}

//! Write byte to intel 82077AA floppy controller chip
void fdc_write_byte( floppy_dr_t* floppy, iobyte_t byte )
{
    int timeout = 0 ;
    // untill timeout
    while( timeout++ < FLOPPY_TIMEOUT  )
    {
       
       // read main status register
      msr_t msr = in_port_byte( floppy->base + FLOPPY_MSR );
      
      // loop untill ready status and FIFO direction is inward
      if( CHECKWRITE(msr) )
      {
         printf("Port %p %p\n",floppy->base + FLOPPY_DATA,byte) ;
          out_port_byte( floppy->base + FLOPPY_DATA, byte );
          return;
      }
      in_port_byte( 0x80 );
    }   
}
 
//! Turn floppy motor on
void fdc_motor_on( floppy_dr_t* floppy )
{
   dor_t dor = 0 ;

   SETDORDMA(dor) ;
   SETDORRESET(dor) ;
   if( floppy->base != FLOPPY_PRI_IO )
   {
      SETDORFLOPPY2(dor) ;
      SETDORMOTB(dor) ;
   }
   else
      SETDORMOTA(dor) ;
   
   out_port_byte( floppy->base + FLOPPY_DOR , dor );
   timer_wait(1500) ;      /* Too much yet */
}

//! Turn floppy motor off
void fdc_motor_off( floppy_dr_t * floppy )
{
   dor_t dor = 0 ;

   SETDORDMA(dor) ;
   SETDORRESET(dor) ;
   
   if( floppy->base != FLOPPY_PRI_IO )
      SETDORFLOPPY2(dor) ;
   
   out_port_byte( floppy->base + FLOPPY_DOR , dor );
   
}

//! Waits for an interupt to happen
void fdc_wait( void )
{
   // wait for flopppy interrupt
    while( 1 )
    {
       if(done_int)
          break ;
      // Schedule a new task
       schedule_int() ;
    }
    // reset flag
    done_int = 0 ;
}

void fdc_read_stat( floppy_dr_t* floppy )
{
   fdc_write_byte(floppy,FLOPPY_SIS) ;
   floppy->st0 = fdc_read_byte( floppy );
   floppy->cylinder = fdc_read_byte(floppy) ;
}

void fdc_recalibrate( floppy_dr_t* floppy )
{
   printf("FLOPPY RECALIBRATE\n") ;
    fdc_motor_on( floppy );
   
    // recalibrate the drive
    fdc_write_byte( floppy, FLOPPY_RECALIBRATE );
    // specify which drive
    fdc_write_byte( floppy, ( (floppy->base == FLOPPY_PRI_IO) ? 0 : 1 ) );
    // wait
    printf("FD Recalibrate WAIT\n") ;
    fdc_wait();
    //floppy_read_stat(floppy) ;
    
    fdc_motor_off( floppy );
    printf("FD Recalibrate completed Stat %p \n",floppy->st0) ;
}

void fdc_reset( floppy_dr_t* floppy )
{
   dor_t dor = 0 ;
   
   out_port_byte(floppy->base + FLOPPY_DOR, 0x00) ;
   out_port_byte(floppy->base + FLOPPY_MSR,0x00) ;
   
   out_port_byte( floppy->base + FLOPPY_DOR, 0x0C );
   
   floppy_wait();
   
   fdc_write_byte(floppy,0x03);    // timing
    fdc_write_byte(floppy,0xDF);     // timing
    fdc_write_byte(floppy,0x02);     // timing
   
   floppy_recalibrate( floppy );
   
   printf("Floppy reset completed\n") ;
}

int fdc_seek_cylinder( floppy_dr_t* floppy, floppy_cyl_t cylinder )
{
   printf("SEEK  track\n") ;
   
   fdc_motor_on( floppy );
   
   fdc_write_byte( floppy, FLOPPY_SEEK );
   // specify drive
   fdc_write_byte( floppy, ( floppy->base == FLOPPY_PRI_IO ? 0x00 : 0x01 ) );
   // specify cylinder
   fdc_write_byte( floppy, cylinder );
   // wait for the controller to send an interrupt back
   fdc_wait();
   // test if the seek operation performed correctly
   
   fdc_motor_off( floppy );
   
   if( floppy->cylinder != cylinder )
      return -1;
   return 1;
}
To write an OS you need 2 minds one for coding and other for debugging.
jimboynugget

Re:Floppy seek and recalibration problem

Post by jimboynugget »

Hi. I've just started writing my own floppy code, so my code looks very similar to yours. I've managed to get mine working (after many headaches) so I was able to remove bits of code from my routines to match your code and see how it behaves.

fdc_reset(): The 82077AA datasheet has an initialization flowchart on p.41 which should be implemented. I can see two things missing from your function:

= You might need to write the data rate to the CCR port (0x3F7). I use 0x00 for default values, but I guessed this value, and leaving it out doesn't seem to break the code.
= You also need to issue a "Sense Interrupt Status" four times, one for each of the 4 drives on the contoller. This clears out the interrupt status. If I comment this out of my reset function it hangs, so I guess this might be your problem.

fdc_recalibrate(): I think that a "Sense Interrupt Status" is also necessary after the fdc_wait(). According to the datasheet "Seek", "Relative Seek", and "Recalibrate" require an SIS because they have no result phase, so it's required to acknowledge the end of the command.

Hope this helps. I'm still learning this stuff myself. Let me know how you get on.
User avatar
ces_mohab
Member
Member
Posts: 77
Joined: Wed Oct 18, 2006 3:08 am

Re:Floppy seek and recalibration problem

Post by ces_mohab »

Well I found the problem exactly after I posted the message. It was because of missing SIS command in fdc_reset() and fdc_seek(). Also I fixed some bugs in DMA modules. and now I can read from a floppy. Thanks alot. ;D
To write an OS you need 2 minds one for coding and other for debugging.
Post Reply