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;
}