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.

509 lines
11 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. acpiio.c
  5. Abstract:
  6. ACPI OS Independent I/O routines
  7. Author:
  8. Jason Clark (JasonCl)
  9. Stephane Plante (SPlante)
  10. Environment:
  11. NT Kernel Model Driver only
  12. Revision History:
  13. Eric Nelson - Add Def[ault]Read/Write routines
  14. --*/
  15. #include "pch.h"
  16. //
  17. // This driver is not in alpha or beta stages any more --- we can save some
  18. // CPU calls if we simply define the debug function to nothing
  19. //
  20. #define DebugTraceIO(Write, Port, Length, Value )
  21. static UCHAR IOTrace = 0;
  22. VOID
  23. ACPIIoDebugTrace(
  24. BOOLEAN Write,
  25. PUSHORT Port,
  26. UCHAR Length,
  27. ULONG Value
  28. )
  29. {
  30. if (IOTrace != 0) {
  31. ACPIPrint( (
  32. ACPI_PRINT_IO,
  33. "%x byte %s port 0x%x value %x\n",
  34. Length, Write ? "WRITE" : "READ", Port, Value
  35. ) );
  36. }
  37. }
  38. ULONG
  39. ACPIIoReadPm1Status(
  40. VOID
  41. )
  42. /*++
  43. Routine Description:
  44. This routine reads the PM1 Status registers and masks off any bits that
  45. we don't care about. This is done because some of these bits are actually
  46. owned by the HAL
  47. Arguments:
  48. None
  49. Return Value:
  50. ULONG
  51. --*/
  52. {
  53. return READ_PM1_STATUS() &
  54. (AcpiInformation->pm1_en_bits | PM1_WAK_STS | PM1_TMR_STS | PM1_RTC_STS);
  55. }
  56. VOID
  57. CLEAR_PM1_STATUS_BITS (
  58. USHORT BitMask
  59. )
  60. {
  61. if (AcpiInformation->PM1a_BLK != 0) {
  62. WRITE_ACPI_REGISTER(PM1a_STATUS, 0, BitMask);
  63. DebugTraceIO(
  64. TRUE,
  65. (PUSHORT)(AcpiInformation->PM1a_BLK+PM1_STS_OFFSET),
  66. sizeof(USHORT),
  67. BitMask
  68. );
  69. }
  70. if (AcpiInformation->PM1b_BLK != 0) {
  71. WRITE_ACPI_REGISTER(PM1b_STATUS, 0, BitMask);
  72. DebugTraceIO(
  73. TRUE,
  74. (PUSHORT)(AcpiInformation->PM1b_BLK+PM1_STS_OFFSET),
  75. sizeof(USHORT),
  76. BitMask
  77. );
  78. }
  79. }
  80. VOID
  81. CLEAR_PM1_STATUS_REGISTER (
  82. VOID
  83. )
  84. {
  85. USHORT Value = 0;
  86. if (AcpiInformation->PM1a_BLK != 0) {
  87. Value = READ_ACPI_REGISTER(PM1a_STATUS, 0);
  88. WRITE_ACPI_REGISTER(PM1a_STATUS, 0, Value);
  89. DebugTraceIO(
  90. TRUE,
  91. (PUSHORT)(AcpiInformation->PM1a_BLK+PM1_STS_OFFSET),
  92. sizeof(USHORT),
  93. Value
  94. );
  95. }
  96. if (AcpiInformation->PM1b_BLK != 0) {
  97. Value = READ_ACPI_REGISTER(PM1b_STATUS, 0);
  98. WRITE_ACPI_REGISTER(PM1b_STATUS, 0, Value);
  99. DebugTraceIO(
  100. TRUE,
  101. (PUSHORT)(AcpiInformation->PM1b_BLK+PM1_STS_OFFSET),
  102. sizeof(USHORT),
  103. Value
  104. );
  105. }
  106. }
  107. USHORT
  108. READ_PM1_CONTROL(
  109. VOID
  110. )
  111. {
  112. USHORT pm1=0;
  113. if (AcpiInformation->PM1a_CTRL_BLK != 0) {
  114. pm1 = READ_ACPI_REGISTER(PM1a_CONTROL, 0);
  115. }
  116. if (AcpiInformation->PM1b_CTRL_BLK != 0) {
  117. pm1 |= READ_ACPI_REGISTER(PM1b_CONTROL, 0);
  118. }
  119. return (pm1);
  120. }
  121. USHORT
  122. READ_PM1_ENABLE(
  123. VOID
  124. )
  125. {
  126. USHORT pm1=0;
  127. if (AcpiInformation->PM1a_BLK != 0) {
  128. pm1 = READ_ACPI_REGISTER(PM1a_ENABLE, 0);
  129. DebugTraceIO(
  130. FALSE,
  131. (PUSHORT)(AcpiInformation->PM1a_BLK+PM1_EN_OFFSET),
  132. sizeof(USHORT),
  133. pm1
  134. );
  135. }
  136. if (AcpiInformation->PM1b_BLK != 0) {
  137. pm1 |= READ_ACPI_REGISTER(PM1b_ENABLE, 0);
  138. DebugTraceIO(
  139. FALSE,
  140. (PUSHORT)(AcpiInformation->PM1b_BLK+PM1_EN_OFFSET),
  141. sizeof(USHORT),
  142. pm1
  143. );
  144. }
  145. return (pm1);
  146. }
  147. USHORT
  148. READ_PM1_STATUS(
  149. VOID
  150. )
  151. {
  152. USHORT pm1=0;
  153. if (AcpiInformation->PM1a_BLK != 0) {
  154. pm1 = READ_ACPI_REGISTER(PM1a_STATUS, 0);
  155. DebugTraceIO(
  156. FALSE,
  157. (PUSHORT)(AcpiInformation->PM1a_BLK+PM1_STS_OFFSET),
  158. sizeof(USHORT),
  159. pm1
  160. );
  161. }
  162. if (AcpiInformation->PM1b_BLK != 0) {
  163. pm1 |= READ_ACPI_REGISTER(PM1b_STATUS, 0);
  164. DebugTraceIO(
  165. FALSE,
  166. (PUSHORT)(AcpiInformation->PM1b_BLK+PM1_STS_OFFSET),
  167. sizeof(USHORT),
  168. pm1
  169. );
  170. }
  171. return (pm1);
  172. }
  173. VOID
  174. WRITE_PM1_CONTROL(
  175. USHORT Value,
  176. BOOLEAN Destructive,
  177. ULONG Flags
  178. )
  179. {
  180. if (!Destructive) {
  181. USHORT pm1;
  182. if ( (Flags & WRITE_REGISTER_A) && (AcpiInformation->PM1a_BLK != 0) ) {
  183. pm1 = READ_ACPI_REGISTER(PM1a_CONTROL, 0);
  184. pm1 |= Value;
  185. WRITE_ACPI_REGISTER(PM1a_CONTROL, 0, pm1);
  186. }
  187. if ( (Flags & WRITE_REGISTER_B) && (AcpiInformation->PM1b_BLK != 0) ) {
  188. pm1 = READ_ACPI_REGISTER(PM1b_CONTROL, 0);
  189. pm1 |= Value;
  190. WRITE_ACPI_REGISTER(PM1b_CONTROL, 0, pm1);
  191. }
  192. } else {
  193. //
  194. // clear this bit and the system dies
  195. // it is legit when called by the ACPI shutdown code
  196. // which will use the WRITE_SCI flag.
  197. //
  198. ASSERT ( (Flags & WRITE_SCI) || (Value & PM1_SCI_EN) );
  199. if ( (Flags & WRITE_REGISTER_A) && (AcpiInformation->PM1a_BLK != 0) ) {
  200. WRITE_ACPI_REGISTER(PM1a_CONTROL, 0, Value);
  201. }
  202. if ( (Flags & WRITE_REGISTER_B) && (AcpiInformation->PM1b_BLK != 0) ) {
  203. WRITE_ACPI_REGISTER(PM1b_CONTROL, 0, Value);
  204. }
  205. }
  206. }
  207. VOID
  208. WRITE_PM1_ENABLE(
  209. USHORT Value
  210. )
  211. {
  212. if (AcpiInformation->PM1a_BLK != 0) {
  213. WRITE_ACPI_REGISTER(PM1a_ENABLE, 0, Value);
  214. DebugTraceIO(
  215. TRUE,
  216. (PUSHORT)(AcpiInformation->PM1a_BLK+PM1_EN_OFFSET),
  217. sizeof(USHORT),
  218. Value
  219. );
  220. }
  221. if (AcpiInformation->PM1b_BLK != 0) {
  222. WRITE_ACPI_REGISTER(PM1b_ENABLE, 0, Value);
  223. DebugTraceIO(
  224. TRUE,
  225. (PUSHORT)(AcpiInformation->PM1b_BLK+PM1_EN_OFFSET),
  226. sizeof(USHORT),
  227. Value
  228. );
  229. }
  230. }
  231. USHORT
  232. DefReadAcpiRegister(
  233. ACPI_REG_TYPE AcpiReg,
  234. ULONG Register
  235. )
  236. /*++
  237. Routine Description:
  238. Read from the specified ACPI fixed register.
  239. Arguments:
  240. AcpiReg - Specifies which ACPI fixed register to read from.
  241. Register - Specifies which GP register to read from. Not used for PM1x
  242. registers.
  243. Return Value:
  244. Value of the specified ACPI fixed register.
  245. --*/
  246. {
  247. switch (AcpiReg) {
  248. case PM1a_ENABLE:
  249. return READ_PORT_USHORT((PUSHORT)(AcpiInformation->PM1a_BLK +
  250. PM1_EN_OFFSET));
  251. break;
  252. case PM1b_ENABLE:
  253. return READ_PORT_USHORT((PUSHORT)(AcpiInformation->PM1b_BLK +
  254. PM1_EN_OFFSET));
  255. break;
  256. case PM1a_STATUS:
  257. return READ_PORT_USHORT((PUSHORT)AcpiInformation->PM1a_BLK +
  258. PM1_STS_OFFSET);
  259. break;
  260. case PM1b_STATUS:
  261. return READ_PORT_USHORT((PUSHORT)AcpiInformation->PM1b_BLK +
  262. PM1_STS_OFFSET);
  263. break;
  264. case PM1a_CONTROL:
  265. return READ_PORT_USHORT((PUSHORT)AcpiInformation->PM1a_CTRL_BLK);
  266. break;
  267. case PM1b_CONTROL:
  268. return READ_PORT_USHORT((PUSHORT)AcpiInformation->PM1b_CTRL_BLK);
  269. break;
  270. case GP_STATUS:
  271. if (Register < AcpiInformation->Gpe0Size) {
  272. return READ_PORT_UCHAR((PUCHAR)(AcpiInformation->GP0_BLK +
  273. Register));
  274. } else {
  275. return READ_PORT_UCHAR((PUCHAR)(AcpiInformation->GP1_BLK +
  276. Register -
  277. AcpiInformation->Gpe0Size));
  278. }
  279. break;
  280. case GP_ENABLE:
  281. if (Register < AcpiInformation->Gpe0Size) {
  282. return READ_PORT_UCHAR((PUCHAR)(AcpiInformation->GP0_ENABLE +
  283. Register));
  284. } else {
  285. return READ_PORT_UCHAR((PUCHAR)(AcpiInformation->GP1_ENABLE +
  286. Register -
  287. AcpiInformation->Gpe0Size));
  288. }
  289. break;
  290. case SMI_CMD:
  291. return READ_PORT_UCHAR((PUCHAR)AcpiInformation->SMI_CMD);
  292. break;
  293. default:
  294. break;
  295. }
  296. return (USHORT)-1;
  297. }
  298. VOID
  299. DefWriteAcpiRegister(
  300. ACPI_REG_TYPE AcpiReg,
  301. ULONG Register,
  302. USHORT Value
  303. )
  304. /*++
  305. Routine Description:
  306. Write to the specified ACPI fixed register.
  307. Arguments:
  308. AcpiReg - Specifies which ACPI fixed register to write to.
  309. Register - Specifies which GP register to write to. Not used for PM1x
  310. registers.
  311. Value - Data to write.
  312. Return Value:
  313. None.
  314. --*/
  315. {
  316. switch (AcpiReg) {
  317. case PM1a_ENABLE:
  318. WRITE_PORT_USHORT((PUSHORT)(AcpiInformation->PM1a_BLK +
  319. PM1_EN_OFFSET), Value);
  320. break;
  321. case PM1b_ENABLE:
  322. WRITE_PORT_USHORT((PUSHORT)(AcpiInformation->PM1b_BLK +
  323. PM1_EN_OFFSET), Value);
  324. break;
  325. case PM1a_STATUS:
  326. WRITE_PORT_USHORT((PUSHORT)AcpiInformation->PM1a_BLK +
  327. PM1_STS_OFFSET, Value);
  328. break;
  329. case PM1b_STATUS:
  330. WRITE_PORT_USHORT((PUSHORT)AcpiInformation->PM1b_BLK +
  331. PM1_STS_OFFSET, Value);
  332. break;
  333. case PM1a_CONTROL:
  334. WRITE_PORT_USHORT((PUSHORT)AcpiInformation->PM1a_CTRL_BLK, Value);
  335. break;
  336. case PM1b_CONTROL:
  337. WRITE_PORT_USHORT((PUSHORT)AcpiInformation->PM1b_CTRL_BLK, Value);
  338. break;
  339. case GP_STATUS:
  340. if (Register < AcpiInformation->Gpe0Size) {
  341. WRITE_PORT_UCHAR((PUCHAR)(AcpiInformation->GP0_BLK + Register),
  342. (UCHAR)Value);
  343. } else {
  344. WRITE_PORT_UCHAR((PUCHAR)(AcpiInformation->GP1_BLK + Register -
  345. AcpiInformation->Gpe0Size),
  346. (UCHAR)Value);
  347. }
  348. break;
  349. case GP_ENABLE:
  350. if (Register < AcpiInformation->Gpe0Size) {
  351. WRITE_PORT_UCHAR((PUCHAR)(AcpiInformation->GP0_ENABLE +
  352. Register),
  353. (UCHAR)Value);
  354. } else {
  355. WRITE_PORT_UCHAR((PUCHAR)(AcpiInformation->GP1_ENABLE +
  356. Register -
  357. AcpiInformation->Gpe0Size),
  358. (UCHAR)Value);
  359. }
  360. break;
  361. case SMI_CMD:
  362. WRITE_PORT_UCHAR((PUCHAR)AcpiInformation->SMI_CMD, (UCHAR)Value);
  363. break;
  364. default:
  365. break;
  366. }
  367. }
  368. //
  369. // READ/WRITE_ACPI_REGISTER macros are implemented via these
  370. // function pointers
  371. //
  372. PREAD_ACPI_REGISTER AcpiReadRegisterRoutine = DefReadAcpiRegister;
  373. PWRITE_ACPI_REGISTER AcpiWriteRegisterRoutine = DefWriteAcpiRegister;