ReactOS  0.4.13-dev-241-g63286c6
floppy.c
Go to the documentation of this file.
1 /*
2  * ReactOS Floppy Driver
3  * Copyright (C) 2004, Vizzini (vizzini@plasmic.com)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * PROJECT: ReactOS Floppy Driver
20  * FILE: floppy.c
21  * PURPOSE: Main floppy driver routines
22  * PROGRAMMER: Vizzini (vizzini@plasmic.com)
23  * REVISIONS:
24  * 15-Feb-2004 vizzini - Created
25  * NOTES:
26  * - This driver is only designed to work with ISA-bus floppy controllers. This
27  * won't work on PCI-based controllers or on anything else with level-sensitive
28  * interrupts without modification. I don't think these controllers exist.
29  *
30  * ---- General to-do items ----
31  * TODO: Figure out why CreateClose isn't called any more. Seems to correspond
32  * with the driver not being unloadable.
33  * TODO: Think about StopDpcQueued -- could be a race; too tired atm to tell
34  * TODO: Clean up drive start/stop responsibilities (currently a mess...)
35  *
36  * ---- Support for proper media detection ----
37  * TODO: Handle MFM flag
38  * TODO: Un-hardcode the data rate from various places
39  * TODO: Proper media detection (right now we're hardcoded to 1.44)
40  * TODO: Media detection based on sector 1
41  */
42 
43 #include "precomp.h"
44 
45 #include <ntddk.h>
46 #include <debug.h>
47 
48 #include "ioctl.h"
49 #include "readwrite.h"
50 
51 /*
52  * Global controller info structures. Each controller gets one. Since the system
53  * will probably have only one, with four being a very unlikely maximum, a static
54  * global array is easiest to deal with.
55  */
58 
59 /* Queue thread management */
62 
63 
64 static VOID NTAPI
66 /*
67  * FUNCTION: Stop the floppy motor
68  * ARGUMENTS:
69  * UnusedDpc: DPC object that's going off
70  * DeferredContext: called with DRIVE_INFO for drive to turn off
71  * SystemArgument1: unused
72  * SystemArgument2: unused
73  * NOTES:
74  * - Must set an event to let other threads know we're done turning off the motor
75  * - Called back at DISPATCH_LEVEL
76  */
77 {
79 
82  UNREFERENCED_PARAMETER(UnusedDpc);
83 
85  ASSERT(ControllerInfo);
86 
87  TRACE_(FLOPPY, "MotorStopDpcFunc called\n");
88 
89  HwTurnOffMotor(ControllerInfo);
90  ControllerInfo->StopDpcQueued = FALSE;
92 }
93 
94 
95 VOID NTAPI
97 /*
98  * FUNCTION: Start the motor, taking into account proper handling of the timer race
99  * ARGUMENTS:
100  * DriveInfo: drive to start
101  * NOTES:
102  * - Never call HwTurnOnMotor() directly
103  * - This protocol manages a race between the cancel timer and the requesting thread.
104  * You wouldn't want to turn on the motor and then cancel the timer, because the
105  * cancel dpc might fire in the meantime, and that'd un-do what you just did. If you
106  * cancel the timer first, but KeCancelTimer returns false, the dpc is already running,
107  * so you have to wait until the dpc is completely done running, or else you'll race
108  * with the turner-offer
109  * - PAGED_CODE because we wait
110  */
111 {
112  PAGED_CODE();
113  ASSERT(DriveInfo);
114 
115  TRACE_(FLOPPY, "StartMotor called\n");
116 
117  if(DriveInfo->ControllerInfo->StopDpcQueued && !KeCancelTimer(&DriveInfo->ControllerInfo->MotorTimer))
118  {
119  /* Motor turner-offer is already running; wait for it to finish */
120  INFO_(FLOPPY, "StartMotor: motor turner-offer is already running; waiting for it\n");
121  KeWaitForSingleObject(&DriveInfo->ControllerInfo->MotorStoppedEvent, Executive, KernelMode, FALSE, NULL);
122  INFO_(FLOPPY, "StartMotor: wait satisfied\n");
123  }
124 
125  DriveInfo->ControllerInfo->StopDpcQueued = FALSE;
126 
127  if(HwTurnOnMotor(DriveInfo) != STATUS_SUCCESS)
128  {
129  WARN_(FLOPPY, "StartMotor(): warning: HwTurnOnMotor failed\n");
130  }
131 }
132 
133 
134 VOID NTAPI
136 /*
137  * FUNCTION: Stop all motors on the controller
138  * ARGUMENTS:
139  * DriveInfo: Drive to stop
140  * NOTES:
141  * - Never call HwTurnOffMotor() directly
142  * - This manages the timer cancelation race (see StartMotor for details).
143  * All we have to do is set up a timer.
144  */
145 {
146  LARGE_INTEGER StopTime;
147 
148  ASSERT(ControllerInfo);
149 
150  TRACE_(FLOPPY, "StopMotor called\n");
151 
152  /* one relative second, in 100-ns units */
153  StopTime.QuadPart = 10000000;
154  StopTime.QuadPart *= -1;
155 
156  KeClearEvent(&ControllerInfo->MotorStoppedEvent);
157  KeSetTimer(&ControllerInfo->MotorTimer, StopTime, &ControllerInfo->MotorStopDpc);
158  ControllerInfo->StopDpcQueued = TRUE;
159 }
160 
161 
164 /*
165  * FUNCTION: Wait for the controller to interrupt, and then clear the event
166  * ARGUMENTS:
167  * ControllerInfo: Controller to wait for
168  * Timeout: How long to wait for
169  * NOTES:
170  * - There is a small chance that an unexpected or spurious interrupt could
171  * be lost with this clear/wait/clear scheme used in this driver. This is
172  * deemed to be an acceptable risk due to the unlikeliness of the scenario,
173  * and the fact that it'll probably work fine next time.
174  * - PAGED_CODE because it waits
175  */
176 {
178 
179  PAGED_CODE();
180  ASSERT(ControllerInfo);
181 
183  KeClearEvent(&ControllerInfo->SynchEvent);
184 
185  return Status;
186 }
187 
190  PIRP Irp)
191 /*
192  * FUNCTION: Dispatch function called for Create and Close IRPs
193  * ARGUMENTS:
194  * DeviceObject: DeviceObject that is the target of the IRP
195  * Irp: IRP to process
196  * RETURNS:
197  * STATUS_SUCCESS in all cases
198  * NOTES:
199  * - The Microsoft sample drivers tend to return FILE_OPENED in Information, so I do too.
200  * - No reason to fail the device open
201  * - No state to track, so this routine is easy
202  * - Can be called <= DISPATCH_LEVEL
203  *
204  * TODO: Figure out why this isn't getting called
205  */
206 {
208 
209  TRACE_(FLOPPY, "CreateClose called\n");
210 
211  Irp->IoStatus.Status = STATUS_SUCCESS;
212  Irp->IoStatus.Information = FILE_OPENED;
213 
215 
216  return STATUS_SUCCESS;
217 }
218 
219 
220 static NTSTATUS NTAPI
222 /*
223  * FUNCTION: Start the recalibration process
224  * ARGUMENTS:
225  * DriveInfo: Pointer to the driveinfo struct associated with the targeted drive
226  * RETURNS:
227  * STATUS_SUCCESS on successful starting of the process
228  * STATUS_IO_DEVICE_ERROR if it fails
229  * NOTES:
230  * - Sometimes you have to do two recalibrations, particularly if the disk has <80 tracks.
231  * - PAGED_CODE because we wait
232  */
233 {
235  ULONG i;
236 
237  PAGED_CODE();
238  ASSERT(DriveInfo);
239 
240  /* first turn on the motor */
241  /* Must stop after every start, prior to return */
242  StartMotor(DriveInfo);
243 
244  /* set the data rate */
245  WARN_(FLOPPY, "FIXME: UN-HARDCODE DATA RATE\n");
246  if(HwSetDataRate(DriveInfo->ControllerInfo, 0) != STATUS_SUCCESS)
247  {
248  WARN_(FLOPPY, "Recalibrate: HwSetDataRate failed\n");
249  StopMotor(DriveInfo->ControllerInfo);
250  return STATUS_IO_DEVICE_ERROR;
251  }
252 
253  /* clear the event just in case the last call forgot */
254  KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);
255 
256  /* sometimes you have to do this twice; we'll just do it twice all the time since
257  * we don't know if the people calling this Recalibrate routine expect a disk to
258  * even be in the drive, and if so, if that disk is formatted.
259  */
260  for(i = 0; i < 2; i++)
261  {
262  /* Send the command */
263  Status = HwRecalibrate(DriveInfo);
264  if(Status != STATUS_SUCCESS)
265  {
266  WARN_(FLOPPY, "Recalibrate: HwRecalibrate returned error\n");
267  continue;
268  }
269 
271 
272  /* Get the results */
274  if(Status != STATUS_SUCCESS)
275  {
276  WARN_(FLOPPY, "Recalibrate: HwRecalibrateResult returned error\n");
277  break;
278  }
279  }
280 
281  KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);
282 
283  /* Must stop after every start, prior to return */
284  StopMotor(DriveInfo->ControllerInfo);
285 
286  return Status;
287 }
288 
289 
292 /*
293  * FUNCTION: Reset the drive's change flag (as reflected in the DIR)
294  * ARGUMENTS:
295  * DriveInfo: the drive to reset
296  * RETURNS:
297  * STATUS_SUCCESS if the changeline is cleared
298  * STATUS_NO_MEDIA_IN_DEVICE if the changeline cannot be cleared
299  * STATUS_IO_DEVICE_ERROR if the controller cannot be communicated with
300  * NOTES:
301  * - Change reset procedure: recalibrate, seek 1, seek 0
302  * - If the line is still set after that, there's clearly no disk in the
303  * drive, so we return STATUS_NO_MEDIA_IN_DEVICE
304  * - PAGED_CODE because we wait
305  */
306 {
307  BOOLEAN DiskChanged;
308 
309  PAGED_CODE();
310  ASSERT(DriveInfo);
311 
312  TRACE_(FLOPPY, "ResetChangeFlag called\n");
313 
314  /* Try to recalibrate. We don't care if it works. */
315  Recalibrate(DriveInfo);
316 
317  /* clear spurious interrupts in prep for seeks */
318  KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);
319 
320  /* must re-start the drive because Recalibrate() stops it */
321  StartMotor(DriveInfo);
322 
323  /* Seek to 1 */
324  if(HwSeek(DriveInfo, 1) != STATUS_SUCCESS)
325  {
326  WARN_(FLOPPY, "ResetChangeFlag(): HwSeek failed; returning STATUS_IO_DEVICE_ERROR\n");
327  StopMotor(DriveInfo->ControllerInfo);
328  return STATUS_IO_DEVICE_ERROR;
329  }
330 
332 
334  {
335  WARN_(FLOPPY, "ResetChangeFlag(): HwSenseInterruptStatus failed; bailing out\n");
336  StopMotor(DriveInfo->ControllerInfo);
337  return STATUS_IO_DEVICE_ERROR;
338  }
339 
340  /* Seek back to 0 */
341  if(HwSeek(DriveInfo, 0) != STATUS_SUCCESS)
342  {
343  WARN_(FLOPPY, "ResetChangeFlag(): HwSeek failed; returning STATUS_IO_DEVICE_ERROR\n");
344  StopMotor(DriveInfo->ControllerInfo);
345  return STATUS_IO_DEVICE_ERROR;
346  }
347 
349 
351  {
352  WARN_(FLOPPY, "ResetChangeFlag(): HwSenseInterruptStatus #2 failed; bailing\n");
353  StopMotor(DriveInfo->ControllerInfo);
354  return STATUS_IO_DEVICE_ERROR;
355  }
356 
357  /* Check the change bit */
358  if(HwDiskChanged(DriveInfo, &DiskChanged) != STATUS_SUCCESS)
359  {
360  WARN_(FLOPPY, "ResetChangeFlag(): HwDiskChanged failed; returning STATUS_IO_DEVICE_ERROR\n");
361  StopMotor(DriveInfo->ControllerInfo);
362  return STATUS_IO_DEVICE_ERROR;
363  }
364 
365  StopMotor(DriveInfo->ControllerInfo);
366 
367  /* if the change flag is still set, there's probably no media in the drive. */
368  if(DiskChanged)
370 
371  /* else we're done! */
372  return STATUS_SUCCESS;
373 }
374 
375 
376 static VOID NTAPI
378 /*
379  * FUNCTION: Unload the driver from memory
380  * ARGUMENTS:
381  * DriverObject - The driver that is being unloaded
382  */
383 {
384  ULONG i,j;
385 
386  PAGED_CODE();
388 
389  TRACE_(FLOPPY, "unloading\n");
390 
394 
395  for(i = 0; i < gNumberOfControllers; i++)
396  {
398  continue;
399 
400  for(j = 0; j < gControllerInfo[i].NumberOfDrives; j++)
401  {
402  if(!gControllerInfo[i].DriveInfo[j].Initialized)
403  continue;
404 
405  if(gControllerInfo[i].DriveInfo[j].DeviceObject)
406  {
408 
409  RtlInitUnicodeString(&Link, gControllerInfo[i].DriveInfo[j].SymLinkBuffer);
411 
412  RtlInitUnicodeString(&Link, gControllerInfo[i].DriveInfo[j].ArcPathBuffer);
414 
416  }
417  }
418 
420 
421  /* Power down the controller */
423  {
424  WARN_(FLOPPY, "unload: warning: HwPowerOff failed\n");
425  }
426  }
427 }
428 
429 
430 static NTSTATUS NTAPI
432  PUNICODE_STRING PathName,
435  PKEY_VALUE_FULL_INFORMATION *BusInformation,
436  CONFIGURATION_TYPE ControllerType,
437  ULONG ControllerNumber,
438  PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
439  CONFIGURATION_TYPE PeripheralType,
440  ULONG PeripheralNumber,
441  PKEY_VALUE_FULL_INFORMATION *PeripheralInformation)
442 /*
443  * FUNCTION: Callback to IoQueryDeviceDescription, which tells us about our controllers
444  * ARGUMENTS:
445  * Context: Unused
446  * PathName: Unused
447  * BusType: Type of the bus that our controller is on
448  * BusNumber: Number of the bus that our controller is on
449  * BusInformation: Unused
450  * ControllerType: Unused
451  * ControllerNumber: Number of the controller that we're adding
452  * ControllerInformation: Full configuration information for our controller
453  * PeripheralType: Unused
454  * PeripheralNumber: Unused
455  * PeripheralInformation: Full configuration information for each drive on our controller
456  * RETURNS:
457  * STATUS_SUCCESS in all cases
458  * NOTES:
459  * - The only documentation I've found about the contents of these structures is
460  * from the various Microsoft floppy samples and from the DDK headers. They're
461  * very vague, though, so I'm only mostly sure that this stuff is correct, as
462  * the MS samples do things completely differently than I have done them. Seems
463  * to work in my VMWare, though.
464  * - Basically, the function gets all of the information (port, dma, irq) about the
465  * controller, and then loops through all of the drives presented in PeripheralInformation.
466  * - Each controller has a CONTROLLER_INFO created for it, and each drive has a DRIVE_INFO.
467  * - Device objects are created for each drive (not controller), as that's the targeted
468  * device in the eyes of the rest of the OS. Each DRIVE_INFO points to a single CONTROLLER_INFO.
469  * - We only support up to four controllers in the whole system, each of which supports up to four
470  * drives.
471  */
472 {
473  PKEY_VALUE_FULL_INFORMATION ControllerFullDescriptor = ControllerInformation[IoQueryDeviceConfigurationData];
474  PCM_FULL_RESOURCE_DESCRIPTOR ControllerResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)ControllerFullDescriptor +
475  ControllerFullDescriptor->DataOffset);
476 
477  PKEY_VALUE_FULL_INFORMATION PeripheralFullDescriptor = PeripheralInformation[IoQueryDeviceConfigurationData];
478  PCM_FULL_RESOURCE_DESCRIPTOR PeripheralResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)PeripheralFullDescriptor +
479  PeripheralFullDescriptor->DataOffset);
480 
481  PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
482  PCM_FLOPPY_DEVICE_DATA FloppyDeviceData;
483  UCHAR i;
484 
485  PAGED_CODE();
486  UNREFERENCED_PARAMETER(PeripheralType);
487  UNREFERENCED_PARAMETER(PeripheralNumber);
488  UNREFERENCED_PARAMETER(BusInformation);
490  UNREFERENCED_PARAMETER(ControllerType);
491  UNREFERENCED_PARAMETER(PathName);
492 
493 
494  TRACE_(FLOPPY, "ConfigCallback called with ControllerNumber %d\n", ControllerNumber);
495 
499 
500  /* Get controller interrupt level/vector, dma channel, and port base */
501  for(i = 0; i < ControllerResourceDescriptor->PartialResourceList.Count; i++)
502  {
504 
505  PartialDescriptor = &ControllerResourceDescriptor->PartialResourceList.PartialDescriptors[i];
506 
507  if(PartialDescriptor->Type == CmResourceTypeInterrupt)
508  {
509  gControllerInfo[gNumberOfControllers].Level = PartialDescriptor->u.Interrupt.Level;
510  gControllerInfo[gNumberOfControllers].Vector = PartialDescriptor->u.Interrupt.Vector;
511 
512  if(PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
514  else
516  }
517 
518  else if(PartialDescriptor->Type == CmResourceTypePort)
519  {
521  ULONG AddressSpace = 0x1; /* I/O Port Range */
522 
523  if(!HalTranslateBusAddress(BusType, BusNumber, PartialDescriptor->u.Port.Start, &AddressSpace, &TranslatedAddress))
524  {
525  WARN_(FLOPPY, "HalTranslateBusAddress failed; returning\n");
526  return STATUS_IO_DEVICE_ERROR;
527  }
528 
529  if(AddressSpace == 0)
531  else
533  }
534 
535  else if(PartialDescriptor->Type == CmResourceTypeDma)
536  gControllerInfo[gNumberOfControllers].Dma = PartialDescriptor->u.Dma.Channel;
537  }
538 
539  /* Start with 0 drives, then go looking */
541 
542  /* learn about drives attached to controller */
543  for(i = 0; i < PeripheralResourceDescriptor->PartialResourceList.Count; i++)
544  {
546 
547  PartialDescriptor = &PeripheralResourceDescriptor->PartialResourceList.PartialDescriptors[i];
548 
549  if(PartialDescriptor->Type != CmResourceTypeDeviceSpecific)
550  continue;
551 
552  FloppyDeviceData = (PCM_FLOPPY_DEVICE_DATA)(PartialDescriptor + 1);
553 
555  DriveInfo->UnitNumber = i;
556 
557  DriveInfo->FloppyDeviceData.MaxDensity = FloppyDeviceData->MaxDensity;
558  DriveInfo->FloppyDeviceData.MountDensity = FloppyDeviceData->MountDensity;
559  DriveInfo->FloppyDeviceData.StepRateHeadUnloadTime = FloppyDeviceData->StepRateHeadUnloadTime;
560  DriveInfo->FloppyDeviceData.HeadLoadTime = FloppyDeviceData->HeadLoadTime;
561  DriveInfo->FloppyDeviceData.MotorOffTime = FloppyDeviceData->MotorOffTime;
562  DriveInfo->FloppyDeviceData.SectorLengthCode = FloppyDeviceData->SectorLengthCode;
563  DriveInfo->FloppyDeviceData.SectorPerTrack = FloppyDeviceData->SectorPerTrack;
564  DriveInfo->FloppyDeviceData.ReadWriteGapLength = FloppyDeviceData->ReadWriteGapLength;
565  DriveInfo->FloppyDeviceData.FormatGapLength = FloppyDeviceData->FormatGapLength;
566  DriveInfo->FloppyDeviceData.FormatFillCharacter = FloppyDeviceData->FormatFillCharacter;
567  DriveInfo->FloppyDeviceData.HeadSettleTime = FloppyDeviceData->HeadSettleTime;
568  DriveInfo->FloppyDeviceData.MotorSettleTime = FloppyDeviceData->MotorSettleTime;
569  DriveInfo->FloppyDeviceData.MaximumTrackValue = FloppyDeviceData->MaximumTrackValue;
570  DriveInfo->FloppyDeviceData.DataTransferLength = FloppyDeviceData->DataTransferLength;
571 
572  /* Once it's all set up, acknowledge its existence in the controller info object */
574  }
575 
578 
579  return STATUS_SUCCESS;
580 }
581 
582 
583 static BOOLEAN NTAPI
585 /*
586  * FUNCTION: Interrupt service routine for the controllers
587  * ARGUMENTS:
588  * Interrupt: Interrupt object representing the interrupt that occured
589  * ServiceContext: Pointer to the ControllerInfo object that caused the interrupt
590  * RETURNS:
591  * TRUE in all cases (see notes)
592  * NOTES:
593  * - We should always be the target of the interrupt, being an edge-triggered ISA interrupt, but
594  * this won't be the case with a level-sensitive system like PCI
595  * - Note that it probably doesn't matter if the interrupt isn't dismissed, as it's edge-triggered.
596  * It probably won't keep re-interrupting.
597  * - There are two different ways to dismiss a floppy interrupt. If the command has a result phase
598  * (see intel datasheet), you dismiss the interrupt by reading the first data byte. If it does
599  * not, you dismiss the interrupt by doing a Sense Interrupt command. Again, because it's edge-
600  * triggered, this is safe to not do here, as we can just wait for the DPC.
601  * - Either way, we don't want to do this here. The controller shouldn't interrupt again, so we'll
602  * schedule a DPC to take care of it.
603  * - This driver really cannot share interrupts, as I don't know how to conclusively say
604  * whether it was our controller that interrupted or not. I just have to assume that any time
605  * my ISR gets called, it was my board that called it. Dumb design, yes, but it goes back to
606  * the semantics of ISA buses. That, and I don't know much about ISA drivers. :-)
607  * UPDATE: The high bit of Status Register A seems to work on non-AT controllers.
608  * - Called at DIRQL
609  */
610 {
612 
613  UNREFERENCED_PARAMETER(Interrupt);
614 
615  ASSERT(ControllerInfo);
616 
617  TRACE_(FLOPPY, "ISR called\n");
618 
619  /*
620  * Due to the stupidity of the drive/controller relationship on the floppy drive, only one device object
621  * can have an active interrupt pending. Due to the nature of these IRPs, though, there will only ever
622  * be one thread expecting an interrupt at a time, and furthermore, Interrupts (outside of spurious ones)
623  * won't ever happen unless a thread is expecting them. Therefore, all we have to do is signal an event
624  * and we're done. Queue a DPC and leave.
625  */
626  KeInsertQueueDpc(&ControllerInfo->Dpc, NULL, NULL);
627 
628  return TRUE;
629 }
630 
631 
632 VOID NTAPI
634 /*
635  * FUNCTION: This DPC gets queued by every ISR. Does the real per-interrupt work.
636  * ARGUMENTS:
637  * UnusedDpc: Pointer to the DPC object that represents our function
638  * DeviceObject: Device that this DPC is running for
639  * Irp: Unused
640  * Context: Pointer to our ControllerInfo struct
641  * NOTES:
642  * - This function just kicks off whatever the SynchEvent is and returns. We depend on
643  * the thing that caused the drive to interrupt to handle the work of clearing the interrupt.
644  * This enables us to get back to PASSIVE_LEVEL and not hog system time on a really stupid,
645  * slow, screwed-up piece of hardware.
646  * - If nothing is waiting for us to set the event, the interrupt is effectively lost and will
647  * never be dismissed. I wonder if this will become a problem.
648  * - Called at DISPATCH_LEVEL
649  */
650 {
651  PCONTROLLER_INFO ControllerInfo = (PCONTROLLER_INFO)Context;
652 
653  UNREFERENCED_PARAMETER(UnusedDpc);
656 
657  ASSERT(ControllerInfo);
658 
659  TRACE_(FLOPPY, "DpcForIsr called\n");
660 
661  KeSetEvent(&ControllerInfo->SynchEvent, EVENT_INCREMENT, FALSE);
662 }
663 
664 
665 static NTSTATUS NTAPI
667 /*
668  * FUNCTION: Initialize a newly-found controller
669  * ARGUMENTS:
670  * ControllerInfo: pointer to the controller to be initialized
671  * RETURNS:
672  * STATUS_SUCCESS if the controller is successfully initialized
673  * STATUS_IO_DEVICE_ERROR otherwise
674  */
675 {
676  int i;
677  UCHAR HeadLoadTime;
678  UCHAR HeadUnloadTime;
679  UCHAR StepRateTime;
680  UCHAR ControllerVersion;
681 
682  PAGED_CODE();
683  ASSERT(ControllerInfo);
684 
685  TRACE_(FLOPPY, "InitController called with Controller 0x%p\n", ControllerInfo);
686 
687  /* Get controller in a known state */
688  if(HwConfigure(ControllerInfo, FALSE, TRUE, TRUE, 0, 0) != STATUS_SUCCESS)
689  {
690  WARN_(FLOPPY, "InitController: unable to configure controller\n");
691  return STATUS_IO_DEVICE_ERROR;
692  }
693 
694  /* Get the controller version */
695  ControllerVersion = HwGetVersion(ControllerInfo);
696 
697  KeClearEvent(&ControllerInfo->SynchEvent);
698 
699  /* Reset the controller */
700  if(HwReset(ControllerInfo) != STATUS_SUCCESS)
701  {
702  WARN_(FLOPPY, "InitController: unable to reset controller\n");
703  return STATUS_IO_DEVICE_ERROR;
704  }
705 
706  INFO_(FLOPPY, "InitController: waiting for initial interrupt\n");
707 
708  /* Wait for an interrupt */
709  WaitForControllerInterrupt(ControllerInfo, NULL);
710 
711  /* Reset means you have to clear each of the four interrupts (one per drive) */
712  for(i = 0; i < MAX_DRIVES_PER_CONTROLLER; i++)
713  {
714  INFO_(FLOPPY, "InitController: Sensing interrupt %d\n", i);
715 
716  if(HwSenseInterruptStatus(ControllerInfo) != STATUS_SUCCESS)
717  {
718  WARN_(FLOPPY, "InitController: Unable to clear interrupt 0x%x\n", i);
719  return STATUS_IO_DEVICE_ERROR;
720  }
721  }
722 
723  INFO_(FLOPPY, "InitController: done sensing interrupts\n");
724 
725  /* Next, see if we have the right version to do implied seek */
726  if(ControllerVersion == VERSION_ENHANCED)
727  {
728  /* If so, set that up -- all defaults below except first TRUE for EIS */
729  if(HwConfigure(ControllerInfo, TRUE, TRUE, TRUE, 0, 0) != STATUS_SUCCESS)
730  {
731  WARN_(FLOPPY, "InitController: unable to set up implied seek\n");
732  ControllerInfo->ImpliedSeeks = FALSE;
733  }
734  else
735  {
736  INFO_(FLOPPY, "InitController: implied seeks set!\n");
737  ControllerInfo->ImpliedSeeks = TRUE;
738  }
739 
740  /*
741  * FIXME: Figure out the answer to the below
742  *
743  * I must admit that I'm really confused about the Model 30 issue. At least one
744  * important bit (the disk change bit in the DIR) is flipped if this is a Model 30
745  * controller. However, at least one other floppy driver believes that there are only
746  * two computers that are guaranteed to have a Model 30 controller:
747  * - IBM Thinkpad 750
748  * - IBM PS2e
749  *
750  * ...and another driver only lists a config option for "thinkpad", that flips
751  * the change line. A third driver doesn't mention the Model 30 issue at all.
752  *
753  * What I can't tell is whether or not the average, run-of-the-mill computer now has
754  * a Model 30 controller. For the time being, I'm going to wire this to FALSE,
755  * and just not support the computers mentioned above, while I try to figure out
756  * how ubiquitous these newfangled 30 thingies are.
757  */
758  //ControllerInfo->Model30 = TRUE;
759  ControllerInfo->Model30 = FALSE;
760  }
761  else
762  {
763  INFO_(FLOPPY, "InitController: enhanced version not supported; disabling implied seeks\n");
764  ControllerInfo->ImpliedSeeks = FALSE;
765  ControllerInfo->Model30 = FALSE;
766  }
767 
768  /* Specify */
769  WARN_(FLOPPY, "FIXME: Figure out speed\n");
770  HeadLoadTime = SPECIFY_HLT_500K;
771  HeadUnloadTime = SPECIFY_HUT_500K;
772  StepRateTime = SPECIFY_SRT_500K;
773 
774  INFO_(FLOPPY, "InitController: setting data rate\n");
775 
776  /* Set data rate */
777  if(HwSetDataRate(ControllerInfo, DRSR_DSEL_500KBPS) != STATUS_SUCCESS)
778  {
779  WARN_(FLOPPY, "InitController: unable to set data rate\n");
780  return STATUS_IO_DEVICE_ERROR;
781  }
782 
783  INFO_(FLOPPY, "InitController: issuing specify command to controller\n");
784 
785  /* Don't disable DMA --> enable dma (dumb & confusing) */
786  if(HwSpecify(ControllerInfo, HeadLoadTime, HeadUnloadTime, StepRateTime, FALSE) != STATUS_SUCCESS)
787  {
788  WARN_(FLOPPY, "InitController: unable to specify options\n");
789  return STATUS_IO_DEVICE_ERROR;
790  }
791 
792  /* Init the stop stuff */
793  KeInitializeDpc(&ControllerInfo->MotorStopDpc, MotorStopDpcFunc, ControllerInfo);
794  KeInitializeTimer(&ControllerInfo->MotorTimer);
796  ControllerInfo->StopDpcQueued = FALSE;
797 
798  /*
799  * Recalibrate each drive on the controller (depends on StartMotor, which depends on the timer stuff above)
800  * We don't even know if there is a disk in the drive, so this may not work, but that's OK.
801  */
802  for(i = 0; i < ControllerInfo->NumberOfDrives; i++)
803  {
804  INFO_(FLOPPY, "InitController: recalibrating drive 0x%x on controller 0x%p\n", i, ControllerInfo);
805  Recalibrate(&ControllerInfo->DriveInfo[i]);
806  }
807 
808  INFO_(FLOPPY, "InitController: done initializing; returning STATUS_SUCCESS\n");
809 
810  return STATUS_SUCCESS;
811 }
812 
813 
814 static BOOLEAN NTAPI
816 /*
817  * FUNCTION: Called on initialization to find our controllers and build device and controller objects for them
818  * ARGUMENTS:
819  * DriverObject: Our driver's DriverObject (so we can create devices against it)
820  * RETURNS:
821  * FALSE if we can't allocate a device, adapter, or interrupt object, or if we fail to find any controllers
822  * TRUE otherwise (i.e. we have at least one fully-configured controller)
823  * NOTES:
824  * - Currently we only support ISA buses.
825  * - BUG: Windows 2000 seems to clobber the response from the IoQueryDeviceDescription callback, so now we
826  * just test a boolean value in the first object to see if it was completely populated. The same value
827  * is tested for each controller before we build device objects for it.
828  * TODO:
829  * - Report resource usage to the HAL
830  */
831 {
832  INTERFACE_TYPE InterfaceType = Isa;
833  CONFIGURATION_TYPE ControllerType = DiskController;
834  CONFIGURATION_TYPE PeripheralType = FloppyDiskPeripheral;
837  UCHAR i;
838  UCHAR j;
839 
840  PAGED_CODE();
841 
842  /* Find our controllers on all ISA buses */
843  IoQueryDeviceDescription(&InterfaceType, 0, &ControllerType, 0, &PeripheralType, 0, ConfigCallback, 0);
844 
845  /*
846  * w2k breaks the return val from ConfigCallback, so we have to hack around it, rather than just
847  * looking for a return value from ConfigCallback. We expect at least one controller.
848  */
849  if(!gControllerInfo[0].Populated)
850  {
851  WARN_(FLOPPY, "AddControllers: failed to get controller info from registry\n");
852  return FALSE;
853  }
854 
855  /* Now that we have a controller, set it up with the system */
856  for(i = 0; i < gNumberOfControllers && gControllerInfo[i].NumberOfDrives > 0; i++)
857  {
858  /* 0: Report resource usage to the kernel, to make sure they aren't assigned to anyone else */
859  /* FIXME: Implement me. */
860 
861  /* 1: Set up interrupt */
864  &gControllerInfo[i].MappedLevel, &Affinity);
865 
866  /* Must set up the DPC before we connect the interrupt */
868 
869  INFO_(FLOPPY, "Connecting interrupt %d to controller%d (object 0x%p)\n", gControllerInfo[i].MappedVector,
870  i, &gControllerInfo[i]);
871 
872  /* NOTE: We cannot share our interrupt, even on level-triggered buses. See Isr() for details. */
874  gControllerInfo[i].MappedLevel, gControllerInfo[i].MappedLevel, gControllerInfo[i].InterruptMode,
875  FALSE, Affinity, 0) != STATUS_SUCCESS)
876  {
877  WARN_(FLOPPY, "AddControllers: unable to connect interrupt\n");
878  continue;
879  }
880 
881  /* 2: Set up DMA */
887  DeviceDescription.MaximumLength = 2*18*512; /* based on a 1.44MB floppy */
888 
889  /* DMA 0,1,2,3 are 8-bit; 4,5,6,7 are 16-bit (4 is chain i think) */
891 
893 
894  if(!gControllerInfo[i].AdapterObject)
895  {
896  WARN_(FLOPPY, "AddControllers: unable to allocate an adapter object\n");
898  continue;
899  }
900 
901  /* 2b: Initialize the new controller */
903  {
904  WARN_(FLOPPY, "AddControllers(): Unable to set up controller %d - initialization failed\n", i);
906  continue;
907  }
908 
909  /* 2c: Set the controller's initialized flag so we know to release stuff in Unload */
911 
912  /* 3: per-drive setup */
913  for(j = 0; j < gControllerInfo[i].NumberOfDrives; j++)
914  {
915  WCHAR DeviceNameBuf[MAX_DEVICE_NAME];
917  UNICODE_STRING LinkName;
918  UNICODE_STRING ArcPath;
919  UCHAR DriveNumber;
920 
921  INFO_(FLOPPY, "AddControllers(): Configuring drive %d on controller %d\n", i, j);
922 
923  /*
924  * 3a: create a device object for the drive
925  * Controllers and drives are 0-based, so the combos are:
926  * 0: 0,0
927  * 1: 0,1
928  * 2: 0,2
929  * 3: 0,3
930  * 4: 1,0
931  * 5: 1,1
932  * ...
933  * 14: 3,2
934  * 15: 3,3
935  */
936 
937  DriveNumber = (UCHAR)(i*4 + j); /* loss of precision is OK; there are only 16 of 'em */
938 
939  RtlZeroMemory(&DeviceNameBuf, MAX_DEVICE_NAME * sizeof(WCHAR));
940  swprintf(DeviceNameBuf, L"\\Device\\Floppy%d", DriveNumber);
941  RtlInitUnicodeString(&DeviceName, DeviceNameBuf);
942 
945  &gControllerInfo[i].DriveInfo[j].DeviceObject) != STATUS_SUCCESS)
946  {
947  WARN_(FLOPPY, "AddControllers: unable to register a Device object\n");
949  continue; /* continue on to next drive */
950  }
951 
952  INFO_(FLOPPY, "AddControllers: New device: %S (0x%p)\n", DeviceNameBuf, gControllerInfo[i].DriveInfo[j].DeviceObject);
953 
954  /* 3b.5: Create an ARC path in case we're booting from this drive */
955  swprintf(gControllerInfo[i].DriveInfo[j].ArcPathBuffer,
956  L"\\ArcName\\multi(%d)disk(%d)fdisk(%d)", gControllerInfo[i].BusNumber, i, DriveNumber);
957 
958  RtlInitUnicodeString(&ArcPath, gControllerInfo[i].DriveInfo[j].ArcPathBuffer);
959  IoAssignArcName(&ArcPath, &DeviceName);
960 
961  /* 3c: Set flags up */
963 
964  /* 3d: Create a symlink */
965  swprintf(gControllerInfo[i].DriveInfo[j].SymLinkBuffer, L"\\DosDevices\\%c:", DriveNumber + 'A');
966  RtlInitUnicodeString(&LinkName, gControllerInfo[i].DriveInfo[j].SymLinkBuffer);
968  {
969  WARN_(FLOPPY, "AddControllers: Unable to create a symlink for drive %d\n", DriveNumber);
971  IoDeassignArcName(&ArcPath);
972  continue; /* continue to next drive */
973  }
974 
975  /* 3e: Increase global floppy drives count */
977 
978  /* 3f: Set up the DPC */
980 
981  /* 3g: Point the device extension at our DriveInfo struct */
983 
984  /* 3h: neat comic strip */
985 
986  /* 3i: set the initial media type to unknown */
987  memset(&gControllerInfo[i].DriveInfo[j].DiskGeometry, 0, sizeof(DISK_GEOMETRY));
989 
990  /* 3j: Now that we're done, set the Initialized flag so we know to free this in Unload */
992 
993  /* 3k: Clear the DO_DEVICE_INITIALIZING flag */
995 
996  /* 3l: Attempt to get drive info - if a floppy is already present */
997  StartMotor(&gControllerInfo[i].DriveInfo[j]);
999  StopMotor(gControllerInfo[i].DriveInfo[j].ControllerInfo);
1000  }
1001  }
1002 
1003  INFO_(FLOPPY, "AddControllers: --------------------------------------------> finished adding controllers\n");
1004 
1005  return (IoGetConfigurationInformation()->FloppyCount != 0);
1006 }
1007 
1008 
1009 VOID NTAPI
1011 /*
1012  * FUNCTION: Process an IRP when the media has changed, and possibly notify the user
1013  * ARGUMENTS:
1014  * DeviceObject: DeviceObject associated with the IRP
1015  * Irp: IRP that we're failing due to change
1016  * NOTES:
1017  * - This procedure is documented in the DDK by "Notifying the File System of Possible Media Changes",
1018  * "IoSetHardErrorOrVerifyDevice", and by "Responding to Check-Verify Requests from the File System".
1019  * - Callable at <= DISPATCH_LEVEL
1020  */
1021 {
1023 
1024  TRACE_(FLOPPY, "SignalMediaChanged called\n");
1025 
1026  DriveInfo->DiskChangeCount++;
1027 
1028  /* If volume is not mounted, do NOT set verify and return STATUS_IO_DEVICE_ERROR */
1029  if(!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
1030  {
1031  Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
1032  Irp->IoStatus.Information = 0;
1033  return;
1034  }
1035 
1036  /* Notify the filesystem that it will need to verify the volume */
1038  Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
1039  Irp->IoStatus.Information = 0;
1040 
1041  /*
1042  * If this is a user-based, threaded request, let the IO manager know to pop up a box asking
1043  * the user to supply the correct media, but only if the error (which we just picked out above)
1044  * is deemed by the IO manager to be "user induced". The reason we don't just unconditionally
1045  * call IoSetHardError... is because MS might change the definition of "user induced" some day,
1046  * and we don't want to have to remember to re-code this.
1047  */
1048  if(Irp->Tail.Overlay.Thread && IoIsErrorUserInduced(Irp->IoStatus.Status))
1050 }
1051 
1052 
1053 static VOID NTAPI
1055 /*
1056  * FUNCTION: Thread that manages the queue and dispatches any queued requests
1057  * ARGUMENTS:
1058  * Context: unused
1059  */
1060 {
1061  PIRP Irp;
1062  PIO_STACK_LOCATION Stack;
1064  PVOID Objects[2];
1065 
1066  PAGED_CODE();
1068 
1069  Objects[0] = &QueueSemaphore;
1070  Objects[1] = &QueueThreadTerminate;
1071 
1072  for(;;)
1073  {
1075 
1077  {
1078  INFO_(FLOPPY, "QueueThread terminating\n");
1079  return;
1080  }
1081 
1082  INFO_(FLOPPY, "QueueThread: servicing an IRP\n");
1083 
1084  Irp = IoCsqRemoveNextIrp(&Csq, 0);
1085 
1086  /* we won't get an irp if it was canceled */
1087  if(!Irp)
1088  {
1089  INFO_(FLOPPY, "QueueThread: IRP queue empty\n");
1090  continue;
1091  }
1092 
1093  DeviceObject = (PDEVICE_OBJECT)Irp->Tail.Overlay.DriverContext[0];
1094 
1096 
1098 
1099  /* Decide what to do with the IRP */
1100  switch(Stack->MajorFunction)
1101  {
1102  case IRP_MJ_READ:
1103  case IRP_MJ_WRITE:
1105  break;
1106 
1107  case IRP_MJ_DEVICE_CONTROL:
1109  break;
1110 
1111  default:
1112  WARN_(FLOPPY, "QueueThread(): Unrecognized irp: mj: 0x%x\n", Stack->MajorFunction);
1113  Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1114  Irp->IoStatus.Information = 0;
1116  }
1117  }
1118 }
1119 
1120 
1123 /*
1124  * FUNCTION: Entry-point for the driver
1125  * ARGUMENTS:
1126  * DriverObject: Our driver object
1127  * RegistryPath: Unused
1128  * RETURNS:
1129  * STATUS_SUCCESS on successful initialization of at least one drive
1130  * STATUS_NO_SUCH_DEVICE if we didn't find even one drive
1131  * STATUS_UNSUCCESSFUL otherwise
1132  */
1133 {
1134  HANDLE ThreadHandle;
1135 
1137 
1138  /*
1139  * Set up dispatch routines
1140  */
1146 
1148 
1149  /*
1150  * We depend on some zeroes in these structures. I know this is supposed to be
1151  * initialized to 0 by the complier but this makes me feel beter.
1152  */
1153  memset(&gControllerInfo, 0, sizeof(gControllerInfo));
1154 
1155  /*
1156  * Set up queue. This routine cannot fail (trust me, I wrote it).
1157  */
1160 
1161  /*
1162  * ...and its lock
1163  */
1165 
1166  /*
1167  * ...and the queue list itself
1168  */
1170 
1171  /*
1172  * The queue is counted by a semaphore. The queue management thread
1173  * blocks on this semaphore, so if requests come in faster than the queue
1174  * thread can handle them, the semaphore count goes up.
1175  */
1176  KeInitializeSemaphore(&QueueSemaphore, 0, 0x7fffffff);
1177 
1178  /*
1179  * Event to terminate that thread
1180  */
1182 
1183  /*
1184  * Create the queue processing thread. Save its handle in the global variable
1185  * ThreadHandle so we can wait on its termination during Unload.
1186  */
1187  if(PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, QueueThread, 0) != STATUS_SUCCESS)
1188  {
1189  WARN_(FLOPPY, "Unable to create system thread; failing init\n");
1191  }
1192 
1194  {
1195  WARN_(FLOPPY, "Unable to reference returned thread handle; failing init\n");
1196  return STATUS_UNSUCCESSFUL;
1197  }
1198 
1199  /*
1200  * Close the handle, now that we have the object pointer and a reference of our own.
1201  * The handle will certainly not be valid in the context of the caller next time we
1202  * need it, as handles are process-specific.
1203  */
1204  ZwClose(ThreadHandle);
1205 
1206  /*
1207  * Start the device discovery process. Returns STATUS_SUCCESS if
1208  * it finds even one drive attached to one controller.
1209  */
1211  return STATUS_NO_SUCH_DEVICE;
1212 
1213  return STATUS_SUCCESS;
1214 }
_In_ PIO_CSQ_INSERT_IRP CsqInsertIrp
Definition: iofuncs.h:1884
NTSTATUS NTAPI RWDetermineMediaType(PDRIVE_INFO DriveInfo, BOOLEAN OneShot)
Definition: readwrite.c:153
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
VOID NTAPI ReadWritePassive(PDRIVE_INFO DriveInfo, PIRP Irp)
Definition: readwrite.c:403
FORCEINLINE VOID IoInitializeDpcRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIO_DPC_ROUTINE DpcRoutine)
Definition: iofuncs.h:2792
DRIVER_DISPATCH DeviceIoctl
Definition: ioctl.h:29
signed char * PCHAR
Definition: retypes.h:7
static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
Definition: floppy.c:377
struct _CONTROLLER_INFO * PCONTROLLER_INFO
#define CmResourceTypeDeviceSpecific
Definition: hwresource.cpp:127
#define FILE_DEVICE_DISK
Definition: winioctl.h:112
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
ULONG DiskChangeCount
Definition: floppy.h:53
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
#define TRUE
Definition: types.h:120
INTERFACE_TYPE InterfaceType
Definition: floppy.h:62
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID _In_opt_ PKSPIN_LOCK _In_ ULONG _In_ KIRQL _In_ KIRQL _In_ KINTERRUPT_MODE InterruptMode
Definition: iofuncs.h:798
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
enum _INTERFACE_TYPE INTERFACE_TYPE
#define INFO_(ch,...)
Definition: debug.h:159
NTSTATUS NTAPI WaitForControllerInterrupt(PCONTROLLER_INFO ControllerInfo, PLARGE_INTEGER Timeout)
Definition: floppy.c:163
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@369::@371 Port
NTHALAPI ULONG NTAPI HalGetInterruptVector(INTERFACE_TYPE, ULONG, ULONG, ULONG, PKIRQL, PKAFFINITY)
#define MAX_CONTROLLERS
Definition: fdc.h:17
NTKERNELAPI PIRP NTAPI IoCsqRemoveNextIrp(_Inout_ PIO_CSQ Csq, _In_opt_ PVOID PeekContext)
IoCsqRemoveNextIrp - Removes the next IRP from the queue.
Definition: csq.c:398
ULONG ControllerNumber
Definition: floppy.h:61
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Definition: iorsrce.c:830
_In_opt_ PUNICODE_STRING _In_ PDRIVER_OBJECT _In_ PDEVICE_OBJECT _In_ INTERFACE_TYPE BusType
Definition: halfuncs.h:156
#define SPECIFY_HLT_500K
Definition: hardware.h:219
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
struct _DEVICE_OBJECT * PDEVICE_OBJECT
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
static NTSTATUS NTAPI ConfigCallback(PVOID Context, PUNICODE_STRING PathName, INTERFACE_TYPE BusType, ULONG BusNumber, PKEY_VALUE_FULL_INFORMATION *BusInformation, CONFIGURATION_TYPE ControllerType, ULONG ControllerNumber, PKEY_VALUE_FULL_INFORMATION *ControllerInformation, CONFIGURATION_TYPE PeripheralType, ULONG PeripheralNumber, PKEY_VALUE_FULL_INFORMATION *PeripheralInformation)
Definition: floppy.c:431
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2268
unsigned char * PUCHAR
Definition: retypes.h:3
BOOLEAN Initialized
Definition: floppy.h:54
ULONG BusNumber
Definition: floppy.h:63
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2769
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:724
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_OPENED
Definition: nt_native.h:769
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@369 u
#define SPECIFY_SRT_500K
Definition: hardware.h:227
NTSTATUS NTAPI HwDiskChanged(PDRIVE_INFO DriveInfo, PBOOLEAN DiskChanged)
Definition: hardware.c:785
VOID NTAPI StopMotor(PCONTROLLER_INFO ControllerInfo)
Definition: floppy.c:135
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@369::@375 Dma
LIST_ENTRY IrpQueue
Definition: csqrtns.c:49
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@369::@372 Interrupt
static ULONG gNumberOfControllers
Definition: floppy.c:57
VOID NTAPI DeviceIoctlPassive(PDRIVE_INFO DriveInfo, PIRP Irp)
Definition: ioctl.c:64
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
ULONG Vector
Definition: floppy.h:66
static DRIVER_DISPATCH CreateClose
Definition: floppy.c:188
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
_In_ PIO_CSQ_INSERT_IRP _In_ PIO_CSQ_REMOVE_IRP _In_ PIO_CSQ_PEEK_NEXT_IRP _In_ PIO_CSQ_ACQUIRE_LOCK _In_ PIO_CSQ_RELEASE_LOCK CsqReleaseLock
Definition: iofuncs.h:1884
static NTSTATUS NTAPI Recalibrate(PDRIVE_INFO DriveInfo)
Definition: floppy.c:221
PVOID NTAPI MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress, IN SIZE_T NumberOfBytes, IN MEMORY_CACHING_TYPE CacheType)
Definition: iosup.c:47
WCHAR DeviceName[]
Definition: adapter.cpp:21
static PVOID QueueThreadObject
Definition: floppy.c:61
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG _Out_ PPHYSICAL_ADDRESS TranslatedAddress
Definition: iofuncs.h:2268
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
static KEVENT QueueThreadTerminate
Definition: floppy.c:60
struct _CONTROLLER_INFO * ControllerInfo
Definition: fdc.h:23
static int Link(const char **args)
Definition: vfdcmd.c:2414
UCHAR NumberOfDrives
Definition: fdc.h:58
#define CmResourceTypePort
Definition: hwresource.cpp:123
#define PAGED_CODE()
Definition: video.h:57
#define DEVICE_DESCRIPTION_VERSION
Definition: iotypes.h:2019
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
BOOLEAN ImpliedSeeks
Definition: floppy.h:79
NTSTATUS NTAPI HwTurnOffMotor(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:223
KSEMAPHORE QueueSemaphore
Definition: csqrtns.c:51
#define MAX_DRIVES_PER_CONTROLLER
Definition: fdc.h:16
PDEVICE_OBJECT DeviceObject
Definition: fdc.h:26
CM_PARTIAL_RESOURCE_LIST PartialResourceList
Definition: hwresource.cpp:160
NTSTATUS NTAPI HwSetDataRate(PCONTROLLER_INFO ControllerInfo, UCHAR DataRate)
Definition: hardware.c:204
DRIVER_INITIALIZE DriverEntry
Definition: floppy.c:341
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:496
PADAPTER_OBJECT AdapterObject
Definition: floppy.h:77
#define IO_DISK_INCREMENT
Definition: iotypes.h:567
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
BOOLEAN Populated
Definition: fdc.h:39
NTSTATUS NTAPI IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN KAFFINITY ProcessorEnableMask, IN BOOLEAN FloatingSave)
Definition: irq.c:22
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
struct _CM_FULL_RESOURCE_DESCRIPTOR * PCM_FULL_RESOURCE_DESCRIPTOR
NTSTATUS NTAPI HwReset(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:973
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
VOID NTAPI IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
Definition: irq.c:140
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
NTSTATUS NTAPI HwRecalibrateResult(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:394
_In_ PIO_CSQ_INSERT_IRP _In_ PIO_CSQ_REMOVE_IRP _In_ PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp
Definition: iofuncs.h:1884
NTSTATUS NTAPI HwTurnOnMotor(PDRIVE_INFO DriveInfo)
Definition: hardware.c:245
_In_opt_ PUNICODE_STRING _In_ PDRIVER_OBJECT _In_ PDEVICE_OBJECT _In_ INTERFACE_TYPE _In_ ULONG BusNumber
Definition: halfuncs.h:156
NTSTATUS NTAPI HwConfigure(PCONTROLLER_INFO ControllerInfo, BOOLEAN EIS, BOOLEAN EFIFO, BOOLEAN POLL, UCHAR FIFOTHR, UCHAR PRETRK)
Definition: hardware.c:703
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
NTSTATUS NTAPI HwSenseInterruptStatus(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:539
_In_ PIO_CSQ_INSERT_IRP _In_ PIO_CSQ_REMOVE_IRP CsqRemoveIrp
Definition: iofuncs.h:1884
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
#define TRACE_(x)
Definition: compat.h:66
NTSTATUS NTAPI IoQueryDeviceDescription(PINTERFACE_TYPE BusType OPTIONAL, PULONG BusNumber OPTIONAL, PCONFIGURATION_TYPE ControllerType OPTIONAL, PULONG ControllerNumber OPTIONAL, PCONFIGURATION_TYPE PeripheralType OPTIONAL, PULONG PeripheralNumber OPTIONAL, PIO_QUERY_DEVICE_ROUTINE CalloutRoutine, PVOID Context)
Definition: iorsrce.c:1011
KDPC MotorStopDpc
Definition: floppy.h:85
_Must_inspect_result_ _In_ PDEVICE_DESCRIPTION DeviceDescription
Definition: iofuncs.h:1015
NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo)
Definition: floppy.c:291
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
NTSTATUS NTAPI HwSeek(PDRIVE_INFO DriveInfo, UCHAR Cylinder)
Definition: hardware.c:659
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
VOID NTAPI KeInitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit)
Definition: semphobj.c:22
__wchar_t WCHAR
Definition: xmlstorage.h:180
NTSTATUS NTAPI HwGetVersion(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:749
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
_In_ PIO_CSQ_INSERT_IRP _In_ PIO_CSQ_REMOVE_IRP _In_ PIO_CSQ_PEEK_NEXT_IRP _In_ PIO_CSQ_ACQUIRE_LOCK _In_ PIO_CSQ_RELEASE_LOCK _In_ PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp
Definition: iofuncs.h:1884
#define swprintf(buf, format,...)
Definition: sprintf.c:56
IO_DPC_ROUTINE * PIO_DPC_ROUTINE
Definition: iotypes.h:2491
_In_ ULONG _In_ ULONG _In_ ULONG _Out_ PKIRQL _Out_ PKAFFINITY Affinity
Definition: halfuncs.h:170
#define IoDeassignArcName
MEDIA_TYPE MediaType
Definition: ntdddisk.h:373
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID ServiceContext
Definition: iofuncs.h:798
NTSTATUS NTAPI KeWaitForMultipleObjects(IN ULONG Count, IN PVOID Object[], IN WAIT_TYPE WaitType, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, OUT PKWAIT_BLOCK WaitBlockArray OPTIONAL)
Definition: wait.c:586
DMA_WIDTH DmaWidth
Definition: iotypes.h:2036
KEVENT MotorStoppedEvent
Definition: floppy.h:83
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
unsigned char UCHAR
Definition: xmlstorage.h:181
BOOLEAN Model30
Definition: floppy.h:82
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: hwresource.cpp:119
BOOLEAN StopDpcQueued
Definition: floppy.h:86
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
POBJECT_TYPE PsThreadType
Definition: thread.c:20
CM_FLOPPY_DEVICE_DATA FloppyDeviceData
Definition: fdc.h:27
KINTERRUPT_MODE InterruptMode
Definition: floppy.h:68
static const WCHAR L[]
Definition: oid.c:1250
Definition: ketypes.h:687
PDRIVER_UNLOAD DriverUnload
Definition: iotypes.h:2179
CONFIGURATION_TYPE
Definition: iotypes.h:4036
DISK_GEOMETRY DiskGeometry
Definition: floppy.h:49
BOOLEAN Initialized
Definition: floppy.h:60
DRIVER_DISPATCH(nfs41_FsdDispatch)
ULONG MappedVector
Definition: floppy.h:67
UCHAR UnitNumber
Definition: fdc.h:24
static NTSTATUS NTAPI InitController(PCONTROLLER_INFO ControllerInfo)
Definition: floppy.c:666
BOOLEAN NTAPI HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, IN ULONG BusNumber, IN PHYSICAL_ADDRESS BusAddress, IN OUT PULONG AddressSpace, OUT PPHYSICAL_ADDRESS TranslatedAddress)
Definition: bus.c:140
Status
Definition: gdiplustypes.h:24
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
KSPIN_LOCK IrpQueueLock
Definition: csqrtns.c:50
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1250
ULONG Level
Definition: floppy.h:64
DRIVER_DISPATCH * PDRIVER_DISPATCH
Definition: iotypes.h:2153
UCHAR StepRateHeadUnloadTime
Definition: cmtypes.h:487
#define EVENT_INCREMENT
Definition: iotypes.h:564
static ULONG Timeout
Definition: ping.c:61
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
static VOID NTAPI MotorStopDpcFunc(PKDPC UnusedDpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
Definition: floppy.c:65
#define STANDARD_RIGHTS_ALL
Definition: nt_native.h:69
#define VERSION_ENHANCED
Definition: hardware.h:239
NTSTATUS NTAPI HwPowerOff(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:1010
NTSTATUS NTAPI HwRecalibrate(PDRIVE_INFO DriveInfo)
Definition: hardware.c:503
ULONG_PTR KAFFINITY
Definition: compat.h:75
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
static BOOLEAN NTAPI Isr(PKINTERRUPT Interrupt, PVOID ServiceContext)
Definition: floppy.c:584
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
static BOOLEAN NTAPI AddControllers(PDRIVER_OBJECT DriverObject)
Definition: floppy.c:815
#define IoAssignArcName(_ArcName, _DeviceName)
static VOID NTAPI QueueThread(PVOID Context)
Definition: floppy.c:1054
#define CmResourceTypeInterrupt
Definition: hwresource.cpp:124
KEVENT SynchEvent
Definition: floppy.h:74
DRIVE_INFO DriveInfo[MAX_DRIVES_PER_CONTROLLER]
Definition: fdc.h:60
static CONTROLLER_INFO gControllerInfo[MAX_CONTROLLERS]
Definition: floppy.c:56
#define IRP_MJ_READ
Definition: rdpdr.c:46
IO_CSQ Csq
Definition: csqrtns.c:46
struct _CM_FLOPPY_DEVICE_DATA * PCM_FLOPPY_DEVICE_DATA
#define DRSR_DSEL_500KBPS
Definition: hardware.h:106
PUCHAR BaseAddress
Definition: fdc.h:49
LONG NTAPI KeReadStateEvent(IN PKEVENT Event)
Definition: eventobj.c:120
INTERFACE_TYPE InterfaceType
Definition: iotypes.h:2035
#define SPECIFY_HUT_500K
Definition: hardware.h:223
#define CM_RESOURCE_INTERRUPT_LATCHED
Definition: cmtypes.h:144
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1]
Definition: iotypes.h:2180
NTSTATUS NTAPI HwSpecify(PCONTROLLER_INFO ControllerInfo, UCHAR HeadLoadTime, UCHAR HeadUnloadTime, UCHAR StepRateTime, BOOLEAN NonDma)
Definition: hardware.c:925
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:565
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
_In_ PUNICODE_STRING RegistryPath
Definition: wmip.h:27
#define MAX_DEVICE_NAME
Definition: fdc.h:14
DRIVER_DISPATCH ReadWrite
Definition: readwrite.h:29
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
NTKERNELAPI NTSTATUS NTAPI IoCsqInitialize(_Out_ PIO_CSQ Csq, _In_ PIO_CSQ_INSERT_IRP CsqInsertIrp, _In_ PIO_CSQ_REMOVE_IRP CsqRemoveIrp, _In_ PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp, _In_ PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock, _In_ PIO_CSQ_RELEASE_LOCK CsqReleaseLock, _In_ PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp)
Set up a CSQ struct to initialize the queue.
Definition: csq.c:103
#define FILE_FLOPPY_DISKETTE
Definition: nt_native.h:809
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:711
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
return STATUS_SUCCESS
Definition: btrfs.c:2745
#define memset(x, y, z)
Definition: compat.h:39
_In_ PIO_CSQ_INSERT_IRP _In_ PIO_CSQ_REMOVE_IRP _In_ PIO_CSQ_PEEK_NEXT_IRP _In_ PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock
Definition: iofuncs.h:1884
#define VPB_MOUNTED
Definition: iotypes.h:1763
#define FDC_PORT_BYTES
Definition: hardware.h:40
#define WARN_(ch,...)
Definition: debug.h:157
VOID NTAPI SignalMediaChanged(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: floppy.c:1010
VOID NTAPI StartMotor(PDRIVE_INFO DriveInfo)
Definition: floppy.c:96
#define CmResourceTypeDma
Definition: hwresource.cpp:126
LONGLONG QuadPart
Definition: typedefs.h:112
PADAPTER_OBJECT NTAPI HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription, OUT PULONG NumberOfMapRegisters)
Definition: dma.c:22
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
KTIMER MotorTimer
Definition: floppy.h:84
VOID NTAPI DpcForIsr(PKDPC UnusedDpc, PVOID Context, PVOID SystemArgument1, PVOID SystemArgument2)
Definition: floppy.c:633
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675