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.

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