Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

Floppy Disk
[Device Drivers]


Functions

void fdc_sendbyte (byte b)
 Send a byte to the FDC controller.
Parameters:
b  The byte to send.


int fdc_getbyte ()
 Get a byte from the FDC controller.
Returns:
The byte read from the controller.
Exceptions:
NULL  If timeout is elapsed.


void fdc_motor_on ()
 Turn the floppy motor on.

void fdc_motor_off ()
 Starts the FDC motor kill countdown.

bool fdc_wait (bool sensei)
 Wait for a FDC operation.
Parameters:
sensei 
  • TRUE if a "sense interrupt status" command is required;
  • FALSE for a simple timeout wait.
Returns:
  • TRUE if the operation has successfully done;
  • FALSE if the timeout has been elapsed.


void fdc_recalibrate ()
 Recalibrate the floppy drive.

bool fdc_seek (int track)
 Seek a track.
Parameters:
track  The track to seek.
Returns:


void fdc_reset ()
 Reset the floppy disk controller.

void lba2chs (int lba, int *track, int *head, int *sector)
 Convert from a LBA (Linear Block Address) address to a CHS (Cylinder, Head, Sector) coordinates.
Parameters:
lba  The LBA address.
track  A pointer to the track coordinate.
head  A pointer to the head coordinate.
sector  A pointer to the sector coordinate.


bool fdc_rw (int block, byte *buffer, bool do_read)
 Perform a read/write operation with the floppy drive using the DMA (Direct Memory Access).
Parameters:
block  The LBA address of the block on the floppy.
buffer  The address of the buffer in memory for the transfer operation. It must have a size of at least FDC_SECTOR_SIZE bytes.
do_read 
  • TRUE to perform a read operation (from disk to memory);
  • FALSE to perform a write operation (from memory to disk).
Returns:


bool fdc_read (int block, byte *buffer, uint32_t count)
 Read some contiguous blocks from the floppy disk.
Parameters:
block  The starting block to read.
buffer  The destination buffer in memory where the blocks will be copied.
count  How many blocks to read.
Returns:


bool fdc_write (int block, byte *buffer, uint32_t count)
 Write some contiguous blocks to the floppy disk.
Parameters:
block  The starting block to write.
buffer  The address in memory from which the data will be copied.
count  How many blocks to write.
Returns:


bool fdc_is_changed ()
 Check if the floppy disk was changed.
Returns:
  • TRUE if the disk was changed;
  • FALSE otherwise.


void floppy_thread ()
 This is a routine called from clock_thread() at every clock tick to perform the floppy motor kill countdown and to control the floppy timeouts.

bool init_floppy ()
 Initialize the floppy driver.
Returns:



Variables

volatile bool fdc_motor = FALSE
 Motor on flag.

volatile int fdc_timeout = 0
 FDC timeout.

volatile int fdc_motor_countdown = 0
 Floppy motor kill countdown.

volatile bool fdc_done = FALSE
 FDC operation finish.

volatile bool fdc_change = FALSE
 Disk change flag.

volatile byte fdc_status [7] = { 0 }
 FDC status (result output).

volatile byte fdc_track = 0xFF
 Current head position.

volatile byte ST0 = 0
 Status register 0.

floppy_struct floppy_type []
 Floppy types known from the system.

byte fdc_geometry = 0
 Current floppy geometry.

bytefdc_buffer
 Floppy r/w buffer.


Detailed Description

The floppy disk driver.

Function Documentation

int fdc_getbyte  
 

Get a byte from the FDC controller.

Returns:
The byte read from the controller.
Exceptions:
NULL  If timeout is elapsed.

Definition at line 88 of file floppy.c.

00089 {
00090         int msr;
00091         int tmo;
00092 
00093         for (tmo=0; tmo<128; tmo++)
00094         {
00095                 msr = inportb(FDC_MSR);
00096                 if ((msr & 0xD0) == 0xD0)
00097                         return(inportb(FDC_DATA));
00098                 inportb(0x80); //delay //
00099         }
00100         return(-1); // timeout //
00101 }

bool fdc_is_changed  
 

Check if the floppy disk was changed.

Returns:
  • TRUE if the disk was changed;
  • FALSE otherwise.

Definition at line 411 of file floppy.c.

00412 {
00413         return(fdc_change);
00414 }

void fdc_motor_off  
 

Starts the FDC motor kill countdown.

Definition at line 116 of file floppy.c.

00117 {
00118         if (fdc_motor && (fdc_motor_countdown==-1))
00119                 fdc_motor_countdown = FDC_TIME_MOTOR_OFF/1000*HZ;
00120 }

void fdc_motor_on  
 

Turn the floppy motor on.

Definition at line 104 of file floppy.c.

00105 {
00106         if (!fdc_motor)
00107         {
00108                 outportb(FDC_DOR, 0x1C);
00109                 delay(FDC_TIME_MOTOR_SPINUP);
00110                 fdc_motor = TRUE;
00111         }
00112         fdc_motor_countdown = -1;
00113 }

bool fdc_read int    block,
byte   buffer,
uint32_t    count
 

Read some contiguous blocks from the floppy disk.

Parameters:
block  The starting block to read.
buffer  The destination buffer in memory where the blocks will be copied.
count  How many blocks to read.
Returns:

Definition at line 376 of file floppy.c.

00377 {
00378         register int i;
00379 
00380         for(i=0; i<count; i++)
00381                 if (!(fdc_rw(block+i, buffer+(FDC_SECTOR_SIZE*i), TRUE)))
00382                         return(FALSE);
00383         // Read operation OK! //
00384         return(TRUE);
00385 }

void fdc_recalibrate  
 

Recalibrate the floppy drive.

Definition at line 178 of file floppy.c.

00179 {
00180         // Turn the motor on //
00181         fdc_motor_on();
00182 
00183         // Send recalibrate command //
00184         fdc_sendbyte(CMD_RECAL);
00185         fdc_sendbyte(0);
00186 
00187         // Wait until recalibrate command is finished //
00188         fdc_wait(TRUE);
00189 
00190         // Turn the motor off //
00191         fdc_motor_off();
00192 }

void fdc_reset  
 

Reset the floppy disk controller.

Definition at line 235 of file floppy.c.

00236 {
00237         // Stop the motor and disable IRQ //
00238         outportb(FDC_DOR, 0x00);
00239 
00240         // Program data rate (500K/s) //
00241         outportb(FDC_DSR, 0x00);
00242 
00243         // re-enable floppy IRQ //
00244         outportb(FDC_DOR, 0x0C);
00245 
00246         // Wait for fdc //
00247         fdc_done = TRUE;
00248         fdc_wait(TRUE);
00249 
00250         // Specify drive timings //
00251         fdc_sendbyte(CMD_SPECIFY);
00252         fdc_sendbyte(0xDF); // SRT = 3ms, HUT = 240ms
00253         fdc_sendbyte(0x02); // HLT = 4ms, ND = 0 (DMA mode selected)
00254 
00255         // Clear disk change flag //
00256         fdc_seek(1);
00257         fdc_recalibrate();
00258         fdc_change = FALSE;
00259 }

bool fdc_rw int    block,
byte   buffer,
bool    do_read
 

Perform a read/write operation with the floppy drive using the DMA (Direct Memory Access).

Parameters:
block  The LBA address of the block on the floppy.
buffer  The address of the buffer in memory for the transfer operation. It must have a size of at least FDC_SECTOR_SIZE bytes.
do_read 
  • TRUE to perform a read operation (from disk to memory);
  • FALSE to perform a write operation (from memory to disk).
Returns:

Definition at line 289 of file floppy.c.

00290 {
00291         int track, head, sector, tries;
00292 
00293         // Translate the logical address into CHS address //
00294         lba2chs(block, &track, &head, &sector);
00295 
00296         // Spin up the motor //
00297         fdc_motor_on();
00298 
00299         if (!do_read)
00300                 // Write operation => copy data from buffer into fdc_buffer //
00301                 memcpy(fdc_buffer, buffer, FDC_SECTOR_SIZE);
00302 
00303         for(tries=0; tries<3; tries++)
00304         {
00305                 // Check for disk changed //
00306                 if (inportb(FDC_DIR) & 0x80)
00307                 {
00308                         fdc_change = TRUE;
00309                         fdc_seek(1);
00310                         fdc_recalibrate();
00311                         fdc_motor_off();
00312                         return(FALSE);
00313                 }
00314                 // Move the head to the right track //
00315                 if (!fdc_seek(track))
00316                 {
00317                         fdc_motor_off();
00318                         return(FALSE);
00319                 }
00320                 // Program data rate //
00321                 outportb(FDC_CCR, floppy_type[fdc_geometry].rate);
00322 
00323                 // Send command //
00324                 if (do_read)
00325                 {
00326                         // Read operation //
00327                         dma_xfer(2, (dword)fdc_buffer, FDC_SECTOR_SIZE, FALSE);
00328                         fdc_sendbyte(CMD_READ);
00329                 }
00330                 else
00331                 {
00332                         // Write operation //
00333                         dma_xfer(2, (dword)fdc_buffer, FDC_SECTOR_SIZE, TRUE);
00334                         fdc_sendbyte(CMD_WRITE);
00335                 }
00336                 fdc_sendbyte(head << 2);
00337                 fdc_sendbyte(track);
00338                 fdc_sendbyte(head);
00339                 fdc_sendbyte(sector);
00340                 fdc_sendbyte(2); // 512 bytes/sector //
00341                 fdc_sendbyte(floppy_type[fdc_geometry].spt);
00342                 fdc_sendbyte(floppy_type[fdc_geometry].rwgap);
00343                 fdc_sendbyte(0xFF); // DTL = unused //
00344 
00345                 // Wait for command completion //
00346                 if (!fdc_wait(FALSE))
00347                         return(FALSE); // Timed out! //
00348 
00349                 if ((fdc_status[0] & 0xC0) == 0) break; // Worked! :) //
00350 
00351                 // Try again... //
00352                 fdc_recalibrate();
00353         }
00354 
00355         // Stop the motor //
00356         fdc_motor_off();
00357 
00358         if (do_read)
00359                 // Read operation => copy data from fdc_buffer into buffer //
00360                 memcpy(buffer, fdc_buffer, FDC_SECTOR_SIZE);
00361 
00362         // Return if the R/W operation terminates successfully //
00363         return(tries != 3);
00364 }

bool fdc_seek int    track
 

Seek a track.

Parameters:
track  The track to seek.
Returns:

Definition at line 199 of file floppy.c.

00200 {
00201         // If already threre return //
00202         if (fdc_track == track)
00203                 return(TRUE);
00204 
00205         // Turn the motor on //
00206         fdc_motor_on();
00207 
00208         // Send seek command //
00209         fdc_sendbyte(CMD_SEEK);
00210         fdc_sendbyte(0);
00211         fdc_sendbyte(track);
00212 
00213         // Wait until seek is finished //
00214         if (!fdc_wait(TRUE))
00215         {
00216                 // Timeout! //
00217                 fdc_motor_off();
00218                 return(FALSE);
00219         }
00220 
00221         // Let the head settle for 15msec //
00222         delay(15);
00223 
00224         // Turn off the motor //
00225         fdc_motor_off();
00226 
00227         // Check if seek worked //
00228         if ((ST0 != 0x20) || (fdc_track != track))
00229                 return(FALSE);
00230         else
00231                 return(TRUE);
00232 }

void fdc_sendbyte byte    b
 

Send a byte to the FDC controller.

Parameters:
b  The byte to send.

Definition at line 68 of file floppy.c.

00069 {
00070         int msr;
00071         int tmo;
00072 
00073         for (tmo=0; tmo<128; tmo++)
00074         {
00075                 msr = inportb(FDC_MSR);
00076                 if ((msr & 0xC0) == 0x80)
00077                 {
00078                         outportb(FDC_DATA, b);
00079                         return;
00080                 }
00081                 inportb(0x80); //delay //
00082         }
00083 }

bool fdc_wait bool    sensei
 

Wait for a FDC operation.

Parameters:
sensei 
  • TRUE if a "sense interrupt status" command is required;
  • FALSE for a simple timeout wait.
Returns:
  • TRUE if the operation has successfully done;
  • FALSE if the timeout has been elapsed.

This routine must be invoked every time that we have to verify the correct completion of an operation. If a "sense interrupt status" command is issued, the status of the controller is reported into the ST0 variable and the current track is stored into the fdc_track variable.

Definition at line 136 of file floppy.c.

00137 {
00138         byte i;
00139 
00140         fdc_timeout = HZ; // timeout = 2 sec //
00141 
00142         // Wait for IRQ or timeout //
00143         while((!fdc_done) && (fdc_timeout))
00144         {
00145                 enable();
00146                 idle();
00147         }
00148 
00149         // Read command result bytes //
00150         i = 0;
00151         while ((i < 7) && (inportb(FDC_MSR) & MSR_BUSY))
00152                 fdc_status[i++] = fdc_getbyte();
00153 
00154         // Send a "sense interrupt status" command //
00155         if (sensei)
00156         {
00157                 fdc_sendbyte(CMD_SENSEI);
00158                 ST0 = fdc_getbyte();
00159                 fdc_track = fdc_getbyte();
00160         }
00161 
00162         // Timed out? //
00163         if (!fdc_done)
00164         {
00165                 // Check for disk change //
00166                 if (inportb(FDC_DIR) & 0x80)
00167                         fdc_change = TRUE;
00168                 return(FALSE);
00169         }
00170         else
00171         {
00172                 fdc_done = FALSE;
00173                 return(TRUE);
00174         }
00175 }

bool fdc_write int    block,
byte   buffer,
uint32_t    count
 

Write some contiguous blocks to the floppy disk.

Parameters:
block  The starting block to write.
buffer  The address in memory from which the data will be copied.
count  How many blocks to write.
Returns:

Definition at line 396 of file floppy.c.

00397 {
00398         register int i;
00399 
00400         for(i=0; i<count; i++)
00401                 if (!(fdc_rw(block+i, buffer+(FDC_SECTOR_SIZE*i), FALSE)))
00402                         return(FALSE);
00403         // Write operation OK! //
00404         return(TRUE);
00405 }

void floppy_thread  
 

This is a routine called from clock_thread() at every clock tick to perform the floppy motor kill countdown and to control the floppy timeouts.

Definition at line 422 of file floppy.c.

00423 {
00424         if (fdc_timeout > 0)
00425                 fdc_timeout--;
00426 
00427         if (fdc_motor_countdown > 0)
00428                 fdc_motor_countdown--;
00429         else if (fdc_motor && !fdc_motor_countdown)
00430         {
00431                 outportb(FDC_DOR, 0x0C);
00432                 fdc_motor = FALSE;
00433         }
00434 }

bool init_floppy  
 

Initialize the floppy driver.

Returns:

Definition at line 451 of file floppy.c.

00452 {
00453         int v;
00454 
00455         // Install the interrupt handler routine                        //
00456         install_irq_handler( FLOPPY_IRQ, (void *)floppy_handler );
00457 
00458         // Create the FDC buffer //
00459         fdc_buffer = PHYSICAL( dma_phys_alloc(PAGE_SIZE) );
00460 
00461         // Reset the controller //
00462         fdc_reset();
00463 
00464         // Get floppy controller version //
00465         fdc_sendbyte(CMD_VERSION);
00466         v = fdc_getbyte();
00467 
00468         switch ( v )
00469         {
00470                 case 0xFF:
00471                         return( FALSE );
00472                 break;
00473 
00474                 case 0x90:
00475                         kprintf("\n\rEnhanced controller found!");
00476                         return( TRUE );
00477                 break;
00478 
00479                 default:
00480                         kprintf("\n\r8272A/765A controller found! (cmd_version=%02X)", v);
00481                         return( TRUE );
00482                 break;
00483         }
00484 }

void lba2chs int    lba,
int *    track,
int *    head,
int *    sector
 

Convert from a LBA (Linear Block Address) address to a CHS (Cylinder, Head, Sector) coordinates.

Parameters:
lba  The LBA address.
track  A pointer to the track coordinate.
head  A pointer to the head coordinate.
sector  A pointer to the sector coordinate.

Definition at line 268 of file floppy.c.

00269 {
00270         *track = lba / (floppy_type[fdc_geometry].spt * floppy_type[fdc_geometry].heads);
00271         *head = (lba / floppy_type[fdc_geometry].spt) % floppy_type[fdc_geometry].heads;
00272         *sector = (lba % floppy_type[fdc_geometry].spt) + 1;
00273 }


Variable Documentation

byte* fdc_buffer
 

Floppy r/w buffer.

Definition at line 62 of file floppy.c.

volatile bool fdc_change = FALSE
 

Disk change flag.

Definition at line 41 of file floppy.c.

volatile bool fdc_done = FALSE
 

FDC operation finish.

Definition at line 38 of file floppy.c.

byte fdc_geometry = 0
 

Current floppy geometry.

Definition at line 59 of file floppy.c.

volatile bool fdc_motor = FALSE
 

Motor on flag.

Definition at line 29 of file floppy.c.

volatile int fdc_motor_countdown = 0
 

Floppy motor kill countdown.

Definition at line 35 of file floppy.c.

volatile byte fdc_status[7] = { 0 }
 

FDC status (result output).

Definition at line 44 of file floppy.c.

volatile int fdc_timeout = 0
 

FDC timeout.

Definition at line 32 of file floppy.c.

volatile byte fdc_track = 0xFF
 

Current head position.

Definition at line 47 of file floppy.c.

floppy_struct floppy_type[] [static]
 

Initial value:

 {
{ 2880, 18, 2, 80, 0x54, 0x1B, 0x00, "H1440" }, 
{ 3360, 21, 2, 80, 0x0C, 0x1C, 0x00, "H1680" }  
}
Floppy types known from the system.

Definition at line 53 of file floppy.c.

volatile byte ST0 = 0
 

Status register 0.

Definition at line 50 of file floppy.c.


Generated on Fri Feb 20 15:32:23 2004 for Minirighi by doxygen1.2.18