fixedreg.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. fixedreg.c
  9. Abstract:
  10. This module implements support for accessing ACPI fixed hardware, which
  11. is a mess because there are so many different ways to both access and
  12. specify the register locations.
  13. Author:
  14. Evan Green 21-Nov-2013
  15. Environment:
  16. Kernel
  17. --*/
  18. //
  19. // ------------------------------------------------------------------- Includes
  20. //
  21. #include <minoca/kernel/driver.h>
  22. #include "acpip.h"
  23. #include "amlos.h"
  24. #include "fixedreg.h"
  25. //
  26. // ---------------------------------------------------------------- Definitions
  27. //
  28. //
  29. // Define the number of seconds to wait for the global lock before taking
  30. // the system down.
  31. //
  32. #define ACPI_GLOBAL_LOCK_TIMEOUT 60
  33. //
  34. // ------------------------------------------------------ Data Type Definitions
  35. //
  36. //
  37. // ----------------------------------------------- Internal Function Prototypes
  38. //
  39. KSTATUS
  40. AcpipReadFixedRegister (
  41. ULONG AddressA,
  42. ULONG AddressB,
  43. UCHAR AddressLength,
  44. ULONG GenericAddressAOffset,
  45. ULONG GenericAddressBOffset,
  46. PVOID *MappedAddressA,
  47. PVOID *MappedAddressB,
  48. PULONG MappedSizeA,
  49. PULONG MappedSizeB,
  50. PULONG Value
  51. );
  52. KSTATUS
  53. AcpipWriteFixedRegister (
  54. ULONG AddressA,
  55. ULONG AddressB,
  56. UCHAR AddressLength,
  57. ULONG GenericAddressAOffset,
  58. ULONG GenericAddressBOffset,
  59. PVOID *MappedAddressA,
  60. PVOID *MappedAddressB,
  61. PULONG MappedSizeA,
  62. PULONG MappedSizeB,
  63. ULONG Value
  64. );
  65. KSTATUS
  66. AcpipReadGenericAddressFixedRegister (
  67. PVOID *MappedAddress,
  68. PULONG MappedSize,
  69. PGENERIC_ADDRESS GenericAddress,
  70. PULONG Value
  71. );
  72. KSTATUS
  73. AcpipWriteGenericAddressFixedRegister (
  74. PVOID *MappedAddress,
  75. PULONG MappedSize,
  76. PGENERIC_ADDRESS GenericAddress,
  77. ULONG Value
  78. );
  79. //
  80. // -------------------------------------------------------------------- Globals
  81. //
  82. //
  83. // Store a pointer to the PM1 control block.
  84. //
  85. PVOID AcpiPm1aControlRegister = NULL;
  86. ULONG AcpiPm1aControlRegisterSize = 0;
  87. PVOID AcpiPm1bControlRegister = NULL;
  88. ULONG AcpiPm1bControlRegisterSize = 0;
  89. PVOID AcpiPm2ControlRegister = NULL;
  90. ULONG AcpiPm2ControlRegisterSize = 0;
  91. PVOID AcpiPm1aEventRegister = NULL;
  92. ULONG AcpiPm1aEventRegisterSize = 0;
  93. PVOID AcpiPm1bEventRegister = NULL;
  94. ULONG AcpiPm1bEventRegisterSize = 0;
  95. //
  96. // Store a pointer to the lock that protects the global lock.
  97. //
  98. PQUEUED_LOCK AcpiGlobalLock = NULL;
  99. //
  100. // Store a pointer to the FACS table.
  101. //
  102. PFACS AcpiFacsTable = NULL;
  103. //
  104. // ------------------------------------------------------------------ Functions
  105. //
  106. KSTATUS
  107. AcpipReadPm1ControlRegister (
  108. PULONG Value
  109. )
  110. /*++
  111. Routine Description:
  112. This routine reads the PM1 control register.
  113. Arguments:
  114. Value - Supplies a pointer where the value will be returned on success.
  115. Return Value:
  116. Status code.
  117. --*/
  118. {
  119. PFADT Fadt;
  120. KSTATUS Status;
  121. Fadt = AcpiFadtTable;
  122. if (Fadt == NULL) {
  123. return STATUS_NOT_SUPPORTED;
  124. }
  125. Status = AcpipReadFixedRegister(Fadt->Pm1aControlBlock,
  126. Fadt->Pm1bControlBlock,
  127. Fadt->Pm1ControlLength,
  128. FIELD_OFFSET(FADT, XPm1aControlBlock),
  129. FIELD_OFFSET(FADT, XPm1bControlBlock),
  130. &AcpiPm1aControlRegister,
  131. &AcpiPm1bControlRegister,
  132. &AcpiPm1aControlRegisterSize,
  133. &AcpiPm1bControlRegisterSize,
  134. Value);
  135. return Status;
  136. }
  137. KSTATUS
  138. AcpipWritePm1ControlRegister (
  139. ULONG Value
  140. )
  141. /*++
  142. Routine Description:
  143. This routine writes to the PM1 control register.
  144. Arguments:
  145. Value - Supplies the value to write.
  146. Return Value:
  147. Status code.
  148. --*/
  149. {
  150. PFADT Fadt;
  151. KSTATUS Status;
  152. Fadt = AcpiFadtTable;
  153. if (Fadt == NULL) {
  154. return STATUS_NOT_SUPPORTED;
  155. }
  156. Status = AcpipWriteFixedRegister(Fadt->Pm1aControlBlock,
  157. Fadt->Pm1bControlBlock,
  158. Fadt->Pm1ControlLength,
  159. FIELD_OFFSET(FADT, XPm1aControlBlock),
  160. FIELD_OFFSET(FADT, XPm1bControlBlock),
  161. &AcpiPm1aControlRegister,
  162. &AcpiPm1bControlRegister,
  163. &AcpiPm1aControlRegisterSize,
  164. &AcpiPm1bControlRegisterSize,
  165. Value);
  166. return Status;
  167. }
  168. KSTATUS
  169. AcpipReadPm2ControlRegister (
  170. PULONG Value
  171. )
  172. /*++
  173. Routine Description:
  174. This routine reads the PM2 control register.
  175. Arguments:
  176. Value - Supplies a pointer where the value will be returned on success.
  177. Return Value:
  178. Status code.
  179. --*/
  180. {
  181. PFADT Fadt;
  182. KSTATUS Status;
  183. Fadt = AcpiFadtTable;
  184. if (Fadt == NULL) {
  185. return STATUS_NOT_SUPPORTED;
  186. }
  187. Status = AcpipReadFixedRegister(Fadt->Pm2ControlBlock,
  188. 0,
  189. Fadt->Pm2ControlLength,
  190. FIELD_OFFSET(FADT, XPm2ControlBlock),
  191. 0,
  192. &AcpiPm2ControlRegister,
  193. NULL,
  194. &AcpiPm2ControlRegisterSize,
  195. NULL,
  196. Value);
  197. return Status;
  198. }
  199. KSTATUS
  200. AcpipWritePm2ControlRegister (
  201. ULONG Value
  202. )
  203. /*++
  204. Routine Description:
  205. This routine writes to the PM2 control register.
  206. Arguments:
  207. Value - Supplies the value to write.
  208. Return Value:
  209. Status code.
  210. --*/
  211. {
  212. PFADT Fadt;
  213. KSTATUS Status;
  214. Fadt = AcpiFadtTable;
  215. if (Fadt == NULL) {
  216. return STATUS_NOT_SUPPORTED;
  217. }
  218. Status = AcpipWriteFixedRegister(Fadt->Pm2ControlBlock,
  219. 0,
  220. Fadt->Pm2ControlLength,
  221. FIELD_OFFSET(FADT, XPm2ControlBlock),
  222. 0,
  223. &AcpiPm2ControlRegister,
  224. NULL,
  225. &AcpiPm2ControlRegisterSize,
  226. NULL,
  227. Value);
  228. return Status;
  229. }
  230. KSTATUS
  231. AcpipReadPm1EventRegister (
  232. PULONG Value
  233. )
  234. /*++
  235. Routine Description:
  236. This routine reads the PM1 event/status register.
  237. Arguments:
  238. Value - Supplies a pointer where the value will be returned on success.
  239. Return Value:
  240. Status code.
  241. --*/
  242. {
  243. PFADT Fadt;
  244. KSTATUS Status;
  245. Fadt = AcpiFadtTable;
  246. if (Fadt == NULL) {
  247. return STATUS_NOT_SUPPORTED;
  248. }
  249. Status = AcpipReadFixedRegister(Fadt->Pm1aEventBlock,
  250. Fadt->Pm1bEventBlock,
  251. Fadt->Pm1EventLength,
  252. FIELD_OFFSET(FADT, XPm1aEventBlock),
  253. FIELD_OFFSET(FADT, XPm1bEventBlock),
  254. &AcpiPm1aEventRegister,
  255. &AcpiPm1bEventRegister,
  256. &AcpiPm1aEventRegisterSize,
  257. &AcpiPm1bEventRegisterSize,
  258. Value);
  259. return Status;
  260. }
  261. KSTATUS
  262. AcpipWritePm1EventRegister (
  263. ULONG Value
  264. )
  265. /*++
  266. Routine Description:
  267. This routine writes to the PM1 event register.
  268. Arguments:
  269. Value - Supplies the value to write.
  270. Return Value:
  271. Status code.
  272. --*/
  273. {
  274. PFADT Fadt;
  275. KSTATUS Status;
  276. Fadt = AcpiFadtTable;
  277. if (Fadt == NULL) {
  278. return STATUS_NOT_SUPPORTED;
  279. }
  280. Status = AcpipWriteFixedRegister(Fadt->Pm1aEventBlock,
  281. Fadt->Pm1bEventBlock,
  282. Fadt->Pm1EventLength,
  283. FIELD_OFFSET(FADT, XPm1aEventBlock),
  284. FIELD_OFFSET(FADT, XPm1bEventBlock),
  285. &AcpiPm1aEventRegister,
  286. &AcpiPm1bEventRegister,
  287. &AcpiPm1aEventRegisterSize,
  288. &AcpiPm1bEventRegisterSize,
  289. Value);
  290. return Status;
  291. }
  292. VOID
  293. AcpipAcquireGlobalLock (
  294. VOID
  295. )
  296. /*++
  297. Routine Description:
  298. This routine acquires the ACPI global lock that coordinates between the
  299. OSPM and firmware in SMI-land (or in some external controller).
  300. Arguments:
  301. None.
  302. Return Value:
  303. None.
  304. --*/
  305. {
  306. ULONG CurrentValue;
  307. ULONG NewValue;
  308. ULONG OriginalValue;
  309. KSTATUS Status;
  310. ULONGLONG Timeout;
  311. ASSERT(KeGetRunLevel() == RunLevelLow);
  312. if (AcpiFacsTable == NULL) {
  313. return;
  314. }
  315. KeAcquireQueuedLock(AcpiGlobalLock);
  316. Timeout = KeGetRecentTimeCounter() +
  317. (HlQueryTimeCounterFrequency() * ACPI_GLOBAL_LOCK_TIMEOUT);
  318. //
  319. // Loop trying to acquire the lock until the timeout occurs.
  320. //
  321. Status = STATUS_TIMEOUT;
  322. do {
  323. //
  324. // Loop trying to get a clean compare-exchange.
  325. //
  326. while (TRUE) {
  327. OriginalValue = AcpiFacsTable->GlobalLock;
  328. //
  329. // Clear the pending bit. If the owner bit is set, set the pending
  330. // bit.
  331. //
  332. NewValue = (OriginalValue | FACS_GLOBAL_LOCK_OWNED) &
  333. (~FACS_GLOBAL_LOCK_PENDING);
  334. if ((OriginalValue & FACS_GLOBAL_LOCK_OWNED) != 0) {
  335. NewValue |= FACS_GLOBAL_LOCK_PENDING;
  336. }
  337. CurrentValue = RtlAtomicCompareExchange32(
  338. &(AcpiFacsTable->GlobalLock),
  339. NewValue,
  340. OriginalValue);
  341. if (CurrentValue == OriginalValue) {
  342. break;
  343. }
  344. }
  345. //
  346. // If the value shoved in there didn't have the pending bit set, then
  347. // this routine must have just set the owner bit successfully.
  348. //
  349. if ((NewValue & FACS_GLOBAL_LOCK_PENDING) == 0) {
  350. Status = STATUS_SUCCESS;
  351. break;
  352. }
  353. //
  354. // Stall for a bit to let the firmware do its thing.
  355. //
  356. KeDelayExecution(FALSE, FALSE, MICROSECONDS_PER_MILLISECOND);
  357. } while (KeGetRecentTimeCounter() <= Timeout);
  358. //
  359. // It's serious not to be able to acquire the lock.
  360. //
  361. if (!KSUCCESS(Status)) {
  362. AcpipFatalError(ACPI_CRASH_GLOBAL_LOCK_FAILURE,
  363. Status,
  364. (UINTN)AcpiFacsTable,
  365. 0);
  366. }
  367. return;
  368. }
  369. VOID
  370. AcpipReleaseGlobalLock (
  371. VOID
  372. )
  373. /*++
  374. Routine Description:
  375. This routine releases the ACPI global lock.
  376. Arguments:
  377. None.
  378. Return Value:
  379. None.
  380. --*/
  381. {
  382. ULONG CurrentValue;
  383. ULONG NewValue;
  384. ULONG OriginalValue;
  385. KSTATUS Status;
  386. ASSERT(KeGetRunLevel() == RunLevelLow);
  387. if (AcpiFacsTable == NULL) {
  388. return;
  389. }
  390. //
  391. // Loop trying to get a clean compare exchange clearing the owned and
  392. // pending bits.
  393. //
  394. while (TRUE) {
  395. OriginalValue = AcpiFacsTable->GlobalLock;
  396. NewValue = OriginalValue &
  397. (~(FACS_GLOBAL_LOCK_PENDING | FACS_GLOBAL_LOCK_OWNED));
  398. CurrentValue = RtlAtomicCompareExchange32(&(AcpiFacsTable->GlobalLock),
  399. NewValue,
  400. OriginalValue);
  401. if (CurrentValue == OriginalValue) {
  402. break;
  403. }
  404. }
  405. //
  406. // If the firmware wants control, signal to them that it's their turn.
  407. //
  408. if ((OriginalValue & FACS_GLOBAL_LOCK_PENDING) != 0) {
  409. Status = AcpipReadPm1ControlRegister(&OriginalValue);
  410. if (KSUCCESS(Status)) {
  411. OriginalValue |= FADT_PM1_CONTROL_GLOBAL_LOCK_RELEASED;
  412. AcpipWritePm1ControlRegister(OriginalValue);
  413. }
  414. }
  415. KeReleaseQueuedLock(AcpiGlobalLock);
  416. return;
  417. }
  418. KSTATUS
  419. AcpipInitializeFixedRegisterSupport (
  420. VOID
  421. )
  422. /*++
  423. Routine Description:
  424. This routine initializes support for accessing fixed registers.
  425. Arguments:
  426. None.
  427. Return Value:
  428. Status code.
  429. --*/
  430. {
  431. PHYSICAL_ADDRESS FacsPhysicalAddress;
  432. PFADT Fadt;
  433. KSTATUS Status;
  434. Fadt = AcpiFadtTable;
  435. if (Fadt != NULL) {
  436. //
  437. // Get the physical address of the FACS table.
  438. //
  439. FacsPhysicalAddress = 0;
  440. if (Fadt->Header.Length >=
  441. FIELD_OFFSET(FADT, XFirmwareControl) + sizeof(ULONGLONG)) {
  442. FacsPhysicalAddress = Fadt->XFirmwareControl;
  443. }
  444. if (FacsPhysicalAddress == 0) {
  445. FacsPhysicalAddress = Fadt->FirmwareControlAddress;
  446. }
  447. //
  448. // Map the FACS if it's present. Map it cache-disable as it
  449. // communicates directly to firmware.
  450. //
  451. if (FacsPhysicalAddress != 0) {
  452. AcpiFacsTable = MmMapPhysicalAddress(FacsPhysicalAddress,
  453. sizeof(FACS),
  454. TRUE,
  455. FALSE,
  456. TRUE);
  457. if (AcpiFacsTable == NULL) {
  458. Status = STATUS_INSUFFICIENT_RESOURCES;
  459. goto InitializeFixedRegisterSupportEnd;
  460. }
  461. //
  462. // Also create a global lock to protect the global lock.
  463. //
  464. AcpiGlobalLock = KeCreateQueuedLock();
  465. if (AcpiGlobalLock == NULL) {
  466. Status = STATUS_INSUFFICIENT_RESOURCES;
  467. goto InitializeFixedRegisterSupportEnd;
  468. }
  469. }
  470. }
  471. Status = STATUS_SUCCESS;
  472. InitializeFixedRegisterSupportEnd:
  473. return Status;
  474. }
  475. VOID
  476. AcpipUnmapFixedRegisters (
  477. VOID
  478. )
  479. /*++
  480. Routine Description:
  481. This routine is called before a driver is about to be unloaded from memory.
  482. It unmaps any mappings created to access the fixed ACPI registers.
  483. Arguments:
  484. None.
  485. Return Value:
  486. None.
  487. --*/
  488. {
  489. if (AcpiGlobalLock != NULL) {
  490. KeDestroyQueuedLock(AcpiGlobalLock);
  491. }
  492. //
  493. // Unmap the fixed hardware.
  494. //
  495. if (AcpiPm1aControlRegister != NULL) {
  496. MmUnmapAddress(AcpiPm1aControlRegister, AcpiPm1aControlRegisterSize);
  497. AcpiPm1aControlRegister = NULL;
  498. AcpiPm1aControlRegisterSize = 0;
  499. }
  500. if (AcpiPm1bControlRegister != NULL) {
  501. MmUnmapAddress(AcpiPm1bControlRegister, AcpiPm1bControlRegisterSize);
  502. AcpiPm1bControlRegister = NULL;
  503. AcpiPm1bControlRegisterSize = 0;
  504. }
  505. return;
  506. }
  507. //
  508. // --------------------------------------------------------- Internal Functions
  509. //
  510. KSTATUS
  511. AcpipReadFixedRegister (
  512. ULONG AddressA,
  513. ULONG AddressB,
  514. UCHAR AddressLength,
  515. ULONG GenericAddressAOffset,
  516. ULONG GenericAddressBOffset,
  517. PVOID *MappedAddressA,
  518. PVOID *MappedAddressB,
  519. PULONG MappedSizeA,
  520. PULONG MappedSizeB,
  521. PULONG Value
  522. )
  523. /*++
  524. Routine Description:
  525. This routine reads a fixed register from the FADT.
  526. Arguments:
  527. AddressA - Supplies the I/O port address of the A (or only) portion of
  528. the register.
  529. AddressB - Supplies the I/O port address of the B portion of the register
  530. if it exists, or 0 if there is only an A portion.
  531. AddressLength - Supplies the length of the I/O port address in bytes.
  532. GenericAddressAOffset - Supplies the offset into the FADT where the
  533. generic address of the A portion resides, or 0 if there is no
  534. generic address for this register in the FADT.
  535. GenericAddressBOffset - Supplies the offset into the FADT where the
  536. generic address of the B portion resides, or 0 if there is no B portion.
  537. MappedAddressA - Supplies a pointer that on input contains the mapped
  538. address of the register A for memory mapped addresses. If the value of
  539. this is NULL and the generic address is memory backed, it will be
  540. mapped in this routine and the virtual address stored here.
  541. MappedAddressB - Supplies a pointer that on input contains the mapped
  542. address of the register B for memory mapped addresses. If the value of
  543. this is NULL and the generic address is memory backed, it will be
  544. mapped in this routine and the virtual address stored here.
  545. MappedSizeA - Supplies a pointer that on input contains the size of the
  546. virtual mapping for this address. If this routine maps the register,
  547. it will fill in the size here.
  548. MappedSizeB - Supplies a pointer that on input contains the size of the
  549. virtual mapping for this address. If this routine maps the register,
  550. it will fill in the size here.
  551. Value - Supplies a pointer where the value will be returned on success.
  552. Return Value:
  553. Status code.
  554. --*/
  555. {
  556. PFADT Fadt;
  557. PGENERIC_ADDRESS GenericAddressA;
  558. PGENERIC_ADDRESS GenericAddressB;
  559. ULONG MaxOffset;
  560. KSTATUS Status;
  561. ULONG ValueA;
  562. ULONG ValueB;
  563. Fadt = AcpiFadtTable;
  564. if (Fadt == NULL) {
  565. return STATUS_NOT_SUPPORTED;
  566. }
  567. ValueA = 0;
  568. ValueB = 0;
  569. //
  570. // Use the extended value if it's there.
  571. //
  572. GenericAddressA = (PVOID)Fadt + GenericAddressAOffset;
  573. GenericAddressB = (PVOID)Fadt + GenericAddressBOffset;
  574. MaxOffset = GenericAddressAOffset;
  575. if (GenericAddressBOffset > GenericAddressAOffset) {
  576. MaxOffset = GenericAddressBOffset;
  577. }
  578. MaxOffset += sizeof(GENERIC_ADDRESS);
  579. if ((Fadt->Header.Length >= MaxOffset) &&
  580. (GenericAddressA->Address != 0)) {
  581. Status = AcpipReadGenericAddressFixedRegister(MappedAddressA,
  582. MappedSizeA,
  583. GenericAddressA,
  584. &ValueA);
  585. if (!KSUCCESS(Status)) {
  586. return Status;
  587. }
  588. if (GenericAddressB->Address != 0) {
  589. Status = AcpipReadGenericAddressFixedRegister(MappedAddressB,
  590. MappedSizeB,
  591. GenericAddressB,
  592. &ValueB);
  593. if (!KSUCCESS(Status)) {
  594. return Status;
  595. }
  596. }
  597. *Value = ValueA | ValueB;
  598. return STATUS_SUCCESS;
  599. }
  600. //
  601. // Use the old fashioned values.
  602. //
  603. if (AddressLength == 0) {
  604. return STATUS_NOT_SUPPORTED;
  605. }
  606. ASSERT(AddressA != 0);
  607. switch (AddressLength) {
  608. case 1:
  609. ValueA = HlIoPortInByte(AddressA);
  610. if (AddressB != 0) {
  611. ValueB = HlIoPortInByte(AddressB);
  612. }
  613. break;
  614. case 2:
  615. ValueA = HlIoPortInShort(AddressA);
  616. if (AddressB != 0) {
  617. ValueB = HlIoPortInShort(AddressB);
  618. }
  619. break;
  620. case 4:
  621. ValueA = HlIoPortInLong(AddressA);
  622. if (AddressB != 0) {
  623. ValueB = HlIoPortInLong(AddressB);
  624. }
  625. break;
  626. default:
  627. ASSERT(FALSE);
  628. return STATUS_NOT_SUPPORTED;
  629. }
  630. *Value = ValueA | ValueB;
  631. return STATUS_SUCCESS;
  632. }
  633. KSTATUS
  634. AcpipWriteFixedRegister (
  635. ULONG AddressA,
  636. ULONG AddressB,
  637. UCHAR AddressLength,
  638. ULONG GenericAddressAOffset,
  639. ULONG GenericAddressBOffset,
  640. PVOID *MappedAddressA,
  641. PVOID *MappedAddressB,
  642. PULONG MappedSizeA,
  643. PULONG MappedSizeB,
  644. ULONG Value
  645. )
  646. /*++
  647. Routine Description:
  648. This routine writes to a fixed register from the FADT.
  649. Arguments:
  650. AddressA - Supplies the I/O port address of the A (or only) portion of
  651. the register.
  652. AddressB - Supplies the I/O port address of the B portion of the register
  653. if it exists, or 0 if there is only an A portion.
  654. AddressLength - Supplies the length of the I/O port address in bytes.
  655. GenericAddressAOffset - Supplies the offset into the FADT where the
  656. generic address of the A portion resides, or 0 if there is no
  657. generic address for this register in the FADT.
  658. GenericAddressBOffset - Supplies the offset into the FADT where the
  659. generic address of the B portion resides, or 0 if there is no B portion.
  660. MappedAddressA - Supplies a pointer that on input contains the mapped
  661. address of the register A for memory mapped addresses. If the value of
  662. this is NULL and the generic address is memory backed, it will be
  663. mapped in this routine and the virtual address stored here.
  664. MappedAddressB - Supplies a pointer that on input contains the mapped
  665. address of the register B for memory mapped addresses. If the value of
  666. this is NULL and the generic address is memory backed, it will be
  667. mapped in this routine and the virtual address stored here.
  668. MappedSizeA - Supplies a pointer that on input contains the size of the
  669. virtual mapping for this address. If this routine maps the register,
  670. it will fill in the size here.
  671. MappedSizeB - Supplies a pointer that on input contains the size of the
  672. virtual mapping for this address. If this routine maps the register,
  673. it will fill in the size here.
  674. Value - Supplies the value to write.
  675. Return Value:
  676. Status code.
  677. --*/
  678. {
  679. PFADT Fadt;
  680. PGENERIC_ADDRESS GenericAddressA;
  681. PGENERIC_ADDRESS GenericAddressB;
  682. ULONG MaxOffset;
  683. KSTATUS Status;
  684. Fadt = AcpiFadtTable;
  685. if (Fadt == NULL) {
  686. return STATUS_NOT_SUPPORTED;
  687. }
  688. //
  689. // Use the extended value if it's there.
  690. //
  691. GenericAddressA = (PVOID)Fadt + GenericAddressAOffset;
  692. GenericAddressB = (PVOID)Fadt + GenericAddressBOffset;
  693. MaxOffset = GenericAddressAOffset;
  694. if (GenericAddressBOffset > GenericAddressAOffset) {
  695. MaxOffset = GenericAddressBOffset;
  696. }
  697. MaxOffset += sizeof(GENERIC_ADDRESS);
  698. if ((Fadt->Header.Length >= MaxOffset) &&
  699. (GenericAddressA->Address != 0)) {
  700. Status = AcpipWriteGenericAddressFixedRegister(MappedAddressA,
  701. MappedSizeA,
  702. GenericAddressA,
  703. Value);
  704. if (!KSUCCESS(Status)) {
  705. return Status;
  706. }
  707. if (GenericAddressB->Address != 0) {
  708. Status = AcpipWriteGenericAddressFixedRegister(MappedAddressB,
  709. MappedSizeB,
  710. GenericAddressB,
  711. Value);
  712. if (!KSUCCESS(Status)) {
  713. return Status;
  714. }
  715. }
  716. return STATUS_SUCCESS;
  717. }
  718. //
  719. // Use the old fashioned values.
  720. //
  721. if (AddressLength == 0) {
  722. return STATUS_NOT_SUPPORTED;
  723. }
  724. ASSERT(AddressA != 0);
  725. switch (AddressLength) {
  726. case 1:
  727. HlIoPortOutByte(AddressA, (UCHAR)Value);
  728. if (AddressB != 0) {
  729. HlIoPortOutByte(AddressB, Value);
  730. }
  731. break;
  732. case 2:
  733. HlIoPortOutShort(AddressA, (USHORT)Value);
  734. if (AddressB != 0) {
  735. HlIoPortOutShort(AddressB, (USHORT)Value);
  736. }
  737. break;
  738. case 4:
  739. HlIoPortOutLong(AddressA, Value);
  740. if (AddressB != 0) {
  741. HlIoPortOutLong(AddressB, Value);
  742. }
  743. break;
  744. default:
  745. ASSERT(FALSE);
  746. return STATUS_NOT_SUPPORTED;
  747. }
  748. return STATUS_SUCCESS;
  749. }
  750. KSTATUS
  751. AcpipReadGenericAddressFixedRegister (
  752. PVOID *MappedAddress,
  753. PULONG MappedSize,
  754. PGENERIC_ADDRESS GenericAddress,
  755. PULONG Value
  756. )
  757. /*++
  758. Routine Description:
  759. This routine reads a register value from a generic address.
  760. Arguments:
  761. MappedAddress - Supplies a pointer that on input contains the mapped
  762. address of the register for memory mapped addresses. If the value of
  763. this is NULL and the generic address is memory backed, it will be
  764. mapped in this routine and the virtual address stored here.
  765. MappedSize - Supplies a pointer that on input contains the size of the
  766. virtual mapping for this address. If this routine maps the register,
  767. it will fill in the size here.
  768. GenericAddress - Supplies a pointer to the generic address detailing the
  769. location of the register.
  770. Value - Supplies a pointer where the value will be returned on success.
  771. Return Value:
  772. Status code.
  773. --*/
  774. {
  775. USHORT AccessSize;
  776. USHORT IoPortAddress;
  777. //
  778. // Deal with odd offsets if needed.
  779. //
  780. ASSERT(GenericAddress->RegisterBitOffset == 0);
  781. AccessSize = GenericAddress->AccessSize;
  782. if (AccessSize == 0) {
  783. ASSERT(GenericAddress->RegisterBitWidth != 0);
  784. AccessSize = GenericAddress->RegisterBitWidth / BITS_PER_BYTE;
  785. }
  786. switch (GenericAddress->AddressSpaceId) {
  787. case AddressSpaceMemory:
  788. if (*MappedAddress == NULL) {
  789. *MappedAddress = MmMapPhysicalAddress(GenericAddress->Address,
  790. GenericAddress->AccessSize,
  791. TRUE,
  792. FALSE,
  793. TRUE);
  794. if (*MappedAddress == NULL) {
  795. return STATUS_INSUFFICIENT_RESOURCES;
  796. }
  797. *MappedSize = GenericAddress->AccessSize;
  798. }
  799. switch (AccessSize) {
  800. case 1:
  801. *Value = HlReadRegister8(*MappedAddress);
  802. break;
  803. case 2:
  804. *Value = HlReadRegister16(*MappedAddress);
  805. break;
  806. case 4:
  807. *Value = HlReadRegister32(*MappedAddress);
  808. break;
  809. default:
  810. ASSERT(FALSE);
  811. return STATUS_NOT_SUPPORTED;
  812. }
  813. break;
  814. case AddressSpaceIo:
  815. IoPortAddress = (USHORT)(GenericAddress->Address);
  816. switch (AccessSize) {
  817. case 1:
  818. *Value = HlIoPortInByte(IoPortAddress);
  819. break;
  820. case 2:
  821. *Value = HlIoPortInShort(IoPortAddress);
  822. break;
  823. case 4:
  824. *Value = HlIoPortInLong(IoPortAddress);
  825. break;
  826. default:
  827. ASSERT(FALSE);
  828. return STATUS_NOT_SUPPORTED;
  829. }
  830. break;
  831. //
  832. // Implement other types if needed.
  833. //
  834. default:
  835. ASSERT(FALSE);
  836. return STATUS_NOT_IMPLEMENTED;
  837. }
  838. return STATUS_SUCCESS;
  839. }
  840. KSTATUS
  841. AcpipWriteGenericAddressFixedRegister (
  842. PVOID *MappedAddress,
  843. PULONG MappedSize,
  844. PGENERIC_ADDRESS GenericAddress,
  845. ULONG Value
  846. )
  847. /*++
  848. Routine Description:
  849. This routine writes a register value to a generic address.
  850. Arguments:
  851. MappedAddress - Supplies a pointer that on input contains the mapped
  852. address of the register for memory mapped addresses. If the value of
  853. this is NULL and the generic address is memory backed, it will be
  854. mapped in this routine and the virtual address stored here.
  855. MappedSize - Supplies a pointer that on input contains the size of the
  856. virtual mapping for this address. If this routine maps the register,
  857. it will fill in the size here.
  858. GenericAddress - Supplies a pointer to the generic address detailing the
  859. location of the register.
  860. Value - Supplies the value to write.
  861. Return Value:
  862. Status code.
  863. --*/
  864. {
  865. USHORT AccessSize;
  866. USHORT IoPortAddress;
  867. //
  868. // Deal with odd offsets if needed.
  869. //
  870. ASSERT(GenericAddress->RegisterBitOffset == 0);
  871. AccessSize = GenericAddress->AccessSize;
  872. if (AccessSize == 0) {
  873. ASSERT(GenericAddress->RegisterBitWidth != 0);
  874. AccessSize = GenericAddress->RegisterBitWidth / BITS_PER_BYTE;
  875. } else {
  876. ASSERT(GenericAddress->RegisterBitWidth ==
  877. GenericAddress->AccessSize * BITS_PER_BYTE);
  878. }
  879. switch (GenericAddress->AddressSpaceId) {
  880. case AddressSpaceMemory:
  881. if (*MappedAddress == NULL) {
  882. *MappedAddress = MmMapPhysicalAddress(GenericAddress->Address,
  883. GenericAddress->AccessSize,
  884. TRUE,
  885. FALSE,
  886. TRUE);
  887. if (*MappedAddress == NULL) {
  888. return STATUS_INSUFFICIENT_RESOURCES;
  889. }
  890. *MappedSize = GenericAddress->AccessSize;
  891. }
  892. switch (AccessSize) {
  893. case 1:
  894. HlWriteRegister8(*MappedAddress, (UCHAR)Value);
  895. break;
  896. case 2:
  897. HlWriteRegister16(*MappedAddress, (USHORT)Value);
  898. break;
  899. case 4:
  900. HlWriteRegister32(*MappedAddress, Value);
  901. break;
  902. default:
  903. ASSERT(FALSE);
  904. return STATUS_NOT_SUPPORTED;
  905. }
  906. break;
  907. case AddressSpaceIo:
  908. IoPortAddress = (USHORT)(GenericAddress->Address);
  909. switch (AccessSize) {
  910. case 1:
  911. HlIoPortOutByte(IoPortAddress, (UCHAR)Value);
  912. break;
  913. case 2:
  914. HlIoPortOutShort(IoPortAddress, (USHORT)Value);
  915. break;
  916. case 4:
  917. HlIoPortOutLong(IoPortAddress, Value);
  918. break;
  919. default:
  920. ASSERT(FALSE);
  921. return STATUS_NOT_SUPPORTED;
  922. }
  923. break;
  924. //
  925. // Implement other types if needed.
  926. //
  927. default:
  928. ASSERT(FALSE);
  929. return STATUS_NOT_IMPLEMENTED;
  930. }
  931. return STATUS_SUCCESS;
  932. }