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.

1283 lines
24 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. bios.c
  5. Abstract:
  6. This module implements code to make SMI BIOS calls
  7. Author:
  8. Todd Carpenter (7/20/00) - create file
  9. Environment:
  10. Kernel mode
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include <ntddk.h>
  15. #include <ntacpi.h>
  16. #include "amdk6.h"
  17. LEGACY_GEMINI_SMI LegacyInterface;
  18. #if DBG
  19. VOID
  20. DisplayGBDT (
  21. IN PGBDT GBDT
  22. );
  23. #else
  24. #define DisplayGBDT(_x_)
  25. #endif
  26. #ifdef ALLOC_PRAGMA
  27. #pragma alloc_text(PAGE, FindGBDT)
  28. #pragma alloc_text(PAGE, InitializeLegacyInterface)
  29. #pragma alloc_text(PAGE, IsGeminiSupported)
  30. #endif
  31. NTSTATUS
  32. FindGBDT (
  33. OUT PPGBDT GeminiInfo
  34. )
  35. /*++
  36. Description:
  37. This routine looks in the BIOS memory area for the Gemini BIOS Descriptor
  38. Table. The signature will be located on a 16-byte bountry in the area from
  39. 0C0000h to 0FFFFFh or within the first 1K of the Extended BIOS Data Area.
  40. Arguments:
  41. Return Value:
  42. NTSTATUS
  43. --*/
  44. {
  45. NTSTATUS status = STATUS_UNSUCCESSFUL;
  46. PVOID baseAddress;
  47. PGBDT newGBDTTable;
  48. ULONG_PTR address;
  49. ULONG_PTR limit;
  50. ULONG tableLength;
  51. PHYSICAL_ADDRESS PhysAddress;
  52. DebugEnter();
  53. PAGED_CODE();
  54. PhysAddress.HighPart = 0;
  55. PhysAddress.LowPart = GBDT_SEARCH_RANGE_BEGIN;
  56. //
  57. // Map memory to search for Gemini Bios table
  58. //
  59. baseAddress = MmMapIoSpace(PhysAddress,
  60. GBDT_SEARCH_RANGE_LENGTH,
  61. 0);
  62. if (!baseAddress) {
  63. status = STATUS_INSUFFICIENT_RESOURCES;
  64. goto FindGBDTExit;
  65. }
  66. //
  67. // Compute limit for the for loop. Do not start a scan within 16 bytes of
  68. // physical address 0xFFFFF
  69. //
  70. address = (ULONG_PTR) baseAddress;
  71. limit = address + GBDT_SEARCH_RANGE_LENGTH - GBDT_SEARCH_INTERVAL;
  72. for (; address <= limit; address += GBDT_SEARCH_INTERVAL) {
  73. if ((((PGBDT)address)->Signature == GBDT_SIGNATURE) &&
  74. (GetCheckSum((PUCHAR)address, ((PGBDT)address)->Length) == 0)) {
  75. //
  76. // We found Gemini BIOS Descriptor Table
  77. //
  78. DebugPrint((TRACE, "GBDT Pointer found at: %x\n", address));
  79. newGBDTTable = ExAllocatePoolWithTag(NonPagedPool,
  80. ((PGBDT)address)->Length,
  81. PROCESSOR_POOL_TAG);
  82. if (!newGBDTTable) {
  83. status = STATUS_INSUFFICIENT_RESOURCES;
  84. goto FindGBDTExit;
  85. }
  86. //
  87. // Copy the Gemini BIOS Descriptor Table
  88. //
  89. RtlCopyMemory(newGBDTTable,
  90. (PVOID) address,
  91. ((PGBDT)address)->Length);
  92. //
  93. // Unmap mapped memory
  94. //
  95. MmUnmapIoSpace(baseAddress, GBDT_SEARCH_RANGE_LENGTH);
  96. if (ARGUMENT_PRESENT(GeminiInfo)) {
  97. *GeminiInfo = newGBDTTable;
  98. }
  99. status = STATUS_SUCCESS;
  100. goto FindGBDTExit;
  101. }
  102. }
  103. FindGBDTExit:
  104. DebugExitStatus(status);
  105. return status;
  106. }
  107. NTSTATUS
  108. InitializeLegacyInterface (
  109. VOID
  110. )
  111. /*++
  112. Description:
  113. Arguments:
  114. Return Value:
  115. NTSTATUS
  116. --*/
  117. {
  118. NTSTATUS status;
  119. ULONG currentState;
  120. ULONG platform = 0;
  121. DebugEnter();
  122. PAGED_CODE();
  123. status = FindGBDT(&LegacyInterface.GBDT);
  124. if (!NT_SUCCESS(status)) {
  125. goto InitializeLegacyInterfaceExit;
  126. }
  127. DisplayGBDT(LegacyInterface.GBDT);
  128. //
  129. // Setup LegacyInterface structure
  130. //
  131. LegacyInterface.SmiAccessType = LegacyInterface.GBDT->SmiCommandPortType & 0x1;
  132. LegacyInterface.SmiAccessSize = (LegacyInterface.GBDT->SmiCommandPortType >> 0x4) & 0x3;
  133. LegacyInterface.SmiAddress = LegacyInterface.GBDT->SmiCommandPortAddress;
  134. LegacyInterface.GeminiCode = LegacyInterface.GBDT->GeminiSmiCode;
  135. LegacyInterface.MaxSupportedStates = LegacyInterface.GBDT->MaxStateSupported + 1;
  136. LegacyInterface.CurrentlyAvailableStates = LegacyInterface.GBDT->MaxStateSupported + 1;
  137. //
  138. // No perf states, we bail
  139. //
  140. if (LegacyInterface.CurrentlyAvailableStates == 0) {
  141. status = STATUS_UNSUCCESSFUL;
  142. goto InitializeLegacyInterfaceExit;
  143. }
  144. status = IsGeminiSupported(&platform);
  145. //
  146. // if this is not a Gemini System or not of the K6 family, fail.
  147. //
  148. if (!NT_SUCCESS(status) || (platform != PLATFORM_AMDK6)) {
  149. status = STATUS_UNSUCCESSFUL;
  150. goto InitializeLegacyInterfaceExit;
  151. }
  152. status = GetCurrentStateSmm(&currentState);
  153. if (!NT_SUCCESS(status)) {
  154. goto InitializeLegacyInterfaceExit;
  155. }
  156. DebugAssert(currentState <= LegacyInterface.GBDT->MaxStateSupported);
  157. LegacyInterface.CurrentState = CONVERT_PERF_STATE_INDEX(currentState);
  158. //
  159. // Use direct transition method instead of SMI method
  160. //
  161. EnableGeminiTransitionsMSR(&LegacyInterface.EpmIoAddress);
  162. InitializeLegacyInterfaceExit:
  163. DebugExitStatus(status);
  164. return status;
  165. }
  166. NTSTATUS
  167. IsGeminiSupported (
  168. PULONG Results
  169. )
  170. /*++
  171. Description:
  172. Input:
  173. CX = 0000h
  174. ESI = Gemini_Code
  175. Output:
  176. ESI = 0 SMI was entered successfully
  177. ESI <> 0 SMI was entered, but function failed.
  178. ESI = Gemini Code, SMI was never entered
  179. CF = 0 SMM Function Successful
  180. CF = 1 SMM Function Failed, ESI = error code (see below)
  181. 0x90 requested Gemini State change not supported by hardware
  182. 0x91 the attempted State change failed upon read-back
  183. 0x92 function not supported in current implementation
  184. 0x94 the input parameters were erroneous/invalid
  185. AL = 6 (K6 Gemini platform), 7 (K7 Mustang platform)
  186. Arguments:
  187. Return Value:
  188. NTSTATUS
  189. --*/
  190. {
  191. NTSTATUS status = STATUS_NOT_SUPPORTED;
  192. ULONG esiReturned;
  193. UCHAR platform;
  194. PAGED_CODE();
  195. //
  196. // need to check whether type is I/O or memory mapped
  197. // need to check access type size
  198. //
  199. _asm {
  200. mov ecx, IS_GEMINI_SUPPORTED
  201. mov edx, LegacyInterface.SmiAddress
  202. mov esi, LegacyInterface.GeminiCode
  203. out dx, al
  204. mov esiReturned, esi
  205. test esi, esi
  206. jnz SmmFailed
  207. mov platform, al
  208. }
  209. if (ARGUMENT_PRESENT(Results)) {
  210. ASSERT((platform == PLATFORM_AMDK6) || (platform == PLATFORM_AMDK7));
  211. *Results = (ULONG) platform;
  212. }
  213. return STATUS_SUCCESS;
  214. SmmFailed:
  215. if (esiReturned == LegacyInterface.GeminiCode) {
  216. //
  217. // SMI failed, SMM was never entered.
  218. //
  219. } else {
  220. //
  221. // SMI was successful, but SMM operation failed (esi == failure)
  222. //
  223. }
  224. DebugPrint((ERROR, "IsGeminiSupported() Failed: ESI = 0x%x\n", esiReturned));
  225. return STATUS_UNSUCCESSFUL;
  226. }
  227. #if 0
  228. NTSTATUS
  229. GetAvailableStatesSmm (
  230. PULONG Results
  231. )
  232. /*++
  233. Description:
  234. Input:
  235. CX = 0001h
  236. ESI = Gemini_Code
  237. Output:
  238. ESI = 0 SMI was entered successfully
  239. ESI = Gemini Code, SMI was never entered
  240. CF = 0 SMM Operation Successful
  241. CF = 1 SMM Operation Failed, ESI = error code.
  242. BX = # of vaild entries
  243. Arguments:
  244. Return Value:
  245. NTSTATUS
  246. --*/
  247. {
  248. NTSTATUS status = STATUS_NOT_SUPPORTED;
  249. ULONG esiReturned, bufferSize;
  250. USHORT stateEntries;
  251. PHYSICAL_ADDRESS stateBuffer;
  252. static AVAILABLE_STATE_INFO AvailableStates[16] = {0};
  253. TRAP();
  254. PAGED_CODE();
  255. //
  256. // Allocate buffer to hold state information for each state
  257. // LegacyInterface.GBDT->CurrentlyAvailableStates * sizeof(AVAILABLE_STATE_INFO)
  258. // For now we will just use a global array set to hold max size
  259. //
  260. bufferSize = sizeof(AvailableStates);
  261. stateBuffer = MmGetPhysicalAddress((PVOID)AvailableStates);
  262. ASSERT(stateBuffer.QuadPart);
  263. _asm {
  264. mov ecx, GET_GEMINI_STATES
  265. mov edx, LegacyInterface.SmiAddress
  266. mov esi, LegacyInterface.GeminiCode
  267. mov eax, stateBuffer.LowPart
  268. mov ebx, bufferSize
  269. out dx, al
  270. mov esiReturned, esi
  271. test esi, esi
  272. jnz SmmFailed
  273. mov stateEntries, bx
  274. }
  275. if (ARGUMENT_PRESENT(Results)) {
  276. ASSERT((stateEntries > 0) || (stateEntries <= 16));
  277. *Results = (ULONG) stateEntries;
  278. }
  279. return STATUS_SUCCESS;
  280. SmmFailed:
  281. if (esiReturned == LegacyInterface.GeminiCode) {
  282. //
  283. // SMI failed, SMM was never entered.
  284. //
  285. } else {
  286. //
  287. // SMI was successful, but SMM operation failed (esi == failure)
  288. //
  289. }
  290. DebugPrint((ERROR, "GetAvailableStatesSmm() Failed: ESI = 0x%x\n", esiReturned));
  291. return STATUS_UNSUCCESSFUL;
  292. }
  293. NTSTATUS
  294. GetMaxStateSmm (
  295. PULONG Results
  296. )
  297. /*++
  298. Description:
  299. Input:
  300. CX = 0002h
  301. ESI = Gemini_Code
  302. Output:
  303. ESI = 0 SMI was entered successfully
  304. ESI = Gemini Code, SMI was never entered
  305. CF = 0 SMM Operation Successful
  306. CF = 1 SMM Operation Failed, ESI = error code.
  307. AH = BF
  308. AL = VID
  309. BL = Gemini State number
  310. Arguments:
  311. Return Value:
  312. NTSTATUS
  313. --*/
  314. {
  315. NTSTATUS status = STATUS_NOT_SUPPORTED;
  316. ULONG esiReturned;
  317. UCHAR state;
  318. TRAP();
  319. PAGED_CODE();
  320. _asm {
  321. mov ecx, GET_MAX_GEMINI_STATE
  322. mov edx, LegacyInterface.SmiAddress
  323. mov esi, LegacyInterface.GeminiCode
  324. out dx, al
  325. mov esiReturned, esi
  326. test esi, esi
  327. jnz SmmFailed
  328. mov state, bl
  329. }
  330. //
  331. // NOTE: currently we don't do use the VID and BF data returned in
  332. // AX as it is a bit redundant because we should already have
  333. // that data from the Gemini Bios Descriptor Table.
  334. //
  335. if (ARGUMENT_PRESENT(Results)) {
  336. *Results = (ULONG) state;
  337. }
  338. return STATUS_SUCCESS;
  339. SmmFailed:
  340. if (esiReturned == LegacyInterface.GeminiCode) {
  341. //
  342. // SMI failed, SMM was never entered.
  343. //
  344. } else {
  345. //
  346. // SMI was successful, but SMM operation failed (esi == failure)
  347. //
  348. }
  349. DebugPrint((ERROR, "GetMaxStateSmm() Failed: ESI = 0x%x\n", esiReturned));
  350. return STATUS_UNSUCCESSFUL;
  351. }
  352. NTSTATUS
  353. SetMaxStateSmm (
  354. VOID
  355. )
  356. /*++
  357. Description:
  358. Input:
  359. CX = 0003h
  360. ESI = Gemini_Code
  361. Output:
  362. ESI = 0 SMI was entered successfully
  363. ESI = Gemini Code, SMI was never entered
  364. CF = 0 SMM Operation Successful
  365. CF = 1 SMM Operation Failed, ESI = error code.
  366. Arguments:
  367. Return Value:
  368. NTSTATUS
  369. --*/
  370. {
  371. NTSTATUS status = STATUS_NOT_SUPPORTED;
  372. ULONG esiReturned;
  373. UCHAR maxState;
  374. TRAP();
  375. PAGED_CODE();
  376. _asm {
  377. mov ecx, SET_MAX_GEMINI_STATE
  378. mov edx, LegacyInterface.SmiAddress
  379. mov esi, LegacyInterface.GeminiCode
  380. out dx, al
  381. mov esiReturned, esi
  382. test esi, esi
  383. jnz SmmFailed
  384. }
  385. return STATUS_SUCCESS;
  386. SmmFailed:
  387. if (esiReturned == LegacyInterface.GeminiCode) {
  388. //
  389. // SMI failed, SMM was never entered.
  390. //
  391. } else {
  392. //
  393. // SMI was successful, but SMM operation failed (esi == failure)
  394. //
  395. }
  396. DebugPrint((ERROR, "SetMaxStateSmm() Failed: ESI = 0x%x\n", esiReturned));
  397. return STATUS_UNSUCCESSFUL;
  398. }
  399. NTSTATUS
  400. GetMinStateSmm (
  401. PULONG Results
  402. )
  403. /*++
  404. Description:
  405. Input:
  406. CX = 0004h
  407. ESI = Gemini_Code
  408. Output:
  409. ESI = 0 SMI was entered successfully
  410. ESI = Gemini Code, SMI was never entered
  411. CF = 0 SMM Operation Successful
  412. CF = 1 SMM Operation Failed, ESI = error code.
  413. AH = BF
  414. AL = VID
  415. BL = Gemini State number
  416. Arguments:
  417. Return Value:
  418. NTSTATUS
  419. --*/
  420. {
  421. NTSTATUS status = STATUS_NOT_SUPPORTED;
  422. ULONG esiReturned;
  423. UCHAR state;
  424. TRAP();
  425. PAGED_CODE();
  426. _asm {
  427. mov ecx, GET_MIN_GEMINI_STATE
  428. mov edx, LegacyInterface.SmiAddress
  429. mov esi, LegacyInterface.GeminiCode
  430. out dx, al
  431. mov esiReturned, esi
  432. test esi, esi
  433. jnz SmmFailed
  434. mov state, bl
  435. }
  436. //
  437. // NOTE: currently we don't do use the VID and BF data returned in
  438. // AX as it is a bit redundant because we should already have
  439. // that data from the Gemini Bios Descriptor Table.
  440. //
  441. if (ARGUMENT_PRESENT(Results)) {
  442. *Results = (ULONG) state;
  443. }
  444. return STATUS_SUCCESS;
  445. SmmFailed:
  446. if (esiReturned == LegacyInterface.GeminiCode) {
  447. //
  448. // SMI failed, SMM was never entered.
  449. //
  450. } else {
  451. //
  452. // SMI was successful, but SMM operation failed (esi == failure)
  453. //
  454. }
  455. DebugPrint((ERROR, "GetMinStateSmm() Failed: ESI = 0x%x\n", esiReturned));
  456. return STATUS_UNSUCCESSFUL;
  457. }
  458. NTSTATUS
  459. SetMinStateSmm (
  460. VOID
  461. )
  462. /*++
  463. Description:
  464. Input:
  465. CX = 0005h
  466. ESI = Gemini_Code
  467. Output:
  468. ESI = 0 SMI was entered successfully
  469. ESI = Gemini Code, SMI was never entered
  470. CF = 0 SMM Operation Successful
  471. CF = 1 SMM Operation Failed, ESI = error code.
  472. Arguments:
  473. Return Value:
  474. NTSTATUS
  475. --*/
  476. {
  477. NTSTATUS status = STATUS_NOT_SUPPORTED;
  478. ULONG esiReturned;
  479. UCHAR maxState;
  480. TRAP();
  481. PAGED_CODE();
  482. _asm {
  483. mov ecx, SET_MIN_GEMINI_STATE
  484. mov edx, LegacyInterface.SmiAddress
  485. mov esi, LegacyInterface.GeminiCode
  486. out dx, al
  487. mov esiReturned, esi
  488. test esi, esi
  489. jnz SmmFailed
  490. }
  491. return STATUS_SUCCESS;
  492. SmmFailed:
  493. if (esiReturned == LegacyInterface.GeminiCode) {
  494. //
  495. // SMI failed, SMM was never entered.
  496. //
  497. } else {
  498. //
  499. // SMI was successful, but SMM operation failed (esi == failure)
  500. //
  501. }
  502. DebugPrint((ERROR, "SetMinStateSmm() Failed: ESI = 0x%x\n", esiReturned));
  503. return STATUS_UNSUCCESSFUL;
  504. }
  505. NTSTATUS
  506. SetCurrentStateSmm (
  507. ULONG State
  508. )
  509. /*++
  510. Description:
  511. Input:
  512. CX = 0007h
  513. ESI = Gemini_Code
  514. AL = Gemini State Number
  515. Output:
  516. ESI = 0 SMI was entered successfully
  517. ESI = Gemini Code, SMI was never entered
  518. CF = 0 SMM Operation Successful
  519. CF = 1 SMM Operation Failed, ESI = error code.
  520. Arguments:
  521. Return Value:
  522. NTSTATUS
  523. --*/
  524. {
  525. NTSTATUS status = STATUS_NOT_SUPPORTED;
  526. ULONG esiReturned, geminiState;
  527. UCHAR vidANDbf;
  528. //
  529. // Convert to Gemini State
  530. //
  531. geminiState = CONVERT_PERF_STATE_INDEX(State);
  532. //
  533. // Lookup VID and BF values for geminiState
  534. //
  535. vidANDbf = (LegacyInterface.GBDT->State[geminiState].Vid) |
  536. ((LegacyInterface.GBDT->State[geminiState].Bf) << 5);
  537. _asm {
  538. mov ecx, SET_CURRENT_GEMINI_STATE
  539. mov edx, LegacyInterface.SmiAddress
  540. mov esi, LegacyInterface.GeminiCode
  541. mov al, vidANDbf
  542. out dx, al
  543. mov esiReturned, esi
  544. test esi, esi
  545. jnz SmmFailed
  546. }
  547. return STATUS_SUCCESS;
  548. SmmFailed:
  549. if (esiReturned == LegacyInterface.GeminiCode) {
  550. //
  551. // SMI failed, SMM was never entered.
  552. //
  553. } else {
  554. //
  555. // SMI was successful, but SMM operation failed (esi == failure)
  556. //
  557. }
  558. DebugPrint((ERROR, "SetCurrentStateSmm() Failed: ESI = 0x%x\n", esiReturned));
  559. return STATUS_UNSUCCESSFUL;
  560. }
  561. NTSTATUS
  562. ConnectDisconnectGeminiInterface (
  563. BOOLEAN Connect
  564. )
  565. /*++
  566. Description:
  567. Input:
  568. CX = 0200h connect, 0201h disconnect
  569. ESI = Gemini_Code
  570. Output:
  571. ESI = 0 SMI was entered successfully
  572. ESI = Gemini Code, SMI was never entered
  573. CF = 0 SMM Operation Successful
  574. CF = 1 SMM Operation Failed, ESI = error code.
  575. Arguments:
  576. Return Value:
  577. NTSTATUS
  578. --*/
  579. {
  580. NTSTATUS status = STATUS_NOT_SUPPORTED;
  581. ULONG esiReturned, function;
  582. TRAP();
  583. PAGED_CODE();
  584. function = Connect ? GEMINI_CONNECT : GEMINI_DISCONNECT;
  585. _asm {
  586. mov ecx, function
  587. mov edx, LegacyInterface.SmiAddress
  588. mov esi, LegacyInterface.GeminiCode
  589. out dx, al
  590. mov esiReturned, esi
  591. test esi, esi
  592. jnz SmmFailed
  593. }
  594. return STATUS_SUCCESS;
  595. SmmFailed:
  596. if (esiReturned == LegacyInterface.GeminiCode) {
  597. //
  598. // SMI failed, SMM was never entered.
  599. //
  600. } else {
  601. //
  602. // SMI was successful, but SMM operation failed (esi == failure)
  603. //
  604. }
  605. DebugPrint((ERROR, "ConnectDisconnectGeminiInterface() Failed: ESI = 0x%x\n", esiReturned));
  606. return STATUS_UNSUCCESSFUL;
  607. }
  608. #endif
  609. NTSTATUS
  610. GetCurrentStateSmm (
  611. PULONG Results
  612. )
  613. /*++
  614. Description:
  615. Input:
  616. CX = 0006h
  617. ESI = Gemini_Code
  618. Output:
  619. ESI = 0 SMI was entered successfully
  620. ESI = Gemini Code, SMI was never entered
  621. CF = 0 SMM Operation Successful
  622. CF = 1 SMM Operation Failed, ESI = error code.
  623. AH = BF value
  624. AL = VID value
  625. BL = Gemini State number
  626. BH[0] = 0 (DC power)
  627. BH[0] = 1 (AC power)
  628. Arguments:
  629. Return Value:
  630. NTSTATUS
  631. --*/
  632. {
  633. NTSTATUS status = STATUS_NOT_SUPPORTED;
  634. ULONG esiReturned, state;
  635. UCHAR vidANDbf;
  636. PAGED_CODE();
  637. _asm {
  638. xor ebx, ebx
  639. xor eax, eax
  640. mov ecx, GET_CURRENT_GEMINI_STATE
  641. mov edx, LegacyInterface.SmiAddress
  642. mov esi, LegacyInterface.GeminiCode
  643. out dx, al
  644. mov esiReturned, esi
  645. test esi, esi
  646. jnz SmmFailed
  647. mov vidANDbf, al
  648. }
  649. //
  650. // NOTE: currently we don't do use the VID and BF data returned in
  651. // AX as it is a bit redundant because we should already have
  652. // that data from the Gemini Bios Descriptor Table.
  653. //
  654. // we are not currentingly using the AC / DC indicator either.
  655. // this information is returned in BH [0 ].
  656. //
  657. //
  658. // Lookup VID and BF values for geminiState
  659. //
  660. status = ConvertVidBfValueToGeminiState(vidANDbf, &state);
  661. DebugAssert(status == STATUS_SUCCESS);
  662. if (ARGUMENT_PRESENT(Results)) {
  663. *Results = (ULONG) state;
  664. }
  665. return STATUS_SUCCESS;
  666. SmmFailed:
  667. if (esiReturned == LegacyInterface.GeminiCode) {
  668. //
  669. // SMI failed, SMM was never entered.
  670. //
  671. } else {
  672. //
  673. // SMI was successful, but SMM operation failed (esi == failure)
  674. //
  675. }
  676. DebugPrint((ERROR, "GetCurrentStateSmm() Failed: ESI = 0x%x\n", esiReturned));
  677. return STATUS_UNSUCCESSFUL;
  678. }
  679. NTSTATUS
  680. GetCpuFrequency (
  681. IN ULONG State,
  682. OUT PULONG CpuSpeed
  683. )
  684. /*++
  685. Routine Description:
  686. Arguments:
  687. Return Value:
  688. --*/
  689. {
  690. ULONG geminiState;
  691. ASSERT(LegacyInterface.GBDT);
  692. geminiState = CONVERT_PERF_STATE_INDEX(State);
  693. if (ARGUMENT_PRESENT(CpuSpeed)) {
  694. *CpuSpeed = LegacyInterface.GBDT->State[geminiState].CpuFrequency;
  695. }
  696. return STATUS_SUCCESS;
  697. }
  698. NTSTATUS
  699. GetCpuVoltage (
  700. IN ULONG State,
  701. OUT PULONG Voltage
  702. )
  703. /*++
  704. Routine Description:
  705. Arguments:
  706. Return Value:
  707. --*/
  708. {
  709. ULONG geminiState;
  710. USHORT bcdVoltage;
  711. ULONG intVoltage;
  712. DebugAssert(LegacyInterface.GBDT);
  713. geminiState = CONVERT_PERF_STATE_INDEX(State);
  714. bcdVoltage = LegacyInterface.GBDT->State[geminiState].CpuVoltage;
  715. intVoltage = Bcd8ToUlong(bcdVoltage);
  716. if (ARGUMENT_PRESENT(Voltage)) {
  717. *Voltage = intVoltage;
  718. }
  719. return STATUS_SUCCESS;
  720. }
  721. NTSTATUS
  722. GetLegacyMaxProcFrequency (
  723. OUT PULONG CpuSpeed
  724. )
  725. /*++
  726. Description:
  727. Arguments:
  728. Return Value:
  729. NTSTATUS
  730. --*/
  731. {
  732. DebugAssert(CpuSpeed);
  733. if (LegacyInterface.GBDT) {
  734. *CpuSpeed = LegacyInterface.GBDT->MaxCpuSpeed;
  735. return STATUS_SUCCESS;
  736. }
  737. return STATUS_UNSUCCESSFUL;
  738. }
  739. NTSTATUS
  740. ConvertVidBfValueToGeminiState (
  741. IN UCHAR VidBfValue,
  742. OUT PULONG State
  743. )
  744. /*++
  745. Routine Description:
  746. Arguments:
  747. Return Value:
  748. --*/
  749. {
  750. NTSTATUS status;
  751. ULONG state, x;
  752. UCHAR vid, bf;
  753. vid = VidBfValue & 0x1f; // vid[4:0]
  754. bf = VidBfValue >> 5; // bf[7:5]
  755. for (x = 0; x < LegacyInterface.CurrentlyAvailableStates; x++) {
  756. if ((LegacyInterface.GBDT->State[x].Vid == vid) &&
  757. (LegacyInterface.GBDT->State[x].Bf == bf)) {
  758. if (ARGUMENT_PRESENT(State)) {
  759. *State = x;
  760. }
  761. return STATUS_SUCCESS;
  762. }
  763. }
  764. DebugPrint((ERROR, "Couldn't find a match for vid=0x%x and bf=0x%x\n", vid, bf));
  765. return STATUS_UNSUCCESSFUL;
  766. }
  767. #if DBG
  768. VOID
  769. DisplayGBDT (
  770. IN PGBDT GBDT
  771. )
  772. {
  773. ULONG x;
  774. DebugPrint((MAXTRACE, "\n"));
  775. DebugPrint((MAXTRACE, "Gemini BIOS Descriptor Table:\n"));
  776. DebugPrint((MAXTRACE, " Signature = %.4s\n", &GBDT->Signature)); // ULONG
  777. DebugPrint((MAXTRACE, " Length = 0x%x\n", GBDT->Length)); // UCHAR
  778. DebugPrint((MAXTRACE, " Bios Revision = 0x%x\n", GBDT->Revsion)); // UCHAR
  779. DebugPrint((MAXTRACE, " Checksum = 0x%x\n", GBDT->Checksum)); // UCHAR
  780. DebugPrint((MAXTRACE, " Capabilities = 0x%x\n", GBDT->Capabilities));// UCHAR
  781. DebugPrint((MAXTRACE, " - TALERT is %ssupported\n", (GBDT->Capabilities & 0x1) ? "" : "NOT "));
  782. DebugPrint((MAXTRACE, " - TPANIC is %ssupported\n", (GBDT->Capabilities & 0x2) ? "" : "NOT "));
  783. DebugPrint((MAXTRACE, " Bus Speed = %u mhz\n", GBDT->BusSpeed)); // USHORT
  784. DebugPrint((MAXTRACE, " Max CPU Speed = %u mhz\n", GBDT->MaxCpuSpeed));// USHORT
  785. DebugPrint((MAXTRACE, " Max CPU State = %u\n", GBDT->MaxStateSupported)); // UCHAR
  786. DebugPrint((MAXTRACE, " SMI Port Type = 0x%x\n", GBDT->SmiCommandPortType)); // UCHAR
  787. DebugPrint((MAXTRACE, " - %s address\n", (GBDT->SmiCommandPortType & 0x1) ? "memory mapped" : "x86 I/O"));
  788. DebugPrint((MAXTRACE, " - Data Size = %u bits\n", ((GBDT->SmiCommandPortType >> 0x4) & 0x3) * 8));
  789. DebugPrint((MAXTRACE, " SMI Port Address = 0x%x\n", GBDT->SmiCommandPortAddress)); // ULONG
  790. DebugPrint((MAXTRACE, " Gemini Code = 0x%x\n", GBDT->GeminiSmiCode)); // ULONG
  791. DebugPrint((MAXTRACE, " Perf States:\n"));
  792. for (x=0; x <= GBDT->MaxStateSupported; x++) {
  793. DebugPrint((MAXTRACE, " State %u:\n", x));
  794. DebugPrint((MAXTRACE, " - Voltage = 0x%x\n", GBDT->State[x].CpuVoltage));
  795. DebugPrint((MAXTRACE, " - Frequency = %u%\n", GBDT->State[x].CpuFrequency));
  796. DebugPrint((MAXTRACE, " - VID = 0x%x\n", GBDT->State[x].Vid));
  797. DebugPrint((MAXTRACE, " - BF = 0x%x\n", GBDT->State[x].Bf));
  798. }
  799. DebugPrint((MAXTRACE, "\n"));
  800. }
  801. #endif