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