User Level Floppy Disk Driver
=============================
The user level floppy driver is built using the Userdev library and the
code borrowed from the kernel floppy disk driver. The floppy disk driver
is a complex multi-threaded block device driver. The floppy disk 
driver extensively uses kernel support utilities such as task queues and 
kernel timers to delegate work to another thread and to delay an operation
for certain period of time respectively. The driver not only serves read 
and write requests from the file system buffer cache, but also serves ioctl 
requests to change the floppy drive parameters, to get or set the disk geometry,
format a given track, etc. 

The sequence of steps followed for each disk operation are:
        - Obtain the lock to channelize access to the floppy drive controller
	- Activate the drive to start the motor
	- Wait till the drive has picked up enough speed
	- Issue the operation specific command set to the floppy drive controller
	- Wait for an interrupt from the floppy drive controller to denote 
	  end of operation
	- Read the status from the floppy drive controller to check if the 
	  operation was successful
	- Switch off the drive motor
	- Release the lock on the floppy drive controller

Some of the changes that have been made while porting the kernel driver are:

1) The signature of the driver functions needs to be changed to that of the
   userdev operations of the Userdev library. 

2) The kernel task queues and timers are replaced by the corresponding 
   functions of the Userdev library. 

3) A call to attach the driver to the Userdev driver has to be made 
   giving the list of userdev operations implemented, in place of 
   registring a driver with the kernel.

4) Inorder to implement the locking mechanism used to serialize the access
   to the floppy drive controller, thread synchronisation mechanisms such 
   as mutexes and condition variables are used. 

5) Interrupts from the floppy drive controller are received by the floppy driver 
   using the userdev framework and the associated functions in the Userdev
   library. The framework also allows the user space floppy driver to interact
   with the DMA controller for performing disk I/O. So the functions from the
   Userdev library are used in place of kernel functions for interrupt handling
   and DMA.

6) All the driver interface functions except release, can potentially block, 
   so a separate thread is created for executing each of them. Since threads 
   in Linux are implemented as a separate process and the permisssions to perform
   I/O on ports are not inherited, they need to be obtained separately for each
   individual thread.

7) The user space driver keeps time in the form of 1/100th of a second since 
   epoch instead of jiffies, which is used by the kernel driver.

8) Lastly the module init function is replaced by main function that forms 
   the entry point to the user level floppy driver process. All initializations
   are done here and finally a call to the userdev_start library function is 
   made that does not return.

Other than these most of the driver code remains as it is. Again the make 
utility serves for compiling and building the driver. The driver uses the
usrdriv and pthread libraries

The contents of the directory:
=============================
- Makefile      :make file for building the floppy driver 
- README        :this file
- fd.h		:Header file containing the data structures used by the floppy driver
- fdreg.h	:Header file containing #define's for the floppy disk controller
- floppy		:The floppy driver binary
- floppy.h	:Header file containing functions for DMA and port access
- floppy.c	:The source code for the floppy disk driver
