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.

2072 lines
59 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. xlate.c
  5. Abstract:
  6. This file contains routines to translate resources between PnP ISA/BIOS
  7. format and Windows NT formats.
  8. Author:
  9. Shie-Lin Tzong (shielint) 12-Apr-1995
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. Note:
  14. This file is shared between the io subsystem and the ISAPNP bus driver.
  15. It is not compiled directly but is included by:
  16. base\ntos\io\pnpmgr\pnpcvrt.c
  17. base\busdrv\isapnp\convert.c
  18. ***** If you change this file make sure you build in *BOTH* places *****
  19. --*/
  20. #include "pbios.h"
  21. #include "pnpcvrt.h"
  22. #if UMODETEST
  23. #undef IsNEC_98
  24. #define IsNEC_98 0
  25. #endif
  26. #define NO_PLACEHOLDER_DMA_IRQ_SUPPORT 1
  27. //
  28. // internal structures for resource translation
  29. //
  30. typedef struct _PB_DEPENDENT_RESOURCES {
  31. ULONG Count;
  32. UCHAR Flags;
  33. UCHAR Priority;
  34. struct _PB_DEPENDENT_RESOURCES *Next;
  35. } PB_DEPENDENT_RESOURCES, *PPB_DEPENDENT_RESOURCES;
  36. #define DEPENDENT_FLAGS_END 1
  37. typedef struct _PB_ATERNATIVE_INFORMATION {
  38. PPB_DEPENDENT_RESOURCES Resources;
  39. ULONG NoDependentFunctions;
  40. ULONG TotalResourceCount;
  41. } PB_ALTERNATIVE_INFORMATION, *PPB_ALTERNATIVE_INFORMATION;
  42. //
  43. // Internal function references
  44. //
  45. PPB_DEPENDENT_RESOURCES
  46. PbAddDependentResourcesToList (
  47. IN OUT PUCHAR *ResourceDescriptor,
  48. IN ULONG ListNo,
  49. IN PPB_ALTERNATIVE_INFORMATION AlternativeList
  50. );
  51. NTSTATUS
  52. PbBiosIrqToIoDescriptor (
  53. IN OUT PUCHAR *BiosData,
  54. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  55. );
  56. NTSTATUS
  57. PbBiosDmaToIoDescriptor (
  58. IN OUT PUCHAR *BiosData,
  59. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  60. );
  61. NTSTATUS
  62. PbBiosPortFixedToIoDescriptor (
  63. IN OUT PUCHAR *BiosData,
  64. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
  65. IN BOOLEAN ForceFixedIoTo16bit
  66. );
  67. NTSTATUS
  68. PbBiosPortToIoDescriptor (
  69. IN OUT PUCHAR *BiosData,
  70. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  71. );
  72. NTSTATUS
  73. PbBiosMemoryToIoDescriptor (
  74. IN OUT PUCHAR *BiosData,
  75. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  76. );
  77. NTSTATUS
  78. PpCmResourcesToBiosResources (
  79. IN PCM_RESOURCE_LIST CmResources,
  80. IN PUCHAR BiosRequirements,
  81. IN PUCHAR *BiosResources,
  82. IN PULONG Length
  83. );
  84. NTSTATUS
  85. PbCmIrqToBiosDescriptor (
  86. IN PUCHAR BiosRequirements,
  87. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
  88. OUT PVOID ReturnDescriptor,
  89. OUT PULONG Length
  90. );
  91. NTSTATUS
  92. PbCmDmaToBiosDescriptor (
  93. IN PUCHAR BiosRequirements,
  94. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
  95. OUT PVOID ReturnDescriptor,
  96. OUT PULONG Length
  97. );
  98. NTSTATUS
  99. PbCmPortToBiosDescriptor (
  100. IN PUCHAR BiosRequirements,
  101. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
  102. OUT PVOID ReturnDescriptor,
  103. OUT PULONG Length
  104. );
  105. NTSTATUS
  106. PbCmMemoryToBiosDescriptor (
  107. IN PUCHAR BiosRequirements,
  108. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
  109. OUT PVOID ReturnDescriptor,
  110. OUT PULONG Length
  111. );
  112. #ifdef ALLOC_PRAGMA
  113. #pragma alloc_text(PAGE, PpBiosResourcesToNtResources)
  114. #pragma alloc_text(PAGE, PpBiosResourcesSetToDisabled)
  115. #pragma alloc_text(PAGE, PbAddDependentResourcesToList)
  116. #pragma alloc_text(PAGE, PbBiosIrqToIoDescriptor)
  117. #pragma alloc_text(PAGE, PbBiosDmaToIoDescriptor)
  118. #pragma alloc_text(PAGE, PbBiosPortFixedToIoDescriptor)
  119. #pragma alloc_text(PAGE, PbBiosPortToIoDescriptor)
  120. #pragma alloc_text(PAGE, PbBiosMemoryToIoDescriptor)
  121. #pragma alloc_text(PAGE, PpCmResourcesToBiosResources)
  122. #pragma alloc_text(PAGE, PbCmIrqToBiosDescriptor)
  123. #pragma alloc_text(PAGE, PbCmDmaToBiosDescriptor)
  124. #pragma alloc_text(PAGE, PbCmPortToBiosDescriptor)
  125. #pragma alloc_text(PAGE, PbCmMemoryToBiosDescriptor)
  126. #endif
  127. #ifdef ALLOC_DATA_PRAGMA
  128. #pragma data_seg("PAGEDATA")
  129. #endif
  130. NTSTATUS
  131. PpBiosResourcesToNtResources (
  132. IN ULONG BusNumber,
  133. IN ULONG SlotNumber,
  134. IN OUT PUCHAR *BiosData,
  135. IN ULONG ConvertFlags,
  136. OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList,
  137. OUT PULONG ReturnedLength
  138. )
  139. /*++
  140. Routine Description:
  141. This routine parses the Bios resource list and generates
  142. a NT resource list. The returned Nt resource list could be either IO
  143. format or CM format. It is caller's responsibility to release the
  144. returned data buffer.
  145. Arguments:
  146. SlotNumber - specifies the slot number of the BIOS resource.
  147. BiosData - Supplies a pointer to a variable which specifies the bios resource
  148. data buffer and which to receive the pointer to next bios resource data.
  149. ReturnedList - supplies a variable to receive the desired resource list.
  150. ReturnedLength - Supplies a variable to receive the length of the resource list.
  151. Return Value:
  152. NTSTATUS code
  153. --*/
  154. {
  155. PUCHAR buffer;
  156. USHORT mask16, increment;
  157. UCHAR tagName, mask8;
  158. NTSTATUS status;
  159. PPB_ALTERNATIVE_INFORMATION alternativeList = NULL;
  160. ULONG commonResCount = 0, dependDescCount = 0, i, j;
  161. ULONG alternativeListCount = 0, dependFunctionCount = 0;
  162. PIO_RESOURCE_DESCRIPTOR ioDesc;
  163. PPB_DEPENDENT_RESOURCES dependResList = NULL, dependResources;
  164. BOOLEAN dependent = FALSE;
  165. BOOLEAN forceFixedIoTo16bit;
  166. ULONG listSize, noResLists;
  167. ULONG totalDescCount, descCount;
  168. PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
  169. PIO_RESOURCE_LIST ioResList;
  170. //
  171. // First, scan the bios data to determine the memory requirement and
  172. // the information to build internal data structures.
  173. //
  174. *ReturnedLength = 0;
  175. alternativeListCount = 0;
  176. buffer = *BiosData;
  177. tagName = *buffer;
  178. forceFixedIoTo16bit =
  179. (BOOLEAN)((ConvertFlags & PPCONVERTFLAG_FORCE_FIXED_IO_16BIT_DECODE) != 0);
  180. for ( ; ; ) {
  181. //
  182. // Determine the size of the BIOS resource descriptor
  183. //
  184. if (!(tagName & LARGE_RESOURCE_TAG)) {
  185. increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK);
  186. increment += 1; // length of small tag
  187. tagName &= SMALL_TAG_MASK;
  188. } else {
  189. increment = *(USHORT UNALIGNED *)(buffer+1);
  190. increment += 3; // length of large tag
  191. }
  192. if (tagName == TAG_END) {
  193. buffer += increment;
  194. break;
  195. }
  196. //
  197. // Based on the type of the BIOS resource, determine the count of
  198. // the IO descriptors.
  199. //
  200. switch (tagName) {
  201. case TAG_IRQ:
  202. mask16 = ((PPNP_IRQ_DESCRIPTOR)buffer)->IrqMask;
  203. i = 0;
  204. #if NO_PLACEHOLDER_DMA_IRQ_SUPPORT
  205. while (mask16) {
  206. if(mask16 & 1) {
  207. i++;
  208. }
  209. mask16 >>= 1;
  210. }
  211. #else
  212. if (mask16 == 0) {
  213. i++;
  214. } else {
  215. while (mask16) {
  216. if(mask16 & 1) {
  217. i++;
  218. }
  219. mask16 >>= 1;
  220. }
  221. }
  222. #endif
  223. if (!dependent) {
  224. commonResCount += i;
  225. } else {
  226. dependDescCount += i;
  227. }
  228. break;
  229. case TAG_DMA:
  230. mask8 = ((PPNP_DMA_DESCRIPTOR)buffer)->ChannelMask;
  231. i = 0;
  232. #if NO_PLACEHOLDER_DMA_IRQ_SUPPORT
  233. while (mask8) {
  234. if (mask8 & 1) {
  235. i++;
  236. }
  237. mask8 >>= 1;
  238. }
  239. #else
  240. if (mask8 == 0) {
  241. i++;
  242. } else {
  243. while (mask8) {
  244. if (mask8 & 1) {
  245. i++;
  246. }
  247. mask8 >>= 1;
  248. }
  249. }
  250. #endif
  251. if (!dependent) {
  252. commonResCount += i;
  253. } else {
  254. dependDescCount += i;
  255. }
  256. break;
  257. case TAG_START_DEPEND:
  258. dependent = TRUE;
  259. dependFunctionCount++;
  260. break;
  261. case TAG_END_DEPEND:
  262. dependent = FALSE;
  263. alternativeListCount++;
  264. break;
  265. case TAG_IO_FIXED:
  266. case TAG_IO:
  267. case TAG_MEMORY:
  268. case TAG_MEMORY32:
  269. case TAG_MEMORY32_FIXED:
  270. if (!dependent) {
  271. commonResCount++;
  272. } else {
  273. dependDescCount++;
  274. }
  275. break;
  276. default:
  277. //
  278. // Unknown tag. Skip it.
  279. //
  280. break;
  281. }
  282. //
  283. // Move to next bios resource descriptor.
  284. //
  285. buffer += increment;
  286. tagName = *buffer;
  287. if ((tagName & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
  288. break;
  289. }
  290. }
  291. if (dependent) {
  292. //
  293. // TAG_END_DEPEND was not found before we hit TAG_COMPLETE_END, so
  294. // simulate it.
  295. //
  296. dependent = FALSE;
  297. alternativeListCount++;
  298. }
  299. //
  300. // if empty bios resources, simply return.
  301. //
  302. if (commonResCount == 0 && dependFunctionCount == 0) {
  303. *ReturnedList = NULL;
  304. *ReturnedLength = 0;
  305. *BiosData = buffer;
  306. return STATUS_SUCCESS;
  307. }
  308. //
  309. // Allocate memory for our internal data structures
  310. //
  311. dependFunctionCount += commonResCount;
  312. dependResources = (PPB_DEPENDENT_RESOURCES)ExAllocatePoolWithTag(
  313. PagedPool,
  314. dependFunctionCount * sizeof(PB_DEPENDENT_RESOURCES) +
  315. (commonResCount + dependDescCount) * sizeof(IO_RESOURCE_DESCRIPTOR),
  316. 'bPnP'
  317. );
  318. if (!dependResources) {
  319. return STATUS_INSUFFICIENT_RESOURCES;
  320. }
  321. dependResList = dependResources; // remember it so we can free it.
  322. alternativeListCount += commonResCount;
  323. alternativeList = (PPB_ALTERNATIVE_INFORMATION)ExAllocatePoolWithTag(
  324. PagedPool,
  325. sizeof(PB_ALTERNATIVE_INFORMATION) * (alternativeListCount + 1),
  326. 'bPnP'
  327. );
  328. if (!alternativeList) {
  329. status = STATUS_INSUFFICIENT_RESOURCES;
  330. goto exit0;
  331. }
  332. RtlZeroMemory(alternativeList,
  333. sizeof(PB_ALTERNATIVE_INFORMATION) * alternativeListCount
  334. );
  335. alternativeList[0].Resources = dependResources;
  336. ioDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
  337. //
  338. // Now start over again to process the bios data and initialize our internal
  339. // resource representation.
  340. //
  341. dependDescCount = 0;
  342. alternativeListCount = 0;
  343. buffer = *BiosData;
  344. tagName = *buffer;
  345. dependent = FALSE;
  346. for ( ; ; ) {
  347. if (!(tagName & LARGE_RESOURCE_TAG)) {
  348. tagName &= SMALL_TAG_MASK;
  349. }
  350. if (tagName == TAG_END) {
  351. buffer += (*buffer & SMALL_TAG_SIZE_MASK) + 1;
  352. break;
  353. }
  354. switch (tagName) {
  355. case TAG_DMA:
  356. case TAG_IRQ:
  357. case TAG_IO:
  358. case TAG_IO_FIXED:
  359. case TAG_MEMORY:
  360. case TAG_MEMORY32:
  361. case TAG_MEMORY32_FIXED:
  362. if (tagName == TAG_DMA) {
  363. status = PbBiosDmaToIoDescriptor(&buffer, ioDesc);
  364. } else if (tagName == TAG_IRQ) {
  365. status = PbBiosIrqToIoDescriptor(&buffer, ioDesc);
  366. } else if (tagName == TAG_IO) {
  367. status = PbBiosPortToIoDescriptor(&buffer, ioDesc);
  368. } else if (tagName == TAG_IO_FIXED) {
  369. status = PbBiosPortFixedToIoDescriptor(&buffer, ioDesc, forceFixedIoTo16bit);
  370. } else {
  371. status = PbBiosMemoryToIoDescriptor(&buffer, ioDesc);
  372. }
  373. if (NT_SUCCESS(status)) {
  374. ioDesc++;
  375. if (dependent) {
  376. dependDescCount++;
  377. } else {
  378. alternativeList[alternativeListCount].NoDependentFunctions = 1;
  379. alternativeList[alternativeListCount].TotalResourceCount = 1;
  380. dependResources->Count = 1;
  381. dependResources->Flags = DEPENDENT_FLAGS_END;
  382. dependResources->Next = alternativeList[alternativeListCount].Resources;
  383. alternativeListCount++;
  384. alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)ioDesc;
  385. dependResources = alternativeList[alternativeListCount].Resources;
  386. ioDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
  387. }
  388. }
  389. break;
  390. case TAG_START_DEPEND:
  391. //
  392. // Some card (OPTI) put empty START_DEPENDENT functions
  393. //
  394. dependent = TRUE;
  395. if (alternativeList[alternativeListCount].NoDependentFunctions != 0) {
  396. //
  397. // End of current dependent function
  398. //
  399. dependResources->Count = dependDescCount;
  400. dependResources->Flags = 0;
  401. dependResources->Next = (PPB_DEPENDENT_RESOURCES)ioDesc;
  402. dependResources = dependResources->Next;
  403. ioDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
  404. alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
  405. }
  406. alternativeList[alternativeListCount].NoDependentFunctions++;
  407. if (*buffer & SMALL_TAG_SIZE_MASK) {
  408. dependResources->Priority = *(buffer + 1);
  409. }
  410. dependDescCount = 0;
  411. buffer += 1 + (*buffer & SMALL_TAG_SIZE_MASK);
  412. break;
  413. case TAG_END_DEPEND:
  414. alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
  415. dependResources->Count = dependDescCount;
  416. dependResources->Flags = DEPENDENT_FLAGS_END;
  417. dependResources->Next = alternativeList[alternativeListCount].Resources;
  418. dependent = FALSE;
  419. dependDescCount = 0;
  420. alternativeListCount++;
  421. alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)ioDesc;
  422. dependResources = alternativeList[alternativeListCount].Resources;
  423. ioDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
  424. buffer++;
  425. break;
  426. default:
  427. //
  428. // Don't-care tag simply advance the buffer pointer to next tag.
  429. //
  430. if (*buffer & LARGE_RESOURCE_TAG) {
  431. increment = *(USHORT UNALIGNED *)(buffer+1);
  432. increment += 3; // length of large tag
  433. } else {
  434. increment = (USHORT)(*buffer & SMALL_TAG_SIZE_MASK);
  435. increment += 1; // length of small tag
  436. }
  437. buffer += increment;
  438. }
  439. tagName = *buffer;
  440. if ((tagName & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
  441. break;
  442. }
  443. }
  444. if (dependent) {
  445. //
  446. // TAG_END_DEPEND was not found before we hit TAG_COMPLETE_END, so
  447. // simulate it.
  448. //
  449. alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
  450. dependResources->Count = dependDescCount;
  451. dependResources->Flags = DEPENDENT_FLAGS_END;
  452. dependResources->Next = alternativeList[alternativeListCount].Resources;
  453. dependent = FALSE;
  454. dependDescCount = 0;
  455. alternativeListCount++;
  456. alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)ioDesc;
  457. dependResources = alternativeList[alternativeListCount].Resources;
  458. ioDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
  459. }
  460. if (alternativeListCount != 0) {
  461. alternativeList[alternativeListCount].Resources = NULL; // dummy alternativeList record
  462. }
  463. *BiosData = buffer;
  464. //
  465. // prepare IoResourceList
  466. //
  467. noResLists = 1;
  468. for (i = 0; i < alternativeListCount; i++) {
  469. noResLists *= alternativeList[i].NoDependentFunctions;
  470. }
  471. totalDescCount = 0;
  472. for (i = 0; i < alternativeListCount; i++) {
  473. descCount = 1;
  474. for (j = 0; j < alternativeListCount; j++) {
  475. if (j == i) {
  476. descCount *= alternativeList[j].TotalResourceCount;
  477. } else {
  478. descCount *= alternativeList[j].NoDependentFunctions;
  479. }
  480. }
  481. totalDescCount += descCount;
  482. }
  483. listSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
  484. sizeof(IO_RESOURCE_LIST) * (noResLists - 1) +
  485. sizeof(IO_RESOURCE_DESCRIPTOR) * totalDescCount -
  486. sizeof(IO_RESOURCE_DESCRIPTOR) * noResLists +
  487. sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount * noResLists;
  488. if (ConvertFlags & PPCONVERTFLAG_SET_RESTART_LCPRI) {
  489. listSize += noResLists * sizeof(IO_RESOURCE_DESCRIPTOR);
  490. }
  491. ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePoolWithTag(PagedPool, listSize, 'bPnP');
  492. if (!ioResReqList) {
  493. status = STATUS_INSUFFICIENT_RESOURCES;
  494. goto exit1;
  495. }
  496. ioResReqList->ListSize = listSize;
  497. ioResReqList->InterfaceType = Isa;
  498. ioResReqList->BusNumber = BusNumber;
  499. ioResReqList->SlotNumber = SlotNumber;
  500. ioResReqList->Reserved[0] = 0;
  501. ioResReqList->Reserved[1] = 0;
  502. ioResReqList->Reserved[2] = 0;
  503. ioResReqList->AlternativeLists = noResLists;
  504. ioResList = &ioResReqList->List[0];
  505. //
  506. // Build resource lists
  507. //
  508. for (i = 0; i < noResLists; i++) {
  509. ioResList->Version = 1;
  510. ioResList->Revision = 0x30 | (USHORT)i;
  511. if (ConvertFlags & PPCONVERTFLAG_SET_RESTART_LCPRI) {
  512. RtlZeroMemory(&ioResList->Descriptors[0], sizeof(IO_RESOURCE_DESCRIPTOR));
  513. ioResList->Descriptors[0].Option = IO_RESOURCE_PREFERRED;
  514. ioResList->Descriptors[0].Type = CmResourceTypeConfigData;
  515. ioResList->Descriptors[0].u.ConfigData.Priority = LCPRI_RESTART;
  516. buffer = (PUCHAR)&ioResList->Descriptors[1];
  517. } else {
  518. buffer = (PUCHAR)&ioResList->Descriptors[0];
  519. }
  520. //
  521. // Copy dependent functions if any.
  522. //
  523. if (alternativeList) {
  524. PbAddDependentResourcesToList(&buffer, 0, alternativeList);
  525. }
  526. //
  527. // Update io resource list ptr
  528. //
  529. ioResList->Count = ((ULONG)((ULONG_PTR)buffer - (ULONG_PTR)&ioResList->Descriptors[0])) /
  530. sizeof(IO_RESOURCE_DESCRIPTOR);
  531. //
  532. // Hack for user mode pnp mgr
  533. //
  534. for (j = 0; j < ioResList->Count; j++) {
  535. ioResList->Descriptors[j].Spare2 = (USHORT)j;
  536. }
  537. ioResList = (PIO_RESOURCE_LIST)buffer;
  538. }
  539. *ReturnedLength = listSize;
  540. status = STATUS_SUCCESS;
  541. *ReturnedList = ioResReqList;
  542. exit1:
  543. if (alternativeList) {
  544. ExFreePool(alternativeList);
  545. }
  546. exit0:
  547. if (dependResList) {
  548. ExFreePool(dependResList);
  549. }
  550. return status;
  551. }
  552. VOID
  553. PpBiosResourcesSetToDisabled (
  554. IN OUT PUCHAR BiosData,
  555. OUT PULONG Length
  556. )
  557. /*++
  558. Routine Description:
  559. This routine modifies the passed in Bios resource list so that it reflects
  560. what PnPBIOS expects to see if a device is disabled.
  561. Arguments:
  562. BiosData - Supplies a pointer to the bios resource data buffer
  563. Length - This points to a ULONG that will contain the length of the single
  564. resource list that has been programmed to look disabled.
  565. Return Value:
  566. None.
  567. --*/
  568. {
  569. PUCHAR buffer;
  570. USHORT increment;
  571. UCHAR tagName ;
  572. //
  573. // First, scan the bios data to determine the memory requirement and
  574. // the information to build internal data structures.
  575. //
  576. buffer = BiosData;
  577. do {
  578. tagName = *buffer;
  579. //
  580. // Determine the size of the BIOS resource descriptor
  581. //
  582. if (!(tagName & LARGE_RESOURCE_TAG)) {
  583. increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK);
  584. tagName &= SMALL_TAG_MASK;
  585. //
  586. // Be careful not to wipe out the version field. That's very bad.
  587. //
  588. if (tagName != TAG_VERSION) {
  589. memset(buffer+1, '\0', increment);
  590. }
  591. increment += 1; // length of small tag
  592. } else {
  593. increment = *(USHORT UNALIGNED *)(buffer+1);
  594. memset(buffer+3, '\0', increment);
  595. increment += 3; // length of large tag
  596. }
  597. buffer += increment;
  598. } while (tagName != TAG_END) ;
  599. *Length = (ULONG)(buffer - BiosData) ;
  600. }
  601. PPB_DEPENDENT_RESOURCES
  602. PbAddDependentResourcesToList (
  603. IN OUT PUCHAR *ResourceDescriptor,
  604. IN ULONG ListNo,
  605. IN PPB_ALTERNATIVE_INFORMATION AlternativeList
  606. )
  607. /*++
  608. Routine Description:
  609. This routine adds dependent functions to caller specified list.
  610. Arguments:
  611. ResourceDescriptor - supplies a pointer to the descriptor buffer.
  612. ListNo - supplies an index to the AlternativeList.
  613. AlternativeList - supplies a pointer to the alternativelist array.
  614. Return Value:
  615. return NTSTATUS code to indicate the result of the operation.
  616. --*/
  617. {
  618. PPB_DEPENDENT_RESOURCES dependentResources, ptr;
  619. ULONG size;
  620. //
  621. // Copy dependent resources to caller supplied list buffer and
  622. // update the list buffer pointer.
  623. //
  624. dependentResources = AlternativeList[ListNo].Resources;
  625. size = sizeof(IO_RESOURCE_DESCRIPTOR) * dependentResources->Count;
  626. RtlMoveMemory(*ResourceDescriptor, dependentResources + 1, size);
  627. *ResourceDescriptor = *ResourceDescriptor + size;
  628. //
  629. // Add dependent resource of next list to caller's buffer
  630. //
  631. if (AlternativeList[ListNo + 1].Resources) {
  632. ptr = PbAddDependentResourcesToList(ResourceDescriptor, ListNo + 1, AlternativeList);
  633. } else {
  634. ptr = NULL;
  635. }
  636. if (ptr == NULL) {
  637. AlternativeList[ListNo].Resources = dependentResources->Next;
  638. if (!(dependentResources->Flags & DEPENDENT_FLAGS_END)) {
  639. ptr = dependentResources->Next;
  640. }
  641. }
  642. return ptr;
  643. }
  644. #if NO_PLACEHOLDER_DMA_IRQ_SUPPORT
  645. NTSTATUS
  646. PbBiosIrqToIoDescriptor (
  647. IN OUT PUCHAR *BiosData,
  648. PIO_RESOURCE_DESCRIPTOR IoDescriptor
  649. )
  650. /*++
  651. Routine Description:
  652. This routine translates BIOS IRQ information to NT usable format.
  653. This routine stops when an irq io resource is generated. if there are
  654. more irq io resource descriptors available, the BiosData pointer will
  655. not advance. So caller will pass us the same resource tag again.
  656. Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
  657. for each seperated channel required.
  658. Arguments:
  659. BiosData - Supplies a pointer to the bios resource data buffer.
  660. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  661. Converted resource will be stored here.
  662. Return Value:
  663. return NTSTATUS code to indicate the result of the operation.
  664. --*/
  665. {
  666. static ULONG bitPosition = 0;
  667. USHORT mask;
  668. ULONG irq;
  669. PPNP_IRQ_DESCRIPTOR buffer;
  670. UCHAR size, option;
  671. NTSTATUS status = STATUS_SUCCESS;
  672. buffer = (PPNP_IRQ_DESCRIPTOR)*BiosData;
  673. //
  674. // if this is not the first descriptor for the tag, set
  675. // its option to alternative.
  676. //
  677. if (bitPosition == 0) {
  678. option = 0;
  679. } else {
  680. option = IO_RESOURCE_ALTERNATIVE;
  681. }
  682. size = buffer->Tag & SMALL_TAG_SIZE_MASK;
  683. mask = buffer->IrqMask;
  684. mask >>= bitPosition;
  685. irq = (ULONG) -1;
  686. while (mask) {
  687. if (mask & 1) {
  688. irq = bitPosition;
  689. break;
  690. }
  691. mask >>= 1;
  692. bitPosition++;
  693. }
  694. //
  695. // Fill in Io resource descriptor
  696. //
  697. if (irq != (ULONG)-1) {
  698. IoDescriptor->Option = option;
  699. IoDescriptor->Type = CmResourceTypeInterrupt;
  700. IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  701. IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  702. if (size == 3 && buffer->Information & 0x0C) {
  703. IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
  704. IoDescriptor->ShareDisposition = CmResourceShareShared;
  705. }
  706. IoDescriptor->Spare1 = 0;
  707. IoDescriptor->Spare2 = 0;
  708. IoDescriptor->u.Interrupt.MinimumVector = irq;
  709. IoDescriptor->u.Interrupt.MaximumVector = irq;
  710. } else {
  711. status = STATUS_INVALID_PARAMETER;
  712. }
  713. if (NT_SUCCESS(status)) {
  714. //
  715. // try to move bitPosition to next 1 bit.
  716. //
  717. while (mask) {
  718. mask >>= 1;
  719. bitPosition++;
  720. if (mask & 1) {
  721. return status;
  722. }
  723. }
  724. }
  725. //
  726. // Done with current irq tag, advance pointer to next tag
  727. //
  728. bitPosition = 0;
  729. *BiosData = (PUCHAR)buffer + size + 1;
  730. return status;
  731. }
  732. NTSTATUS
  733. PbBiosDmaToIoDescriptor (
  734. IN OUT PUCHAR *BiosData,
  735. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  736. )
  737. /*++
  738. Routine Description:
  739. This routine translates BIOS DMA information to NT usable format.
  740. This routine stops when an dma io resource is generated. if there are
  741. more dma io resource descriptors available, the BiosData pointer will
  742. not advance. So caller will pass us the same resource tag again.
  743. Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
  744. for each seperated channel required.
  745. Arguments:
  746. BiosData - Supplies a pointer to the bios resource data buffer.
  747. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  748. Converted resource will be stored here.
  749. Return Value:
  750. return NTSTATUS code to indicate the result of the operation.
  751. --*/
  752. {
  753. static ULONG bitPosition = 0;
  754. ULONG dma;
  755. PPNP_DMA_DESCRIPTOR buffer;
  756. UCHAR mask, option;
  757. NTSTATUS status = STATUS_SUCCESS;
  758. buffer = (PPNP_DMA_DESCRIPTOR)*BiosData;
  759. //
  760. // if this is not the first descriptor for the tag, set
  761. // its option to alternative.
  762. //
  763. if (bitPosition == 0) {
  764. option = 0;
  765. } else {
  766. option = IO_RESOURCE_ALTERNATIVE;
  767. }
  768. mask = buffer->ChannelMask;
  769. mask >>= bitPosition;
  770. dma = (ULONG) -1;
  771. while (mask) {
  772. if (mask & 1) {
  773. dma = bitPosition;
  774. break;
  775. }
  776. mask >>= 1;
  777. bitPosition++;
  778. }
  779. //
  780. // Fill in Io resource descriptor
  781. //
  782. if (dma != (ULONG)-1) {
  783. IoDescriptor->Option = option;
  784. IoDescriptor->Type = CmResourceTypeDma;
  785. IoDescriptor->Flags = 0;
  786. IoDescriptor->ShareDisposition = CmResourceShareUndetermined;
  787. IoDescriptor->Spare1 = 0;
  788. IoDescriptor->Spare2 = 0;
  789. IoDescriptor->u.Dma.MinimumChannel = dma;
  790. IoDescriptor->u.Dma.MaximumChannel = dma;
  791. } else {
  792. status = STATUS_INVALID_PARAMETER;
  793. }
  794. if (NT_SUCCESS(status)) {
  795. //
  796. // try to move bitPosition to next 1 bit.
  797. //
  798. while (mask) {
  799. mask >>= 1;
  800. bitPosition++;
  801. if (mask & 1) {
  802. return status;
  803. }
  804. }
  805. }
  806. //
  807. // Done with current dma tag, advance pointer to next tag
  808. //
  809. bitPosition = 0;
  810. buffer += 1;
  811. *BiosData = (PUCHAR)buffer;
  812. return status;
  813. }
  814. #else
  815. NTSTATUS
  816. PbBiosIrqToIoDescriptor (
  817. IN OUT PUCHAR *BiosData,
  818. PIO_RESOURCE_DESCRIPTOR IoDescriptor
  819. )
  820. /*++
  821. Routine Description:
  822. This routine translates BIOS IRQ information to NT usable format.
  823. This routine stops when an irq io resource is generated. if there are
  824. more irq io resource descriptors available, the BiosData pointer will
  825. not advance. So caller will pass us the same resource tag again.
  826. Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
  827. for each seperated channel required.
  828. Arguments:
  829. BiosData - Supplies a pointer to the bios resource data buffer.
  830. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  831. Converted resource will be stored here.
  832. Return Value:
  833. return NTSTATUS code to indicate the result of the operation.
  834. --*/
  835. {
  836. static ULONG bitPosition = 0;
  837. USHORT mask;
  838. ULONG irq;
  839. PPNP_IRQ_DESCRIPTOR buffer;
  840. UCHAR size, option;
  841. buffer = (PPNP_IRQ_DESCRIPTOR)*BiosData;
  842. //
  843. // if this is not the first descriptor for the tag, set
  844. // its option to alternative.
  845. //
  846. if (bitPosition == 0) {
  847. option = 0;
  848. } else {
  849. option = IO_RESOURCE_ALTERNATIVE;
  850. }
  851. size = buffer->Tag & SMALL_TAG_SIZE_MASK;
  852. mask = buffer->IrqMask;
  853. mask >>= bitPosition;
  854. irq = (ULONG) -1;
  855. while (mask) {
  856. if (mask & 1) {
  857. irq = bitPosition;
  858. break;
  859. }
  860. mask >>= 1;
  861. bitPosition++;
  862. }
  863. //
  864. // Fill in Io resource descriptor
  865. //
  866. IoDescriptor->Option = option;
  867. IoDescriptor->Type = CmResourceTypeInterrupt;
  868. IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  869. IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  870. if (size == 3 && buffer->Information & 0x0C) {
  871. IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
  872. IoDescriptor->ShareDisposition = CmResourceShareShared;
  873. }
  874. IoDescriptor->Spare1 = 0;
  875. IoDescriptor->Spare2 = 0;
  876. IoDescriptor->u.Interrupt.MinimumVector = irq;
  877. IoDescriptor->u.Interrupt.MaximumVector = irq;
  878. //
  879. // try to move bitPosition to next 1 bit.
  880. //
  881. while (mask) {
  882. mask >>= 1;
  883. bitPosition++;
  884. if (mask & 1) {
  885. return STATUS_SUCCESS;
  886. }
  887. }
  888. //
  889. // Done with current irq tag, advance pointer to next tag
  890. //
  891. bitPosition = 0;
  892. *BiosData = (PUCHAR)buffer + size + 1;
  893. return STATUS_SUCCESS;
  894. }
  895. NTSTATUS
  896. PbBiosDmaToIoDescriptor (
  897. IN OUT PUCHAR *BiosData,
  898. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  899. )
  900. /*++
  901. Routine Description:
  902. This routine translates BIOS DMA information to NT usable format.
  903. This routine stops when an dma io resource is generated. if there are
  904. more dma io resource descriptors available, the BiosData pointer will
  905. not advance. So caller will pass us the same resource tag again.
  906. Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
  907. for each seperated channel required.
  908. Arguments:
  909. BiosData - Supplies a pointer to the bios resource data buffer.
  910. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  911. Converted resource will be stored here.
  912. Return Value:
  913. return NTSTATUS code to indicate the result of the operation.
  914. --*/
  915. {
  916. static ULONG bitPosition = 0;
  917. ULONG dma;
  918. PPNP_DMA_DESCRIPTOR buffer;
  919. UCHAR mask, option;
  920. buffer = (PPNP_DMA_DESCRIPTOR)*BiosData;
  921. //
  922. // if this is not the first descriptor for the tag, set
  923. // its option to alternative.
  924. //
  925. if (bitPosition == 0) {
  926. option = 0;
  927. } else {
  928. option = IO_RESOURCE_ALTERNATIVE;
  929. }
  930. mask = buffer->ChannelMask;
  931. mask >>= bitPosition;
  932. dma = (ULONG) -1;
  933. while (mask) {
  934. if (mask & 1) {
  935. dma = bitPosition;
  936. break;
  937. }
  938. mask >>= 1;
  939. bitPosition++;
  940. }
  941. //
  942. // Fill in Io resource descriptor
  943. //
  944. IoDescriptor->Option = option;
  945. IoDescriptor->Type = CmResourceTypeDma;
  946. IoDescriptor->Flags = 0;
  947. IoDescriptor->ShareDisposition = CmResourceShareUndetermined;
  948. IoDescriptor->Spare1 = 0;
  949. IoDescriptor->Spare2 = 0;
  950. IoDescriptor->u.Dma.MinimumChannel = dma;
  951. IoDescriptor->u.Dma.MaximumChannel = dma;
  952. //
  953. // try to move bitPosition to next 1 bit.
  954. //
  955. while (mask) {
  956. mask >>= 1;
  957. bitPosition++;
  958. if (mask & 1) {
  959. return STATUS_SUCCESS;
  960. }
  961. }
  962. //
  963. // Done with current dma tag, advance pointer to next tag
  964. //
  965. bitPosition = 0;
  966. buffer += 1;
  967. *BiosData = (PUCHAR)buffer;
  968. return STATUS_SUCCESS;
  969. }
  970. #endif
  971. NTSTATUS
  972. PbBiosPortFixedToIoDescriptor (
  973. IN OUT PUCHAR *BiosData,
  974. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
  975. IN BOOLEAN ForceFixedIoTo16bit
  976. )
  977. /*++
  978. Routine Description:
  979. This routine translates BIOS FIXED IO information to NT usable format.
  980. Arguments:
  981. BiosData - Supplies a pointer to the bios resource data buffer.
  982. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  983. Converted resource will be stored here.
  984. ForceFixedIoTo16bit - hack option to force fixed I/O resources to 16bit
  985. for far too pessimistic BIOS's.
  986. Return Value:
  987. return NTSTATUS code to indicate the result of the operation.
  988. --*/
  989. {
  990. PPNP_FIXED_PORT_DESCRIPTOR buffer;
  991. buffer = (PPNP_FIXED_PORT_DESCRIPTOR)*BiosData;
  992. //
  993. // Fill in Io resource descriptor
  994. //
  995. IoDescriptor->Option = 0;
  996. IoDescriptor->Type = CmResourceTypePort;
  997. if (ForceFixedIoTo16bit) {
  998. IoDescriptor->Flags = CM_RESOURCE_PORT_IO + CM_RESOURCE_PORT_16_BIT_DECODE;
  999. } else {
  1000. IoDescriptor->Flags = CM_RESOURCE_PORT_IO + CM_RESOURCE_PORT_10_BIT_DECODE;
  1001. }
  1002. #if defined(_X86_)
  1003. //
  1004. // Workaround:
  1005. // NEC PC9800 series's PnPBIOS report I/O resources between 0x00 and 0xFF as FIXED IO.
  1006. // But These resources are 16bit DECODE resource, not 10bit DECODE one. We need to check
  1007. // the range of I/O resources .
  1008. //
  1009. if (IsNEC_98) {
  1010. if ( (ULONG)buffer->MinimumAddress < 0x100 ) {
  1011. IoDescriptor->Flags = CM_RESOURCE_PORT_IO + CM_RESOURCE_PORT_16_BIT_DECODE;
  1012. }
  1013. }
  1014. #endif // <--end changing code
  1015. IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  1016. IoDescriptor->Spare1 = 0;
  1017. IoDescriptor->Spare2 = 0;
  1018. IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
  1019. IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)(buffer->MinimumAddress & 0x3ff);
  1020. IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
  1021. IoDescriptor->u.Port.MaximumAddress.LowPart = IoDescriptor->u.Port.MinimumAddress.LowPart +
  1022. IoDescriptor->u.Port.Length - 1;
  1023. IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
  1024. IoDescriptor->u.Port.Alignment = 1;
  1025. //
  1026. // Done with current fixed port tag, advance pointer to next tag
  1027. //
  1028. buffer += 1;
  1029. *BiosData = (PUCHAR)buffer;
  1030. return STATUS_SUCCESS;
  1031. }
  1032. NTSTATUS
  1033. PbBiosPortToIoDescriptor (
  1034. IN OUT PUCHAR *BiosData,
  1035. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  1036. )
  1037. /*++
  1038. Routine Description:
  1039. This routine translates BIOS IO information to NT usable format.
  1040. Arguments:
  1041. BiosData - Supplies a pointer to the bios resource data buffer.
  1042. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  1043. Converted resource will be stored here.
  1044. Return Value:
  1045. return NTSTATUS code to indicate the result of the operation.
  1046. --*/
  1047. {
  1048. PPNP_PORT_DESCRIPTOR buffer;
  1049. buffer = (PPNP_PORT_DESCRIPTOR)*BiosData;
  1050. //
  1051. // Fill in Io resource descriptor
  1052. //
  1053. IoDescriptor->Option = 0;
  1054. IoDescriptor->Type = CmResourceTypePort;
  1055. IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
  1056. if (buffer->Information & 1) {
  1057. IoDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
  1058. } else {
  1059. IoDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
  1060. }
  1061. IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  1062. IoDescriptor->Spare1 = 0;
  1063. IoDescriptor->Spare2 = 0;
  1064. IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
  1065. #if defined(_X86_)
  1066. if (IsNEC_98) {
  1067. if (buffer->Information & 0x80) {
  1068. IoDescriptor->u.Port.Length *= 2;
  1069. }
  1070. }
  1071. #endif
  1072. IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)buffer->MinimumAddress;
  1073. IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
  1074. IoDescriptor->u.Port.MaximumAddress.LowPart = (ULONG)buffer->MaximumAddress +
  1075. IoDescriptor->u.Port.Length - 1;
  1076. IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
  1077. IoDescriptor->u.Port.Alignment = (ULONG)buffer->Alignment;
  1078. //
  1079. // Done with current fixed port tag, advance pointer to next tag
  1080. //
  1081. buffer += 1;
  1082. *BiosData = (PUCHAR)buffer;
  1083. return STATUS_SUCCESS;
  1084. }
  1085. NTSTATUS
  1086. PbBiosMemoryToIoDescriptor (
  1087. IN OUT PUCHAR *BiosData,
  1088. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  1089. )
  1090. /*++
  1091. Routine Description:
  1092. This routine translates BIOS MEMORY information to NT usable format.
  1093. Arguments:
  1094. BiosData - Supplies a pointer to the bios resource data buffer.
  1095. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  1096. Converted resource will be stored here.
  1097. Return Value:
  1098. return NTSTATUS code to indicate the result of the operation.
  1099. --*/
  1100. {
  1101. PUCHAR buffer;
  1102. UCHAR tag;
  1103. PHYSICAL_ADDRESS minAddr, maxAddr;
  1104. ULONG alignment, length;
  1105. USHORT increment;
  1106. USHORT flags = 0;
  1107. buffer = *BiosData;
  1108. tag = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Tag;
  1109. increment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Length + 3; // larg tag size = 3
  1110. minAddr.HighPart = 0;
  1111. maxAddr.HighPart = 0;
  1112. switch (tag) {
  1113. case TAG_MEMORY:
  1114. minAddr.LowPart = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MinimumAddress)) << 8;
  1115. if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Alignment) == 0) {
  1116. alignment = 0x10000;
  1117. }
  1118. length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MemorySize)) << 8;
  1119. maxAddr.LowPart = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MaximumAddress)) << 8) + length - 1;
  1120. flags = CM_RESOURCE_MEMORY_24;
  1121. break;
  1122. case TAG_MEMORY32:
  1123. length = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
  1124. minAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MinimumAddress;
  1125. maxAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MaximumAddress + length - 1;
  1126. alignment = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->Alignment;
  1127. break;
  1128. case TAG_MEMORY32_FIXED:
  1129. length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
  1130. minAddr.LowPart = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->BaseAddress;
  1131. maxAddr.LowPart = minAddr.LowPart + length - 1;
  1132. alignment = 1;
  1133. break;
  1134. }
  1135. //
  1136. // Fill in Io resource descriptor
  1137. //
  1138. IoDescriptor->Option = 0;
  1139. IoDescriptor->Type = CmResourceTypeMemory;
  1140. IoDescriptor->Flags = CM_RESOURCE_PORT_MEMORY + flags;
  1141. IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  1142. IoDescriptor->Spare1 = 0;
  1143. IoDescriptor->Spare2 = 0;
  1144. IoDescriptor->u.Memory.MinimumAddress = minAddr;
  1145. IoDescriptor->u.Memory.MaximumAddress = maxAddr;
  1146. IoDescriptor->u.Memory.Alignment = alignment;
  1147. IoDescriptor->u.Memory.Length = length;
  1148. //
  1149. // Done with current tag, advance pointer to next tag
  1150. //
  1151. buffer += increment;
  1152. *BiosData = (PUCHAR)buffer;
  1153. return STATUS_SUCCESS;
  1154. }
  1155. NTSTATUS
  1156. PpCmResourcesToBiosResources (
  1157. IN PCM_RESOURCE_LIST CmResources,
  1158. IN PUCHAR BiosRequirements,
  1159. IN PUCHAR *BiosResources,
  1160. IN PULONG Length
  1161. )
  1162. /*++
  1163. Routine Description:
  1164. This routine parses the Cm resource list and generates
  1165. a Pnp BIOS resource list. It is caller's responsibility to release the
  1166. returned data buffer.
  1167. Arguments:
  1168. CmResources - Supplies a pointer to a Cm resource list buffer.
  1169. BiosRequirements - supplies a pointer to the PnP BIOS possible resources.
  1170. BiosResources - Supplies a variable to receive the pointer to the
  1171. converted bios resource buffer.
  1172. Length - supplies a pointer to a variable to receive the length
  1173. of the Pnp Bios resources.
  1174. Return Value:
  1175. a pointer to a Pnp Bios resource list if succeeded. Else,
  1176. a NULL pointer will be returned.
  1177. --*/
  1178. {
  1179. PCM_FULL_RESOURCE_DESCRIPTOR cmFullDesc;
  1180. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDesc;
  1181. ULONG i, l, count, length, totalSize = 0;
  1182. PUCHAR p, px;
  1183. PNP_MEMORY_DESCRIPTOR biosDesc;
  1184. NTSTATUS status;
  1185. *BiosResources = NULL;
  1186. *Length = 0;
  1187. CmResources->Count;
  1188. if (CmResources->Count == 0) {
  1189. return STATUS_SUCCESS;
  1190. }
  1191. //
  1192. // Determine pool size needed
  1193. //
  1194. count = 0;
  1195. cmFullDesc = &CmResources->List[0];
  1196. for (l = 0; l < CmResources->Count; l++) {
  1197. cmDesc = cmFullDesc->PartialResourceList.PartialDescriptors;
  1198. for (i = 0; i < cmFullDesc->PartialResourceList.Count; i++) {
  1199. switch (cmDesc->Type) {
  1200. case CmResourceTypePort:
  1201. case CmResourceTypeInterrupt:
  1202. case CmResourceTypeMemory:
  1203. case CmResourceTypeDma:
  1204. count++;
  1205. cmDesc++;
  1206. break;
  1207. case CmResourceTypeDeviceSpecific:
  1208. length = cmDesc->u.DeviceSpecificData.DataSize;
  1209. cmDesc++;
  1210. cmDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmDesc + length);
  1211. }
  1212. }
  1213. cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmDesc;
  1214. }
  1215. if (count == 0) {
  1216. return STATUS_SUCCESS;
  1217. }
  1218. //
  1219. // Allocate max amount of memory
  1220. //
  1221. px = p= ExAllocatePoolWithTag(PagedPool,
  1222. count * sizeof(PNP_MEMORY_DESCRIPTOR),
  1223. 'bPnP');
  1224. if (!p) {
  1225. return STATUS_INSUFFICIENT_RESOURCES;
  1226. }
  1227. status = STATUS_RESOURCE_TYPE_NOT_FOUND;
  1228. cmFullDesc = &CmResources->List[0];
  1229. for (l = 0; l < CmResources->Count; l++) {
  1230. cmDesc = cmFullDesc->PartialResourceList.PartialDescriptors;
  1231. for (i = 0; i < cmFullDesc->PartialResourceList.Count; i++) {
  1232. switch (cmDesc->Type) {
  1233. case CmResourceTypePort:
  1234. status = PbCmPortToBiosDescriptor (
  1235. BiosRequirements,
  1236. cmDesc,
  1237. &biosDesc,
  1238. &length
  1239. );
  1240. break;
  1241. case CmResourceTypeInterrupt:
  1242. status = PbCmIrqToBiosDescriptor(
  1243. BiosRequirements,
  1244. cmDesc,
  1245. &biosDesc,
  1246. &length
  1247. );
  1248. break;
  1249. case CmResourceTypeMemory:
  1250. status = PbCmMemoryToBiosDescriptor (
  1251. BiosRequirements,
  1252. cmDesc,
  1253. &biosDesc,
  1254. &length
  1255. );
  1256. break;
  1257. case CmResourceTypeDma:
  1258. status = PbCmDmaToBiosDescriptor (
  1259. BiosRequirements,
  1260. cmDesc,
  1261. &biosDesc,
  1262. &length
  1263. );
  1264. break;
  1265. case CmResourceTypeDeviceSpecific:
  1266. length = cmDesc->u.DeviceSpecificData.DataSize;
  1267. cmDesc++;
  1268. cmDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmDesc + length);
  1269. continue;
  1270. }
  1271. if (NT_SUCCESS(status)) {
  1272. cmDesc++;
  1273. RtlCopyMemory(p, &biosDesc, length);
  1274. p += length;
  1275. totalSize += length;
  1276. } else {
  1277. ExFreePool(px);
  1278. goto exit;
  1279. }
  1280. }
  1281. cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmDesc;
  1282. }
  1283. exit:
  1284. if (NT_SUCCESS(status)) {
  1285. *p = TAG_COMPLETE_END;
  1286. p++;
  1287. *p = 0; // checksum ignored
  1288. totalSize += 2;
  1289. *BiosResources = px;
  1290. *Length = totalSize;
  1291. }
  1292. return status;
  1293. }
  1294. NTSTATUS
  1295. PbCmIrqToBiosDescriptor (
  1296. IN PUCHAR BiosRequirements,
  1297. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
  1298. OUT PVOID ReturnDescriptor,
  1299. OUT PULONG Length
  1300. )
  1301. /*++
  1302. Routine Description:
  1303. This routine translates CM IRQ information to Pnp BIOS format.
  1304. Since there is not enough information in the CM int descriptor to
  1305. convert it to Pnp BIOS descriptor. We will search the Bios
  1306. possible resource lists for the corresponding resource information.
  1307. Arguments:
  1308. BiosRequirements - Supplies a pointer to the bios possible resource lists.
  1309. CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
  1310. ReturnDescriptor - Supplies a buffer to receive the returned BIOS descriptor.
  1311. Length - Supplies a variable to receive the length of the returned bios descriptor.
  1312. Return Value:
  1313. return a pointer to the desired dma descriptor in the BiosRequirements. Null
  1314. if not found.
  1315. --*/
  1316. {
  1317. USHORT irqMask;
  1318. UCHAR tag;
  1319. PPNP_IRQ_DESCRIPTOR biosDesc;
  1320. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1321. ULONG increment;
  1322. PPNP_IRQ_DESCRIPTOR irqDesc = (PPNP_IRQ_DESCRIPTOR)ReturnDescriptor;
  1323. if (!(CmDescriptor->u.Interrupt.Level & 0xfffffff0)) {
  1324. irqMask = (USHORT)(1 << CmDescriptor->u.Interrupt.Level);
  1325. } else {
  1326. return STATUS_INVALID_PARAMETER;
  1327. }
  1328. if (!BiosRequirements) {
  1329. irqDesc->Tag = TAG_IRQ | (sizeof(PNP_IRQ_DESCRIPTOR) - 2); // No Information
  1330. irqDesc->IrqMask = irqMask;
  1331. *Length = sizeof(PNP_IRQ_DESCRIPTOR) - 1;
  1332. status = STATUS_SUCCESS;
  1333. } else {
  1334. tag = *BiosRequirements;
  1335. while (tag != TAG_COMPLETE_END) {
  1336. if ((tag & SMALL_TAG_MASK) == TAG_IRQ) {
  1337. biosDesc = (PPNP_IRQ_DESCRIPTOR)BiosRequirements;
  1338. if (biosDesc->IrqMask & irqMask) {
  1339. *Length = (biosDesc->Tag & SMALL_TAG_SIZE_MASK) + 1;
  1340. RtlCopyMemory(ReturnDescriptor, BiosRequirements, *Length);
  1341. ((PPNP_IRQ_DESCRIPTOR)ReturnDescriptor)->IrqMask = irqMask;
  1342. status = STATUS_SUCCESS;
  1343. break;
  1344. }
  1345. }
  1346. //
  1347. // Don't-care tag simply advance the buffer pointer to next tag.
  1348. //
  1349. if (tag & LARGE_RESOURCE_TAG) {
  1350. increment = *(USHORT UNALIGNED *)(BiosRequirements + 1);
  1351. increment += 3; // length of large tag
  1352. } else {
  1353. increment = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
  1354. increment += 1; // length of small tag
  1355. }
  1356. BiosRequirements += increment;
  1357. tag = *BiosRequirements;
  1358. }
  1359. }
  1360. return status;
  1361. }
  1362. NTSTATUS
  1363. PbCmDmaToBiosDescriptor (
  1364. IN PUCHAR BiosRequirements,
  1365. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
  1366. OUT PVOID ReturnDescriptor,
  1367. OUT PULONG Length
  1368. )
  1369. /*++
  1370. Routine Description:
  1371. This routine translates CM DMA information to Pnp BIOS format.
  1372. Since there is not enough information in the CM descriptor to
  1373. convert it to Pnp BIOS descriptor. We will search the Bios
  1374. possible resource lists for the corresponding resource information.
  1375. Arguments:
  1376. BiosRequirements - Supplies a pointer to the bios possible resource lists.
  1377. CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
  1378. BiosDescriptor - Supplies a variable to receive the returned BIOS descriptor.
  1379. Length - Supplies a variable to receive the length of the returned bios descriptor.
  1380. Return Value:
  1381. return a pointer to the desired dma descriptor in the BiosRequirements. Null
  1382. if not found.
  1383. --*/
  1384. {
  1385. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1386. UCHAR dmaMask, tag;
  1387. PPNP_DMA_DESCRIPTOR biosDesc;
  1388. ULONG increment;
  1389. PPNP_DMA_DESCRIPTOR dmaDesc = (PPNP_DMA_DESCRIPTOR)ReturnDescriptor;
  1390. USHORT flags = CmDescriptor->Flags;
  1391. if (!(CmDescriptor->u.Dma.Channel & 0xfffffff0)) {
  1392. dmaMask = (UCHAR)(1 << CmDescriptor->u.Dma.Channel);
  1393. } else {
  1394. return STATUS_INVALID_PARAMETER;
  1395. }
  1396. if (!BiosRequirements) {
  1397. dmaDesc->Tag = TAG_DMA | (sizeof(PNP_DMA_DESCRIPTOR) - 1);
  1398. dmaDesc->ChannelMask = dmaMask;
  1399. dmaDesc->Flags = 0;
  1400. if (flags & CM_RESOURCE_DMA_8_AND_16) {
  1401. dmaDesc->Flags += 1;
  1402. } else if (flags & CM_RESOURCE_DMA_16) {
  1403. dmaDesc->Flags += 2;
  1404. }
  1405. if (flags & CM_RESOURCE_DMA_BUS_MASTER) {
  1406. dmaDesc->Flags += 4;
  1407. }
  1408. if (flags & CM_RESOURCE_DMA_TYPE_A) {
  1409. dmaDesc->Flags += 32;
  1410. }
  1411. if (flags & CM_RESOURCE_DMA_TYPE_B) {
  1412. dmaDesc->Flags += 64;
  1413. }
  1414. if (flags & CM_RESOURCE_DMA_TYPE_F) {
  1415. dmaDesc->Flags += 96;
  1416. }
  1417. *Length = sizeof(PNP_DMA_DESCRIPTOR);
  1418. status = STATUS_SUCCESS;
  1419. } else {
  1420. tag = *BiosRequirements;
  1421. while (tag != TAG_COMPLETE_END) {
  1422. if ((tag & SMALL_TAG_MASK) == TAG_DMA) {
  1423. biosDesc = (PPNP_DMA_DESCRIPTOR)BiosRequirements;
  1424. if (biosDesc->ChannelMask & dmaMask) {
  1425. *Length = (biosDesc->Tag & SMALL_TAG_SIZE_MASK) + 1;
  1426. RtlMoveMemory(ReturnDescriptor, BiosRequirements, *Length);
  1427. ((PPNP_DMA_DESCRIPTOR)ReturnDescriptor)->ChannelMask = dmaMask;
  1428. status = STATUS_SUCCESS;
  1429. break;
  1430. }
  1431. }
  1432. //
  1433. // Don't-care tag simply advance the buffer pointer to next tag.
  1434. //
  1435. if (tag & LARGE_RESOURCE_TAG) {
  1436. increment = *(USHORT UNALIGNED *)(BiosRequirements + 1);
  1437. increment += 3; // length of large tag
  1438. } else {
  1439. increment = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
  1440. increment += 1; // length of small tag
  1441. }
  1442. BiosRequirements += increment;
  1443. tag = *BiosRequirements;
  1444. }
  1445. }
  1446. return status;
  1447. }
  1448. NTSTATUS
  1449. PbCmPortToBiosDescriptor (
  1450. IN PUCHAR BiosRequirements,
  1451. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
  1452. OUT PVOID ReturnDescriptor,
  1453. OUT PULONG Length
  1454. )
  1455. /*++
  1456. Routine Description:
  1457. This routine translates CM PORT information to Pnp BIOS format.
  1458. Since there is not enough information in the CM descriptor to
  1459. convert it to Pnp BIOS full function port descriptor. We will
  1460. convert it to Pnp Bios fixed PORT descriptor. It is caller's
  1461. responsibility to release the returned data buffer.
  1462. Arguments:
  1463. CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
  1464. BiosDescriptor - supplies a variable to receive the buffer which contains
  1465. the desired Bios Port descriptor.
  1466. Length - supplies a variable to receive the size the returned bios port
  1467. descriptor.
  1468. ReturnDescriptor - supplies a buffer to receive the desired Bios Port descriptor.
  1469. Length - Supplies a variable to receive the length of the returned bios descriptor.
  1470. Return Value:
  1471. A NTSTATUS code.
  1472. --*/
  1473. {
  1474. PPNP_PORT_DESCRIPTOR portDesc = (PPNP_PORT_DESCRIPTOR)ReturnDescriptor;
  1475. USHORT minAddr, maxAddr, address;
  1476. UCHAR alignment, length, size, information, tag, returnTag;
  1477. USHORT increment;
  1478. BOOLEAN test = FALSE;
  1479. if (CmDescriptor->u.Port.Start.HighPart != 0 ||
  1480. CmDescriptor->u.Port.Start.LowPart & 0xffff0000 ||
  1481. CmDescriptor->u.Port.Length & 0xffffff00) {
  1482. return STATUS_INVALID_PARAMETER;
  1483. }
  1484. //
  1485. // Search the possible resource list to get the information
  1486. // for the port range described by CmDescriptor.
  1487. //
  1488. address = (USHORT) CmDescriptor->u.Port.Start.LowPart;
  1489. size = (UCHAR) CmDescriptor->u.Port.Length;
  1490. if (!BiosRequirements) {
  1491. //
  1492. // No BiosRequirement. Use TAG_IO as default.
  1493. //
  1494. portDesc->Tag = TAG_IO | (sizeof(PNP_PORT_DESCRIPTOR) - 1);
  1495. if (CmDescriptor->Flags & CM_RESOURCE_PORT_16_BIT_DECODE) {
  1496. portDesc->Information = 1;
  1497. } else {
  1498. portDesc->Information = 0;
  1499. }
  1500. portDesc->Length = size;
  1501. portDesc->Alignment = 1;
  1502. portDesc->MinimumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
  1503. portDesc->MaximumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
  1504. *Length = sizeof(PNP_PORT_DESCRIPTOR);
  1505. } else {
  1506. tag = *BiosRequirements;
  1507. while (tag != TAG_COMPLETE_END) {
  1508. test = FALSE;
  1509. switch (tag & SMALL_TAG_MASK) {
  1510. case TAG_IO:
  1511. minAddr = ((PPNP_PORT_DESCRIPTOR)BiosRequirements)->MinimumAddress;
  1512. alignment = ((PPNP_PORT_DESCRIPTOR)BiosRequirements)->Alignment;
  1513. length = ((PPNP_PORT_DESCRIPTOR)BiosRequirements)->Length;
  1514. maxAddr = ((PPNP_PORT_DESCRIPTOR)BiosRequirements)->MaximumAddress;
  1515. information = ((PPNP_PORT_DESCRIPTOR)BiosRequirements)->Information;
  1516. test = TRUE;
  1517. returnTag = TAG_IO;
  1518. if (!alignment) {
  1519. if (minAddr == maxAddr) {
  1520. //
  1521. // If the max is equal to the min, the alignment is
  1522. // meaningless. As we told OEMs 0 is appropriate here,
  1523. // let us handle it.
  1524. //
  1525. alignment = 1 ;
  1526. }
  1527. }
  1528. maxAddr += length - 1;
  1529. break;
  1530. case TAG_IO_FIXED:
  1531. length = ((PPNP_FIXED_PORT_DESCRIPTOR)BiosRequirements)->Length;
  1532. minAddr = ((PPNP_FIXED_PORT_DESCRIPTOR)BiosRequirements)->MinimumAddress;
  1533. maxAddr = minAddr + length - 1;
  1534. alignment = 1;
  1535. information = 0; // 10 bit decode
  1536. returnTag = TAG_IO_FIXED;
  1537. test = TRUE;
  1538. break;
  1539. }
  1540. if (test) {
  1541. if (minAddr <= address && maxAddr >= (address + size - 1) && !(address & (alignment - 1 ))) {
  1542. break;
  1543. }
  1544. test = FALSE;
  1545. }
  1546. //
  1547. // Advance to next tag
  1548. //
  1549. if (tag & LARGE_RESOURCE_TAG) {
  1550. increment = *(USHORT UNALIGNED *)(BiosRequirements + 1);
  1551. increment += 3; // length of large tag
  1552. } else {
  1553. increment = (USHORT) tag & SMALL_TAG_SIZE_MASK;
  1554. increment += 1; // length of small tag
  1555. }
  1556. BiosRequirements += increment;
  1557. tag = *BiosRequirements;
  1558. }
  1559. if (tag == TAG_COMPLETE_END) {
  1560. return STATUS_UNSUCCESSFUL;
  1561. }
  1562. //
  1563. // Set the return port descriptor
  1564. //
  1565. if (returnTag == TAG_IO) {
  1566. portDesc->Tag = TAG_IO + (sizeof(PNP_PORT_DESCRIPTOR) - 1);
  1567. portDesc->Information = information;
  1568. portDesc->Length = size;
  1569. portDesc->Alignment = alignment;
  1570. portDesc->MinimumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
  1571. portDesc->MaximumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
  1572. *Length = sizeof(PNP_PORT_DESCRIPTOR);
  1573. } else {
  1574. PPNP_FIXED_PORT_DESCRIPTOR fixedPortDesc = (PPNP_FIXED_PORT_DESCRIPTOR)ReturnDescriptor;
  1575. fixedPortDesc->Tag = TAG_IO_FIXED + (sizeof(PPNP_FIXED_PORT_DESCRIPTOR) - 1);
  1576. fixedPortDesc->MinimumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
  1577. fixedPortDesc->Length = size;
  1578. *Length = sizeof(PNP_FIXED_PORT_DESCRIPTOR);
  1579. }
  1580. }
  1581. return STATUS_SUCCESS;
  1582. }
  1583. NTSTATUS
  1584. PbCmMemoryToBiosDescriptor (
  1585. IN PUCHAR BiosRequirements,
  1586. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
  1587. OUT PVOID ReturnDescriptor,
  1588. OUT PULONG Length
  1589. )
  1590. /*++
  1591. Routine Description:
  1592. This routine translates CM Memory information to Pnp BIOS format.
  1593. Since there is not enough information in the CM descriptor to
  1594. convert it to Pnp BIOS descriptor. We will search the Bios
  1595. possible resource lists for the corresponding resource information and
  1596. build a Pnp BIOS memory descriptor from there. It is caller's responsibility
  1597. to release the returned buffer.
  1598. Arguments:
  1599. BiosRequirements - Supplies a pointer to the bios possible resource lists.
  1600. CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
  1601. ReturnDescriptor - supplies a buffer to receive the desired Bios Memory descriptor.
  1602. Length - supplies a variable to receive the size the returned bios port
  1603. descriptor.
  1604. Return Value:
  1605. A NTSTATUS code.
  1606. --*/
  1607. {
  1608. UCHAR tag, information;
  1609. PPNP_FIXED_MEMORY32_DESCRIPTOR memoryDesc = (PPNP_FIXED_MEMORY32_DESCRIPTOR)ReturnDescriptor;
  1610. ULONG address, size, length, minAddr, maxAddr, alignment;
  1611. USHORT increment;
  1612. BOOLEAN test = FALSE;
  1613. //
  1614. // Search the possible resource list to get the information
  1615. // for the memory range described by CmDescriptor.
  1616. //
  1617. address = CmDescriptor->u.Memory.Start.LowPart;
  1618. size = CmDescriptor->u.Memory.Length;
  1619. if (!BiosRequirements) {
  1620. //
  1621. // We don't support reserving legacy device's memory ranges from PNP
  1622. // BIOS. There isn't really any reason why not it just wasn't
  1623. // implemented for Windows 2000. It isn't near as necessary as it is
  1624. // for I/O ports since ROM memory has a signature and is self
  1625. // describing.
  1626. //
  1627. *Length = 0;
  1628. return STATUS_SUCCESS;
  1629. }
  1630. tag = *BiosRequirements;
  1631. while (tag != TAG_COMPLETE_END) {
  1632. switch (tag & SMALL_TAG_MASK) {
  1633. case TAG_MEMORY:
  1634. minAddr = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MinimumAddress)) << 8;
  1635. if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->Alignment) == 0) {
  1636. alignment = 0x10000;
  1637. }
  1638. length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MemorySize)) << 8;
  1639. maxAddr = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MaximumAddress)) << 8)
  1640. + length - 1;
  1641. test = TRUE;
  1642. break;
  1643. case TAG_MEMORY32:
  1644. length = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
  1645. minAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MinimumAddress;
  1646. maxAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MaximumAddress
  1647. + length - 1;
  1648. alignment = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Alignment;
  1649. break;
  1650. case TAG_MEMORY32_FIXED:
  1651. length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
  1652. minAddr = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->BaseAddress;
  1653. maxAddr = minAddr + length - 1;
  1654. alignment = 1;
  1655. test = TRUE;
  1656. break;
  1657. }
  1658. if (test) {
  1659. if (minAddr <= address && maxAddr >= (address + size - 1) && !(address & (alignment - 1 ))) {
  1660. information = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Information;
  1661. break;
  1662. }
  1663. test = FALSE;
  1664. }
  1665. //
  1666. // Advance to next tag
  1667. //
  1668. if (tag & LARGE_RESOURCE_TAG) {
  1669. increment = *(USHORT UNALIGNED *)(BiosRequirements + 1);
  1670. increment += 3; // length of large tag
  1671. } else {
  1672. increment = (USHORT) tag & SMALL_TAG_SIZE_MASK;
  1673. increment += 1; // length of small tag
  1674. }
  1675. BiosRequirements += increment;
  1676. tag = *BiosRequirements;
  1677. }
  1678. if (tag == TAG_COMPLETE_END) {
  1679. return STATUS_UNSUCCESSFUL;
  1680. }
  1681. //
  1682. // Set up Pnp BIOS memory descriptor
  1683. //
  1684. memoryDesc->Tag = TAG_MEMORY32_FIXED;
  1685. memoryDesc->Length = sizeof (PNP_FIXED_MEMORY32_DESCRIPTOR);
  1686. memoryDesc->Information = information;
  1687. memoryDesc->BaseAddress = address;
  1688. memoryDesc->MemorySize = size;
  1689. *Length = sizeof(PNP_FIXED_MEMORY32_DESCRIPTOR);
  1690. return STATUS_SUCCESS;
  1691. }