OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Apr 24, 2017 7:10 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 14 posts ] 
Author Message
 Post subject: Floppy Disk Driver...
PostPosted: Fri Nov 24, 2006 9:57 am 
Offline

Joined: Fri Nov 24, 2006 9:51 am
Posts: 7
hello progammers,

what the steps do make a floppy disk driver ?
what i need to know to make it ?
somebody have a tutorial step by step ?

thanks..

obs:
i was using C language and my kernel is in PMode...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 24, 2006 10:54 am 
Offline

Joined: Fri Nov 24, 2006 9:51 am
Posts: 7
My initial code to the driver is...
Code:
/*
* Sistema Operacional BrOS
* CodeD by CorN_Sk8
* Kernel em C
*/

#include "include\floppy.h"
#include "include\system.h"
#include "include\video.h"
#include "include\in_out.h"

int fdc_flag=0;

void reset_floppy(int device){
     char devs[] = {0x1C, 0x2D, 0x4E, 0x8F};
     
     irq_install_handler(6, fdc_handler());
     
     outportb(0x3f7, 0x00);
     outportb(0x3f2, 0x0c);     
     
     fdc_flag=1;
}

void init_floppy(int device){
     
     reset_floppy(device);
     while(fdc_flag);
     
         
}

void fdc_handler(struct regs *r){
     fdc_flag = 0;
}


thanks..


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 24, 2006 11:26 am 
Offline
Member
Member
User avatar

Joined: Fri Jan 27, 2006 12:00 am
Posts: 1444
Maybe some of the doc's on bubach site, may help: http://bos.asmhackers.net/docs/floppy/


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 24, 2006 12:11 pm 
Offline

Joined: Fri Nov 24, 2006 9:51 am
Posts: 7
i read some tutorials, but i need help to understand...
my atual code is:
Code:
/*
* Sistema Operacional BrOS
* CodeD by CorN_Sk8
* Kernel em C
*/

#include "include\floppy.h"
#include "include\system.h"
#include "include\video.h"
#include "include\in_out.h"

int fdc_flag=0;

void fdc_wait(){
     fdc_flag=1;
     while(fdc_flag) ;
}

void fdc_sendbyte(int b){
     outportb(FDC_DATA, b);   
}

int reset_floppy(int device){
     char devs[] = {0x1C, 0x2D, 0x4E, 0x8F};
     
     outportb(FDC_DOR, 0x00);
     
     outportb(FDC_CCR, 0x00);
     outportb(FDC_DOR, 0x0C);
     
     fdc_wait();
     
  return 1;
}

void fdc_handler(struct regs *r){
     fdc_flag = 0;
}

int init_floppy(int device){
    int flag;
   
     // Instal IRQ
     irq_install_handler(6, fdc_handler);
     
     // reset floppy driver         
     flag = reset_floppy(device);
     if(flag == 0){
         printf("\nError on init floppy driver in stage of [Reset].\n");
         return 0;
     }
         
}

what the next step ?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 24, 2006 1:05 pm 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 9:29 pm
Posts: 2423
Location: Canada
Code:
int reset_floppy(int device){
     char devs[] = {0x1C, 0x2D, 0x4E, 0x8F};
     
     outportb(FDC_DOR, 0x00);
     
     outportb(FDC_CCR, 0x00);
     outportb(FDC_DOR, 0x0C);
     
     fdc_wait();
     
  return 1;
}

int init_floppy(int device){
    int flag;
   
     // Instal IRQ
     irq_install_handler(6, fdc_handler);
     
     // reset floppy driver         
     flag = reset_floppy(device);
     if(flag == 0){
         printf("\nError on init floppy driver in stage of [Reset].\n");
         return 0;
     }
         
}

I'm confused about that device variable, both init_floppy and reset_floppy seem to declare it, but apparently it's not used for anything.. :roll:

_________________
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
UNIX&BSD's, your only aspirations, to be imitated! 8)
Windows, are an opening in an otherwise solid and opaque surface through which light and, sometimes, even air can pass through; nothing more.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 24, 2006 1:19 pm 
Offline

Joined: Fri Nov 24, 2006 9:51 am
Posts: 7
Code:
/*
* Sistema Operacional BrOS
* CodeD by CorN_Sk8
* Kernel em C
*/

#include "include\floppy.h"
#include "include\system.h"
#include "include\video.h"
#include "include\in_out.h"

int fdc_flag            = 0;
int ST0                 = 0;
int fdc_status[7]       = { 0 };
int fdc_track           = 0xFF;
int fdc_motor           = 0;
int fdc_motor_countdown = 0;
int fdc_device          = 0;
int *fdc_buffer;

static int fdc_wait_until_ready( void )
{
   int counter, status;

   for( counter = 0; counter < 10000; counter++ )
   {
      status = inportb( FDC_MSR );
      if( status & MSR_READY )
      {
         return( status );
      }
   }
   return( -1 );
}

static int fdc_getbyte()
{
   int msr;

   msr = fdc_wait_until_ready();
   if( msr < 0 )
   {
      return( -1 );
   }
   msr &= MSR_DIR | MSR_READY | MSR_BUSY | MSR_DMA;
   if( msr == (MSR_DIR | MSR_READY | MSR_BUSY) )
   {
      return( inportb(FDC_DATA) );
   }
   return( -1 );
}

static int fdc_sendbyte( int b )
{
   int msr;

   msr = fdc_wait_until_ready();
   if( msr < 0 )
   {
      return( -1 );
   }
   if( (msr & (MSR_READY | MSR_DIR | MSR_DMA)) == MSR_READY )
   {
      outportb( FDC_DATA, b );
      return( 0 );
   }
   return( -1 );
}

int fdc_wait(int sensei){
     int i;
     
     fdc_flag=1;
     while(fdc_flag) ;
     
     i = 0;
     while( (i < 7) && (inportb(FDC_MSR) & MSR_BUSY) ){
         fdc_status[ i++ ] = fdc_getbyte();
     }
     
     if( sensei ){
         fdc_sendbyte( CMD_SENSEI );
         ST0 = fdc_getbyte();
         fdc_track = fdc_getbyte();
     }
     return 1;   
}

void fdc_motor_on(){
     
     char devs[] = {0x1C, 0x2D, 0x4E, 0x8F};   
     
     if(!fdc_motor){
         outportb( FDC_DOR, devs[fdc_device] );
         timer_wait(100);
         fdc_motor = 1;                   
     } 
}

void fdc_motor_off(){
     
     if(fdc_motor){
           outportb( FDC_DOR, 0x0C );
          fdc_motor = 1;                   
     }
}

static void fdc_recalibrate()
{
   // Turn the motor on.
   fdc_motor_on();

   // Send recalibrate command.
   fdc_sendbyte( CMD_RECAL );
   fdc_sendbyte( 0 );

   // Wait until recalibrate command is finished.
   fdc_wait( 1 );

   // Turn the motor off.
   fdc_motor_off();
}

int __fdc_seek( int track ){

   // If already there return.
   if( fdc_track == track )
   {
      return( 0 );
   }

   // Turn the motor on.
   fdc_motor_on();

   // Send seek command.
   fdc_sendbyte( CMD_SEEK );
   fdc_sendbyte( 0 );
   fdc_sendbyte( track );

   // Wait until seek is finished.
   if( fdc_wait(1) == 0 )
   {
      // Timeout!
      fdc_motor_off();
      printf("ERRO");
      return 0;
   }

   // Let the head settle for 15msec.
   timer_wait(50);

   // Turn off the motor.
   fdc_motor_off();

   // Check if seek worked.
   if( (ST0 == 0x20) && (fdc_track == track) )
   {
      return( 0 );
   }
   return 0;
}

int reset_floppy(int device){
   
    fdc_device = device;       

    outportb(FDC_DOR, 0x00);
     
    outportb(FDC_CCR, 0x00);
    outportb(FDC_DOR, 0x0C);
     
    fdc_wait(1);
     
    fdc_sendbyte( CMD_SPECIFY );
    fdc_sendbyte( 0xdf );
    fdc_sendbyte( 0x02 ); 
   
    __fdc_seek( 1 );   
    fdc_recalibrate();
     
    return 1;
}

void fdc_handler(struct regs *r){
     fdc_flag = 0;
}

int init_floppy(int device){
    int flag;
    int ret;
    int v;
   
    // Instal IRQ
    irq_install_handler(6, fdc_handler);
     
    // reset floppy driver         
    flag = reset_floppy(device);
    if(flag == 0){
        printf("\nError on init floppy driver in stage of [Reset].\n");
        return 0;
    }
     
     fdc_sendbyte( CMD_VERSION );
     v = fdc_getbyte();

     switch ( v ) {
         case 0xFF: printf(" [ controller not found ]");
         ret = 0;
         break;

           case 0x80: printf(" [ NEC controller ]");
         ret = 1;           
         break;

           case 0x81: printf(" [ VMware controller ]");
         ret = 1;           
         break;

         case 0x90: printf(" [ enhanced controller ]");
         ret = 1;         
         break;

           default: printf(" [ unknown controller [%d] ]", v);
         ret = 1;           
         break;
    }   

    return 1;
         
}

now i need write FDC_READ ...


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 24, 2007 5:58 am 
Offline
Member
Member

Joined: Sun Jan 14, 2007 9:15 pm
Posts: 2563
Location: Sydney, Australia (I come from a land down under!)
Hmmm... dunno if this is the right place to post but hey, who cares? It's only 3 months old...

I came across this in looking up how to control the floppy drive without DMA... now I can actually reset the drive (and stop it from spinning out of control). This is good. But I still have a problem: how do I actually read sectors? I don't care about writing (yet) but I would like to know how to read them...

Please, no DMA!

_________________
Pedigree | GitHub | Twitter | LinkedIn


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 24, 2007 1:34 pm 
Offline
Member
Member
User avatar

Joined: Sat Oct 23, 2004 11:00 pm
Posts: 1220
Location: Sweden
I think this has code to read a sector without DMA:
http://bos.asmhackers.net/docs/floppy/s ... 6/fdc1.txt

_________________
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 24, 2007 5:03 pm 
Offline
Member
Member

Joined: Sun Jan 14, 2007 9:15 pm
Posts: 2563
Location: Sydney, Australia (I come from a land down under!)
I'm really confused right now... This is my current floppy driver code:

Code:
#include "mattise.h"

/**** revision 2 ****/

int floppy_flag = 1;

// ports
#define DOR 0x3F2
#define CCR 0x3F7

char* drive_types[6] =   { "No floppy drive.",
            "360KB 5.25in floppy",
            "1.2MB 5.25in floppy",
            "720KB 3.5in floppy",
            "1.44MB 3.5in floppy",
            "2.88MB 3.5in floppy"
         };

void DetectFloppyDrives()
{
   unsigned char c;
   outportb( 0x70, 0x10 );
   c = inportb( 0x71 );

   unsigned char drive1;
   unsigned char drive2;
   drive1 = c >> 4;
   drive2 = c & 0xF;

   kputs( "Floppy 1: " ); kputs( drive_types[ drive1 ] );
   kputs( "\n" );
   kputs( "Floppy 2: " ); kputs( drive_types[ drive2 ] );
   kputs( "\n" );
}

// floppy acessory functions

void SendByte_FDC( char b )
{
   // byte storage
   unsigned char a = 0;

   // wait for ready
   while( true )
   {
      // wait a little while
      sleep( 100 );

      // get a byte from the controller
      a = inportb( 0x3F4 );

      // bitwise and
      a &= 0x80;

      // check
      if( a == 0x80 )
         break;
   }

   // wait a bit more
   sleep( 100 );

   // send the byte
   outportb( 0x3F5, b );
}

unsigned char RecByte_FDC()
{
   // two byte length storage areas
   unsigned char a;
   unsigned char b;

   // wait for ready
   while( true )
   {
      // wait a little while
      sleep( 100 );

      // get a byte from the controller
      a = inportb( 0x3F4 );

      // bitwise and
      a &= 0x80;

      // check
      if( a == 0x80 )
         break;
   }

   // get the byte and return it
   b = inportb( 0x3F5 );

   // return to caller
   return b;
}

void Recal()
{
   // recalibrate the floppy drive
   unsigned char res = 0;
   unsigned char cres = 0;

   // main loop - may have to keep recalibrating numerous times
   while( true )
   {
      // send the recalibrate command
      SendByte_FDC( 7 );

      // send 'drive a' indicator
      SendByte_FDC( 0 ); // replace 0 with 1 for b

      // send 'sense interrupt'
      SendByte_FDC( 0x08 );

      // wait for data from controller
      res = RecByte_FDC();

      // play with the byte
      cres = res & 0x80;

      // equal?
      if( cres == 0x80 )
         continue;

      // get another byte
      res = RecByte_FDC();

      // result byte got nothing?
      if( res == 0 )
         break;
   }
}

void SeekTrackSide( unsigned char track, unsigned char side )
{
   // bytes, lots of bytes
   unsigned char a,b,c;

   // do something cool
   while( true ) /* go_and_seek_it_again: */
   {
      // seek command
      SendByte_FDC( 0x0F );

      // send the side
      SendByte_FDC( side * 4 );

      // send the track
      SendByte_FDC( track );

      // sense interrupt
      SendByte_FDC( 0x08 );

      // recieve a byte
      a = RecByte_FDC();

      // bitwise fun
      a &= 0x80;

      // checks
      if( a != 0x80 )
         break;

      // recieve another byte
      a = RecByte_FDC();

      // check
      if( a == track )
         break;
   }
}

void MotorOn()
{
   // turn on the motor
   outportb( DOR, 0x1C );
}

void MotorOff()
{
   // turn off the motor
   outportb( DOR, 0x0 );
}

// floppy IRQ handler
void FloppyHandler( struct regs* r )
{
   // reset the flag, say that we
   // have handled the interrupt
   // lets the initialization return
   floppy_flag = 0;
}

// reset the floppy disk
void ResetFloppy()
{
   // reset the drive
   outportb( DOR, 0x00 );
   outportb( DOR, 0x0C );
   outportb( CCR, 0x00 );

   // set the flag
   floppy_flag = 1;

   // wait for the interrupt...
   while( floppy_flag == 1 );
}

// initializes the floppy
void InitFloppy()
{
   // install the handler
   irq_install_handler( 6, FloppyHandler );
}


How can I read the sectors I want from the disk?

_________________
Pedigree | GitHub | Twitter | LinkedIn


Top
 Profile  
 
 Post subject: General timer
PostPosted: Fri Jul 27, 2007 3:32 am 
Offline

Joined: Tue Jul 24, 2007 1:19 am
Posts: 21
While looking at Teemu Voipio's floppy disk driver, I incurred into a call:

Code:
timer_sleep(1); // sleep 10 ms


How does he do it? I mean, the timer interrupt has a granularity of around 1/18th second. How can he sleep for 1/100th second?

Is there a way to calibrate the clock to trigger at a different interval, or is there some other time-measuring device with a higher precision :?:


Attachments:
File comment: Teemu Voipio's floppy disk driver
floppy.c [16.3 KiB]
Downloaded 393 times

_________________
Computer science: all about things that "should" work
Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 27, 2007 3:58 am 
Offline
Member
Member
User avatar

Joined: Tue Jul 10, 2007 5:27 am
Posts: 2935
Location: York, United Kingdom
bran wrote:
The timer will divide it's input clock of 1.19MHz (1193180Hz) by the number you give it in the data register to figure out how many times per second to fire the signal for that channel


The default is for the divisor register to be set so it fires at 18.222Hz. If you set it to 1, you should be able to get interrupts up to 1.19MHz.

Impressive bumping, btw :P

JamesM


Last edited by JamesM on Fri Jul 27, 2007 4:07 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 27, 2007 4:01 am 
Offline

Joined: Tue Jul 24, 2007 1:19 am
Posts: 21
:P I guess this is all detailed in the Wiki about the pit (which I should probably have looked at before posting), right?
I'm gonna give a look at that before bothering again :oops:

_________________
Computer science: all about things that "should" work


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 28, 2007 5:58 am 
Offline

Joined: Tue Jul 24, 2007 1:19 am
Posts: 21
I am trying to understand the floppy disk driver by comparing the tutorial at http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html with Teemu Voipio's driver..but I can't seem to figure out this piece of code (commands being sent to the controller for actual read/write):
Code:
        floppy_write_cmd(base, cmd);  // set above for current direction
        floppy_write_cmd(base, 0);    // 0:0:0:0:0:HD:US1:US0 = head and drive
        floppy_write_cmd(base, cyl);  // cylinder
        floppy_write_cmd(base, 0);    // first head (should match with above)
        floppy_write_cmd(base, 1);    // first sector, strangely counts from 1
        floppy_write_cmd(base, 2);    // bytes/sector, 128*2^x (x=2 -> 512)

Shouldn't this be 512? Why is it just 2? :shock:
Code:
        floppy_write_cmd(base, 18);   // number of tracks to operate on

If I write 1 in here, will it just read or write 1 sector?
Code:
        floppy_write_cmd(base, 0x1b); // GAP3 length, 27 is default for 3.5"
        floppy_write_cmd(base, 0xff); // data length (0xff if B/S != 0)


Thanks for any hints!

_________________
Computer science: all about things that "should" work


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 28, 2007 8:01 am 
Offline
Member
Member

Joined: Mon Apr 09, 2007 12:10 pm
Posts: 770
Location: London, UK
enrico granata wrote:
Shouldn't this be 512? Why is it just 2?

82077aa datasheet
See table 5-2, page 24.

Regards,
John


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: MSNbot Media and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group