Functions | |||||||||
| void | fdc_sendbyte (byte b) | ||||||||
Send a byte to the FDC controller.
| |||||||||
| int | fdc_getbyte () | ||||||||
Get a byte from the FDC controller.
| |||||||||
| 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.
| |||||||||
| void | fdc_recalibrate () | ||||||||
| Recalibrate the floppy drive. | |||||||||
| bool | fdc_seek (int track) | ||||||||
Seek a track.
| |||||||||
| 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.
| |||||||||
| 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).
| |||||||||
| bool | fdc_read (int block, byte *buffer, uint32_t count) | ||||||||
Read some contiguous blocks from the floppy disk.
| |||||||||
| bool | fdc_write (int block, byte *buffer, uint32_t count) | ||||||||
Write some contiguous blocks to the floppy disk.
| |||||||||
| bool | fdc_is_changed () | ||||||||
| Check if the floppy disk was changed. | |||||||||
| 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. | |||||||||
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. | |||||||||
| byte * | fdc_buffer | ||||||||
| Floppy r/w buffer. | |||||||||
|
|
Get a byte from the FDC controller.
Definition at line 88 of file floppy.c.
|
|
|
Check if the floppy disk was changed.
Definition at line 411 of file floppy.c.
00412 {
00413 return(fdc_change);
00414 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||
|
Read some contiguous blocks from the floppy disk.
Definition at line 376 of file floppy.c.
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||
|
Perform a read/write operation with the floppy drive using the DMA (Direct Memory Access).
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, §or);
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 }
|
|
|
Seek a track.
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 }
|
|
|
Send a byte to the FDC controller.
Definition at line 68 of file floppy.c.
|
|
|
Wait for a FDC operation.
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 }
|
|
||||||||||||||||
|
Write some contiguous blocks to the floppy disk.
Definition at line 396 of file floppy.c.
|
|
|
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 }
|
|
|
Initialize the floppy driver.
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 }
|
|
||||||||||||||||||||
|
Convert from a LBA (Linear Block Address) address to a CHS (Cylinder, Head, Sector) coordinates.
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 }
|
|
|
Floppy r/w buffer.
|
|
|
Disk change flag.
|
|
|
FDC operation finish.
|
|
|
Current floppy geometry.
|
|
|
Motor on flag.
|
|
|
Floppy motor kill countdown.
|
|
|
FDC status (result output).
|
|
|
FDC timeout.
|
|
|
Current head position.
|
|
|
Initial value: {
{ 2880, 18, 2, 80, 0x54, 0x1B, 0x00, "H1440" },
{ 3360, 21, 2, 80, 0x0C, 0x1C, 0x00, "H1680" }
}
|
|
|
Status register 0.
|
1.2.18