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.

2029 lines
50 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 ACPI driver
  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. //
  21. // Cause the GUID to be defined.
  22. //
  23. #include "initguid.h"
  24. #include "wdmguid.h"
  25. #include "halpnpp.h"
  26. #if DBG
  27. ULONG HalDebug = 0;
  28. #endif
  29. extern WCHAR HalHardwareIdString[];
  30. typedef enum {
  31. Hal = 0x80,
  32. AcpiDriver
  33. } PDO_TYPE;
  34. typedef enum {
  35. PdoExtensionType = 0xc0,
  36. FdoExtensionType
  37. } EXTENSION_TYPE;
  38. typedef struct _PDO_EXTENSION *PPDO_EXTENSION;
  39. typedef struct _FDO_EXTENSION *PFDO_EXTENSION;
  40. typedef struct _PDO_EXTENSION{
  41. EXTENSION_TYPE ExtensionType;
  42. PPDO_EXTENSION Next;
  43. PDEVICE_OBJECT PhysicalDeviceObject;
  44. PFDO_EXTENSION ParentFdoExtension;
  45. PDO_TYPE PdoType;
  46. LONG InterfaceReferenceCount;
  47. } PDO_EXTENSION, *PPDO_EXTENSION;
  48. #define ASSERT_PDO_EXTENSION(x) ASSERT((x)->ExtensionType == PdoExtensionType );
  49. typedef struct _FDO_EXTENSION{
  50. EXTENSION_TYPE ExtensionType;
  51. PPDO_EXTENSION ChildPdoList;
  52. PDEVICE_OBJECT PhysicalDeviceObject; // PDO passed into AddDevice()
  53. PDEVICE_OBJECT FunctionalDeviceObject;
  54. PDEVICE_OBJECT AttachedDeviceObject;
  55. } FDO_EXTENSION, *PFDO_EXTENSION;
  56. #define ASSERT_FDO_EXTENSION(x) ASSERT((x)->ExtensionType == FdoExtensionType );
  57. INT_ROUTE_INTERFACE_STANDARD PciIrqRoutingInterface = {0};
  58. NTSTATUS
  59. HalpDriverEntry (
  60. IN PDRIVER_OBJECT DriverObject,
  61. IN PUNICODE_STRING RegistryPath
  62. );
  63. NTSTATUS
  64. HalpAddDevice(
  65. IN PDRIVER_OBJECT DriverObject,
  66. IN PDEVICE_OBJECT PhysicalDeviceObject
  67. );
  68. NTSTATUS
  69. HalpDispatchPnp(
  70. IN PDEVICE_OBJECT DeviceObject,
  71. IN OUT PIRP Irp
  72. );
  73. NTSTATUS
  74. HalpDispatchWmi(
  75. IN PDEVICE_OBJECT DeviceObject,
  76. IN OUT PIRP Irp
  77. );
  78. NTSTATUS
  79. HalpDispatchPower(
  80. IN PDEVICE_OBJECT DeviceObject,
  81. IN OUT PIRP Irp
  82. );
  83. NTSTATUS
  84. HalpQueryDeviceRelations(
  85. IN PDEVICE_OBJECT DeviceObject,
  86. IN DEVICE_RELATION_TYPE RelationType,
  87. OUT PDEVICE_RELATIONS *DeviceRelations
  88. );
  89. NTSTATUS
  90. HalpQueryIdPdo(
  91. IN PDEVICE_OBJECT PdoExtension,
  92. IN BUS_QUERY_ID_TYPE IdType,
  93. IN OUT PWSTR *BusQueryId
  94. );
  95. NTSTATUS
  96. HalpQueryIdFdo(
  97. IN PDEVICE_OBJECT PdoExtension,
  98. IN BUS_QUERY_ID_TYPE IdType,
  99. IN OUT PWSTR *BusQueryId
  100. );
  101. NTSTATUS
  102. HalpQueryCapabilities(
  103. IN PDEVICE_OBJECT PdoExtension,
  104. IN PDEVICE_CAPABILITIES Capabilities
  105. );
  106. NTSTATUS
  107. HalpQueryResources(
  108. PDEVICE_OBJECT DeviceObject,
  109. PCM_RESOURCE_LIST *Resources
  110. );
  111. NTSTATUS
  112. HalpQueryResourceRequirements(
  113. PDEVICE_OBJECT DeviceObject,
  114. PIO_RESOURCE_REQUIREMENTS_LIST *Requirements
  115. );
  116. NTSTATUS
  117. HalpQueryInterface(
  118. IN PDEVICE_OBJECT DeviceObject,
  119. IN LPCGUID InterfaceType,
  120. IN USHORT Version,
  121. IN PVOID InterfaceSpecificData,
  122. IN ULONG InterfaceBufferSize,
  123. IN OUT PINTERFACE Interface,
  124. IN OUT PULONG Length
  125. );
  126. #ifdef WANT_IRQ_ROUTING
  127. NTSTATUS
  128. HalpQueryInterfaceFdo(
  129. IN PDEVICE_OBJECT DeviceObject,
  130. IN LPCGUID InterfaceType,
  131. IN USHORT Version,
  132. IN PVOID InterfaceSpecificData,
  133. IN ULONG InterfaceBufferSize,
  134. IN OUT PINTERFACE Interface,
  135. IN OUT PULONG Length
  136. );
  137. #endif
  138. NTSTATUS
  139. HalIrqTranslateResourcesRoot(
  140. IN PVOID Context,
  141. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  142. IN RESOURCE_TRANSLATION_DIRECTION Direction,
  143. IN ULONG AlternativesCount, OPTIONAL
  144. IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
  145. IN PDEVICE_OBJECT PhysicalDeviceObject,
  146. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  147. );
  148. NTSTATUS
  149. HalIrqTranslateResourceRequirementsRoot(
  150. IN PVOID Context,
  151. IN PIO_RESOURCE_DESCRIPTOR Source,
  152. IN PDEVICE_OBJECT PhysicalDeviceObject,
  153. OUT PULONG TargetCount,
  154. OUT PIO_RESOURCE_DESCRIPTOR *Target
  155. );
  156. VOID
  157. HalpMaskAcpiInterrupt(
  158. VOID
  159. );
  160. VOID
  161. HalpUnmaskAcpiInterrupt(
  162. VOID
  163. );
  164. // from xxacpi.c
  165. NTSTATUS
  166. HalpQueryAcpiResourceRequirements(
  167. IN PIO_RESOURCE_REQUIREMENTS_LIST *Requirements
  168. );
  169. VOID
  170. HalpMarkAcpiHal(
  171. VOID
  172. );
  173. NTSTATUS
  174. HalpOpenRegistryKey(
  175. OUT PHANDLE Handle,
  176. IN HANDLE BaseHandle OPTIONAL,
  177. IN PUNICODE_STRING KeyName,
  178. IN ACCESS_MASK DesiredAccess,
  179. IN BOOLEAN Create
  180. );
  181. //
  182. // Define the PNP interface functions.
  183. //
  184. VOID
  185. HalPnpInterfaceReference(
  186. PVOID Context
  187. );
  188. VOID
  189. HalPnpInterfaceDereference(
  190. PVOID Context
  191. );
  192. BOOLEAN
  193. HalPnpTranslateBusAddress(
  194. IN PVOID Context,
  195. IN PHYSICAL_ADDRESS BusAddress,
  196. IN ULONG Length,
  197. IN OUT PULONG AddressSpace,
  198. OUT PPHYSICAL_ADDRESS TranslatedAddress
  199. );
  200. struct _DMA_ADAPTER *
  201. HalPnpGetDmaAdapter(
  202. IN PVOID Context,
  203. IN struct _DEVICE_DESCRIPTION *DeviceDescriptor,
  204. OUT PULONG NumberOfMapRegisters
  205. );
  206. BOOLEAN
  207. HalpFakeAcpiRegisters(
  208. VOID
  209. );
  210. #define HAL_DRIVER_NAME L"\\Driver\\ACPI_HAL"
  211. #ifdef ALLOC_PRAGMA
  212. #pragma alloc_text(PAGE, HaliInitPnpDriver)
  213. #pragma alloc_text(PAGE, HalpMarkAcpiHal)
  214. #pragma alloc_text(PAGE, HalpOpenRegistryKey)
  215. #pragma alloc_text(PAGE, HalpDispatchPnp)
  216. #pragma alloc_text(PAGE, HalpAddDevice)
  217. #pragma alloc_text(PAGE, HalpDriverEntry)
  218. #pragma alloc_text(PAGE, HalpQueryDeviceRelations)
  219. #pragma alloc_text(PAGE, HalpQueryIdPdo)
  220. #pragma alloc_text(PAGE, HalpQueryIdFdo)
  221. #pragma alloc_text(PAGE, HalpQueryCapabilities)
  222. #pragma alloc_text(PAGE, HalpQueryResources)
  223. #pragma alloc_text(PAGE, HalpQueryResourceRequirements)
  224. #pragma alloc_text(PAGE, HalpQueryInterface)
  225. #ifdef WANT_IRQ_ROUTING
  226. #pragma alloc_text(PAGE, HalpQueryInterfaceFdo)
  227. #endif
  228. #pragma alloc_text(PAGELK, HalpDispatchPower)
  229. #pragma alloc_text(PAGE, HalpDispatchWmi)
  230. #endif
  231. PDRIVER_OBJECT HalpDriverObject;
  232. NTSTATUS
  233. HaliInitPnpDriver(
  234. VOID
  235. )
  236. /*++
  237. Routine Description:
  238. This routine starts the process of making the HAL into
  239. a "driver," which is necessary because we need to
  240. enumerate a Plug and Play PDO for the ACPI driver.
  241. Arguments:
  242. DriverName - Unicode string that will be used for the
  243. driver object.
  244. Return Value:
  245. status
  246. --*/
  247. {
  248. UNICODE_STRING DriverName;
  249. NTSTATUS Status;
  250. PAGED_CODE();
  251. RtlInitUnicodeString( &DriverName, HAL_DRIVER_NAME );
  252. Status = IoCreateDriver( &DriverName, HalpDriverEntry );
  253. HalpMarkAcpiHal();
  254. ASSERT( NT_SUCCESS( Status ));
  255. return Status;
  256. }
  257. VOID
  258. HalpMarkAcpiHal(
  259. VOID
  260. )
  261. /*++
  262. Routine Description:
  263. Arguments:
  264. None.
  265. Return Value:
  266. None.
  267. --*/
  268. {
  269. ULONG tmpValue;
  270. UNICODE_STRING unicodeString;
  271. HANDLE hCurrentControlSet, handle;
  272. NTSTATUS status;
  273. PAGED_CODE();
  274. //
  275. // Open/create System\CurrentControlSet key.
  276. //
  277. RtlInitUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
  278. status = HalpOpenRegistryKey (
  279. &hCurrentControlSet,
  280. NULL,
  281. &unicodeString,
  282. KEY_ALL_ACCESS,
  283. FALSE
  284. );
  285. if (!NT_SUCCESS(status)) {
  286. return;
  287. }
  288. //
  289. // Open HKLM\System\CurrentControlSet\Control\Pnp
  290. //
  291. RtlInitUnicodeString(&unicodeString, L"Control\\Pnp");
  292. status = HalpOpenRegistryKey (
  293. &handle,
  294. hCurrentControlSet,
  295. &unicodeString,
  296. KEY_ALL_ACCESS,
  297. TRUE
  298. );
  299. ZwClose(hCurrentControlSet);
  300. if (!NT_SUCCESS(status)) {
  301. return;
  302. }
  303. RtlInitUnicodeString(&unicodeString, L"DisableFirmwareMapper");
  304. tmpValue = 1;
  305. ZwSetValueKey(handle,
  306. &unicodeString,
  307. 0,
  308. REG_DWORD,
  309. &tmpValue,
  310. sizeof(tmpValue)
  311. );
  312. ZwClose(handle);
  313. }
  314. NTSTATUS
  315. HalpOpenRegistryKey(
  316. OUT PHANDLE Handle,
  317. IN HANDLE BaseHandle OPTIONAL,
  318. IN PUNICODE_STRING KeyName,
  319. IN ACCESS_MASK DesiredAccess,
  320. IN BOOLEAN Create
  321. )
  322. /*++
  323. Routine Description:
  324. Opens or creates a VOLATILE registry key using the name passed in based
  325. at the BaseHandle node.
  326. Arguments:
  327. Handle - Pointer to the handle which will contain the registry key that
  328. was opened.
  329. BaseHandle - Handle to the base path from which the key must be opened.
  330. KeyName - Name of the Key that must be opened/created.
  331. DesiredAccess - Specifies the desired access that the caller needs to
  332. the key.
  333. Create - Determines if the key is to be created if it does not exist.
  334. Return Value:
  335. The function value is the final status of the operation.
  336. --*/
  337. {
  338. OBJECT_ATTRIBUTES objectAttributes;
  339. ULONG disposition;
  340. PAGED_CODE();
  341. //
  342. // Initialize the object for the key.
  343. //
  344. InitializeObjectAttributes( &objectAttributes,
  345. KeyName,
  346. OBJ_CASE_INSENSITIVE,
  347. BaseHandle,
  348. (PSECURITY_DESCRIPTOR) NULL );
  349. //
  350. // Create the key or open it, as appropriate based on the caller's
  351. // wishes.
  352. //
  353. if (Create) {
  354. return ZwCreateKey( Handle,
  355. DesiredAccess,
  356. &objectAttributes,
  357. 0,
  358. (PUNICODE_STRING) NULL,
  359. REG_OPTION_VOLATILE,
  360. &disposition );
  361. } else {
  362. return ZwOpenKey( Handle,
  363. DesiredAccess,
  364. &objectAttributes );
  365. }
  366. }
  367. NTSTATUS
  368. HalpDriverEntry (
  369. IN PDRIVER_OBJECT DriverObject,
  370. IN PUNICODE_STRING RegistryPath
  371. )
  372. /*++
  373. Routine Description:
  374. This is the callback function when we call IoCreateDriver to create a
  375. PnP Driver Object. In this function, we need to remember the DriverObject.
  376. Arguments:
  377. DriverObject - Pointer to the driver object created by the system.
  378. RegistryPath - is NULL.
  379. Return Value:
  380. STATUS_SUCCESS
  381. --*/
  382. {
  383. NTSTATUS status;
  384. PDEVICE_OBJECT detectedDeviceObject = NULL;
  385. ANSI_STRING AKeyName;
  386. PAGED_CODE();
  387. //
  388. // File the pointer to our driver object away
  389. //
  390. HalpDriverObject = DriverObject;
  391. //
  392. // Fill in the driver object
  393. //
  394. DriverObject->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)HalpAddDevice;
  395. DriverObject->MajorFunction[ IRP_MJ_PNP ] = HalpDispatchPnp;
  396. DriverObject->MajorFunction[ IRP_MJ_POWER ] = HalpDispatchPower;
  397. DriverObject->MajorFunction[ IRP_MJ_SYSTEM_CONTROL ] = HalpDispatchWmi;
  398. status = IoReportDetectedDevice(DriverObject,
  399. InterfaceTypeUndefined,
  400. -1,
  401. -1,
  402. NULL,
  403. NULL,
  404. FALSE,
  405. &detectedDeviceObject);
  406. ASSERT(detectedDeviceObject);
  407. if (!(NT_SUCCESS(status))) {
  408. return status;
  409. }
  410. HalpAddDevice(DriverObject,
  411. detectedDeviceObject);
  412. return STATUS_SUCCESS;
  413. }
  414. NTSTATUS
  415. HalpAddDevice(
  416. IN PDRIVER_OBJECT DriverObject,
  417. IN PDEVICE_OBJECT PhysicalDeviceObject
  418. )
  419. /*++
  420. Routine Description:
  421. This routine handles AddDevice for an madeup PDO device.
  422. Arguments:
  423. DriverObject - Pointer to our pseudo driver object.
  424. DeviceObject - Pointer to the device object for which this requestapplies.
  425. Return Value:
  426. NT status.
  427. --*/
  428. {
  429. PDEVICE_OBJECT functionalDeviceObject;
  430. PDEVICE_OBJECT childDeviceObject;
  431. PDEVICE_OBJECT AttachedDevice;
  432. NTSTATUS status;
  433. PFDO_EXTENSION FdoExtension;
  434. PPDO_EXTENSION PdoExtension;
  435. PAGED_CODE();
  436. //
  437. // We've been given the PhysicalDeviceObject. Create the
  438. // FunctionalDeviceObject. Our FDO will be nameless.
  439. //
  440. status = IoCreateDevice(
  441. DriverObject, // our driver object
  442. sizeof(FDO_EXTENSION), // size of our extension
  443. NULL, // our name
  444. FILE_DEVICE_BUS_EXTENDER, // device type
  445. 0, // device characteristics
  446. FALSE, // not exclusive
  447. &functionalDeviceObject // store new device object here
  448. );
  449. if( !NT_SUCCESS( status )){
  450. DbgBreakPoint();
  451. return status;
  452. }
  453. //
  454. // Fill in the FDO extension
  455. //
  456. FdoExtension = (PFDO_EXTENSION)functionalDeviceObject->DeviceExtension;
  457. FdoExtension->ExtensionType = FdoExtensionType;
  458. FdoExtension->PhysicalDeviceObject = PhysicalDeviceObject;
  459. FdoExtension->FunctionalDeviceObject = functionalDeviceObject;
  460. functionalDeviceObject->Flags &= ~(DO_DEVICE_INITIALIZING);
  461. //
  462. // Now attach to the PDO we were given.
  463. //
  464. AttachedDevice = IoAttachDeviceToDeviceStack(functionalDeviceObject,
  465. PhysicalDeviceObject );
  466. if(AttachedDevice == NULL){
  467. //
  468. // Couldn't attach. Delete the FDO.
  469. //
  470. IoDeleteDevice( functionalDeviceObject );
  471. return STATUS_NO_SUCH_DEVICE;
  472. }
  473. FdoExtension->AttachedDeviceObject = AttachedDevice;
  474. //
  475. // Next, create a PDO for the ACPI driver.
  476. //
  477. status = IoCreateDevice(
  478. DriverObject, // our driver object
  479. sizeof(PDO_EXTENSION), // size of our extension
  480. NULL, // our name
  481. FILE_DEVICE_BUS_EXTENDER, // device type
  482. FILE_AUTOGENERATED_DEVICE_NAME, // device characteristics
  483. FALSE, // not exclusive
  484. &childDeviceObject // store new device object here
  485. );
  486. if (!NT_SUCCESS(status)) {
  487. return status;
  488. }
  489. //
  490. // Fill in the PDO extension
  491. //
  492. PdoExtension = (PPDO_EXTENSION)childDeviceObject->DeviceExtension;
  493. PdoExtension->ExtensionType = PdoExtensionType;
  494. PdoExtension->Next = NULL;
  495. PdoExtension->PhysicalDeviceObject = childDeviceObject;
  496. PdoExtension->ParentFdoExtension = FdoExtension;
  497. PdoExtension->PdoType = AcpiDriver;
  498. childDeviceObject->Flags &= ~(DO_DEVICE_INITIALIZING);
  499. //
  500. // Record this as a child of the HAL
  501. //
  502. FdoExtension->ChildPdoList = PdoExtension;
  503. return STATUS_SUCCESS;
  504. }
  505. NTSTATUS
  506. HalpPassIrpFromFdoToPdo(
  507. PDEVICE_OBJECT DeviceObject,
  508. PIRP Irp
  509. )
  510. /*++
  511. Description:
  512. Given an FDO, pass the IRP to the next device object in the
  513. device stack. This is the PDO if there are no lower level
  514. filters.
  515. Arguments:
  516. DeviceObject - the Fdo
  517. Irp - the request
  518. Return Value:
  519. Returns the result from calling the next level.
  520. --*/
  521. {
  522. PIO_STACK_LOCATION irpSp; // our stack location
  523. PIO_STACK_LOCATION nextIrpSp; // next guy's
  524. PFDO_EXTENSION fdoExtension;
  525. //
  526. // Get the pointer to the device extension.
  527. //
  528. fdoExtension = (PFDO_EXTENSION)DeviceObject->DeviceExtension;
  529. IoSkipCurrentIrpStackLocation(Irp);
  530. //
  531. // Call the PDO driver with the request.
  532. //
  533. return IoCallDriver(fdoExtension->AttachedDeviceObject ,Irp);
  534. }
  535. NTSTATUS
  536. HalpDispatchPnp(
  537. IN PDEVICE_OBJECT DeviceObject,
  538. IN OUT PIRP Irp
  539. )
  540. /*++
  541. Routine Description:
  542. This routine handles all IRP_MJ_PNP IRPs for madeup PDO device.
  543. Arguments:
  544. DeviceObject - Pointer to the device object for which this IRP applies.
  545. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  546. Return Value:
  547. NT status.
  548. --*/
  549. {
  550. PIO_STACK_LOCATION irpSp;
  551. NTSTATUS status;
  552. ULONG length;
  553. DEVICE_RELATION_TYPE relationType;
  554. EXTENSION_TYPE extensionType;
  555. BOOLEAN passDown;
  556. PUCHAR objectTypeString;
  557. PAGED_CODE();
  558. extensionType = ((PFDO_EXTENSION)(DeviceObject->DeviceExtension))->ExtensionType;
  559. //
  560. // Get a pointer to our stack location and take appropriate action based
  561. // on the minor function.
  562. //
  563. irpSp = IoGetCurrentIrpStackLocation(Irp);
  564. status = Irp->IoStatus.Status;
  565. switch (extensionType) {
  566. case PdoExtensionType:
  567. objectTypeString = "PDO";
  568. switch (irpSp->MinorFunction) {
  569. case IRP_MN_START_DEVICE:
  570. HalDebugPrint(( HAL_PNP, "HAL: (%s) Start_Device Irp received\n",
  571. objectTypeString ));
  572. //
  573. // If we get a start device request for a PDO, we simply
  574. // return success.
  575. //
  576. status = STATUS_SUCCESS;
  577. break;
  578. case IRP_MN_QUERY_STOP_DEVICE:
  579. HalDebugPrint(( HAL_PNP, "HAL: (%s) Query_Stop_Device Irp received",
  580. objectTypeString));
  581. status = STATUS_SUCCESS;
  582. break;
  583. case IRP_MN_CANCEL_STOP_DEVICE:
  584. HalDebugPrint(( HAL_PNP, "HAL: (%s) Cancel_Stop_Device Irp received",
  585. objectTypeString ));
  586. status = STATUS_SUCCESS;
  587. break;
  588. case IRP_MN_STOP_DEVICE:
  589. HalDebugPrint(( HAL_PNP, "HAL: (%s) Stop_Device Irp received\n",
  590. objectTypeString ));
  591. //
  592. // If we get a stop device request for a PDO, we simply
  593. // return success.
  594. //
  595. status = STATUS_SUCCESS;
  596. break;
  597. case IRP_MN_QUERY_RESOURCES:
  598. HalDebugPrint(( HAL_PNP, "HAL: (%s) Query_Resources Irp received\n",
  599. objectTypeString ));
  600. status = HalpQueryResources(DeviceObject,
  601. (PCM_RESOURCE_LIST*)&Irp->IoStatus.Information);
  602. break;
  603. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  604. HalDebugPrint(( HAL_PNP, "HAL: (%s) Query_Resource_Requirements Irp received\n",
  605. objectTypeString ));
  606. status = HalpQueryResourceRequirements(DeviceObject,
  607. (PIO_RESOURCE_REQUIREMENTS_LIST*)&Irp->IoStatus.Information);
  608. break;
  609. case IRP_MN_QUERY_REMOVE_DEVICE:
  610. HalDebugPrint(( HAL_PNP, "HAL: (%s) Query_Remove_device Irp for %p",
  611. objectTypeString,
  612. DeviceObject ));
  613. status = STATUS_UNSUCCESSFUL;
  614. break;
  615. case IRP_MN_CANCEL_REMOVE_DEVICE:
  616. HalDebugPrint(( HAL_PNP, "HAL: (%s) Cancel_Remove_device Irp for %p",
  617. objectTypeString,
  618. DeviceObject));
  619. status = STATUS_SUCCESS;
  620. break;
  621. case IRP_MN_REMOVE_DEVICE:
  622. HalDebugPrint(( HAL_PNP, "HAL: (%s) Remove_device Irp for PDO %p\n",
  623. objectTypeString,
  624. DeviceObject ));
  625. status = STATUS_SUCCESS;
  626. break;
  627. case IRP_MN_QUERY_DEVICE_RELATIONS:
  628. HalDebugPrint(( HAL_PNP, "HAL: (%s) Query_Device_Relations Irp received\n",
  629. objectTypeString ));
  630. relationType = irpSp->Parameters.QueryDeviceRelations.Type;
  631. status = HalpQueryDeviceRelations(DeviceObject,
  632. relationType,
  633. (PDEVICE_RELATIONS*)&Irp->IoStatus.Information);
  634. break;
  635. case IRP_MN_QUERY_ID:
  636. HalDebugPrint(( HAL_PNP, "HAL: (%s) Query_Id Irp received\n",
  637. objectTypeString ));
  638. status = HalpQueryIdPdo(DeviceObject,
  639. irpSp->Parameters.QueryId.IdType,
  640. (PWSTR*)&Irp->IoStatus.Information);
  641. break;
  642. case IRP_MN_QUERY_INTERFACE:
  643. HalDebugPrint(( HAL_PNP, "HAL: (%s) Query_Interface Irp received\n",
  644. objectTypeString));
  645. status = HalpQueryInterface(
  646. DeviceObject,
  647. irpSp->Parameters.QueryInterface.InterfaceType,
  648. irpSp->Parameters.QueryInterface.Version,
  649. irpSp->Parameters.QueryInterface.InterfaceSpecificData,
  650. irpSp->Parameters.QueryInterface.Size,
  651. irpSp->Parameters.QueryInterface.Interface,
  652. (PULONG)&Irp->IoStatus.Information
  653. );
  654. break;
  655. case IRP_MN_QUERY_CAPABILITIES:
  656. HalDebugPrint(( HAL_PNP, "HAL: (%s) Query_Capabilities Irp received\n",
  657. objectTypeString));
  658. status = HalpQueryCapabilities(DeviceObject,
  659. irpSp->Parameters.DeviceCapabilities.Capabilities);
  660. break;
  661. case IRP_MN_DEVICE_USAGE_NOTIFICATION:
  662. HalDebugPrint(( HAL_PNP, "HAL: DEVICE_USAGE Irp received\n" ));
  663. status = STATUS_SUCCESS;
  664. break;
  665. default:
  666. HalDebugPrint(( HAL_PNP, "HAL: (%s) Unsupported Irp (%d) received\n",
  667. objectTypeString,
  668. irpSp->MinorFunction));
  669. status = STATUS_NOT_SUPPORTED ;
  670. break;
  671. }
  672. break; // end PDO cases
  673. case FdoExtensionType:
  674. objectTypeString = "FDO";
  675. passDown = TRUE;
  676. //
  677. // In case we don't touch this IRP, save the current status.
  678. //
  679. switch (irpSp->MinorFunction) {
  680. case IRP_MN_QUERY_DEVICE_RELATIONS:
  681. HalDebugPrint(( HAL_PNP, "HAL: (%s) Query_Device_Relations Irp received\n",
  682. objectTypeString));
  683. relationType = irpSp->Parameters.QueryDeviceRelations.Type;
  684. status = HalpQueryDeviceRelations(DeviceObject,
  685. relationType,
  686. (PDEVICE_RELATIONS*)&Irp->IoStatus.Information);
  687. break;
  688. case IRP_MN_QUERY_INTERFACE:
  689. #ifdef WANT_IRQ_ROUTING
  690. case IRP_MN_QUERY_INTERFACE:
  691. HalDebugPrint(( HAL_PNP, "(%s) Query_Interface Irp received",
  692. objectTypeString));
  693. HalDebugPrint(( HAL_PNP, "HAL: (%s) Query_Interface Irp received",
  694. objectTypeString ));
  695. Status = HalpQueryInterfaceFdo(
  696. DeviceObject,
  697. irpSp->Parameters.QueryInterface.InterfaceType,
  698. irpSp->Parameters.QueryInterface.Version,
  699. irpSp->Parameters.QueryInterface.InterfaceSpecificData,
  700. irpSp->Parameters.QueryInterface.Size,
  701. irpSp->Parameters.QueryInterface.Interface,
  702. &Irp->IoStatus.Information
  703. );
  704. break;
  705. #endif
  706. case IRP_MN_QUERY_ID:
  707. HalDebugPrint(( HAL_PNP, "HAL: (%s) Query_Id Irp received\n",
  708. objectTypeString ));
  709. status = HalpQueryIdFdo(DeviceObject,
  710. irpSp->Parameters.QueryId.IdType,
  711. (PWSTR*)&Irp->IoStatus.Information);
  712. break;
  713. default:
  714. //
  715. // Ignore any PNP Irps unknown by the FDO but allow them
  716. // down to the PDO.
  717. //
  718. status = STATUS_NOT_SUPPORTED ;
  719. break;
  720. }
  721. if (passDown && (NT_SUCCESS(status) || (status == STATUS_NOT_SUPPORTED))) {
  722. //
  723. // Pass FDO IRPs down to the PDO.
  724. //
  725. // Set Irp status first.
  726. //
  727. if (status != STATUS_NOT_SUPPORTED) {
  728. Irp->IoStatus.Status = status;
  729. }
  730. HalDebugPrint(( HAL_PNP, "HAL: (%s) Passing down Irp (%x)\n",
  731. objectTypeString, irpSp->MinorFunction ));
  732. return HalpPassIrpFromFdoToPdo(DeviceObject, Irp);
  733. }
  734. break; // end FDO cases
  735. default:
  736. HalDebugPrint(( HAL_PNP, "HAL: Received IRP for unknown Device Object\n" ));
  737. status = STATUS_INVALID_DEVICE_REQUEST ;
  738. break;
  739. }
  740. //
  741. // Complete the Irp and return.
  742. //
  743. if (status != STATUS_NOT_SUPPORTED) {
  744. Irp->IoStatus.Status = status;
  745. } else {
  746. status = Irp->IoStatus.Status ;
  747. }
  748. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  749. return status;
  750. }
  751. NTSTATUS
  752. HalpDispatchPower(
  753. IN PDEVICE_OBJECT DeviceObject,
  754. IN OUT PIRP Irp
  755. )
  756. /*++
  757. Routine Description:
  758. This routine handles all IRP_MJ_POWER IRPs for madeup PDO device.
  759. Note: We don't actually handle any Power IRPs at this level so
  760. all we do is return the status from the incoming IRP.
  761. Arguments:
  762. DeviceObject - Pointer to the device object for which this IRP applies.
  763. Irp - Pointer to the IRP_MJ_POWER IRP to dispatch.
  764. Return Value:
  765. NT status.
  766. --*/
  767. {
  768. NTSTATUS Status;
  769. EXTENSION_TYPE extensionType;
  770. PIO_STACK_LOCATION irpSp;
  771. HalDebugPrint(( HAL_PNP, "HAL: Power IRP for DevObj: %p\n", DeviceObject ));
  772. extensionType = ((PFDO_EXTENSION)(DeviceObject->DeviceExtension))->ExtensionType;
  773. irpSp = IoGetCurrentIrpStackLocation(Irp);
  774. //
  775. // Simply store the appropriate status and complete the request.
  776. //
  777. Status = Irp->IoStatus.Status;
  778. PoStartNextPowerIrp(Irp);
  779. if (extensionType == FdoExtensionType) {
  780. switch (irpSp->MinorFunction) {
  781. case IRP_MN_SET_POWER:
  782. if (irpSp->Parameters.Power.Type == SystemPowerState) {
  783. if (irpSp->Parameters.Power.State.SystemState ==
  784. PowerSystemWorking) {
  785. HalpUnmaskAcpiInterrupt();
  786. } else {
  787. HalpMaskAcpiInterrupt();
  788. }
  789. }
  790. //
  791. // Fall through.
  792. //
  793. case IRP_MN_QUERY_POWER:
  794. Irp->IoStatus.Status = Status = STATUS_SUCCESS;
  795. //
  796. // Fall through.
  797. //
  798. default:
  799. Status = HalpPassIrpFromFdoToPdo(DeviceObject, Irp);
  800. break;
  801. }
  802. } else {
  803. switch (irpSp->MinorFunction) {
  804. case IRP_MN_SET_POWER:
  805. case IRP_MN_QUERY_POWER:
  806. Irp->IoStatus.Status = Status = STATUS_SUCCESS;
  807. //
  808. // Fall through.
  809. //
  810. default:
  811. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  812. break;
  813. }
  814. }
  815. return Status;
  816. }
  817. NTSTATUS
  818. HalpDispatchWmi(
  819. IN PDEVICE_OBJECT DeviceObject,
  820. IN OUT PIRP Irp
  821. )
  822. {
  823. NTSTATUS Status;
  824. EXTENSION_TYPE extensionType;
  825. extensionType = ((PFDO_EXTENSION)(DeviceObject->DeviceExtension))->ExtensionType;
  826. if (extensionType == FdoExtensionType) {
  827. Status = HalpPassIrpFromFdoToPdo(DeviceObject, Irp);
  828. } else {
  829. Status = Irp->IoStatus.Status;
  830. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  831. }
  832. return Status;
  833. }
  834. NTSTATUS
  835. HalpQueryDeviceRelations(
  836. IN PDEVICE_OBJECT DeviceObject,
  837. IN DEVICE_RELATION_TYPE RelationType,
  838. OUT PDEVICE_RELATIONS *DeviceRelations
  839. )
  840. /*++
  841. Routine Description:
  842. This routine builds a DEVICE_RELATIONS structure that
  843. tells the PnP manager how many children we have.
  844. Arguments:
  845. DeviceObject - FDO of ACPI_HAL
  846. RelationType - we only respond to BusRelations
  847. DeviceRelations - pointer to the structure
  848. Return Value:
  849. status
  850. --*/
  851. {
  852. PFDO_EXTENSION FdoExtension;
  853. PDEVICE_RELATIONS relations = NULL;
  854. PDEVICE_OBJECT deviceObjectToReturn ;
  855. EXTENSION_TYPE extensionType;
  856. NTSTATUS status ;
  857. PAGED_CODE();
  858. FdoExtension = (PFDO_EXTENSION)DeviceObject->DeviceExtension;
  859. extensionType = FdoExtension->ExtensionType;
  860. status = STATUS_NOT_SUPPORTED ;
  861. switch(RelationType) {
  862. case BusRelations:
  863. if (extensionType == FdoExtensionType) {
  864. deviceObjectToReturn = FdoExtension->ChildPdoList->PhysicalDeviceObject ;
  865. status = STATUS_SUCCESS ;
  866. }
  867. break;
  868. case TargetDeviceRelation:
  869. if (extensionType == PdoExtensionType) {
  870. deviceObjectToReturn = DeviceObject ;
  871. status = STATUS_SUCCESS ;
  872. }
  873. break;
  874. }
  875. if (status == STATUS_NOT_SUPPORTED) {
  876. HalDebugPrint(( HAL_PNP, "HAL: We don't support this kind of device relation\n" ));
  877. } else if (NT_SUCCESS(status)) {
  878. ASSERT(*DeviceRelations == 0);
  879. relations = ExAllocatePoolWithTag(
  880. PagedPool,
  881. sizeof(DEVICE_RELATIONS),
  882. HAL_POOL_TAG
  883. );
  884. if (!relations) {
  885. status = STATUS_INSUFFICIENT_RESOURCES;
  886. } else {
  887. relations->Count = 1;
  888. relations->Objects[0] = deviceObjectToReturn ;
  889. ObReferenceObject(relations->Objects[0]);
  890. *DeviceRelations = relations;
  891. }
  892. }
  893. return status ;
  894. }
  895. NTSTATUS
  896. HalpQueryIdPdo(
  897. IN PDEVICE_OBJECT DeviceObject,
  898. IN BUS_QUERY_ID_TYPE IdType,
  899. IN OUT PWSTR *BusQueryId
  900. )
  901. /*++
  902. Routine Description:
  903. This routine identifies each of the children that were
  904. enumerated in HalpQueryDeviceRelations.
  905. Arguments:
  906. DeviceObject - PDO of the child
  907. IdType - the type of ID to be returned, currently ignored
  908. BusQueryId - pointer to the wide string being returned
  909. Return Value:
  910. status
  911. --*/
  912. {
  913. PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
  914. PWSTR idString;
  915. PWCHAR sourceString;
  916. ULONG stringLen;
  917. static WCHAR AcpiHardwareIdString[] = L"ACPI_HAL\\PNP0C08\0*PNP0C08";
  918. static WCHAR AcpiCompatibleString[] = L"*PNP0C08";
  919. static WCHAR AcpiInstanceIdString[] = L"0";
  920. PAGED_CODE();
  921. switch (IdType) {
  922. case BusQueryDeviceID:
  923. case BusQueryHardwareIDs:
  924. switch (PdoExtension->PdoType) {
  925. case AcpiDriver:
  926. sourceString = AcpiHardwareIdString;
  927. stringLen = sizeof(AcpiHardwareIdString);
  928. break;
  929. default:
  930. return STATUS_NOT_SUPPORTED;
  931. }
  932. break;
  933. case BusQueryCompatibleIDs:
  934. return STATUS_NOT_SUPPORTED;
  935. break;
  936. case BusQueryInstanceID:
  937. sourceString = AcpiInstanceIdString;
  938. stringLen = sizeof(AcpiInstanceIdString);
  939. break;
  940. default:
  941. return STATUS_NOT_SUPPORTED;
  942. }
  943. idString = ExAllocatePoolWithTag(PagedPool,
  944. stringLen + sizeof(UNICODE_NULL),
  945. HAL_POOL_TAG);
  946. if (!idString) {
  947. return STATUS_INSUFFICIENT_RESOURCES;
  948. }
  949. RtlCopyMemory(idString,
  950. sourceString, stringLen);
  951. *(idString + stringLen / sizeof(WCHAR)) = UNICODE_NULL;
  952. *BusQueryId = idString;
  953. return STATUS_SUCCESS;
  954. }
  955. NTSTATUS
  956. HalpQueryIdFdo(
  957. IN PDEVICE_OBJECT DeviceObject,
  958. IN BUS_QUERY_ID_TYPE IdType,
  959. IN OUT PWSTR *BusQueryId
  960. )
  961. /*++
  962. Routine Description:
  963. This routine identifies each of the children that were
  964. enumerated in HalpQueryDeviceRelations.
  965. Arguments:
  966. DeviceObject - PDO of the child
  967. IdType - the type of ID to be returned.
  968. BusQueryId - pointer to the wide string being returned
  969. Return Value:
  970. status
  971. --*/
  972. {
  973. PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
  974. PWSTR idString;
  975. PWCHAR sourceString = NULL;
  976. ULONG stringLen;
  977. UNICODE_STRING String;
  978. WCHAR Buffer[16];
  979. NTSTATUS Status;
  980. PWCHAR widechar;
  981. static WCHAR HalInstanceIdString[] = L"0";
  982. PAGED_CODE();
  983. switch (IdType) {
  984. case BusQueryDeviceID:
  985. case BusQueryHardwareIDs:
  986. sourceString = HalHardwareIdString;
  987. widechar = (PWCHAR)&HalHardwareIdString;
  988. while (*widechar != 0) widechar++;
  989. stringLen = (ULONG)((PUCHAR)widechar - ((PUCHAR)&HalHardwareIdString) + 2);
  990. break;
  991. case BusQueryInstanceID:
  992. sourceString = HalInstanceIdString;
  993. stringLen = sizeof(HalInstanceIdString);
  994. break;
  995. default:
  996. break;
  997. }
  998. if (sourceString) {
  999. //
  1000. // Note that hardware IDs and compatible IDs must be terminated by
  1001. // 2 NULLs.
  1002. //
  1003. idString = ExAllocatePoolWithTag(PagedPool,
  1004. stringLen + sizeof(UNICODE_NULL),
  1005. HAL_POOL_TAG);
  1006. if (!idString) {
  1007. HalDebugPrint(( HAL_PNP, "HalpQueryIdFdo: couldn't allocate pool\n" ));
  1008. return STATUS_INSUFFICIENT_RESOURCES;
  1009. }
  1010. RtlCopyMemory(idString,
  1011. sourceString, stringLen);
  1012. *(idString + stringLen / sizeof(WCHAR)) = UNICODE_NULL;
  1013. *BusQueryId = idString;
  1014. return STATUS_SUCCESS;
  1015. } else {
  1016. return STATUS_NOT_SUPPORTED;
  1017. }
  1018. }
  1019. NTSTATUS
  1020. HalpQueryCapabilities(
  1021. IN PDEVICE_OBJECT PdoExtension,
  1022. IN PDEVICE_CAPABILITIES Capabilities
  1023. )
  1024. /*++
  1025. Routine Description:
  1026. This routine fills in the DEVICE_CAPABILITIES structure for
  1027. a device.
  1028. Arguments:
  1029. DeviceObject - PDO of the child
  1030. Capabilities - pointer to the structure to be filled in.
  1031. Return Value:
  1032. status
  1033. --*/
  1034. {
  1035. PAGED_CODE();
  1036. ASSERT(Capabilities->Version == 1);
  1037. if (Capabilities->Version != 1) {
  1038. return STATUS_NOT_SUPPORTED;
  1039. }
  1040. Capabilities->LockSupported = FALSE;
  1041. Capabilities->EjectSupported = FALSE;
  1042. Capabilities->Removable = FALSE;
  1043. Capabilities->DockDevice = FALSE;
  1044. Capabilities->UniqueID = TRUE;
  1045. Capabilities->SilentInstall = TRUE;
  1046. Capabilities->RawDeviceOK = FALSE;
  1047. Capabilities->Address = 0xffffffff;
  1048. Capabilities->UINumber = 0xffffffff;
  1049. Capabilities->D1Latency = 0;
  1050. Capabilities->D2Latency = 0;
  1051. Capabilities->D3Latency = 0;
  1052. //
  1053. // Default S->D mapping
  1054. //
  1055. Capabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
  1056. Capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  1057. Capabilities->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
  1058. return STATUS_SUCCESS;
  1059. }
  1060. NTSTATUS
  1061. HalpQueryResources(
  1062. PDEVICE_OBJECT DeviceObject,
  1063. PCM_RESOURCE_LIST *Resources
  1064. )
  1065. {
  1066. PIO_RESOURCE_REQUIREMENTS_LIST requirements;
  1067. PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
  1068. PIO_RESOURCE_DESCRIPTOR descriptor;
  1069. PCM_RESOURCE_LIST cmResList;
  1070. NTSTATUS status;
  1071. ULONG i;
  1072. PAGED_CODE();
  1073. if (PdoExtension->PdoType == AcpiDriver) {
  1074. //
  1075. // The whole point behind creating a boot config for the
  1076. // ACPI PDO is that the PnP Manager will not terminate
  1077. // its algorithm that tries to reserve boot configs for
  1078. // all of ACPI's children. So it is not necessary that
  1079. // ACPI have a complicated list of resources in its boot
  1080. // config. We'll be happy with just the IRQ.
  1081. //
  1082. // N.B. At the time of this writing, it should also be
  1083. // true that the IRQ is the only resource that the ACPI
  1084. // claims anyhow.
  1085. //
  1086. status = HalpQueryAcpiResourceRequirements(&requirements);
  1087. if (!NT_SUCCESS(status)) {
  1088. return status;
  1089. }
  1090. cmResList = ExAllocatePoolWithTag(PagedPool,
  1091. sizeof(CM_RESOURCE_LIST),
  1092. HAL_POOL_TAG);
  1093. if (!cmResList) {
  1094. ExFreePool(requirements);
  1095. return STATUS_INSUFFICIENT_RESOURCES;
  1096. }
  1097. RtlZeroMemory(cmResList, sizeof(CM_RESOURCE_LIST));
  1098. cmResList->Count = 1;
  1099. cmResList->List[0].InterfaceType = PNPBus;
  1100. cmResList->List[0].BusNumber = -1;
  1101. cmResList->List[0].PartialResourceList.Version = 1;
  1102. cmResList->List[0].PartialResourceList.Revision = 1;
  1103. cmResList->List[0].PartialResourceList.Count = 1;
  1104. cmResList->List[0].PartialResourceList.PartialDescriptors[0].Type =
  1105. CmResourceTypeInterrupt;
  1106. ASSERT(requirements->AlternativeLists == 1);
  1107. for (i = 0; i < requirements->List[0].Count; i++) {
  1108. descriptor = &requirements->List[0].Descriptors[i];
  1109. if (descriptor->Type == CmResourceTypeInterrupt) {
  1110. cmResList->List[0].PartialResourceList.PartialDescriptors[0].ShareDisposition =
  1111. descriptor->ShareDisposition;
  1112. cmResList->List[0].PartialResourceList.PartialDescriptors[0].Flags =
  1113. descriptor->Flags;
  1114. ASSERT(descriptor->u.Interrupt.MinimumVector ==
  1115. descriptor->u.Interrupt.MaximumVector);
  1116. cmResList->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Level =
  1117. descriptor->u.Interrupt.MinimumVector;
  1118. cmResList->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector =
  1119. descriptor->u.Interrupt.MinimumVector;
  1120. cmResList->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = -1;
  1121. *Resources = cmResList;
  1122. ExFreePool(requirements);
  1123. return STATUS_SUCCESS;
  1124. }
  1125. }
  1126. ExFreePool(requirements);
  1127. ExFreePool(cmResList);
  1128. return STATUS_NOT_FOUND;
  1129. } else {
  1130. return STATUS_NOT_SUPPORTED;
  1131. }
  1132. }
  1133. NTSTATUS
  1134. HalpQueryResourceRequirements(
  1135. IN PDEVICE_OBJECT DeviceObject,
  1136. IN PIO_RESOURCE_REQUIREMENTS_LIST *Requirements
  1137. )
  1138. /*++
  1139. Routine Description:
  1140. This routine handles IRP_MN_QUERY_RESOURCE_REQUIREMENTS.
  1141. Arguments:
  1142. DeviceObject - PDO of the child
  1143. Requirements - pointer to be filled in with the devices
  1144. resource requirements.
  1145. Return Value:
  1146. status
  1147. --*/
  1148. {
  1149. PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
  1150. PAGED_CODE();
  1151. if (PdoExtension->PdoType == AcpiDriver) {
  1152. return HalpQueryAcpiResourceRequirements(Requirements);
  1153. } else {
  1154. return STATUS_NOT_SUPPORTED;
  1155. }
  1156. }
  1157. NTSTATUS
  1158. HalpQueryInterface(
  1159. IN PDEVICE_OBJECT DeviceObject,
  1160. IN LPCGUID InterfaceType,
  1161. IN USHORT Version,
  1162. IN PVOID InterfaceSpecificData,
  1163. IN ULONG InterfaceBufferSize,
  1164. IN OUT PINTERFACE Interface,
  1165. IN OUT PULONG Length
  1166. )
  1167. /*++
  1168. Routine Description:
  1169. This routine fills in the interface structure for a device.
  1170. Arguments:
  1171. DeviceObject - PDO of the child
  1172. InterfaceType - Pointer to the interface type GUID.
  1173. Version - Supplies the requested interface version.
  1174. InterfaceSpecificData - This is context that means something based on the interface.
  1175. Interface Buffer Size - Supplies the length of a buffer for the interface structure.
  1176. Interface - Supplies a pointer where interference information should be returned.ointer to the supplied interface buffer.
  1177. Length - The value is updated on return to actual number of bytes modified.
  1178. Return Value:
  1179. status
  1180. --*/
  1181. {
  1182. PPDO_EXTENSION PdoExtension = (PPDO_EXTENSION)DeviceObject->DeviceExtension;
  1183. CM_RESOURCE_TYPE resource = (CM_RESOURCE_TYPE)(INT_PTR)InterfaceSpecificData;
  1184. PAGED_CODE();
  1185. ASSERT_PDO_EXTENSION(PdoExtension);
  1186. if (IsEqualGUID(&GUID_BUS_INTERFACE_STANDARD, InterfaceType)) {
  1187. PBUS_INTERFACE_STANDARD standard = (PBUS_INTERFACE_STANDARD)Interface;
  1188. //
  1189. // ASSERT we know about all of the fields in the structure.
  1190. //
  1191. ASSERT(sizeof(BUS_INTERFACE_STANDARD) == FIELD_OFFSET(BUS_INTERFACE_STANDARD, GetBusData) + sizeof(PGET_SET_DEVICE_DATA));
  1192. *Length = sizeof(BUS_INTERFACE_STANDARD);
  1193. if (InterfaceBufferSize < sizeof(BUS_INTERFACE_STANDARD)) {
  1194. return STATUS_BUFFER_TOO_SMALL;
  1195. }
  1196. //
  1197. // The only version this code knows about is 1.
  1198. //
  1199. standard->Size = sizeof(BUS_INTERFACE_STANDARD);
  1200. standard->Version = HAL_BUS_INTERFACE_STD_VERSION;
  1201. standard->Context = DeviceObject;
  1202. standard->InterfaceReference = HalPnpInterfaceReference;
  1203. standard->InterfaceDereference = HalPnpInterfaceDereference;
  1204. standard->TranslateBusAddress = HalPnpTranslateBusAddress;
  1205. standard->GetDmaAdapter = HalPnpGetDmaAdapter;
  1206. standard->SetBusData = NULL;
  1207. standard->GetBusData = NULL;
  1208. } else if (IsEqualGUID(&GUID_TRANSLATOR_INTERFACE_STANDARD, InterfaceType)) {
  1209. PTRANSLATOR_INTERFACE translator = (PTRANSLATOR_INTERFACE)Interface;
  1210. //
  1211. // Common initialization.
  1212. //
  1213. if (InterfaceBufferSize < sizeof(TRANSLATOR_INTERFACE)) {
  1214. *Length = sizeof(TRANSLATOR_INTERFACE);
  1215. return STATUS_BUFFER_TOO_SMALL;
  1216. }
  1217. switch ((CM_RESOURCE_TYPE)(INT_PTR)InterfaceSpecificData) {
  1218. case CmResourceTypeInterrupt:
  1219. translator->Size = sizeof(TRANSLATOR_INTERFACE);
  1220. translator->Version = HAL_IRQ_TRANSLATOR_VERSION;
  1221. translator->Context = DeviceObject;
  1222. translator->InterfaceReference = HalTranslatorReference;
  1223. translator->InterfaceDereference = HalTranslatorDereference;
  1224. translator->TranslateResources = HalIrqTranslateResourcesRoot;
  1225. translator->TranslateResourceRequirements =
  1226. HalIrqTranslateResourceRequirementsRoot;
  1227. *Length = sizeof(TRANSLATOR_INTERFACE);
  1228. break;
  1229. default:
  1230. return STATUS_NOT_SUPPORTED;
  1231. }
  1232. } else if (IsEqualGUID(&GUID_ACPI_REGS_INTERFACE_STANDARD, InterfaceType)) {
  1233. //
  1234. // ACPI register function interface.
  1235. //
  1236. PACPI_REGS_INTERFACE_STANDARD AcpiRegInterface =
  1237. (PACPI_REGS_INTERFACE_STANDARD)Interface;
  1238. if (!HalpFakeAcpiRegisters()) {
  1239. return STATUS_NOT_FOUND;
  1240. }
  1241. DbgPrint("Faking ACPI registers\n");
  1242. //
  1243. // Common initialization.
  1244. //
  1245. *Length = sizeof(ACPI_REGS_INTERFACE_STANDARD);
  1246. if (InterfaceBufferSize < sizeof(ACPI_REGS_INTERFACE_STANDARD)) {
  1247. return STATUS_BUFFER_TOO_SMALL;
  1248. }
  1249. AcpiRegInterface->Size = sizeof(ACPI_REGS_INTERFACE_STANDARD);
  1250. AcpiRegInterface->Context = NULL;
  1251. AcpiRegInterface->InterfaceReference = HalTranslatorReference;
  1252. AcpiRegInterface->InterfaceDereference = HalTranslatorDereference;
  1253. //
  1254. // Set the two ACPI register access routines.
  1255. //
  1256. AcpiRegInterface->ReadAcpiRegister = HalpReadAcpiRegister;
  1257. AcpiRegInterface->WriteAcpiRegister = HalpWriteAcpiRegister;
  1258. } else if (IsEqualGUID(&GUID_ACPI_PORT_RANGES_INTERFACE_STANDARD,
  1259. InterfaceType)) {
  1260. PHAL_PORT_RANGE_INTERFACE PortRanges = (PHAL_PORT_RANGE_INTERFACE)Interface;
  1261. *Length = sizeof(HAL_PORT_RANGE_INTERFACE);
  1262. if (InterfaceBufferSize < sizeof(HAL_PORT_RANGE_INTERFACE)) {
  1263. return STATUS_BUFFER_TOO_SMALL;
  1264. }
  1265. PortRanges->Size = sizeof(HAL_PORT_RANGE_INTERFACE);
  1266. PortRanges->Version = HAL_PORT_RANGE_INTERFACE_VERSION;
  1267. PortRanges->Context = DeviceObject;
  1268. PortRanges->InterfaceReference = HalPnpInterfaceReference;
  1269. PortRanges->InterfaceDereference = HalPnpInterfaceDereference;
  1270. PortRanges->QueryAllocateRange = HalpQueryAllocatePortRange;
  1271. PortRanges->FreeRange = HalpFreePortRange;
  1272. } else {
  1273. //
  1274. // Unsupport bus interface type.
  1275. //
  1276. return STATUS_NOT_SUPPORTED ;
  1277. }
  1278. //
  1279. // Bump the reference count.
  1280. //
  1281. InterlockedIncrement(&PdoExtension->InterfaceReferenceCount);
  1282. return STATUS_SUCCESS;
  1283. }
  1284. #ifdef WANT_IRQ_ROUTING
  1285. NTSTATUS
  1286. HalpQueryInterfaceFdo(
  1287. IN PDEVICE_OBJECT DeviceObject,
  1288. IN LPCGUID InterfaceType,
  1289. IN USHORT Version,
  1290. IN PVOID InterfaceSpecificData,
  1291. IN ULONG InterfaceBufferSize,
  1292. IN OUT PINTERFACE Interface,
  1293. IN OUT PULONG Length
  1294. )
  1295. /*++
  1296. Routine Description:
  1297. This routine fills in the interface structure for
  1298. a device.
  1299. Arguments:
  1300. DeviceObject - FDO of the child
  1301. InterfaceType - Pointer to the interface type GUID.
  1302. Version - Supplies the requested interface version.
  1303. InterfaceSpecificData - This is context that means something based on the
  1304. interface.
  1305. InterfaceBufferSize - Supplies the length of the buffer for the interface
  1306. structure.
  1307. Interface - Supplies a pointer where the interface informaiton should
  1308. be returned.
  1309. Length - Supplies the length of the buffer for the interface structure.
  1310. This value is updated on return to actual number of bytes modified.
  1311. Return Value:
  1312. status
  1313. --*/
  1314. {
  1315. NTSTATUS status = STATUS_NOT_SUPPORTED;
  1316. CM_RESOURCE_TYPE resource = (CM_RESOURCE_TYPE)InterfaceSpecificData;
  1317. PAGED_CODE();
  1318. if ( resource == CmResourceTypeInterrupt &&
  1319. IsPciIrqRoutingEnabled()) {
  1320. if (IsEqualGUID(&GUID_ARBITER_INTERFACE_STANDARD, InterfaceType)) {
  1321. status = HalpInitIrqArbiter(DeviceObject);
  1322. if (NT_SUCCESS(status))
  1323. {
  1324. status = HalpFillInIrqArbiter(
  1325. DeviceObject,
  1326. InterfaceType,
  1327. Version,
  1328. InterfaceSpecificData,
  1329. InterfaceBufferSize,
  1330. Interface,
  1331. Length
  1332. );
  1333. }
  1334. }
  1335. else if (IsEqualGUID(&GUID_TRANSLATOR_INTERFACE_STANDARD, InterfaceType)) {
  1336. PTRANSLATOR_INTERFACE translator;
  1337. *Length = sizeof(TRANSLATOR_INTERFACE);
  1338. if (InterfaceBufferSize < sizeof(TRANSLATOR_INTERFACE)) {
  1339. return STATUS_BUFFER_TOO_SMALL;
  1340. }
  1341. translator = (PTRANSLATOR_INTERFACE)Interface;
  1342. //
  1343. // Fill in the common bits.
  1344. //
  1345. RtlZeroMemory(translator, sizeof (TRANSLATOR_INTERFACE));
  1346. translator->Size = sizeof(TRANSLATOR_INTERFACE);
  1347. translator->Version = HAL_IRQ_TRANSLATOR_VERSION;
  1348. translator->Context = DeviceObject;
  1349. translator->InterfaceReference = HalTranslatorReference;
  1350. translator->InterfaceDereference = HalTranslatorDereference;
  1351. //
  1352. // Set IRQ translator for PCI interrupts.
  1353. //
  1354. translator->TranslateResources = HalIrqTranslateResourcesRoot;
  1355. translator->TranslateResourceRequirements =
  1356. HalIrqTranslateResourceRequirementsRoot;
  1357. status = STATUS_SUCCESS;
  1358. HalDebugPrint(( HAL_PNP, "Providing Irq translator for FDO %p since Pci Irq Routing is enabled!", DeviceObject));
  1359. }
  1360. }
  1361. return (status);
  1362. }
  1363. #endif
  1364. VOID
  1365. HalPnpInterfaceReference(
  1366. PVOID Context
  1367. )
  1368. /*++
  1369. Routine Description:
  1370. This function increments the reference count on the interface context.
  1371. Arguments:
  1372. Context - Supplies a pointer to the interface context. This is actually
  1373. the PDO for the root bus.
  1374. Return Value:
  1375. None
  1376. --*/
  1377. {
  1378. PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
  1379. PAGED_CODE();
  1380. ASSERT_PDO_EXTENSION( PdoExtension );
  1381. InterlockedIncrement( &PdoExtension->InterfaceReferenceCount );
  1382. }
  1383. VOID
  1384. HalPnpInterfaceDereference(
  1385. PVOID Context
  1386. )
  1387. /*++
  1388. Routine Description:
  1389. This function decrements the reference count on the interface context.
  1390. Arguments:
  1391. Context - Supplies a pointer to the interface context. This is actually
  1392. the PDO for the root bus.
  1393. Return Value:
  1394. None
  1395. --*/
  1396. {
  1397. PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
  1398. LONG Result;
  1399. PAGED_CODE();
  1400. ASSERT_PDO_EXTENSION( PdoExtension );
  1401. Result = InterlockedDecrement( &PdoExtension->InterfaceReferenceCount );
  1402. ASSERT( Result >= 0 );
  1403. }
  1404. BOOLEAN
  1405. HalPnpTranslateBusAddress(
  1406. IN PVOID Context,
  1407. IN PHYSICAL_ADDRESS BusAddress,
  1408. IN ULONG Length,
  1409. IN OUT PULONG AddressSpace,
  1410. OUT PPHYSICAL_ADDRESS TranslatedAddress
  1411. )
  1412. /*++
  1413. Routine Description:
  1414. This function is used to translate bus addresses from legacy drivers. It really
  1415. should never get called on an ACPI system as the PCI or ACPI driver should field
  1416. these requests before it gets here.
  1417. Arguments:
  1418. Context - Supplies a pointer to the interface context. This is actually
  1419. the PDO for the root bus.
  1420. BusAddress - Supplies the orginal address to be translated.
  1421. Length - Supplies the length of the range to be translated.
  1422. AddressSpace - Points to the location of of the address space type such as
  1423. memory or I/O port. This value is updated by the translation.
  1424. TranslatedAddress - Returns the translated address.
  1425. Return Value:
  1426. Returns a boolean indicating if the operations was a success.
  1427. --*/
  1428. {
  1429. HalDebugPrint(( HAL_PNP, "HAL: HalPnpTranslateBusAddress Called, BusAddress = %p\n", BusAddress ));
  1430. *TranslatedAddress = BusAddress;
  1431. return TRUE;
  1432. }
  1433. PDMA_ADAPTER
  1434. HalPnpGetDmaAdapter(
  1435. IN PVOID Context,
  1436. IN struct _DEVICE_DESCRIPTION *DeviceDescriptor,
  1437. OUT PULONG NumberOfMapRegisters
  1438. )
  1439. /*++
  1440. Routine Description:
  1441. This function writes the PCI configuration space.
  1442. Arguments:
  1443. Context - Supplies a pointer to the interface context. This is actually
  1444. the PDO for the root bus.
  1445. DeviceDescriptor - Supplies the device descriptor used to allocate the dma
  1446. adapter object.
  1447. NubmerOfMapRegisters - Returns the maximum number of map registers a device
  1448. can allocate at one time.
  1449. Return Value:
  1450. Returns a DMA adapter or NULL.
  1451. --*/
  1452. {
  1453. PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
  1454. PAGED_CODE();
  1455. ASSERT_PDO_EXTENSION( PdoExtension );
  1456. //
  1457. // Fill in the bus number.
  1458. //
  1459. return (PDMA_ADAPTER) HalGetAdapter( DeviceDescriptor, NumberOfMapRegisters );
  1460. }