xref: /reactos/drivers/usb/usbccgp/fdo.c (revision 1ac9e484)
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 USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
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 
163     /* Request completed successfully */
164     return STATUS_SUCCESS;
165 }
166 
167 NTSTATUS
168 FDO_CreateChildPdo(
169     IN PDEVICE_OBJECT DeviceObject)
170 {
171     NTSTATUS Status;
172     PDEVICE_OBJECT PDODeviceObject;
173     PPDO_DEVICE_EXTENSION PDODeviceExtension;
174     PFDO_DEVICE_EXTENSION FDODeviceExtension;
175     ULONG Index;
176 
177     /* Get device extension */
178     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
179     ASSERT(FDODeviceExtension->Common.IsFDO);
180 
181     /* Lets create array for the child PDO */
182     FDODeviceExtension->ChildPDO = AllocateItem(NonPagedPool,
183                                                 sizeof(PDEVICE_OBJECT) * FDODeviceExtension->FunctionDescriptorCount);
184     if (!FDODeviceExtension->ChildPDO)
185     {
186         /* No memory */
187         return STATUS_INSUFFICIENT_RESOURCES;
188     }
189 
190     /* Create pdo for each function */
191     for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
192     {
193         /* Create the PDO */
194         Status = IoCreateDevice(FDODeviceExtension->DriverObject,
195                                 sizeof(PDO_DEVICE_EXTENSION),
196                                 NULL,
197                                 FILE_DEVICE_USB,
198                                 FILE_AUTOGENERATED_DEVICE_NAME,
199                                 FALSE,
200                                 &PDODeviceObject);
201         if (!NT_SUCCESS(Status))
202         {
203             /* Failed to create device object */
204             DPRINT1("IoCreateDevice failed with %x\n", Status);
205             return Status;
206         }
207 
208         /* Store in array */
209         FDODeviceExtension->ChildPDO[Index] = PDODeviceObject;
210 
211         /* Get device extension */
212         PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
213         RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
214 
215         /* Init device extension */
216         PDODeviceExtension->Common.IsFDO = FALSE;
217         PDODeviceExtension->FunctionDescriptor = &FDODeviceExtension->FunctionDescriptor[Index];
218         PDODeviceExtension->NextDeviceObject = DeviceObject;
219         PDODeviceExtension->FunctionIndex = Index;
220         PDODeviceExtension->FDODeviceExtension = FDODeviceExtension;
221         PDODeviceExtension->InterfaceList = FDODeviceExtension->InterfaceList;
222         PDODeviceExtension->InterfaceListCount = FDODeviceExtension->InterfaceListCount;
223         PDODeviceExtension->ConfigurationHandle = FDODeviceExtension->ConfigurationHandle;
224         PDODeviceExtension->ConfigurationDescriptor = FDODeviceExtension->ConfigurationDescriptor;
225         RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
226         RtlCopyMemory(&PDODeviceExtension->DeviceDescriptor, FDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
227 
228         /* Patch the stack size */
229         PDODeviceObject->StackSize = DeviceObject->StackSize + 1;
230 
231         /* Set device flags */
232         PDODeviceObject->Flags |= DO_DIRECT_IO | DO_MAP_IO_BUFFER;
233 
234         /* Device is initialized */
235         PDODeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
236     }
237 
238     /* Done */
239     return STATUS_SUCCESS;
240 }
241 
242 NTSTATUS
243 FDO_StartDevice(
244     PDEVICE_OBJECT DeviceObject,
245     PIRP Irp)
246 {
247     NTSTATUS Status;
248     PFDO_DEVICE_EXTENSION FDODeviceExtension;
249 
250     /* Get device extension */
251     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
252     ASSERT(FDODeviceExtension->Common.IsFDO);
253 
254     /* First start lower device */
255     Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
256 
257     if (!NT_SUCCESS(Status))
258     {
259         /* Failed to start lower device */
260         DPRINT1("FDO_StartDevice lower device failed to start with %x\n", Status);
261         return Status;
262     }
263 
264     /* Get descriptors */
265     Status = USBCCGP_GetDescriptors(DeviceObject);
266     if (!NT_SUCCESS(Status))
267     {
268         /* Failed to start lower device */
269         DPRINT1("FDO_StartDevice failed to get descriptors with %x\n", Status);
270         return Status;
271     }
272 
273     /* Get capabilities */
274     Status = FDO_QueryCapabilities(DeviceObject,
275                                    &FDODeviceExtension->Capabilities);
276     if (!NT_SUCCESS(Status))
277     {
278         /* Failed to start lower device */
279         DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status);
280         return Status;
281     }
282 
283     /* Now select the configuration */
284     Status = USBCCGP_SelectConfiguration(DeviceObject, FDODeviceExtension);
285     if (!NT_SUCCESS(Status))
286     {
287         /* Failed to select interface */
288         DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status);
289         return Status;
290     }
291 
292     /* Query bus interface */
293     USBCCGP_QueryInterface(FDODeviceExtension->NextDeviceObject,
294                            &FDODeviceExtension->BusInterface);
295 
296     /* Now enumerate the functions */
297     Status = USBCCGP_EnumerateFunctions(DeviceObject);
298     if (!NT_SUCCESS(Status))
299     {
300         /* Failed to enumerate functions */
301         DPRINT1("Failed to enumerate functions with %x\n", Status);
302         return Status;
303     }
304 
305     /* Sanity checks */
306     ASSERT(FDODeviceExtension->FunctionDescriptorCount);
307     ASSERT(FDODeviceExtension->FunctionDescriptor);
308     DumpFunctionDescriptor(FDODeviceExtension->FunctionDescriptor,
309                            FDODeviceExtension->FunctionDescriptorCount);
310 
311     /* Now create the pdo */
312     Status = FDO_CreateChildPdo(DeviceObject);
313     if (!NT_SUCCESS(Status))
314     {
315         /* Failed */
316         DPRINT1("FDO_CreateChildPdo failed with %x\n", Status);
317         return Status;
318     }
319 
320     /* Inform pnp manager of new device objects */
321     IoInvalidateDeviceRelations(FDODeviceExtension->PhysicalDeviceObject,
322                                 BusRelations);
323 
324     /* Done */
325     DPRINT("[USBCCGP] FDO initialized successfully\n");
326     return Status;
327 }
328 
329 NTSTATUS
330 FDO_CloseConfiguration(
331     IN PDEVICE_OBJECT DeviceObject)
332 {
333     NTSTATUS Status;
334     PURB Urb;
335     PFDO_DEVICE_EXTENSION FDODeviceExtension;
336 
337     /* Get device extension */
338     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
339     ASSERT(FDODeviceExtension->Common.IsFDO);
340 
341     /* Nothing to do if we're not configured */
342     if (FDODeviceExtension->ConfigurationDescriptor == NULL ||
343         FDODeviceExtension->InterfaceList == NULL)
344     {
345         return STATUS_SUCCESS;
346     }
347 
348     /* Now allocate the urb */
349     Urb = USBD_CreateConfigurationRequestEx(FDODeviceExtension->ConfigurationDescriptor,
350                                             FDODeviceExtension->InterfaceList);
351     if (!Urb)
352     {
353         /* No memory */
354         return STATUS_INSUFFICIENT_RESOURCES;
355     }
356 
357     /* Clear configuration descriptor to make it an unconfigure request */
358     Urb->UrbSelectConfiguration.ConfigurationDescriptor = NULL;
359 
360     /* Submit urb */
361     Status = USBCCGP_SyncUrbRequest(FDODeviceExtension->NextDeviceObject, Urb);
362     if (!NT_SUCCESS(Status))
363     {
364         /* Failed to set configuration */
365         DPRINT1("USBCCGP_SyncUrbRequest failed to unconfigure device\n", Status);
366     }
367 
368     ExFreePool(Urb);
369     return Status;
370 }
371 
372 
373 NTSTATUS
374 FDO_HandlePnp(
375     PDEVICE_OBJECT DeviceObject,
376     PIRP Irp)
377 {
378     PIO_STACK_LOCATION IoStack;
379     NTSTATUS Status;
380     PFDO_DEVICE_EXTENSION FDODeviceExtension;
381 
382     /* Get device extension */
383     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
384     ASSERT(FDODeviceExtension->Common.IsFDO);
385 
386 
387     /* Get stack location */
388     IoStack = IoGetCurrentIrpStackLocation(Irp);
389     DPRINT("[USBCCGP] PnP Minor %x\n", IoStack->MinorFunction);
390     switch(IoStack->MinorFunction)
391     {
392         case IRP_MN_REMOVE_DEVICE:
393         {
394             // Unconfigure device */
395             DPRINT1("[USBCCGP] FDO IRP_MN_REMOVE\n");
396             FDO_CloseConfiguration(DeviceObject);
397 
398             /* Send the IRP down the stack */
399             Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject,
400                                             Irp);
401             if (NT_SUCCESS(Status))
402             {
403                 /* Detach from the device stack */
404                 IoDetachDevice(FDODeviceExtension->NextDeviceObject);
405 
406                 /* Delete the device object */
407                 IoDeleteDevice(DeviceObject);
408             }
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             break;
424         }
425         case IRP_MN_QUERY_CAPABILITIES:
426         {
427             /* Copy capabilities */
428             RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities,
429                           &FDODeviceExtension->Capabilities,
430                           sizeof(DEVICE_CAPABILITIES));
431             Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
432             if (NT_SUCCESS(Status))
433             {
434                 /* Surprise removal ok */
435                 IoStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
436             }
437             break;
438        }
439         case IRP_MN_QUERY_REMOVE_DEVICE:
440         case IRP_MN_QUERY_STOP_DEVICE:
441         {
442             /* Sure */
443             Irp->IoStatus.Status = STATUS_SUCCESS;
444 
445             /* Forward irp to next device object */
446             IoSkipCurrentIrpStackLocation(Irp);
447             return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
448         }
449        default:
450        {
451             /* Forward irp to next device object */
452             IoSkipCurrentIrpStackLocation(Irp);
453             return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
454        }
455 
456     }
457 
458     /* Complete request */
459     Irp->IoStatus.Status = Status;
460     IoCompleteRequest(Irp, IO_NO_INCREMENT);
461     return Status;
462 }
463 
464 NTSTATUS
465 FDO_HandleResetCyclePort(
466     PDEVICE_OBJECT DeviceObject,
467     PIRP Irp)
468 {
469     PIO_STACK_LOCATION IoStack;
470     NTSTATUS Status;
471     PFDO_DEVICE_EXTENSION FDODeviceExtension;
472     PLIST_ENTRY ListHead, Entry;
473     LIST_ENTRY TempList;
474     PUCHAR ResetActive;
475     PIRP ListIrp;
476     KIRQL OldLevel;
477 
478     /* Get device extension */
479     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
480     ASSERT(FDODeviceExtension->Common.IsFDO);
481 
482     /* Get stack location */
483     IoStack = IoGetCurrentIrpStackLocation(Irp);
484     DPRINT("FDO_HandleResetCyclePort IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
485 
486     if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT)
487     {
488         /* Use reset port list */
489         ListHead = &FDODeviceExtension->ResetPortListHead;
490         ResetActive = &FDODeviceExtension->ResetPortActive;
491     }
492     else
493     {
494         /* Use cycle port list */
495         ListHead = &FDODeviceExtension->CyclePortListHead;
496         ResetActive = &FDODeviceExtension->CyclePortActive;
497     }
498 
499     /* Acquire lock */
500     KeAcquireSpinLock(&FDODeviceExtension->Lock, &OldLevel);
501 
502     if (*ResetActive)
503     {
504         /* Insert into pending list */
505         InsertTailList(ListHead, &Irp->Tail.Overlay.ListEntry);
506 
507         /* Mark irp pending */
508         IoMarkIrpPending(Irp);
509         Status = STATUS_PENDING;
510 
511         /* Release lock */
512         KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
513     }
514     else
515     {
516         /* Mark reset active */
517         *ResetActive = TRUE;
518 
519         /* Release lock */
520         KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
521 
522         /* Forward request synchronized */
523         USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
524 
525         /* Reacquire lock */
526         KeAcquireSpinLock(&FDODeviceExtension->Lock, &OldLevel);
527 
528         /* Mark reset as completed */
529         *ResetActive = FALSE;
530 
531         /* Move all requests into temporary list */
532         InitializeListHead(&TempList);
533         while(!IsListEmpty(ListHead))
534         {
535             Entry = RemoveHeadList(ListHead);
536             InsertTailList(&TempList, Entry);
537         }
538 
539         /* Release lock */
540         KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
541 
542         /* Complete pending irps */
543         while(!IsListEmpty(&TempList))
544         {
545             Entry = RemoveHeadList(&TempList);
546             ListIrp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
547 
548             /* Complete request with status success */
549             ListIrp->IoStatus.Status = STATUS_SUCCESS;
550             IoCompleteRequest(ListIrp, IO_NO_INCREMENT);
551         }
552 
553         /* Status success */
554         Status = STATUS_SUCCESS;
555     }
556 
557     return Status;
558 }
559 
560 
561 
562 NTSTATUS
563 FDO_HandleInternalDeviceControl(
564     PDEVICE_OBJECT DeviceObject,
565     PIRP Irp)
566 {
567     PIO_STACK_LOCATION IoStack;
568     NTSTATUS Status;
569     PFDO_DEVICE_EXTENSION FDODeviceExtension;
570 
571     /* Get device extension */
572     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
573     ASSERT(FDODeviceExtension->Common.IsFDO);
574 
575     /* Get stack location */
576     IoStack = IoGetCurrentIrpStackLocation(Irp);
577 
578     if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT ||
579         IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_CYCLE_PORT)
580     {
581         /* Handle reset / cycle ports */
582         Status = FDO_HandleResetCyclePort(DeviceObject, Irp);
583         DPRINT("FDO_HandleResetCyclePort Status %x\n", Status);
584         if (Status != STATUS_PENDING)
585         {
586             /* Complete request */
587             Irp->IoStatus.Status = Status;
588             IoCompleteRequest(Irp, IO_NO_INCREMENT);
589         }
590         return Status;
591     }
592 
593     /* Forward and forget request */
594     IoSkipCurrentIrpStackLocation(Irp);
595     return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
596 }
597 
598 NTSTATUS
599 FDO_HandleSystemControl(
600     PDEVICE_OBJECT DeviceObject,
601     PIRP Irp)
602 {
603     PFDO_DEVICE_EXTENSION FDODeviceExtension;
604 
605     /* Get device extension */
606     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
607     ASSERT(FDODeviceExtension->Common.IsFDO);
608 
609     /* Forward and forget request */
610     IoSkipCurrentIrpStackLocation(Irp);
611     return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
612 }
613 
614 NTSTATUS
615 FDO_Dispatch(
616     PDEVICE_OBJECT DeviceObject,
617     PIRP Irp)
618 {
619     PIO_STACK_LOCATION IoStack;
620     NTSTATUS Status;
621     PFDO_DEVICE_EXTENSION FDODeviceExtension;
622 
623     /* Get device extension */
624     FDODeviceExtension = DeviceObject->DeviceExtension;
625     ASSERT(FDODeviceExtension->Common.IsFDO);
626 
627     /* Get stack location */
628     IoStack = IoGetCurrentIrpStackLocation(Irp);
629 
630     switch(IoStack->MajorFunction)
631     {
632         case IRP_MJ_PNP:
633             return FDO_HandlePnp(DeviceObject, Irp);
634         case IRP_MJ_INTERNAL_DEVICE_CONTROL:
635             return FDO_HandleInternalDeviceControl(DeviceObject, Irp);
636         case IRP_MJ_POWER:
637             PoStartNextPowerIrp(Irp);
638             IoSkipCurrentIrpStackLocation(Irp);
639             return PoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
640         case IRP_MJ_SYSTEM_CONTROL:
641             return FDO_HandleSystemControl(DeviceObject, Irp);
642         default:
643             DPRINT1("FDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
644             ASSERT(FALSE);
645             Status = Irp->IoStatus.Status;
646             IoCompleteRequest(Irp, IO_NO_INCREMENT);
647             return Status;
648     }
649 
650 }
651