exregion.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. /******************************************************************************
  2. *
  3. * Module Name: exregion - ACPI default OpRegion (address space) handlers
  4. *
  5. *****************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2019, Intel Corp.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions, and the following disclaimer,
  15. * without modification.
  16. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  17. * substantially similar to the "NO WARRANTY" disclaimer below
  18. * ("Disclaimer") and any redistribution must be conditioned upon
  19. * including a substantially similar Disclaimer requirement for further
  20. * binary redistribution.
  21. * 3. Neither the names of the above-listed copyright holders nor the names
  22. * of any contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * Alternatively, this software may be distributed under the terms of the
  26. * GNU General Public License ("GPL") version 2 as published by the Free
  27. * Software Foundation.
  28. *
  29. * NO WARRANTY
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  33. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  34. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  39. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGES.
  41. */
  42. #include "acpi.h"
  43. #include "accommon.h"
  44. #include "acinterp.h"
  45. #define _COMPONENT ACPI_EXECUTER
  46. ACPI_MODULE_NAME ("exregion")
  47. /*******************************************************************************
  48. *
  49. * FUNCTION: AcpiExSystemMemorySpaceHandler
  50. *
  51. * PARAMETERS: Function - Read or Write operation
  52. * Address - Where in the space to read or write
  53. * BitWidth - Field width in bits (8, 16, or 32)
  54. * Value - Pointer to in or out value
  55. * HandlerContext - Pointer to Handler's context
  56. * RegionContext - Pointer to context specific to the
  57. * accessed region
  58. *
  59. * RETURN: Status
  60. *
  61. * DESCRIPTION: Handler for the System Memory address space (Op Region)
  62. *
  63. ******************************************************************************/
  64. ACPI_STATUS
  65. AcpiExSystemMemorySpaceHandler (
  66. UINT32 Function,
  67. ACPI_PHYSICAL_ADDRESS Address,
  68. UINT32 BitWidth,
  69. UINT64 *Value,
  70. void *HandlerContext,
  71. void *RegionContext)
  72. {
  73. ACPI_STATUS Status = AE_OK;
  74. void *LogicalAddrPtr = NULL;
  75. ACPI_MEM_SPACE_CONTEXT *MemInfo = RegionContext;
  76. UINT32 Length;
  77. ACPI_SIZE MapLength;
  78. ACPI_SIZE PageBoundaryMapLength;
  79. #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
  80. UINT32 Remainder;
  81. #endif
  82. ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler);
  83. /* Validate and translate the bit width */
  84. switch (BitWidth)
  85. {
  86. case 8:
  87. Length = 1;
  88. break;
  89. case 16:
  90. Length = 2;
  91. break;
  92. case 32:
  93. Length = 4;
  94. break;
  95. case 64:
  96. Length = 8;
  97. break;
  98. default:
  99. ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %u",
  100. BitWidth));
  101. return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
  102. }
  103. #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
  104. /*
  105. * Hardware does not support non-aligned data transfers, we must verify
  106. * the request.
  107. */
  108. (void) AcpiUtShortDivide ((UINT64) Address, Length, NULL, &Remainder);
  109. if (Remainder != 0)
  110. {
  111. return_ACPI_STATUS (AE_AML_ALIGNMENT);
  112. }
  113. #endif
  114. /*
  115. * Does the request fit into the cached memory mapping?
  116. * Is 1) Address below the current mapping? OR
  117. * 2) Address beyond the current mapping?
  118. */
  119. if ((Address < MemInfo->MappedPhysicalAddress) ||
  120. (((UINT64) Address + Length) >
  121. ((UINT64)
  122. MemInfo->MappedPhysicalAddress + MemInfo->MappedLength)))
  123. {
  124. /*
  125. * The request cannot be resolved by the current memory mapping;
  126. * Delete the existing mapping and create a new one.
  127. */
  128. if (MemInfo->MappedLength)
  129. {
  130. /* Valid mapping, delete it */
  131. AcpiOsUnmapMemory (MemInfo->MappedLogicalAddress,
  132. MemInfo->MappedLength);
  133. }
  134. /*
  135. * October 2009: Attempt to map from the requested address to the
  136. * end of the region. However, we will never map more than one
  137. * page, nor will we cross a page boundary.
  138. */
  139. MapLength = (ACPI_SIZE)
  140. ((MemInfo->Address + MemInfo->Length) - Address);
  141. /*
  142. * If mapping the entire remaining portion of the region will cross
  143. * a page boundary, just map up to the page boundary, do not cross.
  144. * On some systems, crossing a page boundary while mapping regions
  145. * can cause warnings if the pages have different attributes
  146. * due to resource management.
  147. *
  148. * This has the added benefit of constraining a single mapping to
  149. * one page, which is similar to the original code that used a 4k
  150. * maximum window.
  151. */
  152. PageBoundaryMapLength = (ACPI_SIZE)
  153. (ACPI_ROUND_UP (Address, ACPI_DEFAULT_PAGE_SIZE) - Address);
  154. if (PageBoundaryMapLength == 0)
  155. {
  156. PageBoundaryMapLength = ACPI_DEFAULT_PAGE_SIZE;
  157. }
  158. if (MapLength > PageBoundaryMapLength)
  159. {
  160. MapLength = PageBoundaryMapLength;
  161. }
  162. /* Create a new mapping starting at the address given */
  163. MemInfo->MappedLogicalAddress = AcpiOsMapMemory (Address, MapLength);
  164. if (!MemInfo->MappedLogicalAddress)
  165. {
  166. ACPI_ERROR ((AE_INFO,
  167. "Could not map memory at 0x%8.8X%8.8X, size %u",
  168. ACPI_FORMAT_UINT64 (Address), (UINT32) MapLength));
  169. MemInfo->MappedLength = 0;
  170. return_ACPI_STATUS (AE_NO_MEMORY);
  171. }
  172. /* Save the physical address and mapping size */
  173. MemInfo->MappedPhysicalAddress = Address;
  174. MemInfo->MappedLength = MapLength;
  175. }
  176. /*
  177. * Generate a logical pointer corresponding to the address we want to
  178. * access
  179. */
  180. LogicalAddrPtr = MemInfo->MappedLogicalAddress +
  181. ((UINT64) Address - (UINT64) MemInfo->MappedPhysicalAddress);
  182. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  183. "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
  184. BitWidth, Function, ACPI_FORMAT_UINT64 (Address)));
  185. /*
  186. * Perform the memory read or write
  187. *
  188. * Note: For machines that do not support non-aligned transfers, the target
  189. * address was checked for alignment above. We do not attempt to break the
  190. * transfer up into smaller (byte-size) chunks because the AML specifically
  191. * asked for a transfer width that the hardware may require.
  192. */
  193. switch (Function)
  194. {
  195. case ACPI_READ:
  196. *Value = 0;
  197. switch (BitWidth)
  198. {
  199. case 8:
  200. *Value = (UINT64) ACPI_GET8 (LogicalAddrPtr);
  201. break;
  202. case 16:
  203. *Value = (UINT64) ACPI_GET16 (LogicalAddrPtr);
  204. break;
  205. case 32:
  206. *Value = (UINT64) ACPI_GET32 (LogicalAddrPtr);
  207. break;
  208. case 64:
  209. *Value = (UINT64) ACPI_GET64 (LogicalAddrPtr);
  210. break;
  211. default:
  212. /* BitWidth was already validated */
  213. break;
  214. }
  215. break;
  216. case ACPI_WRITE:
  217. switch (BitWidth)
  218. {
  219. case 8:
  220. ACPI_SET8 (LogicalAddrPtr, *Value);
  221. break;
  222. case 16:
  223. ACPI_SET16 (LogicalAddrPtr, *Value);
  224. break;
  225. case 32:
  226. ACPI_SET32 (LogicalAddrPtr, *Value);
  227. break;
  228. case 64:
  229. ACPI_SET64 (LogicalAddrPtr, *Value);
  230. break;
  231. default:
  232. /* BitWidth was already validated */
  233. break;
  234. }
  235. break;
  236. default:
  237. Status = AE_BAD_PARAMETER;
  238. break;
  239. }
  240. return_ACPI_STATUS (Status);
  241. }
  242. /*******************************************************************************
  243. *
  244. * FUNCTION: AcpiExSystemIoSpaceHandler
  245. *
  246. * PARAMETERS: Function - Read or Write operation
  247. * Address - Where in the space to read or write
  248. * BitWidth - Field width in bits (8, 16, or 32)
  249. * Value - Pointer to in or out value
  250. * HandlerContext - Pointer to Handler's context
  251. * RegionContext - Pointer to context specific to the
  252. * accessed region
  253. *
  254. * RETURN: Status
  255. *
  256. * DESCRIPTION: Handler for the System IO address space (Op Region)
  257. *
  258. ******************************************************************************/
  259. ACPI_STATUS
  260. AcpiExSystemIoSpaceHandler (
  261. UINT32 Function,
  262. ACPI_PHYSICAL_ADDRESS Address,
  263. UINT32 BitWidth,
  264. UINT64 *Value,
  265. void *HandlerContext,
  266. void *RegionContext)
  267. {
  268. ACPI_STATUS Status = AE_OK;
  269. UINT32 Value32;
  270. ACPI_FUNCTION_TRACE (ExSystemIoSpaceHandler);
  271. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  272. "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
  273. BitWidth, Function, ACPI_FORMAT_UINT64 (Address)));
  274. /* Decode the function parameter */
  275. switch (Function)
  276. {
  277. case ACPI_READ:
  278. Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) Address,
  279. &Value32, BitWidth);
  280. *Value = Value32;
  281. break;
  282. case ACPI_WRITE:
  283. Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) Address,
  284. (UINT32) *Value, BitWidth);
  285. break;
  286. default:
  287. Status = AE_BAD_PARAMETER;
  288. break;
  289. }
  290. return_ACPI_STATUS (Status);
  291. }
  292. /*******************************************************************************
  293. *
  294. * FUNCTION: AcpiExPciConfigSpaceHandler
  295. *
  296. * PARAMETERS: Function - Read or Write operation
  297. * Address - Where in the space to read or write
  298. * BitWidth - Field width in bits (8, 16, or 32)
  299. * Value - Pointer to in or out value
  300. * HandlerContext - Pointer to Handler's context
  301. * RegionContext - Pointer to context specific to the
  302. * accessed region
  303. *
  304. * RETURN: Status
  305. *
  306. * DESCRIPTION: Handler for the PCI Config address space (Op Region)
  307. *
  308. ******************************************************************************/
  309. ACPI_STATUS
  310. AcpiExPciConfigSpaceHandler (
  311. UINT32 Function,
  312. ACPI_PHYSICAL_ADDRESS Address,
  313. UINT32 BitWidth,
  314. UINT64 *Value,
  315. void *HandlerContext,
  316. void *RegionContext)
  317. {
  318. ACPI_STATUS Status = AE_OK;
  319. ACPI_PCI_ID *PciId;
  320. UINT16 PciRegister;
  321. ACPI_FUNCTION_TRACE (ExPciConfigSpaceHandler);
  322. /*
  323. * The arguments to AcpiOs(Read|Write)PciConfiguration are:
  324. *
  325. * PciSegment is the PCI bus segment range 0-31
  326. * PciBus is the PCI bus number range 0-255
  327. * PciDevice is the PCI device number range 0-31
  328. * PciFunction is the PCI device function number
  329. * PciRegister is the Config space register range 0-255 bytes
  330. *
  331. * Value - input value for write, output address for read
  332. *
  333. */
  334. PciId = (ACPI_PCI_ID *) RegionContext;
  335. PciRegister = (UINT16) (UINT32) Address;
  336. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  337. "Pci-Config %u (%u) Seg(%04x) Bus(%04x) "
  338. "Dev(%04x) Func(%04x) Reg(%04x)\n",
  339. Function, BitWidth, PciId->Segment, PciId->Bus, PciId->Device,
  340. PciId->Function, PciRegister));
  341. switch (Function)
  342. {
  343. case ACPI_READ:
  344. *Value = 0;
  345. Status = AcpiOsReadPciConfiguration (
  346. PciId, PciRegister, Value, BitWidth);
  347. break;
  348. case ACPI_WRITE:
  349. Status = AcpiOsWritePciConfiguration (
  350. PciId, PciRegister, *Value, BitWidth);
  351. break;
  352. default:
  353. Status = AE_BAD_PARAMETER;
  354. break;
  355. }
  356. return_ACPI_STATUS (Status);
  357. }
  358. /*******************************************************************************
  359. *
  360. * FUNCTION: AcpiExCmosSpaceHandler
  361. *
  362. * PARAMETERS: Function - Read or Write operation
  363. * Address - Where in the space to read or write
  364. * BitWidth - Field width in bits (8, 16, or 32)
  365. * Value - Pointer to in or out value
  366. * HandlerContext - Pointer to Handler's context
  367. * RegionContext - Pointer to context specific to the
  368. * accessed region
  369. *
  370. * RETURN: Status
  371. *
  372. * DESCRIPTION: Handler for the CMOS address space (Op Region)
  373. *
  374. ******************************************************************************/
  375. ACPI_STATUS
  376. AcpiExCmosSpaceHandler (
  377. UINT32 Function,
  378. ACPI_PHYSICAL_ADDRESS Address,
  379. UINT32 BitWidth,
  380. UINT64 *Value,
  381. void *HandlerContext,
  382. void *RegionContext)
  383. {
  384. ACPI_STATUS Status = AE_OK;
  385. ACPI_FUNCTION_TRACE (ExCmosSpaceHandler);
  386. return_ACPI_STATUS (Status);
  387. }
  388. /*******************************************************************************
  389. *
  390. * FUNCTION: AcpiExPciBarSpaceHandler
  391. *
  392. * PARAMETERS: Function - Read or Write operation
  393. * Address - Where in the space to read or write
  394. * BitWidth - Field width in bits (8, 16, or 32)
  395. * Value - Pointer to in or out value
  396. * HandlerContext - Pointer to Handler's context
  397. * RegionContext - Pointer to context specific to the
  398. * accessed region
  399. *
  400. * RETURN: Status
  401. *
  402. * DESCRIPTION: Handler for the PCI BarTarget address space (Op Region)
  403. *
  404. ******************************************************************************/
  405. ACPI_STATUS
  406. AcpiExPciBarSpaceHandler (
  407. UINT32 Function,
  408. ACPI_PHYSICAL_ADDRESS Address,
  409. UINT32 BitWidth,
  410. UINT64 *Value,
  411. void *HandlerContext,
  412. void *RegionContext)
  413. {
  414. ACPI_STATUS Status = AE_OK;
  415. ACPI_FUNCTION_TRACE (ExPciBarSpaceHandler);
  416. return_ACPI_STATUS (Status);
  417. }
  418. /*******************************************************************************
  419. *
  420. * FUNCTION: AcpiExDataTableSpaceHandler
  421. *
  422. * PARAMETERS: Function - Read or Write operation
  423. * Address - Where in the space to read or write
  424. * BitWidth - Field width in bits (8, 16, or 32)
  425. * Value - Pointer to in or out value
  426. * HandlerContext - Pointer to Handler's context
  427. * RegionContext - Pointer to context specific to the
  428. * accessed region
  429. *
  430. * RETURN: Status
  431. *
  432. * DESCRIPTION: Handler for the Data Table address space (Op Region)
  433. *
  434. ******************************************************************************/
  435. ACPI_STATUS
  436. AcpiExDataTableSpaceHandler (
  437. UINT32 Function,
  438. ACPI_PHYSICAL_ADDRESS Address,
  439. UINT32 BitWidth,
  440. UINT64 *Value,
  441. void *HandlerContext,
  442. void *RegionContext)
  443. {
  444. ACPI_FUNCTION_TRACE (ExDataTableSpaceHandler);
  445. /*
  446. * Perform the memory read or write. The BitWidth was already
  447. * validated.
  448. */
  449. switch (Function)
  450. {
  451. case ACPI_READ:
  452. memcpy (ACPI_CAST_PTR (char, Value), ACPI_PHYSADDR_TO_PTR (Address),
  453. ACPI_DIV_8 (BitWidth));
  454. break;
  455. case ACPI_WRITE:
  456. memcpy (ACPI_PHYSADDR_TO_PTR (Address), ACPI_CAST_PTR (char, Value),
  457. ACPI_DIV_8 (BitWidth));
  458. break;
  459. default:
  460. return_ACPI_STATUS (AE_BAD_PARAMETER);
  461. }
  462. return_ACPI_STATUS (AE_OK);
  463. }