86c79e89ccc64eb26b767e05260fdcbc549682c2
[reactos.git] / reactos / drivers / storage / fdc / fdc / fdo.c
1 /*
2 * PROJECT: ReactOS Floppy Disk Controller Driver
3 * LICENSE: GNU GPLv2 only as published by the Free Software Foundation
4 * FILE: drivers/storage/fdc/fdc/fdo.c
5 * PURPOSE: Functional Device Object routines
6 * PROGRAMMERS: Eric Kohl
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "fdc.h"
12
13 /* FUNCTIONS ******************************************************************/
14
15 static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion;
16
17 static
18 NTSTATUS
19 NTAPI
20 ForwardIrpAndWaitCompletion(
21 IN PDEVICE_OBJECT DeviceObject,
22 IN PIRP Irp,
23 IN PVOID Context)
24 {
25 if (Irp->PendingReturned)
26 KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
27 return STATUS_MORE_PROCESSING_REQUIRED;
28 }
29
30
31 NTSTATUS
32 ForwardIrpAndWait(
33 IN PDEVICE_OBJECT DeviceObject,
34 IN PIRP Irp)
35 {
36 PDEVICE_OBJECT LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
37 KEVENT Event;
38 NTSTATUS Status;
39
40 ASSERT(LowerDevice);
41
42 KeInitializeEvent(&Event, NotificationEvent, FALSE);
43 IoCopyCurrentIrpStackLocationToNext(Irp);
44
45 DPRINT("Calling lower device %p\n", LowerDevice);
46 IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
47
48 Status = IoCallDriver(LowerDevice, Irp);
49 if (Status == STATUS_PENDING)
50 {
51 Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
52 if (NT_SUCCESS(Status))
53 Status = Irp->IoStatus.Status;
54 }
55
56 return Status;
57 }
58
59
60 NTSTATUS
61 NTAPI
62 ForwardIrpAndForget(
63 IN PDEVICE_OBJECT DeviceObject,
64 IN PIRP Irp)
65 {
66 PDEVICE_OBJECT LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
67
68 ASSERT(LowerDevice);
69
70 IoSkipCurrentIrpStackLocation(Irp);
71 return IoCallDriver(LowerDevice, Irp);
72 }
73
74
75 NTSTATUS
76 NTAPI
77 FdcAddDevice(
78 IN PDRIVER_OBJECT DriverObject,
79 IN PDEVICE_OBJECT Pdo)
80 {
81 PFDO_DEVICE_EXTENSION DeviceExtension = NULL;
82 PDEVICE_OBJECT Fdo = NULL;
83 NTSTATUS Status;
84
85 DPRINT1("FdcAddDevice()\n");
86
87 ASSERT(DriverObject);
88 ASSERT(Pdo);
89
90 /* Create functional device object */
91 Status = IoCreateDevice(DriverObject,
92 sizeof(FDO_DEVICE_EXTENSION),
93 NULL,
94 FILE_DEVICE_CONTROLLER,
95 FILE_DEVICE_SECURE_OPEN,
96 FALSE,
97 &Fdo);
98 if (NT_SUCCESS(Status))
99 {
100 DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
101 RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
102
103 DeviceExtension->Common.IsFDO = TRUE;
104
105 DeviceExtension->Fdo = Fdo;
106 DeviceExtension->Pdo = Pdo;
107
108
109 Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
110 if (!NT_SUCCESS(Status))
111 {
112 DPRINT1("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
113 IoDeleteDevice(Fdo);
114 return Status;
115 }
116
117
118 Fdo->Flags |= DO_DIRECT_IO;
119 Fdo->Flags |= DO_POWER_PAGABLE;
120
121 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
122 }
123
124 return Status;
125 }
126
127
128 static
129 NTSTATUS
130 FdcFdoStartDevice(
131 IN PDEVICE_OBJECT DeviceObject,
132 IN PCM_RESOURCE_LIST ResourceList,
133 IN PCM_RESOURCE_LIST ResourceListTranslated)
134 {
135 PFDO_DEVICE_EXTENSION DeviceExtension;
136 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
137 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptorTranslated;
138 ULONG i;
139
140 DPRINT1("FdcFdoStartDevice called\n");
141
142 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
143
144 ASSERT(DeviceExtension);
145
146 if (ResourceList == NULL ||
147 ResourceListTranslated == NULL)
148 {
149 DPRINT1("No allocated resources sent to driver\n");
150 return STATUS_INSUFFICIENT_RESOURCES;
151 }
152
153 if (ResourceList->Count != 1)
154 {
155 DPRINT1("Wrong number of allocated resources sent to driver\n");
156 return STATUS_INSUFFICIENT_RESOURCES;
157 }
158
159 if (ResourceList->List[0].PartialResourceList.Version != 1 ||
160 ResourceList->List[0].PartialResourceList.Revision != 1 ||
161 ResourceListTranslated->List[0].PartialResourceList.Version != 1 ||
162 ResourceListTranslated->List[0].PartialResourceList.Revision != 1)
163 {
164 DPRINT1("Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n",
165 ResourceList->List[0].PartialResourceList.Version,
166 ResourceList->List[0].PartialResourceList.Revision,
167 ResourceListTranslated->List[0].PartialResourceList.Version,
168 ResourceListTranslated->List[0].PartialResourceList.Revision);
169 return STATUS_REVISION_MISMATCH;
170 }
171
172 for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++)
173 {
174 PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
175 PartialDescriptorTranslated = &ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[i];
176
177 switch (PartialDescriptor->Type)
178 {
179 case CmResourceTypePort:
180 DPRINT1("Port: 0x%lx (%lu)\n",
181 PartialDescriptor->u.Port.Start.u.LowPart,
182 PartialDescriptor->u.Port.Length);
183 break;
184
185 case CmResourceTypeInterrupt:
186 DPRINT1("Interrupt: Level %lu Vector %lu\n",
187 PartialDescriptorTranslated->u.Interrupt.Level,
188 PartialDescriptorTranslated->u.Interrupt.Vector);
189 break;
190
191 case CmResourceTypeDma:
192 DPRINT1("Dma: Channel %lu\n",
193 PartialDescriptor->u.Dma.Channel);
194 break;
195 }
196 }
197
198 return STATUS_SUCCESS;
199 }
200
201
202 static
203 NTSTATUS
204 FdcFdoQueryBusRelations(
205 IN PDEVICE_OBJECT DeviceObject,
206 OUT PDEVICE_RELATIONS *DeviceRelations)
207 {
208 DPRINT1("FdcFdoQueryBusRelations() called\n");
209 return STATUS_SUCCESS;
210 }
211
212
213 NTSTATUS
214 NTAPI
215 FdcFdoPnp(
216 IN PDEVICE_OBJECT DeviceObject,
217 IN PIRP Irp)
218 {
219 PIO_STACK_LOCATION IrpSp;
220 PDEVICE_RELATIONS DeviceRelations = NULL;
221 ULONG_PTR Information = 0;
222 NTSTATUS Status = STATUS_NOT_SUPPORTED;
223
224 DPRINT1("FdcFdoPnp()\n");
225
226 IrpSp = IoGetCurrentIrpStackLocation(Irp);
227
228 switch (IrpSp->MinorFunction)
229 {
230 case IRP_MN_START_DEVICE:
231 DPRINT1(" IRP_MN_START_DEVICE received\n");
232 /* Call lower driver */
233 Status = ForwardIrpAndWait(DeviceObject, Irp);
234 if (NT_SUCCESS(Status))
235 {
236 Status = FdcFdoStartDevice(DeviceObject,
237 IrpSp->Parameters.StartDevice.AllocatedResources,
238 IrpSp->Parameters.StartDevice.AllocatedResourcesTranslated);
239 }
240 break;
241
242 case IRP_MN_QUERY_REMOVE_DEVICE:
243 DPRINT1(" IRP_MN_QUERY_REMOVE_DEVICE\n");
244 break;
245
246 case IRP_MN_REMOVE_DEVICE:
247 DPRINT1(" IRP_MN_REMOVE_DEVICE received\n");
248 break;
249
250 case IRP_MN_CANCEL_REMOVE_DEVICE:
251 DPRINT1(" IRP_MN_CANCEL_REMOVE_DEVICE\n");
252 break;
253
254 case IRP_MN_STOP_DEVICE:
255 DPRINT1(" IRP_MN_STOP_DEVICE received\n");
256 break;
257
258 case IRP_MN_QUERY_STOP_DEVICE:
259 DPRINT1(" IRP_MN_QUERY_STOP_DEVICE received\n");
260 break;
261
262 case IRP_MN_CANCEL_STOP_DEVICE:
263 DPRINT1(" IRP_MN_CANCEL_STOP_DEVICE\n");
264 break;
265
266 case IRP_MN_QUERY_DEVICE_RELATIONS:
267 DPRINT1(" IRP_MN_QUERY_DEVICE_RELATIONS\n");
268
269 switch (IrpSp->Parameters.QueryDeviceRelations.Type)
270 {
271 case BusRelations:
272 DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
273 Status = FdcFdoQueryBusRelations((DeviceObject, &DeviceRelations);
274 Information = (ULONG_PTR)DeviceRelations;
275 break;
276
277 case RemovalRelations:
278 DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
279 return ForwardIrpAndForget(DeviceObject, Irp);
280
281 default:
282 DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
283 IrpSp->Parameters.QueryDeviceRelations.Type);
284 return ForwardIrpAndForget(DeviceObject, Irp);
285 }
286 break;
287
288 case IRP_MN_SURPRISE_REMOVAL:
289 DPRINT1(" IRP_MN_SURPRISE_REMOVAL received\n");
290 break;
291
292 default:
293 DPRINT(" Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
294 return ForwardIrpAndForget(DeviceObject, Irp);
295 }
296
297 Irp->IoStatus.Information = Information;
298 Irp->IoStatus.Status = Status;
299 IoCompleteRequest(Irp, IO_NO_INCREMENT);
300
301 return Status;
302 }
303
304 /* EOF */