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