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