Navigation
Highlights

Release 0.0.5

The latest release, alpha testing, unstable. See "downloads".

2005-06-01

Links
Documentation

Floppy driver

The FreeDOS-32 Floppy Driver is a loadable driver which allows FreeDOS-32 to access floppy disks, using NEC765 or compatible floppy disk controllers. This document is intended for those people who want to use its features and/or study the source code, in the hope it will be useful

Contents

  • What's new What's new in this version of the driver source and documentation
  • About the driver General informations on the FD32 Floppy Driver
  • Floppy Driver issues An overview of the issues behind the Floppy Driver functionality
  • Portability How to port the FD32 Floppy Driver to other platforms
  • List of source files The list of source files of the driver with a brief description of them

What's new

This is the first version of this driver and documentation. Please submit your comments to the developers' mailing list.

About the driver

The FreeDOS-32 Floppy Driver, as well as the rest of the FreeDOS-32 code, is released under the terms of the GNU General Public License.

Current features

  • Direct support for floppy drives through the NEC765 or compatible floppy drive controllers
  • Support for more than one drive per controller and for more controllers (to be tested)
  • Floppy disk format autodetection, and funetuning using boot sector informations
  • Cached read, buffering a whole cylinder at a time (can be extended to more cylinders)

Planned features

  • Switchable cached write, using the buffers for cached read
  • Support for perpendicular recording (Extra-Density disks)

Download

You can get the latest development source code for the Floppy Driver by checking out the floppy module from our CVS repository. See the downloads of the FreeDOS-32 web site page for details about this procedure. At present the driver only work under DOS, compiled with DJGPP. See the Makefile for informations on how to compile the driver from scratch. The COPYING.txt file contains the GNU General Public License: be sure you respect its terms if you intend to use the code.

Acknowledgement

The FreeDOS-32 Floppy Driver is derived from the "floppy controller handler library", Copyright (C) 1998 by Fabian Nunez. This library, released under the terms on the GNU General Public License, has been optimized and extended to include support for several drives and controllers, drives and disk format autodetection and custom system timers. You can download the original library from the Cottontail OS Development Library, in the Floppy section: the file is fdc.zip.

Some useful informations come from the Linux floppy driver too, like floppy format tables and drive parameter tables, as well as hints for the autodetection process, as described in the Linux fdutils.

Disclaimer

The FreeDOS-32 Floppy Driver is still under development and test, so it is not guaranted to be bug free by this time. Please consider that the code might have bugs that could corrupt your data seriously. Just to be more formal: as stated in the GNU General Public License, the program is provided "AS IS" WITHOUT ANY WARRANTY. TRY IT AT YOUR OWN RISK. I'M NOT RESPONSIBLE FOR ANY DAMAGE.

Floppy driver issues

This section describes some internal details on how the Floppy Driver works. These are intended to show what implementation issues are behind the driver. This discussion has been kept simple, without explaining all details. If you need more informations, you may want to check the Operating System Resource Center and the Cottontail OS Development Library, where you can find several interesting documents and source code about these topics.

The Floppy Disk Controller

Floppy disk drives (or FDDs for short) are managed by a floppy disk controller (or FDC for short), such as the NEC765 or compatibles and enhanced ones like Intel 82072 up to 82078. The FDC receives binary commands like read/write sectors, seek to track, recalibrate and format, and performs the required operations on the floppy drive. At present, the FD32 Floppy Driver uses only the basic commands available on NEC765 (and thus all the newer ones).

Usually a PC has one FDC, with base address port 3F0h (ports 3F2h to 3F7h), and up to two drives can be connected to the FDC. Older ones supported four drives, but this feature has been dropped. If a second FDC is present, it has base address port 370h. All installed FDCs share DMA channel 2 for data transfer and IRQ 6 to report command completion, thus making each floppy operation a critical section.

Floppy drives detection

Besides date and time, the memory embedded in the CMOS clock of the PC is used to store informations on the installed equipment. The location 10h stores informations on the installed floppy drives, up to two ones, using a 4-bit code for each of them. The code of the first drive is in the high nibble (bits 7-4) of the 8-bit register and the code for the second drive is in the low nibble (bits 3-0). Defined codes are the following:

code description
0 unknown (not installed)
1 5.25" DD, 360 KiB (does not support disk change line)
2 5.25" HD, 1200 KiB
3 3.5" DD, 720 KiB
4 3.5" HD, 1440 KiB
5 3.5" ED, 2880 KiB (reported by AMI BIOS instead of "tape drive")
6 3.5" ED, 2880 KiB

The FreeDOS-32 Floppy Driver uses these codes to determine the FDDs installed, "trusting" them. The floppy drive type is used to know what mechanical parameters to use (such as motor spinup and spindown times) and the allowed disk formats.

Floppy drives detection is performed in the FDC initialization code, implemented by the fdc_setup function (see fdc.c). For each detected drive a callback function is called, with its prototype defined by the FdcSetupCallback typedef. This callback function is used, inside the FreeDOS-32 Floppy Driver, to register a device for the drive to the FD32 kernel.

Floppy disk format autodetection

The floppy formats table is from the Linux floppy driver, and includes parameters for 32 disk formats. For each drive type, 8 allowed disk formats are included. For example a 3.5" HD drive allows 1440 KiB format with 80 tracks, 2 sides, 18 sectors per track, and 720 KiB format with 80 tracks, 2 sides, 9 sectors per track, plus other less common formats.

Disk format autodetection is performed by the fdc_log_disk function of the driver (see fdc.c), that has to be called every time a disk change is reported by the drive change line. This function attempts to probe the disk format by trying to read the last sector of the first track of the disk, using the parameters described in the floppy parameters table. For example, for a 3.5" HD drive, a 1440 KiB format is first checked by reading sector 18 of the first track, and, if reading fails, a 720 KiB format is checked by reading sector 9.

This kind of autodetection is fairly fast but not 100% accurate: for example a disk containing more that 80 tracks is not detected. To improve the autodetection reliability, once the driver has a first idea of the disk format the boot sector is read. The boot sector, according to the file system stored in the disk (if any), usually contains informations on the disk geometry. The FD32 Floppy Driver has a very basic knowledge of the boot sector format of the most common file systems (only FAT at present), and reads the geometry from it, finetuning the format autodetection. This is much faster than seeking the head to probe the number of tracks, or checking in the first place for less common formats, but with more sectors per track than usual (such as 1680 KiB disks, with 21 sectors per track, in a 3.5" HD drive).

Knowning the actual disk geometry inside the driver is important, because the controller accepts disk coordinates expressed as track number, head number and sector number, while the FreeDOS-32 driver interface expects a monodimensional sector number (as in Large Block Addressing) which must be translated.

Timer-driven events

Programming the floppy controller needs controlling delays and timeouts, for which the system timer is used. For generality and portability, the 8254 timer is not programmed directly (hooking IRQ 0 or handling INT 1Ch), but a generic fdc_event_post function is used to schedule a delayed event to something else which controls the system timer. This is supposed to be a function, installed on IRQ 0, which decreases counters and issues specified callback functions when the counters expire. In FD32 this handler is provided by OSLib.

The first timer-driven event is the timeout when waiting for FDC response: when the FDC executes a command, the driver waits up to 3 seconds (or anything else defined in the DriveParams structure, see fdc.h) for IRQ 6, which reports command completion, and after that time, a timeout error is reported (see wait_fdc in fdc.c).

Another important delay is needed when turning on the drive motor, because data cannot be transferred between the disk and the controller until the motor spins quickly enough. For example, for a 3.5" HD drive, a 400 ms delay is used before data transfer is performed. When this delay expires, the DF_SPINUP flag is set in the drive status structure (see Fdd in fdc.h), and the transfer is performed. This delay is needed only before data transfer and not for seek, recalibration or disk change check. Of course, if the motor is already on and fast, the spinup delay is not used, because the DF_SPINUP flag is already set.

Finally, when a function requests to turn off the drive motor, it actually schedules to turn it off after a spindown time, usually 3 seconds (or anything else defined in the DriveParams structure). This is done in order to keep the motor on if another command arrives in a short time, gaining time because the motor is already spinning fast. When you see the drive LED turning off after some time after disk access, this is the reason.

Naming conventions

The Floppy Driver uses the Linux naming convention for floppy drive devices: names start with "fd", followed by a zero-based number, so the first floppy device is "fd0", the second "fd1" and so on. The PC setup usually allows only one floppy controller, and only two drives connected to them.

Portability

The author of the library the FreeDOS-32 Floppy Driver is derived from has payed much attention to portability. The FD32 Floppy Driver aims to keep this spirit by splitting the code so that it should be easier to use it in other projects with little modifications.

The fdc.c (plus fdc.h) source file implements all the code needed to interface with the floppy disk controller. The routines in this files are general and not tied to a specific system, except they are written for the PC architecture. Other files implement a higher level of abstraction of the floppy controller, adding buffered access or target-dependent code.

List of source files

Follows the list of the files of the FreeDOS-32 Floppy Driver source code, with a short description for each function. For more informations look at the source files: a more detailed description precedes each function, including parameters and return value.

Subdirectories

At present there are two subdirectories in the floppy driver source tree: djgpp and fd32. Each of them contains code pertinent to a specific target. The idea is to put any target-dependent code in two files, portab.c and portab.h, which are used when compiling the driver for a certain target. So, for example, when compiling for the DOS target, the portab.* files in djgpp are used, which use the DJGPP libc, whereas when compiling for FD32 the portab.* files in fd32 are used, which use the OSLib services.

Moreover, the djgpp directory contains some tests programs, and the fd32 directory contains a fd32.c file with the driver request function and initialization code for FreeDOS-32.

fdc.c - Floppy Disk Controller low level support

Implements all the code needed to interface with the floppy disk controller (FDC). Public functions are fdc_disk_changed, which reports the disk change line status, fdc_log_disk, for disk format autodetection, fdc_read and fdc_write, to transfer sectors between the disk and a buffer, fdc_read_cylinder and fdc_write_cylinderto transfer a whole cylinder at once (which is usually faster), plus the fdc_setup and fdc_dispose functions which, respectively, initialize and dispose the controller support code. This file also implements internal functions, such as seeking to a track, waiting for FDC response and communicating between the processor and the FDC.

fdc.h - Floppy Disk Controller low level support declarations

This header file defines the FloppyFormat structure to store disk format parameters, the DriveParams structure to store drive parameters and the Fdd structure to store status for a floppy drive. Moreover it defines the prototype for the fdc_setup callback function and function prototypes for public functions implemented in fdc.c.

bootsect.c - format autodetection finetuning using data in the boot sector

The floppy_bootsector function is called by fdc_log_disk (see fdc.c) when the disk format appears to be successfully probed. It reads the boot sector of the disk (the first one), where usually file systems store informations about the actual disk geometry, and try to use these informations to finetune the floppy format autodetection.

For example, a disk may be probed as a 1440 KiB floppy (80 tracks, 2 sides, 18 sectors per track), but reading the boot sector it could be possible to learn that the floppy contains a FAT file system, which reports a geometry of 80 tracks, 2 sides and 21 sectors per track, so the format is actually 1680 KiB.

floppy.c - high level half of the floppy driver

This file provides high level functions to access floppies: floppy_read and floppy_write. They are standard block I/O functions, taking an absolute block number to start from, the count of block to transfer and a pointer to a user buffer. They convert absolute block numbers to track/head/sector using the current disk geometry and call the appropriate functions of the low level half of the driver (fdc.c). Moreover, floppy_read is able to do buffered read, caching a whole cylinder (the tracks of both sides) with a single read operation, speeding up floppy access, to the fastest rate of a cylinder read in two disk revolutions (usually around 450 ms).

floppy.h - high level half declarations

Besides the prototypes for floppy_read and floppy_write, this file defines the Floppy structure, which represents a floppy disk device in the floppy driver. This structure is used in order to provide buffered access to the floppy.