Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1863 lines
61 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. devres.c
  5. Abstract:
  6. This module contains the high level device resources support routines.
  7. Author:
  8. Shie-Lin Tzong (shielint) July-27-1995
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "busp.h"
  14. #include "pnpisa.h"
  15. #include "pbios.h"
  16. #include "pnpcvrt.h"
  17. #if ISOLATE_CARDS
  18. #define IDBG 0
  19. PIO_RESOURCE_REQUIREMENTS_LIST
  20. PipCmResourcesToIoResources (
  21. IN PCM_RESOURCE_LIST CmResourceList
  22. );
  23. NTSTATUS
  24. PipMergeResourceRequirementsLists (
  25. IN PIO_RESOURCE_REQUIREMENTS_LIST IoList1,
  26. IN PIO_RESOURCE_REQUIREMENTS_LIST IoList2,
  27. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *MergedList
  28. );
  29. NTSTATUS
  30. PipBuildBootResourceRequirementsList (
  31. IN PIO_RESOURCE_REQUIREMENTS_LIST IoList,
  32. IN PCM_RESOURCE_LIST CmList,
  33. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *FilteredList,
  34. OUT PBOOLEAN ExactMatch
  35. );
  36. VOID
  37. PipMergeBootResourcesToRequirementsList(
  38. PDEVICE_INFORMATION DeviceInfo,
  39. PCM_RESOURCE_LIST BootResources,
  40. PIO_RESOURCE_REQUIREMENTS_LIST *IoResources
  41. );
  42. #pragma alloc_text(PAGE, PipGetCardIdentifier)
  43. #pragma alloc_text(PAGE, PipGetFunctionIdentifier)
  44. #pragma alloc_text(PAGE, PipGetCompatibleDeviceId)
  45. #pragma alloc_text(PAGE, PipQueryDeviceId)
  46. #pragma alloc_text(PAGE, PipQueryDeviceUniqueId)
  47. //#pragma alloc_text(PAGE, PipQueryDeviceResources)
  48. #pragma alloc_text(PAGE, PipQueryDeviceResourceRequirements)
  49. //#pragma alloc_text(PAGE, PipFilterResourceRequirementsList)
  50. #pragma alloc_text(PAGE, PipCmResourcesToIoResources)
  51. #pragma alloc_text(PAGE, PipMergeResourceRequirementsLists)
  52. #pragma alloc_text(PAGE, PipBuildBootResourceRequirementsList)
  53. #pragma alloc_text(PAGE, PipMergeBootResourcesToRequirementsList)
  54. //#pragma alloc_text(PAGE, PipSetDeviceResources)
  55. NTSTATUS
  56. PipGetCardIdentifier (
  57. PUCHAR CardData,
  58. PWCHAR *Buffer,
  59. PULONG BufferLength
  60. )
  61. /*++
  62. Routine Description:
  63. This function returns the identifier for a pnpisa card.
  64. Arguments:
  65. CardData - supplies a pointer to the pnp isa device data.
  66. Buffer - supplies a pointer to variable to receive a pointer to the Id.
  67. BufferLength - supplies a pointer to a variable to receive the size of the id buffer.
  68. Return Value:
  69. NTSTATUS code
  70. --*/
  71. {
  72. NTSTATUS status = STATUS_SUCCESS;
  73. UCHAR tag;
  74. LONG size, length;
  75. UNICODE_STRING unicodeString;
  76. ANSI_STRING ansiString;
  77. PCHAR ansiBuffer;
  78. *Buffer = NULL;
  79. *BufferLength = 0;
  80. if (CardData == NULL) {
  81. return status;
  82. }
  83. tag = *CardData;
  84. //
  85. // Make sure CardData does *NOT* point to a Logical Device Id tag
  86. //
  87. if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
  88. DbgPrint("PipGetCardIdentifier: CardData is at a Logical Id tag\n");
  89. return status;
  90. }
  91. //
  92. // Find the resource descriptor which describle identifier string
  93. //
  94. do {
  95. //
  96. // Do we find the identifer resource tag?
  97. //
  98. if (tag == TAG_ANSI_ID) {
  99. CardData++;
  100. length = *(USHORT UNALIGNED *)CardData;
  101. CardData += 2;
  102. ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1);
  103. if (ansiBuffer == NULL) {
  104. status = STATUS_INSUFFICIENT_RESOURCES;
  105. break;
  106. }
  107. RtlMoveMemory(ansiBuffer, CardData, length);
  108. ansiBuffer[length] = 0;
  109. RtlInitAnsiString(&ansiString, ansiBuffer);
  110. status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
  111. ExFreePool(ansiBuffer);
  112. if (!NT_SUCCESS(status)) {
  113. status = STATUS_INSUFFICIENT_RESOURCES;
  114. break;
  115. }
  116. *Buffer = unicodeString.Buffer;
  117. *BufferLength = unicodeString.Length + sizeof(WCHAR);
  118. break;
  119. }
  120. //
  121. // Determine the size of the BIOS resource descriptor and
  122. // advance to next resource descriptor.
  123. //
  124. if (!(tag & LARGE_RESOURCE_TAG)) {
  125. size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
  126. size += 1; // length of small tag
  127. } else {
  128. size = *(USHORT UNALIGNED *)(CardData + 1);
  129. size += 3; // length of large tag
  130. }
  131. CardData += size;
  132. tag = *CardData;
  133. } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
  134. return status;
  135. }
  136. NTSTATUS
  137. PipGetFunctionIdentifier (
  138. PUCHAR DeviceData,
  139. PWCHAR *Buffer,
  140. PULONG BufferLength
  141. )
  142. /*++
  143. Routine Description:
  144. This function returns the desired pnp isa identifier for the specified
  145. DeviceData/LogicalFunction. The Identifier for a logical function is
  146. optional. If no Identifier available , Buffer is set to NULL.
  147. Arguments:
  148. DeviceData - supplies a pointer to the pnp isa device data.
  149. Buffer - supplies a pointer to variable to receive a pointer to the Id.
  150. BufferLength - supplies a pointer to a variable to receive the size of the id buffer.
  151. Return Value:
  152. NTSTATUS code
  153. --*/
  154. {
  155. NTSTATUS status = STATUS_SUCCESS;
  156. UCHAR tag;
  157. LONG size, length;
  158. UNICODE_STRING unicodeString;
  159. ANSI_STRING ansiString;
  160. PCHAR ansiBuffer;
  161. *Buffer = NULL;
  162. *BufferLength = 0;
  163. if (DeviceData==NULL) {
  164. return status;
  165. }
  166. tag = *DeviceData;
  167. #if DBG
  168. //
  169. // Make sure device data points to Logical Device Id tag
  170. //
  171. if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
  172. DbgPrint("PipGetFunctionIdentifier: DeviceData is not at a Logical Id tag\n");
  173. }
  174. #endif
  175. //
  176. // Skip all the resource descriptors to find compatible Id descriptor
  177. //
  178. do {
  179. //
  180. // Determine the size of the BIOS resource descriptor and
  181. // advance to next resource descriptor.
  182. //
  183. if (!(tag & LARGE_RESOURCE_TAG)) {
  184. size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
  185. size += 1; // length of small tag
  186. } else {
  187. size = *(USHORT UNALIGNED *)(DeviceData + 1);
  188. size += 3; // length of large tag
  189. }
  190. DeviceData += size;
  191. tag = *DeviceData;
  192. //
  193. // Do we find the identifer resource tag?
  194. //
  195. if (tag == TAG_ANSI_ID) {
  196. DeviceData++;
  197. length = *(USHORT UNALIGNED *)DeviceData;
  198. DeviceData += 2;
  199. ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1);
  200. if (ansiBuffer == NULL) {
  201. status = STATUS_INSUFFICIENT_RESOURCES;
  202. break;
  203. }
  204. RtlMoveMemory(ansiBuffer, DeviceData, length);
  205. ansiBuffer[length] = 0;
  206. RtlInitAnsiString(&ansiString, ansiBuffer);
  207. status = RtlAnsiStringToUnicodeString(&unicodeString,
  208. &ansiString,
  209. TRUE);
  210. ExFreePool(ansiBuffer);
  211. if (!NT_SUCCESS(status)) {
  212. status = STATUS_INSUFFICIENT_RESOURCES;
  213. break;
  214. }
  215. *Buffer = unicodeString.Buffer;
  216. *BufferLength = unicodeString.Length + sizeof(WCHAR);
  217. break;
  218. }
  219. } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
  220. return status;
  221. }
  222. NTSTATUS
  223. PipGetCompatibleDeviceId (
  224. IN PUCHAR DeviceData,
  225. IN ULONG IdIndex,
  226. OUT PWCHAR *Buffer,
  227. OUT PULONG BufferSize
  228. )
  229. /*++
  230. Routine Description:
  231. This function returns the desired pnp isa id for the specified DeviceData
  232. and Id index. If Id index = 0, the Hardware ID will be return; if id
  233. index = n, the Nth compatible id will be returned.
  234. Arguments:
  235. DeviceData - supplies a pointer to the pnp isa device data.
  236. IdIndex - supplies the index of the compatible id desired.
  237. Buffer - supplies a pointer to variable to receive a pointer to the compatible Id.
  238. BufferSize - the length of the pointer allocated and returned to the caller in *Buffer.
  239. Return Value:
  240. NTSTATUS code
  241. --*/
  242. {
  243. NTSTATUS status = STATUS_NO_MORE_ENTRIES;
  244. UCHAR tag;
  245. ULONG count = 0,length;
  246. LONG size;
  247. UNICODE_STRING unicodeString;
  248. WCHAR eisaId[8];
  249. ULONG id;
  250. ULONG bufferSize;
  251. //
  252. // Bail out BEFORE we touch the device data for the RDP
  253. //
  254. if (IdIndex == -1) {
  255. length = 2* sizeof(WCHAR);
  256. *Buffer = (PWCHAR) ExAllocatePool(PagedPool, length);
  257. if (*Buffer) {
  258. *BufferSize = length;
  259. RtlZeroMemory (*Buffer,length);
  260. }else {
  261. return STATUS_INSUFFICIENT_RESOURCES;
  262. }
  263. return STATUS_SUCCESS;
  264. }
  265. tag = *DeviceData;
  266. #if DBG
  267. //
  268. // Make sure device data points to Logical Device Id tag
  269. //
  270. if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
  271. DbgPrint("PipGetCompatibleDeviceId: DeviceData is not at Logical Id tag\n");
  272. }
  273. #endif
  274. if (IdIndex == 0) {
  275. //
  276. // Caller is asking for hardware id
  277. //
  278. DeviceData++; // Skip tag
  279. id = *(ULONG UNALIGNED *)DeviceData;
  280. status = STATUS_SUCCESS;
  281. } else {
  282. //
  283. // caller is asking for compatible id
  284. //
  285. IdIndex--;
  286. //
  287. // Skip all the resource descriptors to find compatible Id descriptor
  288. //
  289. do {
  290. //
  291. // Determine the size of the BIOS resource descriptor and
  292. // advance to next resource descriptor.
  293. //
  294. if (!(tag & LARGE_RESOURCE_TAG)) {
  295. size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
  296. size += 1; // length of small tag
  297. } else {
  298. size = *(USHORT UNALIGNED *)(DeviceData + 1);
  299. size += 3; // length of large tag
  300. }
  301. DeviceData += size;
  302. tag = *DeviceData;
  303. //
  304. // Do we reach the compatible ID descriptor?
  305. //
  306. if ((tag & SMALL_TAG_MASK) == TAG_COMPATIBLE_ID) {
  307. if (count == IdIndex) {
  308. id = *(ULONG UNALIGNED *)(DeviceData + 1);
  309. status = STATUS_SUCCESS;
  310. break;
  311. } else {
  312. count++;
  313. }
  314. }
  315. } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
  316. }
  317. if (NT_SUCCESS(status)) {
  318. PipDecompressEisaId(id, eisaId);
  319. RtlInitUnicodeString(&unicodeString, eisaId);
  320. bufferSize = sizeof(L"*") + sizeof(WCHAR) + unicodeString.Length;
  321. *Buffer = (PWCHAR)ExAllocatePool (
  322. PagedPool,
  323. bufferSize
  324. );
  325. if (*Buffer) {
  326. if (FAILED(StringCbPrintf(*Buffer,
  327. bufferSize,
  328. L"*%s",
  329. unicodeString.Buffer
  330. ))) {
  331. ASSERT(FALSE);
  332. status = STATUS_INVALID_PARAMETER;
  333. } else {
  334. *BufferSize = bufferSize;
  335. }
  336. } else {
  337. status = STATUS_INSUFFICIENT_RESOURCES;
  338. }
  339. }
  340. return status;
  341. }
  342. NTSTATUS
  343. PipQueryDeviceUniqueId (
  344. IN PDEVICE_INFORMATION DeviceInfo,
  345. OUT PWCHAR *DeviceId,
  346. OUT PULONG DeviceIdLength
  347. )
  348. /*++
  349. Routine Description:
  350. This function returns the unique id for the particular device.
  351. Arguments:
  352. DeviceData - Device data information for the specificied device.
  353. DeviceId - supplies a pointer to a variable to receive device id.
  354. DeviceIdLength - On success, will contain the length of the buffer
  355. allocated and returned to the caller in *DeviceId
  356. Return Value:
  357. NTSTATUS code.
  358. --*/
  359. {
  360. NTSTATUS status = STATUS_SUCCESS;
  361. ULONG size;
  362. //
  363. // Set up device's unique id.
  364. // device unique id = SerialNumber of the card
  365. //
  366. size = (8 + 1) * sizeof(WCHAR); // serial number + null
  367. *DeviceId = (PWCHAR)ExAllocatePool (
  368. PagedPool,
  369. size
  370. );
  371. if (*DeviceId) {
  372. if (DeviceInfo->Flags & DF_READ_DATA_PORT) {
  373. //
  374. // Override the unique ID for the RDP
  375. //
  376. StringCbPrintf(*DeviceId,
  377. size,
  378. L"0"
  379. );
  380. } else {
  381. StringCbPrintf (*DeviceId,
  382. size,
  383. L"%01X",
  384. ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->SerialNumber
  385. );
  386. }
  387. *DeviceIdLength = size;
  388. #if IDBG
  389. {
  390. ANSI_STRING ansiString;
  391. UNICODE_STRING unicodeString;
  392. RtlInitUnicodeString(&unicodeString, *DeviceId);
  393. if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE))) {
  394. DbgPrint("PnpIsa: return Unique Id = %s\n", ansiString.Buffer);
  395. RtlFreeAnsiString(&ansiString);
  396. }
  397. }
  398. #endif
  399. } else {
  400. status = STATUS_INSUFFICIENT_RESOURCES;
  401. }
  402. return status;
  403. }
  404. NTSTATUS
  405. PipQueryDeviceId (
  406. IN PDEVICE_INFORMATION DeviceInfo,
  407. OUT PWCHAR *DeviceId,
  408. OUT PULONG DeviceIdLength,
  409. IN ULONG IdIndex
  410. )
  411. /*++
  412. Routine Description:
  413. This function returns the device id for the particular device.
  414. Arguments:
  415. DeviceInfo - Device information for the specificied device.
  416. DeviceId - supplies a pointer to a variable to receive the device id.
  417. DeviceIdLength - On success, will contain the length of the buffer
  418. allocated and returned to the caller in *DeviceId
  419. IdIndex - specifies device id or compatible id (0 - device id)
  420. Return Value:
  421. NTSTATUS code.
  422. --*/
  423. {
  424. NTSTATUS status = STATUS_SUCCESS;
  425. PWSTR format;
  426. ULONG size,length;
  427. WCHAR eisaId[8];
  428. UNICODE_STRING unicodeString;
  429. //
  430. // Bail out BEFORE we touch the device data for the RDP
  431. //
  432. if (DeviceInfo->Flags & DF_READ_DATA_PORT) {
  433. length = (sizeof (wReadDataPort)+
  434. + sizeof(WCHAR) +sizeof (L"ISAPNP\\"));
  435. *DeviceId = (PWCHAR) ExAllocatePool(PagedPool, length);
  436. if (*DeviceId) {
  437. *DeviceIdLength = length;
  438. StringCbPrintf(*DeviceId,
  439. length,
  440. L"ISAPNP\\%s",
  441. wReadDataPort
  442. );
  443. } else {
  444. return STATUS_INSUFFICIENT_RESOURCES;
  445. }
  446. return STATUS_SUCCESS;
  447. }
  448. //
  449. // Set up device's id.
  450. // device id = VenderId + Logical device number
  451. //
  452. if (DeviceInfo->CardInformation->NumberLogicalDevices == 1) {
  453. format = L"ISAPNP\\%s";
  454. size = sizeof(L"ISAPNP\\*") + sizeof(WCHAR);
  455. } else {
  456. format = L"ISAPNP\\%s_DEV%04X";
  457. size = sizeof(L"ISAPNP\\_DEV") + 4 * sizeof(WCHAR) + sizeof(WCHAR);
  458. }
  459. PipDecompressEisaId(
  460. ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->VenderId,
  461. eisaId
  462. );
  463. RtlInitUnicodeString(&unicodeString, eisaId);
  464. size += unicodeString.Length;
  465. *DeviceId = (PWCHAR)ExAllocatePool (PagedPool, size);
  466. if (*DeviceId) {
  467. *DeviceIdLength = size;
  468. StringCbPrintf(*DeviceId,
  469. size,
  470. format,
  471. unicodeString.Buffer,
  472. DeviceInfo->LogicalDeviceNumber
  473. );
  474. #if IDBG
  475. {
  476. ANSI_STRING dbgAnsiString;
  477. UNICODE_STRING dbgUnicodeString;
  478. RtlInitUnicodeString(&dbgUnicodeString, *DeviceId);
  479. if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&dbgAnsiString, &dbgUnicodeString, TRUE))) {
  480. DbgPrint("PnpIsa: return device Id = %s\n", dbgAnsiString.Buffer);
  481. RtlFreeAnsiString(&dbgAnsiString);
  482. }
  483. }
  484. #endif
  485. } else {
  486. status = STATUS_INSUFFICIENT_RESOURCES;
  487. }
  488. return status;
  489. }
  490. NTSTATUS
  491. PipQueryDeviceResources (
  492. PDEVICE_INFORMATION DeviceInfo,
  493. ULONG BusNumber,
  494. PCM_RESOURCE_LIST *CmResources,
  495. ULONG *Size
  496. )
  497. /*++
  498. Routine Description:
  499. This function returns the bus resources being used by the specified device
  500. Arguments:
  501. DeviceInfo - Device information for the specificied slot
  502. BusNumber - should always be 0
  503. CmResources - supplies a pointer to a variable to receive the device resource
  504. data.
  505. Size - Supplies a pointer to avariable to receive the size of device resource
  506. data.
  507. Return Value:
  508. NTSTATUS code.
  509. --*/
  510. {
  511. ULONG length;
  512. NTSTATUS status = STATUS_SUCCESS;
  513. PCM_RESOURCE_LIST cmResources;
  514. *CmResources = NULL;
  515. *Size = 0;
  516. if (DeviceInfo->BootResources){ // && DeviceInfo->LogConfHandle) {
  517. *CmResources = ExAllocatePool(PagedPool, DeviceInfo->BootResourcesLength);
  518. if (*CmResources) {
  519. RtlMoveMemory(*CmResources, DeviceInfo->BootResources, DeviceInfo->BootResourcesLength);
  520. *Size = DeviceInfo->BootResourcesLength;
  521. } else {
  522. status = STATUS_INSUFFICIENT_RESOURCES;
  523. }
  524. }
  525. return status;
  526. }
  527. NTSTATUS
  528. PipQueryDeviceResourceRequirements (
  529. PDEVICE_INFORMATION DeviceInfo,
  530. ULONG BusNumber,
  531. ULONG Slot,
  532. PCM_RESOURCE_LIST BootResources,
  533. USHORT IrqFlags,
  534. PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
  535. ULONG *Size
  536. )
  537. /*++
  538. Routine Description:
  539. This function returns the possible bus resources that this device may be
  540. satisfied with.
  541. Arguments:
  542. DeviceData - Device data information for the specificied slot
  543. BusNumber - Supplies the bus number
  544. Slot - supplies the slot number of the BusNumber
  545. IoResources - supplies a pointer to a variable to receive the IO resource
  546. requirements list
  547. Return Value:
  548. The device control is completed
  549. --*/
  550. {
  551. ULONG length = 0;
  552. NTSTATUS status;
  553. PUCHAR deviceData;
  554. PIO_RESOURCE_REQUIREMENTS_LIST ioResources;
  555. deviceData = DeviceInfo->DeviceData;
  556. status = PpBiosResourcesToNtResources (
  557. BusNumber,
  558. Slot,
  559. &deviceData,
  560. 0,
  561. &ioResources,
  562. &length
  563. );
  564. //
  565. // Return results
  566. //
  567. if (NT_SUCCESS(status)) {
  568. if (length == 0) {
  569. ioResources = NULL; // Just to make sure
  570. } else {
  571. // * Set the irq level/edge requirements to be consistent
  572. // with the our determination earlier as to what is
  573. // likely to work for this card
  574. //
  575. // * Make requirements reflect boot configed ROM if any.
  576. //
  577. // Make these changes across all alternatives.
  578. PipTrimResourceRequirements(&ioResources,
  579. IrqFlags,
  580. BootResources);
  581. //PipFilterResourceRequirementsList(&ioResources);
  582. PipMergeBootResourcesToRequirementsList(DeviceInfo,
  583. BootResources,
  584. &ioResources
  585. );
  586. ASSERT(ioResources);
  587. length = ioResources->ListSize;
  588. }
  589. *IoResources = ioResources;
  590. *Size = length;
  591. #if IDBG
  592. PipDumpIoResourceList(ioResources);
  593. #endif
  594. }
  595. return status;
  596. }
  597. NTSTATUS
  598. PipSetDeviceResources (
  599. PDEVICE_INFORMATION DeviceInfo,
  600. PCM_RESOURCE_LIST CmResources
  601. )
  602. /*++
  603. Routine Description:
  604. This function configures the device to the specified device setttings
  605. Arguments:
  606. DeviceInfo - Device information for the specificied slot
  607. CmResources - pointer to the desired resource list
  608. Return Value:
  609. NTSTATUS code.
  610. --*/
  611. {
  612. NTSTATUS status = STATUS_SUCCESS;
  613. if (CmResources && (CmResources->Count != 0)) {
  614. //
  615. // Set resource settings for the device
  616. //
  617. status = PipWriteDeviceResources (
  618. DeviceInfo->DeviceData,
  619. (PCM_RESOURCE_LIST) CmResources
  620. );
  621. //
  622. // Put all cards into wait for key state.
  623. //
  624. DebugPrint((DEBUG_STATE,
  625. "SetDeviceResources CSN %d/LDN %d\n",
  626. DeviceInfo->CardInformation->CardSelectNumber,
  627. DeviceInfo->LogicalDeviceNumber));
  628. //
  629. // Delay some time for the newly set resources to be avaiable.
  630. // This is required on some slow machines.
  631. //
  632. KeStallExecutionProcessor(10000); // delay 10 ms
  633. }
  634. return status;
  635. }
  636. PIO_RESOURCE_REQUIREMENTS_LIST
  637. PipCmResourcesToIoResources (
  638. IN PCM_RESOURCE_LIST CmResourceList
  639. )
  640. /*++
  641. Routine Description:
  642. This routines converts the input CmResourceList to IO_RESOURCE_REQUIREMENTS_LIST.
  643. Arguments:
  644. CmResourceList - the cm resource list to convert.
  645. Return Value:
  646. returns a IO_RESOURCE_REQUIREMENTS_LISTST if succeeds. Otherwise a NULL value is
  647. returned.
  648. --*/
  649. {
  650. PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
  651. ULONG count = 0, size, i, j;
  652. PCM_FULL_RESOURCE_DESCRIPTOR cmFullDesc;
  653. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartDesc;
  654. PIO_RESOURCE_DESCRIPTOR ioDesc;
  655. //
  656. // First determine number of descriptors required.
  657. //
  658. cmFullDesc = &CmResourceList->List[0];
  659. for (i = 0; i < CmResourceList->Count; i++) {
  660. count += cmFullDesc->PartialResourceList.Count;
  661. cmPartDesc = &cmFullDesc->PartialResourceList.PartialDescriptors[0];
  662. for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) {
  663. size = 0;
  664. switch (cmPartDesc->Type) {
  665. case CmResourceTypeDeviceSpecific:
  666. size = cmPartDesc->u.DeviceSpecificData.DataSize;
  667. count--;
  668. break;
  669. }
  670. cmPartDesc++;
  671. cmPartDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmPartDesc + size);
  672. }
  673. cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmPartDesc;
  674. }
  675. if (count == 0) {
  676. return NULL;
  677. }
  678. //
  679. // Count the extra descriptors for InterfaceType and BusNumber information.
  680. //
  681. count += CmResourceList->Count - 1;
  682. //
  683. // Allocate heap space for IO RESOURCE REQUIREMENTS LIST
  684. //
  685. count++; // add one for CmResourceTypeConfigData
  686. ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(
  687. PagedPool,
  688. sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
  689. count * sizeof(IO_RESOURCE_DESCRIPTOR)
  690. );
  691. if (!ioResReqList) {
  692. return NULL;
  693. }
  694. //
  695. // Parse the cm resource descriptor and build its corresponding IO resource descriptor
  696. //
  697. ioResReqList->InterfaceType = CmResourceList->List[0].InterfaceType;
  698. ioResReqList->BusNumber = CmResourceList->List[0].BusNumber;
  699. ioResReqList->SlotNumber = 0;
  700. ioResReqList->Reserved[0] = 0;
  701. ioResReqList->Reserved[1] = 0;
  702. ioResReqList->Reserved[2] = 0;
  703. ioResReqList->AlternativeLists = 1;
  704. ioResReqList->List[0].Version = 1;
  705. ioResReqList->List[0].Revision = 1;
  706. ioResReqList->List[0].Count = count;
  707. //
  708. // Generate a CmResourceTypeConfigData descriptor
  709. //
  710. ioDesc = &ioResReqList->List[0].Descriptors[0];
  711. ioDesc->Option = IO_RESOURCE_PREFERRED;
  712. ioDesc->Type = CmResourceTypeConfigData;
  713. ioDesc->ShareDisposition = CmResourceShareShared;
  714. ioDesc->Flags = 0;
  715. ioDesc->Spare1 = 0;
  716. ioDesc->Spare2 = 0;
  717. ioDesc->u.ConfigData.Priority = BOOT_CONFIG_PRIORITY;
  718. ioDesc++;
  719. cmFullDesc = &CmResourceList->List[0];
  720. for (i = 0; i < CmResourceList->Count; i++) {
  721. cmPartDesc = &cmFullDesc->PartialResourceList.PartialDescriptors[0];
  722. for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) {
  723. ioDesc->Option = IO_RESOURCE_PREFERRED;
  724. ioDesc->Type = cmPartDesc->Type;
  725. ioDesc->ShareDisposition = cmPartDesc->ShareDisposition;
  726. ioDesc->Flags = cmPartDesc->Flags;
  727. ioDesc->Spare1 = 0;
  728. ioDesc->Spare2 = 0;
  729. size = 0;
  730. switch (cmPartDesc->Type) {
  731. case CmResourceTypePort:
  732. ioDesc->u.Port.MinimumAddress = cmPartDesc->u.Port.Start;
  733. ioDesc->u.Port.MaximumAddress.QuadPart = cmPartDesc->u.Port.Start.QuadPart +
  734. cmPartDesc->u.Port.Length - 1;
  735. ioDesc->u.Port.Alignment = 1;
  736. ioDesc->u.Port.Length = cmPartDesc->u.Port.Length;
  737. ioDesc++;
  738. break;
  739. case CmResourceTypeInterrupt:
  740. #if defined(_X86_)
  741. ioDesc->u.Interrupt.MinimumVector = ioDesc->u.Interrupt.MaximumVector =
  742. cmPartDesc->u.Interrupt.Level;
  743. #else
  744. ioDesc->u.Interrupt.MinimumVector = ioDesc->u.Interrupt.MaximumVector =
  745. cmPartDesc->u.Interrupt.Vector;
  746. #endif
  747. ioDesc++;
  748. break;
  749. case CmResourceTypeMemory:
  750. ioDesc->u.Memory.MinimumAddress = cmPartDesc->u.Memory.Start;
  751. ioDesc->u.Memory.MaximumAddress.QuadPart = cmPartDesc->u.Memory.Start.QuadPart +
  752. cmPartDesc->u.Memory.Length - 1;
  753. ioDesc->u.Memory.Alignment = 1;
  754. ioDesc->u.Memory.Length = cmPartDesc->u.Memory.Length;
  755. ioDesc++;
  756. break;
  757. case CmResourceTypeDma:
  758. ioDesc->u.Dma.MinimumChannel = cmPartDesc->u.Dma.Channel;
  759. ioDesc->u.Dma.MaximumChannel = cmPartDesc->u.Dma.Channel;
  760. ioDesc++;
  761. break;
  762. case CmResourceTypeDeviceSpecific:
  763. size = cmPartDesc->u.DeviceSpecificData.DataSize;
  764. break;
  765. case CmResourceTypeBusNumber:
  766. ioDesc->u.BusNumber.MinBusNumber = cmPartDesc->u.BusNumber.Start;
  767. ioDesc->u.BusNumber.MaxBusNumber = cmPartDesc->u.BusNumber.Start +
  768. cmPartDesc->u.BusNumber.Length - 1;
  769. ioDesc->u.BusNumber.Length = cmPartDesc->u.BusNumber.Length;
  770. ioDesc++;
  771. break;
  772. default:
  773. ioDesc->u.DevicePrivate.Data[0] = cmPartDesc->u.DevicePrivate.Data[0];
  774. ioDesc->u.DevicePrivate.Data[1] = cmPartDesc->u.DevicePrivate.Data[1];
  775. ioDesc->u.DevicePrivate.Data[2] = cmPartDesc->u.DevicePrivate.Data[2];
  776. ioDesc++;
  777. break;
  778. }
  779. cmPartDesc++;
  780. cmPartDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmPartDesc + size);
  781. }
  782. cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmPartDesc;
  783. }
  784. ioResReqList->ListSize = (ULONG)((ULONG_PTR)ioDesc - (ULONG_PTR)ioResReqList);
  785. return ioResReqList;
  786. }
  787. NTSTATUS
  788. PipMergeResourceRequirementsLists (
  789. IN PIO_RESOURCE_REQUIREMENTS_LIST IoList1,
  790. IN PIO_RESOURCE_REQUIREMENTS_LIST IoList2,
  791. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *MergedList
  792. )
  793. /*++
  794. Routine Description:
  795. This routines merges two IoLists into one.
  796. Arguments:
  797. IoList1 - supplies the pointer to the first IoResourceRequirementsList
  798. IoList2 - supplies the pointer to the second IoResourceRequirementsList
  799. MergedList - Supplies a variable to receive the merged resource
  800. requirements list.
  801. Return Value:
  802. A NTSTATUS code to indicate the result of the function.
  803. --*/
  804. {
  805. NTSTATUS status = STATUS_SUCCESS;
  806. PIO_RESOURCE_REQUIREMENTS_LIST ioList, newList;
  807. ULONG size;
  808. PUCHAR p;
  809. PAGED_CODE();
  810. *MergedList = NULL;
  811. //
  812. // First handle the easy cases that both IO Lists are empty or any one of
  813. // them is empty.
  814. //
  815. if ((IoList1 == NULL || IoList1->AlternativeLists == 0) &&
  816. (IoList2 == NULL || IoList2->AlternativeLists == 0)) {
  817. return status;
  818. }
  819. ioList = NULL;
  820. if (IoList1 == NULL || IoList1->AlternativeLists == 0) {
  821. ioList = IoList2;
  822. } else if (IoList2 == NULL || IoList2->AlternativeLists == 0) {
  823. ioList = IoList1;
  824. }
  825. if (ioList) {
  826. newList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, ioList->ListSize);
  827. if (newList == NULL) {
  828. return STATUS_INSUFFICIENT_RESOURCES;
  829. }
  830. RtlMoveMemory(newList, ioList, ioList->ListSize);
  831. *MergedList = newList;
  832. return status;
  833. }
  834. //
  835. // Do real work...
  836. //
  837. size = IoList1->ListSize + IoList2->ListSize - FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List);
  838. newList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(
  839. PagedPool,
  840. size
  841. );
  842. if (newList == NULL) {
  843. return STATUS_INSUFFICIENT_RESOURCES;
  844. }
  845. p = (PUCHAR)newList;
  846. RtlMoveMemory(p, IoList1, IoList1->ListSize);
  847. p += IoList1->ListSize;
  848. RtlMoveMemory(p,
  849. &IoList2->List[0],
  850. size - IoList1->ListSize
  851. );
  852. newList->ListSize = size;
  853. newList->AlternativeLists += IoList2->AlternativeLists;
  854. *MergedList = newList;
  855. return status;
  856. }
  857. VOID
  858. PipMergeBootResourcesToRequirementsList(
  859. PDEVICE_INFORMATION DeviceInfo,
  860. PCM_RESOURCE_LIST BootResources,
  861. PIO_RESOURCE_REQUIREMENTS_LIST *IoResources
  862. )
  863. /*++
  864. Routine Description:
  865. This routines merges two IoLists into one.
  866. Arguments:
  867. IoList1 - supplies the pointer to the first IoResourceRequirementsList
  868. IoList2 - supplies the pointer to the second IoResourceRequirementsList
  869. MergedList - Supplies a variable to receive the merged resource
  870. requirements list.
  871. Return Value:
  872. A NTSTATUS code to indicate the result of the function.
  873. --*/
  874. {
  875. NTSTATUS status = STATUS_SUCCESS;
  876. PIO_RESOURCE_REQUIREMENTS_LIST ioResources = *IoResources, bootResReq = NULL, newList = NULL;
  877. BOOLEAN exactMatch;
  878. PAGED_CODE();
  879. if (DeviceInfo->BootResources) {
  880. PipBuildBootResourceRequirementsList (ioResources, BootResources, &bootResReq, &exactMatch);
  881. if (bootResReq) {
  882. if (exactMatch && ioResources->AlternativeLists == 1) {
  883. ExFreePool(ioResources);
  884. *IoResources = bootResReq;
  885. } else {
  886. PipMergeResourceRequirementsLists (bootResReq, ioResources, &newList);
  887. if (newList) {
  888. ExFreePool(ioResources);
  889. *IoResources = newList;
  890. }
  891. ExFreePool(bootResReq);
  892. }
  893. }
  894. }
  895. }
  896. NTSTATUS
  897. PipBuildBootResourceRequirementsList (
  898. IN PIO_RESOURCE_REQUIREMENTS_LIST IoList,
  899. IN PCM_RESOURCE_LIST CmList,
  900. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *FilteredList,
  901. OUT PBOOLEAN ExactMatch
  902. )
  903. /*++
  904. Routine Description:
  905. This routines adjusts the input IoList based on input BootConfig.
  906. Arguments:
  907. IoList - supplies the pointer to an IoResourceRequirementsList
  908. CmList - supplies the pointer to a BootConfig.
  909. FilteredList - Supplies a variable to receive the filtered resource
  910. requirements list.
  911. Return Value:
  912. A NTSTATUS code to indicate the result of the function.
  913. --*/
  914. {
  915. NTSTATUS status;
  916. PIO_RESOURCE_REQUIREMENTS_LIST ioList, newList;
  917. PIO_RESOURCE_LIST ioResourceList, newIoResourceList;
  918. PIO_RESOURCE_DESCRIPTOR ioResourceDescriptor, ioResourceDescriptorEnd;
  919. PIO_RESOURCE_DESCRIPTOR newIoResourceDescriptor, configDataDescriptor;
  920. LONG ioResourceDescriptorCount = 0;
  921. USHORT version;
  922. PCM_FULL_RESOURCE_DESCRIPTOR cmFullDesc;
  923. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDescriptor;
  924. ULONG cmDescriptorCount = 0;
  925. ULONG size, i, j, oldCount, phase;
  926. LONG k, alternativeLists;
  927. BOOLEAN exactMatch;
  928. PAGED_CODE();
  929. *FilteredList = NULL;
  930. *ExactMatch = FALSE;
  931. //
  932. // Make sure there is some resource requirements to be filtered.
  933. // If no, we will convert CmList/BootConfig to an IoResourceRequirementsList
  934. //
  935. if (IoList == NULL || IoList->AlternativeLists == 0) {
  936. if (CmList && CmList->Count != 0) {
  937. *FilteredList = PipCmResourcesToIoResources (CmList);
  938. }
  939. return STATUS_SUCCESS;
  940. }
  941. //
  942. // Make a copy of the Io Resource Requirements List
  943. //
  944. ioList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, IoList->ListSize);
  945. if (ioList == NULL) {
  946. return STATUS_INSUFFICIENT_RESOURCES;
  947. }
  948. RtlMoveMemory(ioList, IoList, IoList->ListSize);
  949. //
  950. // If there is no BootConfig, simply return the copy of the input Io list.
  951. //
  952. if (CmList == NULL || CmList->Count == 0) {
  953. *FilteredList = ioList;
  954. return STATUS_SUCCESS;
  955. }
  956. //
  957. // First determine minimum number of descriptors required.
  958. //
  959. cmFullDesc = &CmList->List[0];
  960. for (i = 0; i < CmList->Count; i++) {
  961. cmDescriptorCount += cmFullDesc->PartialResourceList.Count;
  962. cmDescriptor = &cmFullDesc->PartialResourceList.PartialDescriptors[0];
  963. for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) {
  964. size = 0;
  965. switch (cmDescriptor->Type) {
  966. case CmResourceTypeConfigData:
  967. case CmResourceTypeDevicePrivate:
  968. cmDescriptorCount--;
  969. break;
  970. case CmResourceTypeDeviceSpecific:
  971. size = cmDescriptor->u.DeviceSpecificData.DataSize;
  972. cmDescriptorCount--;
  973. break;
  974. default:
  975. //
  976. // Invalid cmresource list. Ignore it and use io resources
  977. //
  978. if (cmDescriptor->Type == CmResourceTypeNull ||
  979. cmDescriptor->Type >= CmResourceTypeMaximum) {
  980. cmDescriptorCount--;
  981. }
  982. }
  983. cmDescriptor++;
  984. cmDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmDescriptor + size);
  985. }
  986. cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmDescriptor;
  987. }
  988. if (cmDescriptorCount == 0) {
  989. *FilteredList = ioList;
  990. return STATUS_SUCCESS;
  991. }
  992. //
  993. // cmDescriptorCount is the number of BootConfig Descriptors needs.
  994. //
  995. // For each IO list Alternative ...
  996. //
  997. ioResourceList = ioList->List;
  998. k = ioList->AlternativeLists;
  999. while (--k >= 0) {
  1000. ioResourceDescriptor = ioResourceList->Descriptors;
  1001. ioResourceDescriptorEnd = ioResourceDescriptor + ioResourceList->Count;
  1002. while (ioResourceDescriptor < ioResourceDescriptorEnd) {
  1003. ioResourceDescriptor->Spare1 = 0;
  1004. ioResourceDescriptor++;
  1005. }
  1006. ioResourceList = (PIO_RESOURCE_LIST) ioResourceDescriptorEnd;
  1007. }
  1008. ioResourceList = ioList->List;
  1009. k = alternativeLists = ioList->AlternativeLists;
  1010. while (--k >= 0) {
  1011. version = ioResourceList->Version;
  1012. if (version == 0xffff) { // Convert bogus version to valid number
  1013. version = 1;
  1014. }
  1015. //
  1016. // We use Version field to store number of BootConfig found.
  1017. // Count field to store new number of descriptor in the alternative list.
  1018. //
  1019. ioResourceList->Version = 0;
  1020. oldCount = ioResourceList->Count;
  1021. ioResourceDescriptor = ioResourceList->Descriptors;
  1022. ioResourceDescriptorEnd = ioResourceDescriptor + ioResourceList->Count;
  1023. if (ioResourceDescriptor == ioResourceDescriptorEnd) {
  1024. //
  1025. // An alternative list with zero descriptor count
  1026. //
  1027. ioResourceList->Version = 0xffff; // Mark it as invalid
  1028. ioList->AlternativeLists--;
  1029. continue;
  1030. }
  1031. exactMatch = TRUE;
  1032. //
  1033. // For each Cm Resource descriptor ... except DevicePrivate and
  1034. // DeviceSpecific...
  1035. //
  1036. cmFullDesc = &CmList->List[0];
  1037. for (i = 0; i < CmList->Count; i++) {
  1038. cmDescriptor = &cmFullDesc->PartialResourceList.PartialDescriptors[0];
  1039. for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) {
  1040. size = 0;
  1041. switch (cmDescriptor->Type) {
  1042. case CmResourceTypeDevicePrivate:
  1043. break;
  1044. case CmResourceTypeDeviceSpecific:
  1045. size = cmDescriptor->u.DeviceSpecificData.DataSize;
  1046. break;
  1047. default:
  1048. if (cmDescriptor->Type == CmResourceTypeNull ||
  1049. cmDescriptor->Type >= CmResourceTypeMaximum) {
  1050. break;
  1051. }
  1052. //
  1053. // Check CmDescriptor against current Io Alternative list
  1054. //
  1055. for (phase = 0; phase < 2; phase++) {
  1056. ioResourceDescriptor = ioResourceList->Descriptors;
  1057. while (ioResourceDescriptor < ioResourceDescriptorEnd) {
  1058. if ((ioResourceDescriptor->Type == cmDescriptor->Type) &&
  1059. (ioResourceDescriptor->Spare1 == 0)) {
  1060. ULONGLONG min1, max1, min2, max2;
  1061. ULONG len1 = 1, len2 = 1, align1, align2;
  1062. UCHAR share1, share2;
  1063. share2 = ioResourceDescriptor->ShareDisposition;
  1064. share1 = cmDescriptor->ShareDisposition;
  1065. if ((share1 == CmResourceShareUndetermined) ||
  1066. (share1 > CmResourceShareShared)) {
  1067. share1 = share2;
  1068. }
  1069. if ((share2 == CmResourceShareUndetermined) ||
  1070. (share2 > CmResourceShareShared)) {
  1071. share2 = share1;
  1072. }
  1073. align1 = align2 = 1;
  1074. switch (cmDescriptor->Type) {
  1075. case CmResourceTypePort:
  1076. case CmResourceTypeMemory:
  1077. min1 = cmDescriptor->u.Port.Start.QuadPart;
  1078. max1 = cmDescriptor->u.Port.Start.QuadPart + cmDescriptor->u.Port.Length - 1;
  1079. len1 = cmDescriptor->u.Port.Length;
  1080. min2 = ioResourceDescriptor->u.Port.MinimumAddress.QuadPart;
  1081. max2 = ioResourceDescriptor->u.Port.MaximumAddress.QuadPart;
  1082. len2 = ioResourceDescriptor->u.Port.Length;
  1083. align2 = ioResourceDescriptor->u.Port.Alignment;
  1084. break;
  1085. case CmResourceTypeInterrupt:
  1086. max1 = min1 = cmDescriptor->u.Interrupt.Vector;
  1087. min2 = ioResourceDescriptor->u.Interrupt.MinimumVector;
  1088. max2 = ioResourceDescriptor->u.Interrupt.MaximumVector;
  1089. break;
  1090. case CmResourceTypeDma:
  1091. min1 = max1 =cmDescriptor->u.Dma.Channel;
  1092. min2 = ioResourceDescriptor->u.Dma.MinimumChannel;
  1093. max2 = ioResourceDescriptor->u.Dma.MaximumChannel;
  1094. break;
  1095. case CmResourceTypeBusNumber:
  1096. min1 = cmDescriptor->u.BusNumber.Start;
  1097. max1 = cmDescriptor->u.BusNumber.Start + cmDescriptor->u.BusNumber.Length - 1;
  1098. len1 = cmDescriptor->u.BusNumber.Length;
  1099. min2 = ioResourceDescriptor->u.BusNumber.MinBusNumber;
  1100. max2 = ioResourceDescriptor->u.BusNumber.MaxBusNumber;
  1101. len2 = ioResourceDescriptor->u.BusNumber.Length;
  1102. break;
  1103. default:
  1104. ASSERT(0);
  1105. break;
  1106. }
  1107. if (phase == 0) {
  1108. if (share1 == share2 && min2 == min1 && max2 >= max1 && len2 >= len1) {
  1109. //
  1110. // For phase 0 match, we want near exact match...
  1111. //
  1112. if (max2 != max1) {
  1113. exactMatch = FALSE;
  1114. }
  1115. ioResourceList->Version++;
  1116. ioResourceDescriptor->Spare1 = 0x80;
  1117. if (ioResourceDescriptor->Option & IO_RESOURCE_ALTERNATIVE) {
  1118. PIO_RESOURCE_DESCRIPTOR ioDesc;
  1119. ioDesc = ioResourceDescriptor;
  1120. ioDesc--;
  1121. while (ioDesc >= ioResourceList->Descriptors) {
  1122. ioDesc->Type = CmResourceTypeNull;
  1123. ioResourceList->Count--;
  1124. if (ioDesc->Option == IO_RESOURCE_ALTERNATIVE) {
  1125. ioDesc--;
  1126. } else {
  1127. break;
  1128. }
  1129. }
  1130. }
  1131. ioResourceDescriptor->Option = IO_RESOURCE_PREFERRED;
  1132. if (ioResourceDescriptor->Type == CmResourceTypePort ||
  1133. ioResourceDescriptor->Type == CmResourceTypeMemory) {
  1134. ioResourceDescriptor->u.Port.MinimumAddress.QuadPart = min1;
  1135. ioResourceDescriptor->u.Port.MaximumAddress.QuadPart = min1 + len2 - 1;
  1136. ioResourceDescriptor->u.Port.Alignment = 1;
  1137. } else if (ioResourceDescriptor->Type == CmResourceTypeBusNumber) {
  1138. ioResourceDescriptor->u.BusNumber.MinBusNumber = (ULONG)min1;
  1139. ioResourceDescriptor->u.BusNumber.MaxBusNumber = (ULONG)(min1 + len2 - 1);
  1140. }
  1141. ioResourceDescriptor++;
  1142. while (ioResourceDescriptor < ioResourceDescriptorEnd) {
  1143. if (ioResourceDescriptor->Option & IO_RESOURCE_ALTERNATIVE) {
  1144. ioResourceDescriptor->Type = CmResourceTypeNull;
  1145. ioResourceDescriptor++;
  1146. ioResourceList->Count--;
  1147. } else {
  1148. break;
  1149. }
  1150. }
  1151. phase = 1; // skip phase 1
  1152. break;
  1153. } else {
  1154. ioResourceDescriptor++;
  1155. }
  1156. } else {
  1157. exactMatch = FALSE;
  1158. if (share1 == share2 && min2 <= min1 && max2 >= max1 && len2 >= len1 &&
  1159. (min1 & (align2 - 1)) == 0) {
  1160. //
  1161. // Io range covers Cm range ... Change the Io range to what is specified
  1162. // in BootConfig.
  1163. //
  1164. //
  1165. switch (cmDescriptor->Type) {
  1166. case CmResourceTypePort:
  1167. case CmResourceTypeMemory:
  1168. ioResourceDescriptor->u.Port.MinimumAddress.QuadPart = min1;
  1169. ioResourceDescriptor->u.Port.MaximumAddress.QuadPart = min1 + len2 - 1;
  1170. break;
  1171. case CmResourceTypeInterrupt:
  1172. case CmResourceTypeDma:
  1173. ioResourceDescriptor->u.Interrupt.MinimumVector = (ULONG)min1;
  1174. ioResourceDescriptor->u.Interrupt.MaximumVector = (ULONG)max1;
  1175. break;
  1176. case CmResourceTypeBusNumber:
  1177. ioResourceDescriptor->u.BusNumber.MinBusNumber = (ULONG)min1;
  1178. ioResourceDescriptor->u.BusNumber.MaxBusNumber = (ULONG)(min1 + len2 - 1);
  1179. break;
  1180. }
  1181. ioResourceList->Version++;
  1182. ioResourceDescriptor->Spare1 = 0x80;
  1183. if (ioResourceDescriptor->Option & IO_RESOURCE_ALTERNATIVE) {
  1184. PIO_RESOURCE_DESCRIPTOR ioDesc;
  1185. ioDesc = ioResourceDescriptor;
  1186. ioDesc--;
  1187. while (ioDesc >= ioResourceList->Descriptors) {
  1188. ioDesc->Type = CmResourceTypeNull;
  1189. ioResourceList->Count--;
  1190. if (ioDesc->Option == IO_RESOURCE_ALTERNATIVE) {
  1191. ioDesc--;
  1192. } else {
  1193. break;
  1194. }
  1195. }
  1196. }
  1197. ioResourceDescriptor->Option = IO_RESOURCE_PREFERRED;
  1198. ioResourceDescriptor++;
  1199. while (ioResourceDescriptor < ioResourceDescriptorEnd) {
  1200. if (ioResourceDescriptor->Option & IO_RESOURCE_ALTERNATIVE) {
  1201. ioResourceDescriptor->Type = CmResourceTypeNull;
  1202. ioResourceList->Count--;
  1203. ioResourceDescriptor++;
  1204. } else {
  1205. break;
  1206. }
  1207. }
  1208. break;
  1209. } else {
  1210. ioResourceDescriptor++;
  1211. }
  1212. }
  1213. } else {
  1214. ioResourceDescriptor++;
  1215. }
  1216. } // Don't add any instruction after this ...
  1217. } // phase
  1218. } // switch
  1219. //
  1220. // Move to next Cm Descriptor
  1221. //
  1222. cmDescriptor++;
  1223. cmDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmDescriptor + size);
  1224. }
  1225. //
  1226. // Move to next Cm List
  1227. //
  1228. cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmDescriptor;
  1229. }
  1230. if (ioResourceList->Version != (USHORT)cmDescriptorCount) {
  1231. //
  1232. // If the current alternative list does not cover all the boot config
  1233. // descriptors, make it as invalid.
  1234. //
  1235. ioResourceList->Version = 0xffff;
  1236. ioList->AlternativeLists--;
  1237. } else {
  1238. ioResourceDescriptorCount += ioResourceList->Count;
  1239. ioResourceList->Version = version;
  1240. ioResourceList->Count = oldCount; // ++ single alternative list
  1241. break; // ++ single alternative list
  1242. }
  1243. ioResourceList->Count = oldCount;
  1244. //
  1245. // Move to next Io alternative list.
  1246. //
  1247. ioResourceList = (PIO_RESOURCE_LIST) ioResourceDescriptorEnd;
  1248. }
  1249. //
  1250. // If there is not any valid alternative, convert CmList to Io list.
  1251. //
  1252. if (ioList->AlternativeLists == 0) {
  1253. *FilteredList = PipCmResourcesToIoResources (CmList);
  1254. ExFreePool(ioList);
  1255. return STATUS_SUCCESS;
  1256. }
  1257. //
  1258. // we have finished filtering the resource requirements list. Now allocate memory
  1259. // and rebuild a new list.
  1260. //
  1261. size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
  1262. //sizeof(IO_RESOURCE_LIST) * (ioList->AlternativeLists - 1) + // ++ Single Alternative list
  1263. sizeof(IO_RESOURCE_DESCRIPTOR) * (ioResourceDescriptorCount);
  1264. newList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size);
  1265. if (newList == NULL) {
  1266. ExFreePool(ioList);
  1267. return STATUS_INSUFFICIENT_RESOURCES;
  1268. }
  1269. //
  1270. // Walk through the io resource requirements list and pick up any valid descriptor.
  1271. //
  1272. newList->ListSize = size;
  1273. newList->InterfaceType = CmList->List->InterfaceType;
  1274. newList->BusNumber = CmList->List->BusNumber;
  1275. newList->SlotNumber = ioList->SlotNumber;
  1276. newList->AlternativeLists = 1;
  1277. ioResourceList = ioList->List;
  1278. newIoResourceList = newList->List;
  1279. while (--alternativeLists >= 0) {
  1280. ioResourceDescriptor = ioResourceList->Descriptors;
  1281. ioResourceDescriptorEnd = ioResourceDescriptor + ioResourceList->Count;
  1282. if (ioResourceList->Version == 0xffff) {
  1283. ioResourceList = (PIO_RESOURCE_LIST)ioResourceDescriptorEnd;
  1284. continue;
  1285. }
  1286. newIoResourceList->Version = ioResourceList->Version;
  1287. newIoResourceList->Revision = ioResourceList->Revision;
  1288. newIoResourceDescriptor = newIoResourceList->Descriptors;
  1289. if (ioResourceDescriptor->Type != CmResourceTypeConfigData) {
  1290. newIoResourceDescriptor->Option = IO_RESOURCE_PREFERRED;
  1291. newIoResourceDescriptor->Type = CmResourceTypeConfigData;
  1292. newIoResourceDescriptor->ShareDisposition = CmResourceShareShared;
  1293. newIoResourceDescriptor->Flags = 0;
  1294. newIoResourceDescriptor->Spare1 = 0;
  1295. newIoResourceDescriptor->Spare2 = 0;
  1296. newIoResourceDescriptor->u.ConfigData.Priority = BOOT_CONFIG_PRIORITY;
  1297. configDataDescriptor = newIoResourceDescriptor;
  1298. newIoResourceDescriptor++;
  1299. } else {
  1300. newList->ListSize -= sizeof(IO_RESOURCE_DESCRIPTOR);
  1301. configDataDescriptor = newIoResourceDescriptor;
  1302. }
  1303. while (ioResourceDescriptor < ioResourceDescriptorEnd) {
  1304. if (ioResourceDescriptor->Type != CmResourceTypeNull) {
  1305. *newIoResourceDescriptor = *ioResourceDescriptor;
  1306. newIoResourceDescriptor++;
  1307. }
  1308. ioResourceDescriptor++;
  1309. }
  1310. newIoResourceList->Count = (ULONG)(newIoResourceDescriptor - newIoResourceList->Descriptors);
  1311. configDataDescriptor->u.ConfigData.Priority = BOOT_CONFIG_PRIORITY;
  1312. break;
  1313. }
  1314. ASSERT((PUCHAR)newIoResourceDescriptor == ((PUCHAR)newList + newList->ListSize));
  1315. *FilteredList = newList;
  1316. *ExactMatch = exactMatch;
  1317. ExFreePool(ioList);
  1318. return STATUS_SUCCESS;
  1319. }
  1320. PCM_PARTIAL_RESOURCE_DESCRIPTOR
  1321. PipFindMatchingBootMemResource(
  1322. IN ULONG Index,
  1323. IN PIO_RESOURCE_DESCRIPTOR IoDesc,
  1324. IN PCM_RESOURCE_LIST BootResources
  1325. )
  1326. /*++
  1327. Routine Description:
  1328. This routine finds boot resources that match the i/o descriptor
  1329. Arguments:
  1330. Index - Index of memory boot config resource the caller is interested in.
  1331. IoDesc - I/O descriptor
  1332. BootResources - boot config
  1333. Return Value:
  1334. A pointer to a matching descriptor in the boot config
  1335. --*/
  1336. {
  1337. PCM_FULL_RESOURCE_DESCRIPTOR cmFullDesc;
  1338. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartDesc;
  1339. ULONG count = 0, size, i, j, noMem;
  1340. if (BootResources == NULL) {
  1341. return NULL;
  1342. }
  1343. cmFullDesc = &BootResources->List[0];
  1344. for (i = 0; i < BootResources->Count; i++) {
  1345. cmPartDesc = &cmFullDesc->PartialResourceList.PartialDescriptors[0];
  1346. noMem = 0;
  1347. for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) {
  1348. size = 0;
  1349. if (cmPartDesc->Type == CmResourceTypeMemory) {
  1350. if (((cmPartDesc->u.Memory.Start.QuadPart >=
  1351. IoDesc->u.Memory.MinimumAddress.QuadPart) &&
  1352. ((cmPartDesc->u.Memory.Start.QuadPart +
  1353. cmPartDesc->u.Memory.Length - 1) <=
  1354. IoDesc->u.Memory.MaximumAddress.QuadPart)) &&
  1355. noMem == Index) {
  1356. return cmPartDesc;
  1357. }
  1358. noMem++;
  1359. } else if (cmPartDesc->Type == CmResourceTypeDeviceSpecific) {
  1360. size = cmPartDesc->u.DeviceSpecificData.DataSize;
  1361. }
  1362. cmPartDesc++;
  1363. cmPartDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmPartDesc + size);
  1364. }
  1365. cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmPartDesc;
  1366. }
  1367. return NULL;
  1368. }
  1369. NTSTATUS
  1370. PipTrimResourceRequirements (
  1371. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoList,
  1372. IN USHORT IrqFlags,
  1373. IN PCM_RESOURCE_LIST BootResources
  1374. )
  1375. /*++
  1376. Routine Description:
  1377. This routine:
  1378. * adjusts the irq requirements level/edge to the value
  1379. decided on in PipCheckBus()
  1380. * adjusts the memory requirements to reflect the memory boot
  1381. config.
  1382. Arguments:
  1383. IoList - supplies the pointer to an IoResourceRequirementsList
  1384. IrqFlags - level/edge irq reuirements to be applied to all interrupt requirements in all alternatives.
  1385. BootResources - Used as a reference.
  1386. --*/
  1387. {
  1388. PIO_RESOURCE_REQUIREMENTS_LIST newReqList;
  1389. PIO_RESOURCE_LIST resList, newList;
  1390. PIO_RESOURCE_DESCRIPTOR resDesc, newDesc;
  1391. PCM_PARTIAL_RESOURCE_DESCRIPTOR bootDesc;
  1392. ULONG listCount, i, j, pass, size, noMem;
  1393. BOOLEAN goodAlt;
  1394. if (IoList == NULL) {
  1395. return STATUS_SUCCESS;
  1396. }
  1397. // The only way to create a new req list only if absolutely
  1398. // necessary and make it the perfect size is perform this
  1399. // operation in two passes.
  1400. // 1. figure out how many alternatives will be eliminated and
  1401. // compute size of new req list. if all of the alternatives
  1402. // survived, return the original list (now modified)
  1403. //
  1404. // 2. construct new reqlist minus the bad alternatives.
  1405. listCount = 0;
  1406. size = 0;
  1407. for (pass = 0; pass < 2; pass++) {
  1408. if (pass == 0) {
  1409. size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) -
  1410. sizeof(IO_RESOURCE_LIST);
  1411. } else {
  1412. newReqList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size);
  1413. if (newReqList == NULL) {
  1414. return STATUS_INSUFFICIENT_RESOURCES;
  1415. }
  1416. *newReqList = **IoList;
  1417. newReqList->ListSize = size;
  1418. newReqList->AlternativeLists = listCount;
  1419. newList = &newReqList->List[0];
  1420. }
  1421. resList = &(*IoList)->List[0];
  1422. for (i = 0; i < (*IoList)->AlternativeLists; i++) {
  1423. if (pass == 1) {
  1424. *newList = *resList;
  1425. newDesc = &newList->Descriptors[0];
  1426. }
  1427. resDesc = &resList->Descriptors[0];
  1428. goodAlt = TRUE;
  1429. noMem = 0;
  1430. for (j = 0; j < resList->Count; j++) {
  1431. if (resDesc->Type == CmResourceTypeInterrupt) {
  1432. resDesc->Flags = IrqFlags;
  1433. if (resDesc->Flags & CM_RESOURCE_INTERRUPT_LATCHED) {
  1434. resDesc->ShareDisposition = CmResourceShareDeviceExclusive;
  1435. }
  1436. } else if (resDesc->Type == CmResourceTypeMemory) {
  1437. resDesc->Flags |= CM_RESOURCE_MEMORY_24;
  1438. if (BootResources) {
  1439. bootDesc = PipFindMatchingBootMemResource(noMem, resDesc, BootResources);
  1440. // have matching boot config resource, can trim requirements
  1441. if (bootDesc) {
  1442. if (bootDesc->Flags & CM_RESOURCE_MEMORY_READ_ONLY) {
  1443. // exact or inclusive ROM match is
  1444. // converted into a fixed requirement.
  1445. resDesc->u.Memory.MinimumAddress.QuadPart =
  1446. bootDesc->u.Memory.Start.QuadPart;
  1447. if (bootDesc->u.Memory.Length) {
  1448. resDesc->u.Memory.MaximumAddress.QuadPart =
  1449. bootDesc->u.Memory.Start.QuadPart +
  1450. bootDesc->u.Memory.Length - 1;
  1451. } else {
  1452. resDesc->u.Memory.MaximumAddress.QuadPart =
  1453. bootDesc->u.Memory.Start.QuadPart;
  1454. }
  1455. resDesc->u.Memory.Length = bootDesc->u.Memory.Length;
  1456. resDesc->u.Memory.Alignment = 1;
  1457. resDesc->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
  1458. }
  1459. } else {
  1460. goodAlt = FALSE;
  1461. }
  1462. } else {
  1463. resDesc->Flags &= ~CM_RESOURCE_MEMORY_READ_ONLY;
  1464. }
  1465. noMem++;
  1466. }
  1467. if (pass == 1) {
  1468. *newDesc = *resDesc;
  1469. PipDumpIoResourceDescriptor(" ", newDesc);
  1470. newDesc++;
  1471. }
  1472. resDesc++;
  1473. }
  1474. if (pass == 0) {
  1475. if (goodAlt) {
  1476. size += sizeof(IO_RESOURCE_LIST) +
  1477. sizeof(IO_RESOURCE_DESCRIPTOR) * (resList->Count - 1);
  1478. listCount++;
  1479. }
  1480. } else {
  1481. if (goodAlt) {
  1482. newList = (PIO_RESOURCE_LIST) newDesc;
  1483. } else {
  1484. DebugPrint((DEBUG_RESOURCE, "An alternative trimmed off of reqlist\n"));
  1485. }
  1486. }
  1487. resList = (PIO_RESOURCE_LIST) resDesc;
  1488. }
  1489. // If we have the same number of alternatives as before use
  1490. // the use existing (modified in-place) requirements list
  1491. if (!pass && (listCount == (*IoList)->AlternativeLists)) {
  1492. return STATUS_SUCCESS;
  1493. }
  1494. // if all alternatives have been eliminated, then it is better
  1495. // to use the existing requirements list than to hope to build
  1496. // one out of the boot config alone.
  1497. if (!pass && (listCount == 0)) {
  1498. DebugPrint((DEBUG_RESOURCE, "All alternatives trimmed off of reqlist, going with original\n"));
  1499. return STATUS_SUCCESS;
  1500. }
  1501. }
  1502. ExFreePool(*IoList);
  1503. *IoList = newReqList;
  1504. return STATUS_SUCCESS;
  1505. }
  1506. #endif