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 163 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 164 IoCompleteRequest(Irp, IO_NO_INCREMENT); 165 return STATUS_UNSUCCESSFUL; 166 } 167 168 VOID 169 CALLBACK 170 PwrCompletionFunction( 171 IN PDEVICE_OBJECT DeviceObject, 172 IN UCHAR MinorFunction, 173 IN POWER_STATE PowerState, 174 IN PVOID Context, 175 IN PIO_STATUS_BLOCK IoStatus) 176 { 177 NTSTATUS Status; 178 PQUERY_POWER_CONTEXT PwrContext = (PQUERY_POWER_CONTEXT)Context; 179 180 if (NT_SUCCESS(IoStatus->Status)) 181 { 182 // forward request to lower device object 183 Status = PcForwardIrpSynchronous(PwrContext->DeviceObject, PwrContext->Irp); 184 } 185 else 186 { 187 // failed 188 Status = IoStatus->Status; 189 } 190 191 // start next power irp 192 PoStartNextPowerIrp(PwrContext->Irp); 193 194 // complete request 195 PwrContext->Irp->IoStatus.Status = Status; 196 IoCompleteRequest(PwrContext->Irp, IO_NO_INCREMENT); 197 198 // free context 199 FreeItem(PwrContext, TAG_PORTCLASS); 200 } 201 202 203 NTSTATUS 204 NTAPI 205 PortClsPower( 206 IN PDEVICE_OBJECT DeviceObject, 207 IN PIRP Irp) 208 { 209 PIO_STACK_LOCATION IoStack; 210 PPCLASS_DEVICE_EXTENSION DeviceExtension; 211 PQUERY_POWER_CONTEXT PwrContext; 212 POWER_STATE PowerState; 213 NTSTATUS Status = STATUS_SUCCESS; 214 215 DPRINT("PortClsPower called\n"); 216 217 // get currrent stack location 218 IoStack = IoGetCurrentIrpStackLocation(Irp); 219 220 if (IoStack->MinorFunction != IRP_MN_SET_POWER && IoStack->MinorFunction != IRP_MN_QUERY_POWER) 221 { 222 // just forward the request 223 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 224 225 // start next power irp 226 PoStartNextPowerIrp(Irp); 227 228 // complete request 229 Irp->IoStatus.Status = Status; 230 IoCompleteRequest(Irp, IO_NO_INCREMENT); 231 232 // done 233 return Status; 234 } 235 236 237 // get device extension 238 DeviceExtension = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension; 239 240 // get current request type 241 if (IoStack->Parameters.Power.Type == DevicePowerState) 242 { 243 // request for device power state 244 if (DeviceExtension->DevicePowerState == IoStack->Parameters.Power.State.DeviceState) 245 { 246 // nothing has changed 247 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) 248 { 249 // only forward query requests 250 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 251 } 252 253 // start next power irp 254 PoStartNextPowerIrp(Irp); 255 256 // complete request 257 Irp->IoStatus.Status = Status; 258 IoCompleteRequest(Irp, IO_NO_INCREMENT); 259 260 // done 261 return Status; 262 } 263 264 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) 265 { 266 // check if there is a registered adapter power management 267 if (DeviceExtension->AdapterPowerManagement) 268 { 269 // it is query if the change can be changed 270 PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState); 271 Status = DeviceExtension->AdapterPowerManagement->QueryPowerChangeState(PowerState); 272 273 // sanity check 274 PC_ASSERT(Status == STATUS_SUCCESS); 275 } 276 277 // only forward query requests 278 PcForwardIrpSynchronous(DeviceObject, Irp); 279 280 // start next power irp 281 PoStartNextPowerIrp(Irp); 282 283 // complete request 284 Irp->IoStatus.Status = Status; 285 IoCompleteRequest(Irp, IO_NO_INCREMENT); 286 287 // done 288 return Status; 289 } 290 else 291 { 292 // set power state 293 PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState); 294 PoSetPowerState(DeviceObject, DevicePowerState, PowerState); 295 296 // check if there is a registered adapter power management 297 if (DeviceExtension->AdapterPowerManagement) 298 { 299 // notify of a power change state 300 DeviceExtension->AdapterPowerManagement->PowerChangeState(PowerState); 301 } 302 303 // FIXME call all registered IPowerNotify interfaces via ISubdevice interface 304 305 // store new power state 306 DeviceExtension->DevicePowerState = IoStack->Parameters.Power.State.DeviceState; 307 308 // complete request 309 Irp->IoStatus.Status = Status; 310 IoCompleteRequest(Irp, IO_NO_INCREMENT); 311 312 // done 313 return Status; 314 } 315 } 316 else 317 { 318 // sanity check 319 PC_ASSERT(IoStack->Parameters.Power.Type == SystemPowerState); 320 321 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) 322 { 323 // mark irp as pending 324 IoMarkIrpPending(Irp); 325 326 // allocate power completion context 327 PwrContext = (PQUERY_POWER_CONTEXT)AllocateItem(NonPagedPool, sizeof(QUERY_POWER_CONTEXT), TAG_PORTCLASS); 328 329 if (!PwrContext) 330 { 331 // no memory 332 PoStartNextPowerIrp(Irp); 333 334 // complete and forget 335 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 336 IoCompleteRequest(Irp, IO_NO_INCREMENT); 337 338 // done 339 return Status; 340 } 341 342 // setup power context 343 PwrContext->Irp = Irp; 344 PwrContext->DeviceObject = DeviceObject; 345 346 // pass the irp down 347 PowerState = *((POWER_STATE*)IoStack->Parameters.Power.State.SystemState); 348 Status = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IoStack->MinorFunction, PowerState, PwrCompletionFunction, (PVOID)PwrContext, NULL); 349 350 // check for success 351 if (!NT_SUCCESS(Status)) 352 { 353 // failed 354 Irp->IoStatus.Status = Status; 355 IoCompleteRequest(Irp, IO_NO_INCREMENT); 356 357 // done 358 return Status; 359 } 360 361 // done 362 return STATUS_PENDING; 363 } 364 else 365 { 366 // set power request 367 DeviceExtension->SystemPowerState = IoStack->Parameters.Power.State.SystemState; 368 369 // only forward query requests 370 Status = PcForwardIrpSynchronous(DeviceObject, Irp); 371 372 // start next power irp 373 PoStartNextPowerIrp(Irp); 374 375 // complete request 376 Irp->IoStatus.Status = Status; 377 IoCompleteRequest(Irp, IO_NO_INCREMENT); 378 379 // done 380 return Status; 381 } 382 } 383 } 384 385 NTSTATUS 386 NTAPI 387 PortClsSysControl( 388 IN PDEVICE_OBJECT DeviceObject, 389 IN PIRP Irp) 390 { 391 DPRINT("PortClsSysControl called\n"); 392 393 // TODO 394 395 Irp->IoStatus.Status = STATUS_SUCCESS; 396 Irp->IoStatus.Information = 0; 397 IoCompleteRequest(Irp, IO_NO_INCREMENT); 398 399 return STATUS_SUCCESS; 400 } 401 402 NTSTATUS 403 NTAPI 404 PortClsShutdown( 405 IN PDEVICE_OBJECT DeviceObject, 406 IN PIRP Irp) 407 { 408 PPCLASS_DEVICE_EXTENSION DeviceExtension; 409 DPRINT("PortClsShutdown called\n"); 410 411 // get device extension 412 DeviceExtension = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 413 414 if (DeviceExtension->AdapterPowerManagement) 415 { 416 // release adapter power management 417 DPRINT("Power %u\n", DeviceExtension->AdapterPowerManagement->Release()); 418 } 419 420 Irp->IoStatus.Status = STATUS_SUCCESS; 421 Irp->IoStatus.Information = 0; 422 IoCompleteRequest(Irp, IO_NO_INCREMENT); 423 424 return STATUS_SUCCESS; 425 } 426 427 NTSTATUS 428 NTAPI 429 PcDispatchIrp( 430 IN PDEVICE_OBJECT DeviceObject, 431 IN PIRP Irp) 432 { 433 PIO_STACK_LOCATION IoStack; 434 435 IoStack = IoGetCurrentIrpStackLocation(Irp); 436 437 DPRINT("PcDispatchIrp called - handling IRP in PortCls MajorFunction %x MinorFunction %x\n", IoStack->MajorFunction, IoStack->MinorFunction); 438 439 switch ( IoStack->MajorFunction ) 440 { 441 // PortCls 442 case IRP_MJ_CREATE : 443 return PortClsCreate(DeviceObject, Irp); 444 445 case IRP_MJ_PNP : 446 return PortClsPnp(DeviceObject, Irp); 447 448 case IRP_MJ_POWER : 449 return PortClsPower(DeviceObject, Irp); 450 451 case IRP_MJ_DEVICE_CONTROL: 452 return KsDispatchIrp(DeviceObject, Irp); 453 454 case IRP_MJ_CLOSE: 455 return KsDispatchIrp(DeviceObject, Irp); 456 457 case IRP_MJ_SYSTEM_CONTROL : 458 return PortClsSysControl(DeviceObject, Irp); 459 460 case IRP_MJ_SHUTDOWN: 461 return PortClsShutdown(DeviceObject, Irp); 462 463 default: 464 DPRINT("Unhandled function %x\n", IoStack->MajorFunction); 465 break; 466 }; 467 468 // If we reach here, we just complete the IRP 469 Irp->IoStatus.Status = STATUS_SUCCESS; 470 Irp->IoStatus.Information = 0; 471 IoCompleteRequest(Irp, IO_NO_INCREMENT); 472 473 return STATUS_SUCCESS; 474 } 475 476 477 NTSTATUS 478 NTAPI 479 PcCompleteIrp( 480 IN PDEVICE_OBJECT DeviceObject, 481 IN PIRP Irp, 482 IN NTSTATUS Status) 483 { 484 #if 0 485 PC_ASSERT(DeviceObject); 486 PC_ASSERT(Irp); 487 PC_ASSERT(Status != STATUS_PENDING); 488 #endif 489 490 Irp->IoStatus.Status = Status; 491 IoCompleteRequest(Irp, IO_NO_INCREMENT); 492 493 return Status; 494 } 495 496 NTSTATUS 497 NTAPI 498 CompletionRoutine( 499 IN PDEVICE_OBJECT DeviceObject, 500 IN PIRP Irp, 501 IN PVOID Context) 502 { 503 if (Irp->PendingReturned == TRUE) 504 { 505 KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE); 506 } 507 return STATUS_MORE_PROCESSING_REQUIRED; 508 } 509 510 #undef IoSetCompletionRoutine 511 #define IoSetCompletionRoutine(_Irp, \ 512 _CompletionRoutine, \ 513 _Context, \ 514 _InvokeOnSuccess, \ 515 _InvokeOnError, \ 516 _InvokeOnCancel) \ 517 { \ 518 PIO_STACK_LOCATION _IrpSp; \ 519 _IrpSp = IoGetNextIrpStackLocation(_Irp); \ 520 _IrpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)(_CompletionRoutine); \ 521 _IrpSp->Context = (_Context); \ 522 _IrpSp->Control = 0; \ 523 if (_InvokeOnSuccess) _IrpSp->Control = SL_INVOKE_ON_SUCCESS; \ 524 if (_InvokeOnError) _IrpSp->Control |= SL_INVOKE_ON_ERROR; \ 525 if (_InvokeOnCancel) _IrpSp->Control |= SL_INVOKE_ON_CANCEL; \ 526 } 527 528 529 530 NTSTATUS 531 NTAPI 532 PcForwardIrpSynchronous( 533 IN PDEVICE_OBJECT DeviceObject, 534 IN PIRP Irp) 535 { 536 KEVENT Event; 537 PPCLASS_DEVICE_EXTENSION DeviceExt; 538 NTSTATUS Status; 539 540 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 541 542 DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 543 544 // initialize the notification event 545 KeInitializeEvent(&Event, NotificationEvent, FALSE); 546 547 IoCopyCurrentIrpStackLocationToNext(Irp); 548 549 IoSetCompletionRoutine(Irp, CompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE); 550 551 // now call the driver 552 Status = IoCallDriver(DeviceExt->PrevDeviceObject, Irp); 553 // did the request complete yet 554 if (Status == STATUS_PENDING) 555 { 556 // not yet, lets wait a bit 557 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 558 Status = Irp->IoStatus.Status; 559 } 560 return Status; 561 } 562