250454959750e02dc90c0ac8fb1ae84259b02d6f
[reactos.git] / drivers / dd / floppy / floppy.c
1 /*
2  *  FLOPPY.C - NEC-765/8272A floppy device driver
3  *   written by Rex Jolliff
4  *    with help from various other sources, including but not limited to:
5  *    Art Baker's NT Device Driver Book, Linux Source, and the internet.
6  *
7  *  Modification History:
8  *    08/19/98  RJJ  Created.
9  *    01/31/01  PJS  Heavy rewrite, most of code thrown out
10  *
11  *  To do:
12  * FIXME: get it working
13  * FIXME: add support for DMA hardware
14  * FIXME: should add support for floppy tape/zip devices
15  */
16
17 #include <ddk/ntddk.h>
18
19 #include "floppy.h"
20 #define NDEBUG
21 #include <debug.h>
22
23
24 FLOPPY_CONTROLLER_PARAMETERS ControllerParameters[FLOPPY_MAX_CONTROLLERS] = 
25 {
26   {0x03f0, 6, 2, Latched}
27   //  {0x0370, 6, 6, Latched}
28 };
29
30 const FLOPPY_MEDIA_TYPE MediaTypes[] = {
31    { 0x02, 80, 2, 18, 512 },
32    { 0, 0, 0, 0, 0 } };
33
34 static BOOLEAN
35 FloppyCreateController(PDRIVER_OBJECT DriverObject,
36                        PFLOPPY_CONTROLLER_PARAMETERS ControllerParameters,
37                        int Index)
38 {
39    PCONTROLLER_OBJECT ControllerObject;
40    PFLOPPY_CONTROLLER_EXTENSION ControllerExtension;
41    PFLOPPY_DEVICE_EXTENSION DeviceExtension;
42    UNICODE_STRING DeviceName;
43    NTSTATUS Status;
44    PDEVICE_OBJECT DeviceObject;
45    PCONFIGURATION_INFORMATION ConfigInfo;
46    LARGE_INTEGER Timeout;
47    BYTE Byte;
48    int c;
49    PCONFIGURATION_INFORMATION Config;
50    DEVICE_DESCRIPTION DeviceDescription;
51    ULONG MaxMapRegs;
52    ULONG MappedIrq;
53    KIRQL Dirql;
54    KAFFINITY Affinity;
55    
56    /* FIXME: Register port ranges with HAL */
57    MappedIrq = HalGetInterruptVector(Isa,
58                                      0,
59                                      ControllerParameters->Vector,
60                                      ControllerParameters->Vector,
61                                      &Dirql,
62                                      &Affinity);
63
64    /*  Create controller object for FDC  */
65    ControllerObject = IoCreateController(sizeof(FLOPPY_CONTROLLER_EXTENSION));
66    if (ControllerObject == NULL)
67      {
68         DPRINT("Could not create controller object for controller %d\n",
69                Index);
70         return FALSE;
71      }
72    
73    /* FIXME: fill out controller data */
74    ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)
75      ControllerObject->ControllerExtension;
76    ControllerExtension->Number = Index;
77    ControllerExtension->PortBase = ControllerParameters->PortBase;
78    ControllerExtension->Vector = MappedIrq;
79    KeInitializeEvent( &ControllerExtension->Event, SynchronizationEvent, FALSE );
80    ControllerExtension->Device = 0;  // no active device
81    ControllerExtension->Irp = 0;     // no active IRP
82    /*  Initialize the spin lock in the controller extension  */
83    KeInitializeSpinLock(&ControllerExtension->SpinLock);
84    ControllerExtension->IsrState = FloppyIsrDetect;
85    ControllerExtension->DpcState = FloppyDpcDetect;
86    
87    /*  Register an interrupt handler for this controller  */
88    Status = IoConnectInterrupt(&ControllerExtension->Interrupt,
89                                FloppyIsr, 
90                                ControllerObject, 
91                                &ControllerExtension->SpinLock, 
92                                MappedIrq, 
93                                Dirql, 
94                                Dirql, 
95                                ControllerParameters->InterruptMode, 
96                                FALSE, 
97                                Affinity, 
98                                FALSE);
99    if (!NT_SUCCESS(Status)) 
100      {
101         DPRINT("Could not Connect Interrupt %d\n", 
102                ControllerExtension->Vector);
103         goto controllercleanup;
104      }
105
106    
107    /* setup DMA stuff for controller */
108    DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
109    DeviceDescription.Master = FALSE;
110    DeviceDescription.ScatterGather = FALSE;
111    DeviceDescription.AutoInitialize = FALSE;
112    DeviceDescription.Dma32BitAddress = FALSE;
113    DeviceDescription.DmaChannel = ControllerParameters->DmaChannel;
114    DeviceDescription.InterfaceType = Isa;
115    //   DeviceDescription.DmaWidth = Width8Bits;
116    ControllerExtension->AdapterObject = HalGetAdapter( &DeviceDescription, &MaxMapRegs );
117    if( ControllerExtension->AdapterObject == NULL )
118       {
119          DPRINT1( "Could not get adapter object\n" );
120          goto interruptcleanup;
121       }
122                              
123 #if 0
124    /*  Check for each possible drive and create devices for them */
125    for (DriveIdx = 0; DriveIdx < FLOPPY_MAX_DRIVES; DriveIdx++)
126      {
127         /* FIXME: try to identify the drive */
128         /* FIXME: create a device if it's there */
129      }
130 #endif
131     
132    /* FIXME: Let's assume one drive and one controller for the moment */
133    RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\Device\\Floppy0");
134    Status = IoCreateDevice(DriverObject,
135                            sizeof(FLOPPY_DEVICE_EXTENSION),
136                            &DeviceName,
137                            FILE_DEVICE_DISK,
138                            FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE,
139                            FALSE,
140                            &DeviceObject);
141    if (!NT_SUCCESS(Status))
142      {
143         goto interruptcleanup;
144      }
145    DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
146    DeviceExtension->DriveSelect = 0;
147    DeviceExtension->Controller = ControllerObject;
148    DeviceExtension->MediaType = ~0;
149    ControllerExtension->MotorOn = ~0;
150    // set up DPC
151    ControllerExtension->Device = DeviceObject;
152    KeInitializeDpc( &ControllerExtension->MotorSpinupDpc,
153                     FloppyMotorSpinupDpc,
154                     ControllerObject );
155    KeInitializeDpc( &ControllerExtension->MotorSpindownDpc,
156                     FloppyMotorSpindownDpc,
157                     ControllerObject );
158    KeInitializeTimer( &ControllerExtension->SpinupTimer );
159    IoInitializeDpcRequest( DeviceObject, FloppyDpc );
160    // reset controller and wait for interrupt
161    DPRINT( "Controller Off\n" );
162    FloppyWriteDOR( ControllerExtension->PortBase, 0 );
163    // let controller reset for at least FLOPPY_RESET_TIME
164    KeStallExecutionProcessor( FLOPPY_RESET_TIME );
165    DPRINT( "Controller On\n" ); 
166    FloppyWriteDOR( ControllerExtension->PortBase, FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA );
167    // wait for interrupt now
168    Timeout.QuadPart = -10000000;
169    Status = KeWaitForSingleObject( &ControllerExtension->Event,
170                                    Executive,
171                                    KernelMode,
172                                    FALSE,
173                                    &Timeout );
174    if( Status != STATUS_WAIT_0 )
175       {
176          DPRINT1( "Error: KeWaitForSingleObject returned: %x\n", Status );
177          goto devicecleanup;
178       }
179    // set for high speed mode
180    //   FloppyWriteCCNTL( ControllerExtension->PortBase, FLOPPY_CCNTL_1MBIT );
181    // ok, so we have an FDC, now check for drives
182    // aparently the sense drive status command does not work on any FDC I can find
183    // so instead we will just have to assume a 1.44 meg 3.5 inch floppy.  At some
184    // point we should get the bios disk parameters passed in to the kernel at boot
185    // and stored in the HARDWARE registry key for us to pick up here.
186
187    // turn on motor, wait for spinup time, and recalibrate the drive
188    FloppyWriteDOR( ControllerExtension->PortBase, FLOPPY_DRIVE0_ON );
189    Timeout.QuadPart = FLOPPY_MOTOR_SPINUP_TIME;
190    KeDelayExecutionThread( KernelMode, FALSE, &Timeout );
191    DPRINT( "MSTAT: %2x\n", FloppyReadMSTAT( ControllerExtension->PortBase ) );
192    FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_RECAL );
193    DPRINT( "MSTAT: %2x\n", FloppyReadMSTAT( ControllerExtension->PortBase ) );
194    KeStallExecutionProcessor( 10000 );
195    FloppyWriteDATA( ControllerExtension->PortBase, 0 ); // drive select
196    Timeout.QuadPart = FLOPPY_RECAL_TIMEOUT;
197    Status = KeWaitForSingleObject( &ControllerExtension->Event,
198                                    Executive,
199                                    KernelMode,
200                                    FALSE,
201                                    &Timeout );
202    if( Status != STATUS_WAIT_0 )
203       {
204          DPRINT1( "Error: KeWaitForSingleObject returned: %x\n", Status );
205          goto devicecleanup;
206       }
207    if( ControllerExtension->St0 != FLOPPY_ST0_SEEKGD )
208      {
209        DbgPrint( "Floppy: error recalibrating drive, ST0: %2x\n", (DWORD)ControllerExtension->St0 );
210        goto devicecleanup;
211      }
212    DeviceExtension->Cyl = 0;
213    // drive is good, and it is now on track 0, turn off the motor
214    FloppyWriteDOR( ControllerExtension->PortBase, FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA );
215    /* Initialize the device */
216    DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
217    DeviceObject->AlignmentRequirement = FILE_512_BYTE_ALIGNMENT;
218    // change state machine, no interrupt expected
219    ControllerExtension->IsrState = FloppyIsrUnexpected;
220    Config = IoGetConfigurationInformation();
221    Config->FloppyCount++;
222    // call IoAllocateAdapterChannel, and wait for execution routine to be given the channel
223    CHECKPOINT;
224    Status = IoAllocateAdapterChannel( ControllerExtension->AdapterObject,
225                                       DeviceObject,
226                                       0x3000/PAGE_SIZE,  // max track size is 12k
227                                       FloppyAdapterControl,
228                                       ControllerExtension );
229    if( !NT_SUCCESS( Status ) )
230      {
231        DPRINT1( "Error: IoAllocateAdapterChannel returned %x\n", Status );
232        goto devicecleanup;
233      }
234    CHECKPOINT;
235    Status = KeWaitForSingleObject( &ControllerExtension->Event,
236                                    Executive,
237                                    KernelMode,
238                                    FALSE,
239                                    &Timeout );
240    CHECKPOINT;
241    if( Status != STATUS_WAIT_0 )
242       {
243          DPRINT1( "Error: KeWaitForSingleObject returned: %x\n", Status );
244          goto devicecleanup;
245       }
246    // Ok, we own the adapter object, from now on we can just IoMapTransfer, and not
247    // bother releasing the adapter ever.
248
249    DPRINT( "Floppy drive initialized\n" );
250    return TRUE;
251
252  devicecleanup:
253    IoDeleteDevice( DeviceObject );
254  interruptcleanup:
255    IoDisconnectInterrupt(ControllerExtension->Interrupt);
256  controllercleanup:
257    // turn off controller
258    FloppyWriteDOR( ControllerExtension->PortBase, 0 );
259    IoDeleteController(ControllerObject);
260    return FALSE;
261 }
262
263 IO_ALLOCATION_ACTION STDCALL
264 FloppyExecuteSpindown(PDEVICE_OBJECT DeviceObject,
265                       PIRP Irp,
266                       PVOID MapRegisterbase,
267                       PVOID Context)
268 {
269    PFLOPPY_CONTROLLER_EXTENSION ControllerExtension= (PFLOPPY_CONTROLLER_EXTENSION)Context;
270
271    // turn off motor, and return
272    DPRINT( "Spinning down motor\n" );
273    ControllerExtension->MotorOn = ~0;
274    FloppyWriteDOR( ControllerExtension->PortBase,
275                    FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA );
276    return DeallocateObject;
277 }
278
279 IO_ALLOCATION_ACTION STDCALL
280 FloppyExecuteReadWrite(PDEVICE_OBJECT DeviceObject,
281                        PIRP Irp,
282                        PVOID MapRegisterbase,
283                        PVOID Context)
284 {
285    PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
286    PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)DeviceExtension->Controller->ControllerExtension;
287    LARGE_INTEGER Timeout;
288    BOOLEAN WriteToDevice;
289    DWORD Cyl, Sector, Head;
290    PIO_STACK_LOCATION Stk;
291    DWORD Length;
292
293    ControllerExtension->Irp = Irp = (PIRP)Context;
294    Stk = IoGetCurrentIrpStackLocation( Irp );
295    ControllerExtension->Device = DeviceObject;
296    Timeout.QuadPart = FLOPPY_MOTOR_SPINUP_TIME;
297    DPRINT( "FloppyExecuteReadWrite()\n" );
298    CHECKPOINT;
299    WriteToDevice = Stk->MajorFunction == IRP_MJ_WRITE ? TRUE : FALSE;
300    // verify drive is spun up and selected
301    if( ControllerExtension->MotorOn != DeviceExtension->DriveSelect )
302       {
303          // turn on and select drive, and allow it to spin up
304          // FloppyMotorSpinupDpc will restart this operation once motor is spun up
305          DPRINT( "Motor not on, turning it on now\n" );
306          FloppyWriteDOR( ControllerExtension->PortBase,
307                          DeviceExtension->DriveSelect ? FLOPPY_DRIVE1_ON : FLOPPY_DRIVE0_ON );
308          // cancel possible spindown timer first
309          KeCancelTimer( &ControllerExtension->SpinupTimer );
310          KeSetTimerEx( &ControllerExtension->SpinupTimer,
311                        Timeout,
312                        0,
313                        &ControllerExtension->MotorSpinupDpc );
314          return KeepObject;
315       }
316    else {
317      Timeout.QuadPart = FLOPPY_MOTOR_SPINDOWN_TIME;
318      // motor is already spinning, so reset the spindown timer
319      KeCancelTimer( &ControllerExtension->SpinupTimer );
320      KeSetTimer( &ControllerExtension->SpinupTimer,
321                  Timeout,
322                  &ControllerExtension->MotorSpindownDpc );
323    }
324 #if 0
325    /* Handle disk change, doesn't work correctly */
326    if( FloppyReadDIR( ControllerExtension->PortBase ) & FLOPPY_DI_DSKCHNG )
327       {
328          // No disk is in the drive
329          DPRINT( "No disk is in the drive\n" );
330          Irp->IoStatus.Status = STATUS_MEDIA_CHANGED;
331          Irp->IoStatus.Information = 0;
332          IoCompleteRequest( Irp, 0 );
333          return DeallocateObject;
334       }
335 #endif
336    if( DeviceExtension->MediaType == ~0 )
337       {
338          // media is in disk, but we have not yet detected what kind it is,
339          // so detect it now
340          // First, we need to recalibrate the drive though
341          ControllerExtension->IsrState = FloppyIsrRecal;
342          DPRINT( "Recalibrating drive\n" );
343          KeStallExecutionProcessor( 1000 );
344          FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_RECAL );
345          KeStallExecutionProcessor( 1000 );
346          FloppyWriteDATA( ControllerExtension->PortBase, DeviceExtension->DriveSelect );
347          return KeepObject;
348       }
349    // looks like we have media in the drive.... do the read
350    // first, calculate geometry for read
351    Sector = Stk->Parameters.Read.ByteOffset.u.LowPart / MediaTypes[DeviceExtension->MediaType].BytesPerSector;
352    // absolute sector right now
353    Cyl = Sector / MediaTypes[DeviceExtension->MediaType].SectorsPerTrack;
354    DPRINT( "Sector = %x, Offset = %x, Cyl = %x, Heads = %x MediaType = %x\n", Sector, Stk->Parameters.Read.ByteOffset.u.LowPart, (DWORD)Cyl, (DWORD)MediaTypes[DeviceExtension->MediaType].Heads, (DWORD)DeviceExtension->MediaType );
355    Head = Cyl % MediaTypes[DeviceExtension->MediaType].Heads;
356    DPRINT( "Head = %2x\n", Head );
357    // convert absolute cyl to relative
358    Cyl /= MediaTypes[DeviceExtension->MediaType].Heads;
359    // convert absolute sector to relative
360    Sector %= MediaTypes[DeviceExtension->MediaType].SectorsPerTrack;
361    Sector++;  // track relative sector numbers are 1 based, not 0 based
362    DPRINT( "Cyl = %2x, Head = %2x, Sector = %2x\n", Cyl, Head, Sector );
363
364    // seek if we need to seek
365    if( DeviceExtension->Cyl != Cyl )
366      {
367        DPRINT( "Seeking...\n" );
368        ControllerExtension->IsrState = FloppyIsrDetect;
369        ControllerExtension->DpcState = FloppySeekDpc;
370        FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_SEEK );
371        KeStallExecutionProcessor( 100 );
372        FloppyWriteDATA( ControllerExtension->PortBase, DeviceExtension->DriveSelect );
373        KeStallExecutionProcessor( 100 );
374        FloppyWriteDATA( ControllerExtension->PortBase, Cyl );
375        return KeepObject;
376      }
377    //set up DMA and issue read command
378    Length = MediaTypes[DeviceExtension->MediaType].SectorsPerTrack - Sector + 1;
379    // number of sectors untill end of track
380    Length *= 512;   // convert to bytes
381    if( Length > Stk->Parameters.Read.Length )
382      Length = Stk->Parameters.Read.Length;
383    DPRINT( "Sector: %d, Length: %d\n", Sector, Length );
384    ControllerExtension->TransferLength = Length;
385    IoMapTransfer( ControllerExtension->AdapterObject,
386                   Irp->MdlAddress,
387                   ControllerExtension->MapRegisterBase,
388                   Irp->Tail.Overlay.DriverContext[0], // current va
389                   &Length,
390                   WriteToDevice );
391    ControllerExtension->IsrState = FloppyIsrReadWrite;
392    ControllerExtension->DpcState = FloppyDpcReadWrite;
393    CHECKPOINT;
394    FloppyWriteDATA( ControllerExtension->PortBase, WriteToDevice ? FLOPPY_CMD_WRITE : FLOPPY_CMD_READ );
395    KeStallExecutionProcessor( 100 );
396    FloppyWriteDATA( ControllerExtension->PortBase, ( Head << 2 ) | DeviceExtension->DriveSelect );
397    KeStallExecutionProcessor( 100 );
398    FloppyWriteDATA( ControllerExtension->PortBase, Cyl );
399    KeStallExecutionProcessor( 100 );
400    FloppyWriteDATA( ControllerExtension->PortBase, Head );
401    KeStallExecutionProcessor( 100 );
402    FloppyWriteDATA( ControllerExtension->PortBase, Sector );
403    KeStallExecutionProcessor( 100 );
404    FloppyWriteDATA( ControllerExtension->PortBase, MediaTypes[DeviceExtension->MediaType].SectorSizeCode );
405    KeStallExecutionProcessor( 100 );
406    FloppyWriteDATA( ControllerExtension->PortBase, MediaTypes[DeviceExtension->MediaType].SectorsPerTrack );
407    KeStallExecutionProcessor( 100 );
408    FloppyWriteDATA( ControllerExtension->PortBase, 0 );
409    KeStallExecutionProcessor( 100 );
410    FloppyWriteDATA( ControllerExtension->PortBase, 0xFF );
411    CHECKPOINT;
412    // eventually, the FDC will interrupt and we will read results then
413    return KeepObject;
414 }
415
416 NTSTATUS STDCALL
417 FloppyDispatchOpenClose(PDEVICE_OBJECT DeviceObject,
418                         PIRP Irp)
419 {
420    DPRINT("FloppyDispatchOpenClose\n");
421    return STATUS_SUCCESS;
422 }
423
424 NTSTATUS STDCALL
425 FloppyDispatchReadWrite(PDEVICE_OBJECT DeviceObject,
426                         PIRP Irp)
427 {
428   PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
429   PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)DeviceExtension->Controller->ControllerExtension;
430   PIO_STACK_LOCATION Stk = IoGetCurrentIrpStackLocation( Irp );
431   KIRQL oldlvl;
432   
433   if( Stk->Parameters.Read.ByteOffset.u.HighPart )
434     {
435       Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
436       Irp->IoStatus.Information = 0;
437       IoCompleteRequest( Irp, 1 );
438       return STATUS_INVALID_PARAMETER;
439     }
440   // store currentva in drivercontext
441   Irp->Tail.Overlay.DriverContext[0] = MmGetMdlVirtualAddress( Irp->MdlAddress );
442   DPRINT( "FloppyDispatchReadWrite: offset = %x, length = %x, va = %x\n",
443           Stk->Parameters.Read.ByteOffset.u.LowPart,
444           Stk->Parameters.Read.Length,
445           Irp->Tail.Overlay.DriverContext[0] );
446   // Queue IRP
447   Irp->IoStatus.Status = STATUS_SUCCESS;
448   Irp->IoStatus.Information = Stk->Parameters.Read.Length;
449   IoMarkIrpPending( Irp );
450   KeRaiseIrql( DISPATCH_LEVEL, &oldlvl );
451   IoAllocateController( ((PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Controller,
452                         DeviceObject,
453                         FloppyExecuteReadWrite,
454                         Irp );
455   KeLowerIrql( oldlvl );
456   DPRINT( "oldlvl = %x\n", oldlvl );
457   return STATUS_PENDING;
458 }
459
460 IO_ALLOCATION_ACTION STDCALL
461 FloppyAdapterControl(PDEVICE_OBJECT DeviceObject,
462                      PIRP Irp,
463                      PVOID MapRegisterBase,
464                      PVOID Context)
465 {
466   PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Context;
467
468   // just set the event, and return KeepObject
469   CHECKPOINT;
470   ControllerExtension->MapRegisterBase = MapRegisterBase;
471   KeSetEvent( &ControllerExtension->Event, 0, FALSE );
472   return KeepObject;
473 }
474
475 NTSTATUS STDCALL
476 FloppyDispatchDeviceControl(PDEVICE_OBJECT DeviceObject,
477                             PIRP Irp)
478 {
479    PIO_STACK_LOCATION IrpStack;
480    ULONG ControlCode, InputLength, OutputLength;
481    NTSTATUS Status;
482
483    DPRINT("FloppyDispatchDeviceControl\n");
484
485    IrpStack = IoGetCurrentIrpStackLocation(Irp);
486    ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
487    InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
488    OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
489
490    switch (ControlCode)
491    {
492       case IOCTL_DISK_GET_DRIVE_GEOMETRY:
493          if (OutputLength < sizeof(DISK_GEOMETRY))
494          {
495             Status = STATUS_INVALID_PARAMETER;
496          }
497          else
498          {
499             PDISK_GEOMETRY Geometry = Irp->AssociatedIrp.SystemBuffer;
500             // FIXME: read the first sector of the diskette
501             Geometry->MediaType = F3_1Pt44_512;
502             Geometry->Cylinders.QuadPart = 80;
503             Geometry->TracksPerCylinder = 2 * 18;
504             Geometry->SectorsPerTrack = 18;
505             Geometry->BytesPerSector = 512;
506             Status = STATUS_SUCCESS;
507             Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
508         }
509         break;
510      default:
511         Status = STATUS_INVALID_DEVICE_REQUEST;
512    }
513    Irp->IoStatus.Status = Status;
514    IoCompleteRequest(Irp, NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);    
515    return Status;
516 }
517
518 /*    ModuleEntry
519  *
520  *  DESCRIPTION:
521  *    This function initializes the driver, locates and claims 
522  *    hardware resources, and creates various NT objects needed
523  *    to process I/O requests.
524  *
525  *  RUN LEVEL:
526  *    PASSIVE_LEVEL
527  *
528  *  ARGUMENTS:
529  *    IN  PDRIVER_OBJECT   DriverObject  System allocated Driver Object
530  *                                       for this driver
531  *    IN  PUNICODE_STRING  RegistryPath  Name of registry driver service 
532  *                                       key
533  *
534  *  RETURNS:
535  *    NTSTATUS  
536  */
537 NTSTATUS STDCALL
538 DriverEntry(IN PDRIVER_OBJECT DriverObject,
539             IN PUNICODE_STRING RegistryPath)
540 {
541    DPRINT("Floppy driver\n");
542    
543    /* Export other driver entry points... */
544    DriverObject->MajorFunction[IRP_MJ_CREATE] = FloppyDispatchOpenClose;
545    DriverObject->MajorFunction[IRP_MJ_CLOSE] = FloppyDispatchOpenClose;
546    DriverObject->MajorFunction[IRP_MJ_READ] = FloppyDispatchReadWrite;
547    DriverObject->MajorFunction[IRP_MJ_WRITE] = FloppyDispatchReadWrite;
548    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
549      FloppyDispatchDeviceControl;
550    
551    /*  Try to detect controller and abort if it fails */
552    if (!FloppyCreateController(DriverObject,
553                                &ControllerParameters[0],
554                                0))
555      {
556         DPRINT("Could not find floppy controller\n");
557         return STATUS_NO_SUCH_DEVICE;
558      }
559    
560    return STATUS_SUCCESS;
561 }
562
563 /* EOF */