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.

1608 lines
50 KiB

  1. /*++
  2. Copyright (c) 1990-2000 Microsoft Corporation
  3. Module Name:
  4. pdopnp.c
  5. Abstract:
  6. This file contains the PNP IRP dispatch code for PDOs
  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. #if ISOLATE_CARDS
  16. //
  17. // Function Prototypes
  18. //
  19. BOOLEAN PipFailStartPdo = FALSE;
  20. BOOLEAN PipFailStartRdp = FALSE;
  21. NTSTATUS
  22. PiStartPdo(
  23. IN PDEVICE_OBJECT DeviceObject,
  24. IN OUT PIRP Irp
  25. );
  26. NTSTATUS
  27. PiQueryRemoveStopPdo(
  28. IN PDEVICE_OBJECT DeviceObject,
  29. IN OUT PIRP Irp );
  30. NTSTATUS
  31. PiCancelRemoveStopPdo(
  32. IN PDEVICE_OBJECT DeviceObject,
  33. IN OUT PIRP Irp );
  34. NTSTATUS
  35. PiStopPdo(
  36. IN PDEVICE_OBJECT DeviceObject,
  37. IN OUT PIRP Irp
  38. );
  39. NTSTATUS
  40. PiQueryDeviceRelationsPdo(
  41. IN PDEVICE_OBJECT DeviceObject,
  42. IN OUT PIRP Irp
  43. );
  44. NTSTATUS
  45. PiQueryCapabilitiesPdo(
  46. IN PDEVICE_OBJECT DeviceObject,
  47. IN OUT PIRP Irp
  48. );
  49. NTSTATUS
  50. PiQueryDeviceTextPdo(
  51. IN PDEVICE_OBJECT DeviceObject,
  52. IN OUT PIRP Irp
  53. );
  54. NTSTATUS
  55. PiFilterResourceRequirementsPdo(
  56. IN PDEVICE_OBJECT DeviceObject,
  57. IN OUT PIRP Irp
  58. );
  59. NTSTATUS
  60. PiQueryIdPdo(
  61. IN PDEVICE_OBJECT DeviceObject,
  62. IN OUT PIRP Irp
  63. );
  64. NTSTATUS
  65. PiQueryResourcesPdo(
  66. IN PDEVICE_OBJECT DeviceObject,
  67. IN OUT PIRP Irp
  68. );
  69. NTSTATUS
  70. PiQueryResourceRequirementsPdo(
  71. IN PDEVICE_OBJECT DeviceObject,
  72. IN OUT PIRP Irp
  73. );
  74. NTSTATUS
  75. PiRemovePdo(
  76. IN PDEVICE_OBJECT DeviceObject,
  77. IN OUT PIRP Irp
  78. );
  79. NTSTATUS
  80. PiQueryBusInformationPdo(
  81. IN PDEVICE_OBJECT DeviceObject,
  82. IN OUT PIRP Irp
  83. );
  84. NTSTATUS
  85. PiQueryInterfacePdo(
  86. IN PDEVICE_OBJECT DeviceObject,
  87. IN OUT PIRP Irp
  88. );
  89. NTSTATUS
  90. PiDeviceUsageNotificationPdo(
  91. IN PDEVICE_OBJECT DeviceObject,
  92. IN OUT PIRP Irp
  93. );
  94. NTSTATUS
  95. PiSurpriseRemovePdo(
  96. IN PDEVICE_OBJECT DeviceObject,
  97. IN OUT PIRP Irp
  98. );
  99. NTSTATUS
  100. PiIrpNotSupported(
  101. IN PDEVICE_OBJECT DeviceObject,
  102. IN OUT PIRP Irp
  103. );
  104. NTSTATUS
  105. PipBuildRDPResources(
  106. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
  107. IN ULONG Flags
  108. );
  109. NTSTATUS
  110. PiQueryDeviceState(
  111. IN PDEVICE_OBJECT DeviceObject,
  112. IN OUT PIRP Irp
  113. );
  114. #ifdef ALLOC_PRAGMA
  115. #pragma alloc_text(PAGE,PiDispatchPnpPdo)
  116. #pragma alloc_text(PAGE,PiStartPdo)
  117. #pragma alloc_text(PAGE,PiQueryRemoveStopPdo)
  118. #pragma alloc_text(PAGE,PiRemovePdo)
  119. #pragma alloc_text(PAGE,PiCancelRemoveStopPdo)
  120. #pragma alloc_text(PAGE,PiStopPdo)
  121. #pragma alloc_text(PAGE,PiQueryDeviceRelationsPdo)
  122. #pragma alloc_text(PAGE,PiQueryInterfacePdo)
  123. #pragma alloc_text(PAGE,PiQueryCapabilitiesPdo)
  124. #pragma alloc_text(PAGE,PiQueryResourcesPdo)
  125. #pragma alloc_text(PAGE,PiQueryResourceRequirementsPdo)
  126. #pragma alloc_text(PAGE,PiQueryDeviceTextPdo)
  127. #pragma alloc_text(PAGE,PiFilterResourceRequirementsPdo)
  128. #pragma alloc_text(PAGE,PiSurpriseRemovePdo)
  129. #pragma alloc_text(PAGE,PiIrpNotSupported)
  130. #pragma alloc_text(PAGE,PiQueryIdPdo)
  131. #pragma alloc_text(PAGE,PiQueryBusInformationPdo)
  132. #pragma alloc_text(PAGE,PiDeviceUsageNotificationPdo)
  133. #pragma alloc_text(PAGE,PipBuildRDPResources)
  134. #pragma alloc_text(PAGE,PiQueryDeviceState)
  135. #endif
  136. //
  137. // PNP IRP Dispatch table for PDOs - This should be updated if new IRPs are added
  138. //
  139. PPI_DISPATCH PiPnpDispatchTablePdo[] = {
  140. PiStartPdo, // IRP_MN_START_DEVICE
  141. PiQueryRemoveStopPdo, // IRP_MN_QUERY_REMOVE_DEVICE
  142. PiRemovePdo, // IRP_MN_REMOVE_DEVICE
  143. PiCancelRemoveStopPdo, // IRP_MN_CANCEL_REMOVE_DEVICE
  144. PiStopPdo, // IRP_MN_STOP_DEVICE
  145. PiQueryRemoveStopPdo, // IRP_MN_QUERY_STOP_DEVICE
  146. PiCancelRemoveStopPdo, // IRP_MN_CANCEL_STOP_DEVICE
  147. PiQueryDeviceRelationsPdo, // IRP_MN_QUERY_DEVICE_RELATIONS
  148. PiQueryInterfacePdo, // IRP_MN_QUERY_INTERFACE
  149. PiQueryCapabilitiesPdo, // IRP_MN_QUERY_CAPABILITIES
  150. PiQueryResourcesPdo, // IRP_MN_QUERY_RESOURCES
  151. PiQueryResourceRequirementsPdo, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
  152. PiQueryDeviceTextPdo, // IRP_MN_QUERY_DEVICE_TEXT
  153. PiFilterResourceRequirementsPdo, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
  154. PiIrpNotSupported, // Unused
  155. PiIrpNotSupported, // IRP_MN_READ_CONFIG
  156. PiIrpNotSupported, // IRP_MN_WRITE_CONFIG
  157. PiIrpNotSupported, // IRP_MN_EJECT
  158. PiIrpNotSupported, // IRP_MN_SET_LOCK
  159. PiQueryIdPdo, // IRP_MN_QUERY_ID
  160. PiQueryDeviceState, // IRP_MN_QUERY_PNP_DEVICE_STATE
  161. PiQueryBusInformationPdo, // IRP_MN_QUERY_BUS_INFORMATION
  162. PiDeviceUsageNotificationPdo, // IRP_MN_DEVICE_USAGE_NOTIFICATION
  163. PiSurpriseRemovePdo, // IRP_MN_SURPRISE_REMOVAL
  164. PiIrpNotSupported // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  165. };
  166. NTSTATUS
  167. PiDispatchPnpPdo(
  168. IN PDEVICE_OBJECT DeviceObject,
  169. IN OUT PIRP Irp
  170. )
  171. /*++
  172. Routine Description:
  173. This routine handles IRP_MJ_PNP IRPs for PDOs.
  174. Arguments:
  175. DeviceObject - Pointer to the PDO for which this IRP applies.
  176. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  177. Return Value:
  178. NT status.
  179. --*/
  180. {
  181. PIO_STACK_LOCATION irpSp;
  182. NTSTATUS status;
  183. PVOID information = NULL;
  184. PAGED_CODE();
  185. //
  186. // Get a pointer to our stack location and take appropriate action based
  187. // on the minor function.
  188. //
  189. irpSp = IoGetCurrentIrpStackLocation(Irp);
  190. if (irpSp->MinorFunction > IRP_MN_PNP_MAXIMUM_FUNCTION) {
  191. status = Irp->IoStatus.Status;
  192. } else {
  193. status = PiPnpDispatchTablePdo[irpSp->MinorFunction](DeviceObject, Irp);
  194. if ( status != STATUS_NOT_SUPPORTED ) {
  195. //
  196. // We understood this IRP and handled it so we need to set status before completing
  197. //
  198. Irp->IoStatus.Status = status;
  199. } else {
  200. status = Irp->IoStatus.Status;
  201. }
  202. }
  203. information = (PVOID)Irp->IoStatus.Information;
  204. ASSERT(status == Irp->IoStatus.Status);
  205. PipCompleteRequest(Irp, status, information);
  206. return status;
  207. } //PipDispatchPnpPdo
  208. NTSTATUS
  209. PiStartPdo(
  210. IN PDEVICE_OBJECT DeviceObject,
  211. IN OUT PIRP Irp
  212. )
  213. {
  214. PIO_STACK_LOCATION irpSp;
  215. NTSTATUS status;
  216. PCM_RESOURCE_LIST cmResources;
  217. PDEVICE_INFORMATION deviceInfo;
  218. UNICODE_STRING unicodeString;
  219. ULONG length;
  220. POWER_STATE newPowerState;
  221. irpSp = IoGetCurrentIrpStackLocation(Irp);
  222. cmResources = irpSp->Parameters.StartDevice.AllocatedResources;
  223. if (PipDebugMask & DEBUG_PNP) {
  224. PipDumpCmResourceList(cmResources);
  225. } else if (!cmResources) {
  226. DbgPrint("StartDevice irp with empty CmResourceList\n");
  227. }
  228. DebugPrint((DEBUG_PNP,
  229. "*** StartDevice irp received PDO: %x\n",DeviceObject));
  230. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, TRUE)) {
  231. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  232. ULONG curSize,newSize;
  233. //
  234. if (PipFailStartRdp) {
  235. PipDereferenceDeviceInformation(deviceInfo, TRUE);
  236. return STATUS_UNSUCCESSFUL;
  237. }
  238. // Read data port is special
  239. //
  240. newSize=PipDetermineResourceListSize(cmResources);
  241. curSize=PipDetermineResourceListSize(deviceInfo->AllocatedResources);
  242. //
  243. // Check if we've been removed, or moved (the +3 is the bit mask for the RDP , we claim 4-7, need xxxi7)
  244. //
  245. if ( (deviceInfo->Flags & DF_REMOVED) ||
  246. !(deviceInfo->Flags & DF_STOPPED) ||
  247. (curSize != newSize) ||
  248. (newSize != RtlCompareMemory (deviceInfo->AllocatedResources,cmResources,newSize))) {
  249. //
  250. // This will release the unused resources
  251. //
  252. status = PipStartReadDataPort (deviceInfo,deviceInfo->ParentDeviceExtension,DeviceObject,cmResources);
  253. if (NT_SUCCESS(status) || status == STATUS_NO_SUCH_DEVICE) {
  254. status = STATUS_SUCCESS;
  255. }
  256. //
  257. // Invalidate the device relations
  258. //
  259. if (NT_SUCCESS (status)) {
  260. IoInvalidateDeviceRelations (
  261. deviceInfo->ParentDeviceExtension->PhysicalBusDevice,BusRelations);
  262. }
  263. deviceInfo->Flags &= ~(DF_STOPPED|DF_REMOVED|DF_SURPRISE_REMOVED);
  264. } else {
  265. deviceInfo->Flags &= ~DF_STOPPED;
  266. IoInvalidateDeviceRelations (
  267. deviceInfo->ParentDeviceExtension->PhysicalBusDevice,BusRelations);
  268. status=STATUS_SUCCESS;
  269. }
  270. deviceInfo->Flags |= DF_ACTIVATED;
  271. PipDereferenceDeviceInformation(deviceInfo, TRUE);
  272. DebugPrint((DEBUG_PNP, "StartDevice(RDP) returning: %x\n",status));
  273. return status;
  274. }
  275. //
  276. if (PipFailStartPdo) {
  277. PipDereferenceDeviceInformation(deviceInfo, TRUE);
  278. return STATUS_UNSUCCESSFUL;
  279. }
  280. // Do this first, so that we allow for no-resource devices in the ref count.
  281. // (when we activate the RDP it won't have resources, yet)
  282. //
  283. // ASSERT (!(PipRDPNode->Flags & (DF_STOPPED|DF_REMOVED)));
  284. if (PipRDPNode->Flags & (DF_STOPPED|DF_REMOVED)) {
  285. //
  286. // If the RDP isn't running, fail the start.
  287. //
  288. PipDereferenceDeviceInformation(deviceInfo, TRUE);
  289. return STATUS_UNSUCCESSFUL;
  290. }
  291. if (cmResources) {
  292. deviceInfo->AllocatedResources = ExAllocatePool(
  293. NonPagedPool,
  294. PipDetermineResourceListSize(cmResources));
  295. if (deviceInfo->AllocatedResources) {
  296. RtlMoveMemory(deviceInfo->AllocatedResources,
  297. cmResources,
  298. length = PipDetermineResourceListSize(cmResources));
  299. deviceInfo->Flags &= ~(DF_REMOVED|DF_STOPPED);
  300. status = PipSetDeviceResources (deviceInfo, cmResources);
  301. if (NT_SUCCESS(status)) {
  302. PipActivateDevice();
  303. DebugPrint((DEBUG_STATE,
  304. "Starting CSN %d/LDN %d\n",
  305. deviceInfo->CardInformation->CardSelectNumber,
  306. deviceInfo->LogicalDeviceNumber));
  307. deviceInfo->Flags |= DF_ACTIVATED;
  308. newPowerState.DeviceState =
  309. deviceInfo->DevicePowerState = PowerDeviceD0;
  310. PoSetPowerState(DeviceObject,
  311. DevicePowerState,
  312. newPowerState);
  313. deviceInfo->DevicePowerState = PowerDeviceD0;
  314. if (deviceInfo->LogConfHandle) {
  315. RtlInitUnicodeString(&unicodeString, L"AllocConfig");
  316. ZwSetValueKey(deviceInfo->LogConfHandle,
  317. &unicodeString,
  318. 0,
  319. REG_RESOURCE_LIST,
  320. cmResources,
  321. length
  322. );
  323. }
  324. }
  325. } else {
  326. status = STATUS_NO_MEMORY;
  327. }
  328. } else if (deviceInfo->ResourceRequirements) {
  329. status = STATUS_INSUFFICIENT_RESOURCES;
  330. } else {
  331. status = STATUS_SUCCESS;
  332. }
  333. PipDereferenceDeviceInformation(deviceInfo, TRUE);
  334. } else {
  335. status = STATUS_NO_SUCH_DEVICE;
  336. }
  337. DebugPrint((DEBUG_PNP, "StartDevice returning: %x\n",status));
  338. return status;
  339. } // PiStartPdo
  340. NTSTATUS
  341. PiQueryRemoveStopPdo(
  342. IN PDEVICE_OBJECT DeviceObject,
  343. IN OUT PIRP Irp
  344. )
  345. {
  346. NTSTATUS status;
  347. PDEVICE_INFORMATION deviceInfo;
  348. PIO_STACK_LOCATION irpSp;
  349. irpSp = IoGetCurrentIrpStackLocation(Irp);
  350. DebugPrint((DEBUG_PNP,
  351. "*** Query%s irp received PDO: %x\n",
  352. (irpSp->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) ? "Stop" : "Remove",
  353. DeviceObject));
  354. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  355. if (deviceInfo->Paging || deviceInfo->CrashDump) {
  356. status = STATUS_DEVICE_BUSY;
  357. } else if ( deviceInfo->Flags & DF_READ_DATA_PORT ) {
  358. if (irpSp->MinorFunction != IRP_MN_QUERY_STOP_DEVICE) {
  359. status = STATUS_SUCCESS;
  360. } else if (deviceInfo->Flags & DF_PROCESSING_RDP) {
  361. //
  362. // If we're in the middle of the two part RDP start process,
  363. // flag this as a device that needs to be requeried for
  364. // resource requirements.
  365. //
  366. status = STATUS_RESOURCE_REQUIREMENTS_CHANGED;
  367. } else {
  368. PSINGLE_LIST_ENTRY deviceLink;
  369. PDEVICE_INFORMATION childDeviceInfo;
  370. PPI_BUS_EXTENSION busExtension = deviceInfo->ParentDeviceExtension;
  371. //
  372. // If trying to stop the RDP, then if any children fail it.
  373. //
  374. PipLockDeviceDatabase();
  375. status = STATUS_SUCCESS;
  376. deviceLink = busExtension->DeviceList.Next;
  377. while (deviceLink) {
  378. childDeviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
  379. if (!(childDeviceInfo->Flags & DF_READ_DATA_PORT) &&
  380. ((childDeviceInfo->Flags & DF_ENUMERATED) ||
  381. !(childDeviceInfo->Flags & DF_REMOVED))) {
  382. status = STATUS_UNSUCCESSFUL;
  383. break;
  384. }
  385. deviceLink = childDeviceInfo->DeviceList.Next;
  386. }
  387. PipUnlockDeviceDatabase();
  388. }
  389. } else {
  390. if ((irpSp->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) &&
  391. !(deviceInfo->Flags & DF_ENUMERATED)) {
  392. status = STATUS_UNSUCCESSFUL;
  393. } else {
  394. ASSERT(!(PipRDPNode->Flags & (DF_STOPPED|DF_REMOVED)));
  395. if ((irpSp->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE) &&
  396. (deviceInfo->CardInformation->CardFlags & CF_ISOLATION_BROKEN)) {
  397. DebugPrint((DEBUG_ERROR, "Failed query remove due to broken isolatee\n"));
  398. status = STATUS_UNSUCCESSFUL;
  399. } else {
  400. deviceInfo->Flags |= DF_QUERY_STOPPED;
  401. status = STATUS_SUCCESS;
  402. }
  403. }
  404. }
  405. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  406. } else {
  407. status = STATUS_NO_SUCH_DEVICE;
  408. }
  409. DebugPrint((DEBUG_PNP, "Query%s Device returning: %x\n",
  410. (irpSp->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) ? "Stop" : "Remove",
  411. status));
  412. return status;
  413. } // PiQueryRemoveStopPdo
  414. NTSTATUS
  415. PiCancelRemoveStopPdo(
  416. IN PDEVICE_OBJECT DeviceObject,
  417. IN OUT PIRP Irp
  418. )
  419. {
  420. NTSTATUS status;
  421. PDEVICE_INFORMATION deviceInfo;
  422. PIO_STACK_LOCATION irpSp;
  423. irpSp = IoGetCurrentIrpStackLocation(Irp);
  424. DebugPrint((DEBUG_PNP,
  425. "*** Cancel%s irp received PDO: %x\n",
  426. (irpSp->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) ? "Stop" : "Remove",
  427. DeviceObject));
  428. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  429. deviceInfo->Flags &= ~DF_QUERY_STOPPED;
  430. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  431. status = STATUS_SUCCESS;
  432. } else {
  433. status = STATUS_NO_SUCH_DEVICE;
  434. }
  435. DebugPrint((DEBUG_PNP, "Cancel%s Device returning: %x\n",
  436. (irpSp->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) ? "Stop" : "Remove",
  437. status));
  438. return status;
  439. } // PiCancelRemoteStopPdo
  440. NTSTATUS
  441. PiStopPdo(
  442. IN PDEVICE_OBJECT DeviceObject,
  443. IN OUT PIRP Irp
  444. )
  445. {
  446. NTSTATUS status;
  447. PDEVICE_INFORMATION deviceInfo;
  448. POWER_STATE newPowerState;
  449. DebugPrint((DEBUG_PNP, "PiStopPdo %x\n",DeviceObject));
  450. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, TRUE)) {
  451. //
  452. // Deselect the cards, but not the RDP node.
  453. //
  454. if (DeviceObject != PipRDPNode->PhysicalDeviceObject) {
  455. PipDeactivateDevice();
  456. DebugPrint((DEBUG_STATE,
  457. "Stopping CSN %d/LDN %d\n",
  458. deviceInfo->CardInformation->CardSelectNumber,
  459. deviceInfo->LogicalDeviceNumber));
  460. PipReleaseDeviceResources (deviceInfo);
  461. }
  462. if ((deviceInfo->Flags & DF_ACTIVATED)) {
  463. deviceInfo->Flags &= ~DF_ACTIVATED;
  464. newPowerState.DeviceState = deviceInfo->DevicePowerState = PowerDeviceD3;
  465. PoSetPowerState(DeviceObject, DevicePowerState, newPowerState);
  466. }
  467. deviceInfo->Flags &= ~DF_QUERY_STOPPED;
  468. deviceInfo->Flags |= DF_STOPPED;
  469. PipDereferenceDeviceInformation(deviceInfo, TRUE);
  470. status = STATUS_SUCCESS;
  471. } else {
  472. status = STATUS_NO_SUCH_DEVICE;
  473. }
  474. DebugPrint((DEBUG_PNP, "StopDevice returning: %x\n",status));
  475. return status;
  476. } // PiStopPdo
  477. NTSTATUS
  478. PiQueryDeviceRelationsPdo(
  479. IN PDEVICE_OBJECT DeviceObject,
  480. IN OUT PIRP Irp
  481. )
  482. {
  483. NTSTATUS status;
  484. PDEVICE_INFORMATION deviceInfo;
  485. PIO_STACK_LOCATION irpSp;
  486. irpSp = IoGetCurrentIrpStackLocation(Irp);
  487. //
  488. // The QueryDeviceRelation Irp is for devices under enumerated PnpIsa device.
  489. //
  490. switch (irpSp->Parameters.QueryDeviceRelations.Type) {
  491. case TargetDeviceRelation: {
  492. PDEVICE_RELATIONS deviceRelations;
  493. deviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
  494. if (deviceRelations == NULL) {
  495. status = STATUS_INSUFFICIENT_RESOURCES;
  496. } else {
  497. deviceRelations->Count = 1;
  498. deviceRelations->Objects[0] = DeviceObject;
  499. ObReferenceObject(DeviceObject);
  500. Irp->IoStatus.Information = (ULONG_PTR)deviceRelations;
  501. status = STATUS_SUCCESS;
  502. }
  503. }
  504. break;
  505. case RemovalRelations: {
  506. PDEVICE_RELATIONS deviceRelations;
  507. if (PipRDPNode && (DeviceObject == PipRDPNode->PhysicalDeviceObject)) {
  508. deviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
  509. if (deviceRelations == NULL) {
  510. status = STATUS_INSUFFICIENT_RESOURCES;
  511. } else {
  512. //
  513. //Don't include ourselves in the list of Removal Relations, hence the -1
  514. //
  515. PipLockDeviceDatabase();
  516. status = PipQueryDeviceRelations(
  517. PipRDPNode->ParentDeviceExtension,
  518. (PDEVICE_RELATIONS *)&Irp->IoStatus.Information,
  519. TRUE
  520. );
  521. PipUnlockDeviceDatabase();
  522. }
  523. } else {
  524. status = STATUS_NOT_SUPPORTED;
  525. }
  526. }
  527. break;
  528. default : {
  529. status = STATUS_NOT_SUPPORTED;
  530. break;
  531. }
  532. }
  533. return status;
  534. } // PiQueryDeviceRelationsPdo
  535. NTSTATUS
  536. PiQueryCapabilitiesPdo(
  537. IN PDEVICE_OBJECT DeviceObject,
  538. IN OUT PIRP Irp
  539. )
  540. {
  541. NTSTATUS status;
  542. PIO_STACK_LOCATION irpSp;
  543. PDEVICE_CAPABILITIES deviceCapabilities;
  544. ULONG i;
  545. PDEVICE_POWER_STATE state;
  546. irpSp = IoGetCurrentIrpStackLocation(Irp);
  547. deviceCapabilities = irpSp->Parameters.DeviceCapabilities.Capabilities;
  548. deviceCapabilities->SystemWake = PowerSystemUnspecified;
  549. deviceCapabilities->DeviceWake = PowerDeviceUnspecified;
  550. deviceCapabilities->LockSupported = FALSE;
  551. deviceCapabilities->EjectSupported = FALSE;
  552. deviceCapabilities->Removable = FALSE;
  553. deviceCapabilities->DockDevice = FALSE;
  554. deviceCapabilities->UniqueID = TRUE;
  555. state = deviceCapabilities->DeviceState;
  556. //
  557. // Init the entire DeviceState array to D3 then replace the entry
  558. // for system state S0.
  559. //
  560. for (i = 0;
  561. i < sizeof(deviceCapabilities->DeviceState);
  562. i += sizeof(deviceCapabilities->DeviceState[0])) {
  563. //
  564. // Only supported state, currently, is off.
  565. //
  566. *state++ = PowerDeviceD3;
  567. }
  568. deviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
  569. //deviceCapabilities->SilentInstall = TRUE;
  570. //deviceCapabilities->RawDeviceOK = FALSE;
  571. if (PipRDPNode && (PipRDPNode->PhysicalDeviceObject == DeviceObject)) {
  572. deviceCapabilities->SilentInstall = TRUE;
  573. deviceCapabilities->RawDeviceOK = TRUE;
  574. }
  575. return STATUS_SUCCESS;
  576. } // PiQueryCapabilitiesPdo
  577. NTSTATUS
  578. PiQueryDeviceTextPdo(
  579. IN PDEVICE_OBJECT DeviceObject,
  580. IN OUT PIRP Irp
  581. )
  582. {
  583. NTSTATUS status;
  584. PIO_STACK_LOCATION irpSp;
  585. PDEVICE_INFORMATION deviceInfo;
  586. irpSp = IoGetCurrentIrpStackLocation(Irp);
  587. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  588. PWSTR functionId;
  589. ULONG functionIdLength;
  590. if (irpSp->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) {
  591. //
  592. // Once we know we're going to touch the IRP
  593. //
  594. status = STATUS_SUCCESS;
  595. PipGetFunctionIdentifier((PUCHAR)deviceInfo->DeviceData,
  596. &functionId,
  597. &functionIdLength);
  598. if (!functionId) {
  599. if (deviceInfo->CardInformation) {
  600. PipGetCardIdentifier((PUCHAR)deviceInfo->CardInformation->CardData + NUMBER_CARD_ID_BYTES,
  601. &functionId,
  602. &functionIdLength);
  603. }else {
  604. functionId=NULL;
  605. }
  606. }
  607. Irp->IoStatus.Information = (ULONG_PTR)functionId;
  608. } else {
  609. status = STATUS_NOT_SUPPORTED;
  610. }
  611. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  612. } else {
  613. status = STATUS_NO_SUCH_DEVICE;
  614. }
  615. return status;
  616. } // PiQueryDeviceTextPdo
  617. NTSTATUS
  618. PiFilterResourceRequirementsPdo(
  619. IN PDEVICE_OBJECT DeviceObject,
  620. IN OUT PIRP Irp
  621. )
  622. /*++
  623. Routine Description:
  624. This routine ensures that the RDP doesn't get its requirements filtered.
  625. Design Note:
  626. This code may now be extraneous now that we ensure that the
  627. DF_PROCESSING_RDP and DF_REQ_TRIMMED flags are cleared on RDP
  628. removal.
  629. Arguments:
  630. DeviceObject - Pointer to the PDO for which this IRP applies.
  631. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  632. Return Value:
  633. NT status.
  634. --*/
  635. {
  636. NTSTATUS status;
  637. PDEVICE_INFORMATION deviceInfo;
  638. PIO_RESOURCE_REQUIREMENTS_LIST IoResources;
  639. USHORT irqBootFlags;
  640. if ((deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) == NULL) {
  641. return STATUS_NO_SUCH_DEVICE;
  642. }
  643. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  644. DebugPrint((DEBUG_PNP, "Filtering resource requirements for RDP\n"));
  645. status = PipBuildRDPResources(&IoResources, deviceInfo->Flags);
  646. if (NT_SUCCESS(status)) {
  647. //
  648. // if someone above us filtered the RDP resource requirements,
  649. // free them.
  650. if (Irp->IoStatus.Information) {
  651. ExFreePool((PVOID) Irp->IoStatus.Information);
  652. }
  653. Irp->IoStatus.Information = (ULONG_PTR) IoResources;
  654. }
  655. } else {
  656. //
  657. // If the device's resource requirements are being filtered
  658. // and the new requirements have only one alternative vs the n
  659. // alternatives of the original, then we're going to assume we
  660. // are receiving a force config. Apply our earlier derived
  661. // IRQ level/edge settings to this force config in order to
  662. // deal with broken force configs from NT4
  663. //
  664. // Design Note:
  665. // Probably should've left out the force config test
  666. // and done it on everything, but this is what we private
  667. // tested.
  668. IoResources =
  669. (PIO_RESOURCE_REQUIREMENTS_LIST) Irp->IoStatus.Information;
  670. if (IoResources &&
  671. (IoResources->AlternativeLists == 1) &&
  672. (deviceInfo->ResourceRequirements->AlternativeLists > 1)) {
  673. status = PipGetBootIrqFlags(deviceInfo, &irqBootFlags);
  674. if (NT_SUCCESS(status)) {
  675. status = PipTrimResourceRequirements(
  676. &IoResources,
  677. irqBootFlags,
  678. NULL);
  679. Irp->IoStatus.Information = (ULONG_PTR) IoResources;
  680. } else {
  681. status = STATUS_NOT_SUPPORTED;
  682. }
  683. } else {
  684. status = STATUS_NOT_SUPPORTED;
  685. }
  686. }
  687. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  688. return status;
  689. }
  690. NTSTATUS
  691. PiQueryIdPdo(
  692. IN PDEVICE_OBJECT DeviceObject,
  693. IN OUT PIRP Irp
  694. )
  695. {
  696. NTSTATUS status;
  697. PIO_STACK_LOCATION irpSp;
  698. PDEVICE_INFORMATION deviceInfo;
  699. ULONG length;
  700. PWCHAR requestId = NULL, ids;
  701. irpSp = IoGetCurrentIrpStackLocation(Irp);
  702. if ((deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) == NULL) {
  703. status = STATUS_NO_SUCH_DEVICE;
  704. return status;
  705. }
  706. switch (irpSp->Parameters.QueryId.IdType) {
  707. case BusQueryCompatibleIDs:
  708. ids = (PWCHAR)ExAllocatePool(PagedPool, 1024);
  709. if (ids) {
  710. PWCHAR p1;
  711. ULONG i;
  712. p1 = ids;
  713. length = 0;
  714. for (i = 1; TRUE; i++) {
  715. //
  716. // Use the -1 as a sentinel so that we get the magic RDP compat. ID and also leave the loop
  717. //
  718. ASSERT (i < 256);
  719. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  720. i =-1;
  721. }
  722. status = PipGetCompatibleDeviceId(
  723. deviceInfo->DeviceData,
  724. i,
  725. &requestId);
  726. if (NT_SUCCESS(status) && requestId) {
  727. if ((length + wcslen(requestId) * sizeof(WCHAR) + 2 * sizeof(WCHAR))
  728. <= 1024) {
  729. RtlMoveMemory(p1, requestId, wcslen(requestId) * sizeof(WCHAR));
  730. p1 += wcslen(requestId);
  731. *p1 = UNICODE_NULL;
  732. p1++;
  733. length += wcslen(requestId) * sizeof(WCHAR) + sizeof(WCHAR);
  734. ExFreePool(requestId);
  735. } else {
  736. ExFreePool(requestId);
  737. break;
  738. }
  739. if ( i == -1 ) {
  740. break;
  741. }
  742. } else {
  743. break;
  744. }
  745. }
  746. if (length == 0) {
  747. ExFreePool(ids);
  748. ids = NULL;
  749. } else {
  750. *p1 = UNICODE_NULL;
  751. }
  752. }
  753. Irp->IoStatus.Information = (ULONG_PTR)ids;
  754. status = STATUS_SUCCESS;
  755. break;
  756. case BusQueryHardwareIDs:
  757. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  758. status = PipGetCompatibleDeviceId(deviceInfo->DeviceData, -1, &requestId);
  759. }else {
  760. status = PipGetCompatibleDeviceId(deviceInfo->DeviceData, 0, &requestId);
  761. }
  762. if (NT_SUCCESS(status) && requestId) {
  763. ULONG idLength, deviceIdLength;
  764. PWCHAR deviceId = NULL, p;
  765. //
  766. // create HardwareId value name. Even though it is a MULTI_SZ,
  767. // we know there is only one HardwareId for PnpIsa.
  768. //
  769. // HACK - The modem inf files use the form of isapnp\xyz0001
  770. // instead of *xyz0001 as the hardware id. To solve this
  771. // problem we will generate two hardware Ids: *xyz0001 and
  772. // isapnp\xyz0001 (device instance name).
  773. //
  774. status = PipQueryDeviceId(deviceInfo, &deviceId, 0);
  775. if (NT_SUCCESS (status)) {
  776. idLength = wcslen(requestId) * sizeof(WCHAR);
  777. deviceIdLength = wcslen(deviceId) * sizeof(WCHAR);
  778. length = idLength + // returned ID
  779. sizeof(WCHAR) + // UNICODE_NULL
  780. deviceIdLength + // isapnp\id
  781. 2 * sizeof(WCHAR); // two UNICODE_NULLs
  782. ids = p = (PWCHAR)ExAllocatePool(PagedPool, length);
  783. if (ids) {
  784. RtlMoveMemory(ids, deviceId, deviceIdLength);
  785. p += deviceIdLength / sizeof(WCHAR);
  786. *p = UNICODE_NULL;
  787. p++;
  788. RtlMoveMemory(p, requestId, idLength);
  789. p += idLength / sizeof(WCHAR);
  790. *p = UNICODE_NULL;
  791. p++;
  792. *p = UNICODE_NULL;
  793. ExFreePool(requestId);
  794. Irp->IoStatus.Information = (ULONG_PTR)ids;
  795. } else {
  796. Irp->IoStatus.Information = (ULONG_PTR)requestId;
  797. }
  798. if (deviceId) {
  799. ExFreePool(deviceId);
  800. }
  801. }
  802. }
  803. break;
  804. case BusQueryDeviceID:
  805. status = PipQueryDeviceId(deviceInfo, &requestId, 0);
  806. Irp->IoStatus.Information = (ULONG_PTR)requestId;
  807. break;
  808. case BusQueryInstanceID:
  809. status = PipQueryDeviceUniqueId (deviceInfo, &requestId);
  810. Irp->IoStatus.Information = (ULONG_PTR)requestId;
  811. break;
  812. default:
  813. status = STATUS_NOT_SUPPORTED;
  814. }
  815. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  816. return status;
  817. } // PiQueryIdPdo
  818. NTSTATUS
  819. PiQueryResourcesPdo(
  820. IN PDEVICE_OBJECT DeviceObject,
  821. IN OUT PIRP Irp
  822. )
  823. {
  824. NTSTATUS status=STATUS_SUCCESS;
  825. PDEVICE_INFORMATION deviceInfo;
  826. PCM_RESOURCE_LIST cmResources=NULL;
  827. ULONG length;
  828. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  829. if ((deviceInfo->Flags & DF_READ_DATA_PORT) ||
  830. ((deviceInfo->Flags & (DF_ENUMERATED|DF_REMOVED)) == DF_ENUMERATED)) {
  831. status = PipQueryDeviceResources (
  832. deviceInfo,
  833. 0, // BusNumber
  834. &cmResources,
  835. &length
  836. );
  837. }
  838. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  839. Irp->IoStatus.Information = (ULONG_PTR)cmResources;
  840. } else {
  841. status = STATUS_NO_SUCH_DEVICE;
  842. }
  843. DebugPrint((DEBUG_PNP, "PiQueryResourcesPdo returning: %x\n",status));
  844. return status;
  845. } // PiQueryResourcesPdo
  846. NTSTATUS
  847. PiQueryResourceRequirementsPdo(
  848. IN PDEVICE_OBJECT DeviceObject,
  849. IN OUT PIRP Irp
  850. )
  851. {
  852. NTSTATUS status;
  853. PDEVICE_INFORMATION deviceInfo;
  854. PIO_RESOURCE_REQUIREMENTS_LIST ioResources;
  855. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  856. status = STATUS_SUCCESS;
  857. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  858. status = PipBuildRDPResources (&ioResources,
  859. deviceInfo->Flags);
  860. } else {
  861. if (deviceInfo->ResourceRequirements &&
  862. !(deviceInfo->Flags & (DF_SURPRISE_REMOVED))) {
  863. ioResources = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool (
  864. PagedPool, deviceInfo->ResourceRequirements->ListSize);
  865. if (ioResources == NULL) {
  866. status = STATUS_INSUFFICIENT_RESOURCES;
  867. } else {
  868. RtlMoveMemory(ioResources,
  869. deviceInfo->ResourceRequirements,
  870. deviceInfo->ResourceRequirements->ListSize
  871. );
  872. }
  873. } else {
  874. ioResources = NULL;
  875. }
  876. }
  877. Irp->IoStatus.Information = (ULONG_PTR)ioResources;
  878. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  879. } else {
  880. status = STATUS_NO_SUCH_DEVICE;
  881. }
  882. DebugPrint((DEBUG_PNP, "PiQueryResourceRequirementsPdo returning: %x\n",status));
  883. return status;
  884. } // PiQueryResourceRequirementsPdo
  885. NTSTATUS
  886. PiRemovePdo(
  887. IN PDEVICE_OBJECT DeviceObject,
  888. IN OUT PIRP Irp
  889. )
  890. {
  891. NTSTATUS status;
  892. PDEVICE_INFORMATION deviceInfo;
  893. POWER_STATE newPowerState;
  894. //
  895. // One of our enumerated device is being removed. Mark it and deactivate the
  896. // device. Note, we do NOT delete its device object.
  897. //
  898. DebugPrint((DEBUG_PNP, "PiRemovePdo %x\n",DeviceObject));
  899. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  900. if (!(deviceInfo->Flags & (DF_REMOVED|DF_SURPRISE_REMOVED))) {
  901. deviceInfo->Flags |= DF_REMOVED;
  902. deviceInfo->Flags &= ~DF_QUERY_STOPPED;
  903. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  904. PSINGLE_LIST_ENTRY deviceLink;
  905. PPI_BUS_EXTENSION busExtension = deviceInfo->ParentDeviceExtension;
  906. //
  907. // If the RDP is removed, mark everyone as missing, and then return only the
  908. // RDP
  909. //
  910. PipLockDeviceDatabase();
  911. deviceLink = busExtension->DeviceList.Next;
  912. while (deviceLink) {
  913. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
  914. if (!(deviceInfo->Flags & DF_READ_DATA_PORT)) {
  915. deviceInfo->Flags &= ~DF_ENUMERATED;
  916. }
  917. deviceLink = deviceInfo->DeviceList.Next;
  918. }
  919. PipUnlockDeviceDatabase();
  920. IoInvalidateDeviceRelations (
  921. deviceInfo->ParentDeviceExtension->PhysicalBusDevice,BusRelations);
  922. deviceInfo->Flags &= ~(DF_REQ_TRIMMED|DF_PROCESSING_RDP);
  923. }
  924. //
  925. // Deactivate the device
  926. //
  927. if (deviceInfo->Flags & DF_ACTIVATED) {
  928. deviceInfo->Flags &= ~DF_ACTIVATED;
  929. if (!(deviceInfo->Flags & (DF_READ_DATA_PORT|DF_NOT_FUNCTIONING))) {
  930. PipWakeAndSelectDevice(
  931. (UCHAR) deviceInfo->CardInformation->CardSelectNumber,
  932. (UCHAR)deviceInfo->LogicalDeviceNumber);
  933. PipDeactivateDevice();
  934. PipWaitForKey();
  935. DebugPrint((DEBUG_STATE,
  936. "Removing CSN %d/LDN %d\n",
  937. deviceInfo->CardInformation->CardSelectNumber,
  938. deviceInfo->LogicalDeviceNumber));
  939. }
  940. newPowerState.DeviceState = deviceInfo->DevicePowerState = PowerDeviceD3;
  941. PoSetPowerState(DeviceObject, DevicePowerState, newPowerState);
  942. }
  943. PipReleaseDeviceResources (deviceInfo);
  944. }
  945. if (!(deviceInfo->Flags & DF_ENUMERATED)) {
  946. PipDeleteDevice(DeviceObject);
  947. }
  948. PipDereferenceDeviceInformation(deviceInfo, TRUE);
  949. status = STATUS_SUCCESS;
  950. } else {
  951. status = STATUS_NO_SUCH_DEVICE;
  952. }
  953. DebugPrint((DEBUG_PNP, "RemoveDevice returning: %x\n",status));
  954. return status;
  955. } // PiRemovePdo
  956. NTSTATUS
  957. PiQueryBusInformationPdo(
  958. IN PDEVICE_OBJECT DeviceObject,
  959. IN OUT PIRP Irp
  960. )
  961. {
  962. PPNP_BUS_INFORMATION pnpBusInfo;
  963. PVOID information = NULL;
  964. PPI_BUS_EXTENSION busExtension;
  965. NTSTATUS status;
  966. busExtension = DeviceObject->DeviceExtension;
  967. pnpBusInfo = (PPNP_BUS_INFORMATION) ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
  968. if (pnpBusInfo) {
  969. pnpBusInfo->BusTypeGuid = GUID_BUS_TYPE_ISAPNP;
  970. pnpBusInfo->LegacyBusType = Isa;
  971. pnpBusInfo->BusNumber = busExtension->BusNumber;
  972. information = pnpBusInfo;
  973. status = STATUS_SUCCESS;
  974. } else {
  975. status = STATUS_INSUFFICIENT_RESOURCES;
  976. information = NULL;
  977. }
  978. Irp->IoStatus.Information = (ULONG_PTR) information;
  979. return status;
  980. } // PiQueryBusInformationPdo
  981. NTSTATUS
  982. PiDeviceUsageNotificationPdo(
  983. IN PDEVICE_OBJECT DeviceObject,
  984. IN OUT PIRP Irp
  985. )
  986. /*++
  987. Routine Description:
  988. This routine notes whether an ISAPNP device is on the crashdump or
  989. paging file path. It fails attempts to put us on the hibernation path.
  990. Arguments:
  991. DeviceObject - Pointer to the PDO for which this IRP applies.
  992. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  993. Return Value:
  994. NT status.
  995. --*/
  996. {
  997. PDEVICE_INFORMATION deviceInfo;
  998. PIO_STACK_LOCATION irpSp;
  999. PLONG addend;
  1000. NTSTATUS status = STATUS_SUCCESS;
  1001. irpSp = IoGetCurrentIrpStackLocation(Irp);
  1002. if ((deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) == NULL) {
  1003. status = STATUS_NO_SUCH_DEVICE;
  1004. return status;
  1005. }
  1006. DebugPrint((DEBUG_PNP, "DeviceUsage CSN %d/LSN %d: InPath %s Type %d\n",
  1007. deviceInfo->CardInformation->CardSelectNumber,
  1008. deviceInfo->LogicalDeviceNumber,
  1009. irpSp->Parameters.UsageNotification.InPath ? "TRUE" : "FALSE",
  1010. irpSp->Parameters.UsageNotification.Type));
  1011. switch (irpSp->Parameters.UsageNotification.Type) {
  1012. case DeviceUsageTypePaging:
  1013. addend = &deviceInfo->Paging;
  1014. break;
  1015. case DeviceUsageTypeHibernation:
  1016. status = STATUS_DEVICE_BUSY;
  1017. break;
  1018. case DeviceUsageTypeDumpFile:
  1019. addend = &deviceInfo->CrashDump;
  1020. break;
  1021. default:
  1022. status = STATUS_NOT_SUPPORTED;
  1023. }
  1024. if (status == STATUS_SUCCESS) {
  1025. if (irpSp->Parameters.UsageNotification.InPath) {
  1026. //
  1027. // Turn on broken isolation flag which causes QDR
  1028. // to use the cache instead of beating on the hardware if
  1029. // we're on the paging or crashdump paths. Some
  1030. // hardware appears unhappy during QDR and causes problems when
  1031. // we take a page fault in this routine.
  1032. //
  1033. deviceInfo->CardInformation->CardFlags |= CF_ISOLATION_BROKEN;
  1034. (*addend)++;
  1035. IoInvalidateDeviceState(DeviceObject);
  1036. }
  1037. else {
  1038. (*addend)--;
  1039. }
  1040. }
  1041. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  1042. return status;
  1043. }
  1044. NTSTATUS
  1045. PiQueryInterfacePdo(
  1046. IN PDEVICE_OBJECT DeviceObject,
  1047. IN OUT PIRP Irp
  1048. )
  1049. {
  1050. UNREFERENCED_PARAMETER(DeviceObject);
  1051. UNREFERENCED_PARAMETER(Irp);
  1052. return STATUS_NOT_SUPPORTED;
  1053. } // PiQueryInterfacePdo
  1054. NTSTATUS
  1055. PiSurpriseRemovePdo(
  1056. IN PDEVICE_OBJECT DeviceObject,
  1057. IN OUT PIRP Irp
  1058. )
  1059. {
  1060. NTSTATUS status;
  1061. PDEVICE_INFORMATION deviceInfo;
  1062. PSINGLE_LIST_ENTRY deviceLink;
  1063. DebugPrint((DEBUG_PNP, "SurpriseRemove PDO %x\n", DeviceObject));
  1064. //
  1065. // One of our enumerated device is being removed. Mark it and deactivate the
  1066. // device. Note, we do NOT delete its device object.
  1067. //
  1068. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  1069. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  1070. //
  1071. // If the RDP is removed, mark everyone as missing, and then return only the
  1072. // RDP
  1073. //
  1074. PipLockDeviceDatabase();
  1075. deviceLink = deviceInfo->ParentDeviceExtension->DeviceList.Next;
  1076. while (deviceLink) {
  1077. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
  1078. if (!(deviceInfo->Flags & DF_READ_DATA_PORT)) {
  1079. deviceInfo->Flags &= ~DF_ENUMERATED;
  1080. }
  1081. deviceLink = deviceInfo->DeviceList.Next;
  1082. }
  1083. PipUnlockDeviceDatabase();
  1084. IoInvalidateDeviceRelations (
  1085. deviceInfo->ParentDeviceExtension->PhysicalBusDevice,BusRelations);
  1086. } else {
  1087. DebugPrint((DEBUG_STATE,
  1088. "Surprise removing CSN %d/LDN %d\n",
  1089. deviceInfo->CardInformation->CardSelectNumber,
  1090. deviceInfo->LogicalDeviceNumber));
  1091. if ((deviceInfo->Flags & (DF_ACTIVATED|DF_NOT_FUNCTIONING)) == DF_ACTIVATED) {
  1092. PipWakeAndSelectDevice(
  1093. (UCHAR) deviceInfo->CardInformation->CardSelectNumber,
  1094. (UCHAR)deviceInfo->LogicalDeviceNumber);
  1095. PipDeactivateDevice();
  1096. PipWaitForKey();
  1097. }
  1098. PipReleaseDeviceResources (deviceInfo);
  1099. deviceInfo->Flags |= DF_SURPRISE_REMOVED;
  1100. deviceInfo->Flags &= ~(DF_QUERY_STOPPED|DF_REMOVED|DF_ACTIVATED);
  1101. }
  1102. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  1103. status = STATUS_SUCCESS;
  1104. } else {
  1105. status = STATUS_NO_SUCH_DEVICE;
  1106. }
  1107. return status;
  1108. } // PiSurpriseRemovePdo
  1109. NTSTATUS
  1110. PiIrpNotSupported(
  1111. IN PDEVICE_OBJECT DeviceObject,
  1112. IN OUT PIRP Irp
  1113. )
  1114. {
  1115. return STATUS_NOT_SUPPORTED;
  1116. } // PiIrpNotSupported
  1117. NTSTATUS
  1118. PipBuildRDPResources(
  1119. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
  1120. IN ULONG Flags
  1121. )
  1122. {
  1123. ULONG MaxCards = 0, CardsFound;
  1124. int i, j, numcases;
  1125. int resSize;
  1126. ASSERT(Flags & DF_READ_DATA_PORT);
  1127. //
  1128. // We need to assemble all possible cases for the RDP
  1129. //
  1130. numcases = 2*READ_DATA_PORT_RANGE_CHOICES;
  1131. if (Flags & DF_REQ_TRIMMED) {
  1132. numcases = 0;
  1133. for (i = 0; i < READ_DATA_PORT_RANGE_CHOICES; i++) {
  1134. CardsFound = PipReadDataPortRanges[i].CardsFound;
  1135. if (MaxCards < CardsFound) {
  1136. MaxCards = CardsFound;
  1137. numcases = 1;
  1138. } else if (MaxCards == CardsFound) {
  1139. numcases++;
  1140. }
  1141. }
  1142. }
  1143. //
  1144. // need to allow for the RDP range, the address port, the cmd port and the 0
  1145. //
  1146. resSize = sizeof (IO_RESOURCE_LIST)+((numcases+3)*sizeof (IO_RESOURCE_REQUIREMENTS_LIST));
  1147. *IoResources = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool (PagedPool,resSize);
  1148. if (*IoResources == NULL) {
  1149. return STATUS_INSUFFICIENT_RESOURCES;
  1150. }
  1151. RtlZeroMemory (*IoResources,resSize);
  1152. (*IoResources)->BusNumber=0;
  1153. (*IoResources)->AlternativeLists = 1;
  1154. (*IoResources)->List->Count = numcases+4;
  1155. (*IoResources)->List->Version = ISAPNP_IO_VERSION;
  1156. (*IoResources)->List->Revision =ISAPNP_IO_REVISION;
  1157. //
  1158. // Requirements specify 16-bit decode even though the spec
  1159. // says 12. No ill effects have ever been observed from 16
  1160. // and 12-bit decode broke some machines when tried.
  1161. //
  1162. // cmd port
  1163. //
  1164. (*IoResources)->List->Descriptors[0].Type=CM_RESOURCE_PORT_IO;
  1165. (*IoResources)->List->Descriptors[0].u.Port.MinimumAddress.LowPart = COMMAND_PORT;
  1166. (*IoResources)->List->Descriptors[0].u.Port.MaximumAddress.LowPart = COMMAND_PORT;
  1167. (*IoResources)->List->Descriptors[0].u.Port.Length = 1;
  1168. (*IoResources)->List->Descriptors[0].u.Port.Alignment = 1;
  1169. (*IoResources)->List->Descriptors[0].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1170. (*IoResources)->List->Descriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
  1171. //
  1172. // alternative of 0 for bioses that include COMMAND_PORT in
  1173. // a PNP0C02 node.
  1174. //
  1175. (*IoResources)->List->Descriptors[1].Type=CM_RESOURCE_PORT_IO;
  1176. (*IoResources)->List->Descriptors[1].u.Port.MinimumAddress.QuadPart = 0;
  1177. (*IoResources)->List->Descriptors[1].u.Port.MaximumAddress.QuadPart = 0;
  1178. (*IoResources)->List->Descriptors[1].u.Port.Length = 0;
  1179. (*IoResources)->List->Descriptors[1].u.Port.Alignment = 1;
  1180. (*IoResources)->List->Descriptors[1].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1181. (*IoResources)->List->Descriptors[1].ShareDisposition = CmResourceShareDeviceExclusive;
  1182. (*IoResources)->List->Descriptors[1].Option = IO_RESOURCE_ALTERNATIVE;
  1183. //
  1184. // Address port
  1185. //
  1186. (*IoResources)->List->Descriptors[2].Type=CM_RESOURCE_PORT_IO;
  1187. (*IoResources)->List->Descriptors[2].u.Port.MinimumAddress.LowPart = ADDRESS_PORT;
  1188. (*IoResources)->List->Descriptors[2].u.Port.MaximumAddress.LowPart = ADDRESS_PORT;
  1189. (*IoResources)->List->Descriptors[2].u.Port.Length = 1;
  1190. (*IoResources)->List->Descriptors[2].u.Port.Alignment = 1;
  1191. (*IoResources)->List->Descriptors[2].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1192. (*IoResources)->List->Descriptors[2].ShareDisposition = CmResourceShareDeviceExclusive;
  1193. //
  1194. // alternative of 0
  1195. //
  1196. (*IoResources)->List->Descriptors[3].Type=CM_RESOURCE_PORT_IO;
  1197. (*IoResources)->List->Descriptors[3].u.Port.MinimumAddress.QuadPart = 0;
  1198. (*IoResources)->List->Descriptors[3].u.Port.MaximumAddress.QuadPart = 0;
  1199. (*IoResources)->List->Descriptors[3].u.Port.Length = 0;
  1200. (*IoResources)->List->Descriptors[3].u.Port.Alignment = 1;
  1201. (*IoResources)->List->Descriptors[3].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1202. (*IoResources)->List->Descriptors[3].ShareDisposition = CmResourceShareDeviceExclusive;
  1203. (*IoResources)->List->Descriptors[3].Option = IO_RESOURCE_ALTERNATIVE;
  1204. if (Flags & DF_REQ_TRIMMED) {
  1205. j = 0;
  1206. for (i = 0; i < READ_DATA_PORT_RANGE_CHOICES; i++) {
  1207. if (PipReadDataPortRanges[i].CardsFound != MaxCards) {
  1208. continue;
  1209. }
  1210. //
  1211. // An RDP alternative
  1212. //
  1213. (*IoResources)->List->Descriptors[4+j].Type=CM_RESOURCE_PORT_IO;
  1214. (*IoResources)->List->Descriptors[4+j].u.Port.MinimumAddress.LowPart =
  1215. PipReadDataPortRanges[i].MinimumAddress;
  1216. (*IoResources)->List->Descriptors[4+j].u.Port.MaximumAddress.LowPart =
  1217. PipReadDataPortRanges[i].MaximumAddress;
  1218. (*IoResources)->List->Descriptors[4+j].u.Port.Length =
  1219. PipReadDataPortRanges[i].MaximumAddress -
  1220. PipReadDataPortRanges[i].MinimumAddress+1;
  1221. (*IoResources)->List->Descriptors[4+j].u.Port.Alignment = 1;
  1222. (*IoResources)->List->Descriptors[4+j].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1223. (*IoResources)->List->Descriptors[4+j].ShareDisposition = CmResourceShareDeviceExclusive;
  1224. (*IoResources)->List->Descriptors[4+j].Option = IO_RESOURCE_ALTERNATIVE;
  1225. j++;
  1226. }
  1227. (*IoResources)->List->Descriptors[4].Option = 0;
  1228. } else {
  1229. for (i = 0;i< (numcases >> 1);i++) {
  1230. //
  1231. // The RDP
  1232. //
  1233. (*IoResources)->List->Descriptors[4+i*2].Type=CM_RESOURCE_PORT_IO;
  1234. (*IoResources)->List->Descriptors[4+i*2].u.Port.MinimumAddress.LowPart =
  1235. PipReadDataPortRanges[i].MinimumAddress;
  1236. (*IoResources)->List->Descriptors[4+i*2].u.Port.MaximumAddress.LowPart =
  1237. PipReadDataPortRanges[i].MaximumAddress;
  1238. (*IoResources)->List->Descriptors[4+i*2].u.Port.Length =
  1239. PipReadDataPortRanges[i].MaximumAddress -
  1240. PipReadDataPortRanges[i].MinimumAddress+1;
  1241. (*IoResources)->List->Descriptors[4+i*2].u.Port.Alignment = 1;
  1242. (*IoResources)->List->Descriptors[4+i*2].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1243. (*IoResources)->List->Descriptors[4+i*2].ShareDisposition = CmResourceShareDeviceExclusive;
  1244. //
  1245. // alternative of 0
  1246. //
  1247. (*IoResources)->List->Descriptors[4+i*2+1].Type=CM_RESOURCE_PORT_IO;
  1248. (*IoResources)->List->Descriptors[4+i*2+1].u.Port.MinimumAddress.QuadPart = 0;
  1249. (*IoResources)->List->Descriptors[4+i*2+1].u.Port.MaximumAddress.QuadPart = 0;
  1250. (*IoResources)->List->Descriptors[4+i*2+1].u.Port.Length = 0;
  1251. (*IoResources)->List->Descriptors[4+i*2+1].u.Port.Alignment = 1;
  1252. (*IoResources)->List->Descriptors[4+i*2+1].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1253. (*IoResources)->List->Descriptors[4+i*2+1].ShareDisposition = CmResourceShareDeviceExclusive;
  1254. (*IoResources)->List->Descriptors[4+i*2+1].Option = IO_RESOURCE_ALTERNATIVE;
  1255. }
  1256. }
  1257. (*IoResources)->ListSize = resSize;
  1258. return STATUS_SUCCESS;
  1259. }
  1260. NTSTATUS
  1261. PiQueryDeviceState(
  1262. IN PDEVICE_OBJECT DeviceObject,
  1263. IN OUT PIRP Irp
  1264. )
  1265. {
  1266. NTSTATUS status=STATUS_NOT_SUPPORTED;
  1267. PDEVICE_INFORMATION deviceInfo;
  1268. //
  1269. // One of our enumerated device is being removed. Mark it and deactivate the
  1270. // device. Note, we do NOT delete its device object.
  1271. //
  1272. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  1273. if ((deviceInfo->Flags & DF_READ_DATA_PORT) && (deviceInfo->Flags & DF_PROCESSING_RDP)) {
  1274. Irp->IoStatus.Information |= PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED |
  1275. PNP_DEVICE_FAILED |
  1276. PNP_DEVICE_NOT_DISABLEABLE ;
  1277. status = STATUS_SUCCESS;
  1278. }
  1279. if (deviceInfo->Paging || deviceInfo->CrashDump) {
  1280. Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
  1281. status = STATUS_SUCCESS;
  1282. }
  1283. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  1284. }
  1285. return status;
  1286. }
  1287. #endif