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.

797 lines
18 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. pnpdispatch.c
  5. Abstract:
  6. This module contains functions for General PnP Irp Handlers.
  7. Author:
  8. Nicholas Owens (Nichow) - 1999
  9. Revision History:
  10. Brandon Allsop (BrandonA) Feb, 2000 - Bug fixes and general cleanup.
  11. --*/
  12. #include "pch.h"
  13. NTSTATUS
  14. SoftPCISetEventCompletion(
  15. IN PDEVICE_OBJECT DeviceObject,
  16. IN PIRP Irp,
  17. IN PVOID Context
  18. );
  19. NTSTATUS
  20. SoftPCIPostProcessIrp(
  21. IN PSOFTPCI_DEVICE_EXTENSION DeviceExtension,
  22. IN OUT PIRP Irp
  23. );
  24. #ifdef ALLOC_PRAGMA
  25. #pragma alloc_text(PAGE,SoftPCISetEventCompletion)
  26. #pragma alloc_text(PAGE,SoftPCIPostProcessIrp)
  27. #pragma alloc_text(PAGE,SoftPCICompleteSuccess)
  28. #pragma alloc_text(PAGE,SoftPCIPassIrpDown)
  29. #pragma alloc_text(PAGE,SoftPCIPassIrpDownSuccess)
  30. #pragma alloc_text(PAGE,SoftPCIIrpRemoveDevice)
  31. #pragma alloc_text(PAGE,SoftPCIFilterStartDevice)
  32. #pragma alloc_text(PAGE,SoftPCIFilterQueryInterface)
  33. #pragma alloc_text(PAGE,SoftPCI_FdoStartDevice)
  34. #endif
  35. NTSTATUS
  36. SoftPCISetEventCompletion(
  37. IN PDEVICE_OBJECT DeviceObject,
  38. IN PIRP Irp,
  39. IN PVOID Context
  40. )
  41. /*++
  42. Routine Description:
  43. Completetion routine for synchronous IRP processing.
  44. Arguments:
  45. DeviceObject - Pointer to the device object.
  46. Irp - PnP Irp we are handling
  47. Context - Pointer to our event
  48. Return Value:
  49. NTSTATUS.
  50. --*/
  51. {
  52. UNREFERENCED_PARAMETER(DeviceObject);
  53. UNREFERENCED_PARAMETER(Irp);
  54. //
  55. // Set event
  56. //
  57. KeSetEvent(Context,
  58. IO_NO_INCREMENT,
  59. FALSE
  60. );
  61. return STATUS_MORE_PROCESSING_REQUIRED;
  62. }
  63. NTSTATUS
  64. SoftPCIPostProcessIrp(
  65. IN PSOFTPCI_DEVICE_EXTENSION DeviceExtension,
  66. IN OUT PIRP Irp
  67. )
  68. /*++
  69. Routine Description:
  70. This routine is used to defer processing of an IRP until drivers
  71. lower in the stack including the bus driver have done their
  72. processing.
  73. This routine uses an IoCompletion routine along with an event to
  74. wait until the lower level drivers have completed processing of
  75. the irp.
  76. Arguments:
  77. Extension - device extension for the devobj in question
  78. Irp - Pointer to the IRP_MJ_PNP IRP to defer
  79. Return Value:
  80. NT status.
  81. --*/
  82. {
  83. KEVENT event;
  84. NTSTATUS status;
  85. PAGED_CODE();
  86. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  87. //
  88. // Set our completion routine
  89. //
  90. IoCopyCurrentIrpStackLocationToNext(Irp);
  91. IoSetCompletionRoutine(Irp,
  92. SoftPCISetEventCompletion,
  93. &event,
  94. TRUE,
  95. TRUE,
  96. TRUE
  97. );
  98. status = IoCallDriver(DeviceExtension->LowerDevObj, Irp);
  99. if (status == STATUS_PENDING) {
  100. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  101. status = Irp->IoStatus.Status;
  102. }
  103. return status;
  104. }
  105. NTSTATUS
  106. SoftPCIPassIrpDown(
  107. IN PDEVICE_OBJECT DeviceObject,
  108. IN PIRP Irp
  109. )
  110. /*++
  111. Routine Description:
  112. This routine is used to pass down all PnP IRPs we dont care about.
  113. Arguments:
  114. DeviceObject - Pointer to the device object.
  115. Irp - PnP Irp we are sending down
  116. Return Value:
  117. NTSTATUS.
  118. --*/
  119. {
  120. PSOFTPCI_DEVICE_EXTENSION deviceExtension;
  121. //
  122. // Get the device extension.
  123. //
  124. deviceExtension = (PSOFTPCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  125. //
  126. // Pass it down
  127. //
  128. IoSkipCurrentIrpStackLocation(Irp);
  129. return IoCallDriver(deviceExtension->LowerDevObj,
  130. Irp
  131. );
  132. }
  133. NTSTATUS
  134. SoftPCIPassIrpDownSuccess(
  135. IN PDEVICE_OBJECT DeviceObject,
  136. IN PIRP Irp
  137. )
  138. /*++
  139. Routine Description:
  140. This routine deals with the required PnP IRPS which we dont really
  141. do anything with currently.
  142. Arguments:
  143. DeviceObject - Pointer to the device object.
  144. Irp - PnP Irp to succeed.
  145. Return Value:
  146. NTSTATUS.
  147. --*/
  148. {
  149. PSOFTPCI_DEVICE_EXTENSION deviceExtension;
  150. NTSTATUS status = STATUS_SUCCESS;
  151. //
  152. // Set Status of Irp and pass it down
  153. //
  154. IoSkipCurrentIrpStackLocation(Irp);
  155. //
  156. // Get the device extension.
  157. //
  158. deviceExtension = DeviceObject->DeviceExtension;
  159. //
  160. // Set the status to STATUS_SUCCESS
  161. //
  162. Irp->IoStatus.Status = status;
  163. //
  164. // Send the Irp to the next driver.
  165. //
  166. status = IoCallDriver( deviceExtension->LowerDevObj,
  167. Irp
  168. );
  169. return status;
  170. }
  171. NTSTATUS
  172. SoftPCIIrpRemoveDevice(
  173. IN PDEVICE_OBJECT DeviceObject,
  174. IN PIRP Irp
  175. )
  176. /*++
  177. Routine Description:
  178. Here we handle all IRP_MN_REMOVE_DEVICE IRPS
  179. Arguments:
  180. DeviceObject - Pointer to the device object of device we are removing
  181. Irp - PnP Irp for remove
  182. Return Value:
  183. NTSTATUS.
  184. --*/
  185. {
  186. PSOFTPCI_DEVICE_EXTENSION deviceExtension;
  187. NTSTATUS status = STATUS_SUCCESS;
  188. //
  189. // Get the device extension.
  190. //
  191. deviceExtension = DeviceObject->DeviceExtension;
  192. #ifdef SIMULATE_MSI
  193. deviceExtension->StopMsiSimulation = TRUE;
  194. #endif
  195. //
  196. // Free up any resources.
  197. //
  198. if (deviceExtension->FilterDevObj) {
  199. //
  200. // Disable the device interface.
  201. //
  202. if (deviceExtension->InterfaceRegistered) {
  203. IoSetDeviceInterfaceState(
  204. &(deviceExtension->SymbolicLinkName),
  205. FALSE
  206. );
  207. }
  208. //
  209. // Free any remaing children
  210. //
  211. if (SoftPciTree.RootDevice) {
  212. status = SoftPCIRemoveDevice(SoftPciTree.RootDevice);
  213. ASSERT(NT_SUCCESS(status));
  214. }
  215. }
  216. //
  217. // Detatch from the stack.
  218. //
  219. IoDetachDevice(deviceExtension->LowerDevObj);
  220. //
  221. // Delete the device object.
  222. //
  223. IoDeleteDevice(DeviceObject);
  224. //
  225. // Set the status to STATUS_SUCCESS
  226. //
  227. Irp->IoStatus.Status = status;
  228. //
  229. // Skip and pass down
  230. //
  231. IoSkipCurrentIrpStackLocation(Irp);
  232. status = IoCallDriver(deviceExtension->LowerDevObj,
  233. Irp
  234. );
  235. return status;
  236. }
  237. //
  238. // Filter DO PnP Irp Handlers
  239. //
  240. NTSTATUS
  241. SoftPCIFilterStartDevice(
  242. IN PDEVICE_OBJECT DeviceObject,
  243. IN PIRP Irp
  244. )
  245. /*++
  246. Routine Description:
  247. Here we handle all IRP_MN_START_DEVICE IRPS for our Filter DOs
  248. Arguments:
  249. DeviceObject - Pointer to the device object of device we are starting
  250. Irp - PnP Start Irp
  251. Return Value:
  252. NTSTATUS.
  253. --*/
  254. {
  255. NTSTATUS status = STATUS_SUCCESS;
  256. PDRIVER_OBJECT upperDrvObj;
  257. PIO_STACK_LOCATION irpSp;
  258. PSOFTPCI_DEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  259. PCM_RESOURCE_LIST resList = NULL;
  260. //
  261. // We do our work on the way up...
  262. //
  263. status = SoftPCIPostProcessIrp(deviceExtension,
  264. Irp
  265. );
  266. ASSERT(status == Irp->IoStatus.Status);
  267. //
  268. // Set the status to success if the status is correct.
  269. //
  270. if (NT_SUCCESS(status)) {
  271. //
  272. // Get current stack location
  273. //
  274. irpSp = IoGetCurrentIrpStackLocation(Irp);
  275. //
  276. // Patch PCI.SYS' Irp dispatch routines so we can get a handle to the device.
  277. // ISSUE - BrandonA 03-02-00: Remove this hack if PCI.SYS ever makes it so
  278. // we can be an upper filter instead of a lower filter.
  279. upperDrvObj = DeviceObject->AttachedDevice->DriverObject;
  280. upperDrvObj->MajorFunction[IRP_MJ_CREATE] = SoftPCIOpenDeviceControl;
  281. upperDrvObj->MajorFunction[IRP_MJ_CLOSE] = SoftPCICloseDeviceControl;
  282. //
  283. // Enable the device interface if there is one
  284. //
  285. if (deviceExtension->InterfaceRegistered) {
  286. IoSetDeviceInterfaceState(&(deviceExtension->SymbolicLinkName),
  287. TRUE
  288. );
  289. }
  290. //
  291. // At this point we need to grab the Bus number info for this root bus
  292. // and use it to create a PlaceHolder device.
  293. //
  294. // This will be required for Multi-root support
  295. resList = (PCM_RESOURCE_LIST) irpSp->Parameters.StartDevice.AllocatedResourcesTranslated;
  296. if (resList){
  297. status = SoftPCIProcessRootBus(resList);
  298. if (!NT_SUCCESS(status)) {
  299. //
  300. // If we fail this then we have to bail
  301. //
  302. }
  303. }
  304. }
  305. //
  306. // Complete the Irp.
  307. //
  308. IoCompleteRequest(Irp,
  309. IO_NO_INCREMENT
  310. );
  311. return status;
  312. }
  313. NTSTATUS
  314. SoftPCI_FdoStartDeviceCompletion(
  315. IN PDEVICE_OBJECT DeviceObject,
  316. IN PIRP Irp,
  317. IN PVOID Context
  318. )
  319. {
  320. PSOFTPCI_DEVICE_EXTENSION deviceExtension;
  321. PIO_STACK_LOCATION irpStack;
  322. #ifdef SIMULATE_MSI
  323. PIO_WORKITEM workItem;
  324. #endif
  325. UNREFERENCED_PARAMETER(Context);
  326. deviceExtension = DeviceObject->DeviceExtension;
  327. irpStack = IoGetCurrentIrpStackLocation(Irp);
  328. //
  329. // Keep track of the assigned resources.
  330. //
  331. deviceExtension->RawResources = irpStack->Parameters.StartDevice.AllocatedResources;
  332. deviceExtension->TranslatedResources = irpStack->Parameters.StartDevice.AllocatedResourcesTranslated;
  333. deviceExtension->StopMsiSimulation = FALSE;
  334. //
  335. // Spin off a work item that will connect the interrupts and
  336. // simulate some device interrupts.
  337. //
  338. #ifdef SIMULATE_MSI
  339. workItem = IoAllocateWorkItem(DeviceObject);
  340. if (workItem) {
  341. IoQueueWorkItem(workItem,
  342. SoftPCISimulateMSI,
  343. DelayedWorkQueue,
  344. workItem);
  345. }
  346. #endif
  347. return STATUS_MORE_PROCESSING_REQUIRED;
  348. }
  349. NTSTATUS
  350. SoftPCI_FdoStartDevice(
  351. IN PDEVICE_OBJECT DeviceObject,
  352. IN PIRP Irp
  353. )
  354. {
  355. PSOFTPCI_DEVICE_EXTENSION deviceExtension;
  356. NTSTATUS status = STATUS_SUCCESS;
  357. PAGED_CODE();
  358. //
  359. // Set Status of Irp and pass it down
  360. //
  361. IoCopyCurrentIrpStackLocationToNext(Irp);
  362. //
  363. // Set a completion routine.
  364. //
  365. IoSetCompletionRoutine(Irp,
  366. SoftPCI_FdoStartDeviceCompletion,
  367. NULL,
  368. TRUE,
  369. TRUE,
  370. TRUE);
  371. //
  372. // Get the device extension.
  373. //
  374. deviceExtension = DeviceObject->DeviceExtension;
  375. //
  376. // Set the status to STATUS_SUCCESS
  377. //
  378. Irp->IoStatus.Status = status;
  379. //
  380. // Send the Irp to the next driver.
  381. //
  382. status = IoCallDriver( deviceExtension->LowerDevObj,
  383. Irp
  384. );
  385. return status;
  386. }
  387. NTSTATUS
  388. SoftPCI_FdoFilterRequirements(
  389. IN PDEVICE_OBJECT DeviceObject,
  390. IN PIRP Irp
  391. )
  392. {
  393. PIO_STACK_LOCATION irpStack;
  394. PIO_RESOURCE_REQUIREMENTS_LIST resList;
  395. PIO_RESOURCE_DESCRIPTOR descriptor;
  396. ULONG currentRequirement;
  397. ULONG memRangeStart = 0;
  398. ULONG memRangeLength = 0;
  399. ULONG ioRangeStart = 0;
  400. ULONG ioRangeLength = 0;
  401. irpStack = IoGetCurrentIrpStackLocation(Irp);
  402. resList = irpStack->Parameters.FilterResourceRequirements.IoResourceRequirementList;
  403. if ((resList != NULL) &&
  404. (SoftPCIGetResourceValueFromRegistry(&memRangeStart, &memRangeLength, &ioRangeStart, &ioRangeLength))){
  405. for (currentRequirement = 0;
  406. currentRequirement < resList->List[0].Count;
  407. currentRequirement++) {
  408. descriptor = &resList->List[0].Descriptors[currentRequirement];
  409. if ((descriptor->Type == CmResourceTypePort) &&
  410. (descriptor->u.Port.Length == ioRangeLength)) {
  411. descriptor->u.Port.MinimumAddress.QuadPart = ioRangeStart;
  412. descriptor->u.Port.MaximumAddress.QuadPart = (ioRangeStart + ioRangeLength) - 1;
  413. }
  414. if ((descriptor->Type == CmResourceTypeMemory) &&
  415. (descriptor->u.Port.Length == memRangeLength)) {
  416. descriptor->u.Port.MinimumAddress.QuadPart = memRangeStart;
  417. descriptor->u.Port.MaximumAddress.QuadPart = (memRangeStart + memRangeLength) - 1;
  418. }
  419. }
  420. }
  421. return SoftPCIPassIrpDown(DeviceObject, Irp);
  422. }
  423. NTSTATUS
  424. SoftPCIFilterQueryInterface(
  425. IN PDEVICE_OBJECT DeviceObject,
  426. IN PIRP Irp
  427. )
  428. /*++
  429. Routine Description:
  430. Here we handle all IRP_MN_QUERY_INTERFACE IRPS for our Filter DOs. The objective here
  431. is to hijack the BUS_INTERFACE used for accessing configspace on the machine so that
  432. we can replace it with out own.
  433. Arguments:
  434. DeviceObject - Pointer to the device object of device we are starting
  435. Irp - PnP Start Irp
  436. Return Value:
  437. NTSTATUS.
  438. --*/
  439. {
  440. NTSTATUS status = STATUS_SUCCESS;
  441. PSOFTPCI_DEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  442. PIO_STACK_LOCATION irpSp;
  443. //
  444. // Get current stack location
  445. //
  446. irpSp = IoGetCurrentIrpStackLocation(Irp);
  447. //
  448. // If this is the right interface replace the whole lot,
  449. // otherwise handle it just like any other Irp.
  450. //
  451. if (IsEqualGUID(&GUID_PCI_BUS_INTERFACE_STANDARD, irpSp->Parameters.QueryInterface.InterfaceType)) {
  452. //
  453. // We do our work on the way up...
  454. //
  455. status = SoftPCIPostProcessIrp(deviceExtension,
  456. Irp
  457. );
  458. //
  459. // Only finish up if the Irp succeeded.
  460. //
  461. if ((NT_SUCCESS(status)) &&
  462. SoftPciTree.BusInterface != NULL) {
  463. PPCI_BUS_INTERFACE_STANDARD pciStandard;
  464. PSOFTPCI_PCIBUS_INTERFACE busInterface = SoftPciTree.BusInterface;
  465. //
  466. // Grab the interface
  467. //
  468. pciStandard = (PPCI_BUS_INTERFACE_STANDARD) irpSp->Parameters.QueryInterface.Interface;
  469. //
  470. // Save the old [Read/Write]Config routines
  471. //
  472. busInterface->ReadConfig = pciStandard->ReadConfig;
  473. busInterface->WriteConfig = pciStandard->WriteConfig;
  474. //
  475. // Put our [Read/Write]Config routines in the Interface
  476. // so PCI calls us instead of the Hal.
  477. //
  478. pciStandard->ReadConfig = SoftPCIReadConfigSpace;
  479. pciStandard->WriteConfig = SoftPCIWriteConfigSpace;
  480. //
  481. // Save the old context and update the context the caller will recieve.
  482. //
  483. busInterface->Context = pciStandard->Context;
  484. pciStandard->Context = busInterface;
  485. }
  486. //
  487. // Complete the Irp.
  488. //
  489. IoCompleteRequest(Irp,
  490. IO_NO_INCREMENT
  491. );
  492. } else {
  493. //
  494. // Pass the Irp down the stack, this is some
  495. // other interface than GUID_PCI_BUS_INTERFACE_STANDARD.
  496. //
  497. status = SoftPCIPassIrpDown(DeviceObject,
  498. Irp
  499. );
  500. }
  501. return status;
  502. }
  503. #if 0 //Currently not used.
  504. NTSTATUS
  505. SoftPCIQueryFilterCaps(
  506. IN PDEVICE_OBJECT DeviceObject,
  507. IN PIRP Irp)
  508. /*++
  509. Routine Description:
  510. Routine used to filter QUERY_CAPABILITIES
  511. Arguments:
  512. DeviceObject - Pointer to the device object.
  513. Irp - PnP Irp we are handling
  514. Return Value:
  515. NTSTATUS.
  516. --*/
  517. {
  518. KEVENT event;
  519. NTSTATUS status = STATUS_SUCCESS;
  520. PSOFTPCI_DEVICE_EXTENSION deviceExtension;
  521. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
  522. PDEVICE_CAPABILITIES devCaps = irpSp->Parameters.DeviceCapabilities.Capabilities;
  523. //
  524. // Initialize and Set event for post-processing Irp
  525. //
  526. KeInitializeEvent(&event,
  527. SynchronizationEvent,
  528. FALSE
  529. );
  530. //
  531. // Set up the next stack location for
  532. // the next driver down the stack.
  533. //
  534. IoCopyCurrentIrpStackLocationToNext(Irp);
  535. //
  536. // Set completion routine
  537. //
  538. IoSetCompletionRoutine(Irp,
  539. SoftPCISetEventCompletion,
  540. &event,
  541. TRUE,
  542. FALSE,
  543. FALSE
  544. );
  545. //
  546. // Get the device extension.
  547. //
  548. deviceExtension = DeviceObject->DeviceExtension;
  549. //
  550. // Send the Irp to the next driver.
  551. //
  552. status = IoCallDriver(deviceExtension->LowerDevObj,
  553. Irp
  554. );
  555. //
  556. // If our completion routine has not been called
  557. // then wait here until it is done.
  558. //
  559. if (status == STATUS_PENDING) {
  560. KeWaitForSingleObject(&event,
  561. Executive,
  562. KernelMode,
  563. FALSE,
  564. 0
  565. );
  566. status = Irp->IoStatus.Status;
  567. }
  568. Irp->IoStatus.Status = status;
  569. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  570. return status;
  571. }
  572. #endif