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.

1571 lines
35 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. cmres.c
  5. Abstract:
  6. This file contains routines to translate resources between PnP ISA/BIOS
  7. format and Windows NT formats.
  8. Author:
  9. Stephane Plante (splante) 20-Nov-1996
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. 13-Feb-1997:
  14. Initial Revision
  15. --*/
  16. #include "pch.h"
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE,PnpiCmResourceToBiosAddress)
  19. #pragma alloc_text(PAGE,PnpiCmResourceToBiosAddressDouble)
  20. #pragma alloc_text(PAGE,PnpiCmResourceToBiosDma)
  21. #pragma alloc_text(PAGE,PnpiCmResourceToBiosExtendedIrq)
  22. #pragma alloc_text(PAGE,PnpiCmResourceToBiosIoFixedPort)
  23. #pragma alloc_text(PAGE,PnpiCmResourceToBiosIoPort)
  24. #pragma alloc_text(PAGE,PnpiCmResourceToBiosIrq)
  25. #pragma alloc_text(PAGE,PnpiCmResourceToBiosMemory)
  26. #pragma alloc_text(PAGE,PnpiCmResourceToBiosMemory32)
  27. #pragma alloc_text(PAGE,PnpiCmResourceToBiosMemory32Fixed)
  28. #pragma alloc_text(PAGE,PnpiCmResourceValidEmptyList)
  29. #pragma alloc_text(PAGE,PnpCmResourcesToBiosResources)
  30. #endif
  31. NTSTATUS
  32. PnpiCmResourceToBiosAddress(
  33. IN PUCHAR Buffer,
  34. IN PCM_RESOURCE_LIST List
  35. )
  36. /*++
  37. Routine Description:
  38. This routine converts the proper Cm resource descriptor back into a
  39. word address descriptor
  40. Arguments:
  41. Buffer - Pointer to the Bios Resource list
  42. List - Pointer to the CM resource List
  43. Return:
  44. NTSTATUS
  45. --*/
  46. {
  47. PCM_FULL_RESOURCE_DESCRIPTOR aList;
  48. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  49. PPNP_WORD_ADDRESS_DESCRIPTOR buffer;
  50. UCHAR type;
  51. ULONG i;
  52. PAGED_CODE();
  53. //
  54. // Setup the initial buffer
  55. //
  56. buffer = (PPNP_WORD_ADDRESS_DESCRIPTOR) Buffer;
  57. //
  58. // We can only have one list...
  59. //
  60. aList = &(List->List[0]);
  61. ASSERT( List->Count == 1 );
  62. ASSERT( aList->PartialResourceList.Count );
  63. //
  64. // Determine which type of descriptor we are looking for
  65. //
  66. switch (buffer->RFlag) {
  67. case PNP_ADDRESS_MEMORY_TYPE:
  68. type = CmResourceTypeMemory;
  69. break;
  70. case PNP_ADDRESS_IO_TYPE:
  71. type = CmResourceTypePort;
  72. break;
  73. case PNP_ADDRESS_BUS_NUMBER_TYPE:
  74. type = CmResourceTypeBusNumber;
  75. break;
  76. default:
  77. return STATUS_UNSUCCESSFUL;
  78. }
  79. //
  80. // Loop for each of the partial resource descriptors
  81. //
  82. for (i = 0; i < aList->PartialResourceList.Count; i++) {
  83. //
  84. // Current descriptor
  85. //
  86. desc = &(aList->PartialResourceList.PartialDescriptors[i]);
  87. //
  88. // Is this an interesting descriptor?
  89. //
  90. if (desc->Type != type) {
  91. //
  92. // No
  93. //
  94. continue;
  95. }
  96. switch (desc->Type) {
  97. case PNP_ADDRESS_MEMORY_TYPE:
  98. //
  99. // Set the flags
  100. //
  101. buffer->TFlag = 0;
  102. if (desc->Flags & CM_RESOURCE_MEMORY_READ_WRITE) {
  103. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_WRITE;
  104. } else {
  105. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_ONLY;
  106. }
  107. if (desc->Flags & CM_RESOURCE_MEMORY_CACHEABLE) {
  108. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_CACHEABLE;
  109. } else if (desc->Flags & CM_RESOURCE_MEMORY_COMBINEDWRITE) {
  110. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_WRITE_COMBINE;
  111. } else if (desc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) {
  112. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_PREFETCHABLE;
  113. } else {
  114. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_NONCACHEABLE;
  115. }
  116. //
  117. // Set the rest of the information
  118. //
  119. buffer->MinimumAddress = (USHORT)
  120. (desc->u.Memory.Start.LowPart & 0xFFFF);
  121. buffer->MaximumAddress = buffer->MinimumAddress +
  122. (USHORT) (desc->u.Memory.Length - 1);
  123. buffer->AddressLength = (USHORT) desc->u.Memory.Length;
  124. break;
  125. case PNP_ADDRESS_IO_TYPE:
  126. //
  127. // We must extract the flags here from the
  128. // devicePrivate resource
  129. //
  130. //
  131. // Set the rest of the information
  132. //
  133. buffer->MinimumAddress = (USHORT)
  134. (desc->u.Port.Start.LowPart & 0xFFFF);
  135. buffer->MaximumAddress = buffer->MinimumAddress +
  136. (USHORT) (desc->u.Port.Length - 1);
  137. buffer->AddressLength = (USHORT) desc->u.Port.Length;
  138. break;
  139. case PNP_ADDRESS_BUS_NUMBER_TYPE:
  140. buffer->MinimumAddress = (USHORT)
  141. (desc->u.BusNumber.Start & 0xFFFF);
  142. buffer->MaximumAddress = buffer->MinimumAddress +
  143. (USHORT) (desc->u.BusNumber.Length - 1);
  144. buffer->AddressLength = (USHORT) desc->u.BusNumber.Length;
  145. break;
  146. } // switch
  147. //
  148. // Handling for the GFlags goes here, if we ever decide to
  149. // support it
  150. //
  151. //
  152. // Done with descriptor and match
  153. //
  154. desc->Type = CmResourceTypeNull;
  155. break;
  156. } // for
  157. //
  158. // Done
  159. //
  160. return STATUS_SUCCESS;
  161. }
  162. NTSTATUS
  163. PnpiCmResourceToBiosAddressDouble(
  164. IN PUCHAR Buffer,
  165. IN PCM_RESOURCE_LIST List
  166. )
  167. /*++
  168. Routine Description:
  169. This routine converts the proper Cm resource descriptor back into a
  170. word address descriptor
  171. Arguments:
  172. Buffer - Pointer to the Bios Resource list
  173. List - Pointer to the CM resource List
  174. Return:
  175. NTSTATUS
  176. --*/
  177. {
  178. PCM_FULL_RESOURCE_DESCRIPTOR aList;
  179. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  180. PPNP_DWORD_ADDRESS_DESCRIPTOR buffer;
  181. UCHAR type;
  182. ULONG i;
  183. PAGED_CODE();
  184. //
  185. // Setup the initial buffer
  186. //
  187. buffer = (PPNP_DWORD_ADDRESS_DESCRIPTOR) Buffer;
  188. //
  189. // We can only have one list...
  190. //
  191. aList = &(List->List[0]);
  192. ASSERT( List->Count == 1 );
  193. ASSERT( aList->PartialResourceList.Count );
  194. //
  195. // Determine which type of descriptor we are looking for
  196. //
  197. switch (buffer->RFlag) {
  198. case PNP_ADDRESS_MEMORY_TYPE:
  199. type = CmResourceTypeMemory;
  200. break;
  201. case PNP_ADDRESS_IO_TYPE:
  202. type = CmResourceTypePort;
  203. break;
  204. case PNP_ADDRESS_BUS_NUMBER_TYPE:
  205. type = CmResourceTypeBusNumber;
  206. break;
  207. default:
  208. return STATUS_UNSUCCESSFUL;
  209. }
  210. //
  211. // Loop for each of the partial resource descriptors
  212. //
  213. for (i = 0; i < aList->PartialResourceList.Count; i++) {
  214. //
  215. // Current descriptor
  216. //
  217. desc = &(aList->PartialResourceList.PartialDescriptors[i]);
  218. //
  219. // Is this an interesting descriptor?
  220. //
  221. if (desc->Type != type) {
  222. //
  223. // No
  224. //
  225. continue;
  226. }
  227. switch (desc->Type) {
  228. case PNP_ADDRESS_MEMORY_TYPE:
  229. //
  230. // Set the flags
  231. //
  232. buffer->TFlag = 0;
  233. if (desc->Flags & CM_RESOURCE_MEMORY_READ_WRITE) {
  234. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_WRITE;
  235. } else {
  236. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_ONLY;
  237. }
  238. if (desc->Flags & CM_RESOURCE_MEMORY_CACHEABLE) {
  239. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_CACHEABLE;
  240. } else if (desc->Flags & CM_RESOURCE_MEMORY_COMBINEDWRITE) {
  241. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_WRITE_COMBINE;
  242. } else if (desc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) {
  243. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_PREFETCHABLE;
  244. } else {
  245. buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_NONCACHEABLE;
  246. }
  247. //
  248. // Set the rest of the information
  249. //
  250. buffer->MinimumAddress = (ULONG) desc->u.Memory.Start.LowPart;
  251. buffer->MaximumAddress = buffer->MinimumAddress +
  252. (ULONG) (desc->u.Memory.Length - 1);
  253. buffer->AddressLength = desc->u.Memory.Length;
  254. break;
  255. case PNP_ADDRESS_IO_TYPE:
  256. //
  257. // We must extract the flags here from the
  258. // devicePrivate resource
  259. //
  260. //
  261. // Set the rest of the information
  262. //
  263. buffer->MinimumAddress = (ULONG) desc->u.Port.Start.LowPart;
  264. buffer->MaximumAddress = buffer->MinimumAddress +
  265. (ULONG) (desc->u.Port.Length - 1);
  266. buffer->AddressLength = desc->u.Port.Length;
  267. break;
  268. case PNP_ADDRESS_BUS_NUMBER_TYPE:
  269. buffer->MinimumAddress = (ULONG) desc->u.BusNumber.Start;
  270. buffer->MaximumAddress = buffer->MinimumAddress +
  271. (ULONG) (desc->u.BusNumber.Length - 1);
  272. buffer->AddressLength = desc->u.BusNumber.Length;
  273. break;
  274. } // switch
  275. //
  276. // Handling for the GFlags goes here if we ever decide to support it
  277. //
  278. //
  279. // Done with descriptor and match
  280. //
  281. desc->Type = CmResourceTypeNull;
  282. break;
  283. } // for
  284. //
  285. // Done
  286. //
  287. return STATUS_SUCCESS;
  288. }
  289. NTSTATUS
  290. PnpiCmResourceToBiosDma(
  291. IN PUCHAR Buffer,
  292. IN PCM_RESOURCE_LIST List
  293. )
  294. /*++
  295. Routine Description:
  296. This routine stores all of the DMAs in the resource list into the Bios resource
  297. list
  298. Arguments:
  299. Buffer - Pointer to the Bios resource List
  300. List - Pointer to the CM resource List
  301. Return:
  302. NTSTATUS
  303. --*/
  304. {
  305. PCM_FULL_RESOURCE_DESCRIPTOR aList;
  306. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  307. PPNP_DMA_DESCRIPTOR buffer;
  308. ULONG i;
  309. PAGED_CODE();
  310. //
  311. // Setup the initial buffer
  312. //
  313. buffer = (PPNP_DMA_DESCRIPTOR) Buffer;
  314. ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 2);
  315. //
  316. // We can only have one list...
  317. //
  318. aList = &(List->List[0]);
  319. ASSERT( List->Count == 1);
  320. ASSERT( aList->PartialResourceList.Count );
  321. //
  322. // We can have a descriptor with no DMA channels
  323. //
  324. buffer->ChannelMask = 0;
  325. //
  326. // Loop for each of the partial resource descriptors
  327. //
  328. for (i = 0; i < aList->PartialResourceList.Count; i++) {
  329. //
  330. // Current descriptor
  331. //
  332. desc = &(aList->PartialResourceList.PartialDescriptors[i]);
  333. //
  334. // Is this an interesting descriptor?
  335. //
  336. if (desc->Type != CmResourceTypeDma) {
  337. //
  338. // No
  339. //
  340. continue;
  341. }
  342. //
  343. // Here we *have* a match...
  344. //
  345. buffer->ChannelMask = (1 << desc->u.Dma.Channel);
  346. //
  347. // Set the correct flags
  348. //
  349. buffer->Flags = 0;
  350. if (desc->Flags & CM_RESOURCE_DMA_8) {
  351. buffer->Flags |= PNP_DMA_SIZE_8;
  352. } else if (desc->Flags & CM_RESOURCE_DMA_8_AND_16) {
  353. buffer->Flags |= PNP_DMA_SIZE_8_AND_16;
  354. } else if (desc->Flags & CM_RESOURCE_DMA_16) {
  355. buffer->Flags |= PNP_DMA_SIZE_16;
  356. } else if (desc->Flags & CM_RESOURCE_DMA_32) {
  357. buffer->Flags |= PNP_DMA_SIZE_RESERVED;
  358. }
  359. if (desc->Flags & CM_RESOURCE_DMA_BUS_MASTER) {
  360. buffer->Flags |= PNP_DMA_BUS_MASTER;
  361. }
  362. if (desc->Flags & CM_RESOURCE_DMA_TYPE_A) {
  363. buffer->Flags |= PNP_DMA_TYPE_A;
  364. } else if (desc->Flags & CM_RESOURCE_DMA_TYPE_B) {
  365. buffer->Flags |= PNP_DMA_TYPE_B;
  366. } else if (desc->Flags & CM_RESOURCE_DMA_TYPE_F) {
  367. buffer->Flags |= PNP_DMA_TYPE_F;
  368. }
  369. //
  370. // Done with descriptor and match
  371. //
  372. desc->Type = CmResourceTypeNull;
  373. break;
  374. }
  375. //
  376. // Done
  377. //
  378. return STATUS_SUCCESS;
  379. }
  380. NTSTATUS
  381. PnpiCmResourceToBiosExtendedIrq(
  382. IN PUCHAR Buffer,
  383. IN PCM_RESOURCE_LIST List
  384. )
  385. /*++
  386. Routine Description:
  387. This routine stores all of the Irqs in the resource list into the Bios resource
  388. list
  389. Arguments:
  390. Buffer - Pointer to the Bios resource List
  391. List - Pointer to the CM resource List
  392. Return Value:
  393. NTSTATUS
  394. --*/
  395. {
  396. PCM_FULL_RESOURCE_DESCRIPTOR aList;
  397. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  398. PPNP_EXTENDED_IRQ_DESCRIPTOR buffer;
  399. ULONG i;
  400. ULONG matches = 0;
  401. PAGED_CODE();
  402. //
  403. // Setup the initial buffer
  404. //
  405. buffer = (PPNP_EXTENDED_IRQ_DESCRIPTOR) Buffer;
  406. ASSERT( buffer->TableSize == 1);
  407. ASSERT( buffer->Length >= 6);
  408. //
  409. // We can only have one list...
  410. //
  411. aList = &(List->List[0]);
  412. ASSERT( List->Count == 1);
  413. ASSERT( aList->PartialResourceList.Count );
  414. //
  415. // Loop for each of the partial resource descriptors
  416. //
  417. for (i = 0; i < aList->PartialResourceList.Count; i++) {
  418. //
  419. // Current descriptor
  420. //
  421. desc = &(aList->PartialResourceList.PartialDescriptors[i]);
  422. //
  423. // Is this an interesting descriptor?
  424. //
  425. if (desc->Type != CmResourceTypeInterrupt) {
  426. //
  427. // No
  428. //
  429. continue;
  430. }
  431. //
  432. // Here we *have* a match...
  433. //
  434. buffer->Table[0] = (ULONG) desc->u.Interrupt.Level;
  435. //
  436. // Set the Flags
  437. //
  438. buffer->Flags = 0;
  439. if ( (desc->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ) {
  440. buffer->Flags |= $EDG | $HGH;
  441. } else {
  442. buffer->Flags |= $LVL | $LOW;
  443. }
  444. if (desc->ShareDisposition == CmResourceShareShared) {
  445. buffer->Flags |= PNP_EXTENDED_IRQ_SHARED;
  446. }
  447. //
  448. // We need to use DevicePrivate information to store this
  449. // bit. For now, assume that it is set to true
  450. //
  451. buffer->Flags |= PNP_EXTENDED_IRQ_RESOURCE_CONSUMER_ONLY;
  452. //
  453. // Done with the record
  454. //
  455. desc->Type = CmResourceTypeNull;
  456. matches++;
  457. break;
  458. }
  459. //
  460. // Done with matches
  461. //
  462. return (matches == 0 ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS );
  463. }
  464. NTSTATUS
  465. PnpiCmResourceToBiosIoFixedPort(
  466. IN PUCHAR Buffer,
  467. IN PCM_RESOURCE_LIST List
  468. )
  469. /*++
  470. Routine Description:
  471. This routine stores all of the IoPort in the resource list into the Bios resource
  472. list
  473. Arguments:
  474. Buffer - Pointer to the Bios resource List
  475. List - Pointer to the CM resource List
  476. Return:
  477. NTSTATUS
  478. --*/
  479. {
  480. PCM_FULL_RESOURCE_DESCRIPTOR aList;
  481. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  482. PPNP_FIXED_PORT_DESCRIPTOR buffer;
  483. ULONG i;
  484. PAGED_CODE();
  485. //
  486. // Setup the initial buffer
  487. //
  488. buffer = (PPNP_FIXED_PORT_DESCRIPTOR) Buffer;
  489. ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 3);
  490. //
  491. // We can only have one list...
  492. //
  493. aList = &(List->List[0]);
  494. ASSERT( List->Count == 1);
  495. ASSERT( aList->PartialResourceList.Count );
  496. //
  497. // Our fixed port can be nothing
  498. //
  499. buffer->MinimumAddress = buffer->Length = 0;
  500. //
  501. // Loop for each of the partial resource descriptors
  502. //
  503. for (i = 0; i < aList->PartialResourceList.Count; i++) {
  504. //
  505. // Current descriptor
  506. //
  507. desc = &(aList->PartialResourceList.PartialDescriptors[i]);
  508. //
  509. // Is this an interesting descriptor?
  510. //
  511. if (desc->Type != CmResourceTypePort) {
  512. //
  513. // No
  514. //
  515. continue;
  516. }
  517. //
  518. // This port type is always set to a 10 bit decode
  519. //
  520. if ( !(desc->Flags & CM_RESOURCE_PORT_10_BIT_DECODE) ) {
  521. //
  522. // No
  523. //
  524. continue;
  525. }
  526. //
  527. // Here we *have* a match...
  528. //
  529. buffer->MinimumAddress = (USHORT) desc->u.Port.Start.LowPart;
  530. buffer->Length = (UCHAR) desc->u.Port.Length;
  531. //
  532. // Done with descriptor and match
  533. //
  534. desc->Type = CmResourceTypeNull;
  535. break;
  536. }
  537. //
  538. // Done
  539. //
  540. return STATUS_SUCCESS;
  541. }
  542. NTSTATUS
  543. PnpiCmResourceToBiosIoPort(
  544. IN PUCHAR Buffer,
  545. IN PCM_RESOURCE_LIST List
  546. )
  547. /*++
  548. Routine Description:
  549. This routine stores all of the IoPort in the resource list into the Bios resource
  550. list
  551. Arguments:
  552. Buffer - Pointer to the Bios resource List
  553. List - Pointer to the CM resource List
  554. Return:
  555. NTSTATUS
  556. --*/
  557. {
  558. PCM_FULL_RESOURCE_DESCRIPTOR aList;
  559. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  560. PPNP_PORT_DESCRIPTOR buffer;
  561. ULONG i;
  562. PAGED_CODE();
  563. //
  564. // Setup the initial buffer
  565. //
  566. buffer = (PPNP_PORT_DESCRIPTOR) Buffer;
  567. ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 7);
  568. //
  569. // We can only have one list...
  570. //
  571. aList = &(List->List[0]);
  572. ASSERT( List->Count == 1);
  573. ASSERT( aList->PartialResourceList.Count );
  574. //
  575. // We can use no ports
  576. //
  577. buffer->Information = 0;
  578. buffer->MinimumAddress = 0;
  579. buffer->MaximumAddress = 0;
  580. buffer->Alignment = 0;
  581. buffer->Length = 0;
  582. //
  583. // Loop for each of the partial resource descriptors
  584. //
  585. for (i = 0; i < aList->PartialResourceList.Count; i++) {
  586. //
  587. // Current descriptor
  588. //
  589. desc = &(aList->PartialResourceList.PartialDescriptors[i]);
  590. //
  591. // Is this an interesting descriptor?
  592. //
  593. if (desc->Type != CmResourceTypePort) {
  594. //
  595. // No
  596. //
  597. continue;
  598. }
  599. //
  600. // Here we *have* a match...
  601. //
  602. buffer->MinimumAddress = (USHORT) desc->u.Port.Start.LowPart;
  603. buffer->MaximumAddress = buffer->MinimumAddress;
  604. buffer->Alignment = 1;
  605. buffer->Length = (UCHAR) desc->u.Port.Length;
  606. //
  607. // Set the flags
  608. //
  609. buffer->Information = 0;
  610. if (desc->Flags & CM_RESOURCE_PORT_10_BIT_DECODE) {
  611. buffer->Information |= PNP_PORT_10_BIT_DECODE;
  612. }
  613. if (desc->Flags & CM_RESOURCE_PORT_16_BIT_DECODE) {
  614. buffer->Information |= PNP_PORT_16_BIT_DECODE;
  615. }
  616. //
  617. // Done with descriptor and match
  618. //
  619. desc->Type = CmResourceTypeNull;
  620. break;
  621. }
  622. //
  623. // Done with matches
  624. //
  625. return STATUS_SUCCESS;
  626. }
  627. NTSTATUS
  628. PnpiCmResourceToBiosIrq(
  629. IN PUCHAR Buffer,
  630. IN PCM_RESOURCE_LIST List
  631. )
  632. /*++
  633. Routine Description:
  634. This routine stores all of the Irqs in the resource list into the Bios resource
  635. list
  636. Arguments:
  637. Buffer - Pointer to the Bios resource List
  638. List - Pointer to the CM resource List
  639. Return Value:
  640. NTSTATUS
  641. --*/
  642. {
  643. PCM_FULL_RESOURCE_DESCRIPTOR aList;
  644. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  645. PPNP_IRQ_DESCRIPTOR buffer;
  646. ULONG i;
  647. PAGED_CODE();
  648. //
  649. // Setup the initial buffer
  650. //
  651. buffer = (PPNP_IRQ_DESCRIPTOR) Buffer;
  652. ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) >= 2);
  653. //
  654. // We can only have one list...
  655. //
  656. aList = &(List->List[0]);
  657. ASSERT( List->Count == 1);
  658. ASSERT( aList->PartialResourceList.Count );
  659. //
  660. // We can use no interrupts
  661. //
  662. buffer->IrqMask = 0;
  663. //
  664. // Loop for each of the partial resource descriptors
  665. //
  666. for (i = 0; i < aList->PartialResourceList.Count; i++) {
  667. //
  668. // Current descriptor
  669. //
  670. desc = &(aList->PartialResourceList.PartialDescriptors[i]);
  671. //
  672. // Is this an interesting descriptor?
  673. //
  674. if (desc->Type != CmResourceTypeInterrupt) {
  675. //
  676. // No
  677. //
  678. continue;
  679. }
  680. //
  681. // Okay, we have a possible match...
  682. //
  683. if (desc->u.Interrupt.Level >= sizeof(USHORT) * 8) {
  684. //
  685. // Interrupts > 15 are Extended Irqs
  686. //
  687. continue;
  688. }
  689. //
  690. // Here we *have* a match...
  691. //
  692. buffer->IrqMask = ( 1 << desc->u.Interrupt.Level );
  693. if ( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 3) {
  694. //
  695. // Wipe out the previous flags
  696. //
  697. buffer->Information = 0;
  698. if ( (desc->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ) {
  699. buffer->Information |= PNP_IRQ_LATCHED;
  700. } else {
  701. buffer->Information |= PNP_IRQ_LEVEL;
  702. }
  703. if (desc->ShareDisposition == CmResourceShareShared) {
  704. buffer->Information |= PNP_IRQ_SHARED;
  705. }
  706. }
  707. //
  708. // Done with descriptor and match
  709. //
  710. desc->Type = CmResourceTypeNull;
  711. break;
  712. }
  713. //
  714. // Done
  715. //
  716. return STATUS_SUCCESS;
  717. }
  718. NTSTATUS
  719. PnpiCmResourceToBiosMemory(
  720. IN PUCHAR Buffer,
  721. IN PCM_RESOURCE_LIST List
  722. )
  723. /*++
  724. Routine Description:
  725. This routine stores all of the Memory elements in the resource list into the Bios resource
  726. list
  727. Arguments:
  728. Buffer - Pointer to the Bios resource List
  729. List - Pointer to the CM resource List
  730. Return:
  731. NTSTATUS
  732. --*/
  733. {
  734. PCM_FULL_RESOURCE_DESCRIPTOR aList;
  735. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  736. PPNP_MEMORY_DESCRIPTOR buffer;
  737. ULONG i;
  738. PAGED_CODE();
  739. //
  740. // Setup the initial buffer
  741. //
  742. buffer = (PPNP_MEMORY_DESCRIPTOR) Buffer;
  743. ASSERT( buffer->Length == 9);
  744. //
  745. // We can only have one list...
  746. //
  747. aList = &(List->List[0]);
  748. ASSERT( List->Count == 1);
  749. ASSERT( aList->PartialResourceList.Count );
  750. //
  751. // We can use no memory
  752. //
  753. buffer->Information = 0;
  754. buffer->MinimumAddress = 0;
  755. buffer->MaximumAddress = 0;
  756. buffer->Alignment = 0;
  757. buffer->MemorySize = 0;
  758. //
  759. // Loop for each of the partial resource descriptors
  760. //
  761. for (i = 0; i < aList->PartialResourceList.Count; i++) {
  762. //
  763. // Current descriptor
  764. //
  765. desc = &(aList->PartialResourceList.PartialDescriptors[i]);
  766. //
  767. // Is this an interesting descriptor?
  768. //
  769. if (desc->Type != CmResourceTypeMemory) {
  770. //
  771. // No
  772. //
  773. continue;
  774. }
  775. //
  776. // Is this a 24 bit memory descriptor?
  777. //
  778. if ( !(desc->Flags & CM_RESOURCE_MEMORY_24)) {
  779. //
  780. // No
  781. //
  782. continue;
  783. }
  784. //
  785. // Here we *have* a match...
  786. //
  787. buffer->MinimumAddress = buffer->MaximumAddress =
  788. (USHORT) (desc->u.Memory.Start.LowPart >> 8);
  789. buffer->MemorySize = (USHORT) (desc->u.Memory.Length >> 8);
  790. if (desc->Flags & CM_RESOURCE_MEMORY_READ_ONLY) {
  791. buffer->Information |= PNP_MEMORY_READ_ONLY;
  792. } else {
  793. buffer->Information |= PNP_MEMORY_READ_WRITE;
  794. }
  795. //
  796. // Done with descriptor and match
  797. //
  798. desc->Type = CmResourceTypeNull;
  799. break;
  800. }
  801. //
  802. // Done
  803. //
  804. return STATUS_SUCCESS;
  805. }
  806. NTSTATUS
  807. PnpiCmResourceToBiosMemory32(
  808. IN PUCHAR Buffer,
  809. IN PCM_RESOURCE_LIST List
  810. )
  811. /*++
  812. Routine Description:
  813. This routine stores all of the Memory elements in the resource list into the Bios resource
  814. list
  815. Arguments:
  816. Buffer - Pointer to the Bios resource List
  817. List - Pointer to the CM resource List
  818. Return:
  819. NTSTATUS
  820. --*/
  821. {
  822. PCM_FULL_RESOURCE_DESCRIPTOR aList;
  823. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  824. PPNP_MEMORY32_DESCRIPTOR buffer;
  825. ULONG i;
  826. PAGED_CODE();
  827. //
  828. // Setup the initial buffer
  829. //
  830. buffer = (PPNP_MEMORY32_DESCRIPTOR) Buffer;
  831. ASSERT( buffer->Length == 17);
  832. //
  833. // We can only have one list...
  834. //
  835. aList = &(List->List[0]);
  836. ASSERT( List->Count == 1);
  837. ASSERT( aList->PartialResourceList.Count );
  838. //
  839. // We can use no memory
  840. //
  841. buffer->Information = 0;
  842. buffer->MinimumAddress = 0;
  843. buffer->MaximumAddress = 0;
  844. buffer->Alignment = 0;
  845. buffer->MemorySize = 0;
  846. //
  847. // Loop for each of the partial resource descriptors
  848. //
  849. for (i = 0; i < aList->PartialResourceList.Count; i++) {
  850. //
  851. // Current descriptor
  852. //
  853. desc = &(aList->PartialResourceList.PartialDescriptors[i]);
  854. //
  855. // Is this an interesting descriptor?
  856. //
  857. if (desc->Type != CmResourceTypeMemory) {
  858. //
  859. // No
  860. //
  861. continue;
  862. }
  863. //
  864. // Here we *have* a match...
  865. //
  866. buffer->MemorySize = desc->u.Memory.Length;
  867. buffer->MinimumAddress = buffer->MaximumAddress = desc->u.Memory.Start.LowPart;
  868. if (desc->Flags & CM_RESOURCE_MEMORY_READ_ONLY) {
  869. buffer->Information |= PNP_MEMORY_READ_ONLY;
  870. } else {
  871. buffer->Information |= PNP_MEMORY_READ_WRITE;
  872. }
  873. //
  874. // Done with descriptor and match
  875. //
  876. desc->Type = CmResourceTypeNull;
  877. break;
  878. }
  879. //
  880. // Done with matches
  881. //
  882. return STATUS_SUCCESS;
  883. }
  884. NTSTATUS
  885. PnpiCmResourceToBiosMemory32Fixed(
  886. IN PUCHAR Buffer,
  887. IN PCM_RESOURCE_LIST List
  888. )
  889. /*++
  890. Routine Description:
  891. This routine stores all of the Memory elements in the resource list into the Bios resource
  892. list
  893. Arguments:
  894. Buffer - Pointer to the Bios resource List
  895. List - Pointer to the CM resource List
  896. Return:
  897. NTSTATUS
  898. --*/
  899. {
  900. PCM_FULL_RESOURCE_DESCRIPTOR aList;
  901. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  902. PPNP_FIXED_MEMORY32_DESCRIPTOR buffer;
  903. ULONG i;
  904. PAGED_CODE();
  905. //
  906. // Setup the initial buffer
  907. //
  908. buffer = (PPNP_FIXED_MEMORY32_DESCRIPTOR) Buffer;
  909. ASSERT( buffer->Length == 9);
  910. //
  911. // We can only have one list...
  912. //
  913. aList = &(List->List[0]);
  914. ASSERT( List->Count == 1);
  915. ASSERT( aList->PartialResourceList.Count );
  916. //
  917. // We can use no memory
  918. //
  919. buffer->Information = 0;
  920. buffer->BaseAddress = 0;
  921. buffer->MemorySize = 0;
  922. //
  923. // Loop for each of the partial resource descriptors
  924. //
  925. for (i = 0; i < aList->PartialResourceList.Count; i++) {
  926. //
  927. // Current descriptor
  928. //
  929. desc = &(aList->PartialResourceList.PartialDescriptors[i]);
  930. //
  931. // Is this an interesting descriptor?
  932. //
  933. if (desc->Type != CmResourceTypeMemory) {
  934. //
  935. // No
  936. //
  937. continue;
  938. }
  939. //
  940. // Here we *have* a match...
  941. //
  942. buffer->BaseAddress = desc->u.Memory.Start.LowPart;
  943. buffer->MemorySize = desc->u.Memory.Length >> 8;
  944. if (desc->Flags & CM_RESOURCE_MEMORY_READ_ONLY) {
  945. buffer->Information |= PNP_MEMORY_READ_ONLY;
  946. } else {
  947. buffer->Information |= PNP_MEMORY_READ_WRITE;
  948. }
  949. //
  950. // Done with descriptor and match
  951. //
  952. desc->Type = CmResourceTypeNull;
  953. break;
  954. }
  955. //
  956. // Done
  957. //
  958. return STATUS_SUCCESS;
  959. }
  960. BOOLEAN
  961. PnpiCmResourceValidEmptyList(
  962. IN PCM_RESOURCE_LIST List
  963. )
  964. /*++
  965. Routine Description:
  966. This routine takes a CM_RESOURCE_LIST and makes sure that no unallocated elements
  967. remain...
  968. Arguments:
  969. List - List to check
  970. Return Value:
  971. TRUE - Empty
  972. FALSE - Nonempty
  973. --*/
  974. {
  975. PCM_FULL_RESOURCE_DESCRIPTOR aList;
  976. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  977. ULONG i;
  978. PAGED_CODE();
  979. //
  980. // We can only have one list...
  981. //
  982. aList = &(List->List[0]);
  983. ASSERT( List->Count == 1);
  984. ASSERT( aList->PartialResourceList.Count );
  985. //
  986. // Loop for each of the partial resource descriptors
  987. //
  988. for (i = 0; i < aList->PartialResourceList.Count; i++) {
  989. //
  990. // Current descriptor
  991. //
  992. desc = &(aList->PartialResourceList.PartialDescriptors[i]);
  993. //
  994. // Is this an interesting descriptor?
  995. //
  996. if (desc->Type != CmResourceTypeNull) {
  997. //
  998. // No
  999. //
  1000. continue;
  1001. }
  1002. //
  1003. // This element wasn't consumed...<sigh>
  1004. //
  1005. break;
  1006. }
  1007. //
  1008. // Done
  1009. //
  1010. return ( i == aList->PartialResourceList.Count ? TRUE : FALSE );
  1011. }
  1012. NTSTATUS
  1013. PnpCmResourcesToBiosResources(
  1014. IN PCM_RESOURCE_LIST List,
  1015. IN PUCHAR Data
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. This routine takes a CM_RESOURCE_LIST and a _CRS buffer. The routine sets the
  1020. resources in the _CRS buffer to equal to those reported in the CM_RESOURCE_LIST.
  1021. That is: the buffer is used as a template for the new resources that are in
  1022. the system.
  1023. Arguments:
  1024. List - Pointer to the CM_RESOURCE_LIST that we wish to assign
  1025. Data - Where we wish to store the data, and the template for it
  1026. Return Value:
  1027. NTSTATUS
  1028. --*/
  1029. {
  1030. NTSTATUS status = STATUS_SUCCESS;
  1031. PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
  1032. PUCHAR buffer;
  1033. UCHAR tagName;
  1034. USHORT increment;
  1035. PAGED_CODE();
  1036. ASSERT( Data != NULL );
  1037. //
  1038. // Setup initial variables.
  1039. //
  1040. buffer = Data;
  1041. tagName = *buffer;
  1042. //
  1043. // The algorithm we use is that we examine each tag in the buffer, and try to
  1044. // match it with an entry in the resource list. So we take the convertion routine
  1045. // for the previous problem and turn it upside down.
  1046. //
  1047. while (1) {
  1048. //
  1049. // Determine the size of the PNP resource descriptor
  1050. //
  1051. if ( !(tagName & LARGE_RESOURCE_TAG) ) {
  1052. //
  1053. // Small Tag
  1054. //
  1055. increment = (USHORT) (tagName & SMALL_TAG_SIZE_MASK) + 1;
  1056. tagName &= SMALL_TAG_MASK;
  1057. ACPIPrint( (
  1058. ACPI_PRINT_RESOURCES_2,
  1059. "PnpCmResourcesToBiosResources: small tag = %#02lx increment = %#02lx\n",
  1060. tagName, increment
  1061. ) );
  1062. } else {
  1063. //
  1064. // Large Tag
  1065. //
  1066. increment = ( *(USHORT UNALIGNED *)(buffer+1) ) + 3;
  1067. ACPIPrint( (
  1068. ACPI_PRINT_RESOURCES_2,
  1069. "PnpCmResourcesToBiosResources: large tag = %#02lx increment = %#02lx\n",
  1070. tagName, increment
  1071. ) );
  1072. }
  1073. //
  1074. // We are done if the current tag is the end tag
  1075. //
  1076. if (tagName == TAG_END) {
  1077. ACPIPrint( (
  1078. ACPI_PRINT_RESOURCES_2,
  1079. "PnpCmResourcesToBiosResources: TAG_END\n"
  1080. ) );
  1081. break;
  1082. }
  1083. switch(tagName) {
  1084. case TAG_IRQ:
  1085. status = PnpiCmResourceToBiosIrq( buffer, List );
  1086. break;
  1087. case TAG_EXTENDED_IRQ:
  1088. status = PnpiCmResourceToBiosExtendedIrq( buffer, List );
  1089. break;
  1090. case TAG_DMA:
  1091. status = PnpiCmResourceToBiosDma( buffer, List );
  1092. break;
  1093. case TAG_START_DEPEND:
  1094. ASSERT( tagName != TAG_START_DEPEND );
  1095. break;
  1096. case TAG_END_DEPEND:
  1097. ASSERT( tagName != TAG_END_DEPEND );
  1098. break;
  1099. case TAG_IO:
  1100. status = PnpiCmResourceToBiosIoPort( buffer, List );
  1101. break;
  1102. case TAG_IO_FIXED:
  1103. status = PnpiCmResourceToBiosIoFixedPort( buffer, List );
  1104. break;
  1105. case TAG_MEMORY:
  1106. status = PnpiCmResourceToBiosMemory( buffer, List );
  1107. break;
  1108. case TAG_MEMORY32:
  1109. status = PnpiCmResourceToBiosMemory32( buffer, List );
  1110. break;
  1111. case TAG_MEMORY32_FIXED:
  1112. status = PnpiCmResourceToBiosMemory32Fixed( buffer, List );
  1113. break;
  1114. case TAG_WORD_ADDRESS:
  1115. status = PnpiCmResourceToBiosAddress( buffer, List );
  1116. break;
  1117. case TAG_DOUBLE_ADDRESS:
  1118. status = PnpiCmResourceToBiosAddressDouble( buffer, List );
  1119. break;
  1120. case TAG_VENDOR:
  1121. //
  1122. // Ignore this tag
  1123. //
  1124. break;
  1125. default: {
  1126. //
  1127. // Unknown tag. Skip it
  1128. //
  1129. ACPIPrint( (
  1130. ACPI_PRINT_WARNING,
  1131. "PnpBiosResourceToNtResources: TAG_UNKNOWN [tagName = %#02lx]\n",
  1132. tagName
  1133. ) );
  1134. break;
  1135. }
  1136. } // switch
  1137. //
  1138. // Did we fail?
  1139. //
  1140. if (!NT_SUCCESS(status)) {
  1141. break;
  1142. }
  1143. //
  1144. // Move to the next descriptor
  1145. //
  1146. buffer += increment;
  1147. tagName = *buffer;
  1148. }
  1149. if (!( NT_SUCCESS(status) )) {
  1150. return status;
  1151. }
  1152. //
  1153. // Check to see if we have consumed all of the appropriate resources...
  1154. //
  1155. if (PnpiCmResourceValidEmptyList( List ) ) {
  1156. //
  1157. // We failed to empty the list... <sigh>
  1158. //
  1159. return STATUS_UNSUCCESSFUL;
  1160. }
  1161. return STATUS_SUCCESS;
  1162. }