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.

1307 lines
37 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. pdo.c
  5. Abstract:
  6. This module handles IRPs for PCI PDO's.
  7. Author:
  8. Adrian J. Oney (adriao) & Andrew Thornton (andrewth) 10-20-1998
  9. Revision History:
  10. --*/
  11. #include "pcip.h"
  12. NTSTATUS
  13. PciPdoIrpStartDevice(
  14. IN PIRP Irp,
  15. IN PIO_STACK_LOCATION IrpSp,
  16. IN PPCI_COMMON_EXTENSION DeviceExtension
  17. );
  18. NTSTATUS
  19. PciPdoIrpQueryRemoveDevice(
  20. IN PIRP Irp,
  21. IN PIO_STACK_LOCATION IrpSp,
  22. IN PPCI_COMMON_EXTENSION DeviceExtension
  23. );
  24. NTSTATUS
  25. PciPdoIrpRemoveDevice(
  26. IN PIRP Irp,
  27. IN PIO_STACK_LOCATION IrpSp,
  28. IN PPCI_COMMON_EXTENSION DeviceExtension
  29. );
  30. NTSTATUS
  31. PciPdoIrpCancelRemoveDevice(
  32. IN PIRP Irp,
  33. IN PIO_STACK_LOCATION IrpSp,
  34. IN PPCI_COMMON_EXTENSION DeviceExtension
  35. );
  36. NTSTATUS
  37. PciPdoIrpStopDevice(
  38. IN PIRP Irp,
  39. IN PIO_STACK_LOCATION IrpSp,
  40. IN PPCI_COMMON_EXTENSION DeviceExtension
  41. );
  42. NTSTATUS
  43. PciPdoIrpQueryStopDevice(
  44. IN PIRP Irp,
  45. IN PIO_STACK_LOCATION IrpSp,
  46. IN PPCI_COMMON_EXTENSION DeviceExtension
  47. );
  48. NTSTATUS
  49. PciPdoIrpCancelStopDevice(
  50. IN PIRP Irp,
  51. IN PIO_STACK_LOCATION IrpSp,
  52. IN PPCI_COMMON_EXTENSION DeviceExtension
  53. );
  54. NTSTATUS
  55. PciPdoIrpQueryDeviceRelations(
  56. IN PIRP Irp,
  57. IN PIO_STACK_LOCATION IrpSp,
  58. IN PPCI_COMMON_EXTENSION DeviceExtension
  59. );
  60. NTSTATUS
  61. PciPdoIrpQueryCapabilities(
  62. IN PIRP Irp,
  63. IN PIO_STACK_LOCATION IrpSp,
  64. IN PPCI_COMMON_EXTENSION DeviceExtension
  65. );
  66. NTSTATUS
  67. PciPdoIrpQueryInterface(
  68. IN PIRP Irp,
  69. IN PIO_STACK_LOCATION IrpSp,
  70. IN PPCI_COMMON_EXTENSION DeviceExtension
  71. );
  72. NTSTATUS
  73. PciPdoIrpQueryResources(
  74. IN PIRP Irp,
  75. IN PIO_STACK_LOCATION IrpSp,
  76. IN PPCI_COMMON_EXTENSION DeviceExtension
  77. );
  78. NTSTATUS
  79. PciPdoIrpQueryResourceRequirements(
  80. IN PIRP Irp,
  81. IN PIO_STACK_LOCATION IrpSp,
  82. IN PPCI_COMMON_EXTENSION DeviceExtension
  83. );
  84. NTSTATUS
  85. PciPdoIrpQueryDeviceText(
  86. IN PIRP Irp,
  87. IN PIO_STACK_LOCATION IrpSp,
  88. IN PPCI_COMMON_EXTENSION DeviceExtension
  89. );
  90. NTSTATUS
  91. PciPdoIrpReadConfig(
  92. IN PIRP Irp,
  93. IN PIO_STACK_LOCATION IrpSp,
  94. IN PPCI_COMMON_EXTENSION DeviceExtension
  95. );
  96. NTSTATUS
  97. PciPdoIrpWriteConfig(
  98. IN PIRP Irp,
  99. IN PIO_STACK_LOCATION IrpSp,
  100. IN PPCI_COMMON_EXTENSION DeviceExtension
  101. );
  102. NTSTATUS
  103. PciPdoIrpQueryId(
  104. IN PIRP Irp,
  105. IN PIO_STACK_LOCATION IrpSp,
  106. IN PPCI_COMMON_EXTENSION DeviceExtension
  107. );
  108. NTSTATUS
  109. PciPdoIrpQueryBusInformation(
  110. IN PIRP Irp,
  111. IN PIO_STACK_LOCATION IrpSp,
  112. IN PPCI_COMMON_EXTENSION DeviceExtension
  113. );
  114. NTSTATUS
  115. PciPdoIrpDeviceUsageNotification(
  116. IN PIRP Irp,
  117. IN PIO_STACK_LOCATION IrpSp,
  118. IN PPCI_COMMON_EXTENSION DeviceExtension
  119. );
  120. NTSTATUS
  121. PciPdoIrpQueryLegacyBusInformation(
  122. IN PIRP Irp,
  123. IN PIO_STACK_LOCATION IrpSp,
  124. IN PPCI_COMMON_EXTENSION DeviceExtension
  125. );
  126. NTSTATUS
  127. PciPdoIrpSurpriseRemoval(
  128. IN PIRP Irp,
  129. IN PIO_STACK_LOCATION IrpSp,
  130. IN PPCI_COMMON_EXTENSION DeviceExtension
  131. );
  132. NTSTATUS
  133. PciPdoIrpQueryDeviceState(
  134. IN PIRP Irp,
  135. IN PIO_STACK_LOCATION IrpSp,
  136. IN PPCI_COMMON_EXTENSION DeviceExtension
  137. );
  138. #ifdef ALLOC_PRAGMA
  139. #pragma alloc_text(PAGE, PciPdoCreate)
  140. #pragma alloc_text(PAGE, PciPdoDestroy)
  141. #pragma alloc_text(PAGE, PciPdoIrpStartDevice)
  142. #pragma alloc_text(PAGE, PciPdoIrpQueryRemoveDevice)
  143. #pragma alloc_text(PAGE, PciPdoIrpRemoveDevice)
  144. #pragma alloc_text(PAGE, PciPdoIrpCancelRemoveDevice)
  145. #pragma alloc_text(PAGE, PciPdoIrpStopDevice)
  146. #pragma alloc_text(PAGE, PciPdoIrpQueryStopDevice)
  147. #pragma alloc_text(PAGE, PciPdoIrpCancelStopDevice)
  148. #pragma alloc_text(PAGE, PciPdoIrpQueryDeviceRelations)
  149. #pragma alloc_text(PAGE, PciPdoIrpQueryInterface)
  150. #pragma alloc_text(PAGE, PciPdoIrpQueryCapabilities)
  151. #pragma alloc_text(PAGE, PciPdoIrpQueryResources)
  152. #pragma alloc_text(PAGE, PciPdoIrpQueryResourceRequirements)
  153. #pragma alloc_text(PAGE, PciPdoIrpQueryDeviceText)
  154. #pragma alloc_text(PAGE, PciPdoIrpReadConfig)
  155. #pragma alloc_text(PAGE, PciPdoIrpWriteConfig)
  156. #pragma alloc_text(PAGE, PciPdoIrpQueryId)
  157. #pragma alloc_text(PAGE, PciPdoIrpQueryBusInformation)
  158. #pragma alloc_text(PAGE, PciPdoIrpDeviceUsageNotification)
  159. #pragma alloc_text(PAGE, PciPdoIrpQueryLegacyBusInformation)
  160. #pragma alloc_text(PAGE, PciPdoIrpSurpriseRemoval)
  161. #pragma alloc_text(PAGE, PciPdoIrpQueryDeviceState)
  162. #endif
  163. /*++
  164. The majority of functions in this file are called based on their presence
  165. in Pnp and Po dispatch tables. In the interests of brevity the arguments
  166. to all those functions will be described below:
  167. NTSTATUS
  168. PciXxxPdo(
  169. IN PIRP Irp,
  170. IN PIO_STACK_LOCATION IrpStack,
  171. IN PPCI_EXTENSION DeviceExtension
  172. )
  173. Routine Description:
  174. This function handles the Xxx requests for a given PCI FDO or PDO.
  175. Arguments:
  176. Irp - Points to the IRP associated with this request.
  177. IrpStack - Points to the current stack location for this request.
  178. DeviceExtension - Points to the device's extension.
  179. Return Value:
  180. Status code that indicates whether or not the function was successful.
  181. STATUS_NOT_SUPPORTED indicates that the IRP should be completed without
  182. changing the Irp->IoStatus.Status field otherwise it is updated with this
  183. status.
  184. --*/
  185. #define PCI_MAX_MINOR_POWER_IRP 0x3
  186. #define PCI_MAX_MINOR_PNP_IRP 0x18
  187. PCI_MN_DISPATCH_TABLE PciPdoDispatchPowerTable[] = {
  188. { IRP_DISPATCH, PciPdoWaitWake }, // 0x00 - IRP_MN_WAIT_WAKE
  189. { IRP_COMPLETE, PciIrpNotSupported }, // 0x01 - IRP_MN_POWER_SEQUENCE
  190. { IRP_COMPLETE, PciPdoSetPowerState }, // 0x02 - IRP_MN_SET_POWER
  191. { IRP_COMPLETE, PciPdoIrpQueryPower }, // 0x03 - IRP_MN_QUERY_POWER
  192. { IRP_COMPLETE, PciIrpNotSupported }, // - UNHANDLED Power IRP
  193. };
  194. PCI_MN_DISPATCH_TABLE PciPdoDispatchPnpTable[] = {
  195. { IRP_COMPLETE, PciPdoIrpStartDevice }, // 0x00 - IRP_MN_START_DEVICE
  196. { IRP_COMPLETE, PciPdoIrpQueryRemoveDevice }, // 0x01 - IRP_MN_QUERY_REMOVE_DEVICE
  197. { IRP_COMPLETE, PciPdoIrpRemoveDevice }, // 0x02 - IRP_MN_REMOVE_DEVICE
  198. { IRP_COMPLETE, PciPdoIrpCancelRemoveDevice }, // 0x03 - IRP_MN_CANCEL_REMOVE_DEVICE
  199. { IRP_COMPLETE, PciPdoIrpStopDevice }, // 0x04 - IRP_MN_STOP_DEVICE
  200. { IRP_COMPLETE, PciPdoIrpQueryStopDevice }, // 0x05 - IRP_MN_QUERY_STOP_DEVICE
  201. { IRP_COMPLETE, PciPdoIrpCancelStopDevice }, // 0x06 - IRP_MN_CANCEL_STOP_DEVICE
  202. { IRP_COMPLETE, PciPdoIrpQueryDeviceRelations }, // 0x07 - IRP_MN_QUERY_DEVICE_RELATIONS
  203. { IRP_COMPLETE, PciPdoIrpQueryInterface }, // 0x08 - IRP_MN_QUERY_INTERFACE
  204. { IRP_COMPLETE, PciPdoIrpQueryCapabilities }, // 0x09 - IRP_MN_QUERY_CAPABILITIES
  205. { IRP_COMPLETE, PciPdoIrpQueryResources }, // 0x0A - IRP_MN_QUERY_RESOURCES
  206. { IRP_COMPLETE, PciPdoIrpQueryResourceRequirements }, // 0x0B - IRP_MN_QUERY_RESOURCE_REQUIREMENTS
  207. { IRP_COMPLETE, PciPdoIrpQueryDeviceText }, // 0x0C - IRP_MN_QUERY_DEVICE_TEXT
  208. { IRP_COMPLETE, PciIrpNotSupported }, // 0x0D - IRP_MN_FILTER_RESOURCE_REQUIREMENTS
  209. { IRP_COMPLETE, PciIrpNotSupported }, // 0x0E - NOT USED
  210. { IRP_COMPLETE, PciPdoIrpReadConfig }, // 0x0F - IRP_MN_READ_CONFIG
  211. { IRP_COMPLETE, PciPdoIrpWriteConfig }, // 0x10 - IRP_MN_WRITE_CONFIG
  212. { IRP_COMPLETE, PciIrpNotSupported }, // 0x11 - IRP_MN_EJECT
  213. { IRP_COMPLETE, PciIrpNotSupported }, // 0x12 - IRP_MN_SET_LOCK
  214. { IRP_COMPLETE, PciPdoIrpQueryId }, // 0x13 - IRP_MN_QUERY_ID
  215. { IRP_COMPLETE, PciPdoIrpQueryDeviceState }, // 0x14 - IRP_MN_QUERY_PNP_DEVICE_STATE
  216. { IRP_COMPLETE, PciPdoIrpQueryBusInformation }, // 0x15 - IRP_MN_QUERY_BUS_INFORMATION
  217. { IRP_COMPLETE, PciPdoIrpDeviceUsageNotification }, // 0x16 - IRP_MN_DEVICE_USAGE_NOTIFICATION
  218. { IRP_COMPLETE, PciPdoIrpSurpriseRemoval }, // 0x17 - IRP_MN_SURPRISE_REMOVAL
  219. { IRP_COMPLETE, PciPdoIrpQueryLegacyBusInformation }, // 0x18 - IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  220. { IRP_COMPLETE, PciIrpNotSupported } // - UNHANDLED PNP IRP
  221. };
  222. //
  223. // This is the major function dispatch table for Pdo's
  224. //
  225. PCI_MJ_DISPATCH_TABLE PciPdoDispatchTable = {
  226. PCI_MAX_MINOR_PNP_IRP, PciPdoDispatchPnpTable, // Pnp irps
  227. PCI_MAX_MINOR_POWER_IRP, PciPdoDispatchPowerTable, // Power irps
  228. IRP_COMPLETE, PciIrpNotSupported,
  229. IRP_COMPLETE, PciIrpInvalidDeviceRequest // Other
  230. };
  231. //
  232. // Data
  233. //
  234. BOOLEAN PciStopOnIllegalConfigAccess = FALSE;
  235. ULONG PciPdoSequenceNumber = (ULONG)-1;
  236. NTSTATUS
  237. PciPdoCreate(
  238. IN PPCI_FDO_EXTENSION FdoExtension,
  239. IN PCI_SLOT_NUMBER Slot,
  240. OUT PDEVICE_OBJECT *PhysicalDeviceObject
  241. )
  242. {
  243. NTSTATUS status;
  244. PDRIVER_OBJECT driverObject;
  245. PDEVICE_OBJECT functionalDeviceObject;
  246. PDEVICE_OBJECT physicalDeviceObject;
  247. PPCI_PDO_EXTENSION pdoExtension;
  248. UNICODE_STRING unicodeDeviceString;
  249. WCHAR deviceString[32];
  250. BOOLEAN ok;
  251. PAGED_CODE();
  252. //
  253. // We've been asked to create a new PDO for a PCI device. First get
  254. // a pointer to our driver object.
  255. //
  256. functionalDeviceObject = FdoExtension->FunctionalDeviceObject;
  257. driverObject = functionalDeviceObject->DriverObject;
  258. //
  259. // Create the physical device object for this device.
  260. // In theory it doesn't need a name,... It must have
  261. // a name.
  262. //
  263. // But what name? For now we'll call it NTPNP_PCIxxxx,
  264. // where xxxx is the 0-based number of PCI devices we've
  265. // found.
  266. //
  267. ok = SUCCEEDED(StringCbPrintfW(deviceString,
  268. sizeof(deviceString),
  269. L"\\Device\\NTPNP_PCI%04d",
  270. InterlockedIncrement(&PciPdoSequenceNumber)
  271. ));
  272. ASSERT(ok);
  273. RtlInitUnicodeString(&unicodeDeviceString, deviceString);
  274. status = IoCreateDevice(
  275. driverObject, // our driver object
  276. sizeof(PCI_PDO_EXTENSION), // size of our extension,
  277. &unicodeDeviceString, // our name
  278. FILE_DEVICE_UNKNOWN, // device type
  279. 0, // device characteristics
  280. FALSE, // not exclusive
  281. &physicalDeviceObject // store new device object here
  282. );
  283. if (!NT_SUCCESS(status)) {
  284. PCI_ASSERT(NT_SUCCESS(status));
  285. return status;
  286. }
  287. pdoExtension = (PPCI_PDO_EXTENSION)physicalDeviceObject->DeviceExtension;
  288. PciDebugPrint(PciDbgVerbose,
  289. "PCI: New PDO (b=0x%x, d=0x%x, f=0x%x) @ %p, ext @ %p\n",
  290. FdoExtension->BaseBus,
  291. Slot.u.bits.DeviceNumber,
  292. Slot.u.bits.FunctionNumber,
  293. physicalDeviceObject,
  294. pdoExtension);
  295. //
  296. // We have our physical device object, initialize it.
  297. //
  298. // And yes, I would have zeroed the extension if I didn't know
  299. // for a fact that it was zeroed by IoCreateDevice().
  300. //
  301. pdoExtension->ExtensionType = PciPdoExtensionType;
  302. pdoExtension->IrpDispatchTable = &PciPdoDispatchTable;
  303. pdoExtension->PhysicalDeviceObject = physicalDeviceObject;
  304. pdoExtension->Slot = Slot;
  305. pdoExtension->PowerState.CurrentSystemState = PowerSystemWorking;
  306. pdoExtension->PowerState.CurrentDeviceState = PowerDeviceD0;
  307. pdoExtension->ParentFdoExtension = FdoExtension;
  308. ExInitializeFastMutex(&pdoExtension->SecondaryExtMutex);
  309. PciInitializeState((PPCI_COMMON_EXTENSION) pdoExtension);
  310. //
  311. // Insert it into the list of child PDOs hanging off of the FdoExtension.
  312. // We won't be re-entered enumerating the same bus, so we don't need to
  313. // protect the list.
  314. //
  315. pdoExtension->Next = NULL;
  316. PciInsertEntryAtTail(
  317. (PSINGLE_LIST_ENTRY)&FdoExtension->ChildPdoList,
  318. (PSINGLE_LIST_ENTRY)&pdoExtension->Next,
  319. &FdoExtension->ChildListMutex
  320. );
  321. *PhysicalDeviceObject = physicalDeviceObject;
  322. return STATUS_SUCCESS;
  323. }
  324. VOID
  325. PciPdoDestroy(
  326. IN PDEVICE_OBJECT PhysicalDeviceObject
  327. )
  328. {
  329. PPCI_PDO_EXTENSION pdoExtension;
  330. PPCI_PDO_EXTENSION *previousBridge;
  331. PPCI_FDO_EXTENSION fdoExtension;
  332. PAGED_CODE();
  333. pdoExtension = (PPCI_PDO_EXTENSION)PhysicalDeviceObject->DeviceExtension;
  334. ASSERT_PCI_PDO_EXTENSION(pdoExtension);
  335. PCI_ASSERT(!pdoExtension->LegacyDriver);
  336. fdoExtension = PCI_PARENT_FDOX(pdoExtension);
  337. ASSERT_PCI_FDO_EXTENSION(fdoExtension);
  338. PciDebugPrint(PciDbgVerbose,
  339. "PCI: destroy PDO (b=0x%x, d=0x%x, f=0x%x)\n",
  340. PCI_PARENT_FDOX(pdoExtension)->BaseBus,
  341. pdoExtension->Slot.u.bits.DeviceNumber,
  342. pdoExtension->Slot.u.bits.FunctionNumber);
  343. //
  344. // Remove this PDO from the Child Pdo List.
  345. //
  346. ASSERT_MUTEX_HELD(&fdoExtension->ChildListMutex);
  347. PciRemoveEntryFromList((PSINGLE_LIST_ENTRY)&fdoExtension->ChildPdoList,
  348. (PSINGLE_LIST_ENTRY)pdoExtension,
  349. NULL);
  350. for (previousBridge = &fdoExtension->ChildBridgePdoList;
  351. *previousBridge;
  352. previousBridge = &((*previousBridge)->NextBridge)) {
  353. if (*previousBridge == pdoExtension) {
  354. *previousBridge = pdoExtension->NextBridge;
  355. pdoExtension->NextBridge = NULL;
  356. break;
  357. }
  358. }
  359. pdoExtension->Next = NULL;
  360. //
  361. // Delete any secondary extensions this PDO may have.
  362. //
  363. while (pdoExtension->SecondaryExtension.Next) {
  364. PcipDestroySecondaryExtension(&pdoExtension->SecondaryExtension,
  365. NULL,
  366. pdoExtension->SecondaryExtension.Next);
  367. }
  368. //
  369. // Zap the extension type so we'll trip up if we try to resuse it.
  370. //
  371. pdoExtension->ExtensionType = 0xdead;
  372. //
  373. // If there are any resource lists etc associated with this puppy,
  374. // give them back to the system.
  375. //
  376. //PciInvalidateResourceInfoCache(pdoExtension);
  377. // BUGBUG - leak
  378. if (pdoExtension->Resources) {
  379. ExFreePool(pdoExtension->Resources);
  380. }
  381. //
  382. // And finally,...
  383. //
  384. IoDeleteDevice(PhysicalDeviceObject);
  385. }
  386. NTSTATUS
  387. PciPdoIrpStartDevice(
  388. IN PIRP Irp,
  389. IN PIO_STACK_LOCATION IrpSp,
  390. IN PPCI_COMMON_EXTENSION DeviceExtension
  391. )
  392. {
  393. NTSTATUS status;
  394. BOOLEAN change, powerOn, isVideoController;
  395. PPCI_PDO_EXTENSION pdoExtension;
  396. PAGED_CODE();
  397. status = PciBeginStateTransition(DeviceExtension, PciStarted);
  398. if (!NT_SUCCESS(status)) {
  399. return status;
  400. }
  401. pdoExtension = (PPCI_PDO_EXTENSION) DeviceExtension;
  402. //
  403. // If there is a motherboard video device and a plug in video
  404. // device, the BIOS will have disabled the motherboard one. The
  405. // video drivers use this fact to determine if this device should
  406. // be disabled,... don't change its settings here.
  407. //
  408. isVideoController =
  409. ((pdoExtension->BaseClass == PCI_CLASS_PRE_20) &&
  410. (pdoExtension->SubClass == PCI_SUBCLASS_PRE_20_VGA)) ||
  411. ((pdoExtension->BaseClass == PCI_CLASS_DISPLAY_CTLR) &&
  412. (pdoExtension->SubClass == PCI_SUBCLASS_VID_VGA_CTLR));
  413. if ( !isVideoController ) {
  414. //
  415. // Non-VGA, unconditionally enable the IO and Memory for the device.
  416. //
  417. pdoExtension->CommandEnables |= (PCI_ENABLE_IO_SPACE
  418. | PCI_ENABLE_MEMORY_SPACE);
  419. }
  420. //
  421. // Disable interrupt generation for IDE controllers until IDE is up and
  422. // running (See comment in PciConfigureIdeController)
  423. //
  424. if (pdoExtension->IoSpaceUnderNativeIdeControl) {
  425. pdoExtension->CommandEnables &= ~PCI_ENABLE_IO_SPACE;
  426. }
  427. //
  428. // Always enable the bus master bit - even for video controllers
  429. //
  430. pdoExtension->CommandEnables |= PCI_ENABLE_BUS_MASTER;
  431. //
  432. // Extract the PDO Resources (PCI driver internal style)
  433. // from the incoming resource list.
  434. //
  435. change = PciComputeNewCurrentSettings(
  436. pdoExtension,
  437. IrpSp->Parameters.StartDevice.AllocatedResources
  438. );
  439. //
  440. // Remember if we ever move the device
  441. //
  442. if (change) {
  443. pdoExtension->MovedDevice = TRUE;
  444. }
  445. #if DBG
  446. if (!change) {
  447. PciDebugPrint(
  448. PciDbgObnoxious,
  449. "PCI - START not changing resource settings.\n"
  450. );
  451. }
  452. #endif
  453. //
  454. // The device should be powered up at this stage.
  455. //
  456. powerOn = FALSE;
  457. if (pdoExtension->PowerState.CurrentDeviceState != PowerDeviceD0) {
  458. POWER_STATE powerState;
  459. status = PciSetPowerManagedDevicePowerState(
  460. pdoExtension,
  461. PowerDeviceD0,
  462. FALSE
  463. );
  464. if (!NT_SUCCESS(status)) {
  465. PciCancelStateTransition(DeviceExtension, PciStarted);
  466. return STATUS_DEVICE_POWER_FAILURE;
  467. }
  468. powerState.DeviceState = PowerDeviceD0;
  469. PoSetPowerState(
  470. pdoExtension->PhysicalDeviceObject,
  471. DevicePowerState,
  472. powerState
  473. );
  474. //
  475. // Force PciSetResources to write the configuration
  476. // and other extraneous data to the device.
  477. //
  478. powerOn = TRUE;
  479. pdoExtension->PowerState.CurrentDeviceState = PowerDeviceD0;
  480. }
  481. //
  482. // Program the device with the resources allocated.
  483. //
  484. status = PciSetResources(
  485. pdoExtension,
  486. powerOn,
  487. TRUE
  488. );
  489. if (NT_SUCCESS(status)) {
  490. PciCommitStateTransition(DeviceExtension, PciStarted);
  491. } else {
  492. PciCancelStateTransition(DeviceExtension, PciStarted);
  493. }
  494. return status;
  495. }
  496. NTSTATUS
  497. PciPdoIrpQueryRemoveDevice(
  498. IN PIRP Irp,
  499. IN PIO_STACK_LOCATION IrpSp,
  500. IN PPCI_COMMON_EXTENSION DeviceExtension
  501. )
  502. {
  503. PPCI_PDO_EXTENSION pdoExtension;
  504. PAGED_CODE();
  505. pdoExtension = (PPCI_PDO_EXTENSION) DeviceExtension;
  506. //
  507. // Don't allow the paging device (or a hibernate device) to
  508. // be removed or stopped
  509. //
  510. if (pdoExtension->PowerState.Hibernate ||
  511. pdoExtension->PowerState.Paging ||
  512. pdoExtension->PowerState.CrashDump ||
  513. pdoExtension->OnDebugPath ||
  514. (pdoExtension->HackFlags & PCI_HACK_FAIL_QUERY_REMOVE)) {
  515. return STATUS_DEVICE_BUSY;
  516. }
  517. //
  518. // Don't allow devices with legacy drivers to be removed (even thought the
  519. // driver may be root enumerated)
  520. //
  521. if (pdoExtension->LegacyDriver) {
  522. return STATUS_INVALID_DEVICE_REQUEST;
  523. }
  524. if (DeviceExtension->DeviceState == PciNotStarted) {
  525. return STATUS_SUCCESS;
  526. } else {
  527. return PciBeginStateTransition(DeviceExtension, PciNotStarted);
  528. }
  529. }
  530. NTSTATUS
  531. PciPdoIrpRemoveDevice(
  532. IN PIRP Irp,
  533. IN PIO_STACK_LOCATION IrpSp,
  534. IN PPCI_COMMON_EXTENSION DeviceExtension
  535. )
  536. {
  537. NTSTATUS status;
  538. PPCI_PDO_EXTENSION pdoExtension;
  539. PAGED_CODE();
  540. pdoExtension = (PPCI_PDO_EXTENSION) DeviceExtension;
  541. //
  542. // If this PDO is for a PCI-PCI bridge, it has a pointer
  543. // to the FDO that was attached to it. That FDO was destroyed
  544. // as a result of the IRP coming down the stack. Clear the
  545. // pointer. (Unconditionally as it is only set for bridges).
  546. //
  547. pdoExtension->BridgeFdoExtension = NULL;
  548. if (!pdoExtension->NotPresent) {
  549. //
  550. // Turn the device off. (Checks for whether or not
  551. // this is a good idea are in the PciDecodeEnable routine).
  552. // While you might think this should be done only if we were already
  553. // headed to PciNotStarted, we may in fact have a boot config that
  554. // needs to be disabled.
  555. //
  556. PciDecodeEnable(pdoExtension, FALSE, NULL);
  557. //
  558. // Power it down if we are allowed to disable its decodes - if not then
  559. // don't turn it off. eg. Don't turn of the VGA card...
  560. //
  561. if (pdoExtension->PowerState.CurrentDeviceState != PowerDeviceD3
  562. && PciCanDisableDecodes(pdoExtension, NULL, 0, 0)) {
  563. POWER_STATE powerState;
  564. status = PciSetPowerManagedDevicePowerState(
  565. pdoExtension,
  566. PowerDeviceD3,
  567. FALSE
  568. );
  569. pdoExtension->PowerState.CurrentDeviceState = PowerDeviceD3;
  570. powerState.DeviceState = PowerDeviceD3;
  571. PoSetPowerState(
  572. pdoExtension->PhysicalDeviceObject,
  573. DevicePowerState,
  574. powerState
  575. );
  576. }
  577. }
  578. //
  579. // We can get a remove in one of three states:
  580. // 1) We have received a QueryRemove/SurpriseRemove in which case we are
  581. // transitioning to PciNotStarted.
  582. // 2) We were never started, so we are already in PciNotStarted.
  583. // 3) We started the PDO, but the FDO failed start. We are in PciStarted in
  584. // this case.
  585. //
  586. if (!PciIsInTransitionToState(DeviceExtension, PciNotStarted)&&
  587. (DeviceExtension->DeviceState == PciStarted)) {
  588. PciBeginStateTransition(DeviceExtension, PciNotStarted);
  589. }
  590. if (PciIsInTransitionToState(DeviceExtension, PciNotStarted)) {
  591. PciCommitStateTransition(DeviceExtension, PciNotStarted);
  592. }
  593. if (pdoExtension->ReportedMissing) {
  594. status = PciBeginStateTransition(DeviceExtension, PciDeleted);
  595. PCI_ASSERT(NT_SUCCESS(status));
  596. PciCommitStateTransition(DeviceExtension, PciDeleted);
  597. PciPdoDestroy(pdoExtension->PhysicalDeviceObject);
  598. }
  599. return STATUS_SUCCESS;
  600. }
  601. NTSTATUS
  602. PciPdoIrpCancelRemoveDevice(
  603. IN PIRP Irp,
  604. IN PIO_STACK_LOCATION IrpSp,
  605. IN PPCI_COMMON_EXTENSION DeviceExtension
  606. )
  607. {
  608. PAGED_CODE();
  609. PciCancelStateTransition(DeviceExtension, PciNotStarted);
  610. return STATUS_SUCCESS;
  611. }
  612. NTSTATUS
  613. PciPdoIrpStopDevice(
  614. IN PIRP Irp,
  615. IN PIO_STACK_LOCATION IrpSp,
  616. IN PPCI_COMMON_EXTENSION DeviceExtension
  617. )
  618. {
  619. PAGED_CODE();
  620. //
  621. // Turn the device off. (Checks for whether or not
  622. // this is a good idea are in the PciDecodeEnable routine).
  623. //
  624. PciDecodeEnable((PPCI_PDO_EXTENSION) DeviceExtension, FALSE, NULL);
  625. PciCommitStateTransition(DeviceExtension, PciStopped);
  626. return STATUS_SUCCESS;
  627. }
  628. NTSTATUS
  629. PciPdoIrpQueryStopDevice(
  630. IN PIRP Irp,
  631. IN PIO_STACK_LOCATION IrpSp,
  632. IN PPCI_COMMON_EXTENSION DeviceExtension
  633. )
  634. {
  635. PPCI_PDO_EXTENSION pdoExtension;
  636. PAGED_CODE();
  637. //
  638. // Don't allow the paging device (or a hibernate device) to
  639. // be removed or stopped
  640. //
  641. pdoExtension = (PPCI_PDO_EXTENSION) DeviceExtension;
  642. if (pdoExtension->PowerState.Hibernate ||
  643. pdoExtension->PowerState.Paging ||
  644. pdoExtension->PowerState.CrashDump ||
  645. pdoExtension->OnDebugPath) {
  646. return STATUS_DEVICE_BUSY;
  647. }
  648. //
  649. // Don't stop PCI->PCI and CardBus bridges
  650. //
  651. if (pdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV
  652. && (pdoExtension->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI
  653. || pdoExtension->SubClass == PCI_SUBCLASS_BR_CARDBUS)) {
  654. return STATUS_INVALID_DEVICE_REQUEST;
  655. }
  656. //
  657. // Don't allow devices with legacy drivers to be stopped (even thought the
  658. // driver may be root enumerated)
  659. //
  660. if (pdoExtension->LegacyDriver) {
  661. return STATUS_INVALID_DEVICE_REQUEST;
  662. }
  663. //
  664. // If we cannot free the resources, do tell the OS.
  665. //
  666. if (!PciCanDisableDecodes(pdoExtension, NULL, 0, 0)) {
  667. return STATUS_INVALID_DEVICE_REQUEST;
  668. }
  669. return PciBeginStateTransition(DeviceExtension, PciStopped);
  670. }
  671. NTSTATUS
  672. PciPdoIrpCancelStopDevice(
  673. IN PIRP Irp,
  674. IN PIO_STACK_LOCATION IrpSp,
  675. IN PPCI_COMMON_EXTENSION DeviceExtension
  676. )
  677. {
  678. PAGED_CODE();
  679. PciCancelStateTransition(DeviceExtension, PciStopped);
  680. return STATUS_SUCCESS;
  681. }
  682. NTSTATUS
  683. PciPdoIrpQueryDeviceRelations(
  684. IN PIRP Irp,
  685. IN PIO_STACK_LOCATION IrpSp,
  686. IN PPCI_COMMON_EXTENSION DeviceExtension
  687. )
  688. {
  689. NTSTATUS status;
  690. PPCI_PDO_EXTENSION pdoExtension;
  691. PAGED_CODE();
  692. pdoExtension = (PPCI_PDO_EXTENSION) DeviceExtension;
  693. switch(IrpSp->Parameters.QueryDeviceRelations.Type) {
  694. case EjectionRelations:
  695. status = PciQueryEjectionRelations(
  696. pdoExtension,
  697. (PDEVICE_RELATIONS*)&Irp->IoStatus.Information
  698. );
  699. break;
  700. case TargetDeviceRelation:
  701. status = PciQueryTargetDeviceRelations(
  702. pdoExtension,
  703. (PDEVICE_RELATIONS*)&Irp->IoStatus.Information
  704. );
  705. break;
  706. default:
  707. status = STATUS_NOT_SUPPORTED;
  708. break;
  709. }
  710. return status;
  711. }
  712. NTSTATUS
  713. PciPdoIrpQueryInterface(
  714. IN PIRP Irp,
  715. IN PIO_STACK_LOCATION IrpSp,
  716. IN PPCI_COMMON_EXTENSION DeviceExtension
  717. )
  718. {
  719. NTSTATUS status;
  720. PPCI_PDO_EXTENSION pdoExtension;
  721. PAGED_CODE();
  722. pdoExtension = (PPCI_PDO_EXTENSION) DeviceExtension;
  723. status = PciQueryInterface(
  724. pdoExtension,
  725. IrpSp->Parameters.QueryInterface.InterfaceType,
  726. IrpSp->Parameters.QueryInterface.Size,
  727. IrpSp->Parameters.QueryInterface.Version,
  728. IrpSp->Parameters.QueryInterface.InterfaceSpecificData,
  729. IrpSp->Parameters.QueryInterface.Interface,
  730. FALSE
  731. );
  732. if (!NT_SUCCESS(status)) {
  733. //
  734. // KLUDGE: If this pdo has a fake FDO attatched to
  735. // it (because it's a cardbus controller), we should
  736. // check to see if this interface could have been supplied
  737. // by the FDO and supply it if so.
  738. //
  739. // Yes, this is really gross and yes it breaks the filter
  740. // model. The correct thing is for cardbus to pass the
  741. // IRP here via the "backdoor" while it has it at the FDO
  742. // level.
  743. //
  744. PPCI_FDO_EXTENSION fakeFdo;
  745. fakeFdo = pdoExtension->BridgeFdoExtension;
  746. if (fakeFdo && (fakeFdo->Fake == TRUE)) {
  747. PCI_ASSERT((pdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
  748. (pdoExtension->SubClass == PCI_SUBCLASS_BR_CARDBUS));
  749. status = PciQueryInterface(
  750. fakeFdo,
  751. IrpSp->Parameters.QueryInterface.InterfaceType,
  752. IrpSp->Parameters.QueryInterface.Size,
  753. IrpSp->Parameters.QueryInterface.Version,
  754. IrpSp->Parameters.QueryInterface.InterfaceSpecificData,
  755. IrpSp->Parameters.QueryInterface.Interface,
  756. FALSE
  757. );
  758. }
  759. }
  760. return status;
  761. }
  762. NTSTATUS
  763. PciPdoIrpQueryCapabilities(
  764. IN PIRP Irp,
  765. IN PIO_STACK_LOCATION IrpSp,
  766. IN PPCI_COMMON_EXTENSION DeviceExtension
  767. )
  768. {
  769. PAGED_CODE();
  770. return PciQueryCapabilities(
  771. (PPCI_PDO_EXTENSION) DeviceExtension,
  772. IrpSp->Parameters.DeviceCapabilities.Capabilities
  773. );
  774. }
  775. NTSTATUS
  776. PciPdoIrpQueryId(
  777. IN PIRP Irp,
  778. IN PIO_STACK_LOCATION IrpSp,
  779. IN PPCI_COMMON_EXTENSION DeviceExtension
  780. )
  781. {
  782. PAGED_CODE();
  783. //
  784. // Get a pointer to the query id structure and process.
  785. //
  786. return PciQueryId(
  787. (PPCI_PDO_EXTENSION) DeviceExtension,
  788. IrpSp->Parameters.QueryId.IdType,
  789. (PWSTR*)&Irp->IoStatus.Information
  790. );
  791. }
  792. NTSTATUS
  793. PciPdoIrpQueryResources(
  794. IN PIRP Irp,
  795. IN PIO_STACK_LOCATION IrpSp,
  796. IN PPCI_COMMON_EXTENSION DeviceExtension
  797. )
  798. {
  799. PAGED_CODE();
  800. return PciQueryResources(
  801. (PPCI_PDO_EXTENSION) DeviceExtension,
  802. (PCM_RESOURCE_LIST*)&Irp->IoStatus.Information
  803. );
  804. }
  805. NTSTATUS
  806. PciPdoIrpQueryResourceRequirements(
  807. IN PIRP Irp,
  808. IN PIO_STACK_LOCATION IrpSp,
  809. IN PPCI_COMMON_EXTENSION DeviceExtension
  810. )
  811. {
  812. PAGED_CODE();
  813. return PciQueryRequirements(
  814. (PPCI_PDO_EXTENSION) DeviceExtension,
  815. (PIO_RESOURCE_REQUIREMENTS_LIST*)&Irp->IoStatus.Information
  816. );
  817. }
  818. NTSTATUS
  819. PciPdoIrpQueryDeviceText(
  820. IN PIRP Irp,
  821. IN PIO_STACK_LOCATION IrpSp,
  822. IN PPCI_COMMON_EXTENSION DeviceExtension
  823. )
  824. {
  825. PAGED_CODE();
  826. return PciQueryDeviceText(
  827. (PPCI_PDO_EXTENSION) DeviceExtension,
  828. IrpSp->Parameters.QueryDeviceText.DeviceTextType,
  829. IrpSp->Parameters.QueryDeviceText.LocaleId,
  830. (PWSTR*)&Irp->IoStatus.Information
  831. );
  832. }
  833. NTSTATUS
  834. PciPdoIrpReadConfig(
  835. IN PIRP Irp,
  836. IN PIO_STACK_LOCATION IrpSp,
  837. IN PPCI_COMMON_EXTENSION DeviceExtension
  838. )
  839. {
  840. NTSTATUS status;
  841. ULONG lengthRead;
  842. PPCI_PDO_EXTENSION pdoExtension;
  843. PAGED_CODE();
  844. pdoExtension = (PPCI_PDO_EXTENSION) DeviceExtension;
  845. status = PciReadDeviceSpace(pdoExtension,
  846. IrpSp->Parameters.ReadWriteConfig.WhichSpace,
  847. IrpSp->Parameters.ReadWriteConfig.Buffer,
  848. IrpSp->Parameters.ReadWriteConfig.Offset,
  849. IrpSp->Parameters.ReadWriteConfig.Length,
  850. &lengthRead
  851. );
  852. //
  853. // Update the information files with the number of bytes read
  854. //
  855. Irp->IoStatus.Information = lengthRead;
  856. return status;
  857. }
  858. NTSTATUS
  859. PciPdoIrpWriteConfig(
  860. IN PIRP Irp,
  861. IN PIO_STACK_LOCATION IrpSp,
  862. IN PPCI_COMMON_EXTENSION DeviceExtension
  863. )
  864. {
  865. NTSTATUS status;
  866. ULONG lengthWritten;
  867. PPCI_PDO_EXTENSION pdoExtension;
  868. PAGED_CODE();
  869. pdoExtension = (PPCI_PDO_EXTENSION) DeviceExtension;
  870. status = PciWriteDeviceSpace(pdoExtension,
  871. IrpSp->Parameters.ReadWriteConfig.WhichSpace,
  872. IrpSp->Parameters.ReadWriteConfig.Buffer,
  873. IrpSp->Parameters.ReadWriteConfig.Offset,
  874. IrpSp->Parameters.ReadWriteConfig.Length,
  875. &lengthWritten
  876. );
  877. //
  878. // Update the information files with the number of bytes read
  879. //
  880. Irp->IoStatus.Information = lengthWritten;
  881. return status;
  882. }
  883. NTSTATUS
  884. PciPdoIrpQueryBusInformation(
  885. IN PIRP Irp,
  886. IN PIO_STACK_LOCATION IrpSp,
  887. IN PPCI_COMMON_EXTENSION DeviceExtension
  888. )
  889. {
  890. PAGED_CODE();
  891. return PciQueryBusInformation(
  892. (PPCI_PDO_EXTENSION) DeviceExtension,
  893. (PPNP_BUS_INFORMATION *) &Irp->IoStatus.Information
  894. );
  895. }
  896. NTSTATUS
  897. PciPdoIrpDeviceUsageNotification(
  898. IN PIRP Irp,
  899. IN PIO_STACK_LOCATION IrpSp,
  900. IN PPCI_COMMON_EXTENSION DeviceExtension
  901. )
  902. {
  903. PAGED_CODE();
  904. return PciPdoDeviceUsage((PPCI_PDO_EXTENSION) DeviceExtension, Irp);
  905. }
  906. NTSTATUS
  907. PciPdoIrpQueryLegacyBusInformation(
  908. IN PIRP Irp,
  909. IN PIO_STACK_LOCATION IrpSp,
  910. IN PPCI_COMMON_EXTENSION DeviceExtension
  911. )
  912. {
  913. PPCI_PDO_EXTENSION PdoExtension;
  914. PLEGACY_BUS_INFORMATION information;
  915. PAGED_CODE();
  916. //
  917. // We're interested in IRP_MN_QUERY_LEGACY_BUS_INFORMATION on a
  918. // PDO if the PDO is for a CardBus bridge. In this case, the
  919. // CardBus/PCMCIA FDO has passed the irp down so that we can
  920. // answer it correctly.
  921. //
  922. PdoExtension = (PPCI_PDO_EXTENSION) DeviceExtension;
  923. if (PciClassifyDeviceType(PdoExtension) != PciTypeCardbusBridge) {
  924. return STATUS_NOT_SUPPORTED;
  925. }
  926. information = ExAllocatePool(PagedPool, sizeof(LEGACY_BUS_INFORMATION));
  927. if (information == NULL) {
  928. return STATUS_INSUFFICIENT_RESOURCES;
  929. }
  930. RtlCopyMemory(&information->BusTypeGuid, &GUID_BUS_TYPE_PCI, sizeof(GUID));
  931. information->LegacyBusType = PCIBus;
  932. information->BusNumber = PdoExtension->Dependent.type1.SecondaryBus;
  933. Irp->IoStatus.Information = (ULONG_PTR) information;
  934. return STATUS_SUCCESS;
  935. }
  936. NTSTATUS
  937. PciPdoIrpSurpriseRemoval(
  938. IN PIRP Irp,
  939. IN PIO_STACK_LOCATION IrpSp,
  940. IN PPCI_COMMON_EXTENSION DeviceExtension
  941. )
  942. {
  943. PPCI_PDO_EXTENSION pdoExtension;
  944. PAGED_CODE();
  945. pdoExtension = (PPCI_PDO_EXTENSION) DeviceExtension;
  946. //
  947. // There are two kinds of surprise removals
  948. // - Surprise removals due to removal of our device
  949. // - Surprise removals due to failure of our device to start
  950. //
  951. if (!pdoExtension->NotPresent) {
  952. //
  953. // Turn the device off. (Checks for whether or not
  954. // this is a good idea are in the PciDecodeEnable routine).
  955. // While you might think this should be done only if we were already
  956. // headed to PciNotStarted, we may in fact have a boot config that
  957. // needs to be disabled. Note that we may turn it off again in remove
  958. // device. No big deal.
  959. //
  960. PciDecodeEnable(pdoExtension, FALSE, NULL);
  961. //
  962. // Power it down if we are allowed to disable its decodes - if not then
  963. // don't turn it off. eg. Don't turn of the VGA card...
  964. //
  965. if (pdoExtension->PowerState.CurrentDeviceState != PowerDeviceD3
  966. && PciCanDisableDecodes(pdoExtension, NULL, 0, 0)) {
  967. POWER_STATE powerState;
  968. //
  969. // Power it down - if it fails we don't care - the hardware may be
  970. // gone!
  971. //
  972. PciSetPowerManagedDevicePowerState(
  973. pdoExtension,
  974. PowerDeviceD3,
  975. FALSE
  976. );
  977. pdoExtension->PowerState.CurrentDeviceState = PowerDeviceD3;
  978. powerState.DeviceState = PowerDeviceD3;
  979. PoSetPowerState(
  980. pdoExtension->PhysicalDeviceObject,
  981. DevicePowerState,
  982. powerState
  983. );
  984. }
  985. }
  986. if (!pdoExtension->ReportedMissing) {
  987. PciBeginStateTransition(DeviceExtension, PciNotStarted);
  988. } else {
  989. //
  990. // The device is physically gone, don't dare touch it!
  991. //
  992. PciBeginStateTransition(DeviceExtension, PciSurpriseRemoved);
  993. PciCommitStateTransition(DeviceExtension, PciSurpriseRemoved);
  994. }
  995. return STATUS_SUCCESS;
  996. }
  997. NTSTATUS
  998. PciPdoIrpQueryDeviceState(
  999. IN PIRP Irp,
  1000. IN PIO_STACK_LOCATION IrpSp,
  1001. IN PPCI_COMMON_EXTENSION DeviceExtension
  1002. )
  1003. {
  1004. PPCI_PDO_EXTENSION pdoExtension;
  1005. PAGED_CODE();
  1006. pdoExtension = (PPCI_PDO_EXTENSION) DeviceExtension;
  1007. //
  1008. // Host brides cannot be disabled and the user should not be given a
  1009. // opportunity to do so.
  1010. //
  1011. if ((pdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
  1012. (pdoExtension->SubClass == PCI_SUBCLASS_BR_HOST)) {
  1013. //
  1014. // PNP_DEVICE_STATE us a ULONG value just passed in the information field
  1015. // of the IRP.
  1016. //
  1017. Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
  1018. }
  1019. return STATUS_SUCCESS;
  1020. }