2002-10-01 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / 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