xref: /reactos/drivers/storage/floppy/fdc/fdo.c (revision c1f22c88)
1*c1f22c88SEric Kohl /*
2*c1f22c88SEric Kohl  * PROJECT:        ReactOS Floppy Disk Controller Driver
3*c1f22c88SEric Kohl  * LICENSE:        GNU GPLv2 only as published by the Free Software Foundation
4*c1f22c88SEric Kohl  * FILE:           drivers/storage/fdc/fdc/fdo.c
5*c1f22c88SEric Kohl  * PURPOSE:        Functional Device Object routines
6*c1f22c88SEric Kohl  * PROGRAMMERS:    Eric Kohl
7*c1f22c88SEric Kohl  */
8*c1f22c88SEric Kohl 
9*c1f22c88SEric Kohl /* INCLUDES *******************************************************************/
10*c1f22c88SEric Kohl 
11*c1f22c88SEric Kohl #include "fdc.h"
12*c1f22c88SEric Kohl 
13*c1f22c88SEric Kohl #include <stdio.h>
14*c1f22c88SEric Kohl #define NDEBUG
15*c1f22c88SEric Kohl #include <debug.h>
16*c1f22c88SEric Kohl 
17*c1f22c88SEric Kohl /* FUNCTIONS ******************************************************************/
18*c1f22c88SEric Kohl 
19*c1f22c88SEric Kohl static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion;
20*c1f22c88SEric Kohl 
21*c1f22c88SEric Kohl static
22*c1f22c88SEric Kohl NTSTATUS
23*c1f22c88SEric Kohl NTAPI
24*c1f22c88SEric Kohl ForwardIrpAndWaitCompletion(
25*c1f22c88SEric Kohl     IN PDEVICE_OBJECT DeviceObject,
26*c1f22c88SEric Kohl     IN PIRP Irp,
27*c1f22c88SEric Kohl     IN PVOID Context)
28*c1f22c88SEric Kohl {
29*c1f22c88SEric Kohl     if (Irp->PendingReturned)
30*c1f22c88SEric Kohl         KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
31*c1f22c88SEric Kohl     return STATUS_MORE_PROCESSING_REQUIRED;
32*c1f22c88SEric Kohl }
33*c1f22c88SEric Kohl 
34*c1f22c88SEric Kohl 
35*c1f22c88SEric Kohl NTSTATUS
36*c1f22c88SEric Kohl ForwardIrpAndWait(
37*c1f22c88SEric Kohl     IN PDEVICE_OBJECT DeviceObject,
38*c1f22c88SEric Kohl     IN PIRP Irp)
39*c1f22c88SEric Kohl {
40*c1f22c88SEric Kohl     PDEVICE_OBJECT LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
41*c1f22c88SEric Kohl     KEVENT Event;
42*c1f22c88SEric Kohl     NTSTATUS Status;
43*c1f22c88SEric Kohl 
44*c1f22c88SEric Kohl     ASSERT(LowerDevice);
45*c1f22c88SEric Kohl 
46*c1f22c88SEric Kohl     KeInitializeEvent(&Event, NotificationEvent, FALSE);
47*c1f22c88SEric Kohl     IoCopyCurrentIrpStackLocationToNext(Irp);
48*c1f22c88SEric Kohl 
49*c1f22c88SEric Kohl     DPRINT("Calling lower device %p\n", LowerDevice);
50*c1f22c88SEric Kohl     IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
51*c1f22c88SEric Kohl 
52*c1f22c88SEric Kohl     Status = IoCallDriver(LowerDevice, Irp);
53*c1f22c88SEric Kohl     if (Status == STATUS_PENDING)
54*c1f22c88SEric Kohl     {
55*c1f22c88SEric Kohl         Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
56*c1f22c88SEric Kohl         if (NT_SUCCESS(Status))
57*c1f22c88SEric Kohl             Status = Irp->IoStatus.Status;
58*c1f22c88SEric Kohl     }
59*c1f22c88SEric Kohl 
60*c1f22c88SEric Kohl     return Status;
61*c1f22c88SEric Kohl }
62*c1f22c88SEric Kohl 
63*c1f22c88SEric Kohl 
64*c1f22c88SEric Kohl NTSTATUS
65*c1f22c88SEric Kohl NTAPI
66*c1f22c88SEric Kohl ForwardIrpAndForget(
67*c1f22c88SEric Kohl     IN PDEVICE_OBJECT DeviceObject,
68*c1f22c88SEric Kohl     IN PIRP Irp)
69*c1f22c88SEric Kohl {
70*c1f22c88SEric Kohl     PDEVICE_OBJECT LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
71*c1f22c88SEric Kohl 
72*c1f22c88SEric Kohl     ASSERT(LowerDevice);
73*c1f22c88SEric Kohl 
74*c1f22c88SEric Kohl     IoSkipCurrentIrpStackLocation(Irp);
75*c1f22c88SEric Kohl     return IoCallDriver(LowerDevice, Irp);
76*c1f22c88SEric Kohl }
77*c1f22c88SEric Kohl 
78*c1f22c88SEric Kohl 
79*c1f22c88SEric Kohl 
80*c1f22c88SEric Kohl 
81*c1f22c88SEric Kohl static
82*c1f22c88SEric Kohl NTSTATUS
83*c1f22c88SEric Kohl FdcFdoStartDevice(
84*c1f22c88SEric Kohl     IN PDEVICE_OBJECT DeviceObject,
85*c1f22c88SEric Kohl     IN PCM_RESOURCE_LIST ResourceList,
86*c1f22c88SEric Kohl     IN PCM_RESOURCE_LIST ResourceListTranslated)
87*c1f22c88SEric Kohl {
88*c1f22c88SEric Kohl     PFDO_DEVICE_EXTENSION DeviceExtension;
89*c1f22c88SEric Kohl     PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
90*c1f22c88SEric Kohl //    PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptorTranslated;
91*c1f22c88SEric Kohl     ULONG i;
92*c1f22c88SEric Kohl 
93*c1f22c88SEric Kohl     DPRINT("FdcFdoStartDevice called\n");
94*c1f22c88SEric Kohl 
95*c1f22c88SEric Kohl     DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
96*c1f22c88SEric Kohl 
97*c1f22c88SEric Kohl     ASSERT(DeviceExtension);
98*c1f22c88SEric Kohl 
99*c1f22c88SEric Kohl     if (ResourceList == NULL ||
100*c1f22c88SEric Kohl         ResourceListTranslated == NULL)
101*c1f22c88SEric Kohl     {
102*c1f22c88SEric Kohl         DPRINT1("No allocated resources sent to driver\n");
103*c1f22c88SEric Kohl         return STATUS_INSUFFICIENT_RESOURCES;
104*c1f22c88SEric Kohl     }
105*c1f22c88SEric Kohl 
106*c1f22c88SEric Kohl     if (ResourceList->Count != 1)
107*c1f22c88SEric Kohl     {
108*c1f22c88SEric Kohl         DPRINT1("Wrong number of allocated resources sent to driver\n");
109*c1f22c88SEric Kohl         return STATUS_INSUFFICIENT_RESOURCES;
110*c1f22c88SEric Kohl     }
111*c1f22c88SEric Kohl 
112*c1f22c88SEric Kohl     if (ResourceList->List[0].PartialResourceList.Version != 1 ||
113*c1f22c88SEric Kohl         ResourceList->List[0].PartialResourceList.Revision != 1 ||
114*c1f22c88SEric Kohl         ResourceListTranslated->List[0].PartialResourceList.Version != 1 ||
115*c1f22c88SEric Kohl         ResourceListTranslated->List[0].PartialResourceList.Revision != 1)
116*c1f22c88SEric Kohl     {
117*c1f22c88SEric Kohl         DPRINT1("Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n",
118*c1f22c88SEric Kohl                 ResourceList->List[0].PartialResourceList.Version,
119*c1f22c88SEric Kohl                 ResourceList->List[0].PartialResourceList.Revision,
120*c1f22c88SEric Kohl                 ResourceListTranslated->List[0].PartialResourceList.Version,
121*c1f22c88SEric Kohl                 ResourceListTranslated->List[0].PartialResourceList.Revision);
122*c1f22c88SEric Kohl         return STATUS_REVISION_MISMATCH;
123*c1f22c88SEric Kohl     }
124*c1f22c88SEric Kohl 
125*c1f22c88SEric Kohl     for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++)
126*c1f22c88SEric Kohl     {
127*c1f22c88SEric Kohl         PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
128*c1f22c88SEric Kohl //        PartialDescriptorTranslated = &ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[i];
129*c1f22c88SEric Kohl 
130*c1f22c88SEric Kohl         switch (PartialDescriptor->Type)
131*c1f22c88SEric Kohl         {
132*c1f22c88SEric Kohl             case CmResourceTypePort:
133*c1f22c88SEric Kohl                 DPRINT("Port: 0x%lx (%lu)\n",
134*c1f22c88SEric Kohl                         PartialDescriptor->u.Port.Start.u.LowPart,
135*c1f22c88SEric Kohl                         PartialDescriptor->u.Port.Length);
136*c1f22c88SEric Kohl                 if (PartialDescriptor->u.Port.Length >= 6)
137*c1f22c88SEric Kohl                     DeviceExtension->ControllerInfo.BaseAddress = (PUCHAR)(ULONG_PTR)PartialDescriptor->u.Port.Start.QuadPart;
138*c1f22c88SEric Kohl                 break;
139*c1f22c88SEric Kohl 
140*c1f22c88SEric Kohl             case CmResourceTypeInterrupt:
141*c1f22c88SEric Kohl                 DPRINT("Interrupt: Level %lu  Vector %lu\n",
142*c1f22c88SEric Kohl                         PartialDescriptor->u.Interrupt.Level,
143*c1f22c88SEric Kohl                         PartialDescriptor->u.Interrupt.Vector);
144*c1f22c88SEric Kohl /*
145*c1f22c88SEric Kohl                 Dirql = (KIRQL)PartialDescriptorTranslated->u.Interrupt.Level;
146*c1f22c88SEric Kohl                 Vector = PartialDescriptorTranslated->u.Interrupt.Vector;
147*c1f22c88SEric Kohl                 Affinity = PartialDescriptorTranslated->u.Interrupt.Affinity;
148*c1f22c88SEric Kohl                 if (PartialDescriptorTranslated->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
149*c1f22c88SEric Kohl                     InterruptMode = Latched;
150*c1f22c88SEric Kohl                 else
151*c1f22c88SEric Kohl                     InterruptMode = LevelSensitive;
152*c1f22c88SEric Kohl                 ShareInterrupt = (PartialDescriptorTranslated->ShareDisposition == CmResourceShareShared);
153*c1f22c88SEric Kohl */
154*c1f22c88SEric Kohl                 break;
155*c1f22c88SEric Kohl 
156*c1f22c88SEric Kohl             case CmResourceTypeDma:
157*c1f22c88SEric Kohl                 DPRINT("Dma: Channel %lu\n",
158*c1f22c88SEric Kohl                         PartialDescriptor->u.Dma.Channel);
159*c1f22c88SEric Kohl                 break;
160*c1f22c88SEric Kohl         }
161*c1f22c88SEric Kohl     }
162*c1f22c88SEric Kohl 
163*c1f22c88SEric Kohl     return STATUS_SUCCESS;
164*c1f22c88SEric Kohl }
165*c1f22c88SEric Kohl 
166*c1f22c88SEric Kohl 
167*c1f22c88SEric Kohl static
168*c1f22c88SEric Kohl NTSTATUS
169*c1f22c88SEric Kohl NTAPI
170*c1f22c88SEric Kohl FdcFdoConfigCallback(
171*c1f22c88SEric Kohl     PVOID Context,
172*c1f22c88SEric Kohl     PUNICODE_STRING PathName,
173*c1f22c88SEric Kohl     INTERFACE_TYPE BusType,
174*c1f22c88SEric Kohl     ULONG BusNumber,
175*c1f22c88SEric Kohl     PKEY_VALUE_FULL_INFORMATION *BusInformation,
176*c1f22c88SEric Kohl     CONFIGURATION_TYPE ControllerType,
177*c1f22c88SEric Kohl     ULONG ControllerNumber,
178*c1f22c88SEric Kohl     PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
179*c1f22c88SEric Kohl     CONFIGURATION_TYPE PeripheralType,
180*c1f22c88SEric Kohl     ULONG PeripheralNumber,
181*c1f22c88SEric Kohl     PKEY_VALUE_FULL_INFORMATION *PeripheralInformation)
182*c1f22c88SEric Kohl {
183*c1f22c88SEric Kohl     PKEY_VALUE_FULL_INFORMATION ControllerFullDescriptor;
184*c1f22c88SEric Kohl     PCM_FULL_RESOURCE_DESCRIPTOR ControllerResourceDescriptor;
185*c1f22c88SEric Kohl     PKEY_VALUE_FULL_INFORMATION PeripheralFullDescriptor;
186*c1f22c88SEric Kohl     PCM_FULL_RESOURCE_DESCRIPTOR PeripheralResourceDescriptor;
187*c1f22c88SEric Kohl     PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
188*c1f22c88SEric Kohl     PCM_FLOPPY_DEVICE_DATA FloppyDeviceData;
189*c1f22c88SEric Kohl     PFDO_DEVICE_EXTENSION DeviceExtension;
190*c1f22c88SEric Kohl     PDRIVE_INFO DriveInfo;
191*c1f22c88SEric Kohl     BOOLEAN ControllerFound = FALSE;
192*c1f22c88SEric Kohl     ULONG i;
193*c1f22c88SEric Kohl 
194*c1f22c88SEric Kohl     DPRINT("FdcFdoConfigCallback() called\n");
195*c1f22c88SEric Kohl 
196*c1f22c88SEric Kohl     DeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
197*c1f22c88SEric Kohl 
198*c1f22c88SEric Kohl     /* Get the controller resources */
199*c1f22c88SEric Kohl     ControllerFullDescriptor = ControllerInformation[IoQueryDeviceConfigurationData];
200*c1f22c88SEric Kohl     ControllerResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)ControllerFullDescriptor +
201*c1f22c88SEric Kohl                                                                   ControllerFullDescriptor->DataOffset);
202*c1f22c88SEric Kohl 
203*c1f22c88SEric Kohl     for(i = 0; i < ControllerResourceDescriptor->PartialResourceList.Count; i++)
204*c1f22c88SEric Kohl     {
205*c1f22c88SEric Kohl         PartialDescriptor = &ControllerResourceDescriptor->PartialResourceList.PartialDescriptors[i];
206*c1f22c88SEric Kohl 
207*c1f22c88SEric Kohl         if (PartialDescriptor->Type == CmResourceTypePort)
208*c1f22c88SEric Kohl         {
209*c1f22c88SEric Kohl             if ((PUCHAR)(ULONG_PTR)PartialDescriptor->u.Port.Start.QuadPart == DeviceExtension->ControllerInfo.BaseAddress)
210*c1f22c88SEric Kohl                 ControllerFound = TRUE;
211*c1f22c88SEric Kohl         }
212*c1f22c88SEric Kohl     }
213*c1f22c88SEric Kohl 
214*c1f22c88SEric Kohl     /* Leave, if the enumerated controller is not the one represented by the FDO */
215*c1f22c88SEric Kohl     if (ControllerFound == FALSE)
216*c1f22c88SEric Kohl         return STATUS_SUCCESS;
217*c1f22c88SEric Kohl 
218*c1f22c88SEric Kohl     /* Get the peripheral resources */
219*c1f22c88SEric Kohl     PeripheralFullDescriptor = PeripheralInformation[IoQueryDeviceConfigurationData];
220*c1f22c88SEric Kohl     PeripheralResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)PeripheralFullDescriptor +
221*c1f22c88SEric Kohl                                                                   PeripheralFullDescriptor->DataOffset);
222*c1f22c88SEric Kohl 
223*c1f22c88SEric Kohl     /* learn about drives attached to controller */
224*c1f22c88SEric Kohl     for(i = 0; i < PeripheralResourceDescriptor->PartialResourceList.Count; i++)
225*c1f22c88SEric Kohl     {
226*c1f22c88SEric Kohl         PartialDescriptor = &PeripheralResourceDescriptor->PartialResourceList.PartialDescriptors[i];
227*c1f22c88SEric Kohl 
228*c1f22c88SEric Kohl         if (PartialDescriptor->Type != CmResourceTypeDeviceSpecific)
229*c1f22c88SEric Kohl             continue;
230*c1f22c88SEric Kohl 
231*c1f22c88SEric Kohl         FloppyDeviceData = (PCM_FLOPPY_DEVICE_DATA)(PartialDescriptor + 1);
232*c1f22c88SEric Kohl 
233*c1f22c88SEric Kohl         DriveInfo = &DeviceExtension->ControllerInfo.DriveInfo[DeviceExtension->ControllerInfo.NumberOfDrives];
234*c1f22c88SEric Kohl 
235*c1f22c88SEric Kohl         DriveInfo->ControllerInfo = &DeviceExtension->ControllerInfo;
236*c1f22c88SEric Kohl         DriveInfo->UnitNumber = DeviceExtension->ControllerInfo.NumberOfDrives;
237*c1f22c88SEric Kohl         DriveInfo->PeripheralNumber = PeripheralNumber;
238*c1f22c88SEric Kohl 
239*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.MaxDensity = FloppyDeviceData->MaxDensity;
240*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.MountDensity = FloppyDeviceData->MountDensity;
241*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.StepRateHeadUnloadTime = FloppyDeviceData->StepRateHeadUnloadTime;
242*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.HeadLoadTime = FloppyDeviceData->HeadLoadTime;
243*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.MotorOffTime = FloppyDeviceData->MotorOffTime;
244*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.SectorLengthCode = FloppyDeviceData->SectorLengthCode;
245*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.SectorPerTrack = FloppyDeviceData->SectorPerTrack;
246*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.ReadWriteGapLength = FloppyDeviceData->ReadWriteGapLength;
247*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.FormatGapLength = FloppyDeviceData->FormatGapLength;
248*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.FormatFillCharacter = FloppyDeviceData->FormatFillCharacter;
249*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.HeadSettleTime = FloppyDeviceData->HeadSettleTime;
250*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.MotorSettleTime = FloppyDeviceData->MotorSettleTime;
251*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.MaximumTrackValue = FloppyDeviceData->MaximumTrackValue;
252*c1f22c88SEric Kohl         DriveInfo->FloppyDeviceData.DataTransferLength = FloppyDeviceData->DataTransferLength;
253*c1f22c88SEric Kohl 
254*c1f22c88SEric Kohl         /* Once it's all set up, acknowledge its existence in the controller info object */
255*c1f22c88SEric Kohl         DeviceExtension->ControllerInfo.NumberOfDrives++;
256*c1f22c88SEric Kohl     }
257*c1f22c88SEric Kohl 
258*c1f22c88SEric Kohl     DeviceExtension->ControllerInfo.Populated = TRUE;
259*c1f22c88SEric Kohl 
260*c1f22c88SEric Kohl     DPRINT("Detected %lu floppy drives!\n",
261*c1f22c88SEric Kohl             DeviceExtension->ControllerInfo.NumberOfDrives);
262*c1f22c88SEric Kohl 
263*c1f22c88SEric Kohl     return STATUS_SUCCESS;
264*c1f22c88SEric Kohl }
265*c1f22c88SEric Kohl 
266*c1f22c88SEric Kohl 
267*c1f22c88SEric Kohl static
268*c1f22c88SEric Kohl NTSTATUS
269*c1f22c88SEric Kohl PciCreateHardwareIDsString(PUNICODE_STRING HardwareIDs)
270*c1f22c88SEric Kohl {
271*c1f22c88SEric Kohl     WCHAR Buffer[256];
272*c1f22c88SEric Kohl     UNICODE_STRING BufferU;
273*c1f22c88SEric Kohl     ULONG Index;
274*c1f22c88SEric Kohl 
275*c1f22c88SEric Kohl     Index = 0;
276*c1f22c88SEric Kohl     Index += swprintf(&Buffer[Index],
277*c1f22c88SEric Kohl                       L"FDC\\GENERIC_FLOPPY_DRIVE");
278*c1f22c88SEric Kohl     Index++;
279*c1f22c88SEric Kohl 
280*c1f22c88SEric Kohl     Buffer[Index] = UNICODE_NULL;
281*c1f22c88SEric Kohl 
282*c1f22c88SEric Kohl     BufferU.Length = BufferU.MaximumLength = (USHORT) Index * sizeof(WCHAR);
283*c1f22c88SEric Kohl     BufferU.Buffer = Buffer;
284*c1f22c88SEric Kohl 
285*c1f22c88SEric Kohl     return DuplicateUnicodeString(0, &BufferU, HardwareIDs);
286*c1f22c88SEric Kohl }
287*c1f22c88SEric Kohl 
288*c1f22c88SEric Kohl 
289*c1f22c88SEric Kohl static
290*c1f22c88SEric Kohl NTSTATUS
291*c1f22c88SEric Kohl PciCreateCompatibleIDsString(PUNICODE_STRING CompatibleIDs)
292*c1f22c88SEric Kohl {
293*c1f22c88SEric Kohl     WCHAR Buffer[256];
294*c1f22c88SEric Kohl     UNICODE_STRING BufferU;
295*c1f22c88SEric Kohl     ULONG Index;
296*c1f22c88SEric Kohl 
297*c1f22c88SEric Kohl     Index = 0;
298*c1f22c88SEric Kohl     Index += swprintf(&Buffer[Index],
299*c1f22c88SEric Kohl                       L"GenFloppyDisk");
300*c1f22c88SEric Kohl     Index++;
301*c1f22c88SEric Kohl 
302*c1f22c88SEric Kohl     Buffer[Index] = UNICODE_NULL;
303*c1f22c88SEric Kohl 
304*c1f22c88SEric Kohl     BufferU.Length = BufferU.MaximumLength = (USHORT)Index * sizeof(WCHAR);
305*c1f22c88SEric Kohl     BufferU.Buffer = Buffer;
306*c1f22c88SEric Kohl 
307*c1f22c88SEric Kohl     return DuplicateUnicodeString(0, &BufferU, CompatibleIDs);
308*c1f22c88SEric Kohl }
309*c1f22c88SEric Kohl 
310*c1f22c88SEric Kohl 
311*c1f22c88SEric Kohl static
312*c1f22c88SEric Kohl NTSTATUS
313*c1f22c88SEric Kohl PciCreateInstanceIDString(PUNICODE_STRING InstanceID,
314*c1f22c88SEric Kohl                           ULONG PeripheralNumber)
315*c1f22c88SEric Kohl {
316*c1f22c88SEric Kohl     WCHAR Buffer[3];
317*c1f22c88SEric Kohl 
318*c1f22c88SEric Kohl     swprintf(Buffer, L"%02X", PeripheralNumber & 0xff);
319*c1f22c88SEric Kohl 
320*c1f22c88SEric Kohl     return RtlCreateUnicodeString(InstanceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
321*c1f22c88SEric Kohl }
322*c1f22c88SEric Kohl 
323*c1f22c88SEric Kohl 
324*c1f22c88SEric Kohl static
325*c1f22c88SEric Kohl NTSTATUS
326*c1f22c88SEric Kohl FdcFdoQueryBusRelations(
327*c1f22c88SEric Kohl     IN PDEVICE_OBJECT DeviceObject,
328*c1f22c88SEric Kohl     OUT PDEVICE_RELATIONS *DeviceRelations)
329*c1f22c88SEric Kohl {
330*c1f22c88SEric Kohl     PFDO_DEVICE_EXTENSION FdoDeviceExtension;
331*c1f22c88SEric Kohl     PPDO_DEVICE_EXTENSION PdoDeviceExtension;
332*c1f22c88SEric Kohl     INTERFACE_TYPE InterfaceType = Isa;
333*c1f22c88SEric Kohl     CONFIGURATION_TYPE ControllerType = DiskController;
334*c1f22c88SEric Kohl     CONFIGURATION_TYPE PeripheralType = FloppyDiskPeripheral;
335*c1f22c88SEric Kohl     PDEVICE_RELATIONS Relations;
336*c1f22c88SEric Kohl     PDRIVE_INFO DriveInfo;
337*c1f22c88SEric Kohl     PDEVICE_OBJECT Pdo;
338*c1f22c88SEric Kohl     WCHAR DeviceNameBuffer[80];
339*c1f22c88SEric Kohl     UNICODE_STRING DeviceName;
340*c1f22c88SEric Kohl     ULONG DeviceNumber = 0;
341*c1f22c88SEric Kohl     ULONG Size;
342*c1f22c88SEric Kohl     ULONG i;
343*c1f22c88SEric Kohl     NTSTATUS Status;
344*c1f22c88SEric Kohl 
345*c1f22c88SEric Kohl     DPRINT("FdcFdoQueryBusRelations() called\n");
346*c1f22c88SEric Kohl 
347*c1f22c88SEric Kohl     FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
348*c1f22c88SEric Kohl 
349*c1f22c88SEric Kohl     Status = IoQueryDeviceDescription(&InterfaceType,
350*c1f22c88SEric Kohl                                       NULL,
351*c1f22c88SEric Kohl                                       &ControllerType,
352*c1f22c88SEric Kohl                                       NULL,
353*c1f22c88SEric Kohl                                       &PeripheralType,
354*c1f22c88SEric Kohl                                       NULL,
355*c1f22c88SEric Kohl                                       FdcFdoConfigCallback,
356*c1f22c88SEric Kohl                                       FdoDeviceExtension);
357*c1f22c88SEric Kohl     if (!NT_SUCCESS(Status) && (Status != STATUS_NO_MORE_ENTRIES))
358*c1f22c88SEric Kohl         return Status;
359*c1f22c88SEric Kohl 
360*c1f22c88SEric Kohl     Size = sizeof(DEVICE_RELATIONS) +
361*c1f22c88SEric Kohl            sizeof(Relations->Objects) * (FdoDeviceExtension->ControllerInfo.NumberOfDrives - 1);
362*c1f22c88SEric Kohl     Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
363*c1f22c88SEric Kohl     if (Relations == NULL)
364*c1f22c88SEric Kohl     {
365*c1f22c88SEric Kohl         return STATUS_INSUFFICIENT_RESOURCES;
366*c1f22c88SEric Kohl     }
367*c1f22c88SEric Kohl 
368*c1f22c88SEric Kohl     Relations->Count = FdoDeviceExtension->ControllerInfo.NumberOfDrives;
369*c1f22c88SEric Kohl 
370*c1f22c88SEric Kohl     for (i = 0; i < FdoDeviceExtension->ControllerInfo.NumberOfDrives; i++)
371*c1f22c88SEric Kohl     {
372*c1f22c88SEric Kohl         DriveInfo = &FdoDeviceExtension->ControllerInfo.DriveInfo[i];
373*c1f22c88SEric Kohl 
374*c1f22c88SEric Kohl         if (DriveInfo->DeviceObject == NULL)
375*c1f22c88SEric Kohl         {
376*c1f22c88SEric Kohl             do
377*c1f22c88SEric Kohl             {
378*c1f22c88SEric Kohl                 swprintf(DeviceNameBuffer, L"\\Device\\FloppyPDO%lu", DeviceNumber++);
379*c1f22c88SEric Kohl                 RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
380*c1f22c88SEric Kohl                 DPRINT("Device name: %S\n", DeviceNameBuffer);
381*c1f22c88SEric Kohl 
382*c1f22c88SEric Kohl                 /* Create physical device object */
383*c1f22c88SEric Kohl                 Status = IoCreateDevice(FdoDeviceExtension->Common.DeviceObject->DriverObject,
384*c1f22c88SEric Kohl                                         sizeof(PDO_DEVICE_EXTENSION),
385*c1f22c88SEric Kohl                                         &DeviceName,
386*c1f22c88SEric Kohl                                         FILE_DEVICE_MASS_STORAGE,
387*c1f22c88SEric Kohl                                         FILE_DEVICE_SECURE_OPEN,
388*c1f22c88SEric Kohl                                         FALSE,
389*c1f22c88SEric Kohl                                         &Pdo);
390*c1f22c88SEric Kohl             }
391*c1f22c88SEric Kohl             while (Status == STATUS_OBJECT_NAME_COLLISION);
392*c1f22c88SEric Kohl 
393*c1f22c88SEric Kohl             if (!NT_SUCCESS(Status))
394*c1f22c88SEric Kohl             {
395*c1f22c88SEric Kohl                 DPRINT1("PDO creation failed (Status 0x%08lx)\n", Status);
396*c1f22c88SEric Kohl                 goto done;
397*c1f22c88SEric Kohl             }
398*c1f22c88SEric Kohl 
399*c1f22c88SEric Kohl             DPRINT("PDO created: %S\n", DeviceNameBuffer);
400*c1f22c88SEric Kohl 
401*c1f22c88SEric Kohl             DriveInfo->DeviceObject = Pdo;
402*c1f22c88SEric Kohl 
403*c1f22c88SEric Kohl             PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension;
404*c1f22c88SEric Kohl             RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
405*c1f22c88SEric Kohl 
406*c1f22c88SEric Kohl             PdoDeviceExtension->Common.IsFDO = FALSE;
407*c1f22c88SEric Kohl             PdoDeviceExtension->Common.DeviceObject = Pdo;
408*c1f22c88SEric Kohl 
409*c1f22c88SEric Kohl             PdoDeviceExtension->Fdo = FdoDeviceExtension->Common.DeviceObject;
410*c1f22c88SEric Kohl             PdoDeviceExtension->DriveInfo = DriveInfo;
411*c1f22c88SEric Kohl 
412*c1f22c88SEric Kohl             Pdo->Flags |= DO_DIRECT_IO;
413*c1f22c88SEric Kohl             Pdo->Flags |= DO_POWER_PAGABLE;
414*c1f22c88SEric Kohl             Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
415*c1f22c88SEric Kohl 
416*c1f22c88SEric Kohl             /* Add Device ID string */
417*c1f22c88SEric Kohl             RtlCreateUnicodeString(&PdoDeviceExtension->DeviceId,
418*c1f22c88SEric Kohl                                    L"FDC\\GENERIC_FLOPPY_DRIVE");
419*c1f22c88SEric Kohl             DPRINT("DeviceID: %S\n", PdoDeviceExtension->DeviceId.Buffer);
420*c1f22c88SEric Kohl 
421*c1f22c88SEric Kohl             /* Add Hardware IDs string */
422*c1f22c88SEric Kohl             Status = PciCreateHardwareIDsString(&PdoDeviceExtension->HardwareIds);
423*c1f22c88SEric Kohl             if (!NT_SUCCESS(Status))
424*c1f22c88SEric Kohl             {
425*c1f22c88SEric Kohl //                ErrorStatus = Status;
426*c1f22c88SEric Kohl //                ErrorOccurred = TRUE;
427*c1f22c88SEric Kohl                 break;
428*c1f22c88SEric Kohl             }
429*c1f22c88SEric Kohl 
430*c1f22c88SEric Kohl             /* Add Compatible IDs string */
431*c1f22c88SEric Kohl             Status = PciCreateCompatibleIDsString(&PdoDeviceExtension->CompatibleIds);
432*c1f22c88SEric Kohl             if (!NT_SUCCESS(Status))
433*c1f22c88SEric Kohl             {
434*c1f22c88SEric Kohl //                ErrorStatus = Status;
435*c1f22c88SEric Kohl //                ErrorOccurred = TRUE;
436*c1f22c88SEric Kohl                 break;
437*c1f22c88SEric Kohl             }
438*c1f22c88SEric Kohl 
439*c1f22c88SEric Kohl             /* Add Instance ID string */
440*c1f22c88SEric Kohl             Status = PciCreateInstanceIDString(&PdoDeviceExtension->InstanceId,
441*c1f22c88SEric Kohl                                                DriveInfo->PeripheralNumber);
442*c1f22c88SEric Kohl             if (!NT_SUCCESS(Status))
443*c1f22c88SEric Kohl             {
444*c1f22c88SEric Kohl //                ErrorStatus = Status;
445*c1f22c88SEric Kohl //                ErrorOccurred = TRUE;
446*c1f22c88SEric Kohl                 break;
447*c1f22c88SEric Kohl             }
448*c1f22c88SEric Kohl 
449*c1f22c88SEric Kohl #if 0
450*c1f22c88SEric Kohl              /* Add device description string */
451*c1f22c88SEric Kohl             Status = PciCreateDeviceDescriptionString(&PdoDeviceExtension->DeviceDescription, Device);
452*c1f22c88SEric Kohl             if (!NT_SUCCESS(Status))
453*c1f22c88SEric Kohl             {
454*c1f22c88SEric Kohl //                ErrorStatus = Status;
455*c1f22c88SEric Kohl //                ErrorOccurred = TRUE;
456*c1f22c88SEric Kohl                 break;
457*c1f22c88SEric Kohl             }
458*c1f22c88SEric Kohl 
459*c1f22c88SEric Kohl             /* Add device location string */
460*c1f22c88SEric Kohl             Status = PciCreateDeviceLocationString(&PdoDeviceExtension->DeviceLocation, Device);
461*c1f22c88SEric Kohl             if (!NT_SUCCESS(Status))
462*c1f22c88SEric Kohl             {
463*c1f22c88SEric Kohl //                ErrorStatus = Status;
464*c1f22c88SEric Kohl //                ErrorOccurred = TRUE;
465*c1f22c88SEric Kohl                 break;
466*c1f22c88SEric Kohl             }
467*c1f22c88SEric Kohl #endif
468*c1f22c88SEric Kohl         }
469*c1f22c88SEric Kohl 
470*c1f22c88SEric Kohl         ObReferenceObject(DriveInfo->DeviceObject);
471*c1f22c88SEric Kohl         Relations->Objects[i] = DriveInfo->DeviceObject;
472*c1f22c88SEric Kohl     }
473*c1f22c88SEric Kohl 
474*c1f22c88SEric Kohl done:
475*c1f22c88SEric Kohl     if (NT_SUCCESS(Status))
476*c1f22c88SEric Kohl     {
477*c1f22c88SEric Kohl         *DeviceRelations = Relations;
478*c1f22c88SEric Kohl     }
479*c1f22c88SEric Kohl     else
480*c1f22c88SEric Kohl     {
481*c1f22c88SEric Kohl         if (Relations != NULL)
482*c1f22c88SEric Kohl             ExFreePool(Relations);
483*c1f22c88SEric Kohl     }
484*c1f22c88SEric Kohl 
485*c1f22c88SEric Kohl     return Status;
486*c1f22c88SEric Kohl }
487*c1f22c88SEric Kohl 
488*c1f22c88SEric Kohl 
489*c1f22c88SEric Kohl NTSTATUS
490*c1f22c88SEric Kohl NTAPI
491*c1f22c88SEric Kohl FdcFdoPnp(
492*c1f22c88SEric Kohl     IN PDEVICE_OBJECT DeviceObject,
493*c1f22c88SEric Kohl     IN PIRP Irp)
494*c1f22c88SEric Kohl {
495*c1f22c88SEric Kohl     PIO_STACK_LOCATION IrpSp;
496*c1f22c88SEric Kohl     PDEVICE_RELATIONS DeviceRelations = NULL;
497*c1f22c88SEric Kohl     ULONG_PTR Information = 0;
498*c1f22c88SEric Kohl     NTSTATUS Status = STATUS_NOT_SUPPORTED;
499*c1f22c88SEric Kohl 
500*c1f22c88SEric Kohl     DPRINT("FdcFdoPnp()\n");
501*c1f22c88SEric Kohl 
502*c1f22c88SEric Kohl     IrpSp = IoGetCurrentIrpStackLocation(Irp);
503*c1f22c88SEric Kohl 
504*c1f22c88SEric Kohl     switch (IrpSp->MinorFunction)
505*c1f22c88SEric Kohl     {
506*c1f22c88SEric Kohl         case IRP_MN_START_DEVICE:
507*c1f22c88SEric Kohl             DPRINT("  IRP_MN_START_DEVICE received\n");
508*c1f22c88SEric Kohl             /* Call lower driver */
509*c1f22c88SEric Kohl             Status = ForwardIrpAndWait(DeviceObject, Irp);
510*c1f22c88SEric Kohl             if (NT_SUCCESS(Status))
511*c1f22c88SEric Kohl             {
512*c1f22c88SEric Kohl                 Status = FdcFdoStartDevice(DeviceObject,
513*c1f22c88SEric Kohl                                            IrpSp->Parameters.StartDevice.AllocatedResources,
514*c1f22c88SEric Kohl                                            IrpSp->Parameters.StartDevice.AllocatedResourcesTranslated);
515*c1f22c88SEric Kohl             }
516*c1f22c88SEric Kohl             break;
517*c1f22c88SEric Kohl 
518*c1f22c88SEric Kohl         case IRP_MN_QUERY_REMOVE_DEVICE:
519*c1f22c88SEric Kohl             DPRINT("  IRP_MN_QUERY_REMOVE_DEVICE\n");
520*c1f22c88SEric Kohl             break;
521*c1f22c88SEric Kohl 
522*c1f22c88SEric Kohl         case IRP_MN_REMOVE_DEVICE:
523*c1f22c88SEric Kohl             DPRINT("  IRP_MN_REMOVE_DEVICE received\n");
524*c1f22c88SEric Kohl             break;
525*c1f22c88SEric Kohl 
526*c1f22c88SEric Kohl         case IRP_MN_CANCEL_REMOVE_DEVICE:
527*c1f22c88SEric Kohl             DPRINT("  IRP_MN_CANCEL_REMOVE_DEVICE\n");
528*c1f22c88SEric Kohl             break;
529*c1f22c88SEric Kohl 
530*c1f22c88SEric Kohl         case IRP_MN_STOP_DEVICE:
531*c1f22c88SEric Kohl             DPRINT("  IRP_MN_STOP_DEVICE received\n");
532*c1f22c88SEric Kohl             break;
533*c1f22c88SEric Kohl 
534*c1f22c88SEric Kohl         case IRP_MN_QUERY_STOP_DEVICE:
535*c1f22c88SEric Kohl             DPRINT("  IRP_MN_QUERY_STOP_DEVICE received\n");
536*c1f22c88SEric Kohl             break;
537*c1f22c88SEric Kohl 
538*c1f22c88SEric Kohl         case IRP_MN_CANCEL_STOP_DEVICE:
539*c1f22c88SEric Kohl             DPRINT("  IRP_MN_CANCEL_STOP_DEVICE\n");
540*c1f22c88SEric Kohl             break;
541*c1f22c88SEric Kohl 
542*c1f22c88SEric Kohl         case IRP_MN_QUERY_DEVICE_RELATIONS:
543*c1f22c88SEric Kohl             DPRINT("  IRP_MN_QUERY_DEVICE_RELATIONS\n");
544*c1f22c88SEric Kohl 
545*c1f22c88SEric Kohl             switch (IrpSp->Parameters.QueryDeviceRelations.Type)
546*c1f22c88SEric Kohl             {
547*c1f22c88SEric Kohl                 case BusRelations:
548*c1f22c88SEric Kohl                     DPRINT("    IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
549*c1f22c88SEric Kohl                     Status = FdcFdoQueryBusRelations(DeviceObject, &DeviceRelations);
550*c1f22c88SEric Kohl                     Information = (ULONG_PTR)DeviceRelations;
551*c1f22c88SEric Kohl                     break;
552*c1f22c88SEric Kohl 
553*c1f22c88SEric Kohl                 case RemovalRelations:
554*c1f22c88SEric Kohl                     DPRINT("    IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
555*c1f22c88SEric Kohl                     return ForwardIrpAndForget(DeviceObject, Irp);
556*c1f22c88SEric Kohl 
557*c1f22c88SEric Kohl                 default:
558*c1f22c88SEric Kohl                     DPRINT("    IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
559*c1f22c88SEric Kohl                             IrpSp->Parameters.QueryDeviceRelations.Type);
560*c1f22c88SEric Kohl                     return ForwardIrpAndForget(DeviceObject, Irp);
561*c1f22c88SEric Kohl             }
562*c1f22c88SEric Kohl             break;
563*c1f22c88SEric Kohl 
564*c1f22c88SEric Kohl         case IRP_MN_SURPRISE_REMOVAL:
565*c1f22c88SEric Kohl             DPRINT("  IRP_MN_SURPRISE_REMOVAL received\n");
566*c1f22c88SEric Kohl             break;
567*c1f22c88SEric Kohl 
568*c1f22c88SEric Kohl         default:
569*c1f22c88SEric Kohl             DPRINT("  Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
570*c1f22c88SEric Kohl             return ForwardIrpAndForget(DeviceObject, Irp);
571*c1f22c88SEric Kohl     }
572*c1f22c88SEric Kohl 
573*c1f22c88SEric Kohl     Irp->IoStatus.Information = Information;
574*c1f22c88SEric Kohl     Irp->IoStatus.Status = Status;
575*c1f22c88SEric Kohl     IoCompleteRequest(Irp, IO_NO_INCREMENT);
576*c1f22c88SEric Kohl 
577*c1f22c88SEric Kohl     return Status;
578*c1f22c88SEric Kohl }
579*c1f22c88SEric Kohl 
580*c1f22c88SEric Kohl /* EOF */
581