1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS 4 * FILE: drivers/wdm/audio/backpln/portcls/irp.cpp 5 * PURPOSE: Port Class driver / IRP Handling 6 * PROGRAMMER: Andrew Greenwood 7 * Johannes Anderwald 8 * HISTORY: 9 * 27 Jan 07 Created 10 */ 11 12 13 #include "private.hpp" 14 15 typedef struct 16 { 17 PIRP Irp; 18 PDEVICE_OBJECT DeviceObject; 19 }QUERY_POWER_CONTEXT, *PQUERY_POWER_CONTEXT; 20 21 22 NTSTATUS 23 NTAPI 24 PortClsCreate( 25 IN PDEVICE_OBJECT DeviceObject, 26 IN PIRP Irp) 27 { 28 DPRINT("PortClsCreate called\n"); 29 30 return KsDispatchIrp(DeviceObject, Irp); 31 } 32 33 34 NTSTATUS 35 NTAPI 36 PortClsPnp( 37 IN PDEVICE_OBJECT DeviceObject, 38 IN PIRP Irp) 39 { 40 NTSTATUS Status; 41 PPCLASS_DEVICE_EXTENSION DeviceExt; 42 PIO_STACK_LOCATION IoStack; 43 POWER_STATE PowerState; 44 IResourceList* resource_list = NULL; 45 //ULONG Index; 46 //PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor, UnPartialDescriptor; 47 48 DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension; 49 IoStack = IoGetCurrentIrpStackLocation(Irp); 50 51 52 DPRINT("PortClsPnp called %u\n", IoStack->MinorFunction); 53 54 //PC_ASSERT(DeviceExt); 55 56 switch (IoStack->MinorFunction) 57 { 58 case IRP_MN_START_DEVICE: 59 DPRINT("IRP_MN_START_DEVICE\n"); 60 61 // Create the resource list 62 Status = PcNewResourceList( 63 &resource_list, 64 NULL, 65 PagedPool, 66 IoStack->Parameters.StartDevice.AllocatedResourcesTranslated, 67 IoStack->Parameters.StartDevice.AllocatedResources); 68 if (!NT_SUCCESS(Status)) 69 { 70 DPRINT("PcNewResourceList failed [0x%8x]\n", Status); 71 Irp->IoStatus.Status = Status; 72 IoCompleteRequest(Irp, IO_NO_INCREMENT); 73 return Status; 74 } 75 76 // forward irp to lower device object 77 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 78 79 if (!NT_SUCCESS(Status)) 80 { 81 // lower device object failed to start 82 resource_list->Release(); 83 // complete the request 84 IoCompleteRequest(Irp, IO_NO_INCREMENT); 85 // return result 86 return Status; 87 } 88 89 // sanity check 90 //PC_ASSERT(DeviceExt->StartDevice); 91 // Call the StartDevice routine 92 DPRINT("Calling StartDevice at 0x%8p\n", DeviceExt->StartDevice); 93 Status = DeviceExt->StartDevice(DeviceObject, Irp, resource_list); 94 if (!NT_SUCCESS(Status)) 95 { 96 DPRINT("StartDevice returned a failure code [0x%8x]\n", Status); 97 Irp->IoStatus.Status = Status; 98 IoCompleteRequest(Irp, IO_NO_INCREMENT); 99 return Status; 100 } 101 102 // Assign the resource list to our extension 103 DeviceExt->resources = resource_list; 104 105 // store device power state 106 DeviceExt->DevicePowerState = PowerDeviceD0; 107 DeviceExt->SystemPowerState = PowerSystemWorking; 108 109 // notify power manager of current state 110 PowerState = *((POWER_STATE*)&DeviceExt->DevicePowerState); 111 PoSetPowerState(DeviceObject, DevicePowerState, PowerState); 112 113 Irp->IoStatus.Status = STATUS_SUCCESS; 114 IoCompleteRequest(Irp, IO_NO_INCREMENT); 115 return Status; 116 117 case IRP_MN_REMOVE_DEVICE: 118 // Clean up 119 DPRINT("IRP_MN_REMOVE_DEVICE\n"); 120 121 // sanity check 122 PC_ASSERT(DeviceExt); 123 124 // FIXME more cleanup */ 125 if (DeviceExt->resources) 126 { 127 // free resource list */ 128 DeviceExt->resources->Release(); 129 130 // set to null 131 DeviceExt->resources = NULL; 132 } 133 134 // Forward request 135 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 136 137 return PcCompleteIrp(DeviceObject, Irp, Status); 138 139 case IRP_MN_QUERY_INTERFACE: 140 DPRINT("IRP_MN_QUERY_INTERFACE\n"); 141 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 142 return PcCompleteIrp(DeviceObject, Irp, Status); 143 case IRP_MN_QUERY_DEVICE_RELATIONS: 144 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n"); 145 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 146 return PcCompleteIrp(DeviceObject, Irp, Status); 147 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: 148 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); 149 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 150 return PcCompleteIrp(DeviceObject, Irp, Status); 151 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 152 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); 153 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 154 return PcCompleteIrp(DeviceObject, Irp, Status); 155 case IRP_MN_READ_CONFIG: 156 DPRINT("IRP_MN_READ_CONFIG\n"); 157 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 158 return PcCompleteIrp(DeviceObject, Irp, Status); 159 } 160 161 DPRINT("unhandled function %u\n", IoStack->MinorFunction); 162 Status = Irp->IoStatus.Status; 163 IoCompleteRequest(Irp, IO_NO_INCREMENT); 164 return Status; 165 } 166 167 VOID 168 CALLBACK 169 PwrCompletionFunction( 170 IN PDEVICE_OBJECT DeviceObject, 171 IN UCHAR MinorFunction, 172 IN POWER_STATE PowerState, 173 IN PVOID Context, 174 IN PIO_STATUS_BLOCK IoStatus) 175 { 176 NTSTATUS Status; 177 PQUERY_POWER_CONTEXT PwrContext = (PQUERY_POWER_CONTEXT)Context; 178 179 if (NT_SUCCESS(IoStatus->Status)) 180 { 181 // forward request to lower device object 182 Status = PcForwardIrpSynchronous(PwrContext->DeviceObject, PwrContext->Irp); 183 } 184 else 185 { 186 // failed 187 Status = IoStatus->Status; 188 } 189 190 // start next power irp 191 PoStartNextPowerIrp(PwrContext->Irp); 192 193 // complete request 194 PwrContext->Irp->IoStatus.Status = Status; 195 IoCompleteRequest(PwrContext->Irp, IO_NO_INCREMENT); 196 197 // free context 198 FreeItem(PwrContext, TAG_PORTCLASS); 199 } 200 201 202 NTSTATUS 203 NTAPI 204 PortClsPower( 205 IN PDEVICE_OBJECT DeviceObject, 206 IN PIRP Irp) 207 { 208 PIO_STACK_LOCATION IoStack; 209 PPCLASS_DEVICE_EXTENSION DeviceExtension; 210 PQUERY_POWER_CONTEXT PwrContext; 211 POWER_STATE PowerState; 212 NTSTATUS Status = STATUS_SUCCESS; 213 214 DPRINT("PortClsPower called\n"); 215 216 // get currrent stack location 217 IoStack = IoGetCurrentIrpStackLocation(Irp); 218 219 if (IoStack->MinorFunction != IRP_MN_SET_POWER && IoStack->MinorFunction != IRP_MN_QUERY_POWER) 220 { 221 // just forward the request 222 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 223 224 // start next power irp 225 PoStartNextPowerIrp(Irp); 226 227 // complete request 228 Irp->IoStatus.Status = Status; 229 IoCompleteRequest(Irp, IO_NO_INCREMENT); 230 231 // done 232 return Status; 233 } 234 235 236 // get device extension 237 DeviceExtension = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension; 238 239 // get current request type 240 if (IoStack->Parameters.Power.Type == DevicePowerState) 241 { 242 // request for device power state 243 if (DeviceExtension->DevicePowerState == IoStack->Parameters.Power.State.DeviceState) 244 { 245 // nothing has changed 246 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) 247 { 248 // only forward query requests 249 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 250 } 251 252 // start next power irp 253 PoStartNextPowerIrp(Irp); 254 255 // complete request 256 Irp->IoStatus.Status = Status; 257 IoCompleteRequest(Irp, IO_NO_INCREMENT); 258 259 // done 260 return Status; 261 } 262 263 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) 264 { 265 // check if there is a registered adapter power management 266 if (DeviceExtension->AdapterPowerManagement) 267 { 268 // it is query if the change can be changed 269 PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState); 270 Status = DeviceExtension->AdapterPowerManagement->QueryPowerChangeState(PowerState); 271 272 // sanity check 273 PC_ASSERT(Status == STATUS_SUCCESS); 274 } 275 276 // only forward query requests 277 PcForwardIrpSynchronous(DeviceObject, Irp); 278 279 // start next power irp 280 PoStartNextPowerIrp(Irp); 281 282 // complete request 283 Irp->IoStatus.Status = Status; 284 IoCompleteRequest(Irp, IO_NO_INCREMENT); 285 286 // done 287 return Status; 288 } 289 else 290 { 291 // set power state 292 PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState); 293 PoSetPowerState(DeviceObject, DevicePowerState, PowerState); 294 295 // check if there is a registered adapter power management 296 if (DeviceExtension->AdapterPowerManagement) 297 { 298 // notify of a power change state 299 DeviceExtension->AdapterPowerManagement->PowerChangeState(PowerState); 300 } 301 302 // FIXME call all registered IPowerNotify interfaces via ISubdevice interface 303 304 // store new power state 305 DeviceExtension->DevicePowerState = IoStack->Parameters.Power.State.DeviceState; 306 307 // complete request 308 Irp->IoStatus.Status = Status; 309 IoCompleteRequest(Irp, IO_NO_INCREMENT); 310 311 // done 312 return Status; 313 } 314 } 315 else 316 { 317 // sanity check 318 PC_ASSERT(IoStack->Parameters.Power.Type == SystemPowerState); 319 320 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) 321 { 322 // mark irp as pending 323 IoMarkIrpPending(Irp); 324 325 // allocate power completion context 326 PwrContext = (PQUERY_POWER_CONTEXT)AllocateItem(NonPagedPool, sizeof(QUERY_POWER_CONTEXT), TAG_PORTCLASS); 327 328 if (!PwrContext) 329 { 330 // no memory 331 PoStartNextPowerIrp(Irp); 332 333 // complete and forget 334 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 335 IoCompleteRequest(Irp, IO_NO_INCREMENT); 336 337 // done 338 return Status; 339 } 340 341 // setup power context 342 PwrContext->Irp = Irp; 343 PwrContext->DeviceObject = DeviceObject; 344 345 // pass the irp down 346 PowerState = *((POWER_STATE*)IoStack->Parameters.Power.State.SystemState); 347 Status = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IoStack->MinorFunction, PowerState, PwrCompletionFunction, (PVOID)PwrContext, NULL); 348 349 // check for success 350 if (!NT_SUCCESS(Status)) 351 { 352 // failed 353 Irp->IoStatus.Status = Status; 354 IoCompleteRequest(Irp, IO_NO_INCREMENT); 355 356 // done 357 return Status; 358 } 359 360 // done 361 return STATUS_PENDING; 362 } 363 else 364 { 365 // set power request 366 DeviceExtension->SystemPowerState = IoStack->Parameters.Power.State.SystemState; 367 368 // only forward query requests 369 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 370 371 // start next power irp 372 PoStartNextPowerIrp(Irp); 373 374 // complete request 375 Irp->IoStatus.Status = Status; 376 IoCompleteRequest(Irp, IO_NO_INCREMENT); 377 378 // done 379 return Status; 380 } 381 } 382 } 383 384 NTSTATUS 385 NTAPI 386 PortClsSysControl( 387 IN PDEVICE_OBJECT DeviceObject, 388 IN PIRP Irp) 389 { 390 DPRINT("PortClsSysControl called\n"); 391 392 // TODO 393 394 Irp->IoStatus.Status = STATUS_SUCCESS; 395 Irp->IoStatus.Information = 0; 396 IoCompleteRequest(Irp, IO_NO_INCREMENT); 397 398 return STATUS_SUCCESS; 399 } 400 401 NTSTATUS 402 NTAPI 403 PortClsShutdown( 404 IN PDEVICE_OBJECT DeviceObject, 405 IN PIRP Irp) 406 { 407 PPCLASS_DEVICE_EXTENSION DeviceExtension; 408 DPRINT("PortClsShutdown called\n"); 409 410 // get device extension 411 DeviceExtension = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 412 413 if (DeviceExtension->AdapterPowerManagement) 414 { 415 // release adapter power management 416 DPRINT("Power %u\n", DeviceExtension->AdapterPowerManagement->Release()); 417 } 418 419 Irp->IoStatus.Status = STATUS_SUCCESS; 420 Irp->IoStatus.Information = 0; 421 IoCompleteRequest(Irp, IO_NO_INCREMENT); 422 423 return STATUS_SUCCESS; 424 } 425 426 NTSTATUS 427 NTAPI 428 PcDispatchIrp( 429 IN PDEVICE_OBJECT DeviceObject, 430 IN PIRP Irp) 431 { 432 PIO_STACK_LOCATION IoStack; 433 434 IoStack = IoGetCurrentIrpStackLocation(Irp); 435 436 DPRINT("PcDispatchIrp called - handling IRP in PortCls MajorFunction %x MinorFunction %x\n", IoStack->MajorFunction, IoStack->MinorFunction); 437 438 switch ( IoStack->MajorFunction ) 439 { 440 // PortCls 441 case IRP_MJ_CREATE : 442 return PortClsCreate(DeviceObject, Irp); 443 444 case IRP_MJ_PNP : 445 return PortClsPnp(DeviceObject, Irp); 446 447 case IRP_MJ_POWER : 448 return PortClsPower(DeviceObject, Irp); 449 450 case IRP_MJ_DEVICE_CONTROL: 451 return KsDispatchIrp(DeviceObject, Irp); 452 453 case IRP_MJ_CLOSE: 454 return KsDispatchIrp(DeviceObject, Irp); 455 456 case IRP_MJ_SYSTEM_CONTROL : 457 return PortClsSysControl(DeviceObject, Irp); 458 459 case IRP_MJ_SHUTDOWN: 460 return PortClsShutdown(DeviceObject, Irp); 461 462 default: 463 DPRINT("Unhandled function %x\n", IoStack->MajorFunction); 464 break; 465 }; 466 467 // If we reach here, we just complete the IRP 468 Irp->IoStatus.Status = STATUS_SUCCESS; 469 Irp->IoStatus.Information = 0; 470 IoCompleteRequest(Irp, IO_NO_INCREMENT); 471 472 return STATUS_SUCCESS; 473 } 474 475 476 NTSTATUS 477 NTAPI 478 PcCompleteIrp( 479 IN PDEVICE_OBJECT DeviceObject, 480 IN PIRP Irp, 481 IN NTSTATUS Status) 482 { 483 #if 0 484 PC_ASSERT(DeviceObject); 485 PC_ASSERT(Irp); 486 PC_ASSERT(Status != STATUS_PENDING); 487 #endif 488 489 Irp->IoStatus.Status = Status; 490 IoCompleteRequest(Irp, IO_NO_INCREMENT); 491 492 return Status; 493 } 494 495 NTSTATUS 496 NTAPI 497 CompletionRoutine( 498 IN PDEVICE_OBJECT DeviceObject, 499 IN PIRP Irp, 500 IN PVOID Context) 501 { 502 if (Irp->PendingReturned == TRUE) 503 { 504 KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE); 505 } 506 return STATUS_MORE_PROCESSING_REQUIRED; 507 } 508 509 #undef IoSetCompletionRoutine 510 #define IoSetCompletionRoutine(_Irp, \ 511 _CompletionRoutine, \ 512 _Context, \ 513 _InvokeOnSuccess, \ 514 _InvokeOnError, \ 515 _InvokeOnCancel) \ 516 { \ 517 PIO_STACK_LOCATION _IrpSp; \ 518 _IrpSp = IoGetNextIrpStackLocation(_Irp); \ 519 _IrpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)(_CompletionRoutine); \ 520 _IrpSp->Context = (_Context); \ 521 _IrpSp->Control = 0; \ 522 if (_InvokeOnSuccess) _IrpSp->Control = SL_INVOKE_ON_SUCCESS; \ 523 if (_InvokeOnError) _IrpSp->Control |= SL_INVOKE_ON_ERROR; \ 524 if (_InvokeOnCancel) _IrpSp->Control |= SL_INVOKE_ON_CANCEL; \ 525 } 526 527 528 529 NTSTATUS 530 NTAPI 531 PcForwardIrpSynchronous( 532 IN PDEVICE_OBJECT DeviceObject, 533 IN PIRP Irp) 534 { 535 KEVENT Event; 536 PPCLASS_DEVICE_EXTENSION DeviceExt; 537 NTSTATUS Status; 538 539 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 540 541 DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 542 543 // initialize the notification event 544 KeInitializeEvent(&Event, NotificationEvent, FALSE); 545 546 IoCopyCurrentIrpStackLocationToNext(Irp); 547 548 IoSetCompletionRoutine(Irp, CompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE); 549 550 // now call the driver 551 Status = IoCallDriver(DeviceExt->PrevDeviceObject, Irp); 552 // did the request complete yet 553 if (Status == STATUS_PENDING) 554 { 555 // not yet, lets wait a bit 556 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 557 Status = Irp->IoStatus.Status; 558 } 559 return Status; 560 } 561