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.

226 lines
4.9 KiB

  1. /*++
  2. Copyright (c) 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. hwapm.c
  5. Abstract:
  6. Author:
  7. Environment:
  8. Real mode.
  9. Revision History:
  10. --*/
  11. #include "hwdetect.h"
  12. #include <string.h>
  13. #include "apm.h"
  14. #include <ntapmsdk.h>
  15. ULONG
  16. HwWriteLog(
  17. PUCHAR p,
  18. UCHAR loc,
  19. ULONG data
  20. );
  21. UCHAR DetName[] = "DETLOG1";
  22. VOID Int15 (PULONG, PULONG, PULONG, PULONG, PULONG);
  23. BOOLEAN
  24. HwGetApmSystemData(
  25. PVOID Buf
  26. )
  27. {
  28. PAPM_REGISTRY_INFO ApmEntry;
  29. ULONG RegEax, RegEbx, RegEcx, RegEdx, CyFlag;
  30. UCHAR ApmMajor, ApmMinor;
  31. PUCHAR lp, p;
  32. ApmEntry = Buf;
  33. ApmEntry->Signature[0] = 'A';
  34. ApmEntry->Signature[1] = 'P';
  35. ApmEntry->Signature[2] = 'M';
  36. ApmEntry->Valid = 0;
  37. lp = &(ApmEntry->DetectLog[0]);
  38. p = DetName;
  39. while (*p != '\0') {
  40. *lp = *p;
  41. p++;
  42. lp++;
  43. }
  44. //
  45. // Perform APM installation check
  46. //
  47. RegEax = APM_INSTALLATION_CHECK;
  48. RegEbx = APM_DEVICE_BIOS;
  49. Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
  50. if (CyFlag ||
  51. (RegEbx & 0xff) != 'M' ||
  52. ((RegEbx >> 8) & 0xff) != 'P') {
  53. //
  54. // this is a case where int15 says apm just isn't there,
  55. // so tell the caller to not even create the node
  56. //
  57. return FALSE;
  58. }
  59. //
  60. // If we get here, we have an APM bios. If we just call it,
  61. // we may get grief. So we will connect in real mode, then
  62. // set our version to whatever the driver says it is, or 1.2,
  63. // whichever is LESS. Then query options again.
  64. //
  65. ApmMajor = (UCHAR) (RegEax >> 8) & 0xff;
  66. ApmMinor = (UCHAR) RegEax & 0xff;
  67. if (ApmMajor > 1) ApmMajor = 1;
  68. if (ApmMinor > 2) ApmMinor = 2;
  69. //
  70. // Connect to Real mode interface
  71. //
  72. RegEax = APM_REAL_MODE_CONNECT;
  73. RegEbx = APM_DEVICE_BIOS;
  74. Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
  75. if (CyFlag) {
  76. lp += HwWriteLog(lp, 'A', RegEax);
  77. return TRUE;
  78. }
  79. //
  80. // Call APM Driver Version in real mode, and set the driver
  81. // version to be MIN(v1.2, apm version of the machine)
  82. //
  83. RegEax = APM_DRIVER_VERSION;
  84. RegEbx = APM_DEVICE_BIOS;
  85. RegEcx = ((ApmMajor << 8) | ApmMinor) & 0xffff;
  86. Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
  87. if (CyFlag) {
  88. lp += HwWriteLog(lp, 'B', RegEax);
  89. return TRUE;
  90. }
  91. //
  92. // Perform APM installation check again
  93. //
  94. RegEax = APM_INSTALLATION_CHECK;
  95. RegEbx = APM_DEVICE_BIOS;
  96. Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
  97. if (CyFlag) {
  98. lp += HwWriteLog(lp, 'C', RegEax);
  99. return TRUE;
  100. }
  101. ApmEntry->ApmRevMajor = (UCHAR) (RegEax >> 8) & 0xff;
  102. ApmEntry->ApmRevMinor = (UCHAR) RegEax & 0xff;
  103. ApmEntry->ApmInstallFlags = (USHORT) RegEcx;
  104. //
  105. // Disconnect from real mode interface
  106. //
  107. RegEax = APM_DISCONNECT;
  108. RegEbx = APM_DEVICE_BIOS;
  109. Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
  110. if (CyFlag) {
  111. lp += HwWriteLog(lp, 'D', RegEax);
  112. return TRUE;
  113. }
  114. //
  115. // If we get this far, there's an APM bios in the machine,
  116. // and we've told it that we're the latest version we think
  117. // it and we like, so now, in theory, things should just work....
  118. //
  119. if (ApmEntry->ApmInstallFlags & APM_MODE_16BIT) {
  120. //
  121. // Connect to 16 bit interface
  122. //
  123. RegEax = APM_PROTECT_MODE_16bit_CONNECT;
  124. RegEbx = APM_DEVICE_BIOS;
  125. Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
  126. if (CyFlag) {
  127. lp += HwWriteLog(lp, 'E', RegEax);
  128. return TRUE;
  129. }
  130. ApmEntry->Code16BitSegment = (USHORT) RegEax;
  131. ApmEntry->Code16BitOffset = (USHORT) RegEbx;
  132. ApmEntry->Data16BitSegment = (USHORT) RegEcx;
  133. //
  134. // On most bioses, the following call just works.
  135. // On some, it doesn't, and their authors point at the spec.
  136. // And finally, most bioses don't seem to need this call
  137. // in the first place.
  138. // We cannot do it in ntapm.sys because it's on the loader's
  139. // hibernate resume path as well as here.
  140. //
  141. // SO> make the call, report any error, but IGNORE it.
  142. //
  143. RegEax = APM_DRIVER_VERSION;
  144. RegEbx = APM_DEVICE_BIOS;
  145. RegEcx = ((ApmMajor << 8) | ApmMinor) & 0xffff;
  146. Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
  147. if (CyFlag) {
  148. lp += HwWriteLog(lp, 'F', RegEax);
  149. ApmEntry->Valid = 1; // pretend it worked....
  150. return TRUE;
  151. }
  152. ApmEntry->Valid = 1;
  153. return TRUE;
  154. }
  155. HwWriteLog(lp, 'H', ApmEntry->ApmInstallFlags);
  156. return TRUE;
  157. }
  158. ULONG
  159. HwWriteLog(
  160. PUCHAR p,
  161. UCHAR loc,
  162. ULONG data
  163. )
  164. {
  165. p[0] = loc;
  166. p[1] = (UCHAR)(data & 0xff);
  167. p[2] = (UCHAR)((data & 0xff00) >> 8);
  168. return 4;
  169. }