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.

993 lines
25 KiB

  1. /*++
  2. Copyright (c) 1990-2000 Microsoft Corporation
  3. Module Name:
  4. fdopnp.c
  5. Abstract:
  6. This file contains the PNP IRP dispatch code for FDOs
  7. Environment:
  8. Kernel Mode Driver.
  9. Revision History:
  10. --*/
  11. #include "busp.h"
  12. #include "pnpisa.h"
  13. #include <wdmguid.h>
  14. #include "halpnpp.h"
  15. //
  16. // Function Prototypes
  17. //
  18. NTSTATUS
  19. PiDeferProcessingFdo(
  20. IN PPI_BUS_EXTENSION BusExtension,
  21. IN OUT PIRP Irp
  22. );
  23. NTSTATUS
  24. PiStartFdo(
  25. IN PDEVICE_OBJECT DeviceObject,
  26. IN OUT PIRP Irp
  27. );
  28. NTSTATUS
  29. PiQueryRemoveStopFdo(
  30. IN PDEVICE_OBJECT DeviceObject,
  31. IN OUT PIRP Irp
  32. );
  33. NTSTATUS
  34. PiCancelRemoveStopFdo(
  35. IN PDEVICE_OBJECT DeviceObject,
  36. IN OUT PIRP Irp
  37. );
  38. NTSTATUS
  39. PiStopFdo(
  40. IN PDEVICE_OBJECT DeviceObject,
  41. IN OUT PIRP Irp
  42. );
  43. NTSTATUS
  44. PiQueryDeviceRelationsFdo(
  45. IN PDEVICE_OBJECT DeviceObject,
  46. IN OUT PIRP Irp
  47. );
  48. NTSTATUS
  49. PiRemoveFdo(
  50. IN PDEVICE_OBJECT DeviceObject,
  51. IN OUT PIRP Irp
  52. );
  53. NTSTATUS
  54. PiQueryLegacyBusInformationFdo(
  55. IN PDEVICE_OBJECT DeviceObject,
  56. IN OUT PIRP Irp
  57. );
  58. NTSTATUS
  59. PiQueryInterfaceFdo(
  60. IN PDEVICE_OBJECT DeviceObject,
  61. IN OUT PIRP Irp
  62. );
  63. NTSTATUS
  64. PiQueryPnpDeviceState(
  65. IN PDEVICE_OBJECT DeviceObject,
  66. IN OUT PIRP Irp
  67. );
  68. NTSTATUS
  69. PiSurpriseRemoveFdo(
  70. IN PDEVICE_OBJECT DeviceObject,
  71. IN OUT PIRP Irp
  72. );
  73. #ifdef ALLOC_PRAGMA
  74. #pragma alloc_text(PAGE,PiDispatchPnpFdo)
  75. #pragma alloc_text(PAGE,PiDeferProcessingFdo)
  76. #pragma alloc_text(PAGE,PiStartFdo)
  77. #pragma alloc_text(PAGE,PiQueryRemoveStopFdo)
  78. #pragma alloc_text(PAGE,PiRemoveFdo)
  79. #pragma alloc_text(PAGE,PiCancelRemoveStopFdo)
  80. #pragma alloc_text(PAGE,PiStopFdo)
  81. #pragma alloc_text(PAGE,PiQueryRemoveStopFdo)
  82. #pragma alloc_text(PAGE,PiCancelRemoveStopFdo)
  83. #pragma alloc_text(PAGE,PiQueryDeviceRelationsFdo)
  84. #pragma alloc_text(PAGE,PiQueryInterfaceFdo)
  85. #pragma alloc_text(PAGE,PipPassIrp)
  86. #pragma alloc_text(PAGE,PiQueryLegacyBusInformationFdo)
  87. #pragma alloc_text(PAGE,PiQueryPnpDeviceState)
  88. #pragma alloc_text(PAGE,PiSurpriseRemoveFdo)
  89. #endif
  90. //
  91. // PNP IRP Dispatch table for FDOs
  92. //
  93. PPI_DISPATCH PiPnpDispatchTableFdo[] = {
  94. PiStartFdo, // IRP_MN_START_DEVICE
  95. PiQueryRemoveStopFdo, // IRP_MN_QUERY_REMOVE_DEVICE
  96. PiRemoveFdo, // IRP_MN_REMOVE_DEVICE
  97. PiCancelRemoveStopFdo, // IRP_MN_CANCEL_REMOVE_DEVICE
  98. PiStopFdo, // IRP_MN_STOP_DEVICE
  99. PiQueryRemoveStopFdo, // IRP_MN_QUERY_STOP_DEVICE
  100. PiCancelRemoveStopFdo, // IRP_MN_CANCEL_STOP_DEVICE
  101. PiQueryDeviceRelationsFdo, // IRP_MN_QUERY_DEVICE_RELATIONS
  102. PiQueryInterfaceFdo, // IRP_MN_QUERY_INTERFACE
  103. PipPassIrp, // IRP_MN_QUERY_CAPABILITIES
  104. PipPassIrp, // IRP_MN_QUERY_RESOURCES
  105. PipPassIrp, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
  106. PipPassIrp, // IRP_MN_QUERY_DEVICE_TEXT
  107. PipPassIrp, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
  108. PipPassIrp, // Unused
  109. PipPassIrp, // IRP_MN_READ_CONFIG
  110. PipPassIrp, // IRP_MN_WRITE_CONFIG
  111. PipPassIrp, // IRP_MN_EJECT
  112. PipPassIrp, // IRP_MN_SET_LOCK
  113. PipPassIrp, // IRP_MN_QUERY_ID
  114. PiQueryPnpDeviceState, // IRP_MN_QUERY_PNP_DEVICE_STATE
  115. PipPassIrp, // IRP_MN_QUERY_BUS_INFORMATION
  116. PipPassIrp, // IRP_MN_DEVICE_USAGE_NOTIFICATION
  117. PiSurpriseRemoveFdo, // IRP_MN_SURPRISE_REMOVAL
  118. PiQueryLegacyBusInformationFdo // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  119. };
  120. //
  121. // Function declarations
  122. //
  123. NTSTATUS
  124. PiDispatchPnpFdo(
  125. IN PDEVICE_OBJECT DeviceObject,
  126. IN OUT PIRP Irp
  127. )
  128. /*++
  129. Routine Description:
  130. This routine handles IRP_MJ_PNP IRPs for FDOs.
  131. Arguments:
  132. DeviceObject - Pointer to the FDO for which this IRP applies.
  133. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  134. Return Value:
  135. NT status.
  136. --*/
  137. {
  138. PIO_STACK_LOCATION irpSp;
  139. NTSTATUS status;
  140. PPI_BUS_EXTENSION busExtension;
  141. PAGED_CODE();
  142. //
  143. // Get a pointer to our stack location and take appropriate action based
  144. // on the minor function.
  145. //
  146. irpSp = IoGetCurrentIrpStackLocation(Irp);
  147. busExtension = DeviceObject->DeviceExtension;
  148. if (irpSp->MinorFunction > IRP_MN_PNP_MAXIMUM_FUNCTION) {
  149. return PipPassIrp(DeviceObject, Irp);
  150. } else {
  151. status = PiPnpDispatchTableFdo[irpSp->MinorFunction](DeviceObject, Irp);
  152. }
  153. return status;
  154. } //PipDispatchPnpFdo
  155. NTSTATUS
  156. PiPnPFdoCompletion(
  157. IN PDEVICE_OBJECT DeviceObject,
  158. IN PIRP Irp,
  159. IN PVOID Context
  160. )
  161. /*++
  162. Routine Description:
  163. This routine is used to defer processing of an IRP until drivers
  164. lower in the stack including the bus driver have done their
  165. processing.
  166. This routine triggers the event to indicate that processing of the
  167. irp can now continue.
  168. Arguments:
  169. DeviceObject - Pointer to the FDO for which this IRP applies.
  170. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  171. Return Value:
  172. NT status.
  173. --*/
  174. {
  175. KeSetEvent((PKEVENT) Context, EVENT_INCREMENT, FALSE);
  176. return STATUS_MORE_PROCESSING_REQUIRED;
  177. }
  178. NTSTATUS
  179. PiDeferProcessingFdo(
  180. IN PPI_BUS_EXTENSION BusExtension,
  181. IN OUT PIRP Irp
  182. )
  183. /*++
  184. Routine Description:
  185. This routine is used to defer processing of an IRP until drivers
  186. lower in the stack including the bus driver have done their
  187. processing.
  188. This routine uses an IoCompletion routine along with an event to
  189. wait until the lower level drivers have completed processing of
  190. the irp.
  191. Arguments:
  192. BusExtension - FDO extension for the FDO devobj in question
  193. Irp - Pointer to the IRP_MJ_PNP IRP to defer
  194. Return Value:
  195. NT status.
  196. --*/
  197. {
  198. KEVENT event;
  199. NTSTATUS status;
  200. KeInitializeEvent(&event, NotificationEvent, FALSE);
  201. //
  202. // Set our completion routine
  203. //
  204. IoCopyCurrentIrpStackLocationToNext(Irp);
  205. IoSetCompletionRoutine(Irp,
  206. PiPnPFdoCompletion,
  207. &event,
  208. TRUE,
  209. TRUE,
  210. TRUE
  211. );
  212. status = IoCallDriver(BusExtension->AttachedDevice, Irp);
  213. if (status == STATUS_PENDING) {
  214. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  215. status = Irp->IoStatus.Status;
  216. }
  217. return status;
  218. }
  219. NTSTATUS
  220. PiStartFdo(
  221. IN PDEVICE_OBJECT DeviceObject,
  222. IN OUT PIRP Irp
  223. )
  224. {
  225. PPI_BUS_EXTENSION busExtension;
  226. NTSTATUS status;
  227. DebugPrint((DEBUG_PNP,
  228. "*** StartDevice irp received FDO: %x\n",DeviceObject));
  229. busExtension = DeviceObject->DeviceExtension;
  230. //
  231. // Postpones start operations until all lower drivers have
  232. // finished with the IRP.
  233. //
  234. status = PiDeferProcessingFdo(busExtension, Irp);
  235. if (NT_SUCCESS(status)) {
  236. busExtension->SystemPowerState = PowerSystemWorking;
  237. busExtension->DevicePowerState = PowerDeviceD0;
  238. }
  239. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  240. return status;
  241. } // PiStartFdo
  242. NTSTATUS
  243. PiQueryRemoveStopFdo(
  244. IN PDEVICE_OBJECT DeviceObject,
  245. IN OUT PIRP Irp
  246. )
  247. {
  248. NTSTATUS status;
  249. PPI_BUS_EXTENSION busExtension;
  250. DebugPrint((DEBUG_PNP,
  251. "*** QR/R/StopDevice irp received FDO: %x\n",DeviceObject));
  252. busExtension = DeviceObject->DeviceExtension;
  253. KeWaitForSingleObject( &IsaBusNumberLock,
  254. Executive,
  255. KernelMode,
  256. FALSE,
  257. NULL );
  258. if (busExtension->BusNumber != 0) {
  259. status = PipReleaseInterfaces(busExtension);
  260. ActiveIsaCount--;
  261. busExtension->Flags |= DF_QUERY_STOPPED;
  262. } else {
  263. Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL;
  264. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  265. }
  266. KeSetEvent( &IsaBusNumberLock,
  267. 0,
  268. FALSE );
  269. if (NT_SUCCESS(status)) {
  270. Irp->IoStatus.Status = STATUS_SUCCESS;
  271. status = PipPassIrp(DeviceObject, Irp);
  272. }
  273. DebugPrint((DEBUG_PNP, "QR/R/Stop Device returning: %x\n",status));
  274. return status;
  275. } // PiQueryRemoveStopFdo
  276. NTSTATUS
  277. PiCancelRemoveStopFdo(
  278. IN PDEVICE_OBJECT DeviceObject,
  279. IN OUT PIRP Irp
  280. )
  281. {
  282. NTSTATUS status;
  283. PPI_BUS_EXTENSION busExtension;
  284. DebugPrint((DEBUG_PNP,
  285. "*** Cancel R/Stop Device irp received FDO: %x\n",DeviceObject));
  286. busExtension = DeviceObject->DeviceExtension;
  287. status = PiDeferProcessingFdo(busExtension, Irp);
  288. // NTRAID#53498
  289. // ASSERT(status == STATUS_SUCCESS);
  290. // Uncomment after PCI state machine is fixed to not fail bogus stops
  291. //
  292. // Add back to active count
  293. //
  294. KeWaitForSingleObject( &IsaBusNumberLock,
  295. Executive,
  296. KernelMode,
  297. FALSE,
  298. NULL );
  299. if (busExtension->Flags & DF_QUERY_STOPPED) {
  300. ActiveIsaCount++;
  301. }
  302. busExtension->Flags &= ~DF_QUERY_STOPPED;
  303. KeSetEvent( &IsaBusNumberLock,
  304. 0,
  305. FALSE );
  306. status = PipRebuildInterfaces (busExtension);
  307. ASSERT(status == STATUS_SUCCESS);
  308. PipCompleteRequest(Irp, STATUS_SUCCESS, NULL);
  309. DebugPrint((DEBUG_PNP, "Cancel R/Stop Device returning: %x\n",status));
  310. return STATUS_SUCCESS;
  311. } // PiCancelRemoveStopFdo
  312. NTSTATUS
  313. PiStopFdo(
  314. IN PDEVICE_OBJECT DeviceObject,
  315. IN OUT PIRP Irp
  316. )
  317. {
  318. PPI_BUS_EXTENSION busExtension;
  319. NTSTATUS status;
  320. DebugPrint((DEBUG_PNP,
  321. "*** Stop Device irp received FDO: %x\n",DeviceObject));
  322. busExtension = DeviceObject->DeviceExtension;
  323. KeWaitForSingleObject( &IsaBusNumberLock,
  324. Executive,
  325. KernelMode,
  326. FALSE,
  327. NULL );
  328. //
  329. //Actually clear the bitmap
  330. //
  331. ASSERT (RtlAreBitsSet (BusNumBM,busExtension->BusNumber,1));
  332. RtlClearBits (BusNumBM,busExtension->BusNumber,1);
  333. KeSetEvent( &IsaBusNumberLock,
  334. 0,
  335. FALSE );
  336. busExtension->DevicePowerState = PowerDeviceD3;
  337. //
  338. // Handled in QueryStop, pass it down.
  339. //
  340. Irp->IoStatus.Status = STATUS_SUCCESS;
  341. status = PipPassIrp (DeviceObject,Irp);
  342. DebugPrint((DEBUG_PNP, "Stop Device returning: %x\n",status));
  343. return status;
  344. } // PiStopFdo
  345. NTSTATUS
  346. PiQueryDeviceRelationsFdo(
  347. IN PDEVICE_OBJECT DeviceObject,
  348. IN OUT PIRP Irp
  349. )
  350. {
  351. PPI_BUS_EXTENSION busExtension;
  352. PIO_STACK_LOCATION irpSp;
  353. PDEVICE_RELATIONS deviceRelations;
  354. PDEVICE_INFORMATION deviceInfo;
  355. PSINGLE_LIST_ENTRY deviceLink;
  356. BOOLEAN creatingRDP=FALSE,accessHW;
  357. NTSTATUS status;
  358. DebugPrint((DEBUG_PNP, "QueryDeviceRelations FDO %x\n",
  359. DeviceObject));
  360. busExtension = DeviceObject->DeviceExtension;
  361. irpSp = IoGetCurrentIrpStackLocation(Irp);
  362. #if ISOLATE_CARDS
  363. //
  364. // Only support BusRelations on PnpIsa bus PDO.
  365. //
  366. switch (irpSp->Parameters.QueryDeviceRelations.Type) {
  367. case BusRelations: {
  368. //
  369. // Isolation may have been disabled via registry key. In
  370. // that case, never enumerate an RDP.
  371. //
  372. // Note: Must return success and empty relations list
  373. // *RATHER* than just passing the irp down to accomplish
  374. // the same task due because of assumptions in the pnpres
  375. // code.
  376. //
  377. if (PipIsolationDisabled) {
  378. deviceRelations = ExAllocatePool(PagedPool,
  379. sizeof(DEVICE_RELATIONS));
  380. if (deviceRelations) {
  381. deviceRelations->Count = 0;
  382. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  383. Irp->IoStatus.Status = STATUS_SUCCESS;
  384. } else {
  385. PipCompleteRequest(Irp,STATUS_INSUFFICIENT_RESOURCES,NULL);
  386. return STATUS_INSUFFICIENT_RESOURCES;
  387. }
  388. break;
  389. }
  390. //
  391. // All relations exist on the 'root' isa bus. (don't ask)
  392. //
  393. if (busExtension->BusNumber != 0) {
  394. break;
  395. }
  396. if (PipRDPNode) {
  397. //
  398. // overload the notion of "creating" for multi-bridge systems
  399. //
  400. if (PipRDPNode->Flags & (DF_PROCESSING_RDP|DF_ACTIVATED)) {
  401. creatingRDP=TRUE;
  402. }
  403. }
  404. if (PipReadDataPort == NULL && !creatingRDP && !PipRDPNode ) {
  405. status = PipCreateReadDataPort(busExtension);
  406. if (!NT_SUCCESS(status)) {
  407. PipCompleteRequest(Irp, status, NULL);
  408. return status;
  409. }
  410. creatingRDP=TRUE;
  411. }
  412. if ((PipRDPNode && (creatingRDP) &&
  413. !(PipRDPNode->Flags & DF_ACTIVATED)) ||
  414. (PipRDPNode && (PipRDPNode->Flags & DF_REMOVED))) {
  415. PSINGLE_LIST_ENTRY deviceLink;
  416. deviceRelations = (PDEVICE_RELATIONS) ExAllocatePool(
  417. PagedPool,
  418. sizeof(DEVICE_RELATIONS) );
  419. if (deviceRelations) {
  420. //
  421. // If a device exists, mark it as disappeared so
  422. // it's not reported again
  423. //
  424. PipLockDeviceDatabase();
  425. deviceLink = busExtension->DeviceList.Next;
  426. while (deviceLink) {
  427. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
  428. if (!(deviceInfo->Flags & DF_READ_DATA_PORT)) {
  429. deviceInfo->Flags &= ~DF_ENUMERATED;
  430. }
  431. deviceLink = deviceInfo->DeviceList.Next;
  432. }
  433. PipUnlockDeviceDatabase();
  434. deviceRelations->Count = 1;
  435. DebugPrint((DEBUG_PNP,
  436. "QueryDeviceRelations handing back the FDO\n"));
  437. ObReferenceObject(PipRDPNode->PhysicalDeviceObject);
  438. deviceRelations->Objects[0] = PipRDPNode->PhysicalDeviceObject;
  439. (PDEVICE_RELATIONS)Irp->IoStatus.Information = deviceRelations;
  440. Irp->IoStatus.Status = STATUS_SUCCESS;
  441. break;
  442. } else {
  443. PipCompleteRequest(Irp, STATUS_INSUFFICIENT_RESOURCES,NULL);
  444. return STATUS_INSUFFICIENT_RESOURCES;
  445. }
  446. }
  447. //
  448. // Perform bus check to enumerate all the device under pnpisa bus.
  449. //
  450. PipLockDeviceDatabase();
  451. if ((PipRDPNode->Flags & (DF_ACTIVATED|DF_QUERY_STOPPED)) == DF_ACTIVATED) {
  452. accessHW = TRUE;
  453. deviceLink = busExtension->DeviceList.Next;
  454. while (deviceLink) {
  455. deviceInfo = CONTAINING_RECORD (deviceLink,
  456. DEVICE_INFORMATION,
  457. DeviceList);
  458. if (!(deviceInfo->Flags & DF_READ_DATA_PORT)) {
  459. accessHW = FALSE;
  460. DebugPrint((DEBUG_PNP,
  461. "QueryDeviceRelations: Found 1 card, no more isolation\n"));
  462. break;
  463. }
  464. deviceLink = deviceInfo->DeviceList.Next;
  465. }
  466. } else {
  467. accessHW = FALSE;
  468. }
  469. if (PipRDPNode->Flags & DF_NEEDS_RESCAN) {
  470. DebugPrint((DEBUG_PNP,
  471. "QueryDeviceRelations: Force rescan\n"));
  472. PipRDPNode->Flags &= ~DF_NEEDS_RESCAN;
  473. accessHW = TRUE;
  474. }
  475. if (accessHW) {
  476. PipCheckBus(busExtension);
  477. } else {
  478. DebugPrint((DEBUG_PNP, "QueryDeviceRelations: Using cached data\n"));
  479. }
  480. status = PipQueryDeviceRelations(
  481. busExtension,
  482. (PDEVICE_RELATIONS *)&Irp->IoStatus.Information,
  483. FALSE );
  484. PipUnlockDeviceDatabase();
  485. Irp->IoStatus.Status = status;
  486. if (!NT_SUCCESS(status)) {
  487. PipCompleteRequest(Irp, status, NULL);
  488. return status;
  489. }
  490. }
  491. break;
  492. case EjectionRelations: {
  493. if (PipRDPNode) {
  494. deviceRelations = (PDEVICE_RELATIONS) ExAllocatePool(
  495. PagedPool,
  496. sizeof(DEVICE_RELATIONS) );
  497. if (deviceRelations) {
  498. deviceRelations->Count = 1;
  499. ObReferenceObject(PipRDPNode->PhysicalDeviceObject);
  500. deviceRelations->Objects[0] = PipRDPNode->PhysicalDeviceObject;
  501. (PDEVICE_RELATIONS)Irp->IoStatus.Information = deviceRelations;
  502. Irp->IoStatus.Status = STATUS_SUCCESS;
  503. } else {
  504. PipCompleteRequest(Irp,STATUS_INSUFFICIENT_RESOURCES,NULL);
  505. return STATUS_INSUFFICIENT_RESOURCES;
  506. }
  507. }
  508. }
  509. break;
  510. }
  511. #else
  512. if (irpSp->Parameters.QueryDeviceRelations.Type == BusRelations &&
  513. busExtension->BusNumber == 0) {
  514. deviceRelations = (PDEVICE_RELATIONS) ExAllocatePool(
  515. PagedPool,
  516. sizeof(DEVICE_RELATIONS) );
  517. if (deviceRelations) {
  518. deviceRelations->Count = 0;
  519. (PDEVICE_RELATIONS)Irp->IoStatus.Information = deviceRelations;
  520. Irp->IoStatus.Status = STATUS_SUCCESS;
  521. } else {
  522. PipCompleteRequest(Irp,STATUS_INSUFFICIENT_RESOURCES,NULL);
  523. return STATUS_INSUFFICIENT_RESOURCES;
  524. }
  525. }
  526. #endif
  527. return PipPassIrp(DeviceObject, Irp);
  528. } // PiQueryDeviceRelationsFdo
  529. NTSTATUS
  530. PiRemoveFdo(
  531. IN PDEVICE_OBJECT DeviceObject,
  532. IN OUT PIRP Irp
  533. )
  534. {
  535. NTSTATUS status;
  536. PPI_BUS_EXTENSION busExtension;
  537. PSINGLE_LIST_ENTRY child;
  538. PBUS_EXTENSION_LIST busList,prevBus;
  539. USHORT count=0;
  540. DebugPrint((DEBUG_PNP,
  541. "*** Remove Device irp received FDO: %x\n",DeviceObject));
  542. busExtension = DeviceObject->DeviceExtension;
  543. //
  544. // Clear the entry in the BM. Count dropped in
  545. // Query Remove.
  546. //
  547. KeWaitForSingleObject( &IsaBusNumberLock,
  548. Executive,
  549. KernelMode,
  550. FALSE,
  551. NULL );
  552. if (!(busExtension->Flags & DF_SURPRISE_REMOVED)) {
  553. #ifdef DBG
  554. ASSERT (RtlAreBitsSet (BusNumBM,busExtension->BusNumber,1));
  555. #endif
  556. RtlClearBits (BusNumBM,busExtension->BusNumber,1);
  557. }
  558. #if ISOLATE_CARDS
  559. PipLockDeviceDatabase();
  560. //
  561. // Walk the list of children and delete them
  562. //
  563. child=PopEntryList (&busExtension->DeviceList);
  564. while (child) {
  565. ASSERT (CONTAINING_RECORD (child, DEVICE_INFORMATION,DeviceList)->PhysicalDeviceObject);
  566. //
  567. // This pulls them from the list!
  568. //
  569. count ++;
  570. if (CONTAINING_RECORD (child, DEVICE_INFORMATION,DeviceList)->Flags & DF_READ_DATA_PORT) {
  571. //
  572. // Force the recreate of the RDP
  573. //
  574. PipCleanupAcquiredResources (busExtension);
  575. PipReadDataPort = NULL;
  576. PipRDPNode = NULL;
  577. } else {
  578. PipReleaseDeviceResources ((PDEVICE_INFORMATION)child);
  579. }
  580. IoDeleteDevice (CONTAINING_RECORD (child, DEVICE_INFORMATION,DeviceList)->PhysicalDeviceObject);
  581. child=PopEntryList (&busExtension->DeviceList);
  582. }
  583. PipUnlockDeviceDatabase();
  584. #endif
  585. //
  586. // Delete this extension.
  587. //
  588. prevBus= busList = PipBusExtension;
  589. ASSERT (busList != NULL);
  590. while (busList->BusExtension != busExtension) {
  591. prevBus= busList;
  592. busList = busList->Next;
  593. ASSERT (busList != NULL);
  594. }
  595. //
  596. // Remove the node
  597. //
  598. if (prevBus == busList) {
  599. //
  600. // First Node.
  601. //
  602. PipBusExtension=busList->Next;
  603. }else {
  604. prevBus->Next = busList->Next;
  605. }
  606. ExFreePool (busList);
  607. KeSetEvent( &IsaBusNumberLock,
  608. 0,
  609. FALSE );
  610. if (count > 0 ) {
  611. //
  612. // If we STILL have an ISA bus. Do this.
  613. //
  614. if (ActiveIsaCount > 0 ) {
  615. ASSERT (PipBusExtension->BusExtension);
  616. IoInvalidateDeviceRelations (PipBusExtension->BusExtension->PhysicalBusDevice,BusRelations);
  617. }
  618. }
  619. #if ISOLATE_CARDS
  620. //
  621. // Cleanup all the resources on the last remove.
  622. //
  623. if (!(busExtension->Flags & DF_SURPRISE_REMOVED)) {
  624. PipCleanupAcquiredResources (busExtension);
  625. }
  626. #endif
  627. //
  628. // The PnpISa bus PDO is being removed...
  629. //
  630. IoDetachDevice(busExtension->AttachedDevice);
  631. Irp->IoStatus.Status=STATUS_SUCCESS;
  632. status = PipPassIrp(DeviceObject, Irp);
  633. busExtension->AttachedDevice = NULL;
  634. busExtension->Flags |= DF_DELETED;
  635. busExtension->DevicePowerState = PowerDeviceD3;
  636. IoDeleteDevice(busExtension->FunctionalBusDevice);
  637. return status;
  638. } // PiRemoveFdo
  639. NTSTATUS
  640. PiQueryLegacyBusInformationFdo(
  641. IN PDEVICE_OBJECT DeviceObject,
  642. IN OUT PIRP Irp
  643. )
  644. {
  645. PLEGACY_BUS_INFORMATION legacyBusInfo;
  646. PVOID information = NULL;
  647. PPI_BUS_EXTENSION busExtension;
  648. NTSTATUS status;
  649. busExtension = DeviceObject->DeviceExtension;
  650. legacyBusInfo = (PLEGACY_BUS_INFORMATION) ExAllocatePool(PagedPool, sizeof(LEGACY_BUS_INFORMATION));
  651. if (legacyBusInfo) {
  652. legacyBusInfo->BusTypeGuid = GUID_BUS_TYPE_ISAPNP;
  653. legacyBusInfo->LegacyBusType = Isa;
  654. legacyBusInfo->BusNumber = busExtension->BusNumber;
  655. information = legacyBusInfo;
  656. status = STATUS_SUCCESS;
  657. } else {
  658. status = STATUS_INSUFFICIENT_RESOURCES;
  659. }
  660. if (NT_SUCCESS(status)) {
  661. Irp->IoStatus.Status = status;
  662. Irp->IoStatus.Information = (ULONG_PTR) information;
  663. return PipPassIrp(DeviceObject, Irp);
  664. } else {
  665. PipCompleteRequest (Irp,status,NULL);
  666. return status;
  667. }
  668. }
  669. NTSTATUS
  670. PiQueryInterfaceFdo(
  671. IN PDEVICE_OBJECT DeviceObject,
  672. IN OUT PIRP Irp
  673. )
  674. {
  675. NTSTATUS status;
  676. PPI_BUS_EXTENSION busExtension;
  677. busExtension = DeviceObject->DeviceExtension;
  678. //
  679. // We are a FDO - check if we are being asked for an interface we
  680. // support
  681. //
  682. status = PiQueryInterface(busExtension, Irp);
  683. if (NT_SUCCESS(status)) {
  684. Irp->IoStatus.Status = status;
  685. Irp->IoStatus.Information = 0;
  686. return PipPassIrp(DeviceObject, Irp);
  687. } else if (status == STATUS_NOT_SUPPORTED) {
  688. return PipPassIrp(DeviceObject, Irp);
  689. } else {
  690. PipCompleteRequest (Irp,status,NULL);
  691. return status;
  692. }
  693. } // PiQueryInterfaceFdo
  694. NTSTATUS
  695. PiQueryPnpDeviceState(
  696. IN PDEVICE_OBJECT DeviceObject,
  697. IN OUT PIRP Irp
  698. )
  699. {
  700. PPI_BUS_EXTENSION busExtension;
  701. busExtension = DeviceObject->DeviceExtension;
  702. //
  703. // We are a FDO
  704. //
  705. (PNP_DEVICE_STATE) Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
  706. Irp->IoStatus.Status = STATUS_SUCCESS;
  707. return PipPassIrp(DeviceObject, Irp);
  708. } // PiQueryPnpDeviceState
  709. NTSTATUS
  710. PiSurpriseRemoveFdo(
  711. IN PDEVICE_OBJECT DeviceObject,
  712. IN OUT PIRP Irp
  713. )
  714. {
  715. NTSTATUS status;
  716. PPI_BUS_EXTENSION busExtension;
  717. DebugPrint((DEBUG_PNP,
  718. "*** Surprise Remove Device irp received FDO: %x\n",DeviceObject));
  719. busExtension = DeviceObject->DeviceExtension;
  720. //
  721. // Clear the entry in the BM. Count dropped in
  722. // Query Remove.
  723. //
  724. KeWaitForSingleObject( &IsaBusNumberLock,
  725. Executive,
  726. KernelMode,
  727. FALSE,
  728. NULL );
  729. #ifdef DBG
  730. ASSERT (RtlAreBitsSet (BusNumBM,busExtension->BusNumber,1));
  731. #endif
  732. RtlClearBits (BusNumBM,busExtension->BusNumber,1);
  733. KeSetEvent( &IsaBusNumberLock,
  734. 0,
  735. FALSE );
  736. #if ISOLATE_CARDS
  737. PipCleanupAcquiredResources (busExtension);
  738. #endif
  739. //
  740. // The PnpISa bus PDO is being removed...
  741. //
  742. Irp->IoStatus.Status=STATUS_SUCCESS;
  743. status = PipPassIrp(DeviceObject, Irp);
  744. busExtension->AttachedDevice = NULL;
  745. busExtension->Flags |= DF_SURPRISE_REMOVED;
  746. busExtension->DevicePowerState = PowerDeviceD3;
  747. return status;
  748. } // PiSurpriseRemoveFdo