Leaked source code of windows server 2003
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
26 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. if (!NT_SUCCESS(status)) {
  261. PipCompleteRequest(Irp,status,NULL);
  262. return status;
  263. }
  264. ActiveIsaCount--;
  265. busExtension->Flags |= DF_QUERY_STOPPED;
  266. } else {
  267. Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL;
  268. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  269. }
  270. KeSetEvent( &IsaBusNumberLock,
  271. 0,
  272. FALSE );
  273. if (NT_SUCCESS(status)) {
  274. Irp->IoStatus.Status = STATUS_SUCCESS;
  275. status = PipPassIrp(DeviceObject, Irp);
  276. }
  277. DebugPrint((DEBUG_PNP, "QR/R/Stop Device returning: %x\n",status));
  278. return status;
  279. } // PiQueryRemoveStopFdo
  280. NTSTATUS
  281. PiCancelRemoveStopFdo(
  282. IN PDEVICE_OBJECT DeviceObject,
  283. IN OUT PIRP Irp
  284. )
  285. {
  286. NTSTATUS status;
  287. PPI_BUS_EXTENSION busExtension;
  288. DebugPrint((DEBUG_PNP,
  289. "*** Cancel R/Stop Device irp received FDO: %x\n",DeviceObject));
  290. busExtension = DeviceObject->DeviceExtension;
  291. status = PiDeferProcessingFdo(busExtension, Irp);
  292. // NTRAID#53498
  293. // ASSERT(status == STATUS_SUCCESS);
  294. // Uncomment after PCI state machine is fixed to not fail bogus stops
  295. //
  296. // Add back to active count
  297. //
  298. KeWaitForSingleObject( &IsaBusNumberLock,
  299. Executive,
  300. KernelMode,
  301. FALSE,
  302. NULL );
  303. if (busExtension->Flags & DF_QUERY_STOPPED) {
  304. ActiveIsaCount++;
  305. }
  306. busExtension->Flags &= ~DF_QUERY_STOPPED;
  307. KeSetEvent( &IsaBusNumberLock,
  308. 0,
  309. FALSE );
  310. status = PipRebuildInterfaces (busExtension);
  311. ASSERT(status == STATUS_SUCCESS);
  312. PipCompleteRequest(Irp, STATUS_SUCCESS, NULL);
  313. DebugPrint((DEBUG_PNP, "Cancel R/Stop Device returning: %x\n",status));
  314. return STATUS_SUCCESS;
  315. } // PiCancelRemoveStopFdo
  316. NTSTATUS
  317. PiStopFdo(
  318. IN PDEVICE_OBJECT DeviceObject,
  319. IN OUT PIRP Irp
  320. )
  321. {
  322. PPI_BUS_EXTENSION busExtension;
  323. NTSTATUS status;
  324. DebugPrint((DEBUG_PNP,
  325. "*** Stop Device irp received FDO: %x\n",DeviceObject));
  326. busExtension = DeviceObject->DeviceExtension;
  327. KeWaitForSingleObject( &IsaBusNumberLock,
  328. Executive,
  329. KernelMode,
  330. FALSE,
  331. NULL );
  332. //
  333. //Actually clear the bitmap
  334. //
  335. ASSERT (RtlAreBitsSet (BusNumBM,busExtension->BusNumber,1));
  336. RtlClearBits (BusNumBM,busExtension->BusNumber,1);
  337. KeSetEvent( &IsaBusNumberLock,
  338. 0,
  339. FALSE );
  340. busExtension->DevicePowerState = PowerDeviceD3;
  341. //
  342. // Handled in QueryStop, pass it down.
  343. //
  344. Irp->IoStatus.Status = STATUS_SUCCESS;
  345. status = PipPassIrp (DeviceObject,Irp);
  346. DebugPrint((DEBUG_PNP, "Stop Device returning: %x\n",status));
  347. return status;
  348. } // PiStopFdo
  349. NTSTATUS
  350. PiQueryDeviceRelationsFdo(
  351. IN PDEVICE_OBJECT DeviceObject,
  352. IN OUT PIRP Irp
  353. )
  354. {
  355. PPI_BUS_EXTENSION busExtension;
  356. PIO_STACK_LOCATION irpSp;
  357. PDEVICE_RELATIONS deviceRelations;
  358. PDEVICE_INFORMATION deviceInfo;
  359. PSINGLE_LIST_ENTRY deviceLink;
  360. BOOLEAN creatingRDP=FALSE,accessHW;
  361. NTSTATUS status;
  362. DebugPrint((DEBUG_PNP, "QueryDeviceRelations FDO %x\n",
  363. DeviceObject));
  364. busExtension = DeviceObject->DeviceExtension;
  365. irpSp = IoGetCurrentIrpStackLocation(Irp);
  366. #if ISOLATE_CARDS
  367. //
  368. // Only support BusRelations on PnpIsa bus PDO.
  369. //
  370. switch (irpSp->Parameters.QueryDeviceRelations.Type) {
  371. case BusRelations: {
  372. //
  373. // Isolation may have been disabled via registry key. In
  374. // that case, never enumerate an RDP.
  375. //
  376. // Note: Must return success and empty relations list
  377. // *RATHER* than just passing the irp down to accomplish
  378. // the same task due because of assumptions in the pnpres
  379. // code.
  380. //
  381. if (PipIsolationDisabled) {
  382. deviceRelations = ExAllocatePool(PagedPool,
  383. sizeof(DEVICE_RELATIONS));
  384. if (deviceRelations) {
  385. deviceRelations->Count = 0;
  386. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  387. Irp->IoStatus.Status = STATUS_SUCCESS;
  388. } else {
  389. PipCompleteRequest(Irp,STATUS_INSUFFICIENT_RESOURCES,NULL);
  390. return STATUS_INSUFFICIENT_RESOURCES;
  391. }
  392. break;
  393. }
  394. //
  395. // All relations exist on the 'root' isa bus. (don't ask)
  396. //
  397. if (busExtension->BusNumber != 0) {
  398. break;
  399. }
  400. if (PipRDPNode) {
  401. //
  402. // overload the notion of "creating" for multi-bridge systems
  403. //
  404. if (PipRDPNode->Flags & (DF_PROCESSING_RDP|DF_ACTIVATED)) {
  405. creatingRDP=TRUE;
  406. }
  407. }
  408. if (PipReadDataPort == NULL && !creatingRDP && !PipRDPNode ) {
  409. status = PipCreateReadDataPort(busExtension);
  410. if (!NT_SUCCESS(status)) {
  411. PipCompleteRequest(Irp, status, NULL);
  412. return status;
  413. }
  414. creatingRDP=TRUE;
  415. }
  416. if ((PipRDPNode && (creatingRDP) &&
  417. !(PipRDPNode->Flags & DF_ACTIVATED)) ||
  418. (PipRDPNode && (PipRDPNode->Flags & DF_REMOVED))) {
  419. deviceRelations = (PDEVICE_RELATIONS) ExAllocatePool(
  420. PagedPool,
  421. sizeof(DEVICE_RELATIONS) );
  422. if (deviceRelations) {
  423. //
  424. // If a device exists, mark it as disappeared so
  425. // it's not reported again
  426. //
  427. PipLockDeviceDatabase();
  428. deviceLink = busExtension->DeviceList.Next;
  429. while (deviceLink) {
  430. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
  431. if (!(deviceInfo->Flags & DF_READ_DATA_PORT)) {
  432. deviceInfo->Flags &= ~DF_ENUMERATED;
  433. }
  434. deviceLink = deviceInfo->DeviceList.Next;
  435. }
  436. PipUnlockDeviceDatabase();
  437. deviceRelations->Count = 1;
  438. DebugPrint((DEBUG_PNP,
  439. "QueryDeviceRelations handing back the FDO\n"));
  440. ObReferenceObject(PipRDPNode->PhysicalDeviceObject);
  441. deviceRelations->Objects[0] = PipRDPNode->PhysicalDeviceObject;
  442. (PDEVICE_RELATIONS)Irp->IoStatus.Information = deviceRelations;
  443. Irp->IoStatus.Status = STATUS_SUCCESS;
  444. break;
  445. } else {
  446. PipCompleteRequest(Irp, STATUS_INSUFFICIENT_RESOURCES,NULL);
  447. return STATUS_INSUFFICIENT_RESOURCES;
  448. }
  449. }
  450. //
  451. // Perform bus check to enumerate all the device under pnpisa bus.
  452. //
  453. PipLockDeviceDatabase();
  454. if ((PipRDPNode->Flags & (DF_ACTIVATED|DF_QUERY_STOPPED)) == DF_ACTIVATED) {
  455. accessHW = TRUE;
  456. deviceLink = busExtension->DeviceList.Next;
  457. while (deviceLink) {
  458. deviceInfo = CONTAINING_RECORD (deviceLink,
  459. DEVICE_INFORMATION,
  460. DeviceList);
  461. if (!(deviceInfo->Flags & DF_READ_DATA_PORT)) {
  462. accessHW = FALSE;
  463. DebugPrint((DEBUG_PNP,
  464. "QueryDeviceRelations: Found 1 card, no more isolation\n"));
  465. break;
  466. }
  467. deviceLink = deviceInfo->DeviceList.Next;
  468. }
  469. } else {
  470. accessHW = FALSE;
  471. }
  472. if (PipRDPNode->Flags & DF_NEEDS_RESCAN) {
  473. DebugPrint((DEBUG_PNP,
  474. "QueryDeviceRelations: Force rescan\n"));
  475. PipRDPNode->Flags &= ~DF_NEEDS_RESCAN;
  476. accessHW = TRUE;
  477. }
  478. if (accessHW) {
  479. PipCheckBus(busExtension);
  480. } else {
  481. DebugPrint((DEBUG_PNP, "QueryDeviceRelations: Using cached data\n"));
  482. }
  483. status = PipQueryDeviceRelations(
  484. busExtension,
  485. (PDEVICE_RELATIONS *)&Irp->IoStatus.Information,
  486. FALSE );
  487. PipUnlockDeviceDatabase();
  488. Irp->IoStatus.Status = status;
  489. if (!NT_SUCCESS(status)) {
  490. PipCompleteRequest(Irp, status, NULL);
  491. return status;
  492. }
  493. }
  494. break;
  495. case EjectionRelations: {
  496. if (PipRDPNode) {
  497. deviceRelations = (PDEVICE_RELATIONS) ExAllocatePool(
  498. PagedPool,
  499. sizeof(DEVICE_RELATIONS) );
  500. if (deviceRelations) {
  501. deviceRelations->Count = 1;
  502. ObReferenceObject(PipRDPNode->PhysicalDeviceObject);
  503. deviceRelations->Objects[0] = PipRDPNode->PhysicalDeviceObject;
  504. (PDEVICE_RELATIONS)Irp->IoStatus.Information = deviceRelations;
  505. Irp->IoStatus.Status = STATUS_SUCCESS;
  506. } else {
  507. PipCompleteRequest(Irp,STATUS_INSUFFICIENT_RESOURCES,NULL);
  508. return STATUS_INSUFFICIENT_RESOURCES;
  509. }
  510. }
  511. }
  512. break;
  513. }
  514. #else
  515. if (irpSp->Parameters.QueryDeviceRelations.Type == BusRelations &&
  516. busExtension->BusNumber == 0) {
  517. deviceRelations = (PDEVICE_RELATIONS) ExAllocatePool(
  518. PagedPool,
  519. sizeof(DEVICE_RELATIONS) );
  520. if (deviceRelations) {
  521. deviceRelations->Count = 0;
  522. (PDEVICE_RELATIONS)Irp->IoStatus.Information = deviceRelations;
  523. Irp->IoStatus.Status = STATUS_SUCCESS;
  524. } else {
  525. PipCompleteRequest(Irp,STATUS_INSUFFICIENT_RESOURCES,NULL);
  526. return STATUS_INSUFFICIENT_RESOURCES;
  527. }
  528. }
  529. #endif
  530. return PipPassIrp(DeviceObject, Irp);
  531. } // PiQueryDeviceRelationsFdo
  532. NTSTATUS
  533. PiRemoveFdo(
  534. IN PDEVICE_OBJECT DeviceObject,
  535. IN OUT PIRP Irp
  536. )
  537. {
  538. NTSTATUS status;
  539. PPI_BUS_EXTENSION busExtension;
  540. PSINGLE_LIST_ENTRY child;
  541. PBUS_EXTENSION_LIST busList,prevBus;
  542. USHORT count=0;
  543. DebugPrint((DEBUG_PNP,
  544. "*** Remove Device irp received FDO: %x\n",DeviceObject));
  545. busExtension = DeviceObject->DeviceExtension;
  546. //
  547. // Clear the entry in the BM. Count dropped in
  548. // Query Remove.
  549. //
  550. KeWaitForSingleObject( &IsaBusNumberLock,
  551. Executive,
  552. KernelMode,
  553. FALSE,
  554. NULL );
  555. if (!(busExtension->Flags & DF_SURPRISE_REMOVED)) {
  556. #ifdef DBG
  557. ASSERT (RtlAreBitsSet (BusNumBM,busExtension->BusNumber,1));
  558. #endif
  559. RtlClearBits (BusNumBM,busExtension->BusNumber,1);
  560. }
  561. #if ISOLATE_CARDS
  562. PipLockDeviceDatabase();
  563. //
  564. // Walk the list of children and delete them
  565. //
  566. child=PopEntryList (&busExtension->DeviceList);
  567. while (child) {
  568. ASSERT (CONTAINING_RECORD (child, DEVICE_INFORMATION,DeviceList)->PhysicalDeviceObject);
  569. //
  570. // This pulls them from the list!
  571. //
  572. count ++;
  573. if (CONTAINING_RECORD (child, DEVICE_INFORMATION,DeviceList)->Flags & DF_READ_DATA_PORT) {
  574. //
  575. // Force the recreate of the RDP
  576. //
  577. PipCleanupAcquiredResources (busExtension);
  578. PipReadDataPort = NULL;
  579. PipRDPNode = NULL;
  580. } else {
  581. PipReleaseDeviceResources ((PDEVICE_INFORMATION)child);
  582. }
  583. IoDeleteDevice (CONTAINING_RECORD (child, DEVICE_INFORMATION,DeviceList)->PhysicalDeviceObject);
  584. child=PopEntryList (&busExtension->DeviceList);
  585. }
  586. PipUnlockDeviceDatabase();
  587. #endif
  588. //
  589. // Delete this extension.
  590. //
  591. prevBus= busList = PipBusExtension;
  592. ASSERT (busList != NULL);
  593. while (busList->BusExtension != busExtension) {
  594. prevBus= busList;
  595. busList = busList->Next;
  596. ASSERT (busList != NULL);
  597. }
  598. //
  599. // Remove the node
  600. //
  601. if (prevBus == busList) {
  602. //
  603. // First Node.
  604. //
  605. PipBusExtension=busList->Next;
  606. }else {
  607. prevBus->Next = busList->Next;
  608. }
  609. ExFreePool (busList);
  610. KeSetEvent( &IsaBusNumberLock,
  611. 0,
  612. FALSE );
  613. if (count > 0 ) {
  614. //
  615. // If we STILL have an ISA bus. Do this.
  616. //
  617. if (ActiveIsaCount > 0 ) {
  618. ASSERT (PipBusExtension->BusExtension);
  619. IoInvalidateDeviceRelations (PipBusExtension->BusExtension->PhysicalBusDevice,BusRelations);
  620. }
  621. }
  622. #if ISOLATE_CARDS
  623. //
  624. // Cleanup all the resources on the last remove.
  625. //
  626. if (!(busExtension->Flags & DF_SURPRISE_REMOVED)) {
  627. PipCleanupAcquiredResources (busExtension);
  628. }
  629. #endif
  630. //
  631. // The PnpISa bus PDO is being removed...
  632. //
  633. IoDetachDevice(busExtension->AttachedDevice);
  634. Irp->IoStatus.Status=STATUS_SUCCESS;
  635. status = PipPassIrp(DeviceObject, Irp);
  636. busExtension->AttachedDevice = NULL;
  637. busExtension->Flags |= DF_DELETED;
  638. busExtension->DevicePowerState = PowerDeviceD3;
  639. IoDeleteDevice(busExtension->FunctionalBusDevice);
  640. return status;
  641. } // PiRemoveFdo
  642. NTSTATUS
  643. PiQueryLegacyBusInformationFdo(
  644. IN PDEVICE_OBJECT DeviceObject,
  645. IN OUT PIRP Irp
  646. )
  647. {
  648. PLEGACY_BUS_INFORMATION legacyBusInfo;
  649. PVOID information = NULL;
  650. PPI_BUS_EXTENSION busExtension;
  651. NTSTATUS status;
  652. busExtension = DeviceObject->DeviceExtension;
  653. legacyBusInfo = (PLEGACY_BUS_INFORMATION) ExAllocatePool(PagedPool, sizeof(LEGACY_BUS_INFORMATION));
  654. if (legacyBusInfo) {
  655. legacyBusInfo->BusTypeGuid = GUID_BUS_TYPE_ISAPNP;
  656. legacyBusInfo->LegacyBusType = Isa;
  657. legacyBusInfo->BusNumber = busExtension->BusNumber;
  658. information = legacyBusInfo;
  659. status = STATUS_SUCCESS;
  660. } else {
  661. status = STATUS_INSUFFICIENT_RESOURCES;
  662. }
  663. if (NT_SUCCESS(status)) {
  664. Irp->IoStatus.Status = status;
  665. Irp->IoStatus.Information = (ULONG_PTR) information;
  666. return PipPassIrp(DeviceObject, Irp);
  667. } else {
  668. PipCompleteRequest (Irp,status,NULL);
  669. return status;
  670. }
  671. }
  672. NTSTATUS
  673. PiQueryInterfaceFdo(
  674. IN PDEVICE_OBJECT DeviceObject,
  675. IN OUT PIRP Irp
  676. )
  677. {
  678. NTSTATUS status;
  679. PPI_BUS_EXTENSION busExtension;
  680. busExtension = DeviceObject->DeviceExtension;
  681. //
  682. // We are a FDO - check if we are being asked for an interface we
  683. // support
  684. //
  685. status = PiQueryInterface(busExtension, Irp);
  686. if (NT_SUCCESS(status)) {
  687. Irp->IoStatus.Status = status;
  688. Irp->IoStatus.Information = 0;
  689. return PipPassIrp(DeviceObject, Irp);
  690. } else if (status == STATUS_NOT_SUPPORTED) {
  691. return PipPassIrp(DeviceObject, Irp);
  692. } else {
  693. PipCompleteRequest (Irp,status,NULL);
  694. return status;
  695. }
  696. } // PiQueryInterfaceFdo
  697. NTSTATUS
  698. PiQueryPnpDeviceState(
  699. IN PDEVICE_OBJECT DeviceObject,
  700. IN OUT PIRP Irp
  701. )
  702. {
  703. PPI_BUS_EXTENSION busExtension;
  704. busExtension = DeviceObject->DeviceExtension;
  705. //
  706. // We are a FDO
  707. //
  708. (PNP_DEVICE_STATE) Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
  709. Irp->IoStatus.Status = STATUS_SUCCESS;
  710. return PipPassIrp(DeviceObject, Irp);
  711. } // PiQueryPnpDeviceState
  712. NTSTATUS
  713. PiSurpriseRemoveFdo(
  714. IN PDEVICE_OBJECT DeviceObject,
  715. IN OUT PIRP Irp
  716. )
  717. {
  718. NTSTATUS status;
  719. PPI_BUS_EXTENSION busExtension;
  720. DebugPrint((DEBUG_PNP,
  721. "*** Surprise Remove Device irp received FDO: %x\n",DeviceObject));
  722. busExtension = DeviceObject->DeviceExtension;
  723. //
  724. // Clear the entry in the BM. Count dropped in
  725. // Query Remove.
  726. //
  727. KeWaitForSingleObject( &IsaBusNumberLock,
  728. Executive,
  729. KernelMode,
  730. FALSE,
  731. NULL );
  732. #ifdef DBG
  733. ASSERT (RtlAreBitsSet (BusNumBM,busExtension->BusNumber,1));
  734. #endif
  735. RtlClearBits (BusNumBM,busExtension->BusNumber,1);
  736. KeSetEvent( &IsaBusNumberLock,
  737. 0,
  738. FALSE );
  739. #if ISOLATE_CARDS
  740. PipCleanupAcquiredResources (busExtension);
  741. #endif
  742. //
  743. // The PnpISa bus PDO is being removed...
  744. //
  745. Irp->IoStatus.Status=STATUS_SUCCESS;
  746. status = PipPassIrp(DeviceObject, Irp);
  747. busExtension->AttachedDevice = NULL;
  748. busExtension->Flags |= DF_SURPRISE_REMOVED;
  749. busExtension->DevicePowerState = PowerDeviceD3;
  750. return status;
  751. } // PiSurpriseRemoveFdo