exregion.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Module Name: exregion - ACPI default op_region (address space) handlers
  5. *
  6. * Copyright (C) 2000 - 2018, Intel Corp.
  7. *
  8. *****************************************************************************/
  9. #include <acpi/acpi.h>
  10. #include "accommon.h"
  11. #include "acinterp.h"
  12. #define _COMPONENT ACPI_EXECUTER
  13. ACPI_MODULE_NAME("exregion")
  14. /*******************************************************************************
  15. *
  16. * FUNCTION: acpi_ex_system_memory_space_handler
  17. *
  18. * PARAMETERS: function - Read or Write operation
  19. * address - Where in the space to read or write
  20. * bit_width - Field width in bits (8, 16, or 32)
  21. * value - Pointer to in or out value
  22. * handler_context - Pointer to Handler's context
  23. * region_context - Pointer to context specific to the
  24. * accessed region
  25. *
  26. * RETURN: Status
  27. *
  28. * DESCRIPTION: Handler for the System Memory address space (Op Region)
  29. *
  30. ******************************************************************************/
  31. acpi_status
  32. acpi_ex_system_memory_space_handler(u32 function,
  33. acpi_physical_address address,
  34. u32 bit_width,
  35. u64 *value,
  36. void *handler_context, void *region_context)
  37. {
  38. acpi_status status = AE_OK;
  39. void *logical_addr_ptr = NULL;
  40. struct acpi_mem_space_context *mem_info = region_context;
  41. u32 length;
  42. acpi_size map_length;
  43. acpi_size page_boundary_map_length;
  44. #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
  45. u32 remainder;
  46. #endif
  47. ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
  48. /* Validate and translate the bit width */
  49. switch (bit_width) {
  50. case 8:
  51. length = 1;
  52. break;
  53. case 16:
  54. length = 2;
  55. break;
  56. case 32:
  57. length = 4;
  58. break;
  59. case 64:
  60. length = 8;
  61. break;
  62. default:
  63. ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u",
  64. bit_width));
  65. return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
  66. }
  67. #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
  68. /*
  69. * Hardware does not support non-aligned data transfers, we must verify
  70. * the request.
  71. */
  72. (void)acpi_ut_short_divide((u64) address, length, NULL, &remainder);
  73. if (remainder != 0) {
  74. return_ACPI_STATUS(AE_AML_ALIGNMENT);
  75. }
  76. #endif
  77. /*
  78. * Does the request fit into the cached memory mapping?
  79. * Is 1) Address below the current mapping? OR
  80. * 2) Address beyond the current mapping?
  81. */
  82. if ((address < mem_info->mapped_physical_address) ||
  83. (((u64) address + length) > ((u64)
  84. mem_info->mapped_physical_address +
  85. mem_info->mapped_length))) {
  86. /*
  87. * The request cannot be resolved by the current memory mapping;
  88. * Delete the existing mapping and create a new one.
  89. */
  90. if (mem_info->mapped_length) {
  91. /* Valid mapping, delete it */
  92. acpi_os_unmap_memory(mem_info->mapped_logical_address,
  93. mem_info->mapped_length);
  94. }
  95. /*
  96. * October 2009: Attempt to map from the requested address to the
  97. * end of the region. However, we will never map more than one
  98. * page, nor will we cross a page boundary.
  99. */
  100. map_length = (acpi_size)
  101. ((mem_info->address + mem_info->length) - address);
  102. /*
  103. * If mapping the entire remaining portion of the region will cross
  104. * a page boundary, just map up to the page boundary, do not cross.
  105. * On some systems, crossing a page boundary while mapping regions
  106. * can cause warnings if the pages have different attributes
  107. * due to resource management.
  108. *
  109. * This has the added benefit of constraining a single mapping to
  110. * one page, which is similar to the original code that used a 4k
  111. * maximum window.
  112. */
  113. page_boundary_map_length = (acpi_size)
  114. (ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address);
  115. if (page_boundary_map_length == 0) {
  116. page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE;
  117. }
  118. if (map_length > page_boundary_map_length) {
  119. map_length = page_boundary_map_length;
  120. }
  121. /* Create a new mapping starting at the address given */
  122. mem_info->mapped_logical_address =
  123. acpi_os_map_memory(address, map_length);
  124. if (!mem_info->mapped_logical_address) {
  125. ACPI_ERROR((AE_INFO,
  126. "Could not map memory at 0x%8.8X%8.8X, size %u",
  127. ACPI_FORMAT_UINT64(address),
  128. (u32)map_length));
  129. mem_info->mapped_length = 0;
  130. return_ACPI_STATUS(AE_NO_MEMORY);
  131. }
  132. /* Save the physical address and mapping size */
  133. mem_info->mapped_physical_address = address;
  134. mem_info->mapped_length = map_length;
  135. }
  136. /*
  137. * Generate a logical pointer corresponding to the address we want to
  138. * access
  139. */
  140. logical_addr_ptr = mem_info->mapped_logical_address +
  141. ((u64) address - (u64) mem_info->mapped_physical_address);
  142. ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  143. "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
  144. bit_width, function, ACPI_FORMAT_UINT64(address)));
  145. /*
  146. * Perform the memory read or write
  147. *
  148. * Note: For machines that do not support non-aligned transfers, the target
  149. * address was checked for alignment above. We do not attempt to break the
  150. * transfer up into smaller (byte-size) chunks because the AML specifically
  151. * asked for a transfer width that the hardware may require.
  152. */
  153. switch (function) {
  154. case ACPI_READ:
  155. *value = 0;
  156. switch (bit_width) {
  157. case 8:
  158. *value = (u64)ACPI_GET8(logical_addr_ptr);
  159. break;
  160. case 16:
  161. *value = (u64)ACPI_GET16(logical_addr_ptr);
  162. break;
  163. case 32:
  164. *value = (u64)ACPI_GET32(logical_addr_ptr);
  165. break;
  166. case 64:
  167. *value = (u64)ACPI_GET64(logical_addr_ptr);
  168. break;
  169. default:
  170. /* bit_width was already validated */
  171. break;
  172. }
  173. break;
  174. case ACPI_WRITE:
  175. switch (bit_width) {
  176. case 8:
  177. ACPI_SET8(logical_addr_ptr, *value);
  178. break;
  179. case 16:
  180. ACPI_SET16(logical_addr_ptr, *value);
  181. break;
  182. case 32:
  183. ACPI_SET32(logical_addr_ptr, *value);
  184. break;
  185. case 64:
  186. ACPI_SET64(logical_addr_ptr, *value);
  187. break;
  188. default:
  189. /* bit_width was already validated */
  190. break;
  191. }
  192. break;
  193. default:
  194. status = AE_BAD_PARAMETER;
  195. break;
  196. }
  197. return_ACPI_STATUS(status);
  198. }
  199. /*******************************************************************************
  200. *
  201. * FUNCTION: acpi_ex_system_io_space_handler
  202. *
  203. * PARAMETERS: function - Read or Write operation
  204. * address - Where in the space to read or write
  205. * bit_width - Field width in bits (8, 16, or 32)
  206. * value - Pointer to in or out value
  207. * handler_context - Pointer to Handler's context
  208. * region_context - Pointer to context specific to the
  209. * accessed region
  210. *
  211. * RETURN: Status
  212. *
  213. * DESCRIPTION: Handler for the System IO address space (Op Region)
  214. *
  215. ******************************************************************************/
  216. acpi_status
  217. acpi_ex_system_io_space_handler(u32 function,
  218. acpi_physical_address address,
  219. u32 bit_width,
  220. u64 *value,
  221. void *handler_context, void *region_context)
  222. {
  223. acpi_status status = AE_OK;
  224. u32 value32;
  225. ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
  226. ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  227. "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
  228. bit_width, function, ACPI_FORMAT_UINT64(address)));
  229. /* Decode the function parameter */
  230. switch (function) {
  231. case ACPI_READ:
  232. status = acpi_hw_read_port((acpi_io_address)address,
  233. &value32, bit_width);
  234. *value = value32;
  235. break;
  236. case ACPI_WRITE:
  237. status = acpi_hw_write_port((acpi_io_address)address,
  238. (u32)*value, bit_width);
  239. break;
  240. default:
  241. status = AE_BAD_PARAMETER;
  242. break;
  243. }
  244. return_ACPI_STATUS(status);
  245. }
  246. /*******************************************************************************
  247. *
  248. * FUNCTION: acpi_ex_pci_config_space_handler
  249. *
  250. * PARAMETERS: function - Read or Write operation
  251. * address - Where in the space to read or write
  252. * bit_width - Field width in bits (8, 16, or 32)
  253. * value - Pointer to in or out value
  254. * handler_context - Pointer to Handler's context
  255. * region_context - Pointer to context specific to the
  256. * accessed region
  257. *
  258. * RETURN: Status
  259. *
  260. * DESCRIPTION: Handler for the PCI Config address space (Op Region)
  261. *
  262. ******************************************************************************/
  263. acpi_status
  264. acpi_ex_pci_config_space_handler(u32 function,
  265. acpi_physical_address address,
  266. u32 bit_width,
  267. u64 *value,
  268. void *handler_context, void *region_context)
  269. {
  270. acpi_status status = AE_OK;
  271. struct acpi_pci_id *pci_id;
  272. u16 pci_register;
  273. ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
  274. /*
  275. * The arguments to acpi_os(Read|Write)pci_configuration are:
  276. *
  277. * pci_segment is the PCI bus segment range 0-31
  278. * pci_bus is the PCI bus number range 0-255
  279. * pci_device is the PCI device number range 0-31
  280. * pci_function is the PCI device function number
  281. * pci_register is the Config space register range 0-255 bytes
  282. *
  283. * value - input value for write, output address for read
  284. *
  285. */
  286. pci_id = (struct acpi_pci_id *)region_context;
  287. pci_register = (u16) (u32) address;
  288. ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  289. "Pci-Config %u (%u) Seg(%04x) Bus(%04x) "
  290. "Dev(%04x) Func(%04x) Reg(%04x)\n",
  291. function, bit_width, pci_id->segment, pci_id->bus,
  292. pci_id->device, pci_id->function, pci_register));
  293. switch (function) {
  294. case ACPI_READ:
  295. *value = 0;
  296. status =
  297. acpi_os_read_pci_configuration(pci_id, pci_register, value,
  298. bit_width);
  299. break;
  300. case ACPI_WRITE:
  301. status =
  302. acpi_os_write_pci_configuration(pci_id, pci_register,
  303. *value, bit_width);
  304. break;
  305. default:
  306. status = AE_BAD_PARAMETER;
  307. break;
  308. }
  309. return_ACPI_STATUS(status);
  310. }
  311. /*******************************************************************************
  312. *
  313. * FUNCTION: acpi_ex_cmos_space_handler
  314. *
  315. * PARAMETERS: function - Read or Write operation
  316. * address - Where in the space to read or write
  317. * bit_width - Field width in bits (8, 16, or 32)
  318. * value - Pointer to in or out value
  319. * handler_context - Pointer to Handler's context
  320. * region_context - Pointer to context specific to the
  321. * accessed region
  322. *
  323. * RETURN: Status
  324. *
  325. * DESCRIPTION: Handler for the CMOS address space (Op Region)
  326. *
  327. ******************************************************************************/
  328. acpi_status
  329. acpi_ex_cmos_space_handler(u32 function,
  330. acpi_physical_address address,
  331. u32 bit_width,
  332. u64 *value,
  333. void *handler_context, void *region_context)
  334. {
  335. acpi_status status = AE_OK;
  336. ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
  337. return_ACPI_STATUS(status);
  338. }
  339. /*******************************************************************************
  340. *
  341. * FUNCTION: acpi_ex_pci_bar_space_handler
  342. *
  343. * PARAMETERS: function - Read or Write operation
  344. * address - Where in the space to read or write
  345. * bit_width - Field width in bits (8, 16, or 32)
  346. * value - Pointer to in or out value
  347. * handler_context - Pointer to Handler's context
  348. * region_context - Pointer to context specific to the
  349. * accessed region
  350. *
  351. * RETURN: Status
  352. *
  353. * DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
  354. *
  355. ******************************************************************************/
  356. acpi_status
  357. acpi_ex_pci_bar_space_handler(u32 function,
  358. acpi_physical_address address,
  359. u32 bit_width,
  360. u64 *value,
  361. void *handler_context, void *region_context)
  362. {
  363. acpi_status status = AE_OK;
  364. ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
  365. return_ACPI_STATUS(status);
  366. }
  367. /*******************************************************************************
  368. *
  369. * FUNCTION: acpi_ex_data_table_space_handler
  370. *
  371. * PARAMETERS: function - Read or Write operation
  372. * address - Where in the space to read or write
  373. * bit_width - Field width in bits (8, 16, or 32)
  374. * value - Pointer to in or out value
  375. * handler_context - Pointer to Handler's context
  376. * region_context - Pointer to context specific to the
  377. * accessed region
  378. *
  379. * RETURN: Status
  380. *
  381. * DESCRIPTION: Handler for the Data Table address space (Op Region)
  382. *
  383. ******************************************************************************/
  384. acpi_status
  385. acpi_ex_data_table_space_handler(u32 function,
  386. acpi_physical_address address,
  387. u32 bit_width,
  388. u64 *value,
  389. void *handler_context, void *region_context)
  390. {
  391. ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
  392. /*
  393. * Perform the memory read or write. The bit_width was already
  394. * validated.
  395. */
  396. switch (function) {
  397. case ACPI_READ:
  398. memcpy(ACPI_CAST_PTR(char, value),
  399. ACPI_PHYSADDR_TO_PTR(address), ACPI_DIV_8(bit_width));
  400. break;
  401. case ACPI_WRITE:
  402. memcpy(ACPI_PHYSADDR_TO_PTR(address),
  403. ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width));
  404. break;
  405. default:
  406. return_ACPI_STATUS(AE_BAD_PARAMETER);
  407. }
  408. return_ACPI_STATUS(AE_OK);
  409. }