Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3410 lines
88 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. ixpnpdrv.c
  5. Abstract:
  6. Implements functionality necessary for the
  7. HAL to become a PnP-style device driver
  8. after system initialization. This is done
  9. so that the HAL can enumerate the PCI busses
  10. in the way that the PnP stuff expects.
  11. Author:
  12. Jake Oshins (jakeo) 27-Jan-1997
  13. Environment:
  14. Kernel mode only.
  15. Revision History:
  16. --*/
  17. #include "halp.h"
  18. #include "exboosts.h"
  19. #include "wchar.h"
  20. #include "pci.h"
  21. #include "pcip.h"
  22. #if defined(NT_UP) && defined(APIC_HAL)
  23. #include "apic.inc"
  24. #include "pcmp_nt.inc"
  25. #endif
  26. #ifdef ALLOC_DATA_PRAGMA
  27. #pragma const_seg("PAGECONST")
  28. #endif // ALLOC_DATA_PRAGMA
  29. //Instantiate the guids here only.
  30. #include "initguid.h"
  31. #include "wdmguid.h"
  32. #ifdef ALLOC_DATA_PRAGMA
  33. #pragma const_seg()
  34. #endif // ALLOC_DATA_PRAGMA
  35. #ifdef WANT_IRQ_ROUTING
  36. // Pci Irq Routing.
  37. #include "ixpciir.h"
  38. #endif
  39. WCHAR rgzTranslated[] = L".Translated";
  40. WCHAR rgzBusTranslated[] = L".Bus.Translated";
  41. WCHAR rgzResourceMap[] = L"\\REGISTRY\\MACHINE\\HARDWARE\\RESOURCEMAP";
  42. #if DBG
  43. ULONG HalDebug = 0;
  44. #endif
  45. extern WCHAR rgzTranslated[];
  46. extern WCHAR rgzBusTranslated[];
  47. extern WCHAR rgzResourceMap[];
  48. extern WCHAR HalHardwareIdString[];
  49. #if defined(NT_UP) && defined(APIC_HAL)
  50. extern WCHAR MpHalHardwareIdString[];
  51. #endif
  52. extern struct HalpMpInfo HalpMpInfoTable;
  53. typedef enum {
  54. Hal = 0x80,
  55. PciDriver,
  56. IsaPnpDriver,
  57. McaDriver
  58. } PDO_TYPE;
  59. typedef enum {
  60. PdoExtensionType = 0xc0,
  61. FdoExtensionType
  62. } EXTENSION_TYPE;
  63. typedef struct _PDO_EXTENSION *PPDO_EXTENSION;
  64. typedef struct _FDO_EXTENSION *PFDO_EXTENSION;
  65. typedef struct _PDO_EXTENSION{
  66. EXTENSION_TYPE ExtensionType;
  67. PDEVICE_OBJECT Next;
  68. PDEVICE_OBJECT PhysicalDeviceObject;
  69. PFDO_EXTENSION ParentFdoExtension;
  70. PDO_TYPE PdoType;
  71. ULONG BusNumber;
  72. ULONG MaxSubordinateBusNumber;
  73. PBUS_HANDLER Bus;
  74. LONG InterfaceReferenceCount;
  75. } PDO_EXTENSION, *PPDO_EXTENSION;
  76. #define ASSERT_PDO_EXTENSION(x) ASSERT((x)->ExtensionType == PdoExtensionType );
  77. typedef struct _FDO_EXTENSION{
  78. EXTENSION_TYPE ExtensionType;
  79. PDEVICE_OBJECT ChildPdoList;
  80. PDEVICE_OBJECT PhysicalDeviceObject; // PDO passed into AddDevice()
  81. PDEVICE_OBJECT FunctionalDeviceObject;
  82. PDEVICE_OBJECT AttachedDeviceObject;
  83. ULONG BusCount;
  84. } FDO_EXTENSION, *PFDO_EXTENSION;
  85. #define ASSERT_FDO_EXTENSION(x) ASSERT((x)->ExtensionType == FdoExtensionType );
  86. INT_ROUTE_INTERFACE_STANDARD PciIrqRoutingInterface = {0};
  87. NTSTATUS
  88. HalpDriverEntry (
  89. IN PDRIVER_OBJECT DriverObject,
  90. IN PUNICODE_STRING RegistryPath
  91. );
  92. NTSTATUS
  93. HalpAddDevice(
  94. IN PDRIVER_OBJECT DriverObject,
  95. IN PDEVICE_OBJECT PhysicalDeviceObject
  96. );
  97. NTSTATUS
  98. HalpDispatchPnp(
  99. IN PDEVICE_OBJECT DeviceObject,
  100. IN OUT PIRP Irp
  101. );
  102. NTSTATUS
  103. HalpDispatchPower(
  104. IN PDEVICE_OBJECT DeviceObject,
  105. IN OUT PIRP Irp
  106. );
  107. NTSTATUS
  108. HalpDispatchWmi(
  109. IN PDEVICE_OBJECT DeviceObject,
  110. IN OUT PIRP Irp
  111. );
  112. VOID
  113. HalpCompleteRequest(
  114. IN OUT PIRP Irp,
  115. IN NTSTATUS Status,
  116. IN ULONG Information
  117. );
  118. NTSTATUS
  119. HalpQueryDeviceRelations(
  120. IN PDEVICE_OBJECT DeviceObject,
  121. IN DEVICE_RELATION_TYPE RelationType,
  122. OUT PDEVICE_RELATIONS *DeviceRelations
  123. );
  124. NTSTATUS
  125. HalpQueryIdPdo(
  126. IN PDEVICE_OBJECT PdoExtension,
  127. IN BUS_QUERY_ID_TYPE IdType,
  128. IN OUT PWSTR *BusQueryId
  129. );
  130. NTSTATUS
  131. HalpQueryIdFdo(
  132. IN PDEVICE_OBJECT PdoExtension,
  133. IN BUS_QUERY_ID_TYPE IdType,
  134. IN OUT PWSTR *BusQueryId
  135. );
  136. NTSTATUS
  137. HalpQueryCapabilities(
  138. IN PDEVICE_OBJECT Pdo,
  139. IN PDEVICE_CAPABILITIES Capabilities
  140. );
  141. NTSTATUS
  142. HalpQueryDeviceText(
  143. IN PDEVICE_OBJECT DeviceObject,
  144. IN DEVICE_TEXT_TYPE IdType,
  145. IN OUT PWSTR *BusQueryId
  146. );
  147. NTSTATUS
  148. HalpQueryInterface(
  149. IN PDEVICE_OBJECT DeviceObject,
  150. IN LPCGUID InterfaceType,
  151. IN USHORT Version,
  152. IN PVOID InterfaceSpecificData,
  153. IN ULONG InterfaceBufferSize,
  154. IN OUT PINTERFACE Interface,
  155. IN OUT PULONG Length
  156. );
  157. #ifdef WANT_IRQ_ROUTING
  158. NTSTATUS
  159. HalpQueryInterfaceFdo(
  160. IN PDEVICE_OBJECT DeviceObject,
  161. IN LPCGUID InterfaceType,
  162. IN USHORT Version,
  163. IN PVOID InterfaceSpecificData,
  164. IN ULONG InterfaceBufferSize,
  165. IN OUT PINTERFACE Interface,
  166. IN OUT PULONG Length
  167. );
  168. #endif
  169. NTSTATUS
  170. HalpQueryResources(
  171. PDEVICE_OBJECT DeviceObject,
  172. PCM_RESOURCE_LIST *Resources
  173. );
  174. NTSTATUS
  175. HalpQueryResourceRequirements(
  176. PDEVICE_OBJECT DeviceObject,
  177. PIO_RESOURCE_REQUIREMENTS_LIST *Requirements
  178. );
  179. NTSTATUS
  180. HalpRemoveAssignedResources(
  181. PBUS_HANDLER Bus
  182. );
  183. VOID
  184. HalpMarkNonAcpiHal(
  185. VOID
  186. );
  187. //
  188. // Define the PNP interface functions.
  189. //
  190. VOID
  191. HalPnpInterfaceReference(
  192. PVOID Context
  193. );
  194. VOID
  195. HalPnpInterfaceDereference(
  196. PVOID Context
  197. );
  198. BOOLEAN
  199. HalPnpTranslateBusAddress(
  200. IN PVOID Context,
  201. IN PHYSICAL_ADDRESS BusAddress,
  202. IN ULONG Length,
  203. IN OUT PULONG AddressSpace,
  204. OUT PPHYSICAL_ADDRESS TranslatedAddress
  205. );
  206. struct _DMA_ADAPTER *
  207. HalPnpGetDmaAdapter(
  208. IN PVOID Context,
  209. IN struct _DEVICE_DESCRIPTION *DeviceDescriptor,
  210. OUT PULONG NumberOfMapRegisters
  211. );
  212. ULONG
  213. HalPnpReadConfig(
  214. IN PVOID Context,
  215. IN ULONG Slot,
  216. IN PVOID Buffer,
  217. IN ULONG Offset,
  218. IN ULONG Length
  219. );
  220. ULONG
  221. HalPnpWriteConfig(
  222. IN PVOID Context,
  223. IN ULONG Slot,
  224. IN PVOID Buffer,
  225. IN ULONG Offset,
  226. IN ULONG Length
  227. );
  228. NTSTATUS
  229. HalpGetPciInterfaces(
  230. IN PDEVICE_OBJECT PciPdo
  231. );
  232. #ifdef APIC_HAL
  233. NTSTATUS
  234. HalpPci2MpsBusNumber(
  235. IN UCHAR PciBusNumber,
  236. OUT UCHAR *MpsBusNumber
  237. );
  238. BOOLEAN
  239. HalpMpsBusIsRootBus(
  240. IN UCHAR MpsBus
  241. );
  242. #endif
  243. #define PCI_HAL_DRIVER_NAME L"\\Driver\\PCI_HAL"
  244. #define ISA_HAL_DRIVER_NAME L"\\Driver\\ISA_HAL"
  245. #define MCA_HAL_DRIVER_NAME L"\\Driver\\MCA_HAL"
  246. #ifdef ALLOC_PRAGMA
  247. #pragma alloc_text(PAGE, HaliInitPnpDriver)
  248. #pragma alloc_text(PAGE, HalpDriverEntry)
  249. #pragma alloc_text(PAGE, HalpAddDevice)
  250. #pragma alloc_text(PAGE, HalpDispatchPnp)
  251. #pragma alloc_text(PAGELK, HalpDispatchPower)
  252. #pragma alloc_text(PAGE, HalpDispatchWmi)
  253. #pragma alloc_text(PAGE, HalpQueryDeviceRelations)
  254. #pragma alloc_text(PAGE, HalpQueryIdPdo)
  255. #pragma alloc_text(PAGE, HalpQueryIdFdo)
  256. #pragma alloc_text(PAGE, HalpQueryCapabilities)
  257. #pragma alloc_text(PAGE, HalpQueryInterface)
  258. #ifdef WANT_IRQ_ROUTING
  259. #pragma alloc_text(PAGE, HalpQueryInterfaceFdo)
  260. #endif
  261. #pragma alloc_text(PAGE, HalpQueryDeviceText)
  262. #pragma alloc_text(PAGE, HalpQueryResources)
  263. #pragma alloc_text(PAGE, HalpQueryResourceRequirements)
  264. #pragma alloc_text(PAGE, HalpRemoveAssignedResources)
  265. #pragma alloc_text(PAGE, HalpMarkNonAcpiHal)
  266. #pragma alloc_text(INIT, HalpMarkChipsetDecode)
  267. #pragma alloc_text(PAGE, HalpOpenRegistryKey)
  268. #pragma alloc_text(PAGE, HalpGetPciInterfaces)
  269. #pragma alloc_text(PAGE, HalPnpInterfaceDereference)
  270. #endif
  271. PDRIVER_OBJECT HalpDriverObject;
  272. NTSTATUS
  273. HaliInitPnpDriver(
  274. VOID
  275. )
  276. /*++
  277. Routine Description:
  278. This routine starts the process of making the HAL into
  279. a "driver," which is necessary because we need to
  280. enumerate a Plug and Play PDO for the PCI driver and ISAPNP
  281. driver.
  282. Arguments:
  283. None.
  284. Return Value:
  285. NTSTATUS.
  286. --*/
  287. {
  288. UNICODE_STRING DriverName;
  289. NTSTATUS Status;
  290. PAGED_CODE();
  291. //
  292. // For different bus pdo, we will use different hal name such that
  293. // it is less confusion.
  294. //
  295. if (HalpHandlerForBus (PCIBus, 0)) {
  296. RtlInitUnicodeString( &DriverName, PCI_HAL_DRIVER_NAME );
  297. } else if (HalpHandlerForBus(MicroChannel, 0)) {
  298. RtlInitUnicodeString( &DriverName, MCA_HAL_DRIVER_NAME );
  299. } else {
  300. RtlInitUnicodeString( &DriverName, ISA_HAL_DRIVER_NAME );
  301. }
  302. Status = IoCreateDriver( &DriverName, HalpDriverEntry );
  303. //
  304. // John Vert (jvert) 7/23/1998
  305. // There is a value in the registry that the ACPI HAL sets to disable
  306. // the firmware mapper. Unfortunately this value is persistent. So if
  307. // you have an ACPI machine and "upgrade" it to a non-ACPI machine, the
  308. // value is still present. Workaround here is to set the value to zero.
  309. //
  310. HalpMarkNonAcpiHal();
  311. if (!NT_SUCCESS( Status )) {
  312. ASSERT( NT_SUCCESS( Status ));
  313. return Status;
  314. }
  315. return STATUS_SUCCESS;
  316. }
  317. NTSTATUS
  318. HalpDriverEntry (
  319. IN PDRIVER_OBJECT DriverObject,
  320. IN PUNICODE_STRING RegistryPath
  321. )
  322. /*++
  323. Routine Description:
  324. This is the callback function when we call IoCreateDriver to create a
  325. PnP Driver Object. In this function, we need to remember the DriverObject.
  326. Arguments:
  327. DriverObject - Pointer to the driver object created by the system.
  328. RegistryPath - is NULL.
  329. Return Value:
  330. STATUS_SUCCESS
  331. --*/
  332. {
  333. NTSTATUS Status;
  334. PDEVICE_OBJECT detectedDeviceObject = NULL;
  335. PAGED_CODE();
  336. //
  337. // File the pointer to our driver object away
  338. //
  339. HalpDriverObject = DriverObject;
  340. //
  341. // Fill in the driver object
  342. //
  343. DriverObject->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE) HalpAddDevice;
  344. DriverObject->MajorFunction[ IRP_MJ_PNP ] = HalpDispatchPnp;
  345. DriverObject->MajorFunction[ IRP_MJ_POWER ] = HalpDispatchPower;
  346. DriverObject->MajorFunction[ IRP_MJ_SYSTEM_CONTROL ] = HalpDispatchWmi;
  347. Status = IoReportDetectedDevice(DriverObject,
  348. InterfaceTypeUndefined,
  349. -1,
  350. -1,
  351. NULL,
  352. NULL,
  353. FALSE,
  354. &detectedDeviceObject);
  355. ASSERT( detectedDeviceObject != NULL );
  356. if (!(NT_SUCCESS(Status))) {
  357. HalPrint(("IoReportDetectedDevice failed"));
  358. return Status;
  359. }
  360. Status = HalpAddDevice(DriverObject, detectedDeviceObject);
  361. return Status;
  362. }
  363. NTSTATUS
  364. HalpAddDevice(
  365. IN PDRIVER_OBJECT DriverObject,
  366. IN PDEVICE_OBJECT PhysicalDeviceObject
  367. )
  368. /*++
  369. Routine Description:
  370. This routine handles AddDevice for an madeup PDO device.
  371. Arguments:
  372. DriverObject - Pointer to our pseudo driver object.
  373. DeviceObject - Pointer to the device object for which this requestapplies.
  374. Return Value:
  375. NT Status.
  376. --*/
  377. {
  378. PDEVICE_OBJECT FunctionalDeviceObject;
  379. PDEVICE_OBJECT ChildDeviceObject;
  380. PDEVICE_OBJECT AttachedDevice;
  381. NTSTATUS Status;
  382. PFDO_EXTENSION FdoExtension;
  383. PPDO_EXTENSION PdoExtension;
  384. PDEVICE_OBJECT Pdo2;
  385. ULONG BusNumber;
  386. ULONG BusCount = 0;
  387. PBUS_HANDLER Bus;
  388. WCHAR Buffer[40];
  389. UNICODE_STRING Unicode;
  390. PDO_TYPE PdoType;
  391. UCHAR MpsBusNumber;
  392. PAGED_CODE();
  393. //
  394. // We've been given the PhysicalDeviceObject. Create the
  395. // FunctionalDeviceObject. Our FDO will be nameless.
  396. //
  397. Status = IoCreateDevice(
  398. DriverObject, // our driver object
  399. sizeof(FDO_EXTENSION), // size of our extension
  400. NULL, // our name
  401. FILE_DEVICE_BUS_EXTENDER, // device type
  402. 0, // device characteristics
  403. FALSE, // not exclusive
  404. &FunctionalDeviceObject // store new device object here
  405. );
  406. if( !NT_SUCCESS( Status )){
  407. DbgBreakPoint();
  408. return Status;
  409. }
  410. //
  411. // Fill in the FDO extension
  412. //
  413. FdoExtension = (PFDO_EXTENSION) FunctionalDeviceObject->DeviceExtension;
  414. FdoExtension->ExtensionType = FdoExtensionType;
  415. FdoExtension->PhysicalDeviceObject = PhysicalDeviceObject;
  416. FdoExtension->FunctionalDeviceObject = FunctionalDeviceObject;
  417. FdoExtension->ChildPdoList = NULL;
  418. //
  419. // Now attach to the PDO we were given.
  420. //
  421. AttachedDevice = IoAttachDeviceToDeviceStack(FunctionalDeviceObject,
  422. PhysicalDeviceObject );
  423. if (AttachedDevice == NULL) {
  424. HalPrint(("Couldn't attach"));
  425. //
  426. // Couldn't attach. Delete the FDO.
  427. //
  428. IoDeleteDevice( FunctionalDeviceObject );
  429. return STATUS_NO_SUCH_DEVICE;
  430. }
  431. FdoExtension->AttachedDeviceObject = AttachedDevice;
  432. //
  433. // Clear the device initializing flag.
  434. //
  435. FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  436. //
  437. // Find any child PCI busses.
  438. //
  439. for ( BusNumber = 0;
  440. Bus = HaliReferenceHandlerForBus(PCIBus, BusNumber);
  441. BusNumber++ ) {
  442. #ifdef APIC_HAL
  443. Status = HalpPci2MpsBusNumber((UCHAR)BusNumber, &MpsBusNumber);
  444. if (NT_SUCCESS(Status)) {
  445. if (!HalpMpsBusIsRootBus(MpsBusNumber)) {
  446. //
  447. // This is not a root PCI bus, so skip it.
  448. //
  449. continue;
  450. }
  451. }
  452. #endif
  453. if (Bus->ParentHandler != NULL &&
  454. Bus->ParentHandler->InterfaceType == PCIBus) {
  455. //
  456. // Skip bridges.
  457. //
  458. HaliDereferenceBusHandler( Bus );
  459. continue;
  460. }
  461. //
  462. // Remove the system resoruces from the range lists.
  463. //
  464. Status = HalpRemoveAssignedResources( Bus );
  465. if (!NT_SUCCESS(Status)) {
  466. HaliDereferenceBusHandler( Bus );
  467. return Status;
  468. }
  469. _snwprintf( Buffer, sizeof( Buffer ), L"\\Device\\Hal Pci %d", BusCount );
  470. RtlInitUnicodeString( &Unicode, Buffer );
  471. //
  472. // Next, create a PDO for the PCI driver.
  473. //
  474. Status = IoCreateDevice(
  475. DriverObject, // our driver object
  476. sizeof(PDO_EXTENSION), // size of our extension
  477. &Unicode, // our name
  478. FILE_DEVICE_BUS_EXTENDER, // device type
  479. 0, // device characteristics
  480. FALSE, // not exclusive
  481. &ChildDeviceObject // store new device object here
  482. );
  483. if (!NT_SUCCESS(Status)) {
  484. HaliDereferenceBusHandler( Bus );
  485. return Status;
  486. }
  487. //
  488. // Fill in the PDO extension
  489. //
  490. PdoExtension = (PPDO_EXTENSION) ChildDeviceObject->DeviceExtension;
  491. PdoExtension->ExtensionType = PdoExtensionType;
  492. PdoExtension->PhysicalDeviceObject = ChildDeviceObject;
  493. PdoExtension->ParentFdoExtension = FdoExtension;
  494. PdoExtension->PdoType = PciDriver;
  495. PdoExtension->BusNumber = BusNumber;
  496. PdoExtension->MaxSubordinateBusNumber = 0xff; // correct value later
  497. PdoExtension->Bus = Bus;
  498. BusCount++;
  499. //
  500. // Record this as a child of the HAL. Add new childern at the
  501. // end of the list.
  502. //
  503. PdoExtension->Next = NULL;
  504. if (FdoExtension->ChildPdoList == NULL) {
  505. FdoExtension->ChildPdoList = ChildDeviceObject;
  506. } else {
  507. for (Pdo2 = FdoExtension->ChildPdoList;
  508. ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next != NULL;
  509. Pdo2 = ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next);
  510. ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next = ChildDeviceObject;
  511. }
  512. //
  513. // Clear the device initializing flag.
  514. //
  515. ChildDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  516. }
  517. //
  518. // Now loop through all the children PDOs making sure that
  519. // the MaxSubordinateBusNumbers are reasonable. This loop
  520. // assumes that the list is sorted by BusNumber.
  521. //
  522. Pdo2 = FdoExtension->ChildPdoList;
  523. while (Pdo2) {
  524. if (!((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next) {
  525. //
  526. // There is no next Pdo extension, which means that
  527. // this bus represents the last root bus, which means
  528. // that we can leave its subordinate bus number at 0xff.
  529. //
  530. break;
  531. }
  532. if (((PPDO_EXTENSION) Pdo2->DeviceExtension)->MaxSubordinateBusNumber >=
  533. ((PPDO_EXTENSION) ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next->DeviceExtension)->BusNumber) {
  534. //
  535. // Set the subordinate bus number at one less than the bus number of the
  536. // next root bus.
  537. //
  538. ((PPDO_EXTENSION)Pdo2->DeviceExtension)->MaxSubordinateBusNumber =
  539. ((PPDO_EXTENSION) ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next->DeviceExtension)->BusNumber - 1;
  540. }
  541. Pdo2 = ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next;
  542. }
  543. FdoExtension->BusCount = BusCount;
  544. if (BusCount == 0) {
  545. Bus = HaliReferenceHandlerForBus(Isa, 0);
  546. if (!Bus) {
  547. Bus = HaliReferenceHandlerForBus(Eisa, 0);
  548. }
  549. if (Bus) {
  550. _snwprintf( Buffer, sizeof( Buffer ), L"\\Device\\Hal Isa %d", 0 );
  551. RtlInitUnicodeString( &Unicode, Buffer );
  552. PdoType = IsaPnpDriver;
  553. } else {
  554. Bus = HaliReferenceHandlerForBus(MicroChannel, 0);
  555. ASSERT(Bus);
  556. _snwprintf( Buffer, sizeof( Buffer ), L"\\Device\\Hal Mca %d", 0 );
  557. RtlInitUnicodeString( &Unicode, Buffer );
  558. PdoType = McaDriver;
  559. }
  560. }
  561. if (Bus) {
  562. //
  563. // Next, create a PDO for the PCI driver.
  564. //
  565. Status = IoCreateDevice(
  566. DriverObject, // our driver object
  567. sizeof(PDO_EXTENSION), // size of our extension
  568. &Unicode, // our name
  569. FILE_DEVICE_BUS_EXTENDER, // device type
  570. 0, // device characteristics
  571. FALSE, // not exclusive
  572. &ChildDeviceObject // store new device object here
  573. );
  574. if (!NT_SUCCESS(Status)) {
  575. return Status;
  576. }
  577. //
  578. // Fill in the PDO extension
  579. //
  580. PdoExtension = (PPDO_EXTENSION) ChildDeviceObject->DeviceExtension;
  581. PdoExtension->ExtensionType = PdoExtensionType;
  582. PdoExtension->PhysicalDeviceObject = ChildDeviceObject;
  583. PdoExtension->ParentFdoExtension = FdoExtension;
  584. PdoExtension->BusNumber = 0;
  585. PdoExtension->MaxSubordinateBusNumber = 0;
  586. PdoExtension->Bus = Bus;
  587. PdoExtension->PdoType = PdoType;
  588. //
  589. // Record this as a child of the HAL
  590. //
  591. PdoExtension->Next = FdoExtension->ChildPdoList;
  592. FdoExtension->ChildPdoList = ChildDeviceObject;
  593. FdoExtension->BusCount = 1;
  594. //
  595. // Clear the device initializing flag.
  596. //
  597. ChildDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  598. }
  599. return STATUS_SUCCESS;
  600. }
  601. NTSTATUS
  602. HalpPassIrpFromFdoToPdo(
  603. PDEVICE_OBJECT DeviceObject,
  604. PIRP Irp
  605. )
  606. /*++
  607. Description:
  608. Given an FDO, pass the IRP to the next device object in the
  609. device stack. This is the PDO if there are no lower level
  610. filters.
  611. Arguments:
  612. DeviceObject - the Fdo
  613. Irp - the request
  614. Return Value:
  615. Returns the result from calling the next level.
  616. --*/
  617. {
  618. PIO_STACK_LOCATION irpSp; // our stack location
  619. PIO_STACK_LOCATION nextIrpSp; // next guy's
  620. PFDO_EXTENSION fdoExtension;
  621. HalPrint(("PassIrp ..."));
  622. //
  623. // Get the pointer to the device extension.
  624. //
  625. fdoExtension = (PFDO_EXTENSION)DeviceObject->DeviceExtension;
  626. IoSkipCurrentIrpStackLocation(Irp);
  627. //
  628. // Call the PDO driver with the request.
  629. //
  630. return IoCallDriver(fdoExtension->AttachedDeviceObject ,Irp);
  631. }
  632. NTSTATUS
  633. HalpDispatchPnp(
  634. IN PDEVICE_OBJECT DeviceObject,
  635. IN OUT PIRP Irp
  636. )
  637. /*++
  638. Routine Description:
  639. This routine handles all IRP_MJ_PNP_POWER IRPs for madeup PDO device.
  640. Arguments:
  641. DeviceObject - Pointer to the device object for which this IRP applies.
  642. Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
  643. Return Value:
  644. NT status.
  645. --*/
  646. {
  647. PIO_STACK_LOCATION irpSp;
  648. NTSTATUS Status;
  649. ULONG length;
  650. DEVICE_RELATION_TYPE relationType;
  651. EXTENSION_TYPE extensionType;
  652. BOOLEAN passDown;
  653. #if DBG
  654. PUCHAR objectTypeString;
  655. #endif //DBG
  656. PPDO_EXTENSION pdoExtension;
  657. PAGED_CODE();
  658. pdoExtension = (PPDO_EXTENSION)DeviceObject->DeviceExtension;
  659. extensionType = ((PFDO_EXTENSION)pdoExtension)->ExtensionType;
  660. //
  661. // Get a pointer to our stack location and take appropriate action based
  662. // on the minor function.
  663. //
  664. irpSp = IoGetCurrentIrpStackLocation(Irp);
  665. switch (extensionType) {
  666. case PdoExtensionType:
  667. #if DBG
  668. objectTypeString = "PDO";
  669. #endif //DBG
  670. switch (irpSp->MinorFunction) {
  671. case IRP_MN_START_DEVICE:
  672. HalPrint(("(%s) Start_Device Irp received",
  673. objectTypeString));
  674. Status = STATUS_SUCCESS;
  675. //
  676. // If we are starting a PCI PDO, then we want to
  677. // collect a little bit of information from the PCI driver.
  678. //
  679. if (pdoExtension->PdoType == PciDriver) {
  680. Status = HalpGetPciInterfaces(DeviceObject);
  681. ASSERT(NT_SUCCESS(Status));
  682. if (NT_SUCCESS(Status)) {
  683. PciIrqRoutingInterface.InterfaceReference(PciIrqRoutingInterface.Context);
  684. #ifdef WANT_IRQ_ROUTING
  685. //
  686. // Initialize Pci Irq Routing.
  687. //
  688. HalpPciIrqRoutingInfo.PciInterface = &PciIrqRoutingInterface;
  689. if (NT_SUCCESS(HalpInitPciIrqRouting(&HalpPciIrqRoutingInfo)))
  690. {
  691. HalPrint(("Pci Irq Routing initialized successfully!"));
  692. }
  693. else
  694. {
  695. HalPrint(("No Pci Irq routing on this system!"));
  696. }
  697. #endif
  698. } else {
  699. RtlZeroMemory(&PciIrqRoutingInterface, sizeof(INT_ROUTE_INTERFACE_STANDARD));
  700. }
  701. }
  702. break;
  703. case IRP_MN_QUERY_STOP_DEVICE:
  704. HalPrint(("(%s) Query_Stop_Device Irp received",
  705. objectTypeString));
  706. Status = STATUS_SUCCESS;
  707. break;
  708. case IRP_MN_CANCEL_STOP_DEVICE:
  709. HalPrint(("(%s) Cancel_Stop_Device Irp received",
  710. objectTypeString));
  711. Status = STATUS_SUCCESS;
  712. break;
  713. case IRP_MN_STOP_DEVICE:
  714. HalPrint(("(%s) Stop_Device Irp received",
  715. objectTypeString));
  716. //
  717. // If we get a stop device request for a PDO, we simply
  718. // return success.
  719. //
  720. Status = STATUS_SUCCESS;
  721. break;
  722. case IRP_MN_QUERY_RESOURCES:
  723. HalPrint(("(%s) Query_Resources Irp received",
  724. objectTypeString));
  725. Status = HalpQueryResources(DeviceObject,
  726. (PCM_RESOURCE_LIST *)&Irp->IoStatus.Information);
  727. Status = STATUS_SUCCESS;
  728. break;
  729. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  730. HalPrint(("(%s) Query_Resource_Requirements Irp received",
  731. objectTypeString));
  732. Status = HalpQueryResourceRequirements(DeviceObject,
  733. (PIO_RESOURCE_REQUIREMENTS_LIST*)&Irp->IoStatus.Information);
  734. break;
  735. case IRP_MN_QUERY_REMOVE_DEVICE:
  736. HalPrint(("(%s) Query_Remove_device Irp for %x",
  737. objectTypeString,
  738. DeviceObject));
  739. Status = STATUS_UNSUCCESSFUL;
  740. break;
  741. case IRP_MN_CANCEL_REMOVE_DEVICE:
  742. HalPrint(("(%s) Cancel_Remove_device Irp for %x",
  743. objectTypeString,
  744. DeviceObject));
  745. Status = STATUS_SUCCESS;
  746. break;
  747. case IRP_MN_REMOVE_DEVICE:
  748. HalPrint(("(%s) Remove_device Irp for %x",
  749. objectTypeString,
  750. DeviceObject));
  751. if ((((PPDO_EXTENSION)(DeviceObject->DeviceExtension))->PdoType == PciDriver) &&
  752. (PciIrqRoutingInterface.InterfaceReference != NULL)) {
  753. PciIrqRoutingInterface.InterfaceDereference(PciIrqRoutingInterface.Context);
  754. }
  755. Status = STATUS_SUCCESS;
  756. break;
  757. case IRP_MN_QUERY_DEVICE_RELATIONS:
  758. HalPrint(("(%s) Query_Device_Relations Irp received",
  759. objectTypeString));
  760. relationType = irpSp->Parameters.QueryDeviceRelations.Type;
  761. Status = HalpQueryDeviceRelations(DeviceObject,
  762. relationType,
  763. (PDEVICE_RELATIONS*)&Irp->IoStatus.Information);
  764. break;
  765. case IRP_MN_QUERY_DEVICE_TEXT:
  766. HalPrint(("(%s) Query Device Text Irp received",
  767. objectTypeString));
  768. Status = HalpQueryDeviceText(DeviceObject,
  769. irpSp->Parameters.QueryDeviceText.DeviceTextType,
  770. (PWSTR*)&Irp->IoStatus.Information);
  771. break;
  772. case IRP_MN_QUERY_ID:
  773. HalPrint(("(%s) Query_Id Irp received",
  774. objectTypeString));
  775. Status = HalpQueryIdPdo(DeviceObject,
  776. irpSp->Parameters.QueryId.IdType,
  777. (PWSTR*)&Irp->IoStatus.Information);
  778. break;
  779. case IRP_MN_QUERY_INTERFACE:
  780. HalPrint(("(%s) Query_Interface Irp received",
  781. objectTypeString));
  782. Status = HalpQueryInterface(
  783. DeviceObject,
  784. irpSp->Parameters.QueryInterface.InterfaceType,
  785. irpSp->Parameters.QueryInterface.Version,
  786. irpSp->Parameters.QueryInterface.InterfaceSpecificData,
  787. irpSp->Parameters.QueryInterface.Size,
  788. irpSp->Parameters.QueryInterface.Interface,
  789. &Irp->IoStatus.Information
  790. );
  791. break;
  792. case IRP_MN_QUERY_CAPABILITIES:
  793. HalPrint(("(%s) Query_Capabilities Irp received",
  794. objectTypeString));
  795. Status = HalpQueryCapabilities(DeviceObject,
  796. irpSp->Parameters.DeviceCapabilities.Capabilities);
  797. break;
  798. case IRP_MN_DEVICE_USAGE_NOTIFICATION:
  799. HalPrint(("(%s) Device_Usage_Notification Irp received",
  800. objectTypeString));
  801. Status = STATUS_SUCCESS;
  802. break;
  803. default:
  804. HalPrint(("(%s) Unsupported Irp (%d) received",
  805. objectTypeString,
  806. irpSp->MinorFunction));
  807. Status = STATUS_NOT_SUPPORTED ;
  808. break;
  809. }
  810. break; // end PDO cases
  811. case FdoExtensionType:
  812. #if DBG
  813. objectTypeString = "FDO";
  814. #endif //DBG
  815. passDown = TRUE;
  816. switch (irpSp->MinorFunction){
  817. case IRP_MN_QUERY_DEVICE_RELATIONS:
  818. HalPrint(("(%s) Query_Device_Relations Irp received",
  819. objectTypeString));
  820. relationType = irpSp->Parameters.QueryDeviceRelations.Type;
  821. Status = HalpQueryDeviceRelations(DeviceObject,
  822. relationType,
  823. (PDEVICE_RELATIONS*)&Irp->IoStatus.Information);
  824. break;
  825. case IRP_MN_QUERY_ID:
  826. HalPrint(("(%s) Query_Id Irp received",
  827. objectTypeString));
  828. Status = HalpQueryIdFdo(DeviceObject,
  829. irpSp->Parameters.QueryId.IdType,
  830. (PWSTR*)&Irp->IoStatus.Information);
  831. break;
  832. #ifdef WANT_IRQ_ROUTING
  833. case IRP_MN_QUERY_INTERFACE:
  834. HalPrint(("(%s) Query_Interface Irp received",
  835. objectTypeString));
  836. Status = HalpQueryInterfaceFdo(
  837. DeviceObject,
  838. irpSp->Parameters.QueryInterface.InterfaceType,
  839. irpSp->Parameters.QueryInterface.Version,
  840. irpSp->Parameters.QueryInterface.InterfaceSpecificData,
  841. irpSp->Parameters.QueryInterface.Size,
  842. irpSp->Parameters.QueryInterface.Interface,
  843. &Irp->IoStatus.Information
  844. );
  845. break;
  846. #endif
  847. default:
  848. //
  849. // Ignore any PNP Irps unknown by the FDO but allow them
  850. // down to the PDO.
  851. //
  852. Status = STATUS_NOT_SUPPORTED ;
  853. break;
  854. }
  855. if (passDown && (NT_SUCCESS(Status) || (Status == STATUS_NOT_SUPPORTED))) {
  856. //
  857. // Pass FDO IRPs down to the PDO.
  858. //
  859. // Set Irp status first.
  860. //
  861. if (Status != STATUS_NOT_SUPPORTED) {
  862. Irp->IoStatus.Status = Status;
  863. }
  864. HalPrint(("(%s) Passing down Irp (%x)",
  865. objectTypeString, irpSp->MinorFunction));
  866. return HalpPassIrpFromFdoToPdo(DeviceObject, Irp);
  867. }
  868. break; // end FDO cases
  869. default:
  870. HalPrint(("Received IRP for unknown Device Object"));
  871. Status = STATUS_NOT_SUPPORTED;
  872. break;
  873. }
  874. //
  875. // Complete the Irp and return.
  876. //
  877. if (Status != STATUS_NOT_SUPPORTED) {
  878. Irp->IoStatus.Status = Status;
  879. } else {
  880. Status = Irp->IoStatus.Status ;
  881. }
  882. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  883. return Status;
  884. }
  885. NTSTATUS
  886. HalpDispatchPower(
  887. IN PDEVICE_OBJECT DeviceObject,
  888. IN OUT PIRP Irp
  889. )
  890. /*++
  891. Routine Description:
  892. This routine handles all IRP_MJ_POWER IRPs for madeup device.
  893. Arguments:
  894. DeviceObject - Pointer to the device object for which this IRP applies.
  895. Irp - Pointer to the IRP_MJ_POWER IRP to dispatch.
  896. Return Value:
  897. NT status.
  898. --*/
  899. {
  900. NTSTATUS Status;
  901. EXTENSION_TYPE extensionType;
  902. PIO_STACK_LOCATION irpSp;
  903. HalPrint(("Power IRP for DevObj: %x", DeviceObject));
  904. //
  905. // Simply store the appropriate status and complete the request.
  906. //
  907. extensionType = ((PFDO_EXTENSION)(DeviceObject->DeviceExtension))->ExtensionType;
  908. irpSp = IoGetCurrentIrpStackLocation(Irp);
  909. //
  910. // Simply store the appropriate status and complete the request.
  911. //
  912. Status = Irp->IoStatus.Status;
  913. if ((irpSp->MinorFunction == IRP_MN_QUERY_POWER) ||
  914. (irpSp->MinorFunction == IRP_MN_SET_POWER)) {
  915. Irp->IoStatus.Status = Status = STATUS_SUCCESS;
  916. } else if (irpSp->MinorFunction == IRP_MN_WAIT_WAKE) {
  917. //
  918. // Fail this explicitly as we don't know how to wake the system...
  919. //
  920. Irp->IoStatus.Status = Status = STATUS_NOT_SUPPORTED;
  921. }
  922. PoStartNextPowerIrp(Irp);
  923. if (extensionType == PdoExtensionType) {
  924. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  925. } else {
  926. #ifdef APIC_HAL
  927. if (irpSp->MinorFunction == IRP_MN_SET_POWER) {
  928. if (irpSp->Parameters.Power.Type == SystemPowerState) {
  929. switch (irpSp->Parameters.Power.State.SystemState) {
  930. case PowerSystemHibernate:
  931. HalpBuildResumeStructures();
  932. break;
  933. case PowerSystemWorking:
  934. HalpFreeResumeStructures();
  935. break;
  936. default:
  937. break;
  938. }
  939. }
  940. }
  941. #endif
  942. Status = HalpPassIrpFromFdoToPdo(DeviceObject, Irp);
  943. }
  944. return Status;
  945. }
  946. NTSTATUS
  947. HalpDispatchWmi(
  948. IN PDEVICE_OBJECT DeviceObject,
  949. IN OUT PIRP Irp
  950. )
  951. {
  952. NTSTATUS Status;
  953. EXTENSION_TYPE extensionType;
  954. extensionType = ((PFDO_EXTENSION)(DeviceObject->DeviceExtension))->ExtensionType;
  955. if (extensionType == FdoExtensionType) {
  956. Status = HalpPassIrpFromFdoToPdo(DeviceObject, Irp);
  957. } else {
  958. Status = Irp->IoStatus.Status;
  959. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  960. }
  961. return Status;
  962. }
  963. NTSTATUS
  964. HalpQueryDeviceRelations(
  965. IN PDEVICE_OBJECT DeviceObject,
  966. IN DEVICE_RELATION_TYPE RelationType,
  967. OUT PDEVICE_RELATIONS *DeviceRelations
  968. )
  969. /*++
  970. Routine Description:
  971. This routine builds a DEVICE_RELATIONS structure that
  972. tells the PnP manager how many children we have.
  973. Arguments:
  974. DeviceObject - FDO of PCI_HAL
  975. RelationType - we only respond to BusRelations
  976. DeviceRelations - pointer to the structure
  977. Return Value:
  978. status
  979. --*/
  980. {
  981. PFDO_EXTENSION FdoExtension;
  982. PDEVICE_RELATIONS relations = NULL;
  983. ULONG count;
  984. PDEVICE_OBJECT *Pdo;
  985. PDEVICE_OBJECT Pdo2;
  986. EXTENSION_TYPE extensionType;
  987. PAGED_CODE();
  988. FdoExtension = (PFDO_EXTENSION)DeviceObject->DeviceExtension;
  989. extensionType = FdoExtension->ExtensionType;
  990. count = FdoExtension->BusCount;
  991. switch (RelationType) {
  992. case BusRelations:
  993. if ((extensionType == PdoExtensionType)||(count == 0)) {
  994. //
  995. // Don't touch the IRP
  996. //
  997. return STATUS_NOT_SUPPORTED ;
  998. }
  999. if (*DeviceRelations != NULL) {
  1000. count += (*DeviceRelations)->Count;
  1001. }
  1002. relations = ExAllocatePoolWithTag(
  1003. PagedPool,
  1004. sizeof(DEVICE_RELATIONS) +
  1005. (count - 1) * sizeof( PDEVICE_OBJECT),
  1006. HAL_POOL_TAG
  1007. );
  1008. if (relations == NULL) {
  1009. HalPrint(("HalpQueryDeviceRelations: couldn't allocate pool"));
  1010. return STATUS_INSUFFICIENT_RESOURCES;
  1011. }
  1012. relations->Count = count;
  1013. Pdo = relations->Objects;
  1014. count = 0;
  1015. if (*DeviceRelations != NULL) {
  1016. for ( count = 0; count < (*DeviceRelations)->Count; count++) {
  1017. *Pdo = (*DeviceRelations)->Objects[count];
  1018. Pdo++;
  1019. }
  1020. ExFreePool(*DeviceRelations);
  1021. }
  1022. //
  1023. // Add our PDO's to the list.
  1024. //
  1025. Pdo2 = FdoExtension->ChildPdoList;
  1026. while (Pdo2 != NULL) {
  1027. *Pdo = Pdo2;
  1028. ObReferenceObject(Pdo2);
  1029. Pdo2 = ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next;
  1030. Pdo++;
  1031. ASSERT( count++ < relations->Count );
  1032. }
  1033. *DeviceRelations = relations;
  1034. return STATUS_SUCCESS;
  1035. case TargetDeviceRelation:
  1036. if (extensionType == FdoExtensionType) {
  1037. //
  1038. // Don't touch the IRP
  1039. //
  1040. return STATUS_NOT_SUPPORTED ;
  1041. }
  1042. relations = ExAllocatePoolWithTag(
  1043. PagedPool,
  1044. sizeof(DEVICE_RELATIONS),
  1045. HAL_POOL_TAG
  1046. );
  1047. if (!relations) {
  1048. return STATUS_INSUFFICIENT_RESOURCES;
  1049. }
  1050. relations->Count = 1;
  1051. relations->Objects[0] = DeviceObject ;
  1052. ObReferenceObject(relations->Objects[0]);
  1053. *DeviceRelations = relations;
  1054. return STATUS_SUCCESS ;
  1055. default:
  1056. break;
  1057. }
  1058. HalPrint(("We don't support this kind of device relation"));
  1059. return STATUS_NOT_SUPPORTED ;
  1060. }
  1061. NTSTATUS
  1062. HalpQueryIdPdo(
  1063. IN PDEVICE_OBJECT DeviceObject,
  1064. IN BUS_QUERY_ID_TYPE IdType,
  1065. IN OUT PWSTR *BusQueryId
  1066. )
  1067. /*++
  1068. Routine Description:
  1069. This routine identifies each of the children that were
  1070. enumerated in HalpQueryDeviceRelations.
  1071. Arguments:
  1072. DeviceObject - PDO of the child
  1073. IdType - the type of ID to be returned.
  1074. BusQueryId - pointer to the wide string being returned
  1075. Return Value:
  1076. status
  1077. --*/
  1078. {
  1079. PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
  1080. PWSTR idString;
  1081. PWCHAR sourceString = NULL;
  1082. ULONG stringLen;
  1083. UNICODE_STRING String;
  1084. WCHAR Buffer[16];
  1085. NTSTATUS Status;
  1086. static WCHAR PciHardwareIdString[] = L"PCI_HAL\\PNP0A03";
  1087. static WCHAR PciCompatibleString[] = L"*PNP0A03";
  1088. static WCHAR IsaHardwareIdString[] = L"ISA_HAL\\PNP0A00";
  1089. static WCHAR IsaCompatibleString[] = L"*PNP0A00";
  1090. static WCHAR McaHardwareIdString[] = L"ISA_HAL\\PNP0A02";
  1091. static WCHAR McaCompatibleString[] = L"*PNP0A02";
  1092. PAGED_CODE();
  1093. switch (IdType) {
  1094. case BusQueryDeviceID:
  1095. case BusQueryHardwareIDs:
  1096. if (PdoExtension->PdoType == PciDriver) {
  1097. sourceString = PciHardwareIdString;
  1098. stringLen = sizeof(PciHardwareIdString);
  1099. } else if (PdoExtension->PdoType == IsaPnpDriver) {
  1100. sourceString = IsaHardwareIdString;
  1101. stringLen = sizeof(IsaHardwareIdString);
  1102. } else if (PdoExtension->PdoType == McaDriver) {
  1103. sourceString = McaHardwareIdString;
  1104. stringLen = sizeof(McaHardwareIdString);
  1105. }
  1106. break;
  1107. case BusQueryCompatibleIDs:
  1108. if (PdoExtension->PdoType == PciDriver) {
  1109. sourceString = PciCompatibleString;
  1110. stringLen = sizeof(PciCompatibleString);
  1111. } else if (PdoExtension->PdoType == IsaPnpDriver) {
  1112. sourceString = IsaCompatibleString;
  1113. stringLen = sizeof(IsaCompatibleString);
  1114. } else if (PdoExtension->PdoType == McaDriver) {
  1115. sourceString = McaCompatibleString;
  1116. stringLen = sizeof(McaCompatibleString);
  1117. }
  1118. break;
  1119. case BusQueryInstanceID:
  1120. String.Buffer = Buffer;
  1121. String.MaximumLength = 16 * sizeof(WCHAR);
  1122. Status = RtlIntegerToUnicodeString( PdoExtension->BusNumber, 10, &String );
  1123. //
  1124. // Note the string length in this case does not include a NULL.
  1125. // the code below will terminate the string with NULL.
  1126. //
  1127. sourceString = Buffer;
  1128. stringLen = String.Length;
  1129. break;
  1130. }
  1131. if (sourceString) {
  1132. //
  1133. // Note that hardware IDs and compatible IDs must be terminated by
  1134. // 2 NULLs.
  1135. //
  1136. idString = ExAllocatePoolWithTag(PagedPool,
  1137. stringLen + sizeof(UNICODE_NULL),
  1138. HAL_POOL_TAG);
  1139. if (!idString) {
  1140. HalPrint(("HalpQueryIdPdo: couldn't allocate pool\n"));
  1141. return STATUS_INSUFFICIENT_RESOURCES;
  1142. }
  1143. RtlCopyMemory(idString,
  1144. sourceString, stringLen);
  1145. *(idString + stringLen / sizeof(WCHAR)) = UNICODE_NULL;
  1146. *BusQueryId = idString;
  1147. return STATUS_SUCCESS;
  1148. } else {
  1149. return STATUS_NOT_SUPPORTED;
  1150. }
  1151. }
  1152. NTSTATUS
  1153. HalpQueryIdFdo(
  1154. IN PDEVICE_OBJECT DeviceObject,
  1155. IN BUS_QUERY_ID_TYPE IdType,
  1156. IN OUT PWSTR *BusQueryId
  1157. )
  1158. /*++
  1159. Routine Description:
  1160. This routine identifies each of the children that were
  1161. enumerated in HalpQueryDeviceRelations.
  1162. Arguments:
  1163. DeviceObject - PDO of the child
  1164. IdType - the type of ID to be returned.
  1165. BusQueryId - pointer to the wide string being returned
  1166. Return Value:
  1167. status
  1168. --*/
  1169. {
  1170. PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
  1171. PWSTR idString;
  1172. PWCHAR sourceString = NULL;
  1173. ULONG stringLen;
  1174. UNICODE_STRING String;
  1175. WCHAR Buffer[16];
  1176. NTSTATUS Status;
  1177. PWCHAR widechar;
  1178. static WCHAR HalInstanceIdString[] = L"0";
  1179. PAGED_CODE();
  1180. switch (IdType) {
  1181. case BusQueryDeviceID:
  1182. case BusQueryHardwareIDs:
  1183. //
  1184. // For the UP version of the APIC HAL, we want to detect if there is more
  1185. // than one processor installed. If so, we want to return the ID of
  1186. // the MP HAL rather than the UP HAL. This will induce PNP to reconfigure
  1187. // our devnode and setup the MP HAL for the next boot.
  1188. //
  1189. sourceString = HalHardwareIdString;
  1190. #if defined(NT_UP) && defined(APIC_HAL)
  1191. if (HalpMpInfoTable.ProcessorCount > 1) {
  1192. sourceString = MpHalHardwareIdString;
  1193. }
  1194. #endif
  1195. widechar = sourceString;
  1196. while (*widechar != UNICODE_NULL) {
  1197. widechar++;
  1198. }
  1199. stringLen = (PUCHAR)widechar - ((PUCHAR)sourceString) + 2;
  1200. break;
  1201. case BusQueryInstanceID:
  1202. sourceString = HalInstanceIdString;
  1203. stringLen = sizeof(HalInstanceIdString);
  1204. break;
  1205. default:
  1206. break;
  1207. }
  1208. if (sourceString) {
  1209. //
  1210. // Note that hardware IDs and compatible IDs must be terminated by
  1211. // 2 NULLs.
  1212. //
  1213. idString = ExAllocatePoolWithTag(PagedPool,
  1214. stringLen + sizeof(UNICODE_NULL),
  1215. HAL_POOL_TAG);
  1216. if (!idString) {
  1217. HalPrint(("HalpQueryIdFdo: couldn't allocate pool\n"));
  1218. return STATUS_INSUFFICIENT_RESOURCES;
  1219. }
  1220. RtlCopyMemory(idString,
  1221. sourceString, stringLen);
  1222. *(idString + stringLen / sizeof(WCHAR)) = UNICODE_NULL;
  1223. *BusQueryId = idString;
  1224. return STATUS_SUCCESS;
  1225. } else {
  1226. return STATUS_NOT_SUPPORTED;
  1227. }
  1228. }
  1229. NTSTATUS
  1230. HalpQueryCapabilities(
  1231. IN PDEVICE_OBJECT Pdo,
  1232. IN PDEVICE_CAPABILITIES Capabilities
  1233. )
  1234. /*++
  1235. Routine Description:
  1236. This routine fills in the DEVICE_CAPABILITIES structure for
  1237. a device.
  1238. Arguments:
  1239. DeviceObject - PDO of the child
  1240. Capabilities - pointer to the structure to be filled in.
  1241. Return Value:
  1242. status
  1243. --*/
  1244. {
  1245. PPDO_EXTENSION PdoExtension = (PPDO_EXTENSION) Pdo->DeviceExtension;
  1246. PAGED_CODE();
  1247. ASSERT_PDO_EXTENSION( PdoExtension );
  1248. ASSERT(Capabilities->Version == 1);
  1249. if (Capabilities->Version != 1) {
  1250. return STATUS_NOT_SUPPORTED;
  1251. }
  1252. Capabilities->LockSupported = FALSE;
  1253. Capabilities->EjectSupported = FALSE;
  1254. Capabilities->Removable = FALSE;
  1255. Capabilities->DockDevice = FALSE;
  1256. Capabilities->UniqueID = TRUE;
  1257. Capabilities->SilentInstall = TRUE;
  1258. Capabilities->RawDeviceOK = FALSE;
  1259. Capabilities->Address = PdoExtension->BusNumber;
  1260. Capabilities->UINumber = PdoExtension->BusNumber;
  1261. Capabilities->D1Latency = 0;
  1262. Capabilities->D2Latency = 0;
  1263. Capabilities->D3Latency = 0;
  1264. //
  1265. // Default S->D mapping
  1266. //
  1267. Capabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
  1268. Capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  1269. Capabilities->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
  1270. //
  1271. // Make it work on NTAPM --- note that we might have to check to see
  1272. // if the machine supports APM before we do this
  1273. //
  1274. Capabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
  1275. return STATUS_SUCCESS;
  1276. }
  1277. NTSTATUS
  1278. HalpQueryInterface(
  1279. IN PDEVICE_OBJECT DeviceObject,
  1280. IN LPCGUID InterfaceType,
  1281. IN USHORT Version,
  1282. IN PVOID InterfaceSpecificData,
  1283. IN ULONG InterfaceBufferSize,
  1284. IN OUT PINTERFACE Interface,
  1285. IN OUT PULONG Length
  1286. )
  1287. /*++
  1288. Routine Description:
  1289. This routine fills in the interface structure for
  1290. a device.
  1291. Arguments:
  1292. DeviceObject - PDO of the child
  1293. InterfaceType - Pointer to the interface type GUID.
  1294. Version - Supplies the requested interface version.
  1295. InterfaceSpecificData - This is context that means something based on the
  1296. interface.
  1297. InterfaceBufferSize - Supplies the length of the buffer for the interface
  1298. structure.
  1299. Interface - Supplies a pointer where the interface informaiton should
  1300. be returned.
  1301. Length - This value is updated on return to actual number of bytes modified.
  1302. Return Value:
  1303. status
  1304. --*/
  1305. {
  1306. PPDO_EXTENSION PdoExtension = (PPDO_EXTENSION)DeviceObject->DeviceExtension;
  1307. CM_RESOURCE_TYPE resource = (CM_RESOURCE_TYPE)InterfaceSpecificData;
  1308. PAGED_CODE();
  1309. ASSERT_PDO_EXTENSION(PdoExtension);
  1310. if (IsEqualGUID(&GUID_BUS_INTERFACE_STANDARD, InterfaceType)) {
  1311. PBUS_INTERFACE_STANDARD standard = (PBUS_INTERFACE_STANDARD)Interface;
  1312. //
  1313. // ASSERT we know about all of the fields in the structure.
  1314. //
  1315. ASSERT(sizeof(BUS_INTERFACE_STANDARD) == FIELD_OFFSET(BUS_INTERFACE_STANDARD, GetBusData) + sizeof(PGET_SET_DEVICE_DATA));
  1316. *Length = sizeof(BUS_INTERFACE_STANDARD);
  1317. if (InterfaceBufferSize < sizeof(BUS_INTERFACE_STANDARD)) {
  1318. return STATUS_BUFFER_TOO_SMALL;
  1319. }
  1320. //
  1321. // The only version this code knows about is 1.
  1322. //
  1323. standard->Size = sizeof(BUS_INTERFACE_STANDARD);
  1324. standard->Version = HAL_BUS_INTERFACE_STD_VERSION;
  1325. standard->Context = DeviceObject;
  1326. standard->InterfaceReference = HalPnpInterfaceReference;
  1327. standard->InterfaceDereference = HalPnpInterfaceDereference;
  1328. standard->TranslateBusAddress = HalPnpTranslateBusAddress;
  1329. standard->GetDmaAdapter = HalPnpGetDmaAdapter;
  1330. standard->SetBusData = NULL;
  1331. standard->GetBusData = NULL;
  1332. } else if ((IsEqualGUID(&GUID_PCI_BUS_INTERFACE_STANDARD, InterfaceType)) &&
  1333. (PdoExtension->PdoType == PciDriver)) {
  1334. PPCI_BUS_INTERFACE_STANDARD pciStandard = (PPCI_BUS_INTERFACE_STANDARD)Interface;
  1335. *Length = sizeof(PCI_BUS_INTERFACE_STANDARD);
  1336. if (InterfaceBufferSize < sizeof(PCI_BUS_INTERFACE_STANDARD)) {
  1337. return STATUS_BUFFER_TOO_SMALL;
  1338. }
  1339. //
  1340. // Fill in the interface, which is used for reading and
  1341. // writing PCI configuration space.
  1342. //
  1343. pciStandard->Size = sizeof(PCI_BUS_INTERFACE_STANDARD);
  1344. pciStandard->Version = PCI_BUS_INTERFACE_STANDARD_VERSION;
  1345. pciStandard->Context = DeviceObject;
  1346. pciStandard->InterfaceReference = HalPnpInterfaceReference;
  1347. pciStandard->InterfaceDereference = HalPnpInterfaceDereference;
  1348. pciStandard->ReadConfig = HaliPciInterfaceReadConfig;
  1349. pciStandard->WriteConfig = HaliPciInterfaceWriteConfig;
  1350. pciStandard->PinToLine = NULL;
  1351. pciStandard->LineToPin = NULL;
  1352. #if 0
  1353. } else if (IsEqualGUID(&GUID_TRANSLATOR_INTERFACE_STANDARD, InterfaceType)) {
  1354. PTRANSLATOR_INTERFACE translator = (PTRANSLATOR_INTERFACE)Interface;
  1355. if (InterfaceBufferSize < sizeof(TRANSLATOR_INTERFACE)) {
  1356. *Length = sizeof(TRANSLATOR_INTERFACE);
  1357. return STATUS_BUFFER_TOO_SMALL;
  1358. }
  1359. switch ((CM_RESOURCE_TYPE)InterfaceSpecificData) {
  1360. case CmResourceTypeInterrupt:
  1361. switch(PdoExtension->PdoType) {
  1362. case PciDriver:
  1363. translator->Context = (PVOID)PCIBus;
  1364. break;
  1365. case IsaPnpDriver:
  1366. translator->Context = (PVOID)Isa;
  1367. break;
  1368. case McaDriver:
  1369. translator->Context = (PVOID)MicroChannel;
  1370. break;
  1371. default:
  1372. //
  1373. // Don't know how to handle this.
  1374. //
  1375. HalPrint(("HAL: PDO %08x unknown Type 0x%x, failing QueryInterface\n",
  1376. DeviceObject,
  1377. PdoExtension->PdoType
  1378. ));
  1379. return STATUS_NOT_SUPPORTED;
  1380. }
  1381. translator->Version = HAL_IRQ_TRANSLATOR_VERSION;
  1382. translator->TranslateResources = HalIrqTranslateResourcesRoot;
  1383. translator->TranslateResourceRequirements =
  1384. HalIrqTranslateResourceRequirementsRoot;
  1385. break;
  1386. // Truth is, halx86 doesn't provide translators for memory or
  1387. // io resources either. But if it did, it would look like this.
  1388. case CmResourceTypeMemory:
  1389. case CmResourceTypePort:
  1390. translator->Context = DeviceObject;
  1391. translator->Version = HAL_MEMIO_TRANSLATOR_VERSION;
  1392. translator->TranslateResources = HalpTransMemIoResource;
  1393. translator->TranslateResourceRequirements =
  1394. HalpTransMemIoResourceRequirement;
  1395. break;
  1396. default:
  1397. return STATUS_NOT_SUPPORTED;
  1398. }
  1399. //
  1400. // Common initialization
  1401. //
  1402. translator->Size = sizeof(TRANSLATOR_INTERFACE);
  1403. translator->InterfaceReference = HalPnpInterfaceReference;
  1404. translator->InterfaceDereference = HalPnpInterfaceDereference;
  1405. *Length = sizeof(TRANSLATOR_INTERFACE);
  1406. #endif
  1407. #ifdef WANT_IRQ_ROUTING
  1408. } else if ( IsPciIrqRoutingEnabled() &&
  1409. IsEqualGUID(&GUID_TRANSLATOR_INTERFACE_STANDARD, InterfaceType) &&
  1410. resource == CmResourceTypeInterrupt &&
  1411. PdoExtension->PdoType == PciDriver) {
  1412. //
  1413. // We want to arbitrate on untranslated resources, so we get rid of Irq
  1414. // translator provided by Pci iff Irq Routing is enabled.
  1415. //
  1416. HalPrint(("Getting rid of Pci Irq translator interface since Pci Irq Routing is enabled!"));
  1417. RtlZeroMemory((LPGUID)InterfaceType, sizeof(GUID));
  1418. return STATUS_NOT_SUPPORTED;
  1419. #endif
  1420. } else {
  1421. //
  1422. // Unsupport bus interface type.
  1423. //
  1424. return STATUS_NOT_SUPPORTED ;
  1425. }
  1426. //
  1427. // Bump the reference count.
  1428. //
  1429. InterlockedIncrement(&PdoExtension->InterfaceReferenceCount);
  1430. return STATUS_SUCCESS;
  1431. }
  1432. #ifdef WANT_IRQ_ROUTING
  1433. NTSTATUS
  1434. HalpQueryInterfaceFdo(
  1435. IN PDEVICE_OBJECT DeviceObject,
  1436. IN LPCGUID InterfaceType,
  1437. IN USHORT Version,
  1438. IN PVOID InterfaceSpecificData,
  1439. IN ULONG InterfaceBufferSize,
  1440. IN OUT PINTERFACE Interface,
  1441. IN OUT PULONG Length
  1442. )
  1443. /*++
  1444. Routine Description:
  1445. This routine fills in the interface structure for
  1446. a device.
  1447. Arguments:
  1448. DeviceObject - FDO of the child
  1449. InterfaceType - Pointer to the interface type GUID.
  1450. Version - Supplies the requested interface version.
  1451. InterfaceSpecificData - This is context that means something based on the
  1452. interface.
  1453. InterfaceBufferSize - Supplies the length of the buffer for the interface
  1454. structure.
  1455. Interface - Supplies a pointer where the interface informaiton should
  1456. be returned.
  1457. Length - Supplies the length of the buffer for the interface structure.
  1458. This value is updated on return to actual number of bytes modified.
  1459. Return Value:
  1460. status
  1461. --*/
  1462. {
  1463. NTSTATUS status = STATUS_NOT_SUPPORTED;
  1464. CM_RESOURCE_TYPE resource = (CM_RESOURCE_TYPE)InterfaceSpecificData;
  1465. PAGED_CODE();
  1466. if ( resource == CmResourceTypeInterrupt &&
  1467. IsPciIrqRoutingEnabled()) {
  1468. if (IsEqualGUID(&GUID_ARBITER_INTERFACE_STANDARD, InterfaceType)) {
  1469. status = HalpInitIrqArbiter(DeviceObject);
  1470. if (NT_SUCCESS(status))
  1471. {
  1472. status = HalpFillInIrqArbiter(
  1473. DeviceObject,
  1474. InterfaceType,
  1475. Version,
  1476. InterfaceSpecificData,
  1477. InterfaceBufferSize,
  1478. Interface,
  1479. Length
  1480. );
  1481. }
  1482. }
  1483. else if (IsEqualGUID(&GUID_TRANSLATOR_INTERFACE_STANDARD, InterfaceType)) {
  1484. PTRANSLATOR_INTERFACE translator;
  1485. *Length = sizeof(TRANSLATOR_INTERFACE);
  1486. if (InterfaceBufferSize < sizeof(TRANSLATOR_INTERFACE)) {
  1487. return STATUS_BUFFER_TOO_SMALL;
  1488. }
  1489. translator = (PTRANSLATOR_INTERFACE)Interface;
  1490. //
  1491. // Fill in the common bits.
  1492. //
  1493. RtlZeroMemory(translator, sizeof (TRANSLATOR_INTERFACE));
  1494. translator->Size = sizeof(TRANSLATOR_INTERFACE);
  1495. translator->Version = HAL_IRQ_TRANSLATOR_VERSION;
  1496. translator->Context = DeviceObject;
  1497. translator->InterfaceReference = HalTranslatorReference;
  1498. translator->InterfaceDereference = HalTranslatorDereference;
  1499. //
  1500. // Set IRQ translator for PCI interrupts.
  1501. //
  1502. translator->TranslateResources = HalIrqTranslateResourcesRoot;
  1503. translator->TranslateResourceRequirements =
  1504. HalIrqTranslateResourceRequirementsRoot;
  1505. status = STATUS_SUCCESS;
  1506. HalPrint(("Providing Irq translator for FDO %08x since Pci Irq Routing is enabled!", DeviceObject));
  1507. }
  1508. }
  1509. return (status);
  1510. }
  1511. #endif
  1512. NTSTATUS
  1513. HalpQueryDeviceText(
  1514. IN PDEVICE_OBJECT DeviceObject,
  1515. IN DEVICE_TEXT_TYPE IdType,
  1516. IN OUT PWSTR *BusQueryId
  1517. )
  1518. /*++
  1519. Routine Description:
  1520. This routine identifies each of the children that were
  1521. enumerated in HalpQueryDeviceRelations.
  1522. Arguments:
  1523. DeviceObject - PDO of the child
  1524. IdType - the type of ID to be returned.
  1525. BusQueryId - pointer to the wide string being returned
  1526. Return Value:
  1527. status
  1528. --*/
  1529. {
  1530. PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
  1531. PWSTR idString;
  1532. PWCHAR sourceString = NULL;
  1533. ULONG stringLen;
  1534. NTSTATUS Status;
  1535. static WCHAR PciDeviceNameText[] = L"Pci Root Bus";
  1536. static WCHAR IsaDeviceNameText[] = L"Isa Root Bus";
  1537. static WCHAR McaDeviceNameText[] = L"Mca Root Bus";
  1538. PAGED_CODE();
  1539. if (PdoExtension->PdoType == PciDriver) {
  1540. sourceString = PciDeviceNameText;
  1541. stringLen = sizeof(PciDeviceNameText);
  1542. } else if (PdoExtension->PdoType == IsaPnpDriver) {
  1543. sourceString = IsaDeviceNameText;
  1544. stringLen = sizeof(IsaDeviceNameText);
  1545. } else if (PdoExtension->PdoType == McaDriver) {
  1546. sourceString = McaDeviceNameText;
  1547. stringLen = sizeof(McaDeviceNameText);
  1548. }
  1549. if (sourceString) {
  1550. switch (IdType) {
  1551. case DeviceTextDescription:
  1552. case DeviceTextLocationInformation:
  1553. idString = ExAllocatePoolWithTag(PagedPool,
  1554. stringLen,
  1555. HAL_POOL_TAG);
  1556. if (!idString) {
  1557. HalPrint(("HalpQueryDeviceText: couldn't allocate pool\n"));
  1558. return STATUS_INSUFFICIENT_RESOURCES;
  1559. }
  1560. RtlCopyMemory(idString,
  1561. sourceString, stringLen);
  1562. *BusQueryId = idString;
  1563. return STATUS_SUCCESS;
  1564. }
  1565. }
  1566. return STATUS_NOT_SUPPORTED;
  1567. }
  1568. NTSTATUS
  1569. HalpQueryResources(
  1570. IN PDEVICE_OBJECT DeviceObject,
  1571. IN PCM_RESOURCE_LIST *Resources
  1572. )
  1573. /*++
  1574. Routine Description:
  1575. This routine handles IRP_MN_QUERY_RESOURCE_REQUIREMENTS.
  1576. Arguments:
  1577. DeviceObject - PDO of the child
  1578. Resources - pointer to be filled in with the devices
  1579. resource list.
  1580. Return Value:
  1581. status
  1582. --*/
  1583. {
  1584. PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
  1585. PCM_RESOURCE_LIST ResourceList;
  1586. PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  1587. PSUPPORTED_RANGE Range;
  1588. ULONG ResourceListSize;
  1589. ULONG Count = 1;
  1590. if (PdoExtension->PdoType != PciDriver) {
  1591. *Resources = NULL;
  1592. return STATUS_SUCCESS;
  1593. }
  1594. //
  1595. // Determine the number of resourse list needed. Already counted
  1596. // one for the Bus Number.
  1597. //
  1598. for (Range = &PdoExtension->Bus->BusAddresses->IO; Range != NULL; Range = Range->Next) {
  1599. //
  1600. // If the limit is zero then skip this entry.
  1601. //
  1602. if (Range->Limit == 0) {
  1603. continue;
  1604. }
  1605. Count++;
  1606. }
  1607. for (Range = &PdoExtension->Bus->BusAddresses->Memory; Range != NULL; Range = Range->Next) {
  1608. //
  1609. // If the limit is zero then skip this entry.
  1610. //
  1611. if (Range->Limit == 0) {
  1612. continue;
  1613. }
  1614. Count++;
  1615. }
  1616. for (Range = &PdoExtension->Bus->BusAddresses->PrefetchMemory; Range != NULL; Range = Range->Next) {
  1617. //
  1618. // If the limit is zero then skip this entry.
  1619. //
  1620. if (Range->Limit == 0) {
  1621. continue;
  1622. }
  1623. Count++;
  1624. }
  1625. //
  1626. // Convert this resourceListSize into the number of bytes that we
  1627. // must allocate
  1628. //
  1629. ResourceListSize = sizeof(CM_RESOURCE_LIST) +
  1630. ( (Count - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) );
  1631. ResourceList = ExAllocatePoolWithTag(
  1632. PagedPool,
  1633. ResourceListSize,
  1634. HAL_POOL_TAG);
  1635. if (ResourceList == NULL ) {
  1636. return STATUS_INSUFFICIENT_RESOURCES;
  1637. }
  1638. RtlZeroMemory( ResourceList, ResourceListSize );
  1639. //
  1640. // Initialize the list header.
  1641. //
  1642. ResourceList->Count = 1;
  1643. ResourceList->List[0].InterfaceType = PNPBus;
  1644. ResourceList->List[0].BusNumber = -1;
  1645. ResourceList->List[0].PartialResourceList.Version = 1;
  1646. ResourceList->List[0].PartialResourceList.Revision = 1;
  1647. ResourceList->List[0].PartialResourceList.Count = Count;
  1648. Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
  1649. //
  1650. // Create descriptor for the Bus Number.
  1651. //
  1652. Descriptor->Type = CmResourceTypeBusNumber;
  1653. Descriptor->ShareDisposition = CmResourceShareShared;
  1654. Descriptor->u.BusNumber.Start = PdoExtension->BusNumber;
  1655. Descriptor->u.BusNumber.Length = PdoExtension->MaxSubordinateBusNumber -
  1656. PdoExtension->BusNumber + 1;
  1657. Descriptor++;
  1658. for (Range = &PdoExtension->Bus->BusAddresses->IO; Range != NULL; Range = Range->Next) {
  1659. //
  1660. // If the limit is zero then skip this entry.
  1661. //
  1662. if (Range->Limit == 0) {
  1663. continue;
  1664. }
  1665. Descriptor->Type = CmResourceTypePort;
  1666. Descriptor->ShareDisposition = CmResourceShareShared;
  1667. Descriptor->Flags = CM_RESOURCE_PORT_IO;
  1668. Descriptor->u.Port.Length = (ULONG)(Range->Limit - Range->Base) + 1;
  1669. Descriptor->u.Port.Start.QuadPart = Range->Base;
  1670. Descriptor++;
  1671. }
  1672. for (Range = &PdoExtension->Bus->BusAddresses->Memory; Range != NULL; Range = Range->Next) {
  1673. //
  1674. // If the limit is zero then skip this entry.
  1675. //
  1676. if (Range->Limit == 0) {
  1677. continue;
  1678. }
  1679. Descriptor->Type = CmResourceTypeMemory;
  1680. Descriptor->ShareDisposition = CmResourceShareShared;
  1681. Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  1682. Descriptor->u.Memory.Length = (ULONG)(Range->Limit - Range->Base) + 1;
  1683. Descriptor->u.Memory.Start.QuadPart = Range->Base;
  1684. Descriptor++;
  1685. }
  1686. for (Range = &PdoExtension->Bus->BusAddresses->PrefetchMemory; Range != NULL; Range = Range->Next) {
  1687. //
  1688. // If the limit is zero then skip this entry.
  1689. //
  1690. if (Range->Limit == 0) {
  1691. continue;
  1692. }
  1693. Descriptor->Type = CmResourceTypeMemory;
  1694. Descriptor->ShareDisposition = CmResourceShareShared;
  1695. Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_PREFETCHABLE;
  1696. Descriptor->u.Memory.Length = (ULONG)(Range->Limit - Range->Base) + 1;
  1697. Descriptor->u.Memory.Start.QuadPart = Range->Base;
  1698. Descriptor++;
  1699. }
  1700. *Resources = ResourceList;
  1701. return STATUS_SUCCESS;
  1702. }
  1703. NTSTATUS
  1704. HalpQueryResourceRequirements(
  1705. IN PDEVICE_OBJECT DeviceObject,
  1706. IN PIO_RESOURCE_REQUIREMENTS_LIST *Requirements
  1707. )
  1708. /*++
  1709. Routine Description:
  1710. This routine handles IRP_MN_QUERY_RESOURCE_REQUIREMENTS.
  1711. Arguments:
  1712. DeviceObject - PDO of the child
  1713. Requirements - pointer to be filled in with the devices
  1714. resource requirements.
  1715. Return Value:
  1716. status
  1717. --*/
  1718. {
  1719. PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
  1720. PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
  1721. PIO_RESOURCE_DESCRIPTOR Descriptor;
  1722. PSUPPORTED_RANGE Range;
  1723. ULONG ResourceListSize;
  1724. ULONG Count = 0;
  1725. if (PdoExtension->PdoType != PciDriver) {
  1726. *Requirements = NULL;
  1727. return STATUS_SUCCESS;
  1728. }
  1729. //
  1730. // Determine the number of resourse list needed.
  1731. //
  1732. for (Range = &PdoExtension->Bus->BusAddresses->IO; Range != NULL; Range = Range->Next) {
  1733. //
  1734. // If the limit is zero then skip this entry.
  1735. //
  1736. if (Range->Limit == 0) {
  1737. continue;
  1738. }
  1739. Count++;
  1740. }
  1741. for (Range = &PdoExtension->Bus->BusAddresses->Memory; Range != NULL; Range = Range->Next) {
  1742. //
  1743. // If the limit is zero then skip this entry.
  1744. //
  1745. if (Range->Limit == 0) {
  1746. continue;
  1747. }
  1748. Count++;
  1749. }
  1750. for (Range = &PdoExtension->Bus->BusAddresses->PrefetchMemory; Range != NULL; Range = Range->Next) {
  1751. //
  1752. // If the limit is zero then skip this entry.
  1753. //
  1754. if (Range->Limit == 0) {
  1755. continue;
  1756. }
  1757. Count++;
  1758. }
  1759. //
  1760. // Convert this resourceListSize into the number of bytes that we
  1761. // must allocate
  1762. //
  1763. ResourceListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
  1764. ( (Count - 1) * sizeof(IO_RESOURCE_DESCRIPTOR) );
  1765. ResourceList = ExAllocatePoolWithTag(
  1766. PagedPool,
  1767. ResourceListSize,
  1768. HAL_POOL_TAG);
  1769. if (ResourceList == NULL ) {
  1770. return STATUS_INSUFFICIENT_RESOURCES;
  1771. }
  1772. RtlZeroMemory( ResourceList, ResourceListSize );
  1773. ResourceList->ListSize = ResourceListSize;
  1774. //
  1775. // Initialize the list header.
  1776. //
  1777. ResourceList->AlternativeLists = 1;
  1778. ResourceList->InterfaceType = PNPBus;
  1779. ResourceList->BusNumber = -1;
  1780. ResourceList->List[0].Version = 1;
  1781. ResourceList->List[0].Revision = 1;
  1782. ResourceList->List[0].Count = Count;
  1783. Descriptor = ResourceList->List[0].Descriptors;
  1784. for (Range = &PdoExtension->Bus->BusAddresses->IO; Range != NULL; Range = Range->Next) {
  1785. //
  1786. // If the limit is zero then skip this entry.
  1787. //
  1788. if (Range->Limit == 0) {
  1789. continue;
  1790. }
  1791. Descriptor->Type = CmResourceTypePort;
  1792. Descriptor->ShareDisposition = CmResourceShareShared;
  1793. Descriptor->Flags = CM_RESOURCE_PORT_IO;
  1794. Descriptor->u.Port.Length = (ULONG) (Range->Limit - Range->Base + 1);
  1795. Descriptor->u.Port.Alignment = 0x01;
  1796. Descriptor->u.Port.MinimumAddress.QuadPart = Range->Base;
  1797. Descriptor->u.Port.MaximumAddress.QuadPart = Range->Limit;
  1798. Descriptor++;
  1799. }
  1800. for (Range = &PdoExtension->Bus->BusAddresses->Memory; Range != NULL; Range = Range->Next) {
  1801. //
  1802. // If the limit is zero then skip this entry.
  1803. //
  1804. if (Range->Limit == 0) {
  1805. continue;
  1806. }
  1807. Descriptor->Type = CmResourceTypeMemory;
  1808. Descriptor->ShareDisposition = CmResourceShareShared;
  1809. Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  1810. Descriptor->u.Memory.Length = (ULONG) (Range->Limit - Range->Base + 1);
  1811. Descriptor->u.Memory.Alignment = 0x01;
  1812. Descriptor->u.Memory.MinimumAddress.QuadPart = Range->Base;
  1813. Descriptor->u.Memory.MaximumAddress.QuadPart = Range->Limit;
  1814. Descriptor++;
  1815. }
  1816. for (Range = &PdoExtension->Bus->BusAddresses->PrefetchMemory; Range != NULL; Range = Range->Next) {
  1817. //
  1818. // If the limit is zero then skip this entry.
  1819. //
  1820. if (Range->Limit == 0) {
  1821. continue;
  1822. }
  1823. Descriptor->Type = CmResourceTypeMemory;
  1824. Descriptor->ShareDisposition = CmResourceShareShared;
  1825. Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_PREFETCHABLE;
  1826. Descriptor->u.Memory.Length = (ULONG) (Range->Limit - Range->Base + 1);
  1827. Descriptor->u.Memory.Alignment = 0x01;
  1828. Descriptor->u.Memory.MinimumAddress.QuadPart = Range->Base;
  1829. Descriptor->u.Memory.MaximumAddress.QuadPart = Range->Limit;
  1830. Descriptor++;
  1831. }
  1832. *Requirements = ResourceList;
  1833. return STATUS_SUCCESS;
  1834. }
  1835. NTSTATUS
  1836. HalpRemoveAssignedResources (
  1837. PBUS_HANDLER Bus
  1838. )
  1839. /*
  1840. Routine Description:
  1841. Reads the rgzResourceMap in the registry and builds a canonical list of
  1842. all in use resources ranges by resource type.
  1843. Arguments:
  1844. */
  1845. {
  1846. HANDLE ClassKeyHandle, DriverKeyHandle;
  1847. HANDLE ResourceMap;
  1848. ULONG ClassKeyIndex, DriverKeyIndex, DriverValueIndex;
  1849. PCM_RESOURCE_LIST CmResList;
  1850. PCM_FULL_RESOURCE_DESCRIPTOR CmFResDesc;
  1851. PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc;
  1852. UNICODE_STRING KeyName;
  1853. ULONG BufferSize;
  1854. union {
  1855. PVOID Buffer;
  1856. PKEY_BASIC_INFORMATION KeyBInf;
  1857. PKEY_FULL_INFORMATION KeyFInf;
  1858. PKEY_VALUE_FULL_INFORMATION VKeyFInf;
  1859. } U;
  1860. PUCHAR LastAddr;
  1861. ULONG Temp, Length, i, j;
  1862. ULONG TranslatedStrLen;
  1863. ULONG BusTranslatedStrLen;
  1864. NTSTATUS Status;
  1865. LONGLONG li;
  1866. PAGED_CODE();
  1867. //
  1868. // Removed page zero.
  1869. //
  1870. HalpRemoveRange( &Bus->BusAddresses->Memory,
  1871. 0i64,
  1872. (LONGLONG) (PAGE_SIZE - 1)
  1873. );
  1874. //
  1875. // Start out with one page of buffer.
  1876. //
  1877. BufferSize = PAGE_SIZE;
  1878. U.Buffer = ExAllocatePoolWithTag(
  1879. PagedPool,
  1880. BufferSize,
  1881. HAL_POOL_TAG);
  1882. if (U.Buffer == NULL) {
  1883. return STATUS_INSUFFICIENT_RESOURCES;
  1884. }
  1885. for (TranslatedStrLen=0; rgzTranslated[TranslatedStrLen]; TranslatedStrLen++) ;
  1886. for (BusTranslatedStrLen=0; rgzBusTranslated[BusTranslatedStrLen]; BusTranslatedStrLen++) ;
  1887. TranslatedStrLen *= sizeof (WCHAR);
  1888. BusTranslatedStrLen *= sizeof (WCHAR);
  1889. RtlInitUnicodeString( &KeyName, rgzResourceMap );
  1890. Status = HalpOpenRegistryKey( &ResourceMap, NULL, &KeyName, KEY_READ, FALSE );
  1891. if (!NT_SUCCESS( Status )) {
  1892. HalPrint(("HalRemoveSystemResourcesFromPci: Failed to open resource map key Status = %lx\n", Status ));
  1893. ExFreePool( U.Buffer );
  1894. return Status;
  1895. }
  1896. //
  1897. // Walk resource map and collect any inuse resources
  1898. //
  1899. ClassKeyIndex = 0;
  1900. ClassKeyHandle = INVALID_HANDLE;
  1901. DriverKeyHandle = INVALID_HANDLE;
  1902. Status = STATUS_SUCCESS;
  1903. while (NT_SUCCESS(Status)) {
  1904. //
  1905. // Get the class information
  1906. //
  1907. Status = ZwEnumerateKey( ResourceMap,
  1908. ClassKeyIndex++,
  1909. KeyBasicInformation,
  1910. U.KeyBInf,
  1911. BufferSize,
  1912. &Temp );
  1913. if (!NT_SUCCESS( Status )) {
  1914. break;
  1915. }
  1916. //
  1917. // Create a UNICODE_STRING using the counted string passed back to
  1918. // us in the information structure, and open the class key.
  1919. //
  1920. KeyName.Buffer = (PWSTR) U.KeyBInf->Name;
  1921. KeyName.Length = (USHORT) U.KeyBInf->NameLength;
  1922. KeyName.MaximumLength = (USHORT) U.KeyBInf->NameLength;
  1923. Status = HalpOpenRegistryKey( &ClassKeyHandle,
  1924. ResourceMap,
  1925. &KeyName,
  1926. KEY_READ,
  1927. FALSE );
  1928. if (!NT_SUCCESS( Status )) {
  1929. break;
  1930. }
  1931. DriverKeyIndex = 0;
  1932. while (NT_SUCCESS (Status)) {
  1933. //
  1934. // Get the class information
  1935. //
  1936. Status = ZwEnumerateKey( ClassKeyHandle,
  1937. DriverKeyIndex++,
  1938. KeyBasicInformation,
  1939. U.KeyBInf,
  1940. BufferSize,
  1941. &Temp );
  1942. if (!NT_SUCCESS( Status )) {
  1943. break;
  1944. }
  1945. //
  1946. // Create a UNICODE_STRING using the counted string passed back to
  1947. // us in the information structure, and open the class key.
  1948. //
  1949. // This is read from the key we created, and the name
  1950. // was NULL terminated.
  1951. //
  1952. KeyName.Buffer = (PWSTR) U.KeyBInf->Name;
  1953. KeyName.Length = (USHORT) U.KeyBInf->NameLength;
  1954. KeyName.MaximumLength = (USHORT) U.KeyBInf->NameLength;
  1955. Status = HalpOpenRegistryKey( &DriverKeyHandle,
  1956. ClassKeyHandle,
  1957. &KeyName,
  1958. KEY_READ,
  1959. FALSE);
  1960. if (!NT_SUCCESS( Status )) {
  1961. break;
  1962. }
  1963. //
  1964. // Get full information for that key so we can get the
  1965. // information about the data stored in the key.
  1966. //
  1967. Status = ZwQueryKey( DriverKeyHandle,
  1968. KeyFullInformation,
  1969. U.KeyFInf,
  1970. BufferSize,
  1971. &Temp );
  1972. if (!NT_SUCCESS( Status )) {
  1973. break;
  1974. }
  1975. Length = sizeof( KEY_VALUE_FULL_INFORMATION ) +
  1976. U.KeyFInf->MaxValueNameLen + U.KeyFInf->MaxValueDataLen + sizeof(UNICODE_NULL);
  1977. if (Length > BufferSize) {
  1978. PVOID TempBuffer;
  1979. //
  1980. // Get a larger buffer
  1981. //
  1982. TempBuffer = ExAllocatePoolWithTag(
  1983. PagedPool,
  1984. Length,
  1985. HAL_POOL_TAG);
  1986. if (TempBuffer == NULL) {
  1987. Status = STATUS_INSUFFICIENT_RESOURCES;
  1988. break;
  1989. }
  1990. ExFreePool (U.Buffer);
  1991. U.Buffer = TempBuffer;
  1992. BufferSize = Length;
  1993. }
  1994. DriverValueIndex = 0;
  1995. for (; ;) {
  1996. Status = ZwEnumerateValueKey( DriverKeyHandle,
  1997. DriverValueIndex++,
  1998. KeyValueFullInformation,
  1999. U.VKeyFInf,
  2000. BufferSize,
  2001. &Temp );
  2002. if (!NT_SUCCESS( Status )) {
  2003. break;
  2004. }
  2005. //
  2006. // If this is not a translated resource list, skip it.
  2007. //
  2008. i = U.VKeyFInf->NameLength;
  2009. if (i < TranslatedStrLen ||
  2010. RtlCompareMemory (
  2011. ((PUCHAR) U.VKeyFInf->Name) + i - TranslatedStrLen,
  2012. rgzTranslated,
  2013. TranslatedStrLen
  2014. ) != TranslatedStrLen
  2015. ) {
  2016. // does not end in rgzTranslated
  2017. continue;
  2018. }
  2019. //
  2020. // If this is a bus translated resource list, ????
  2021. //
  2022. if (i >= BusTranslatedStrLen &&
  2023. RtlCompareMemory (
  2024. ((PUCHAR) U.VKeyFInf->Name) + i - BusTranslatedStrLen,
  2025. rgzBusTranslated,
  2026. BusTranslatedStrLen
  2027. ) == BusTranslatedStrLen
  2028. ) {
  2029. // ends in rgzBusTranslated
  2030. continue;
  2031. }
  2032. //
  2033. // Run the CmResourceList and save each InUse resource
  2034. //
  2035. CmResList = (PCM_RESOURCE_LIST) ( (PUCHAR) U.VKeyFInf + U.VKeyFInf->DataOffset);
  2036. LastAddr = (PUCHAR) CmResList + U.VKeyFInf->DataLength;
  2037. CmFResDesc = &CmResList->List[0];
  2038. for (i=0; i < CmResList->Count && NT_SUCCESS(Status) ; i++) {
  2039. for (j=0; j < CmFResDesc->PartialResourceList.Count && NT_SUCCESS(Status); j++) {
  2040. CmDesc = &CmFResDesc->PartialResourceList.PartialDescriptors[j];
  2041. if ((PUCHAR) (CmDesc+1) > LastAddr) {
  2042. if (i) {
  2043. HalPrint(("IopAssignResourcesPhase2: a. CmResourceList in regitry too short\n"));
  2044. }
  2045. break;
  2046. }
  2047. if ((PUCHAR) (CmDesc+1) > LastAddr) {
  2048. i = CmResList->Count;
  2049. HalPrint(("IopAssignResourcesPhase2: b. CmResourceList in regitry too short\n"));
  2050. break;
  2051. }
  2052. switch (CmDesc->Type) {
  2053. case CmResourceTypePort:
  2054. HalpRemoveRange( &Bus->BusAddresses->IO,
  2055. CmDesc->u.Generic.Start.QuadPart,
  2056. CmDesc->u.Generic.Start.QuadPart +
  2057. CmDesc->u.Generic.Length - 1
  2058. );
  2059. break;
  2060. case CmResourceTypeMemory:
  2061. //
  2062. // The HAL's notion of prefetchable may not be
  2063. // consistent. So just remove any memory resource
  2064. // from both the prefetchable and non-prefetchable
  2065. // lists.
  2066. //
  2067. HalpRemoveRange( &Bus->BusAddresses->PrefetchMemory,
  2068. CmDesc->u.Generic.Start.QuadPart,
  2069. CmDesc->u.Generic.Start.QuadPart +
  2070. CmDesc->u.Generic.Length - 1
  2071. );
  2072. HalpRemoveRange( &Bus->BusAddresses->Memory,
  2073. CmDesc->u.Generic.Start.QuadPart,
  2074. CmDesc->u.Generic.Start.QuadPart +
  2075. CmDesc->u.Generic.Length - 1
  2076. );
  2077. break;
  2078. default:
  2079. break;
  2080. }
  2081. }
  2082. //
  2083. // Start at the end of the last CmDesc
  2084. // since the PCM_PARTIAL_RESOURCE_DESCRIPTOR array
  2085. // is variable size we can't just use the index.
  2086. //
  2087. (PCM_PARTIAL_RESOURCE_DESCRIPTOR) CmFResDesc = CmDesc+1;
  2088. }
  2089. } // next DriverValueIndex
  2090. if (DriverKeyHandle != INVALID_HANDLE) {
  2091. ZwClose (DriverKeyHandle);
  2092. DriverKeyHandle = INVALID_HANDLE;
  2093. }
  2094. if (Status == STATUS_NO_MORE_ENTRIES) {
  2095. Status = STATUS_SUCCESS;
  2096. }
  2097. if (!NT_SUCCESS(Status)) {
  2098. break;
  2099. }
  2100. } // next DriverKeyIndex
  2101. if (ClassKeyHandle != INVALID_HANDLE) {
  2102. ZwClose (ClassKeyHandle);
  2103. ClassKeyHandle = INVALID_HANDLE;
  2104. }
  2105. if (Status == STATUS_NO_MORE_ENTRIES) {
  2106. Status = STATUS_SUCCESS;
  2107. }
  2108. } // next ClassKeyIndex
  2109. if (Status == STATUS_NO_MORE_ENTRIES) {
  2110. Status = STATUS_SUCCESS;
  2111. }
  2112. ZwClose( ResourceMap );
  2113. ExFreePool (U.Buffer);
  2114. HalpConsolidateRanges (Bus->BusAddresses);
  2115. return Status;
  2116. }
  2117. VOID
  2118. HalpMarkNonAcpiHal(
  2119. VOID
  2120. )
  2121. /*++
  2122. Routine Description:
  2123. Arguments:
  2124. None.
  2125. Return Value:
  2126. None.
  2127. --*/
  2128. {
  2129. ULONG tmpValue;
  2130. UNICODE_STRING unicodeString;
  2131. HANDLE hCurrentControlSet, handle;
  2132. NTSTATUS status;
  2133. PAGED_CODE();
  2134. //
  2135. // Open/create System\CurrentControlSet key.
  2136. //
  2137. RtlInitUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
  2138. status = HalpOpenRegistryKey (
  2139. &hCurrentControlSet,
  2140. NULL,
  2141. &unicodeString,
  2142. KEY_ALL_ACCESS,
  2143. FALSE
  2144. );
  2145. if (!NT_SUCCESS(status)) {
  2146. return;
  2147. }
  2148. //
  2149. // Open HKLM\System\CurrentControlSet\Control\Pnp
  2150. //
  2151. RtlInitUnicodeString(&unicodeString, L"Control\\Pnp");
  2152. status = HalpOpenRegistryKey (
  2153. &handle,
  2154. hCurrentControlSet,
  2155. &unicodeString,
  2156. KEY_ALL_ACCESS,
  2157. TRUE
  2158. );
  2159. ZwClose(hCurrentControlSet);
  2160. if (!NT_SUCCESS(status)) {
  2161. return;
  2162. }
  2163. RtlInitUnicodeString(&unicodeString, L"DisableFirmwareMapper");
  2164. tmpValue = 0;
  2165. ZwSetValueKey(handle,
  2166. &unicodeString,
  2167. 0,
  2168. REG_DWORD,
  2169. &tmpValue,
  2170. sizeof(tmpValue)
  2171. );
  2172. ZwClose(handle);
  2173. }
  2174. VOID
  2175. HalpMarkChipsetDecode(
  2176. BOOLEAN FullDecodeChipset
  2177. )
  2178. /*++
  2179. Routine Description:
  2180. Arguments:
  2181. FullDecodeChipset - TRUE if NTOSKRNL should consider all fixed I/O
  2182. descriptors for PNPBIOS devices as 16bit. FALSE if
  2183. they should be taken at their word.
  2184. Return Value:
  2185. None.
  2186. --*/
  2187. {
  2188. ULONG tmpValue;
  2189. UNICODE_STRING unicodeString;
  2190. HANDLE hCurrentControlSet, handle;
  2191. NTSTATUS status;
  2192. PAGED_CODE();
  2193. //
  2194. // Open/create System\CurrentControlSet key.
  2195. //
  2196. RtlInitUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
  2197. status = HalpOpenRegistryKey (
  2198. &hCurrentControlSet,
  2199. NULL,
  2200. &unicodeString,
  2201. KEY_ALL_ACCESS,
  2202. FALSE
  2203. );
  2204. if (!NT_SUCCESS(status)) {
  2205. return;
  2206. }
  2207. //
  2208. // Open HKLM\System\CurrentControlSet\Control\Biosinfo\PNPBios
  2209. //
  2210. RtlInitUnicodeString(&unicodeString, L"Control\\Biosinfo\\PNPBios");
  2211. status = HalpOpenRegistryKey (
  2212. &handle,
  2213. hCurrentControlSet,
  2214. &unicodeString,
  2215. KEY_ALL_ACCESS,
  2216. TRUE
  2217. );
  2218. ZwClose(hCurrentControlSet);
  2219. if (!NT_SUCCESS(status)) {
  2220. return;
  2221. }
  2222. RtlInitUnicodeString(&unicodeString, L"FullDecodeChipsetOverride");
  2223. tmpValue = (ULONG) FullDecodeChipset;
  2224. ZwSetValueKey(handle,
  2225. &unicodeString,
  2226. 0,
  2227. REG_DWORD,
  2228. &tmpValue,
  2229. sizeof(tmpValue)
  2230. );
  2231. ZwClose(handle);
  2232. }
  2233. NTSTATUS
  2234. HalpOpenRegistryKey(
  2235. OUT PHANDLE Handle,
  2236. IN HANDLE BaseHandle OPTIONAL,
  2237. IN PUNICODE_STRING KeyName,
  2238. IN ACCESS_MASK DesiredAccess,
  2239. IN BOOLEAN Create
  2240. )
  2241. /*++
  2242. Routine Description:
  2243. Opens or creates a VOLATILE registry key using the name passed in based
  2244. at the BaseHandle node.
  2245. Arguments:
  2246. Handle - Pointer to the handle which will contain the registry key that
  2247. was opened.
  2248. BaseHandle - Handle to the base path from which the key must be opened.
  2249. KeyName - Name of the Key that must be opened/created.
  2250. DesiredAccess - Specifies the desired access that the caller needs to
  2251. the key.
  2252. Create - Determines if the key is to be created if it does not exist.
  2253. Return Value:
  2254. The function value is the final status of the operation.
  2255. --*/
  2256. {
  2257. OBJECT_ATTRIBUTES objectAttributes;
  2258. ULONG disposition;
  2259. PAGED_CODE();
  2260. //
  2261. // Initialize the object for the key.
  2262. //
  2263. InitializeObjectAttributes( &objectAttributes,
  2264. KeyName,
  2265. OBJ_CASE_INSENSITIVE,
  2266. BaseHandle,
  2267. (PSECURITY_DESCRIPTOR) NULL );
  2268. //
  2269. // Create the key or open it, as appropriate based on the caller's
  2270. // wishes.
  2271. //
  2272. if (Create) {
  2273. return ZwCreateKey( Handle,
  2274. DesiredAccess,
  2275. &objectAttributes,
  2276. 0,
  2277. (PUNICODE_STRING) NULL,
  2278. REG_OPTION_VOLATILE,
  2279. &disposition );
  2280. } else {
  2281. return ZwOpenKey( Handle,
  2282. DesiredAccess,
  2283. &objectAttributes );
  2284. }
  2285. }
  2286. VOID
  2287. HalPnpInterfaceReference(
  2288. PVOID Context
  2289. )
  2290. /*++
  2291. Routine Description:
  2292. This function increments the reference count on the interface context.
  2293. Arguments:
  2294. Context - Supplies a pointer to the interface context. This is actually
  2295. the PDO for the root bus.
  2296. Return Value:
  2297. None
  2298. --*/
  2299. {
  2300. PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
  2301. PAGED_CODE();
  2302. ASSERT_PDO_EXTENSION( PdoExtension );
  2303. InterlockedIncrement( &PdoExtension->InterfaceReferenceCount );
  2304. }
  2305. VOID
  2306. HalPnpInterfaceDereference(
  2307. PVOID Context
  2308. )
  2309. /*++
  2310. Routine Description:
  2311. This function decrements the reference count on the interface context.
  2312. Arguments:
  2313. Context - Supplies a pointer to the interface context. This is actually
  2314. the PDO for the root bus.
  2315. Return Value:
  2316. None
  2317. --*/
  2318. {
  2319. PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
  2320. LONG Result;
  2321. PAGED_CODE();
  2322. ASSERT_PDO_EXTENSION( PdoExtension );
  2323. Result = InterlockedDecrement( &PdoExtension->InterfaceReferenceCount );
  2324. ASSERT( Result >= 0 );
  2325. }
  2326. BOOLEAN
  2327. HalPnpTranslateBusAddress(
  2328. IN PVOID Context,
  2329. IN PHYSICAL_ADDRESS BusAddress,
  2330. IN ULONG Length,
  2331. IN OUT PULONG AddressSpace,
  2332. OUT PPHYSICAL_ADDRESS TranslatedAddress
  2333. )
  2334. /*++
  2335. Routine Description:
  2336. This function is used to translate bus addresses from legacy drivers.
  2337. Arguments:
  2338. Context - Supplies a pointer to the interface context. This is actually
  2339. the PDO for the root bus.
  2340. BusAddress - Supplies the orginal address to be translated.
  2341. Length - Supplies the length of the range to be translated.
  2342. AddressSpace - Points to the location of of the address space type such as
  2343. memory or I/O port. This value is updated by the translation.
  2344. TranslatedAddress - Returns the translated address.
  2345. Return Value:
  2346. Returns a boolean indicating if the operations was a success.
  2347. --*/
  2348. {
  2349. PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
  2350. PBUS_HANDLER Bus;
  2351. PAGED_CODE();
  2352. ASSERT_PDO_EXTENSION( PdoExtension );
  2353. Bus = PdoExtension->Bus;
  2354. return Bus->TranslateBusAddress( Bus,
  2355. Bus,
  2356. BusAddress,
  2357. AddressSpace,
  2358. TranslatedAddress );
  2359. }
  2360. ULONG
  2361. HalPnpReadConfig(
  2362. IN PVOID Context,
  2363. IN ULONG Slot,
  2364. IN PVOID Buffer,
  2365. IN ULONG Offset,
  2366. IN ULONG Length
  2367. )
  2368. /*++
  2369. Routine Description:
  2370. This function reads the PCI configuration space.
  2371. Arguments:
  2372. Context - Supplies a pointer to the interface context. This is actually
  2373. the PDO for the root bus.
  2374. Slot - Indicates the slot to be read or writen.
  2375. Buffer - Supplies a pointer to where the data should be placed.
  2376. Offset - Indicates the offset into the data where the reading should begin.
  2377. Length - Indicates the count of bytes which should be read.
  2378. Return Value:
  2379. Returns the number of bytes read.
  2380. --*/
  2381. {
  2382. PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
  2383. PBUS_HANDLER Bus;
  2384. PAGED_CODE();
  2385. ASSERT_PDO_EXTENSION( PdoExtension );
  2386. Bus = PdoExtension->Bus;
  2387. return Bus->GetBusData( Bus, Bus, Slot, Buffer, Offset, Length );
  2388. }
  2389. ULONG
  2390. HalPnpWriteConfig(
  2391. IN PVOID Context,
  2392. IN ULONG Slot,
  2393. IN PVOID Buffer,
  2394. IN ULONG Offset,
  2395. IN ULONG Length
  2396. )
  2397. /*++
  2398. Routine Description:
  2399. This function writes the PCI configuration space.
  2400. Arguments:
  2401. Context - Supplies a pointer to the interface context. This is actually
  2402. the PDO for the root bus.
  2403. Slot - Indicates the slot to be read or writen.
  2404. Buffer - Supplies a pointer to where the data to be written is.
  2405. Offset - Indicates the offset into the data where the writing should begin.
  2406. Length - Indicates the count of bytes which should be written.
  2407. Return Value:
  2408. Returns the number of bytes read.
  2409. --*/
  2410. {
  2411. PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
  2412. PBUS_HANDLER Bus;
  2413. PAGED_CODE();
  2414. ASSERT_PDO_EXTENSION( PdoExtension );
  2415. Bus = PdoExtension->Bus;
  2416. return Bus->SetBusData( Bus, Bus, Slot, Buffer, Offset, Length );
  2417. }
  2418. PDMA_ADAPTER
  2419. HalPnpGetDmaAdapter(
  2420. IN PVOID Context,
  2421. IN struct _DEVICE_DESCRIPTION *DeviceDescriptor,
  2422. OUT PULONG NumberOfMapRegisters
  2423. )
  2424. /*++
  2425. Routine Description:
  2426. This function writes the PCI configuration space.
  2427. Arguments:
  2428. Context - Supplies a pointer to the interface context. This is actually
  2429. the PDO for the root bus.
  2430. DeviceDescriptor - Supplies the device descriptor used to allocate the dma
  2431. adapter object.
  2432. NubmerOfMapRegisters - Returns the maximum number of map registers a device
  2433. can allocate at one time.
  2434. Return Value:
  2435. Returns a DMA adapter or NULL.
  2436. --*/
  2437. {
  2438. PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
  2439. PBUS_HANDLER Bus;
  2440. PAGED_CODE();
  2441. ASSERT_PDO_EXTENSION( PdoExtension );
  2442. Bus = PdoExtension->Bus;
  2443. //
  2444. // Fill in the bus number.
  2445. //
  2446. DeviceDescriptor->BusNumber = Bus->BusNumber;
  2447. return (PDMA_ADAPTER) HalGetAdapter( DeviceDescriptor, NumberOfMapRegisters );
  2448. }
  2449. NTSTATUS
  2450. HalpGetPciInterfaces(
  2451. IN PDEVICE_OBJECT PciPdo
  2452. )
  2453. /*++
  2454. Routine Description:
  2455. This function queries the PCI driver for interfaces used in interrupt
  2456. translation and arbitration.
  2457. Arguments:
  2458. PciPdo - PDO of a PCI bus
  2459. Return Value:
  2460. --*/
  2461. {
  2462. NTSTATUS status;
  2463. PDEVICE_OBJECT topDeviceInStack;
  2464. KEVENT irpCompleted;
  2465. PIRP irp;
  2466. IO_STATUS_BLOCK statusBlock;
  2467. PIO_STACK_LOCATION irpStack;
  2468. PAGED_CODE();
  2469. KeInitializeEvent(&irpCompleted, SynchronizationEvent, FALSE);
  2470. //
  2471. // Send an IRP to the PCI driver to get the Interrupt Routing Interface.
  2472. //
  2473. topDeviceInStack = IoGetAttachedDeviceReference(PciPdo);
  2474. irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
  2475. topDeviceInStack,
  2476. NULL, // Buffer
  2477. 0, // Length
  2478. 0, // StartingOffset
  2479. &irpCompleted,
  2480. &statusBlock);
  2481. if (!irp) {
  2482. return STATUS_UNSUCCESSFUL;
  2483. }
  2484. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  2485. irp->IoStatus.Information = 0;
  2486. irpStack = IoGetNextIrpStackLocation(irp);
  2487. //
  2488. // Set the function codes and parameters.
  2489. //
  2490. irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
  2491. irpStack->Parameters.QueryInterface.InterfaceType = &GUID_INT_ROUTE_INTERFACE_STANDARD;
  2492. irpStack->Parameters.QueryInterface.Size = sizeof(INT_ROUTE_INTERFACE_STANDARD);
  2493. irpStack->Parameters.QueryInterface.Version = 1;
  2494. irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) &PciIrqRoutingInterface;
  2495. irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
  2496. //
  2497. // Call the driver and wait for completion
  2498. //
  2499. status = IoCallDriver(topDeviceInStack, irp);
  2500. if (status == STATUS_PENDING) {
  2501. KeWaitForSingleObject(&irpCompleted, Executive, KernelMode, FALSE, NULL);
  2502. status = statusBlock.Status;
  2503. }
  2504. return status;
  2505. }