Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

996 lines
28 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. dispatch.c
  5. Abstract:
  6. IRP dispatching routines for the common AGPLIB library
  7. Author:
  8. John Vert (jvert) 10/25/1997
  9. Revision History:
  10. Elliot Shmukler (elliots) 3/24/1999 - Added support for "favored" memory
  11. ranges for AGP physical memory allocation,
  12. fixed some bugs.
  13. --*/
  14. #include "agplib.h"
  15. //
  16. // Two flavors of each dispatch routine, one for the target (AGP bridge) filter and
  17. // one for the master (video card) filter.
  18. //
  19. NTSTATUS
  20. AgpTargetDispatchPnp(
  21. IN PDEVICE_OBJECT DeviceObject,
  22. IN OUT PIRP Irp,
  23. IN PTARGET_EXTENSION Extension
  24. );
  25. NTSTATUS
  26. AgpMasterDispatchPnp(
  27. IN PDEVICE_OBJECT DeviceObject,
  28. IN OUT PIRP Irp,
  29. IN PMASTER_EXTENSION Extension
  30. );
  31. NTSTATUS
  32. AgpTargetDispatchPower(
  33. IN PDEVICE_OBJECT DeviceObject,
  34. IN OUT PIRP Irp,
  35. IN PTARGET_EXTENSION Extension
  36. );
  37. NTSTATUS
  38. AgpMasterDispatchPower(
  39. IN PDEVICE_OBJECT DeviceObject,
  40. IN OUT PIRP Irp,
  41. IN PMASTER_EXTENSION Extension
  42. );
  43. NTSTATUS
  44. AgpCancelMasterRemove(
  45. IN PDEVICE_OBJECT DeviceObject,
  46. IN PIRP Irp,
  47. IN PMASTER_EXTENSION Extension
  48. );
  49. NTSTATUS
  50. AgpMasterPowerUpCompletion(
  51. IN PDEVICE_OBJECT DeviceObject,
  52. IN PIRP Irp,
  53. IN PMASTER_EXTENSION Extension
  54. );
  55. NTSTATUS
  56. AgpTargetPowerUpCompletion(
  57. IN PDEVICE_OBJECT DeviceObject,
  58. IN PIRP Irp,
  59. IN PTARGET_EXTENSION Extension
  60. );
  61. #ifdef ALLOC_PRAGMA
  62. #pragma alloc_text(PAGE, AgpDispatchPnp)
  63. #pragma alloc_text(PAGE, AgpDispatchDeviceControl)
  64. #pragma alloc_text(PAGE, AgpDispatchWmi)
  65. #pragma alloc_text(PAGE, AgpTargetDispatchPnp)
  66. #pragma alloc_text(PAGE, AgpMasterDispatchPnp)
  67. #pragma alloc_text(PAGE, AgpCancelMasterRemove)
  68. #endif
  69. NTSTATUS
  70. AgpDispatchPnp(
  71. IN PDEVICE_OBJECT DeviceObject,
  72. IN OUT PIRP Irp
  73. )
  74. /*++
  75. Routine Description:
  76. Main dispatch routine for PNP irps sent to the AGP bus filter driver
  77. Arguments:
  78. DeviceObject - Supplies the AGP device object
  79. Irp - Supplies the PNP Irp.
  80. Return Value:
  81. NTSTATUS
  82. --*/
  83. {
  84. PCOMMON_EXTENSION Extension = DeviceObject->DeviceExtension;
  85. PAGED_CODE();
  86. //
  87. // We're deleted, fail the irp
  88. //
  89. if (Extension->Deleted == TRUE) {
  90. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  91. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  92. return STATUS_DELETE_PENDING;
  93. }
  94. ASSERT(Extension->AttachedDevice != NULL);
  95. if (Extension->Type == AgpTargetFilter) {
  96. return(AgpTargetDispatchPnp(DeviceObject,
  97. Irp,
  98. DeviceObject->DeviceExtension));
  99. } else {
  100. ASSERT(Extension->Type == AgpMasterFilter);
  101. return(AgpMasterDispatchPnp(DeviceObject,
  102. Irp,
  103. DeviceObject->DeviceExtension));
  104. }
  105. }
  106. NTSTATUS
  107. AgpDispatchPower(
  108. IN PDEVICE_OBJECT DeviceObject,
  109. IN OUT PIRP Irp
  110. )
  111. /*++
  112. Routine Description:
  113. Main dispatch routine for power irps sent to the AGP bus filter driver
  114. Arguments:
  115. DeviceObject - Supplies the AGP device object
  116. Irp - Supplies the power Irp.
  117. Return Value:
  118. NTSTATUS
  119. --*/
  120. {
  121. PCOMMON_EXTENSION Extension = DeviceObject->DeviceExtension;
  122. //
  123. // We're deleted, fail the irp
  124. //
  125. if (Extension->Deleted == TRUE) {
  126. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  127. PoStartNextPowerIrp(Irp);
  128. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  129. return STATUS_DELETE_PENDING;
  130. }
  131. ASSERT(Extension->AttachedDevice != NULL);
  132. if (Extension->Type == AgpTargetFilter) {
  133. return(AgpTargetDispatchPower(DeviceObject,
  134. Irp,
  135. DeviceObject->DeviceExtension));
  136. } else {
  137. ASSERT(Extension->Type == AgpMasterFilter);
  138. return(AgpMasterDispatchPower(DeviceObject,
  139. Irp,
  140. DeviceObject->DeviceExtension));
  141. }
  142. }
  143. NTSTATUS
  144. AgpTargetDispatchPnp(
  145. IN PDEVICE_OBJECT DeviceObject,
  146. IN OUT PIRP Irp,
  147. IN PTARGET_EXTENSION Extension
  148. )
  149. /*++
  150. Routine Description:
  151. Dispatch routine for PNP irps sent to the AGP bus filter driver
  152. attached to the target (AGP bridge) PDO.
  153. Arguments:
  154. DeviceObject - Supplies the AGP target device object
  155. Irp - Supplies the PNP Irp.
  156. Extension - Supplies the AGP target device extension
  157. Return Value:
  158. NTSTATUS
  159. --*/
  160. {
  161. NTSTATUS Status = STATUS_NOT_SUPPORTED;
  162. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  163. PAGED_CODE();
  164. // AGPLOG(AGP_IRPTRACE,
  165. // ("AgpTargetDispatchPnp: IRP 0x%x\n", irpStack->MinorFunction));
  166. switch (irpStack->MinorFunction) {
  167. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
  168. AGPLOG(AGP_NOISE,
  169. ("AgpTargetDispatchPnp: IRP_MN_FILTER_RESOURCE_REQUIREMENTS to %08lx\n",
  170. DeviceObject));
  171. Status = AgpFilterResourceRequirements(DeviceObject, Irp, Extension);
  172. break;
  173. case IRP_MN_QUERY_RESOURCES:
  174. AGPLOG(AGP_NOISE,
  175. ("AgpTargetDispatchPnp: IRP_MN_QUERY_RESOURCES to %08lx\n",
  176. DeviceObject));
  177. //
  178. // We must handle this IRP on the way back so we can add the AGP
  179. // resources on to it. Set a completion routine.
  180. //
  181. IoCopyCurrentIrpStackLocationToNext(Irp);
  182. IoSetCompletionRoutine(Irp,
  183. AgpQueryResources,
  184. Extension,
  185. TRUE,
  186. FALSE,
  187. FALSE);
  188. Status = IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
  189. return Status ;
  190. case IRP_MN_QUERY_DEVICE_RELATIONS:
  191. if (irpStack->Parameters.QueryDeviceRelations.Type == BusRelations) {
  192. KEVENT event;
  193. KeInitializeEvent(&event, NotificationEvent, FALSE);
  194. //
  195. // We must handle this IRP on the way back so that we can attach
  196. // a filter to any child PDOs of our PCI-PCI bridge.
  197. //
  198. IoCopyCurrentIrpStackLocationToNext(Irp);
  199. IoSetCompletionRoutine(Irp,
  200. AgpSetEventCompletion,
  201. &event,
  202. TRUE,
  203. TRUE,
  204. TRUE);
  205. Status = IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
  206. //
  207. // If we did things asynchronously then wait on our event
  208. //
  209. if (Status == STATUS_PENDING) {
  210. //
  211. // We do a KernelMode wait so that our stack where the
  212. // event is doesn't get paged out!
  213. //
  214. KeWaitForSingleObject(&event,
  215. Executive,
  216. KernelMode,
  217. FALSE,
  218. NULL);
  219. Status = Irp->IoStatus.Status;
  220. }
  221. if (NT_SUCCESS(Status)) {
  222. Status = AgpAttachDeviceRelations(DeviceObject,
  223. Irp,
  224. Extension);
  225. Irp->IoStatus.Status = Status;
  226. }
  227. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  228. return Status;
  229. } else {
  230. break;
  231. }
  232. case IRP_MN_START_DEVICE:
  233. //
  234. // We need to hook this in order to filter out any AGP
  235. // resources that have been added.
  236. //
  237. return(AgpStartTarget(Irp, Extension));
  238. case IRP_MN_QUERY_REMOVE_DEVICE:
  239. case IRP_MN_QUERY_STOP_DEVICE:
  240. case IRP_MN_CANCEL_REMOVE_DEVICE:
  241. //
  242. // We can always succeed this.
  243. //
  244. Status = STATUS_SUCCESS;
  245. break;
  246. case IRP_MN_REMOVE_DEVICE:
  247. AgpDisableAperture(GET_AGP_CONTEXT(Extension));
  248. //
  249. // Pass the irp down
  250. //
  251. IoSkipCurrentIrpStackLocation(Irp);
  252. Status = IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
  253. //
  254. // Clean up and delete ourselves
  255. //
  256. Extension->CommonExtension.Deleted = TRUE;
  257. IoDetachDevice(Extension->CommonExtension.AttachedDevice);
  258. Extension->CommonExtension.AttachedDevice = NULL;
  259. RELEASE_BUS_INTERFACE(Extension);
  260. if (Extension->FavoredMemory.Ranges) {
  261. ExFreePool(Extension->FavoredMemory.Ranges);
  262. }
  263. if (Extension->Resources) {
  264. ExFreePool(Extension->Resources);
  265. }
  266. if (Extension->ResourcesTranslated) {
  267. ExFreePool(Extension->ResourcesTranslated);
  268. }
  269. ExFreePool(Extension->Lock);;
  270. IoDeleteDevice(DeviceObject);
  271. return(Status);
  272. case IRP_MN_STOP_DEVICE:
  273. AgpDisableAperture(GET_AGP_CONTEXT(Extension));
  274. Status = STATUS_SUCCESS;
  275. break; // forward irp down the stack
  276. }
  277. ASSERT(Status != STATUS_PENDING);
  278. if (Status != STATUS_NOT_SUPPORTED) {
  279. Irp->IoStatus.Status = Status;
  280. }
  281. if (NT_SUCCESS(Status) || (Status == STATUS_NOT_SUPPORTED)) {
  282. //
  283. // Forward IRP to PCI driver
  284. //
  285. IoSkipCurrentIrpStackLocation(Irp);
  286. return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
  287. } else {
  288. Status = Irp->IoStatus.Status;
  289. IoCompleteRequest(Irp, IO_NO_INCREMENT) ;
  290. return Status ;
  291. }
  292. }
  293. NTSTATUS
  294. AgpDispatchDeviceControl(
  295. IN PDEVICE_OBJECT DeviceObject,
  296. IN OUT PIRP Irp
  297. )
  298. /*++
  299. Routine Description:
  300. Main dispatch routine for device control irps sent to the AGP bus filter driver
  301. AGP currently does not support any device controls. So we just pass everything
  302. down and hope the PDO knows what to do with it.
  303. Arguments:
  304. DeviceObject - Supplies the AGP device object
  305. Irp - Supplies the power Irp.
  306. Return Value:
  307. NTSTATUS
  308. --*/
  309. {
  310. PCOMMON_EXTENSION Extension = DeviceObject->DeviceExtension;
  311. PAGED_CODE();
  312. //
  313. // We're deleted, fail the irp
  314. //
  315. if (Extension->Deleted == TRUE) {
  316. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  317. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  318. return STATUS_DELETE_PENDING;
  319. }
  320. ASSERT(Extension->AttachedDevice != NULL);
  321. IoSkipCurrentIrpStackLocation(Irp);
  322. return(IoCallDriver(Extension->AttachedDevice, Irp));
  323. }
  324. NTSTATUS
  325. AgpDispatchWmi(
  326. IN PDEVICE_OBJECT DeviceObject,
  327. IN OUT PIRP Irp
  328. )
  329. /*++
  330. Routine Description:
  331. Main dispatch routine for system control irps sent to the AGP bus filter
  332. driver.
  333. AGP currently does not support any WMI IRPs, so we just pass everything
  334. down and hope the PDO knows what to do with it.
  335. Arguments:
  336. DeviceObject - Supplies the AGP device object
  337. Irp - Supplies the power Irp.
  338. Return Value:
  339. NTSTATUS
  340. --*/
  341. {
  342. PCOMMON_EXTENSION Extension = DeviceObject->DeviceExtension;
  343. PAGED_CODE();
  344. //
  345. // We're deleted, fail the irp
  346. //
  347. if (Extension->Deleted == TRUE) {
  348. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  349. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  350. return STATUS_DELETE_PENDING;
  351. }
  352. ASSERT(Extension->AttachedDevice != NULL);
  353. IoSkipCurrentIrpStackLocation(Irp);
  354. return(IoCallDriver(Extension->AttachedDevice, Irp));
  355. }
  356. NTSTATUS
  357. AgpTargetDispatchPower(
  358. IN PDEVICE_OBJECT DeviceObject,
  359. IN OUT PIRP Irp,
  360. IN PTARGET_EXTENSION Extension
  361. )
  362. {
  363. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  364. AGPLOG(AGP_IRPTRACE,
  365. ("AgpTargetDispatchPower: IRP 0x%x\n", irpStack->MinorFunction));
  366. //
  367. // All we keep track of are Dx states. PCI is responsible for mapping
  368. // S-states into D states.
  369. //
  370. if ((irpStack->MinorFunction == IRP_MN_SET_POWER) &&
  371. (irpStack->Parameters.Power.Type == DevicePowerState) &&
  372. (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0)) {
  373. NTSTATUS Status;
  374. //
  375. // We need to reinitialize the target when this IRP has been completed
  376. // by the lower drivers. Set up our completion handler to finish this.
  377. //
  378. IoCopyCurrentIrpStackLocationToNext(Irp);
  379. IoSetCompletionRoutine(Irp,
  380. AgpTargetPowerUpCompletion,
  381. Extension,
  382. TRUE,
  383. FALSE,
  384. FALSE);
  385. IoMarkIrpPending(Irp);
  386. PoStartNextPowerIrp(Irp);
  387. Status = PoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
  388. return STATUS_PENDING;
  389. }
  390. //
  391. // Just forward to target device
  392. //
  393. PoStartNextPowerIrp(Irp);
  394. IoSkipCurrentIrpStackLocation(Irp);
  395. return(PoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
  396. }
  397. NTSTATUS
  398. AgpMasterDispatchPnp(
  399. IN PDEVICE_OBJECT DeviceObject,
  400. IN OUT PIRP Irp,
  401. IN PMASTER_EXTENSION Extension
  402. )
  403. /*++
  404. Routine Description:
  405. Dispatch routine for PNP irps sent to the AGP bus filter driver
  406. attached to the device PDOs.
  407. Arguments:
  408. DeviceObject - Supplies the AGP device object
  409. Irp - Supplies the PNP Irp.
  410. Extension - Supplies the AGP bridge device extension
  411. Return Value:
  412. NTSTATUS
  413. --*/
  414. {
  415. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  416. PAGP_BUS_INTERFACE_STANDARD Interface;
  417. NTSTATUS Status;
  418. PAGED_CODE();
  419. AGPLOG(AGP_IRPTRACE,
  420. ("AgpMasterDispatchPnp: IRP 0x%x\n", irpStack->MinorFunction));
  421. switch (irpStack->MinorFunction) {
  422. case IRP_MN_QUERY_INTERFACE:
  423. #if 0
  424. AGPLOG(AGP_IRPTRACE,
  425. ("\tSize=0x%x, Version=%d\n"
  426. "\tGUID=0x%08x-0x%04x-0x%04x-0x%02x-"
  427. "0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x\n",
  428. irpStack->Parameters.QueryInterface.Size,
  429. irpStack->Parameters.QueryInterface.Version,
  430. *(PULONG)irpStack->Parameters.QueryInterface.InterfaceType,
  431. *((PUSHORT)irpStack->Parameters.QueryInterface.InterfaceType + 2),
  432. *((PUSHORT)irpStack->Parameters.QueryInterface.InterfaceType + 3),
  433. *((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 8),
  434. *((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 9),
  435. *((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 10),
  436. *((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 11),
  437. *((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 12),
  438. *((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 13),
  439. *((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 14),
  440. *((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 15)));
  441. #endif
  442. //
  443. // The only IRP we look for here is IRP_MN_QUERY_INTERFACE for
  444. // GUID_AGP_BUS_INTERFACE_STANDARD.
  445. //
  446. if ((RtlEqualMemory(
  447. irpStack->Parameters.QueryInterface.InterfaceType,
  448. &GUID_AGP_BUS_INTERFACE_STANDARD,
  449. sizeof(GUID))) &&
  450. (((irpStack->Parameters.QueryInterface.Size >=
  451. sizeof(AGP_BUS_INTERFACE_STANDARD)) &&
  452. (irpStack->Parameters.QueryInterface.Version ==
  453. AGP_BUS_INTERFACE_V2)) ||
  454. ((irpStack->Parameters.QueryInterface.Size >=
  455. AGP_BUS_INTERFACE_V1_SIZE) &&
  456. (irpStack->Parameters.QueryInterface.Version ==
  457. AGP_BUS_INTERFACE_V1)))) {
  458. Interface = (PAGP_BUS_INTERFACE_STANDARD)irpStack->Parameters.QueryInterface.Interface;
  459. Interface->Version =
  460. irpStack->Parameters.QueryInterface.Version;
  461. Interface->AgpContext = Extension;
  462. Interface->InterfaceReference = AgpInterfaceReference;
  463. Interface->InterfaceDereference = AgpInterfaceDereference;
  464. Interface->ReserveMemory = AgpInterfaceReserveMemory;
  465. Interface->ReleaseMemory = AgpInterfaceReleaseMemory;
  466. Interface->CommitMemory = AgpInterfaceCommitMemory;
  467. Interface->FreeMemory = AgpInterfaceFreeMemory;
  468. Interface->GetMappedPages = AgpInterfaceGetMappedPages;
  469. if (Interface->Version < AGP_BUS_INTERFACE_V2) {
  470. Interface->Size = AGP_BUS_INTERFACE_V1_SIZE;
  471. } else {
  472. Interface->Size = sizeof(AGP_BUS_INTERFACE_STANDARD);
  473. Interface->SetRate = AgpInterfaceSetRate;
  474. }
  475. Interface->Capabilities = Extension->Capabilities;
  476. //
  477. // Complete the IRP successfully
  478. //
  479. Irp->IoStatus.Status = STATUS_SUCCESS;
  480. // AGPLOG(AGP_IRPTRACE, ("\tOK.\n"));
  481. } // else { AGPLOG(AGP_IRPTRACE, ("\tNO!\n")); }
  482. break;
  483. case IRP_MN_QUERY_REMOVE_DEVICE:
  484. case IRP_MN_QUERY_STOP_DEVICE:
  485. if (irpStack->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE) {
  486. Extension->RemovePending = TRUE;
  487. } else {
  488. Extension->StopPending = TRUE;
  489. }
  490. //
  491. // If we have given out any interfaces or there are some reserved
  492. // pages, we cannot stop.
  493. //
  494. if ((Extension->InterfaceCount > 0) ||
  495. (Extension->ReservedPages > 0)) {
  496. AGPLOG(AGP_NOISE,
  497. ("AgpMasterDispatchPnp: failing %s due to outstanding interfaces\n",
  498. (irpStack->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE)
  499. ? "IRP_MN_QUERY_REMOVE_DEVICE"
  500. : "IRP_MN_QUERY_STOP_DEVICE"
  501. ));
  502. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  503. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  504. return(STATUS_UNSUCCESSFUL);
  505. } else {
  506. //
  507. // We can succeed this, mark our extension as being in limbo so we do
  508. // not give out any interfaces or anything until we get removed or
  509. // get a cancel.
  510. //
  511. InterlockedIncrement(&Extension->DisableCount);
  512. break; // forward irp down the stack
  513. }
  514. case IRP_MN_CANCEL_REMOVE_DEVICE:
  515. //
  516. // This IRP must be handled on the way back up the stack.
  517. // Set a completion routine to reenable the device.
  518. //
  519. if (Extension->RemovePending) {
  520. Extension->RemovePending = FALSE;
  521. IoCopyCurrentIrpStackLocationToNext(Irp);
  522. IoSetCompletionRoutine(Irp,
  523. AgpCancelMasterRemove,
  524. Extension,
  525. TRUE,
  526. FALSE,
  527. FALSE);
  528. return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
  529. } else {
  530. //
  531. // This is a cancel-remove for a query-remove IRP we never saw.
  532. // Ignore it.
  533. //
  534. break;
  535. }
  536. case IRP_MN_CANCEL_STOP_DEVICE:
  537. //
  538. // This IRP must be handled on the way back up the stack.
  539. // Set a completion routine to reenable the device.
  540. //
  541. if (Extension->StopPending) {
  542. Extension->StopPending = FALSE;
  543. IoCopyCurrentIrpStackLocationToNext(Irp);
  544. IoSetCompletionRoutine(Irp,
  545. AgpCancelMasterRemove,
  546. Extension,
  547. TRUE,
  548. FALSE,
  549. FALSE);
  550. return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
  551. } else {
  552. //
  553. // This is a cancel-stop for a query-stop IRP we never saw.
  554. // Ignore it.
  555. //
  556. break;
  557. }
  558. case IRP_MN_REMOVE_DEVICE:
  559. AGPLOG(AGP_NOISE,
  560. ("AgpMasterDispatchPnp: removing device due to IRP_MN_REMOVE_DEVICE\n"));
  561. //
  562. // PNP is supposed to send us a QUERY_REMOVE before any REMOVE. That is
  563. // when we check that we are actually in a state where we can be removed.
  564. // Like all PNP rules, there is an exception - if the START is failed
  565. // after we have succeeded it, then we get a REMOVE without a QUERY_REMOVE.
  566. // Obviously this is totally fatal if we have given out interfaces or
  567. // have pages mapped in the GART. Not much we can do about it then.
  568. //
  569. ASSERT(Extension->InterfaceCount == 0);
  570. ASSERT(Extension->ReservedPages == 0);
  571. //
  572. // Pass the IRP down.
  573. //
  574. IoSkipCurrentIrpStackLocation(Irp);
  575. Status = IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
  576. //
  577. // Clean up and delete ourselves
  578. //
  579. Extension->Target->ChildDevice = NULL;
  580. Extension->CommonExtension.Deleted = TRUE;
  581. IoDetachDevice(Extension->CommonExtension.AttachedDevice);
  582. Extension->CommonExtension.AttachedDevice = NULL;
  583. RELEASE_BUS_INTERFACE(Extension);
  584. IoDeleteDevice(DeviceObject);
  585. return(Status);
  586. case IRP_MN_STOP_DEVICE:
  587. AGPLOG(AGP_NOISE,
  588. ("AgpMasterDispatchPnp: stopping device due to IRP_MN_STOP_DEVICE\n"));
  589. ASSERT(Extension->DisableCount);
  590. //
  591. // Just pass the IRP on down
  592. //
  593. break;
  594. case IRP_MN_START_DEVICE:
  595. AGPLOG(AGP_NOISE,
  596. ("AgpMasterDispatchPnp: starting device due to IRP_MN_START_DEVICE\n"));
  597. ASSERT(Extension->DisableCount);
  598. InterlockedDecrement(&Extension->DisableCount);
  599. break; // forward IRP down the stack
  600. }
  601. //
  602. // Just forward to target device
  603. //
  604. IoSkipCurrentIrpStackLocation(Irp);
  605. return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
  606. }
  607. NTSTATUS
  608. AgpMasterDispatchPower(
  609. IN PDEVICE_OBJECT DeviceObject,
  610. IN OUT PIRP Irp,
  611. IN PMASTER_EXTENSION Extension
  612. )
  613. {
  614. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  615. AGPLOG(AGP_IRPTRACE,
  616. ("AgpMasterDispatchPower: IRP 0x%x\n", irpStack->MinorFunction));
  617. //
  618. // All we keep track of are Dx states. Videoport is responsible for mapping
  619. // S-states into D states.
  620. //
  621. if ((irpStack->MinorFunction == IRP_MN_SET_POWER) &&
  622. (irpStack->Parameters.Power.Type == DevicePowerState) &&
  623. (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0)) {
  624. NTSTATUS Status;
  625. //
  626. // We need to reinitialize the master when this IRP has been completed
  627. // by the lower drivers. Set up a completion routine.
  628. //
  629. IoCopyCurrentIrpStackLocationToNext(Irp);
  630. IoSetCompletionRoutine(Irp,
  631. AgpMasterPowerUpCompletion,
  632. Extension,
  633. TRUE,
  634. FALSE,
  635. FALSE);
  636. IoMarkIrpPending(Irp);
  637. PoStartNextPowerIrp(Irp);
  638. Status = PoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
  639. return STATUS_PENDING;
  640. }
  641. //
  642. // Just forward to target device
  643. //
  644. PoStartNextPowerIrp(Irp);
  645. IoSkipCurrentIrpStackLocation(Irp);
  646. return(PoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
  647. }
  648. NTSTATUS
  649. AgpMasterPowerUpCompletion(
  650. IN PDEVICE_OBJECT DeviceObject,
  651. IN PIRP Irp,
  652. IN PMASTER_EXTENSION Extension
  653. )
  654. /*++
  655. Routine Description:
  656. Powerup completion routine for the master device. It reinitializes the
  657. master registers.
  658. Arguments:
  659. DeviceObject - supplies the master device object.
  660. Irp - Supplies the IRP_MN_SET_POWER irp.
  661. Extension - Supplies the master extension
  662. Return Value:
  663. Status
  664. --*/
  665. {
  666. NTSTATUS Status;
  667. ULONG CurrentCapabilities;
  668. if (Irp->PendingReturned) {
  669. IoMarkIrpPending(Irp);
  670. }
  671. Status = AgpInitializeMaster(GET_AGP_CONTEXT_FROM_MASTER(Extension),
  672. &CurrentCapabilities);
  673. ASSERT(CurrentCapabilities == Extension->Capabilities);
  674. if (!NT_SUCCESS(Status)) {
  675. Irp->IoStatus.Status = Status;
  676. }
  677. return STATUS_SUCCESS;
  678. }
  679. NTSTATUS
  680. AgpTargetPowerUpCompletion(
  681. IN PDEVICE_OBJECT DeviceObject,
  682. IN PIRP Irp,
  683. IN PTARGET_EXTENSION Extension
  684. )
  685. /*++
  686. Routine Description:
  687. Powerup completion routine for the target device. It reinitializes the
  688. GART aperture
  689. Arguments:
  690. DeviceObject - supplies the master device object.
  691. Irp - Supplies the IRP_MN_SET_POWER irp.
  692. Extension - Supplies the target extension
  693. Return Value:
  694. Status
  695. --*/
  696. {
  697. NTSTATUS Status;
  698. if (Irp->PendingReturned) {
  699. IoMarkIrpPending(Irp);
  700. }
  701. //
  702. // Now it is safe to reinitialize the target. All we do here
  703. // is reset the aperture
  704. //
  705. if (Extension->GartLengthInPages != 0) {
  706. Status = AgpSetAperture(GET_AGP_CONTEXT(Extension),
  707. Extension->GartBase,
  708. Extension->GartLengthInPages);
  709. if (!NT_SUCCESS(Status)) {
  710. Irp->IoStatus.Status = Status;
  711. }
  712. }
  713. return STATUS_SUCCESS;
  714. }
  715. NTSTATUS
  716. AgpCancelMasterRemove(
  717. IN PDEVICE_OBJECT DeviceObject,
  718. IN PIRP Irp,
  719. IN PMASTER_EXTENSION Extension
  720. )
  721. /*++
  722. Routine Description:
  723. Completion routine for IRP_MN_CANCEL_REMOVE_DEVICE. This is required
  724. since we cannot reenable AGP until the lower levels have completed their
  725. CANCEL_REMOVE processing.
  726. Arguments:
  727. DeviceObject - Supplies the device object
  728. Irp - Supplies the IRP
  729. Extension - Supplies the master extension
  730. Return Value:
  731. NTSTATUS
  732. --*/
  733. {
  734. if (Irp->PendingReturned) {
  735. IoMarkIrpPending(Irp);
  736. }
  737. ASSERT(Extension->DisableCount > 0);
  738. InterlockedDecrement(&Extension->DisableCount);
  739. return(STATUS_SUCCESS);
  740. }
  741. NTSTATUS
  742. AgpSetEventCompletion(
  743. IN PDEVICE_OBJECT DeviceObject,
  744. IN PIRP Irp,
  745. IN PKEVENT Event
  746. )
  747. /*++
  748. Routine Description:
  749. This routine is used as a completion routine when an IRP is passed
  750. down the stack but more processing must be done on the way back up.
  751. The effect of using this as a completion routine is that the IRP
  752. will not be destroyed in IoCompleteRequest as called by the lower
  753. level object. The event which is a KEVENT is signaled to allow
  754. processing to continue
  755. Arguments:
  756. DeviceObject - Supplies the device object
  757. Irp - The IRP we are processing
  758. Event - Supplies the event to be signaled
  759. Return Value:
  760. STATUS_MORE_PROCESSING_REQUIRED
  761. --*/
  762. {
  763. ASSERT(Event);
  764. //
  765. // This can be called at DISPATCH_LEVEL so must not be paged
  766. //
  767. KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
  768. return STATUS_MORE_PROCESSING_REQUIRED;
  769. }