xref: /reactos/drivers/usb/usbccgp/fdo.c (revision 53221834)
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 }
658