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.

1669 lines
54 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 != NULL) &&
  673. (deviceInfo->ResourceRequirements->AlternativeLists > 1)) {
  674. status = PipGetBootIrqFlags(deviceInfo, &irqBootFlags);
  675. if (NT_SUCCESS(status)) {
  676. status = PipTrimResourceRequirements(
  677. &IoResources,
  678. irqBootFlags,
  679. NULL);
  680. Irp->IoStatus.Information = (ULONG_PTR) IoResources;
  681. } else {
  682. status = STATUS_NOT_SUPPORTED;
  683. }
  684. } else {
  685. status = STATUS_NOT_SUPPORTED;
  686. }
  687. }
  688. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  689. return status;
  690. }
  691. NTSTATUS
  692. PiQueryIdPdo(
  693. IN PDEVICE_OBJECT DeviceObject,
  694. IN OUT PIRP Irp
  695. )
  696. {
  697. NTSTATUS status;
  698. PIO_STACK_LOCATION irpSp;
  699. PDEVICE_INFORMATION deviceInfo;
  700. ULONG length, bytesRemaining;
  701. ULONG requestIdStringLength, deviceIdStringLength;
  702. ULONG requestIdBufferLength, deviceIdBufferLength;
  703. PWCHAR requestId = NULL, ids;
  704. PWCHAR deviceId = NULL, p;
  705. PWCHAR stringEnd;
  706. irpSp = IoGetCurrentIrpStackLocation(Irp);
  707. if ((deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) == NULL) {
  708. status = STATUS_NO_SUCH_DEVICE;
  709. return status;
  710. }
  711. switch (irpSp->Parameters.QueryId.IdType) {
  712. case BusQueryCompatibleIDs:
  713. ids = (PWCHAR)ExAllocatePool(PagedPool, 1024);
  714. length = 1024;
  715. if (ids) {
  716. PWCHAR p1;
  717. ULONG i;
  718. p1 = ids;
  719. for (i = 1; TRUE; i++) {
  720. //
  721. // Use the -1 as a sentinel so that we get the magic RDP compat. ID and also leave the loop
  722. //
  723. ASSERT (i < 256);
  724. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  725. i =-1;
  726. }
  727. status = PipGetCompatibleDeviceId(
  728. deviceInfo->DeviceData,
  729. i,
  730. &requestId,
  731. &requestIdBufferLength
  732. );
  733. if (NT_SUCCESS(status) && requestId) {
  734. if (FAILED(StringCbLength(requestId,
  735. requestIdBufferLength,
  736. &requestIdStringLength
  737. ))) {
  738. status = STATUS_INVALID_PARAMETER;
  739. ASSERT(FALSE);
  740. break;
  741. }
  742. if ((requestIdStringLength + 2*sizeof(WCHAR)) <= length) {
  743. if (FAILED(StringCbCopyEx(p1,
  744. length,
  745. requestId,
  746. &stringEnd,
  747. &bytesRemaining,
  748. 0
  749. ))) {
  750. ASSERT(FALSE);
  751. status = STATUS_INVALID_PARAMETER;
  752. break;
  753. }
  754. p1 = stringEnd;
  755. p1++;
  756. length = bytesRemaining - sizeof(UNICODE_NULL);
  757. ExFreePool(requestId);
  758. } else {
  759. ExFreePool(requestId);
  760. break;
  761. }
  762. if ( i == -1 ) {
  763. break;
  764. }
  765. } else {
  766. break;
  767. }
  768. }
  769. if (length == 1024) {
  770. ExFreePool(ids);
  771. ids = NULL;
  772. } else {
  773. *p1 = UNICODE_NULL;
  774. }
  775. }
  776. Irp->IoStatus.Information = (ULONG_PTR)ids;
  777. status = STATUS_SUCCESS;
  778. break;
  779. case BusQueryHardwareIDs:
  780. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  781. status = PipGetCompatibleDeviceId(deviceInfo->DeviceData, -1, &requestId, &requestIdBufferLength);
  782. }else {
  783. status = PipGetCompatibleDeviceId(deviceInfo->DeviceData, 0, &requestId, &requestIdBufferLength);
  784. }
  785. if (NT_SUCCESS(status) && requestId) {
  786. //
  787. // create HardwareId value name. Even though it is a MULTI_SZ,
  788. // we know there is only one HardwareId for PnpIsa.
  789. //
  790. // HACK - The modem inf files use the form of isapnp\xyz0001
  791. // instead of *xyz0001 as the hardware id. To solve this
  792. // problem we will generate two hardware Ids: *xyz0001 and
  793. // isapnp\xyz0001 (device instance name).
  794. //
  795. status = PipQueryDeviceId(deviceInfo, &deviceId, &deviceIdBufferLength, 0);
  796. if (NT_SUCCESS (status)) {
  797. if (FAILED(StringCbLength(requestId,
  798. requestIdBufferLength,
  799. &requestIdStringLength
  800. ))) {
  801. status = STATUS_INVALID_PARAMETER;
  802. break;
  803. }
  804. if (FAILED(StringCbLength(deviceId,
  805. deviceIdBufferLength,
  806. &deviceIdStringLength
  807. ))) {
  808. status = STATUS_INVALID_PARAMETER;
  809. break;
  810. }
  811. //idLength = wcslen(requestId) * sizeof(WCHAR);
  812. //deviceIdLength = wcslen(deviceId) * sizeof(WCHAR);
  813. length = requestIdStringLength + // returned ID
  814. sizeof(WCHAR) + // UNICODE_NULL
  815. deviceIdStringLength + // isapnp\id
  816. 2 * sizeof(WCHAR); // two UNICODE_NULLs
  817. ids = p = (PWCHAR)ExAllocatePool(PagedPool, length);
  818. if (ids) {
  819. if (FAILED(StringCbCopyEx(ids,
  820. length,
  821. deviceId,
  822. &stringEnd,
  823. &bytesRemaining,
  824. 0
  825. ))) {
  826. ASSERT(FALSE);
  827. status = STATUS_INVALID_PARAMETER;
  828. break;
  829. }
  830. p = stringEnd + 1;
  831. if (FAILED(StringCbCopyEx(p,
  832. length,
  833. requestId,
  834. &stringEnd,
  835. &bytesRemaining,
  836. 0
  837. ))) {
  838. ASSERT(FALSE);
  839. status = STATUS_INVALID_PARAMETER;
  840. break;
  841. }
  842. p = stringEnd + 1;
  843. *p = UNICODE_NULL;
  844. ExFreePool(requestId);
  845. Irp->IoStatus.Information = (ULONG_PTR)ids;
  846. } else {
  847. Irp->IoStatus.Information = (ULONG_PTR)requestId;
  848. }
  849. if (deviceId) {
  850. ExFreePool(deviceId);
  851. }
  852. }
  853. }
  854. break;
  855. case BusQueryDeviceID:
  856. status = PipQueryDeviceId(deviceInfo, &requestId, &requestIdBufferLength, 0);
  857. Irp->IoStatus.Information = (ULONG_PTR)requestId;
  858. break;
  859. case BusQueryInstanceID:
  860. status = PipQueryDeviceUniqueId (deviceInfo, &requestId, &requestIdBufferLength);
  861. Irp->IoStatus.Information = (ULONG_PTR)requestId;
  862. break;
  863. default:
  864. status = STATUS_NOT_SUPPORTED;
  865. }
  866. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  867. return status;
  868. } // PiQueryIdPdo
  869. NTSTATUS
  870. PiQueryResourcesPdo(
  871. IN PDEVICE_OBJECT DeviceObject,
  872. IN OUT PIRP Irp
  873. )
  874. {
  875. NTSTATUS status=STATUS_SUCCESS;
  876. PDEVICE_INFORMATION deviceInfo;
  877. PCM_RESOURCE_LIST cmResources=NULL;
  878. ULONG length;
  879. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  880. if ((deviceInfo->Flags & DF_READ_DATA_PORT) ||
  881. ((deviceInfo->Flags & (DF_ENUMERATED|DF_REMOVED)) == DF_ENUMERATED)) {
  882. status = PipQueryDeviceResources (
  883. deviceInfo,
  884. 0, // BusNumber
  885. &cmResources,
  886. &length
  887. );
  888. }
  889. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  890. Irp->IoStatus.Information = (ULONG_PTR)cmResources;
  891. } else {
  892. status = STATUS_NO_SUCH_DEVICE;
  893. }
  894. DebugPrint((DEBUG_PNP, "PiQueryResourcesPdo returning: %x\n",status));
  895. return status;
  896. } // PiQueryResourcesPdo
  897. NTSTATUS
  898. PiQueryResourceRequirementsPdo(
  899. IN PDEVICE_OBJECT DeviceObject,
  900. IN OUT PIRP Irp
  901. )
  902. {
  903. NTSTATUS status;
  904. PDEVICE_INFORMATION deviceInfo;
  905. PIO_RESOURCE_REQUIREMENTS_LIST ioResources;
  906. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  907. status = STATUS_SUCCESS;
  908. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  909. status = PipBuildRDPResources (&ioResources,
  910. deviceInfo->Flags);
  911. } else {
  912. if (deviceInfo->ResourceRequirements &&
  913. !(deviceInfo->Flags & (DF_SURPRISE_REMOVED))) {
  914. ioResources = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool (
  915. PagedPool, deviceInfo->ResourceRequirements->ListSize);
  916. if (ioResources == NULL) {
  917. status = STATUS_INSUFFICIENT_RESOURCES;
  918. } else {
  919. RtlMoveMemory(ioResources,
  920. deviceInfo->ResourceRequirements,
  921. deviceInfo->ResourceRequirements->ListSize
  922. );
  923. }
  924. } else {
  925. ioResources = NULL;
  926. }
  927. }
  928. Irp->IoStatus.Information = (ULONG_PTR)ioResources;
  929. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  930. } else {
  931. status = STATUS_NO_SUCH_DEVICE;
  932. }
  933. DebugPrint((DEBUG_PNP, "PiQueryResourceRequirementsPdo returning: %x\n",status));
  934. return status;
  935. } // PiQueryResourceRequirementsPdo
  936. NTSTATUS
  937. PiRemovePdo(
  938. IN PDEVICE_OBJECT DeviceObject,
  939. IN OUT PIRP Irp
  940. )
  941. {
  942. NTSTATUS status;
  943. PDEVICE_INFORMATION deviceInfo;
  944. POWER_STATE newPowerState;
  945. //
  946. // One of our enumerated device is being removed. Mark it and deactivate the
  947. // device. Note, we do NOT delete its device object.
  948. //
  949. DebugPrint((DEBUG_PNP, "PiRemovePdo %x\n",DeviceObject));
  950. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  951. if (!(deviceInfo->Flags & (DF_REMOVED|DF_SURPRISE_REMOVED))) {
  952. deviceInfo->Flags |= DF_REMOVED;
  953. deviceInfo->Flags &= ~DF_QUERY_STOPPED;
  954. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  955. PSINGLE_LIST_ENTRY deviceLink;
  956. PPI_BUS_EXTENSION busExtension = deviceInfo->ParentDeviceExtension;
  957. //
  958. // If the RDP is removed, mark everyone as missing, and then return only the
  959. // RDP
  960. //
  961. PipLockDeviceDatabase();
  962. deviceLink = busExtension->DeviceList.Next;
  963. while (deviceLink) {
  964. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
  965. if (!(deviceInfo->Flags & DF_READ_DATA_PORT)) {
  966. deviceInfo->Flags &= ~DF_ENUMERATED;
  967. }
  968. deviceLink = deviceInfo->DeviceList.Next;
  969. }
  970. PipUnlockDeviceDatabase();
  971. IoInvalidateDeviceRelations (
  972. deviceInfo->ParentDeviceExtension->PhysicalBusDevice,BusRelations);
  973. deviceInfo->Flags &= ~(DF_REQ_TRIMMED|DF_PROCESSING_RDP);
  974. }
  975. //
  976. // Deactivate the device
  977. //
  978. if (deviceInfo->Flags & DF_ACTIVATED) {
  979. deviceInfo->Flags &= ~DF_ACTIVATED;
  980. if (!(deviceInfo->Flags & (DF_READ_DATA_PORT|DF_NOT_FUNCTIONING))) {
  981. PipWakeAndSelectDevice(
  982. deviceInfo->CardInformation->CardSelectNumber,
  983. deviceInfo->LogicalDeviceNumber);
  984. PipDeactivateDevice();
  985. PipWaitForKey();
  986. DebugPrint((DEBUG_STATE,
  987. "Removing CSN %d/LDN %d\n",
  988. deviceInfo->CardInformation->CardSelectNumber,
  989. deviceInfo->LogicalDeviceNumber));
  990. }
  991. newPowerState.DeviceState = deviceInfo->DevicePowerState = PowerDeviceD3;
  992. PoSetPowerState(DeviceObject, DevicePowerState, newPowerState);
  993. }
  994. PipReleaseDeviceResources (deviceInfo);
  995. }
  996. if (!(deviceInfo->Flags & DF_ENUMERATED)) {
  997. PipDeleteDevice(DeviceObject);
  998. }
  999. PipDereferenceDeviceInformation(deviceInfo, TRUE);
  1000. status = STATUS_SUCCESS;
  1001. } else {
  1002. status = STATUS_NO_SUCH_DEVICE;
  1003. }
  1004. DebugPrint((DEBUG_PNP, "RemoveDevice returning: %x\n",status));
  1005. return status;
  1006. } // PiRemovePdo
  1007. NTSTATUS
  1008. PiQueryBusInformationPdo(
  1009. IN PDEVICE_OBJECT DeviceObject,
  1010. IN OUT PIRP Irp
  1011. )
  1012. {
  1013. PPNP_BUS_INFORMATION pnpBusInfo;
  1014. PVOID information = NULL;
  1015. PPI_BUS_EXTENSION busExtension;
  1016. NTSTATUS status;
  1017. busExtension = DeviceObject->DeviceExtension;
  1018. pnpBusInfo = (PPNP_BUS_INFORMATION) ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
  1019. if (pnpBusInfo) {
  1020. pnpBusInfo->BusTypeGuid = GUID_BUS_TYPE_ISAPNP;
  1021. pnpBusInfo->LegacyBusType = Isa;
  1022. pnpBusInfo->BusNumber = busExtension->BusNumber;
  1023. information = pnpBusInfo;
  1024. status = STATUS_SUCCESS;
  1025. } else {
  1026. status = STATUS_INSUFFICIENT_RESOURCES;
  1027. information = NULL;
  1028. }
  1029. Irp->IoStatus.Information = (ULONG_PTR) information;
  1030. return status;
  1031. } // PiQueryBusInformationPdo
  1032. NTSTATUS
  1033. PiDeviceUsageNotificationPdo(
  1034. IN PDEVICE_OBJECT DeviceObject,
  1035. IN OUT PIRP Irp
  1036. )
  1037. /*++
  1038. Routine Description:
  1039. This routine notes whether an ISAPNP device is on the crashdump or
  1040. paging file path. It fails attempts to put us on the hibernation path.
  1041. Arguments:
  1042. DeviceObject - Pointer to the PDO for which this IRP applies.
  1043. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  1044. Return Value:
  1045. NT status.
  1046. --*/
  1047. {
  1048. PDEVICE_INFORMATION deviceInfo;
  1049. PIO_STACK_LOCATION irpSp;
  1050. PLONG addend;
  1051. NTSTATUS status = STATUS_SUCCESS;
  1052. irpSp = IoGetCurrentIrpStackLocation(Irp);
  1053. if ((deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) == NULL) {
  1054. status = STATUS_NO_SUCH_DEVICE;
  1055. return status;
  1056. }
  1057. DebugPrint((DEBUG_PNP, "DeviceUsage CSN %d/LSN %d: InPath %s Type %d\n",
  1058. deviceInfo->CardInformation->CardSelectNumber,
  1059. deviceInfo->LogicalDeviceNumber,
  1060. irpSp->Parameters.UsageNotification.InPath ? "TRUE" : "FALSE",
  1061. irpSp->Parameters.UsageNotification.Type));
  1062. switch (irpSp->Parameters.UsageNotification.Type) {
  1063. case DeviceUsageTypePaging:
  1064. addend = &deviceInfo->Paging;
  1065. break;
  1066. case DeviceUsageTypeHibernation:
  1067. status = STATUS_DEVICE_BUSY;
  1068. break;
  1069. case DeviceUsageTypeDumpFile:
  1070. addend = &deviceInfo->CrashDump;
  1071. break;
  1072. default:
  1073. status = STATUS_NOT_SUPPORTED;
  1074. }
  1075. if (status == STATUS_SUCCESS) {
  1076. if (irpSp->Parameters.UsageNotification.InPath) {
  1077. //
  1078. // Turn on broken isolation flag which causes QDR
  1079. // to use the cache instead of beating on the hardware if
  1080. // we're on the paging or crashdump paths. Some
  1081. // hardware appears unhappy during QDR and causes problems when
  1082. // we take a page fault in this routine.
  1083. //
  1084. deviceInfo->CardInformation->CardFlags |= CF_ISOLATION_BROKEN;
  1085. (*addend)++;
  1086. IoInvalidateDeviceState(DeviceObject);
  1087. }
  1088. else {
  1089. (*addend)--;
  1090. }
  1091. }
  1092. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  1093. return status;
  1094. }
  1095. NTSTATUS
  1096. PiQueryInterfacePdo(
  1097. IN PDEVICE_OBJECT DeviceObject,
  1098. IN OUT PIRP Irp
  1099. )
  1100. {
  1101. UNREFERENCED_PARAMETER(DeviceObject);
  1102. UNREFERENCED_PARAMETER(Irp);
  1103. return STATUS_NOT_SUPPORTED;
  1104. } // PiQueryInterfacePdo
  1105. NTSTATUS
  1106. PiSurpriseRemovePdo(
  1107. IN PDEVICE_OBJECT DeviceObject,
  1108. IN OUT PIRP Irp
  1109. )
  1110. {
  1111. NTSTATUS status;
  1112. PDEVICE_INFORMATION deviceInfo;
  1113. PSINGLE_LIST_ENTRY deviceLink;
  1114. DebugPrint((DEBUG_PNP, "SurpriseRemove PDO %x\n", DeviceObject));
  1115. //
  1116. // One of our enumerated device is being removed. Mark it and deactivate the
  1117. // device. Note, we do NOT delete its device object.
  1118. //
  1119. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  1120. if (deviceInfo->Flags & DF_READ_DATA_PORT) {
  1121. //
  1122. // If the RDP is removed, mark everyone as missing, and then return only the
  1123. // RDP
  1124. //
  1125. PipLockDeviceDatabase();
  1126. deviceLink = deviceInfo->ParentDeviceExtension->DeviceList.Next;
  1127. while (deviceLink) {
  1128. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
  1129. if (!(deviceInfo->Flags & DF_READ_DATA_PORT)) {
  1130. deviceInfo->Flags &= ~DF_ENUMERATED;
  1131. }
  1132. deviceLink = deviceInfo->DeviceList.Next;
  1133. }
  1134. PipUnlockDeviceDatabase();
  1135. IoInvalidateDeviceRelations (
  1136. deviceInfo->ParentDeviceExtension->PhysicalBusDevice,BusRelations);
  1137. } else {
  1138. DebugPrint((DEBUG_STATE,
  1139. "Surprise removing CSN %d/LDN %d\n",
  1140. deviceInfo->CardInformation->CardSelectNumber,
  1141. deviceInfo->LogicalDeviceNumber));
  1142. if ((deviceInfo->Flags & (DF_ACTIVATED|DF_NOT_FUNCTIONING)) == DF_ACTIVATED) {
  1143. PipWakeAndSelectDevice(
  1144. deviceInfo->CardInformation->CardSelectNumber,
  1145. deviceInfo->LogicalDeviceNumber);
  1146. PipDeactivateDevice();
  1147. PipWaitForKey();
  1148. }
  1149. PipReleaseDeviceResources (deviceInfo);
  1150. deviceInfo->Flags |= DF_SURPRISE_REMOVED;
  1151. deviceInfo->Flags &= ~(DF_QUERY_STOPPED|DF_REMOVED|DF_ACTIVATED);
  1152. }
  1153. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  1154. status = STATUS_SUCCESS;
  1155. } else {
  1156. status = STATUS_NO_SUCH_DEVICE;
  1157. }
  1158. return status;
  1159. } // PiSurpriseRemovePdo
  1160. NTSTATUS
  1161. PiIrpNotSupported(
  1162. IN PDEVICE_OBJECT DeviceObject,
  1163. IN OUT PIRP Irp
  1164. )
  1165. {
  1166. return STATUS_NOT_SUPPORTED;
  1167. } // PiIrpNotSupported
  1168. NTSTATUS
  1169. PipBuildRDPResources(
  1170. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
  1171. IN ULONG Flags
  1172. )
  1173. {
  1174. UCHAR MaxCards = 0, CardsFound;
  1175. int i, j, numcases;
  1176. int resSize;
  1177. ASSERT(Flags & DF_READ_DATA_PORT);
  1178. //
  1179. // We need to assemble all possible cases for the RDP
  1180. //
  1181. numcases = 2*READ_DATA_PORT_RANGE_CHOICES;
  1182. if (Flags & DF_REQ_TRIMMED) {
  1183. numcases = 0;
  1184. for (i = 0; i < READ_DATA_PORT_RANGE_CHOICES; i++) {
  1185. CardsFound = PipReadDataPortRanges[i].CardsFound;
  1186. if (MaxCards < CardsFound) {
  1187. MaxCards = CardsFound;
  1188. numcases = 1;
  1189. } else if (MaxCards == CardsFound) {
  1190. numcases++;
  1191. }
  1192. }
  1193. }
  1194. //
  1195. // need to allow for the RDP range, the address port, the cmd port and the 0
  1196. //
  1197. resSize = sizeof (IO_RESOURCE_LIST)+((numcases+3)*sizeof (IO_RESOURCE_REQUIREMENTS_LIST));
  1198. *IoResources = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool (PagedPool,resSize);
  1199. if (*IoResources == NULL) {
  1200. return STATUS_INSUFFICIENT_RESOURCES;
  1201. }
  1202. RtlZeroMemory (*IoResources,resSize);
  1203. (*IoResources)->BusNumber=0;
  1204. (*IoResources)->AlternativeLists = 1;
  1205. (*IoResources)->List->Count = numcases+4;
  1206. (*IoResources)->List->Version = ISAPNP_IO_VERSION;
  1207. (*IoResources)->List->Revision =ISAPNP_IO_REVISION;
  1208. //
  1209. // Requirements specify 16-bit decode even though the spec
  1210. // says 12. No ill effects have ever been observed from 16
  1211. // and 12-bit decode broke some machines when tried.
  1212. //
  1213. // cmd port
  1214. //
  1215. (*IoResources)->List->Descriptors[0].Type=CM_RESOURCE_PORT_IO;
  1216. (*IoResources)->List->Descriptors[0].u.Port.MinimumAddress.LowPart = COMMAND_PORT;
  1217. (*IoResources)->List->Descriptors[0].u.Port.MaximumAddress.LowPart = COMMAND_PORT;
  1218. (*IoResources)->List->Descriptors[0].u.Port.Length = 1;
  1219. (*IoResources)->List->Descriptors[0].u.Port.Alignment = 1;
  1220. (*IoResources)->List->Descriptors[0].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1221. (*IoResources)->List->Descriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
  1222. //
  1223. // alternative of 0 for bioses that include COMMAND_PORT in
  1224. // a PNP0C02 node.
  1225. //
  1226. (*IoResources)->List->Descriptors[1].Type=CM_RESOURCE_PORT_IO;
  1227. (*IoResources)->List->Descriptors[1].u.Port.MinimumAddress.QuadPart = 0;
  1228. (*IoResources)->List->Descriptors[1].u.Port.MaximumAddress.QuadPart = 0;
  1229. (*IoResources)->List->Descriptors[1].u.Port.Length = 0;
  1230. (*IoResources)->List->Descriptors[1].u.Port.Alignment = 1;
  1231. (*IoResources)->List->Descriptors[1].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1232. (*IoResources)->List->Descriptors[1].ShareDisposition = CmResourceShareDeviceExclusive;
  1233. (*IoResources)->List->Descriptors[1].Option = IO_RESOURCE_ALTERNATIVE;
  1234. //
  1235. // Address port
  1236. //
  1237. (*IoResources)->List->Descriptors[2].Type=CM_RESOURCE_PORT_IO;
  1238. (*IoResources)->List->Descriptors[2].u.Port.MinimumAddress.LowPart = ADDRESS_PORT;
  1239. (*IoResources)->List->Descriptors[2].u.Port.MaximumAddress.LowPart = ADDRESS_PORT;
  1240. (*IoResources)->List->Descriptors[2].u.Port.Length = 1;
  1241. (*IoResources)->List->Descriptors[2].u.Port.Alignment = 1;
  1242. (*IoResources)->List->Descriptors[2].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1243. (*IoResources)->List->Descriptors[2].ShareDisposition = CmResourceShareDeviceExclusive;
  1244. //
  1245. // alternative of 0
  1246. //
  1247. (*IoResources)->List->Descriptors[3].Type=CM_RESOURCE_PORT_IO;
  1248. (*IoResources)->List->Descriptors[3].u.Port.MinimumAddress.QuadPart = 0;
  1249. (*IoResources)->List->Descriptors[3].u.Port.MaximumAddress.QuadPart = 0;
  1250. (*IoResources)->List->Descriptors[3].u.Port.Length = 0;
  1251. (*IoResources)->List->Descriptors[3].u.Port.Alignment = 1;
  1252. (*IoResources)->List->Descriptors[3].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1253. (*IoResources)->List->Descriptors[3].ShareDisposition = CmResourceShareDeviceExclusive;
  1254. (*IoResources)->List->Descriptors[3].Option = IO_RESOURCE_ALTERNATIVE;
  1255. if (Flags & DF_REQ_TRIMMED) {
  1256. j = 0;
  1257. for (i = 0; i < READ_DATA_PORT_RANGE_CHOICES; i++) {
  1258. if (PipReadDataPortRanges[i].CardsFound != MaxCards) {
  1259. continue;
  1260. }
  1261. //
  1262. // An RDP alternative
  1263. //
  1264. (*IoResources)->List->Descriptors[4+j].Type=CM_RESOURCE_PORT_IO;
  1265. (*IoResources)->List->Descriptors[4+j].u.Port.MinimumAddress.LowPart =
  1266. PipReadDataPortRanges[i].MinimumAddress;
  1267. (*IoResources)->List->Descriptors[4+j].u.Port.MaximumAddress.LowPart =
  1268. PipReadDataPortRanges[i].MaximumAddress;
  1269. (*IoResources)->List->Descriptors[4+j].u.Port.Length =
  1270. PipReadDataPortRanges[i].MaximumAddress -
  1271. PipReadDataPortRanges[i].MinimumAddress+1;
  1272. (*IoResources)->List->Descriptors[4+j].u.Port.Alignment = 1;
  1273. (*IoResources)->List->Descriptors[4+j].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1274. (*IoResources)->List->Descriptors[4+j].ShareDisposition = CmResourceShareDeviceExclusive;
  1275. (*IoResources)->List->Descriptors[4+j].Option = IO_RESOURCE_ALTERNATIVE;
  1276. j++;
  1277. }
  1278. (*IoResources)->List->Descriptors[4].Option = 0;
  1279. } else {
  1280. for (i = 0;i< (numcases >> 1);i++) {
  1281. //
  1282. // The RDP
  1283. //
  1284. (*IoResources)->List->Descriptors[4+i*2].Type=CM_RESOURCE_PORT_IO;
  1285. (*IoResources)->List->Descriptors[4+i*2].u.Port.MinimumAddress.LowPart =
  1286. PipReadDataPortRanges[i].MinimumAddress;
  1287. (*IoResources)->List->Descriptors[4+i*2].u.Port.MaximumAddress.LowPart =
  1288. PipReadDataPortRanges[i].MaximumAddress;
  1289. (*IoResources)->List->Descriptors[4+i*2].u.Port.Length =
  1290. PipReadDataPortRanges[i].MaximumAddress -
  1291. PipReadDataPortRanges[i].MinimumAddress+1;
  1292. (*IoResources)->List->Descriptors[4+i*2].u.Port.Alignment = 1;
  1293. (*IoResources)->List->Descriptors[4+i*2].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1294. (*IoResources)->List->Descriptors[4+i*2].ShareDisposition = CmResourceShareDeviceExclusive;
  1295. //
  1296. // alternative of 0
  1297. //
  1298. (*IoResources)->List->Descriptors[4+i*2+1].Type=CM_RESOURCE_PORT_IO;
  1299. (*IoResources)->List->Descriptors[4+i*2+1].u.Port.MinimumAddress.QuadPart = 0;
  1300. (*IoResources)->List->Descriptors[4+i*2+1].u.Port.MaximumAddress.QuadPart = 0;
  1301. (*IoResources)->List->Descriptors[4+i*2+1].u.Port.Length = 0;
  1302. (*IoResources)->List->Descriptors[4+i*2+1].u.Port.Alignment = 1;
  1303. (*IoResources)->List->Descriptors[4+i*2+1].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  1304. (*IoResources)->List->Descriptors[4+i*2+1].ShareDisposition = CmResourceShareDeviceExclusive;
  1305. (*IoResources)->List->Descriptors[4+i*2+1].Option = IO_RESOURCE_ALTERNATIVE;
  1306. }
  1307. }
  1308. (*IoResources)->ListSize = resSize;
  1309. return STATUS_SUCCESS;
  1310. }
  1311. NTSTATUS
  1312. PiQueryDeviceState(
  1313. IN PDEVICE_OBJECT DeviceObject,
  1314. IN OUT PIRP Irp
  1315. )
  1316. {
  1317. NTSTATUS status=STATUS_NOT_SUPPORTED;
  1318. PDEVICE_INFORMATION deviceInfo;
  1319. //
  1320. // One of our enumerated device is being removed. Mark it and deactivate the
  1321. // device. Note, we do NOT delete its device object.
  1322. //
  1323. if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
  1324. if ((deviceInfo->Flags & DF_READ_DATA_PORT) && (deviceInfo->Flags & DF_PROCESSING_RDP)) {
  1325. Irp->IoStatus.Information |= PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED |
  1326. PNP_DEVICE_FAILED |
  1327. PNP_DEVICE_NOT_DISABLEABLE ;
  1328. status = STATUS_SUCCESS;
  1329. }
  1330. if (deviceInfo->Paging || deviceInfo->CrashDump) {
  1331. Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
  1332. status = STATUS_SUCCESS;
  1333. }
  1334. PipDereferenceDeviceInformation(deviceInfo, FALSE);
  1335. }
  1336. return status;
  1337. }
  1338. #endif