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.

2343 lines
57 KiB

  1. /*++
  2. Copyright (c) 1991-2000 Microsoft Corporation
  3. Module Name:
  4. misc.c
  5. Abstract:
  6. This file contains pnp isa bus extender support routines.
  7. Author:
  8. Shie-Lin Tzong (shielint) 27-July-1995
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "busp.h"
  14. #include "pnpisa.h"
  15. #ifdef ALLOC_PRAGMA
  16. //#pragma alloc_text(PAGE, PipLockDeviceDatabase)
  17. //#pragma alloc_text(PAGE, PipUnlockDeviceDatabase)
  18. #pragma alloc_text(PAGE, PipQueryDeviceRelations)
  19. //#pragma alloc_text(PAGE, PipIsCardEnumeratedAlready)
  20. #pragma alloc_text(PAGE, PipCleanupAcquiredResources)
  21. #pragma alloc_text(PAGE, PipMapReadDataPort)
  22. #pragma alloc_text(PAGE, PipGetMappedAddress)
  23. #pragma alloc_text(PAGE, PipDecompressEisaId)
  24. #pragma alloc_text(PAGE, PipLogError)
  25. #pragma alloc_text(PAGE, PipOpenRegistryKey)
  26. #pragma alloc_text(PAGE, PipGetRegistryValue)
  27. #pragma alloc_text(PAGE, PipOpenCurrentHwProfileDeviceInstanceKey)
  28. #pragma alloc_text(PAGE, PipGetDeviceInstanceCsConfigFlags)
  29. #pragma alloc_text(PAGE, PipDetermineResourceListSize)
  30. #pragma alloc_text(PAGE, PipResetGlobals)
  31. #pragma alloc_text(PAGE, PipMapAddressAndCmdPort)
  32. #pragma alloc_text(PAGE, PiNeedDeferISABridge)
  33. #pragma alloc_text(PAGE, PipReleaseDeviceResources)
  34. #if DBG
  35. //#pragma alloc_text(PAGE, PipDebugPrint)
  36. #pragma alloc_text(PAGE, PipDumpIoResourceDescriptor)
  37. #pragma alloc_text(PAGE, PipDumpIoResourceList)
  38. #pragma alloc_text(PAGE, PipDumpCmResourceDescriptor)
  39. #pragma alloc_text(PAGE, PipDumpCmResourceList)
  40. #endif
  41. #endif
  42. #define IRQFLAGS_VALUE_NAME L"IrqFlags"
  43. #define BOOTRESOURCES_VALUE_NAME L"BootRes"
  44. #if ISOLATE_CARDS
  45. UCHAR CurrentCsn = 0;
  46. UCHAR CurrentDev = 255;
  47. VOID
  48. PipWaitForKey(VOID)
  49. {
  50. ASSERT((PipState == PiSConfig) || (PipState == PiSIsolation) || (PipState == PiSSleep));
  51. PipWriteAddress(CONFIG_CONTROL_PORT);
  52. PipWriteData(CONTROL_WAIT_FOR_KEY);
  53. PipReportStateChange(PiSWaitForKey);
  54. CurrentCsn = 0;
  55. CurrentDev = 255;
  56. }
  57. VOID
  58. PipConfig(
  59. IN UCHAR Csn
  60. )
  61. {
  62. ASSERT(Csn);
  63. ASSERT((PipState == PiSConfig) || (PipState == PiSIsolation) || (PipState == PiSSleep));
  64. PipWriteAddress(WAKE_CSN_PORT);
  65. PipWriteData(Csn);
  66. DebugPrint((DEBUG_STATE, "Wake CSN %u\n", (ULONG) Csn));
  67. CurrentCsn = Csn;
  68. CurrentDev = 255;
  69. PipReportStateChange(PiSConfig);
  70. }
  71. VOID
  72. PipIsolation(
  73. VOID
  74. )
  75. {
  76. ASSERT((PipState == PiSConfig) || (PipState == PiSIsolation) || (PipState == PiSSleep));
  77. PipWriteAddress(WAKE_CSN_PORT);
  78. PipWriteData(0);
  79. CurrentCsn = 0;
  80. CurrentDev = 255;
  81. DebugPrint((DEBUG_STATE, "Isolate cards w/o CSN\n"));
  82. PipReportStateChange(PiSIsolation);
  83. }
  84. VOID
  85. PipSleep(
  86. VOID
  87. )
  88. {
  89. ASSERT((PipState == PiSConfig) || PipState == PiSIsolation);
  90. PipWriteAddress(WAKE_CSN_PORT);
  91. PipWriteData(0);
  92. CurrentCsn = 0;
  93. CurrentDev = 255;
  94. DebugPrint((DEBUG_STATE, "Putting all cards to sleep (we think)\n"));
  95. PipReportStateChange(PiSSleep);
  96. }
  97. VOID
  98. PipActivateDevice (
  99. )
  100. {
  101. UCHAR tmp;
  102. PipWriteAddress(IO_RANGE_CHECK_PORT);
  103. tmp = PipReadData();
  104. tmp &= ~2;
  105. PipWriteAddress(IO_RANGE_CHECK_PORT);
  106. PipWriteData(tmp);
  107. PipWriteAddress(ACTIVATE_PORT);
  108. PipWriteData(1);
  109. DebugPrint((DEBUG_STATE, "Activated card CSN %d/LDN %d\n",
  110. (ULONG) CurrentCsn,
  111. (ULONG) CurrentDev));
  112. }
  113. VOID
  114. PipDeactivateDevice (
  115. )
  116. {
  117. PipWriteAddress(ACTIVATE_PORT);
  118. PipWriteData(0);
  119. DebugPrint((DEBUG_STATE, "Deactivated card CSN %d/LDN %d\n",
  120. (ULONG) CurrentCsn,
  121. (ULONG) CurrentDev));
  122. }
  123. VOID
  124. PipSelectDevice(
  125. IN UCHAR Device
  126. )
  127. {
  128. ASSERT(PipState == PiSConfig);
  129. PipWriteAddress(LOGICAL_DEVICE_PORT);
  130. PipWriteData(Device);
  131. CurrentDev = Device;
  132. DebugPrint((DEBUG_STATE, "Selected CSN %d/LDN %d\n",
  133. (ULONG) CurrentCsn,
  134. (ULONG) Device));
  135. }
  136. VOID
  137. PipWakeAndSelectDevice(
  138. IN UCHAR Csn,
  139. IN UCHAR Device
  140. )
  141. {
  142. PipLFSRInitiation();
  143. PipConfig(Csn);
  144. PipSelectDevice(Device);
  145. }
  146. PDEVICE_INFORMATION
  147. PipReferenceDeviceInformation (
  148. IN PDEVICE_OBJECT DeviceObject,
  149. IN BOOLEAN ConfigHardware
  150. )
  151. /*++
  152. Routine Description:
  153. This function locks a device node so it won't go away.
  154. Note, this function does not lock the whole device node tree.
  155. Arguments:
  156. DeviceNode - Supplies a pointer to the device information node
  157. Return Value:
  158. None.
  159. --*/
  160. {
  161. PDEVICE_INFORMATION deviceInfo;
  162. deviceInfo = (PDEVICE_INFORMATION)DeviceObject->DeviceExtension;
  163. if (deviceInfo && !(deviceInfo->Flags & DF_DELETED)) {
  164. if ((deviceInfo->Flags & DF_NOT_FUNCTIONING) && ConfigHardware) {
  165. PipDereferenceDeviceInformation(NULL, FALSE);
  166. return NULL;
  167. }
  168. if (!(deviceInfo->Flags & DF_READ_DATA_PORT) && ConfigHardware) {
  169. PipWakeAndSelectDevice(
  170. (UCHAR)deviceInfo->CardInformation->CardSelectNumber,
  171. (UCHAR)deviceInfo->LogicalDeviceNumber);
  172. }
  173. return deviceInfo;
  174. } else {
  175. PipDereferenceDeviceInformation(NULL, FALSE);
  176. return NULL;
  177. }
  178. }
  179. VOID
  180. PipDereferenceDeviceInformation(
  181. IN PDEVICE_INFORMATION DeviceInformation, BOOLEAN ConfigedHardware
  182. )
  183. /*++
  184. Routine Description:
  185. This function releases the enumeration lock of the specified device node.
  186. Arguments:
  187. DeviceNode - Supplies a pointer to the device node whose lock is to be released.
  188. Return Value:
  189. None.
  190. --*/
  191. {
  192. //
  193. // Synchronize the dec and set event operations with IopAcquireEnumerationLock.
  194. //
  195. if (DeviceInformation) {
  196. if (!(DeviceInformation->Flags & DF_READ_DATA_PORT) && ConfigedHardware) {
  197. if (PipState != PiSWaitForKey) {
  198. PipWaitForKey();
  199. }
  200. }
  201. }
  202. }
  203. VOID
  204. PipLockDeviceDatabase(
  205. VOID
  206. )
  207. /*++
  208. Routine Description:
  209. This function locks the whole device node tree. Currently, eject operation
  210. needs to lock the whole device node tree.
  211. Arguments:
  212. None.
  213. Return Value:
  214. None.
  215. --*/
  216. {
  217. KeWaitForSingleObject( &PipDeviceTreeLock,
  218. Executive,
  219. KernelMode,
  220. FALSE,
  221. NULL );
  222. }
  223. VOID
  224. PipUnlockDeviceDatabase (
  225. VOID
  226. )
  227. /*++
  228. Routine Description:
  229. This function releases the lock of the whole device node tree.
  230. Arguments:
  231. None.
  232. Return Value:
  233. None.
  234. --*/
  235. {
  236. KeSetEvent( &PipDeviceTreeLock,
  237. 0,
  238. FALSE );
  239. }
  240. VOID
  241. PipDeleteDevice (
  242. PDEVICE_OBJECT DeviceObject
  243. )
  244. /*++
  245. Routine Description:
  246. This routine
  247. Parameters:
  248. P1 -
  249. Return Value:
  250. Status code that indicates whether or not the function was successful.
  251. --*/
  252. {
  253. PDEVICE_INFORMATION deviceInfo, devicex, devicep;
  254. PCARD_INFORMATION cardInfo, cardx, cardp;
  255. PSINGLE_LIST_ENTRY deviceLink, cardLink;
  256. NTSTATUS status = STATUS_SUCCESS;
  257. PPI_BUS_EXTENSION busExtension;
  258. deviceInfo = (PDEVICE_INFORMATION)DeviceObject->DeviceExtension;
  259. deviceInfo->Flags |= DF_DELETED;
  260. //
  261. // Free the pool
  262. //
  263. if (deviceInfo->ResourceRequirements) {
  264. ExFreePool(deviceInfo->ResourceRequirements);
  265. }
  266. if (deviceInfo->BootResources) {
  267. ExFreePool(deviceInfo->BootResources);
  268. }
  269. if (deviceInfo->AllocatedResources) {
  270. ExFreePool(deviceInfo->AllocatedResources);
  271. }
  272. if (deviceInfo->LogConfHandle) {
  273. ZwClose(deviceInfo->LogConfHandle);
  274. deviceInfo->LogConfHandle = NULL;
  275. }
  276. busExtension = deviceInfo->ParentDeviceExtension;
  277. cardInfo = deviceInfo->CardInformation;
  278. PipLockDeviceDatabase();
  279. //
  280. // Remove the device from device list.
  281. //
  282. deviceLink = busExtension->DeviceList.Next;
  283. devicep = NULL;
  284. while (deviceLink) {
  285. devicex = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
  286. if (devicex == deviceInfo) {
  287. break;
  288. }
  289. devicep = devicex;
  290. deviceLink = devicex->DeviceList.Next;
  291. }
  292. ASSERT(devicex == deviceInfo);
  293. if (devicep == NULL) {
  294. busExtension->DeviceList.Next = deviceInfo->DeviceList.Next;
  295. } else {
  296. devicep->DeviceList.Next = deviceInfo->DeviceList.Next;
  297. }
  298. //
  299. // Remove the device from logical device list of the card
  300. //
  301. deviceLink = cardInfo->LogicalDeviceList.Next;
  302. devicep = NULL;
  303. while (deviceLink) {
  304. devicex = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, LogicalDeviceList);
  305. if (devicex == deviceInfo) {
  306. break;
  307. }
  308. devicep = devicex;
  309. deviceLink = devicex->LogicalDeviceList.Next;
  310. }
  311. ASSERT(devicex == deviceInfo);
  312. if (devicep == NULL) {
  313. cardInfo->LogicalDeviceList.Next = deviceInfo->LogicalDeviceList.Next;
  314. } else {
  315. devicep->LogicalDeviceList.Next = deviceInfo->LogicalDeviceList.Next;
  316. }
  317. cardInfo->NumberLogicalDevices--;
  318. //
  319. // All the devices are gone. That means the card is removed.
  320. // Next remove the isapnp card structure.
  321. //
  322. if (cardInfo->NumberLogicalDevices == 0) {
  323. ASSERT(cardInfo->LogicalDeviceList.Next == NULL);
  324. cardLink = busExtension->CardList.Next;
  325. cardp = NULL;
  326. while (cardLink) {
  327. cardx = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
  328. if (cardx == cardInfo) {
  329. break;
  330. }
  331. cardp = cardx;
  332. cardLink = cardx->CardList.Next;
  333. }
  334. ASSERT(cardx == cardInfo);
  335. if (cardp == NULL) {
  336. busExtension->CardList.Next = cardInfo->CardList.Next;
  337. } else {
  338. cardp->CardList.Next = cardInfo->CardList.Next;
  339. }
  340. }
  341. PipUnlockDeviceDatabase();
  342. //
  343. // Remove the card information structure after releasing spin lock.
  344. //
  345. if (cardInfo->NumberLogicalDevices == 0) {
  346. if (cardInfo->CardData) {
  347. ExFreePool(cardInfo->CardData);
  348. }
  349. ExFreePool(cardInfo);
  350. }
  351. IoDeleteDevice(DeviceObject);
  352. }
  353. NTSTATUS
  354. PipQueryDeviceRelations (
  355. PPI_BUS_EXTENSION BusExtension,
  356. PDEVICE_RELATIONS *DeviceRelations,
  357. BOOLEAN Removal
  358. )
  359. /*++
  360. Routine Description:
  361. This routine
  362. Parameters:
  363. P1 -
  364. Return Value:
  365. Status code that indicates whether or not the function was successful.
  366. --*/
  367. {
  368. PDEVICE_INFORMATION deviceInfo;
  369. PSINGLE_LIST_ENTRY deviceLink;
  370. NTSTATUS status = STATUS_SUCCESS;
  371. PDEVICE_OBJECT *devicePtr;
  372. ULONG count = 0;
  373. PDEVICE_RELATIONS deviceRelations;
  374. PAGED_CODE();
  375. *DeviceRelations = NULL;
  376. //
  377. // Go through the card link list to match the card data
  378. //
  379. deviceLink = BusExtension->DeviceList.Next;
  380. while (deviceLink) {
  381. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
  382. //
  383. // if it's the RDP ignore it for removal relations
  384. //
  385. if ((deviceInfo->Flags & DF_ENUMERATED) &&
  386. (!(deviceInfo->Flags & DF_READ_DATA_PORT) || !Removal)) {
  387. count++;
  388. } else {
  389. DebugPrint((DEBUG_PNP, "PipQueryDeviceRelations skipping a node, Flags: %x\n",deviceInfo->Flags));
  390. }
  391. deviceLink = deviceInfo->DeviceList.Next;
  392. }
  393. if (count != 0) {
  394. deviceRelations = (PDEVICE_RELATIONS) ExAllocatePool(
  395. PagedPool,
  396. sizeof(DEVICE_RELATIONS) + (count - 1) * sizeof(PDEVICE_OBJECT));
  397. if (deviceRelations) {
  398. deviceRelations->Count = count;
  399. deviceLink = BusExtension->DeviceList.Next;
  400. devicePtr = deviceRelations->Objects;
  401. while (deviceLink) {
  402. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
  403. if ((deviceInfo->Flags & DF_ENUMERATED) &&
  404. (!(deviceInfo->Flags & DF_READ_DATA_PORT) || !(Removal))) {
  405. ObReferenceObject(deviceInfo->PhysicalDeviceObject);
  406. *devicePtr = deviceInfo->PhysicalDeviceObject;
  407. devicePtr++;
  408. }
  409. deviceLink = deviceInfo->DeviceList.Next;
  410. }
  411. *DeviceRelations = deviceRelations;
  412. } else {
  413. status = STATUS_INSUFFICIENT_RESOURCES;
  414. }
  415. }
  416. return status;
  417. }
  418. PCARD_INFORMATION
  419. PipIsCardEnumeratedAlready(
  420. IN PPI_BUS_EXTENSION BusExtension,
  421. IN PUCHAR CardData,
  422. IN ULONG DataLength
  423. )
  424. /*++
  425. Routine Description:
  426. This routine finds the card information structure which contains the same CardData.
  427. Parameters:
  428. CardData - Supplies a pointer to the CardData
  429. DataLength - The length of the CardData
  430. Return Value:
  431. A pointer to the CARD_INFORMATION structure if found.
  432. --*/
  433. {
  434. PCARD_INFORMATION cardInfo;
  435. PSINGLE_LIST_ENTRY cardLink;
  436. PSERIAL_IDENTIFIER serialId1, serialId2 = (PSERIAL_IDENTIFIER)CardData;
  437. //
  438. // Go through the card link list to match the card data
  439. //
  440. cardLink = BusExtension->CardList.Next;
  441. while (cardLink) {
  442. cardInfo = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
  443. if (cardInfo->CardSelectNumber != 0) { // if == 0, card is no longer present
  444. serialId1 = (PSERIAL_IDENTIFIER)cardInfo->CardData;
  445. ASSERT(serialId1 && serialId2);
  446. if (serialId1->VenderId == serialId2->VenderId &&
  447. serialId1->SerialNumber == serialId2->SerialNumber) {
  448. return cardInfo;
  449. }
  450. }
  451. cardLink = cardInfo->CardList.Next; // Get the next addr before releasing pool
  452. }
  453. return NULL;
  454. }
  455. VOID
  456. PipCleanupAcquiredResources (
  457. PPI_BUS_EXTENSION BusExtension
  458. )
  459. /*++
  460. Routine Description:
  461. This routine cleans up the resources assigned to the readdata, command and address
  462. ports.
  463. Parameters:
  464. BusExtension - specifies the isapnp bus to be cleaned up.
  465. Return Value:
  466. None.
  467. --*/
  468. {
  469. PAGED_CODE();
  470. //
  471. // Release address, command and read data port resources.
  472. //
  473. if (BusExtension->CommandPort && BusExtension->CmdPortMapped) {
  474. MmUnmapIoSpace(BusExtension->CommandPort, 1);
  475. BusExtension->CmdPortMapped = FALSE;
  476. }
  477. BusExtension->CommandPort = NULL;
  478. if (BusExtension->AddressPort && BusExtension->AddrPortMapped) {
  479. MmUnmapIoSpace(BusExtension->AddressPort, 1);
  480. BusExtension->AddrPortMapped = FALSE;
  481. }
  482. BusExtension->AddressPort = NULL;
  483. if (BusExtension->ReadDataPort) {
  484. PipReadDataPort = PipCommandPort = PipAddressPort = NULL;
  485. }
  486. if (BusExtension->ReadDataPort && BusExtension->DataPortMapped) {
  487. MmUnmapIoSpace(BusExtension->ReadDataPort - 3, 4);
  488. BusExtension->DataPortMapped = FALSE;
  489. }
  490. BusExtension->ReadDataPort = NULL;
  491. }
  492. NTSTATUS
  493. PipMapReadDataPort (
  494. IN PPI_BUS_EXTENSION BusExtension,
  495. IN PHYSICAL_ADDRESS Start,
  496. IN ULONG Length
  497. )
  498. /*++
  499. Routine Description:
  500. This routine maps specified port resources.
  501. Arguments:
  502. BusExtension - Supplies a pointer to the pnp bus extension.
  503. BaseAddressLow,
  504. BaseAddressHi - Supplies the read data port base address range to be mapped.
  505. Return Value:
  506. NTSTATUS code.
  507. --*/
  508. {
  509. NTSTATUS status;
  510. ULONG size;
  511. PHYSICAL_ADDRESS physicalAddress;
  512. ULONG dumpData[3];
  513. BOOLEAN conflictDetected;
  514. PAGED_CODE();
  515. if (BusExtension->ReadDataPort && BusExtension->DataPortMapped) {
  516. MmUnmapIoSpace(PipReadDataPort - 3, 4);
  517. PipReadDataPort = BusExtension->ReadDataPort = NULL;
  518. BusExtension->DataPortMapped = FALSE;
  519. }
  520. PipReadDataPort = PipGetMappedAddress(
  521. Isa, // InterfaceType
  522. 0, // BusNumber,
  523. Start,
  524. Length,
  525. CM_RESOURCE_PORT_IO,
  526. &BusExtension->DataPortMapped
  527. );
  528. DebugPrint((DEBUG_RDP, "PnpIsa:ReadDataPort is at %x\n",PipReadDataPort+3));
  529. if (PipReadDataPort) {
  530. PipReadDataPort += 3;
  531. BusExtension->ReadDataPort = PipReadDataPort;
  532. status = STATUS_SUCCESS;
  533. } else {
  534. status = STATUS_INSUFFICIENT_RESOURCES;
  535. }
  536. return status;
  537. }
  538. PVOID
  539. PipGetMappedAddress(
  540. IN INTERFACE_TYPE BusType,
  541. IN ULONG BusNumber,
  542. IN PHYSICAL_ADDRESS IoAddress,
  543. IN ULONG NumberOfBytes,
  544. IN ULONG AddressSpace,
  545. OUT PBOOLEAN MappedAddress
  546. )
  547. /*++
  548. Routine Description:
  549. This routine maps an IO address to system address space.
  550. Arguments:
  551. BusType - Supplies the type of bus - eisa, mca, isa...
  552. IoBusNumber - Supplies the bus number.
  553. IoAddress - Supplies the base device address to be mapped.
  554. NumberOfBytes - Supplies the number of bytes for which the address is
  555. valid.
  556. AddressSpace - Supplies whether the address is in io space or memory.
  557. MappedAddress - Supplies whether the address was mapped. This only has
  558. meaning if the address returned is non-null.
  559. Return Value:
  560. The mapped address.
  561. --*/
  562. {
  563. PHYSICAL_ADDRESS cardAddress;
  564. PVOID address;
  565. PAGED_CODE();
  566. HalTranslateBusAddress(BusType, BusNumber, IoAddress, &AddressSpace,
  567. &cardAddress);
  568. //
  569. // Map the device base address into the virtual address space
  570. // if the address is in memory space.
  571. //
  572. if (!AddressSpace) {
  573. address = MmMapIoSpace(cardAddress, NumberOfBytes, FALSE);
  574. *MappedAddress = (address ? TRUE : FALSE);
  575. } else {
  576. address = (PVOID) cardAddress.LowPart;
  577. *MappedAddress = FALSE;
  578. }
  579. return address;
  580. }
  581. VOID
  582. PipDecompressEisaId(
  583. IN ULONG CompressedId,
  584. IN PUCHAR EisaId
  585. )
  586. /*++
  587. Routine Description:
  588. This routine decompressed compressed Eisa Id and returns the Id to caller
  589. specified character buffer.
  590. Arguments:
  591. CompressedId - supplies the compressed Eisa Id.
  592. EisaId - supplies a 8-char buffer to receive the decompressed Eisa Id.
  593. Return Value:
  594. None.
  595. --*/
  596. {
  597. USHORT c1, c2;
  598. LONG i;
  599. PAGED_CODE();
  600. CompressedId &= 0xffffff7f; // remove the reserved bit (bit 7 of byte 0)
  601. c1 = c2 = (USHORT)CompressedId;
  602. c1 = (c1 & 0xff) << 8;
  603. c2 = (c2 & 0xff00) >> 8;
  604. c1 |= c2;
  605. for (i = 2; i >= 0; i--) {
  606. *(EisaId + i) = (UCHAR)(c1 & 0x1f) + 0x40;
  607. c1 >>= 5;
  608. }
  609. EisaId += 3;
  610. c1 = c2 = (USHORT)(CompressedId >> 16);
  611. c1 = (c1 & 0xff) << 8;
  612. c2 = (c2 & 0xff00) >> 8;
  613. c1 |= c2;
  614. sprintf (EisaId, "%04x", c1);
  615. }
  616. VOID
  617. PipLogError(
  618. IN NTSTATUS ErrorCode,
  619. IN ULONG UniqueErrorValue,
  620. IN NTSTATUS FinalStatus,
  621. IN PULONG DumpData,
  622. IN ULONG DumpCount,
  623. IN USHORT StringLength,
  624. IN PWCHAR String
  625. )
  626. /*++
  627. Routine Description:
  628. This routine contains common code to write an error log entry. It is
  629. called from other routines to avoid duplication of code. This routine
  630. only allows caller to supply one insertion string to the error log.
  631. Arguments:
  632. ErrorCode - The error code for the error log packet.
  633. UniqueErrorValue - The unique error value for the error log packet.
  634. FinalStatus - The final status of the operation for the error log packet.
  635. DumpData - Pointer to an array of dump data for the error log packet.
  636. DumpCount - The number of entries in the dump data array.
  637. StringLength - The length of insertion string *NOT* including the NULL terminater.
  638. String - The pointer to the insertion string
  639. Return Value:
  640. None.
  641. --*/
  642. {
  643. PIO_ERROR_LOG_PACKET errorLogEntry;
  644. ULONG i, size;
  645. PUCHAR p;
  646. size = sizeof(IO_ERROR_LOG_PACKET) + DumpCount * sizeof(ULONG) +
  647. StringLength + sizeof(UNICODE_NULL) - sizeof(ULONG);
  648. errorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry(
  649. PipDriverObject,
  650. (UCHAR) size
  651. );
  652. if (errorLogEntry != NULL) {
  653. RtlZeroMemory(errorLogEntry, size);
  654. errorLogEntry->ErrorCode = ErrorCode;
  655. errorLogEntry->DumpDataSize = (USHORT) (DumpCount * sizeof(ULONG));
  656. errorLogEntry->UniqueErrorValue = UniqueErrorValue;
  657. errorLogEntry->FinalStatus = FinalStatus;
  658. for (i = 0; i < DumpCount; i++)
  659. errorLogEntry->DumpData[i] = DumpData[i];
  660. if (String) {
  661. errorLogEntry->NumberOfStrings = 1;
  662. errorLogEntry->StringOffset = (USHORT)(sizeof(IO_ERROR_LOG_PACKET) +
  663. DumpCount * sizeof(ULONG) - sizeof(ULONG));
  664. p= (PUCHAR)errorLogEntry + errorLogEntry->StringOffset;
  665. RtlMoveMemory(p, String, StringLength);
  666. }
  667. IoWriteErrorLogEntry(errorLogEntry);
  668. }
  669. }
  670. NTSTATUS
  671. PipOpenCurrentHwProfileDeviceInstanceKey(
  672. OUT PHANDLE Handle,
  673. IN PUNICODE_STRING DeviceInstanceName,
  674. IN ACCESS_MASK DesiredAccess
  675. )
  676. /*++
  677. Routine Description:
  678. This routine sets the csconfig flags for the specified device
  679. which is specified by the instance number under ServiceKeyName\Enum.
  680. Arguments:
  681. ServiceKeyName - Supplies a pointer to the name of the subkey in the
  682. system service list (HKEY_LOCAL_MACHINE\CurrentControlSet\Services)
  683. that caused the driver to load. This is the RegistryPath parameter
  684. to the DriverEntry routine.
  685. Instance - Supplies the instance value under ServiceKeyName\Enum key
  686. DesiredAccess - Specifies the desired access that the caller needs to
  687. the key.
  688. Create - Determines if the key is to be created if it does not exist.
  689. Return Value:
  690. status
  691. --*/
  692. {
  693. NTSTATUS status;
  694. UNICODE_STRING unicodeString;
  695. HANDLE profileEnumHandle;
  696. //
  697. // See if we can open the device instance key of current hardware profile
  698. //
  699. RtlInitUnicodeString (
  700. &unicodeString,
  701. L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT\\SYSTEM\\CURRENTCONTROLSET\\ENUM"
  702. );
  703. status = PipOpenRegistryKey(&profileEnumHandle,
  704. NULL,
  705. &unicodeString,
  706. KEY_READ,
  707. FALSE
  708. );
  709. if (NT_SUCCESS(status)) {
  710. status = PipOpenRegistryKey(Handle,
  711. profileEnumHandle,
  712. DeviceInstanceName,
  713. DesiredAccess,
  714. FALSE
  715. );
  716. ZwClose(profileEnumHandle);
  717. }
  718. return status;
  719. }
  720. NTSTATUS
  721. PipGetDeviceInstanceCsConfigFlags(
  722. IN PUNICODE_STRING DeviceInstance,
  723. OUT PULONG CsConfigFlags
  724. )
  725. /*++
  726. Routine Description:
  727. This routine retrieves the csconfig flags for the specified device
  728. which is specified by the instance number under ServiceKeyName\Enum.
  729. Arguments:
  730. ServiceKeyName - Supplies a pointer to the name of the subkey in the
  731. system service list (HKEY_LOCAL_MACHINE\CurrentControlSet\Services)
  732. that caused the driver to load.
  733. // Instance - Supplies the instance value under ServiceKeyName\Enum key
  734. //
  735. CsConfigFlags - Supplies a variable to receive the device's CsConfigFlags
  736. Return Value:
  737. status
  738. --*/
  739. {
  740. NTSTATUS status;
  741. HANDLE handle;
  742. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  743. *CsConfigFlags = 0;
  744. status = PipOpenCurrentHwProfileDeviceInstanceKey(&handle,
  745. DeviceInstance,
  746. KEY_READ
  747. );
  748. if(NT_SUCCESS(status)) {
  749. status = PipGetRegistryValue(handle,
  750. L"CsConfigFlags",
  751. &keyValueInformation
  752. );
  753. if(NT_SUCCESS(status)) {
  754. if((keyValueInformation->Type == REG_DWORD) &&
  755. (keyValueInformation->DataLength >= sizeof(ULONG))) {
  756. *CsConfigFlags = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
  757. }
  758. ExFreePool(keyValueInformation);
  759. }
  760. ZwClose(handle);
  761. }
  762. return status;
  763. }
  764. ULONG
  765. PipDetermineResourceListSize(
  766. IN PCM_RESOURCE_LIST ResourceList
  767. )
  768. /*++
  769. Routine Description:
  770. This routine determines size of the passed in ResourceList
  771. structure.
  772. Arguments:
  773. Configuration1 - Supplies a pointer to the resource list.
  774. Return Value:
  775. size of the resource list structure.
  776. --*/
  777. {
  778. ULONG totalSize, listSize, descriptorSize, i, j;
  779. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceDesc;
  780. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor;
  781. if (!ResourceList) {
  782. totalSize = 0;
  783. } else {
  784. totalSize = FIELD_OFFSET(CM_RESOURCE_LIST, List);
  785. fullResourceDesc = &ResourceList->List[0];
  786. for (i = 0; i < ResourceList->Count; i++) {
  787. listSize = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR,
  788. PartialResourceList) +
  789. FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST,
  790. PartialDescriptors);
  791. partialDescriptor = &fullResourceDesc->PartialResourceList.PartialDescriptors[0];
  792. for (j = 0; j < fullResourceDesc->PartialResourceList.Count; j++) {
  793. descriptorSize = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  794. if (partialDescriptor->Type == CmResourceTypeDeviceSpecific) {
  795. descriptorSize += partialDescriptor->u.DeviceSpecificData.DataSize;
  796. }
  797. listSize += descriptorSize;
  798. partialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
  799. ((PUCHAR)partialDescriptor + descriptorSize);
  800. }
  801. totalSize += listSize;
  802. fullResourceDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)
  803. ((PUCHAR)fullResourceDesc + listSize);
  804. }
  805. }
  806. return totalSize;
  807. }
  808. NTSTATUS
  809. PipMapAddressAndCmdPort (
  810. IN PPI_BUS_EXTENSION BusExtension
  811. )
  812. {
  813. NTSTATUS status = STATUS_SUCCESS;
  814. ULONG dumpData[3];
  815. PHYSICAL_ADDRESS physicalAddress;
  816. //
  817. // Map port addr to memory addr if necessary.
  818. //
  819. if (PipAddressPort == NULL) {
  820. physicalAddress.LowPart = ADDRESS_PORT;
  821. physicalAddress.HighPart = 0;
  822. BusExtension->AddressPort =
  823. PipAddressPort = PipGetMappedAddress(
  824. Isa, // InterfaceType
  825. 0, // BusNumber,
  826. physicalAddress,
  827. 1,
  828. CM_RESOURCE_PORT_IO,
  829. &BusExtension->AddrPortMapped
  830. );
  831. if (PipAddressPort == NULL) {
  832. dumpData[0] = ADDRESS_PORT;
  833. dumpData[1] = 1;
  834. dumpData[2] = CM_RESOURCE_PORT_IO;
  835. PipLogError(PNPISA_REGISTER_NOT_MAPPED,
  836. PNPISA_ACQUIREPORTRESOURCE_1,
  837. STATUS_INSUFFICIENT_RESOURCES,
  838. dumpData,
  839. 3,
  840. 0,
  841. NULL
  842. );
  843. status = STATUS_UNSUCCESSFUL;
  844. }
  845. }
  846. if (PipCommandPort == NULL) {
  847. physicalAddress.LowPart = COMMAND_PORT;
  848. physicalAddress.HighPart = 0;
  849. BusExtension->CommandPort =
  850. PipCommandPort = PipGetMappedAddress(
  851. Isa, // InterfaceType
  852. 0, // BusNumber,
  853. physicalAddress,
  854. 1,
  855. CM_RESOURCE_PORT_IO,
  856. &BusExtension->CmdPortMapped
  857. );
  858. if (PipCommandPort == NULL) {
  859. dumpData[0] = COMMAND_PORT;
  860. dumpData[1] = 1;
  861. dumpData[2] = CM_RESOURCE_PORT_IO;
  862. PipLogError(PNPISA_REGISTER_NOT_MAPPED,
  863. PNPISA_ACQUIREPORTRESOURCE_2,
  864. STATUS_INSUFFICIENT_RESOURCES,
  865. dumpData,
  866. 3,
  867. 0,
  868. NULL
  869. );
  870. status = STATUS_UNSUCCESSFUL;
  871. }
  872. }
  873. return status;
  874. }
  875. VOID
  876. PipReleaseDeviceResources (
  877. PDEVICE_INFORMATION DeviceInfo
  878. )
  879. {
  880. UNICODE_STRING unicodeString;
  881. // This code is here rather than in the following conditional as
  882. // this best reflects how the code used to work before this code
  883. // was moved here from PDO stop/remove/surprise remove.
  884. if (DeviceInfo->LogConfHandle) {
  885. RtlInitUnicodeString(&unicodeString, L"AllocConfig");
  886. ZwDeleteValueKey (DeviceInfo->LogConfHandle, &unicodeString);
  887. }
  888. if (DeviceInfo->AllocatedResources) {
  889. ExFreePool (DeviceInfo->AllocatedResources);
  890. DeviceInfo->AllocatedResources=NULL;
  891. if (DeviceInfo->LogConfHandle) {
  892. // As it stands now it we will close the logconf handle if
  893. // the device gets removed, surprise removed, or stopped.
  894. // When we get started, we'll try to re-create the
  895. // AllocConfig value but fail because of the lack of the
  896. // logconf handle. This is not a change in behavior.
  897. //
  898. // The ZwDeleteKey() was definitely bogus though.
  899. ZwClose(DeviceInfo->LogConfHandle);
  900. DeviceInfo->LogConfHandle=NULL;
  901. }
  902. }
  903. }
  904. VOID
  905. PipReportStateChange(
  906. PNPISA_STATE State
  907. )
  908. {
  909. DebugPrint((DEBUG_STATE, "State transition: %d to %d\n",
  910. PipState, State));
  911. PipState = State;
  912. }
  913. ULONG
  914. PipGetCardFlags(
  915. PCARD_INFORMATION CardInfo
  916. )
  917. /*++
  918. Description:
  919. Look in the registry for any flags for this CardId
  920. Arguments:
  921. CardId First 4 bytes of ISAPNP config space
  922. Return Value:
  923. 32 bit flags value from registry or 0 if not found.
  924. --*/
  925. {
  926. HANDLE serviceHandle, paramHandle;
  927. NTSTATUS status;
  928. ULONG flags, returnedLength;
  929. UNICODE_STRING nameString;
  930. ANSI_STRING ansiString;
  931. WCHAR nameBuffer[9];
  932. UCHAR eisaId[8];
  933. const PWCHAR paramKey = L"Parameters";
  934. struct {
  935. KEY_VALUE_PARTIAL_INFORMATION Header;
  936. //
  937. // The header contains enough space for one UCHAR, pad
  938. // it out by a ULONG, this will ensure the structure
  939. // is large enough for at lease the ULONG we need.
  940. //
  941. // N.B. Natural alignment will get it out far enough that
  942. // this ULONG is 4 bytes to many.
  943. //
  944. ULONG Pad;
  945. } returnedData;
  946. status = PipOpenRegistryKey(&serviceHandle,
  947. NULL,
  948. &PipRegistryPath,
  949. KEY_READ,
  950. FALSE);
  951. if (!NT_SUCCESS(status)) {
  952. return 0;
  953. }
  954. RtlInitUnicodeString(&nameString, paramKey);
  955. status = PipOpenRegistryKey(&paramHandle,
  956. serviceHandle,
  957. &nameString,
  958. KEY_READ,
  959. FALSE);
  960. if (!NT_SUCCESS(status)) {
  961. ZwClose(serviceHandle);
  962. return 0;
  963. }
  964. PipDecompressEisaId(
  965. ((PSERIAL_IDENTIFIER) (CardInfo->CardData))->VenderId,
  966. eisaId
  967. );
  968. RtlInitAnsiString(&ansiString, eisaId);
  969. status = RtlAnsiStringToUnicodeString(&nameString, &ansiString, TRUE);
  970. if (!NT_SUCCESS(status)) {
  971. ZwClose(paramHandle);
  972. ZwClose(serviceHandle);
  973. return 0;
  974. }
  975. //
  976. // Get the "value" of this value.
  977. //
  978. status = ZwQueryValueKey(
  979. paramHandle,
  980. &nameString,
  981. KeyValuePartialInformation,
  982. &returnedData,
  983. sizeof(returnedData),
  984. &returnedLength
  985. );
  986. ZwClose(paramHandle);
  987. ZwClose(serviceHandle);
  988. if (NT_SUCCESS(status) && (returnedData.Header.Type == REG_DWORD) &&
  989. (returnedData.Header.DataLength == sizeof(ULONG))) {
  990. flags = *(PULONG)(returnedData.Header.Data);
  991. DebugPrint((DEBUG_WARN, "Retrieving card flags for %ws: %x\n",
  992. nameString.Buffer, flags));
  993. } else {
  994. flags = 0;
  995. }
  996. RtlFreeUnicodeString(&nameString);
  997. return flags;
  998. }
  999. NTSTATUS
  1000. PipBuildValueName(
  1001. IN PDEVICE_INFORMATION DeviceInfo,
  1002. IN PWSTR Suffix,
  1003. OUT PWSTR *ValuePath)
  1004. /*++
  1005. Description:
  1006. Builds a name describing the device via the device id and unique
  1007. id. Used to store per-device info in our parent's BiosConfig key
  1008. Arguments:
  1009. DeviceInfo Pointer to the PDO Extension for this device.
  1010. Suffix Suffix for value name
  1011. IrqFlags The edge or level setting of the boot config
  1012. Return Value:
  1013. Status
  1014. --*/
  1015. {
  1016. NTSTATUS status;
  1017. PWSTR DeviceId = NULL, Instance = NULL;
  1018. PWSTR Buffer, Current;
  1019. ULONG length;
  1020. status = PipQueryDeviceId(DeviceInfo, &DeviceId, 0);
  1021. if (!NT_SUCCESS(status)) {
  1022. goto cleanup;
  1023. }
  1024. status = PipQueryDeviceUniqueId(DeviceInfo, &Instance);
  1025. if (!NT_SUCCESS(status)) {
  1026. goto cleanup;
  1027. }
  1028. length = (wcslen(DeviceId) + wcslen(Instance) + wcslen(Suffix) + 1) * sizeof(WCHAR);
  1029. Buffer = ExAllocatePool(PagedPool, length);
  1030. if (Buffer == NULL) {
  1031. status = STATUS_INSUFFICIENT_RESOURCES;
  1032. goto cleanup;
  1033. }
  1034. wcscpy(Buffer, DeviceId);
  1035. wcscat(Buffer, Instance);
  1036. wcscat(Buffer, Suffix);
  1037. Current = Buffer;
  1038. while (*Current != UNICODE_NULL) {
  1039. if (*Current == L'\\') {
  1040. *Current = L'_';
  1041. }
  1042. Current++;
  1043. }
  1044. cleanup:
  1045. if (Instance) {
  1046. ExFreePool(Instance);
  1047. }
  1048. if (DeviceId) {
  1049. ExFreePool(DeviceId);
  1050. }
  1051. if (NT_SUCCESS(status)) {
  1052. *ValuePath = Buffer;
  1053. } else {
  1054. *ValuePath = NULL;
  1055. }
  1056. return status;
  1057. }
  1058. NTSTATUS
  1059. PipSaveBootResources(
  1060. IN PDEVICE_INFORMATION DeviceInfo
  1061. )
  1062. /*++
  1063. Description:
  1064. This saves the per-boot configuration of a device in the registry
  1065. Arguments:
  1066. DeviceInfo Pointer to the PDO Extension for this device.
  1067. Return Value:
  1068. Status
  1069. --*/
  1070. {
  1071. NTSTATUS status;
  1072. OBJECT_ATTRIBUTES attributes;
  1073. UNICODE_STRING unicodeString;
  1074. HANDLE deviceHandle, configHandle;
  1075. PWSTR Buffer = NULL;
  1076. ULONG Flags;
  1077. PAGED_CODE();
  1078. status = IoOpenDeviceRegistryKey(DeviceInfo->ParentDeviceExtension->PhysicalBusDevice,
  1079. PLUGPLAY_REGKEY_DEVICE,
  1080. KEY_ALL_ACCESS,
  1081. &deviceHandle
  1082. );
  1083. if (!NT_SUCCESS(status)) {
  1084. goto cleanup;
  1085. }
  1086. RtlInitUnicodeString(&unicodeString, BIOS_CONFIG_KEY_NAME);
  1087. InitializeObjectAttributes(&attributes,
  1088. &unicodeString,
  1089. OBJ_KERNEL_HANDLE,
  1090. deviceHandle,
  1091. NULL
  1092. );
  1093. status = ZwCreateKey(&configHandle,
  1094. KEY_ALL_ACCESS,
  1095. &attributes,
  1096. 0,
  1097. NULL,
  1098. REG_OPTION_VOLATILE,
  1099. NULL
  1100. );
  1101. ZwClose(deviceHandle);
  1102. if (!NT_SUCCESS(status)) {
  1103. goto cleanup;
  1104. }
  1105. status = PipBuildValueName(DeviceInfo, BOOTRESOURCES_VALUE_NAME,
  1106. &Buffer);
  1107. if (!NT_SUCCESS(status)) {
  1108. Buffer = NULL;
  1109. goto cleanup;
  1110. }
  1111. unicodeString.Buffer = Buffer;
  1112. unicodeString.Length = (wcslen(unicodeString.Buffer) + 1) * sizeof(WCHAR);
  1113. unicodeString.MaximumLength = unicodeString.Length;
  1114. status = ZwSetValueKey(configHandle,
  1115. &unicodeString,
  1116. 0,
  1117. REG_BINARY,
  1118. DeviceInfo->BootResources,
  1119. DeviceInfo->BootResourcesLength
  1120. );
  1121. ZwClose(configHandle);
  1122. cleanup:
  1123. if (Buffer != NULL) {
  1124. ExFreePool(Buffer);
  1125. }
  1126. return status;
  1127. }
  1128. NTSTATUS
  1129. PipSaveBootIrqFlags(
  1130. IN PDEVICE_INFORMATION DeviceInfo,
  1131. IN USHORT IrqFlags
  1132. )
  1133. /*++
  1134. Description:
  1135. This saves the per-boot irq configuration of a device in the registry
  1136. Arguments:
  1137. DeviceInfo Pointer to the PDO Extension for this device.
  1138. IrqFlags The edge or level setting of the boot config
  1139. Return Value:
  1140. Status
  1141. --*/
  1142. {
  1143. NTSTATUS status;
  1144. OBJECT_ATTRIBUTES attributes;
  1145. UNICODE_STRING unicodeString;
  1146. HANDLE deviceHandle, configHandle;
  1147. PWSTR Buffer = NULL;
  1148. ULONG Flags;
  1149. PAGED_CODE();
  1150. Flags = (ULONG) IrqFlags;
  1151. status = IoOpenDeviceRegistryKey(DeviceInfo->ParentDeviceExtension->PhysicalBusDevice,
  1152. PLUGPLAY_REGKEY_DEVICE,
  1153. KEY_ALL_ACCESS,
  1154. &deviceHandle
  1155. );
  1156. if (!NT_SUCCESS(status)) {
  1157. goto cleanup;
  1158. }
  1159. RtlInitUnicodeString(&unicodeString, BIOS_CONFIG_KEY_NAME);
  1160. InitializeObjectAttributes(&attributes,
  1161. &unicodeString,
  1162. OBJ_KERNEL_HANDLE,
  1163. deviceHandle,
  1164. NULL
  1165. );
  1166. status = ZwCreateKey(&configHandle,
  1167. KEY_ALL_ACCESS,
  1168. &attributes,
  1169. 0,
  1170. NULL,
  1171. REG_OPTION_VOLATILE,
  1172. NULL
  1173. );
  1174. ZwClose(deviceHandle);
  1175. if (!NT_SUCCESS(status)) {
  1176. goto cleanup;
  1177. }
  1178. status = PipBuildValueName(DeviceInfo, IRQFLAGS_VALUE_NAME, &Buffer);
  1179. if (!NT_SUCCESS(status)) {
  1180. Buffer = NULL;
  1181. goto cleanup;
  1182. }
  1183. unicodeString.Buffer = Buffer;
  1184. unicodeString.Length = (wcslen(unicodeString.Buffer) + 1) * sizeof(WCHAR);
  1185. unicodeString.MaximumLength = unicodeString.Length;
  1186. status = ZwSetValueKey(configHandle,
  1187. &unicodeString,
  1188. 0,
  1189. REG_DWORD,
  1190. &Flags,
  1191. sizeof(ULONG)
  1192. );
  1193. ZwClose(configHandle);
  1194. cleanup:
  1195. if (Buffer != NULL) {
  1196. ExFreePool(Buffer);
  1197. }
  1198. return status;
  1199. }
  1200. NTSTATUS
  1201. PipGetSavedBootResources(
  1202. IN PDEVICE_INFORMATION DeviceInfo,
  1203. OUT PCM_RESOURCE_LIST *BootResources
  1204. )
  1205. /*
  1206. Description:
  1207. This retrieves the saved boot resources
  1208. Arguments:
  1209. DeviceInfo Pointer to the PDO Extension for this device.
  1210. Return Value:
  1211. Status
  1212. --*/
  1213. {
  1214. UNICODE_STRING unicodeString;
  1215. NTSTATUS status;
  1216. OBJECT_ATTRIBUTES attributes;
  1217. HANDLE deviceHandle, configHandle;
  1218. PWSTR Buffer = NULL;
  1219. PKEY_VALUE_PARTIAL_INFORMATION info = NULL;
  1220. ULONG resultLength;
  1221. PAGED_CODE();
  1222. *BootResources = NULL;
  1223. status = IoOpenDeviceRegistryKey(DeviceInfo->ParentDeviceExtension->PhysicalBusDevice,
  1224. PLUGPLAY_REGKEY_DEVICE,
  1225. KEY_READ | KEY_WRITE,
  1226. &deviceHandle
  1227. );
  1228. if (!NT_SUCCESS(status)) {
  1229. goto cleanup;
  1230. }
  1231. RtlInitUnicodeString(&unicodeString, BIOS_CONFIG_KEY_NAME);
  1232. InitializeObjectAttributes(&attributes,
  1233. &unicodeString,
  1234. OBJ_KERNEL_HANDLE,
  1235. deviceHandle,
  1236. NULL
  1237. );
  1238. status = ZwOpenKey(&configHandle,
  1239. KEY_READ,
  1240. &attributes
  1241. );
  1242. ZwClose(deviceHandle);
  1243. if (!NT_SUCCESS(status)) {
  1244. goto cleanup;
  1245. }
  1246. status = PipBuildValueName(DeviceInfo, BOOTRESOURCES_VALUE_NAME, &Buffer);
  1247. if (!NT_SUCCESS(status)) {
  1248. ZwClose(configHandle);
  1249. Buffer = NULL;
  1250. goto cleanup;
  1251. }
  1252. unicodeString.Buffer = Buffer;
  1253. unicodeString.Length = (wcslen(unicodeString.Buffer) + 1) * sizeof(WCHAR);
  1254. unicodeString.MaximumLength = unicodeString.Length;
  1255. status = ZwQueryValueKey(configHandle,
  1256. &unicodeString,
  1257. KeyValuePartialInformation,
  1258. NULL,
  1259. 0,
  1260. &resultLength
  1261. );
  1262. if (status != STATUS_BUFFER_OVERFLOW &&
  1263. status != STATUS_BUFFER_TOO_SMALL) {
  1264. ZwClose(configHandle);
  1265. goto cleanup;
  1266. }
  1267. info = ExAllocatePool(PagedPool, resultLength);
  1268. if (info == NULL) {
  1269. ZwClose(configHandle);
  1270. status = STATUS_INSUFFICIENT_RESOURCES;
  1271. goto cleanup;
  1272. }
  1273. status = ZwQueryValueKey(configHandle,
  1274. &unicodeString,
  1275. KeyValuePartialInformation,
  1276. info,
  1277. resultLength,
  1278. &resultLength
  1279. );
  1280. ZwClose(configHandle);
  1281. if (!NT_SUCCESS(status)) {
  1282. DebugPrint((DEBUG_PNP, "Failed to get boot resources from registry for %ws\n", Buffer));
  1283. goto cleanup;
  1284. }
  1285. *BootResources = ExAllocatePool(PagedPool, info->DataLength);
  1286. if (BootResources) {
  1287. RtlCopyMemory(*BootResources, info->Data, info->DataLength);
  1288. DebugPrint((DEBUG_PNP, "Got boot resources from registry for %ws\n", Buffer));
  1289. } else {
  1290. status = STATUS_INSUFFICIENT_RESOURCES;
  1291. }
  1292. cleanup:
  1293. if (info != NULL) {
  1294. ExFreePool(info);
  1295. }
  1296. if (Buffer != NULL) {
  1297. ExFreePool(Buffer);
  1298. }
  1299. return status;
  1300. }
  1301. NTSTATUS
  1302. PipGetBootIrqFlags(
  1303. IN PDEVICE_INFORMATION DeviceInfo,
  1304. OUT PUSHORT IrqFlags
  1305. )
  1306. /*
  1307. Description:
  1308. This retrieves the per-boot irq configuration of a device from the registry
  1309. Arguments:
  1310. DeviceInfo Pointer to the PDO Extension for this device.
  1311. IrqFlags - flags we originally derived from the device's boot
  1312. config on this boot
  1313. Return Value:
  1314. Status
  1315. --*/
  1316. {
  1317. NTSTATUS status;
  1318. OBJECT_ATTRIBUTES attributes;
  1319. UNICODE_STRING unicodeString;
  1320. HANDLE deviceHandle, configHandle;
  1321. PWSTR Buffer = NULL;
  1322. CHAR returnBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG) - 1];
  1323. PKEY_VALUE_PARTIAL_INFORMATION info;
  1324. ULONG resultLength;
  1325. PAGED_CODE();
  1326. status = IoOpenDeviceRegistryKey(DeviceInfo->ParentDeviceExtension->PhysicalBusDevice,
  1327. PLUGPLAY_REGKEY_DEVICE,
  1328. KEY_READ | KEY_WRITE,
  1329. &deviceHandle
  1330. );
  1331. if (!NT_SUCCESS(status)) {
  1332. goto cleanup;
  1333. }
  1334. RtlInitUnicodeString(&unicodeString, BIOS_CONFIG_KEY_NAME);
  1335. InitializeObjectAttributes(&attributes,
  1336. &unicodeString,
  1337. OBJ_KERNEL_HANDLE,
  1338. deviceHandle,
  1339. NULL
  1340. );
  1341. status = ZwOpenKey(&configHandle,
  1342. KEY_READ,
  1343. &attributes
  1344. );
  1345. ZwClose(deviceHandle);
  1346. if (!NT_SUCCESS(status)) {
  1347. goto cleanup;
  1348. }
  1349. status = PipBuildValueName(DeviceInfo, IRQFLAGS_VALUE_NAME, &Buffer);
  1350. if (!NT_SUCCESS(status)) {
  1351. ZwClose(configHandle);
  1352. Buffer = NULL;
  1353. goto cleanup;
  1354. }
  1355. unicodeString.Buffer = Buffer;
  1356. unicodeString.Length = (wcslen(unicodeString.Buffer) + 1) * sizeof(WCHAR);
  1357. unicodeString.MaximumLength = unicodeString.Length;
  1358. status = ZwQueryValueKey(configHandle,
  1359. &unicodeString,
  1360. KeyValuePartialInformation,
  1361. &returnBuffer,
  1362. sizeof(returnBuffer),
  1363. &resultLength
  1364. );
  1365. ZwClose(configHandle);
  1366. if (NT_SUCCESS(status)) {
  1367. ULONG Temp;
  1368. info = (PKEY_VALUE_PARTIAL_INFORMATION) returnBuffer;
  1369. ASSERT(info->DataLength == sizeof(ULONG));
  1370. Temp = *((PULONG) info->Data);
  1371. ASSERT(!(Temp & 0xFFFF0000));
  1372. *IrqFlags = (USHORT) Temp;
  1373. DebugPrint((DEBUG_IRQ, "Got Irq Flags of %d for %ws\n",
  1374. (ULONG) *IrqFlags,
  1375. unicodeString.Buffer));
  1376. } else {
  1377. DebugPrint((DEBUG_IRQ, "Failed to get irq flags for %ws\n",
  1378. unicodeString.Buffer));
  1379. }
  1380. cleanup:
  1381. if (Buffer != NULL) {
  1382. ExFreePool(Buffer);
  1383. }
  1384. return status;
  1385. }
  1386. VOID
  1387. PipResetGlobals (
  1388. VOID
  1389. )
  1390. {
  1391. PipReadDataPort = PipCommandPort = PipAddressPort = NULL;
  1392. PipRDPNode = NULL;
  1393. }
  1394. #endif
  1395. NTSTATUS
  1396. PipOpenRegistryKey(
  1397. OUT PHANDLE Handle,
  1398. IN HANDLE BaseHandle OPTIONAL,
  1399. IN PUNICODE_STRING KeyName,
  1400. IN ACCESS_MASK DesiredAccess,
  1401. IN BOOLEAN Create
  1402. )
  1403. /*++
  1404. Routine Description:
  1405. Opens or creates a VOLATILE registry key using the name passed in based
  1406. at the BaseHandle node.
  1407. Arguments:
  1408. Handle - Pointer to the handle which will contain the registry key that
  1409. was opened.
  1410. BaseHandle - Handle to the base path from which the key must be opened.
  1411. KeyName - Name of the Key that must be opened/created.
  1412. DesiredAccess - Specifies the desired access that the caller needs to
  1413. the key.
  1414. Create - Determines if the key is to be created if it does not exist.
  1415. Return Value:
  1416. The function value is the final status of the operation.
  1417. --*/
  1418. {
  1419. OBJECT_ATTRIBUTES objectAttributes;
  1420. ULONG disposition;
  1421. PAGED_CODE();
  1422. //
  1423. // Initialize the object for the key.
  1424. //
  1425. InitializeObjectAttributes( &objectAttributes,
  1426. KeyName,
  1427. OBJ_CASE_INSENSITIVE,
  1428. BaseHandle,
  1429. (PSECURITY_DESCRIPTOR) NULL );
  1430. //
  1431. // Create the key or open it, as appropriate based on the caller's
  1432. // wishes.
  1433. //
  1434. if (Create) {
  1435. return ZwCreateKey( Handle,
  1436. DesiredAccess,
  1437. &objectAttributes,
  1438. 0,
  1439. (PUNICODE_STRING) NULL,
  1440. REG_OPTION_VOLATILE,
  1441. &disposition );
  1442. } else {
  1443. return ZwOpenKey( Handle,
  1444. DesiredAccess,
  1445. &objectAttributes );
  1446. }
  1447. }
  1448. NTSTATUS
  1449. PipGetRegistryValue(
  1450. IN HANDLE KeyHandle,
  1451. IN PWSTR ValueName,
  1452. OUT PKEY_VALUE_FULL_INFORMATION *Information
  1453. )
  1454. /*++
  1455. Routine Description:
  1456. This routine is invoked to retrieve the data for a registry key's value.
  1457. This is done by querying the value of the key with a zero-length buffer
  1458. to determine the size of the value, and then allocating a buffer and
  1459. actually querying the value into the buffer.
  1460. It is the responsibility of the caller to free the buffer.
  1461. Arguments:
  1462. KeyHandle - Supplies the key handle whose value is to be queried
  1463. ValueName - Supplies the null-terminated Unicode name of the value.
  1464. Information - Returns a pointer to the allocated data buffer.
  1465. Return Value:
  1466. The function value is the final status of the query operation.
  1467. --*/
  1468. {
  1469. UNICODE_STRING unicodeString;
  1470. NTSTATUS status;
  1471. PKEY_VALUE_FULL_INFORMATION infoBuffer;
  1472. ULONG keyValueLength;
  1473. PAGED_CODE();
  1474. *Information = NULL;
  1475. RtlInitUnicodeString( &unicodeString, ValueName );
  1476. //
  1477. // Figure out how big the data value is so that a buffer of the
  1478. // appropriate size can be allocated.
  1479. //
  1480. status = ZwQueryValueKey( KeyHandle,
  1481. &unicodeString,
  1482. KeyValueFullInformation,
  1483. (PVOID) NULL,
  1484. 0,
  1485. &keyValueLength );
  1486. if (status != STATUS_BUFFER_OVERFLOW &&
  1487. status != STATUS_BUFFER_TOO_SMALL) {
  1488. return status;
  1489. }
  1490. //
  1491. // Allocate a buffer large enough to contain the entire key data value.
  1492. //
  1493. infoBuffer = ExAllocatePool( NonPagedPool, keyValueLength );
  1494. if (!infoBuffer) {
  1495. return STATUS_INSUFFICIENT_RESOURCES;
  1496. }
  1497. //
  1498. // Query the data for the key value.
  1499. //
  1500. status = ZwQueryValueKey( KeyHandle,
  1501. &unicodeString,
  1502. KeyValueFullInformation,
  1503. infoBuffer,
  1504. keyValueLength,
  1505. &keyValueLength );
  1506. if (!NT_SUCCESS( status )) {
  1507. ExFreePool( infoBuffer );
  1508. return status;
  1509. }
  1510. //
  1511. // Everything worked, so simply return the address of the allocated
  1512. // buffer to the caller, who is now responsible for freeing it.
  1513. //
  1514. *Information = infoBuffer;
  1515. return STATUS_SUCCESS;
  1516. }
  1517. BOOLEAN
  1518. PiNeedDeferISABridge(
  1519. IN PDRIVER_OBJECT DriverObject,
  1520. IN PDEVICE_OBJECT DeviceObject
  1521. )
  1522. {
  1523. BOOLEAN defer=FALSE;
  1524. NTSTATUS status;
  1525. HANDLE hKey;
  1526. ULONG value;
  1527. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  1528. status = IoOpenDeviceRegistryKey (DeviceObject,PLUGPLAY_REGKEY_DEVICE,KEY_READ,&hKey);
  1529. if (NT_SUCCESS (status)) {
  1530. status = PipGetRegistryValue (hKey,&BRIDGE_CHECK_KEY,&keyValueInformation);
  1531. if (NT_SUCCESS (status)) {
  1532. if((keyValueInformation->Type == REG_DWORD) &&
  1533. (keyValueInformation->DataLength >= sizeof(ULONG))) {
  1534. value = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
  1535. //
  1536. // Assume that if the value !0 then the bridge is 'broken'
  1537. //
  1538. defer = (value == 0)?FALSE:TRUE;
  1539. }
  1540. }
  1541. ZwClose(hKey);
  1542. }
  1543. return defer;
  1544. }
  1545. #if DBG
  1546. VOID
  1547. PipDebugPrintContinue (
  1548. ULONG Level,
  1549. PCCHAR DebugMessage,
  1550. ...
  1551. )
  1552. /*++
  1553. Routine Description:
  1554. This routine displays debugging message or causes a break.
  1555. Arguments:
  1556. Level - supplies debugging levelcode. DEBUG_MESSAGE - displays message only.
  1557. DEBUG_BREAK - displays message and break.
  1558. DebugMessage - supplies a pointer to the debugging message.
  1559. Return Value:
  1560. None.
  1561. --*/
  1562. {
  1563. va_list ap;
  1564. va_start(ap, DebugMessage);
  1565. vDbgPrintEx(DPFLTR_ISAPNP_ID,
  1566. Level,
  1567. DebugMessage,
  1568. ap
  1569. );
  1570. if (Level & DEBUG_BREAK) {
  1571. DbgBreakPoint();
  1572. }
  1573. va_end(ap);
  1574. }
  1575. VOID
  1576. PipDebugPrint (
  1577. ULONG Level,
  1578. PCCHAR DebugMessage,
  1579. ...
  1580. )
  1581. /*++
  1582. Routine Description:
  1583. This routine displays debugging message or causes a break.
  1584. Arguments:
  1585. Level - supplies debugging levelcode. DEBUG_MESSAGE - displays message only.
  1586. DEBUG_BREAK - displays message and break.
  1587. DebugMessage - supplies a pointer to the debugging message.
  1588. Return Value:
  1589. None.
  1590. --*/
  1591. {
  1592. va_list ap;
  1593. va_start(ap, DebugMessage);
  1594. vDbgPrintExWithPrefix("ISAPNP: ",
  1595. DPFLTR_ISAPNP_ID,
  1596. Level,
  1597. DebugMessage,
  1598. ap
  1599. );
  1600. if (Level & DEBUG_BREAK) {
  1601. DbgBreakPoint();
  1602. }
  1603. va_end(ap);
  1604. }
  1605. #endif
  1606. VOID
  1607. PipDumpIoResourceDescriptor (
  1608. IN PUCHAR Indent,
  1609. IN PIO_RESOURCE_DESCRIPTOR Desc
  1610. )
  1611. /*++
  1612. Routine Description:
  1613. This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
  1614. Arguments:
  1615. Indent - # char of indentation.
  1616. Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
  1617. Return Value:
  1618. None.
  1619. --*/
  1620. {
  1621. UCHAR c = ' ';
  1622. if (Desc->Option == IO_RESOURCE_ALTERNATIVE) {
  1623. c = 'A';
  1624. } else if (Desc->Option == IO_RESOURCE_PREFERRED) {
  1625. c = 'P';
  1626. }
  1627. switch (Desc->Type) {
  1628. case CmResourceTypePort:
  1629. DebugPrint ((
  1630. DEBUG_RESOURCE,
  1631. "%sIO %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
  1632. Indent, c,
  1633. Desc->u.Port.MinimumAddress.HighPart, Desc->u.Port.MinimumAddress.LowPart,
  1634. Desc->u.Port.MaximumAddress.HighPart, Desc->u.Port.MaximumAddress.LowPart,
  1635. Desc->u.Port.Alignment,
  1636. Desc->u.Port.Length
  1637. ));
  1638. break;
  1639. case CmResourceTypeMemory:
  1640. DebugPrint ((
  1641. DEBUG_RESOURCE,
  1642. "%sMEM %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
  1643. Indent, c,
  1644. Desc->u.Memory.MinimumAddress.HighPart, Desc->u.Memory.MinimumAddress.LowPart,
  1645. Desc->u.Memory.MaximumAddress.HighPart, Desc->u.Memory.MaximumAddress.LowPart,
  1646. Desc->u.Memory.Alignment,
  1647. Desc->u.Memory.Length
  1648. ));
  1649. break;
  1650. case CmResourceTypeInterrupt:
  1651. DebugPrint ((
  1652. DEBUG_RESOURCE,
  1653. "%sINT %c Min: %x, Max: %x\n",
  1654. Indent, c,
  1655. Desc->u.Interrupt.MinimumVector,
  1656. Desc->u.Interrupt.MaximumVector
  1657. ));
  1658. break;
  1659. case CmResourceTypeDma:
  1660. DebugPrint ((
  1661. DEBUG_RESOURCE,
  1662. "%sDMA %c Min: %x, Max: %x\n",
  1663. Indent, c,
  1664. Desc->u.Dma.MinimumChannel,
  1665. Desc->u.Dma.MaximumChannel
  1666. ));
  1667. break;
  1668. }
  1669. }
  1670. VOID
  1671. PipDumpIoResourceList (
  1672. IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
  1673. )
  1674. /*++
  1675. Routine Description:
  1676. This routine displays Io resource requirements list.
  1677. Arguments:
  1678. IoList - supplies a pointer to the Io resource requirements list to be displayed.
  1679. Return Value:
  1680. None.
  1681. --*/
  1682. {
  1683. PIO_RESOURCE_LIST resList;
  1684. PIO_RESOURCE_DESCRIPTOR resDesc;
  1685. ULONG listCount, count, i, j;
  1686. if (IoList == NULL) {
  1687. return;
  1688. }
  1689. DebugPrint((DEBUG_RESOURCE,
  1690. "Pnp Bios IO Resource Requirements List for Slot %x -\n",
  1691. IoList->SlotNumber
  1692. ));
  1693. DebugPrint((DEBUG_RESOURCE,
  1694. " List Count = %x, Bus Number = %x\n",
  1695. IoList->AlternativeLists,
  1696. IoList->BusNumber
  1697. ));
  1698. listCount = IoList->AlternativeLists;
  1699. resList = &IoList->List[0];
  1700. for (i = 0; i < listCount; i++) {
  1701. DebugPrint((DEBUG_RESOURCE,
  1702. " Version = %x, Revision = %x, Desc count = %x\n",
  1703. resList->Version, resList->Revision, resList->Count
  1704. ));
  1705. resDesc = &resList->Descriptors[0];
  1706. count = resList->Count;
  1707. for (j = 0; j < count; j++) {
  1708. PipDumpIoResourceDescriptor(" ", resDesc);
  1709. resDesc++;
  1710. }
  1711. resList = (PIO_RESOURCE_LIST) resDesc;
  1712. }
  1713. }
  1714. VOID
  1715. PipDumpCmResourceDescriptor (
  1716. IN PUCHAR Indent,
  1717. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
  1718. )
  1719. /*++
  1720. Routine Description:
  1721. This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
  1722. Arguments:
  1723. Indent - # char of indentation.
  1724. Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
  1725. Return Value:
  1726. None.
  1727. --*/
  1728. {
  1729. switch (Desc->Type) {
  1730. case CmResourceTypePort:
  1731. DebugPrint ((
  1732. DEBUG_RESOURCE,
  1733. "%sIO Start: %x:%08x, Length: %x\n",
  1734. Indent,
  1735. Desc->u.Port.Start.HighPart, Desc->u.Port.Start.LowPart,
  1736. Desc->u.Port.Length
  1737. ));
  1738. break;
  1739. case CmResourceTypeMemory:
  1740. DebugPrint ((
  1741. DEBUG_RESOURCE,
  1742. "%sMEM Start: %x:%08x, Length: %x\n",
  1743. Indent,
  1744. Desc->u.Memory.Start.HighPart, Desc->u.Memory.Start.LowPart,
  1745. Desc->u.Memory.Length
  1746. ));
  1747. break;
  1748. case CmResourceTypeInterrupt:
  1749. DebugPrint ((
  1750. DEBUG_RESOURCE,
  1751. "%sINT Level: %x, Vector: %x, Affinity: %x\n",
  1752. Indent,
  1753. Desc->u.Interrupt.Level,
  1754. Desc->u.Interrupt.Vector,
  1755. Desc->u.Interrupt.Affinity
  1756. ));
  1757. break;
  1758. case CmResourceTypeDma:
  1759. DebugPrint ((
  1760. DEBUG_RESOURCE,
  1761. "%sDMA Channel: %x, Port: %x\n",
  1762. Indent,
  1763. Desc->u.Dma.Channel,
  1764. Desc->u.Dma.Port
  1765. ));
  1766. break;
  1767. }
  1768. }
  1769. VOID
  1770. PipDumpCmResourceList (
  1771. IN PCM_RESOURCE_LIST CmList
  1772. )
  1773. /*++
  1774. Routine Description:
  1775. This routine displays CM resource list.
  1776. Arguments:
  1777. CmList - supplies a pointer to CM resource list
  1778. Return Value:
  1779. None.
  1780. --*/
  1781. {
  1782. PCM_FULL_RESOURCE_DESCRIPTOR fullDesc;
  1783. PCM_PARTIAL_RESOURCE_LIST partialDesc;
  1784. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  1785. ULONG count, i;
  1786. if (CmList) {
  1787. fullDesc = &CmList->List[0];
  1788. DebugPrint((DEBUG_RESOURCE,
  1789. "Pnp Bios Cm Resource List -\n"
  1790. ));
  1791. DebugPrint((DEBUG_RESOURCE,
  1792. " List Count = %x, Bus Number = %x\n",
  1793. CmList->Count, fullDesc->BusNumber
  1794. ));
  1795. partialDesc = &fullDesc->PartialResourceList;
  1796. DebugPrint((DEBUG_RESOURCE,
  1797. " Version = %x, Revision = %x, Desc count = %x\n",
  1798. partialDesc->Version, partialDesc->Revision, partialDesc->Count
  1799. ));
  1800. count = partialDesc->Count;
  1801. desc = &partialDesc->PartialDescriptors[0];
  1802. for (i = 0; i < count; i++) {
  1803. PipDumpCmResourceDescriptor(" ", desc);
  1804. desc++;
  1805. }
  1806. }
  1807. }