Page 1 of 1
Floppy Disk Driver...
Posted: Fri Nov 24, 2006 9:57 am
by CorN_Sk8
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...
Posted: Fri Nov 24, 2006 10:54 am
by CorN_Sk8
My initial code to the driver is...
Code: Select all
/*
* 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..
Posted: Fri Nov 24, 2006 11:26 am
by Dex
Maybe some of the doc's on bubach site, may help:
http://bos.asmhackers.net/docs/floppy/
Posted: Fri Nov 24, 2006 12:11 pm
by CorN_Sk8
i read some tutorials, but i need help to understand...
my atual code is:
Code: Select all
/*
* 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 ?
Posted: Fri Nov 24, 2006 1:05 pm
by Brynet-Inc
Code: Select all
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..
Posted: Fri Nov 24, 2006 1:19 pm
by CorN_Sk8
Code: Select all
/*
* 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 ...
Posted: Sat Feb 24, 2007 5:58 am
by pcmattman
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!
Posted: Sat Feb 24, 2007 1:34 pm
by bubach
Posted: Sat Feb 24, 2007 5:03 pm
by pcmattman
I'm really confused right now... This is my current floppy driver code:
Code: Select all
#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?
General timer
Posted: Fri Jul 27, 2007 3:32 am
by enrico_granata
While looking at Teemu Voipio's floppy disk driver, I incurred into a call:
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
Posted: Fri Jul 27, 2007 3:58 am
by JamesM
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
JamesM
Posted: Fri Jul 27, 2007 4:01 am
by enrico_granata
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
Posted: Sat Jul 28, 2007 5:58 am
by enrico_granata
I am trying to understand the floppy disk driver by comparing the tutorial at
http://debs.future.easyspace.com/Progra ... loppy.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: Select all
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?
Code: Select all
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: Select all
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!
Posted: Sat Jul 28, 2007 8:01 am
by jnc100
enrico granata wrote:Shouldn't this be 512? Why is it just 2?
82077aa datasheet
See table 5-2, page 24.
Regards,
John