[SCSIPORT] Use pointer alignment for MiniPortDeviceExtension
[reactos.git] / drivers / usb / usbccgp / fdo.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbccgp/fdo.c
5 * PURPOSE: USB device driver.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 * Cameron Gutman
10 */
11
12 #include "usbccgp.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 NTSTATUS
18 NTAPI
19 FDO_QueryCapabilitiesCompletionRoutine(
20 IN PDEVICE_OBJECT DeviceObject,
21 IN PIRP Irp,
22 IN PVOID Context)
23 {
24 /* Set event */
25 KeSetEvent((PRKEVENT)Context, 0, FALSE);
26
27 /* Completion is done in the HidClassFDO_QueryCapabilities routine */
28 return STATUS_MORE_PROCESSING_REQUIRED;
29 }
30
31 NTSTATUS
32 FDO_QueryCapabilities(
33 IN PDEVICE_OBJECT DeviceObject,
34 IN OUT PDEVICE_CAPABILITIES Capabilities)
35 {
36 PIRP Irp;
37 KEVENT Event;
38 NTSTATUS Status;
39 PIO_STACK_LOCATION IoStack;
40 PFDO_DEVICE_EXTENSION FDODeviceExtension;
41
42 /* Get device extension */
43 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
44 ASSERT(FDODeviceExtension->Common.IsFDO);
45
46 /* Init event */
47 KeInitializeEvent(&Event, NotificationEvent, FALSE);
48
49 /* Now allocate the irp */
50 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
51 if (!Irp)
52 {
53 /* No memory */
54 return STATUS_INSUFFICIENT_RESOURCES;
55 }
56
57 /* Get next stack location */
58 IoStack = IoGetNextIrpStackLocation(Irp);
59
60 /* Init stack location */
61 IoStack->MajorFunction = IRP_MJ_PNP;
62 IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
63 IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities;
64
65 /* Set completion routine */
66 IoSetCompletionRoutine(Irp,
67 FDO_QueryCapabilitiesCompletionRoutine,
68 (PVOID)&Event,
69 TRUE,
70 TRUE,
71 TRUE);
72
73 /* Init capabilities */
74 RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES));
75 Capabilities->Size = sizeof(DEVICE_CAPABILITIES);
76 Capabilities->Version = 1; // FIXME hardcoded constant
77 Capabilities->Address = MAXULONG;
78 Capabilities->UINumber = MAXULONG;
79
80 /* Pnp irps have default completion code */
81 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
82
83 /* Call lower device */
84 Status = IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
85 if (Status == STATUS_PENDING)
86 {
87 /* Wait for completion */
88 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
89 }
90
91 /* Get status */
92 Status = Irp->IoStatus.Status;
93
94 /* Complete request */
95 IoFreeIrp(Irp);
96
97 /* Done */
98 return Status;
99 }
100
101 NTSTATUS
102 FDO_DeviceRelations(
103 PDEVICE_OBJECT DeviceObject,
104 PIRP Irp)
105 {
106 ULONG DeviceCount = 0;
107 ULONG Index;
108 PDEVICE_RELATIONS DeviceRelations;
109 PIO_STACK_LOCATION IoStack;
110 PFDO_DEVICE_EXTENSION FDODeviceExtension;
111
112 /* Get device extension */
113 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
114
115 /* Get current irp stack location */
116 IoStack = IoGetCurrentIrpStackLocation(Irp);
117
118 /* Check if relation type is BusRelations */
119 if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
120 {
121 /* FDO always only handles bus relations */
122 return STATUS_SUCCESS;
123 }
124
125 /* Go through array and count device objects */
126 for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
127 {
128 if (FDODeviceExtension->ChildPDO[Index])
129 {
130 /* Child pdo */
131 DeviceCount++;
132 }
133 }
134
135 /* Allocate device relations */
136 DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool,
137 sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0));
138 if (!DeviceRelations)
139 {
140 /* No memory */
141 return STATUS_INSUFFICIENT_RESOURCES;
142 }
143
144 /* Add device objects */
145 for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
146 {
147 if (FDODeviceExtension->ChildPDO[Index])
148 {
149 /* Store child pdo */
150 DeviceRelations->Objects[DeviceRelations->Count] = FDODeviceExtension->ChildPDO[Index];
151
152 /* Add reference */
153 ObReferenceObject(FDODeviceExtension->ChildPDO[Index]);
154
155 /* Increment count */
156 DeviceRelations->Count++;
157 }
158 }
159
160 /* Store result */
161 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
162 Irp->IoStatus.Status = STATUS_SUCCESS;
163
164 /* Request completed successfully */
165 return STATUS_SUCCESS;
166 }
167
168 NTSTATUS
169 FDO_CreateChildPdo(
170 IN PDEVICE_OBJECT DeviceObject)
171 {
172 NTSTATUS Status;
173 PDEVICE_OBJECT PDODeviceObject;
174 PPDO_DEVICE_EXTENSION PDODeviceExtension;
175 PFDO_DEVICE_EXTENSION FDODeviceExtension;
176 ULONG Index;
177
178 /* Get device extension */
179 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
180 ASSERT(FDODeviceExtension->Common.IsFDO);
181
182 /* Lets create array for the child PDO */
183 FDODeviceExtension->ChildPDO = AllocateItem(NonPagedPool,
184 sizeof(PDEVICE_OBJECT) * FDODeviceExtension->FunctionDescriptorCount);
185 if (!FDODeviceExtension->ChildPDO)
186 {
187 /* No memory */
188 return STATUS_INSUFFICIENT_RESOURCES;
189 }
190
191 /* Create pdo for each function */
192 for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
193 {
194 /* Create the PDO */
195 Status = IoCreateDevice(FDODeviceExtension->DriverObject,
196 sizeof(PDO_DEVICE_EXTENSION),
197 NULL,
198 FILE_DEVICE_USB,
199 FILE_AUTOGENERATED_DEVICE_NAME,
200 FALSE,
201 &PDODeviceObject);
202 if (!NT_SUCCESS(Status))
203 {
204 /* Failed to create device object */
205 DPRINT1("IoCreateDevice failed with %x\n", Status);
206 return Status;
207 }
208
209 /* Store in array */
210 FDODeviceExtension->ChildPDO[Index] = PDODeviceObject;
211
212 /* Get device extension */
213 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
214 RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
215
216 /* Init device extension */
217 PDODeviceExtension->Common.IsFDO = FALSE;
218 PDODeviceExtension->FunctionDescriptor = &FDODeviceExtension->FunctionDescriptor[Index];
219 PDODeviceExtension->NextDeviceObject = DeviceObject;
220 PDODeviceExtension->FunctionIndex = Index;
221 PDODeviceExtension->FDODeviceExtension = FDODeviceExtension;
222 PDODeviceExtension->InterfaceList = FDODeviceExtension->InterfaceList;
223 PDODeviceExtension->InterfaceListCount = FDODeviceExtension->InterfaceListCount;
224 PDODeviceExtension->ConfigurationHandle = FDODeviceExtension->ConfigurationHandle;
225 PDODeviceExtension->ConfigurationDescriptor = FDODeviceExtension->ConfigurationDescriptor;
226 RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
227 RtlCopyMemory(&PDODeviceExtension->DeviceDescriptor, FDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
228
229 /* Patch the stack size */
230 PDODeviceObject->StackSize = DeviceObject->StackSize + 1;
231
232 /* Set device flags */
233 PDODeviceObject->Flags |= DO_DIRECT_IO | DO_MAP_IO_BUFFER;
234
235 /* Device is initialized */
236 PDODeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
237 }
238
239 /* Done */
240 return STATUS_SUCCESS;
241 }
242
243 NTSTATUS
244 FDO_StartDevice(
245 PDEVICE_OBJECT DeviceObject,
246 PIRP Irp)
247 {
248 NTSTATUS Status;
249 PFDO_DEVICE_EXTENSION FDODeviceExtension;
250
251 /* Get device extension */
252 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
253 ASSERT(FDODeviceExtension->Common.IsFDO);
254
255 /* First start lower device */
256 Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
257
258 if (!NT_SUCCESS(Status))
259 {
260 /* Failed to start lower device */
261 DPRINT1("FDO_StartDevice lower device failed to start with %x\n", Status);
262 return Status;
263 }
264
265 /* Get descriptors */
266 Status = USBCCGP_GetDescriptors(DeviceObject);
267 if (!NT_SUCCESS(Status))
268 {
269 /* Failed to start lower device */
270 DPRINT1("FDO_StartDevice failed to get descriptors with %x\n", Status);
271 return Status;
272 }
273
274 /* Get capabilities */
275 Status = FDO_QueryCapabilities(DeviceObject,
276 &FDODeviceExtension->Capabilities);
277 if (!NT_SUCCESS(Status))
278 {
279 /* Failed to start lower device */
280 DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status);
281 return Status;
282 }
283
284 /* Now select the configuration */
285 Status = USBCCGP_SelectConfiguration(DeviceObject, FDODeviceExtension);
286 if (!NT_SUCCESS(Status))
287 {
288 /* Failed to select interface */
289 DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status);
290 return Status;
291 }
292
293 /* Query bus interface */
294 USBCCGP_QueryInterface(FDODeviceExtension->NextDeviceObject,
295 &FDODeviceExtension->BusInterface);
296
297 /* Now enumerate the functions */
298 Status = USBCCGP_EnumerateFunctions(DeviceObject);
299 if (!NT_SUCCESS(Status))
300 {
301 /* Failed to enumerate functions */
302 DPRINT1("Failed to enumerate functions with %x\n", Status);
303 return Status;
304 }
305
306 /* Sanity checks */
307 ASSERT(FDODeviceExtension->FunctionDescriptorCount);
308 ASSERT(FDODeviceExtension->FunctionDescriptor);
309 DumpFunctionDescriptor(FDODeviceExtension->FunctionDescriptor,
310 FDODeviceExtension->FunctionDescriptorCount);
311
312 /* Now create the pdo */
313 Status = FDO_CreateChildPdo(DeviceObject);
314 if (!NT_SUCCESS(Status))
315 {
316 /* Failed */
317 DPRINT1("FDO_CreateChildPdo failed with %x\n", Status);
318 return Status;
319 }
320
321 /* Inform pnp manager of new device objects */
322 IoInvalidateDeviceRelations(FDODeviceExtension->PhysicalDeviceObject,
323 BusRelations);
324
325 /* Done */
326 DPRINT("[USBCCGP] FDO initialized successfully\n");
327 return Status;
328 }
329
330 NTSTATUS
331 FDO_CloseConfiguration(
332 IN PDEVICE_OBJECT DeviceObject)
333 {
334 NTSTATUS Status;
335 PURB Urb;
336 PFDO_DEVICE_EXTENSION FDODeviceExtension;
337
338 /* Get device extension */
339 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
340 ASSERT(FDODeviceExtension->Common.IsFDO);
341
342 /* Nothing to do if we're not configured */
343 if (FDODeviceExtension->ConfigurationDescriptor == NULL ||
344 FDODeviceExtension->InterfaceList == NULL)
345 {
346 return STATUS_SUCCESS;
347 }
348
349 /* Now allocate the urb */
350 Urb = USBD_CreateConfigurationRequestEx(FDODeviceExtension->ConfigurationDescriptor,
351 FDODeviceExtension->InterfaceList);
352 if (!Urb)
353 {
354 /* No memory */
355 return STATUS_INSUFFICIENT_RESOURCES;
356 }
357
358 /* Clear configuration descriptor to make it an unconfigure request */
359 Urb->UrbSelectConfiguration.ConfigurationDescriptor = NULL;
360
361 /* Submit urb */
362 Status = USBCCGP_SyncUrbRequest(FDODeviceExtension->NextDeviceObject, Urb);
363 if (!NT_SUCCESS(Status))
364 {
365 /* Failed to set configuration */
366 DPRINT1("USBCCGP_SyncUrbRequest failed to unconfigure device\n", Status);
367 }
368
369 ExFreePool(Urb);
370 return Status;
371 }
372
373
374 NTSTATUS
375 FDO_HandlePnp(
376 PDEVICE_OBJECT DeviceObject,
377 PIRP Irp)
378 {
379 PIO_STACK_LOCATION IoStack;
380 NTSTATUS Status;
381 PFDO_DEVICE_EXTENSION FDODeviceExtension;
382
383 /* Get device extension */
384 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
385 ASSERT(FDODeviceExtension->Common.IsFDO);
386
387
388 /* Get stack location */
389 IoStack = IoGetCurrentIrpStackLocation(Irp);
390 DPRINT("[USBCCGP] PnP Minor %x\n", IoStack->MinorFunction);
391 switch(IoStack->MinorFunction)
392 {
393 case IRP_MN_REMOVE_DEVICE:
394 {
395 // Unconfigure device */
396 DPRINT1("[USBCCGP] FDO IRP_MN_REMOVE\n");
397 FDO_CloseConfiguration(DeviceObject);
398
399 /* Send the IRP down the stack */
400 Irp->IoStatus.Status = STATUS_SUCCESS;
401 IoSkipCurrentIrpStackLocation(Irp);
402 Status = IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
403
404 /* Detach from the device stack */
405 IoDetachDevice(FDODeviceExtension->NextDeviceObject);
406
407 /* Delete the device object */
408 IoDeleteDevice(DeviceObject);
409
410 /* Request completed */
411 break;
412 }
413 case IRP_MN_START_DEVICE:
414 {
415 /* Start the device */
416 Status = FDO_StartDevice(DeviceObject, Irp);
417 break;
418 }
419 case IRP_MN_QUERY_DEVICE_RELATIONS:
420 {
421 /* Handle device relations */
422 Status = FDO_DeviceRelations(DeviceObject, Irp);
423 if (!NT_SUCCESS(Status))
424 {
425 break;
426 }
427
428 /* Forward irp to next device object */
429 IoSkipCurrentIrpStackLocation(Irp);
430 return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
431 }
432 case IRP_MN_QUERY_CAPABILITIES:
433 {
434 /* Copy capabilities */
435 RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities,
436 &FDODeviceExtension->Capabilities,
437 sizeof(DEVICE_CAPABILITIES));
438 Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
439 if (NT_SUCCESS(Status))
440 {
441 /* Surprise removal ok */
442 IoStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
443 }
444 break;
445 }
446 case IRP_MN_QUERY_REMOVE_DEVICE:
447 case IRP_MN_QUERY_STOP_DEVICE:
448 {
449 /* Sure */
450 Irp->IoStatus.Status = STATUS_SUCCESS;
451
452 /* Forward irp to next device object */
453 IoSkipCurrentIrpStackLocation(Irp);
454 return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
455 }
456 default:
457 {
458 /* Forward irp to next device object */
459 IoSkipCurrentIrpStackLocation(Irp);
460 return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
461 }
462
463 }
464
465 /* Complete request */
466 Irp->IoStatus.Status = Status;
467 IoCompleteRequest(Irp, IO_NO_INCREMENT);
468 return Status;
469 }
470
471 NTSTATUS
472 FDO_HandleResetCyclePort(
473 PDEVICE_OBJECT DeviceObject,
474 PIRP Irp)
475 {
476 PIO_STACK_LOCATION IoStack;
477 NTSTATUS Status;
478 PFDO_DEVICE_EXTENSION FDODeviceExtension;
479 PLIST_ENTRY ListHead, Entry;
480 LIST_ENTRY TempList;
481 PUCHAR ResetActive;
482 PIRP ListIrp;
483 KIRQL OldLevel;
484
485 /* Get device extension */
486 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
487 ASSERT(FDODeviceExtension->Common.IsFDO);
488
489 /* Get stack location */
490 IoStack = IoGetCurrentIrpStackLocation(Irp);
491 DPRINT("FDO_HandleResetCyclePort IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
492
493 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT)
494 {
495 /* Use reset port list */
496 ListHead = &FDODeviceExtension->ResetPortListHead;
497 ResetActive = &FDODeviceExtension->ResetPortActive;
498 }
499 else
500 {
501 /* Use cycle port list */
502 ListHead = &FDODeviceExtension->CyclePortListHead;
503 ResetActive = &FDODeviceExtension->CyclePortActive;
504 }
505
506 /* Acquire lock */
507 KeAcquireSpinLock(&FDODeviceExtension->Lock, &OldLevel);
508
509 if (*ResetActive)
510 {
511 /* Insert into pending list */
512 InsertTailList(ListHead, &Irp->Tail.Overlay.ListEntry);
513
514 /* Mark irp pending */
515 IoMarkIrpPending(Irp);
516 Status = STATUS_PENDING;
517
518 /* Release lock */
519 KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
520 }
521 else
522 {
523 /* Mark reset active */
524 *ResetActive = TRUE;
525
526 /* Release lock */
527 KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
528
529 /* Forward request synchronized */
530 USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
531
532 /* Reacquire lock */
533 KeAcquireSpinLock(&FDODeviceExtension->Lock, &OldLevel);
534
535 /* Mark reset as completed */
536 *ResetActive = FALSE;
537
538 /* Move all requests into temporary list */
539 InitializeListHead(&TempList);
540 while(!IsListEmpty(ListHead))
541 {
542 Entry = RemoveHeadList(ListHead);
543 InsertTailList(&TempList, Entry);
544 }
545
546 /* Release lock */
547 KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
548
549 /* Complete pending irps */
550 while(!IsListEmpty(&TempList))
551 {
552 Entry = RemoveHeadList(&TempList);
553 ListIrp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
554
555 /* Complete request with status success */
556 ListIrp->IoStatus.Status = STATUS_SUCCESS;
557 IoCompleteRequest(ListIrp, IO_NO_INCREMENT);
558 }
559
560 /* Status success */
561 Status = STATUS_SUCCESS;
562 }
563
564 return Status;
565 }
566
567
568
569 NTSTATUS
570 FDO_HandleInternalDeviceControl(
571 PDEVICE_OBJECT DeviceObject,
572 PIRP Irp)
573 {
574 PIO_STACK_LOCATION IoStack;
575 NTSTATUS Status;
576 PFDO_DEVICE_EXTENSION FDODeviceExtension;
577
578 /* Get device extension */
579 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
580 ASSERT(FDODeviceExtension->Common.IsFDO);
581
582 /* Get stack location */
583 IoStack = IoGetCurrentIrpStackLocation(Irp);
584
585 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT ||
586 IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_CYCLE_PORT)
587 {
588 /* Handle reset / cycle ports */
589 Status = FDO_HandleResetCyclePort(DeviceObject, Irp);
590 DPRINT("FDO_HandleResetCyclePort Status %x\n", Status);
591 if (Status != STATUS_PENDING)
592 {
593 /* Complete request */
594 Irp->IoStatus.Status = Status;
595 IoCompleteRequest(Irp, IO_NO_INCREMENT);
596 }
597 return Status;
598 }
599
600 /* Forward and forget request */
601 IoSkipCurrentIrpStackLocation(Irp);
602 return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
603 }
604
605 NTSTATUS
606 FDO_HandleSystemControl(
607 PDEVICE_OBJECT DeviceObject,
608 PIRP Irp)
609 {
610 PFDO_DEVICE_EXTENSION FDODeviceExtension;
611
612 /* Get device extension */
613 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
614 ASSERT(FDODeviceExtension->Common.IsFDO);
615
616 /* Forward and forget request */
617 IoSkipCurrentIrpStackLocation(Irp);
618 return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
619 }
620
621 NTSTATUS
622 FDO_Dispatch(
623 PDEVICE_OBJECT DeviceObject,
624 PIRP Irp)
625 {
626 PIO_STACK_LOCATION IoStack;
627 NTSTATUS Status;
628 PFDO_DEVICE_EXTENSION FDODeviceExtension;
629
630 /* Get device extension */
631 FDODeviceExtension = DeviceObject->DeviceExtension;
632 ASSERT(FDODeviceExtension->Common.IsFDO);
633
634 /* Get stack location */
635 IoStack = IoGetCurrentIrpStackLocation(Irp);
636
637 switch(IoStack->MajorFunction)
638 {
639 case IRP_MJ_PNP:
640 return FDO_HandlePnp(DeviceObject, Irp);
641 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
642 return FDO_HandleInternalDeviceControl(DeviceObject, Irp);
643 case IRP_MJ_POWER:
644 PoStartNextPowerIrp(Irp);
645 IoSkipCurrentIrpStackLocation(Irp);
646 return PoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
647 case IRP_MJ_SYSTEM_CONTROL:
648 return FDO_HandleSystemControl(DeviceObject, Irp);
649 default:
650 DPRINT1("FDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
651 ASSERT(FALSE);
652 Status = Irp->IoStatus.Status;
653 IoCompleteRequest(Irp, IO_NO_INCREMENT);
654 return Status;
655 }
656
657 }