Windows NT 4.0 source code leak
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.

1092 lines
30 KiB

4 years ago
  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. --*/
  14. #include "busp.h"
  15. #include "pnpisa.h"
  16. #include "pbios.h"
  17. //
  18. // internal structures for resource translation
  19. //
  20. typedef struct _PB_DEPENDENT_RESOURCES {
  21. ULONG Count;
  22. UCHAR Flags;
  23. UCHAR Priority;
  24. struct _PB_DEPENDENT_RESOURCES *Next;
  25. } PB_DEPENDENT_RESOURCES, *PPB_DEPENDENT_RESOURCES;
  26. #define DEPENDENT_FLAGS_END 1
  27. typedef struct _PB_ATERNATIVE_INFORMATION {
  28. PPB_DEPENDENT_RESOURCES Resources;
  29. ULONG NoDependentFunctions;
  30. ULONG TotalResourceCount;
  31. } PB_ALTERNATIVE_INFORMATION, *PPB_ALTERNATIVE_INFORMATION;
  32. //
  33. // Internal function references
  34. //
  35. VOID
  36. PbIoDescriptorToCmDescriptor (
  37. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
  38. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
  39. );
  40. PPB_DEPENDENT_RESOURCES
  41. PbAddDependentResourcesToList (
  42. IN OUT PUCHAR *ResourceDescriptor,
  43. IN ULONG ListNo,
  44. IN PPB_ALTERNATIVE_INFORMATION AlternativeList
  45. );
  46. NTSTATUS
  47. PbBiosIrqToIoDescriptor (
  48. IN OUT PUCHAR *BiosData,
  49. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  50. );
  51. NTSTATUS
  52. PbBiosDmaToIoDescriptor (
  53. IN OUT PUCHAR *BiosData,
  54. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  55. );
  56. NTSTATUS
  57. PbBiosPortFixedToIoDescriptor (
  58. IN OUT PUCHAR *BiosData,
  59. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  60. );
  61. NTSTATUS
  62. PbBiosPortToIoDescriptor (
  63. IN OUT PUCHAR *BiosData,
  64. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  65. );
  66. NTSTATUS
  67. PbBiosMemoryToIoDescriptor (
  68. IN OUT PUCHAR *BiosData,
  69. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  70. );
  71. #ifdef ALLOC_PRAGMA
  72. #pragma alloc_text(INIT,PbBiosResourcesToNtResources)
  73. #pragma alloc_text(INIT,PbIoDescriptorToCmDescriptor)
  74. #pragma alloc_text(INIT,PbAddDependentResourcesToList)
  75. #pragma alloc_text(INIT,PbBiosIrqToIoDescriptor)
  76. #pragma alloc_text(INIT,PbBiosDmaToIoDescriptor)
  77. #pragma alloc_text(INIT,PbBiosPortFixedToIoDescriptor)
  78. #pragma alloc_text(INIT,PbBiosPortToIoDescriptor)
  79. #pragma alloc_text(INIT,PbBiosMemoryToIoDescriptor)
  80. #endif
  81. NTSTATUS
  82. PbBiosResourcesToNtResources (
  83. IN ULONG BusNumber,
  84. IN ULONG SlotNumber,
  85. IN OUT PUCHAR *BiosData,
  86. OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList,
  87. OUT PULONG ReturnedLength
  88. )
  89. /*++
  90. Routine Description:
  91. This routine parses the Bios resource list and generates
  92. a NT resource list. The returned Nt resource list could be either IO
  93. format or CM format. It is caller's responsibility to release the
  94. returned data buffer.
  95. Arguments:
  96. SlotNumber - specifies the slot number of the BIOS resource.
  97. BiosData - Supplies a pointer to a variable which specifies the bios resource
  98. data buffer and which to receive the pointer to next bios resource data.
  99. ReturnedList - supplies a variable to receive the desired resource list.
  100. ReturnedLength - Supplies a variable to receive the length of the resource list.
  101. Return Value:
  102. NTSTATUS code
  103. --*/
  104. {
  105. PUCHAR buffer;
  106. USHORT mask16, increment;
  107. UCHAR tagName, mask8;
  108. NTSTATUS status;
  109. PPB_ALTERNATIVE_INFORMATION alternativeList = NULL;
  110. ULONG commonResCount = 0, dependDescCount = 0, i, j;
  111. ULONG alternativeListCount = 0, dependFunctionCount = 0;
  112. PIO_RESOURCE_DESCRIPTOR commonResources = NULL, commonIoDesc, dependIoDesc, ioDesc;
  113. PPB_DEPENDENT_RESOURCES dependResList = NULL, dependResources;
  114. BOOLEAN dependent = FALSE;
  115. ULONG listSize, noResLists;
  116. ULONG totalDescCount, descCount;
  117. PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
  118. PIO_RESOURCE_LIST ioResList;
  119. //
  120. // First, scan the bios data to determine the memory requirement and
  121. // the information to build internal data structures.
  122. //
  123. *ReturnedLength = 0;
  124. alternativeListCount = 0;
  125. buffer = *BiosData;
  126. tagName = *buffer;
  127. while (tagName != TAG_COMPLETE_END) {
  128. //
  129. // Determine the size of the BIOS resource descriptor
  130. //
  131. if (!(tagName & LARGE_RESOURCE_TAG)) {
  132. increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK);
  133. increment += 1; // length of small tag
  134. tagName &= SMALL_TAG_MASK;
  135. } else {
  136. increment = *(PUSHORT)(buffer+1);
  137. increment += 3; // length of large tag
  138. }
  139. //
  140. // Based on the type of the BIOS resource, determine the count of
  141. // the IO descriptors.
  142. //
  143. switch (tagName) {
  144. case TAG_IRQ:
  145. mask16 = ((PPNP_IRQ_DESCRIPTOR)buffer)->IrqMask;
  146. i = 0;
  147. while (mask16) {
  148. if (mask16 & 1) {
  149. i++;
  150. }
  151. mask16 >>= 1;
  152. }
  153. if (!dependent) {
  154. commonResCount += i;
  155. } else {
  156. dependDescCount += i;
  157. }
  158. break;
  159. case TAG_DMA:
  160. mask8 = ((PPNP_DMA_DESCRIPTOR)buffer)->ChannelMask;
  161. i = 0;
  162. while (mask8) {
  163. if (mask8 & 1) {
  164. i++;
  165. }
  166. mask8 >>= 1;
  167. }
  168. if (!dependent) {
  169. commonResCount += i;
  170. } else {
  171. dependDescCount += i;
  172. }
  173. break;
  174. case TAG_START_DEPEND:
  175. dependent = TRUE;
  176. dependFunctionCount++;
  177. break;
  178. case TAG_END_DEPEND:
  179. dependent = FALSE;
  180. alternativeListCount++;
  181. break;
  182. case TAG_IO_FIXED:
  183. case TAG_IO:
  184. case TAG_MEMORY:
  185. case TAG_MEMORY32:
  186. case TAG_MEMORY32_FIXED:
  187. if (!dependent) {
  188. commonResCount++;
  189. } else {
  190. dependDescCount++;
  191. }
  192. break;
  193. default:
  194. //
  195. // Unknown tag. Skip it.
  196. //
  197. break;
  198. }
  199. //
  200. // Move to next bios resource descriptor.
  201. //
  202. buffer += increment;
  203. tagName = *buffer;
  204. if ((tagName & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
  205. break;
  206. }
  207. }
  208. //
  209. // if empty bios resources, simply return.
  210. //
  211. if (commonResCount == 0 && dependFunctionCount == 0) {
  212. *ReturnedList = NULL;
  213. *ReturnedLength = 0;
  214. *BiosData = buffer + 2;
  215. return STATUS_SUCCESS;
  216. }
  217. //
  218. // Allocate memory for our internal data structures
  219. //
  220. if (dependFunctionCount) {
  221. dependResources = (PPB_DEPENDENT_RESOURCES)ExAllocatePoolWithTag(
  222. PagedPool,
  223. dependFunctionCount * sizeof(PB_DEPENDENT_RESOURCES) +
  224. dependDescCount * sizeof(IO_RESOURCE_DESCRIPTOR),
  225. 'bPnP'
  226. );
  227. if (!dependResources) {
  228. return STATUS_INSUFFICIENT_RESOURCES;
  229. }
  230. dependResList = dependResources; // remember it so we can free it.
  231. }
  232. if (alternativeListCount) {
  233. ASSERT(dependFunctionCount != 0);
  234. alternativeList = (PPB_ALTERNATIVE_INFORMATION)ExAllocatePoolWithTag(
  235. PagedPool,
  236. sizeof(PB_ALTERNATIVE_INFORMATION) * (alternativeListCount + 1),
  237. 'bPnP'
  238. );
  239. if (!alternativeList) {
  240. status = STATUS_INSUFFICIENT_RESOURCES;
  241. goto exit0;
  242. }
  243. RtlZeroMemory(alternativeList,
  244. sizeof(PB_ALTERNATIVE_INFORMATION) * alternativeListCount
  245. );
  246. alternativeList[0].Resources = dependResources;
  247. }
  248. if (commonResCount) {
  249. commonResources = (PIO_RESOURCE_DESCRIPTOR)ExAllocatePoolWithTag (
  250. PagedPool,
  251. sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount,
  252. 'bPnP'
  253. );
  254. if (!commonResources) {
  255. status = STATUS_INSUFFICIENT_RESOURCES;
  256. goto exit1;
  257. }
  258. }
  259. //
  260. // Now start over again to process the bios data and initialize our internal
  261. // resource representation.
  262. //
  263. commonIoDesc = commonResources;
  264. dependDescCount = 0;
  265. alternativeListCount = 0;
  266. buffer = *BiosData;
  267. tagName = *buffer;
  268. dependent = FALSE;
  269. while (tagName != TAG_COMPLETE_END) {
  270. if (!(tagName & LARGE_RESOURCE_TAG)) {
  271. tagName &= SMALL_TAG_MASK;
  272. }
  273. switch (tagName) {
  274. case TAG_IRQ:
  275. if (dependent) {
  276. ioDesc = dependIoDesc;
  277. } else {
  278. ioDesc = commonIoDesc;
  279. }
  280. status = PbBiosIrqToIoDescriptor(&buffer, ioDesc);
  281. if (NT_SUCCESS(status)) {
  282. if (dependent) {
  283. dependIoDesc++;
  284. dependDescCount++;
  285. } else {
  286. commonIoDesc++;
  287. }
  288. }
  289. break;
  290. case TAG_DMA:
  291. if (dependent) {
  292. ioDesc = dependIoDesc;
  293. } else {
  294. ioDesc = commonIoDesc;
  295. }
  296. status = PbBiosDmaToIoDescriptor(&buffer, ioDesc);
  297. if (NT_SUCCESS(status)) {
  298. if (dependent) {
  299. dependIoDesc++;
  300. dependDescCount++;
  301. } else {
  302. commonIoDesc++;
  303. }
  304. }
  305. break;
  306. case TAG_START_DEPEND:
  307. dependent = TRUE;
  308. alternativeList[alternativeListCount].NoDependentFunctions++;
  309. if (dependDescCount != 0) {
  310. //
  311. // End of current dependent function
  312. //
  313. dependResources->Count = dependDescCount;
  314. dependResources->Flags = 0;
  315. dependResources->Next = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
  316. dependResources = dependResources->Next;
  317. alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
  318. }
  319. if (*buffer & SMALL_TAG_SIZE_MASK) {
  320. dependResources->Priority = *(buffer + 1);
  321. }
  322. dependDescCount = 0;
  323. dependIoDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
  324. buffer += 1 + (*buffer & SMALL_TAG_SIZE_MASK);
  325. break;
  326. case TAG_END_DEPEND:
  327. alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
  328. dependResources->Count = dependDescCount;
  329. dependResources->Flags = DEPENDENT_FLAGS_END;
  330. dependResources->Next = alternativeList[alternativeListCount].Resources;
  331. dependent = FALSE;
  332. dependDescCount = 0;
  333. alternativeListCount++;
  334. alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
  335. dependResources = alternativeList[alternativeListCount].Resources;
  336. buffer++;
  337. break;
  338. case TAG_IO:
  339. if (dependent) {
  340. ioDesc = dependIoDesc;
  341. } else {
  342. ioDesc = commonIoDesc;
  343. }
  344. status = PbBiosPortToIoDescriptor(&buffer, ioDesc);
  345. if (NT_SUCCESS(status)) {
  346. if (dependent) {
  347. dependIoDesc++;
  348. dependDescCount++;
  349. } else {
  350. commonIoDesc++;
  351. }
  352. }
  353. break;
  354. case TAG_IO_FIXED:
  355. if (dependent) {
  356. ioDesc = dependIoDesc;
  357. } else {
  358. ioDesc = commonIoDesc;
  359. }
  360. status = PbBiosPortFixedToIoDescriptor(&buffer, ioDesc);
  361. if (NT_SUCCESS(status)) {
  362. if (dependent) {
  363. dependIoDesc++;
  364. dependDescCount++;
  365. } else {
  366. commonIoDesc++;
  367. }
  368. }
  369. break;
  370. case TAG_MEMORY:
  371. case TAG_MEMORY32:
  372. case TAG_MEMORY32_FIXED:
  373. if (dependent) {
  374. ioDesc = dependIoDesc;
  375. dependDescCount;
  376. } else {
  377. ioDesc = commonIoDesc;
  378. }
  379. status = PbBiosMemoryToIoDescriptor(&buffer, ioDesc);
  380. if (NT_SUCCESS(status)) {
  381. if (dependent) {
  382. dependIoDesc++;
  383. dependDescCount++;
  384. } else {
  385. commonIoDesc++;
  386. }
  387. }
  388. break;
  389. default:
  390. //
  391. // Don't-care tag simpley advance the buffer pointer to next tag.
  392. //
  393. if (*buffer & LARGE_RESOURCE_TAG) {
  394. increment = *(PUSHORT)(buffer+1);
  395. increment += 3; // length of large tag
  396. } else {
  397. increment = (USHORT)(*buffer & SMALL_TAG_SIZE_MASK);
  398. increment += 1; // length of small tag
  399. }
  400. buffer += increment;
  401. }
  402. tagName = *buffer;
  403. if ((tagName & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
  404. break;
  405. }
  406. }
  407. if (alternativeListCount != 0) {
  408. alternativeList[alternativeListCount].Resources = NULL; // dummy alternativeList record
  409. }
  410. *BiosData = buffer + 2; // Skip END_TAG
  411. //
  412. // prepare IoResourceList
  413. //
  414. noResLists = 1;
  415. for (i = 0; i < alternativeListCount; i++) {
  416. noResLists *= alternativeList[i].NoDependentFunctions;
  417. }
  418. totalDescCount = 0;
  419. for (i = 0; i < alternativeListCount; i++) {
  420. descCount = 1;
  421. for (j = 0; j < alternativeListCount; j++) {
  422. if (j == i) {
  423. descCount *= alternativeList[j].TotalResourceCount;
  424. } else {
  425. descCount *= alternativeList[j].NoDependentFunctions;
  426. }
  427. }
  428. totalDescCount += descCount;
  429. }
  430. listSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
  431. sizeof(IO_RESOURCE_LIST) * (noResLists - 1) +
  432. sizeof(IO_RESOURCE_DESCRIPTOR) * totalDescCount -
  433. sizeof(IO_RESOURCE_DESCRIPTOR) * noResLists +
  434. sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount * noResLists;
  435. ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePoolWithTag(PagedPool, listSize, 'bPnP');
  436. if (!ioResReqList) {
  437. status = STATUS_INSUFFICIENT_RESOURCES;
  438. goto exit2;
  439. }
  440. ioResReqList->ListSize = listSize;
  441. ioResReqList->InterfaceType = Internal;
  442. ioResReqList->BusNumber = BusNumber;
  443. ioResReqList->SlotNumber = SlotNumber;
  444. ioResReqList->Reserved[0] = 0;
  445. ioResReqList->Reserved[1] = 0;
  446. ioResReqList->Reserved[2] = 0;
  447. ioResReqList->AlternativeLists = noResLists;
  448. ioResList = &ioResReqList->List[0];
  449. //
  450. // Build resource lists
  451. //
  452. for (i = 0; i < noResLists; i++) {
  453. ULONG size;
  454. USHORT j;
  455. ioResList->Version = 1;
  456. ioResList->Revision = 0x30 | (USHORT)i;
  457. buffer = (PUCHAR)&ioResList->Descriptors[0];
  458. //
  459. // Copy common resources to the list
  460. //
  461. if (commonResources) {
  462. size = sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount;
  463. RtlMoveMemory(buffer, commonResources, size);
  464. buffer += size;
  465. }
  466. //
  467. // Copy dependent functions if any.
  468. //
  469. if (alternativeList) {
  470. PbAddDependentResourcesToList(&buffer, 0, alternativeList);
  471. }
  472. //
  473. // Update io resource list ptr
  474. //
  475. ioResList->Count = ((ULONG)buffer - (ULONG)&ioResList->Descriptors[0]) /
  476. sizeof(IO_RESOURCE_DESCRIPTOR);
  477. //
  478. // Hack for user mode pnp mgr
  479. //
  480. for (j = 0; j < ioResList->Count; j++) {
  481. ioResList->Descriptors[j].Spare2 = j;
  482. }
  483. ioResList = (PIO_RESOURCE_LIST)buffer;
  484. }
  485. *ReturnedLength = listSize;
  486. status = STATUS_SUCCESS;
  487. *ReturnedList = ioResReqList;
  488. exit2:
  489. if (commonResources) {
  490. ExFreePool(commonResources);
  491. }
  492. exit1:
  493. if (alternativeList) {
  494. ExFreePool(alternativeList);
  495. }
  496. exit0:
  497. if (dependResList) {
  498. ExFreePool(dependResList);
  499. }
  500. return status;
  501. }
  502. PPB_DEPENDENT_RESOURCES
  503. PbAddDependentResourcesToList (
  504. IN OUT PUCHAR *ResourceDescriptor,
  505. IN ULONG ListNo,
  506. IN PPB_ALTERNATIVE_INFORMATION AlternativeList
  507. )
  508. /*++
  509. Routine Description:
  510. This routine adds dependent functions to caller specified list.
  511. Arguments:
  512. ResourceDescriptor - supplies a pointer to the descriptor buffer.
  513. ListNo - supplies an index to the AlternativeList.
  514. AlternativeList - supplies a pointer to the alternativelist array.
  515. Return Value:
  516. return NTSTATUS code to indicate the result of the operation.
  517. --*/
  518. {
  519. PPB_DEPENDENT_RESOURCES dependentResources, ptr;
  520. ULONG size;
  521. //
  522. // Copy dependent resources to caller supplied list buffer and
  523. // update the list buffer pointer.
  524. //
  525. dependentResources = AlternativeList[ListNo].Resources;
  526. size = sizeof(IO_RESOURCE_DESCRIPTOR) * dependentResources->Count;
  527. RtlMoveMemory(*ResourceDescriptor, dependentResources + 1, size);
  528. *ResourceDescriptor = *ResourceDescriptor + size;
  529. //
  530. // Add dependent resource of next list to caller's buffer
  531. //
  532. if (AlternativeList[ListNo + 1].Resources) {
  533. ptr = PbAddDependentResourcesToList(ResourceDescriptor, ListNo + 1, AlternativeList);
  534. } else {
  535. ptr = NULL;
  536. }
  537. if (ptr == NULL) {
  538. AlternativeList[ListNo].Resources = dependentResources->Next;
  539. if (!(dependentResources->Flags & DEPENDENT_FLAGS_END)) {
  540. ptr = dependentResources->Next;
  541. }
  542. }
  543. return ptr;
  544. }
  545. VOID
  546. PbIoDescriptorToCmDescriptor (
  547. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
  548. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
  549. )
  550. /*++
  551. Routine Description:
  552. This routine translates IO_RESOURCE_DESCRIPTOR to CM_PARTIAL_RESOURCE_DESCRIPTOR.
  553. Arguments:
  554. IoDescriptor - Supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be converted.
  555. CmDescriptor - Supplies a pointer to the receiving CM_PARTIAL_RESOURCE_DESCRIPTOR.
  556. Return Value:
  557. None.
  558. --*/
  559. {
  560. CmDescriptor->Type = IoDescriptor->Type;
  561. CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
  562. CmDescriptor->Flags = IoDescriptor->Flags;
  563. switch (CmDescriptor->Type) {
  564. case CmResourceTypePort:
  565. CmDescriptor->u.Port.Length = IoDescriptor->u.Port.Length;
  566. CmDescriptor->u.Port.Start = IoDescriptor->u.Port.MinimumAddress;
  567. break;
  568. case CmResourceTypeInterrupt:
  569. CmDescriptor->u.Interrupt.Level =
  570. CmDescriptor->u.Interrupt.Vector = IoDescriptor->u.Interrupt.MinimumVector;
  571. CmDescriptor->u.Interrupt.Affinity = (ULONG)-1;
  572. break;
  573. case CmResourceTypeMemory:
  574. CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
  575. CmDescriptor->u.Memory.Start = IoDescriptor->u.Memory.MinimumAddress;
  576. break;
  577. case CmResourceTypeDma:
  578. CmDescriptor->u.Dma.Channel = IoDescriptor->u.Dma.MinimumChannel;
  579. CmDescriptor->u.Dma.Port = 0;
  580. CmDescriptor->u.Dma.Reserved1 = 0;
  581. break;
  582. }
  583. }
  584. NTSTATUS
  585. PbBiosIrqToIoDescriptor (
  586. IN OUT PUCHAR *BiosData,
  587. PIO_RESOURCE_DESCRIPTOR IoDescriptor
  588. )
  589. /*++
  590. Routine Description:
  591. This routine translates BIOS IRQ information to NT usable format.
  592. This routine stops when an irq io resource is generated. if there are
  593. more irq io resource descriptors available, the BiosData pointer will
  594. not advance. So caller will pass us the same resource tag again.
  595. Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
  596. for each seperated channel required.
  597. Arguments:
  598. BiosData - Supplies a pointer to the bios resource data buffer.
  599. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  600. Converted resource will be stored here.
  601. Return Value:
  602. return NTSTATUS code to indicate the result of the operation.
  603. --*/
  604. {
  605. static ULONG bitPosition = 0;
  606. USHORT mask;
  607. ULONG irq;
  608. PPNP_IRQ_DESCRIPTOR buffer;
  609. UCHAR size, option;
  610. NTSTATUS status = STATUS_SUCCESS;
  611. buffer = (PPNP_IRQ_DESCRIPTOR)*BiosData;
  612. //
  613. // if this is not the first descriptor for the tag, set
  614. // its option to alternative.
  615. //
  616. if (bitPosition == 0) {
  617. option = 0;
  618. } else {
  619. option = IO_RESOURCE_ALTERNATIVE;
  620. }
  621. size = buffer->Tag & SMALL_TAG_SIZE_MASK;
  622. mask = buffer->IrqMask;
  623. mask >>= bitPosition;
  624. irq = (ULONG) -1;
  625. while (mask) {
  626. if (mask & 1) {
  627. irq = bitPosition;
  628. break;
  629. }
  630. mask >>= 1;
  631. bitPosition++;
  632. }
  633. //
  634. // Fill in Io resource descriptor
  635. //
  636. if (irq != (ULONG)-1) {
  637. IoDescriptor->Option = option;
  638. IoDescriptor->Type = CmResourceTypeInterrupt;
  639. IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  640. IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  641. if (size == 3 && buffer->Information & 0x0C) {
  642. IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
  643. IoDescriptor->ShareDisposition = CmResourceShareShared;
  644. }
  645. IoDescriptor->Spare1 = 0;
  646. IoDescriptor->Spare2 = 0;
  647. IoDescriptor->u.Interrupt.MinimumVector = irq;
  648. IoDescriptor->u.Interrupt.MaximumVector = irq;
  649. } else {
  650. status = STATUS_INVALID_PARAMETER;
  651. }
  652. if (NT_SUCCESS(status)) {
  653. //
  654. // try to move bitPosition to next 1 bit.
  655. //
  656. while (mask) {
  657. mask >>= 1;
  658. bitPosition++;
  659. if (mask & 1) {
  660. return status;
  661. }
  662. }
  663. }
  664. //
  665. // Done with current irq tag, advance pointer to next tag
  666. //
  667. bitPosition = 0;
  668. *BiosData = (PUCHAR)buffer + size + 1;
  669. return status;
  670. }
  671. NTSTATUS
  672. PbBiosDmaToIoDescriptor (
  673. IN OUT PUCHAR *BiosData,
  674. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  675. )
  676. /*++
  677. Routine Description:
  678. This routine translates BIOS DMA information to NT usable format.
  679. This routine stops when an dma io resource is generated. if there are
  680. more dma io resource descriptors available, the BiosData pointer will
  681. not advance. So caller will pass us the same resource tag again.
  682. Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
  683. for each seperated channel required.
  684. Arguments:
  685. BiosData - Supplies a pointer to the bios resource data buffer.
  686. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  687. Converted resource will be stored here.
  688. Return Value:
  689. return NTSTATUS code to indicate the result of the operation.
  690. --*/
  691. {
  692. static ULONG bitPosition = 0;
  693. ULONG dma;
  694. PPNP_DMA_DESCRIPTOR buffer;
  695. UCHAR mask, option;
  696. NTSTATUS status = STATUS_SUCCESS;
  697. buffer = (PPNP_DMA_DESCRIPTOR)*BiosData;
  698. //
  699. // if this is not the first descriptor for the tag, set
  700. // its option to alternative.
  701. //
  702. if (bitPosition == 0) {
  703. option = 0;
  704. } else {
  705. option = IO_RESOURCE_ALTERNATIVE;
  706. }
  707. mask = buffer->ChannelMask;
  708. mask >>= bitPosition;
  709. dma = (ULONG) -1;
  710. while (mask) {
  711. if (mask & 1) {
  712. dma = bitPosition;
  713. break;
  714. }
  715. mask >>= 1;
  716. bitPosition++;
  717. }
  718. //
  719. // Fill in Io resource descriptor
  720. //
  721. if (dma != (ULONG)-1) {
  722. IoDescriptor->Option = option;
  723. IoDescriptor->Type = CmResourceTypeDma;
  724. IoDescriptor->Flags = 0;
  725. IoDescriptor->ShareDisposition = CmResourceShareUndetermined;
  726. IoDescriptor->Spare1 = 0;
  727. IoDescriptor->Spare2 = 0;
  728. IoDescriptor->u.Dma.MinimumChannel = dma;
  729. IoDescriptor->u.Dma.MaximumChannel = dma;
  730. } else {
  731. status = STATUS_INVALID_PARAMETER;
  732. }
  733. if (NT_SUCCESS(status)) {
  734. //
  735. // try to move bitPosition to next 1 bit.
  736. //
  737. while (mask) {
  738. mask >>= 1;
  739. bitPosition++;
  740. if (mask & 1) {
  741. return status;
  742. }
  743. }
  744. }
  745. //
  746. // Done with current dma tag, advance pointer to next tag
  747. //
  748. bitPosition = 0;
  749. buffer += 1;
  750. *BiosData = (PUCHAR)buffer;
  751. return status;
  752. }
  753. NTSTATUS
  754. PbBiosPortFixedToIoDescriptor (
  755. IN OUT PUCHAR *BiosData,
  756. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  757. )
  758. /*++
  759. Routine Description:
  760. This routine translates BIOS FIXED IO information to NT usable format.
  761. Arguments:
  762. BiosData - Supplies a pointer to the bios resource data buffer.
  763. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  764. Converted resource will be stored here.
  765. Return Value:
  766. return NTSTATUS code to indicate the result of the operation.
  767. --*/
  768. {
  769. PPNP_FIXED_PORT_DESCRIPTOR buffer;
  770. buffer = (PPNP_FIXED_PORT_DESCRIPTOR)*BiosData;
  771. //
  772. // Fill in Io resource descriptor
  773. //
  774. IoDescriptor->Option = 0;
  775. IoDescriptor->Type = CmResourceTypePort;
  776. IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
  777. IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  778. IoDescriptor->Spare1 = 0;
  779. IoDescriptor->Spare2 = 0;
  780. IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
  781. IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)(buffer->MinimumAddress & 0x3ff);
  782. IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
  783. IoDescriptor->u.Port.MaximumAddress.LowPart = IoDescriptor->u.Port.MinimumAddress.LowPart +
  784. IoDescriptor->u.Port.Length - 1;
  785. IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
  786. IoDescriptor->u.Port.Alignment = 1;
  787. //
  788. // Done with current fixed port tag, advance pointer to next tag
  789. //
  790. buffer += 1;
  791. *BiosData = (PUCHAR)buffer;
  792. return STATUS_SUCCESS;
  793. }
  794. NTSTATUS
  795. PbBiosPortToIoDescriptor (
  796. IN OUT PUCHAR *BiosData,
  797. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  798. )
  799. /*++
  800. Routine Description:
  801. This routine translates BIOS IO information to NT usable format.
  802. Arguments:
  803. BiosData - Supplies a pointer to the bios resource data buffer.
  804. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  805. Converted resource will be stored here.
  806. Return Value:
  807. return NTSTATUS code to indicate the result of the operation.
  808. --*/
  809. {
  810. PPNP_PORT_DESCRIPTOR buffer;
  811. buffer = (PPNP_PORT_DESCRIPTOR)*BiosData;
  812. //
  813. // Fill in Io resource descriptor
  814. //
  815. IoDescriptor->Option = 0;
  816. IoDescriptor->Type = CmResourceTypePort;
  817. IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
  818. IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  819. IoDescriptor->Spare1 = 0;
  820. IoDescriptor->Spare2 = 0;
  821. IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
  822. IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)buffer->MinimumAddress;
  823. IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
  824. IoDescriptor->u.Port.MaximumAddress.LowPart = (ULONG)buffer->MaximumAddress +
  825. IoDescriptor->u.Port.Length - 1;
  826. IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
  827. IoDescriptor->u.Port.Alignment = (ULONG)buffer->Alignment;
  828. //
  829. // Done with current fixed port tag, advance pointer to next tag
  830. //
  831. buffer += 1;
  832. *BiosData = (PUCHAR)buffer;
  833. return STATUS_SUCCESS;
  834. }
  835. NTSTATUS
  836. PbBiosMemoryToIoDescriptor (
  837. IN OUT PUCHAR *BiosData,
  838. IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
  839. )
  840. /*++
  841. Routine Description:
  842. This routine translates BIOS MEMORY information to NT usable format.
  843. Arguments:
  844. BiosData - Supplies a pointer to the bios resource data buffer.
  845. IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
  846. Converted resource will be stored here.
  847. Return Value:
  848. return NTSTATUS code to indicate the result of the operation.
  849. --*/
  850. {
  851. PUCHAR buffer;
  852. UCHAR tag;
  853. PHYSICAL_ADDRESS minAddr, maxAddr;
  854. ULONG alignment, length;
  855. USHORT increment;
  856. buffer = *BiosData;
  857. tag = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Tag;
  858. increment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Length + 3; // larg tag size = 3
  859. minAddr.HighPart = 0;
  860. maxAddr.HighPart = 0;
  861. switch (tag) {
  862. case TAG_MEMORY:
  863. minAddr.LowPart = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MinimumAddress)) << 8;
  864. if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Alignment) == 0) {
  865. alignment = 0x10000;
  866. }
  867. length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MemorySize)) << 8;
  868. maxAddr.LowPart = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MaximumAddress)) << 8) + length - 1;
  869. break;
  870. case TAG_MEMORY32:
  871. length = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
  872. minAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MinimumAddress;
  873. maxAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MaximumAddress + length - 1;
  874. alignment = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->Alignment;
  875. break;
  876. case TAG_MEMORY32_FIXED:
  877. length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
  878. minAddr.LowPart = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->BaseAddress;
  879. maxAddr.LowPart = minAddr.LowPart + length - 1;
  880. alignment = 1;
  881. break;
  882. }
  883. //
  884. // Fill in Io resource descriptor
  885. //
  886. IoDescriptor->Option = 0;
  887. IoDescriptor->Type = CmResourceTypeMemory;
  888. IoDescriptor->Flags = CM_RESOURCE_PORT_MEMORY;
  889. IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  890. IoDescriptor->Spare1 = 0;
  891. IoDescriptor->Spare2 = 0;
  892. IoDescriptor->u.Memory.MinimumAddress = minAddr;
  893. IoDescriptor->u.Memory.MaximumAddress = maxAddr;
  894. IoDescriptor->u.Memory.Alignment = alignment;
  895. IoDescriptor->u.Memory.Length = length;
  896. //
  897. // Done with current tag, advance pointer to next tag
  898. //
  899. buffer += increment;
  900. *BiosData = (PUCHAR)buffer;
  901. return STATUS_SUCCESS;
  902. }