rsmisc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. /*******************************************************************************
  2. *
  3. * Module Name: rsmisc - Miscellaneous resource descriptors
  4. *
  5. ******************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2006, R. Byron Moore
  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/acpi.h>
  43. #include <acpi/acresrc.h>
  44. #define _COMPONENT ACPI_RESOURCES
  45. ACPI_MODULE_NAME("rsmisc")
  46. #define INIT_RESOURCE_TYPE(i) i->resource_offset
  47. #define INIT_RESOURCE_LENGTH(i) i->aml_offset
  48. #define INIT_TABLE_LENGTH(i) i->value
  49. #define COMPARE_OPCODE(i) i->resource_offset
  50. #define COMPARE_TARGET(i) i->aml_offset
  51. #define COMPARE_VALUE(i) i->value
  52. /*******************************************************************************
  53. *
  54. * FUNCTION: acpi_rs_convert_aml_to_resource
  55. *
  56. * PARAMETERS: Resource - Pointer to the resource descriptor
  57. * Aml - Where the AML descriptor is returned
  58. * Info - Pointer to appropriate conversion table
  59. *
  60. * RETURN: Status
  61. *
  62. * DESCRIPTION: Convert an external AML resource descriptor to the corresponding
  63. * internal resource descriptor
  64. *
  65. ******************************************************************************/
  66. acpi_status
  67. acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
  68. union aml_resource *aml,
  69. struct acpi_rsconvert_info *info)
  70. {
  71. acpi_rs_length aml_resource_length;
  72. void *source;
  73. void *destination;
  74. char *target;
  75. u8 count;
  76. u8 flags_mode = FALSE;
  77. u16 item_count = 0;
  78. u16 temp16 = 0;
  79. ACPI_FUNCTION_TRACE("rs_get_resource");
  80. if (((acpi_native_uint) resource) & 0x3) {
  81. acpi_os_printf
  82. ("**** GET: Misaligned resource pointer: %p Type %2.2X Len %X\n",
  83. resource, resource->type, resource->length);
  84. }
  85. /* Extract the resource Length field (does not include header length) */
  86. aml_resource_length = acpi_ut_get_resource_length(aml);
  87. /*
  88. * First table entry must be ACPI_RSC_INITxxx and must contain the
  89. * table length (# of table entries)
  90. */
  91. count = INIT_TABLE_LENGTH(info);
  92. while (count) {
  93. /*
  94. * Source is the external AML byte stream buffer,
  95. * destination is the internal resource descriptor
  96. */
  97. source = ACPI_ADD_PTR(void, aml, info->aml_offset);
  98. destination =
  99. ACPI_ADD_PTR(void, resource, info->resource_offset);
  100. switch (info->opcode) {
  101. case ACPI_RSC_INITGET:
  102. /*
  103. * Get the resource type and the initial (minimum) length
  104. */
  105. ACPI_MEMSET(resource, 0, INIT_RESOURCE_LENGTH(info));
  106. resource->type = INIT_RESOURCE_TYPE(info);
  107. resource->length = INIT_RESOURCE_LENGTH(info);
  108. break;
  109. case ACPI_RSC_INITSET:
  110. break;
  111. case ACPI_RSC_FLAGINIT:
  112. flags_mode = TRUE;
  113. break;
  114. case ACPI_RSC_1BITFLAG:
  115. /*
  116. * Mask and shift the flag bit
  117. */
  118. ACPI_SET8(destination) = (u8)
  119. ((ACPI_GET8(source) >> info->value) & 0x01);
  120. break;
  121. case ACPI_RSC_2BITFLAG:
  122. /*
  123. * Mask and shift the flag bits
  124. */
  125. ACPI_SET8(destination) = (u8)
  126. ((ACPI_GET8(source) >> info->value) & 0x03);
  127. break;
  128. case ACPI_RSC_COUNT:
  129. item_count = ACPI_GET8(source);
  130. ACPI_SET8(destination) = (u8) item_count;
  131. resource->length = resource->length +
  132. (info->value * (item_count - 1));
  133. break;
  134. case ACPI_RSC_COUNT16:
  135. item_count = aml_resource_length;
  136. ACPI_SET16(destination) = item_count;
  137. resource->length = resource->length +
  138. (info->value * (item_count - 1));
  139. break;
  140. case ACPI_RSC_LENGTH:
  141. resource->length = resource->length + info->value;
  142. break;
  143. case ACPI_RSC_MOVE8:
  144. case ACPI_RSC_MOVE16:
  145. case ACPI_RSC_MOVE32:
  146. case ACPI_RSC_MOVE64:
  147. /*
  148. * Raw data move. Use the Info value field unless item_count has
  149. * been previously initialized via a COUNT opcode
  150. */
  151. if (info->value) {
  152. item_count = info->value;
  153. }
  154. acpi_rs_move_data(destination, source, item_count,
  155. info->opcode);
  156. break;
  157. case ACPI_RSC_SET8:
  158. ACPI_MEMSET(destination, info->aml_offset, info->value);
  159. break;
  160. case ACPI_RSC_DATA8:
  161. target = ACPI_ADD_PTR(char, resource, info->value);
  162. ACPI_MEMCPY(destination, source, ACPI_GET16(target));
  163. break;
  164. case ACPI_RSC_ADDRESS:
  165. /*
  166. * Common handler for address descriptor flags
  167. */
  168. if (!acpi_rs_get_address_common(resource, aml)) {
  169. return_ACPI_STATUS
  170. (AE_AML_INVALID_RESOURCE_TYPE);
  171. }
  172. break;
  173. case ACPI_RSC_SOURCE:
  174. /*
  175. * Optional resource_source (Index and String)
  176. */
  177. resource->length +=
  178. acpi_rs_get_resource_source(aml_resource_length,
  179. info->value,
  180. destination, aml, NULL);
  181. break;
  182. case ACPI_RSC_SOURCEX:
  183. /*
  184. * Optional resource_source (Index and String). This is the more
  185. * complicated case used by the Interrupt() macro
  186. */
  187. target =
  188. ACPI_ADD_PTR(char, resource,
  189. info->aml_offset + (item_count * 4));
  190. resource->length +=
  191. acpi_rs_get_resource_source(aml_resource_length,
  192. (acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target);
  193. break;
  194. case ACPI_RSC_BITMASK:
  195. /*
  196. * 8-bit encoded bitmask (DMA macro)
  197. */
  198. item_count =
  199. acpi_rs_decode_bitmask(ACPI_GET8(source),
  200. destination);
  201. if (item_count) {
  202. resource->length += (item_count - 1);
  203. }
  204. target = ACPI_ADD_PTR(char, resource, info->value);
  205. ACPI_SET8(target) = (u8) item_count;
  206. break;
  207. case ACPI_RSC_BITMASK16:
  208. /*
  209. * 16-bit encoded bitmask (IRQ macro)
  210. */
  211. ACPI_MOVE_16_TO_16(&temp16, source);
  212. item_count =
  213. acpi_rs_decode_bitmask(temp16, destination);
  214. if (item_count) {
  215. resource->length += (item_count - 1);
  216. }
  217. target = ACPI_ADD_PTR(char, resource, info->value);
  218. ACPI_SET8(target) = (u8) item_count;
  219. break;
  220. case ACPI_RSC_EXIT_NE:
  221. /*
  222. * Control - Exit conversion if not equal
  223. */
  224. switch (info->resource_offset) {
  225. case ACPI_RSC_COMPARE_AML_LENGTH:
  226. if (aml_resource_length != info->value) {
  227. goto exit;
  228. }
  229. break;
  230. case ACPI_RSC_COMPARE_VALUE:
  231. if (ACPI_GET8(source) != info->value) {
  232. goto exit;
  233. }
  234. break;
  235. default:
  236. acpi_os_printf
  237. ("*** Invalid conversion sub-opcode\n");
  238. return_ACPI_STATUS(AE_BAD_PARAMETER);
  239. }
  240. break;
  241. default:
  242. acpi_os_printf("*** Invalid conversion opcode\n");
  243. return_ACPI_STATUS(AE_BAD_PARAMETER);
  244. }
  245. count--;
  246. info++;
  247. }
  248. exit:
  249. if (!flags_mode) {
  250. /* Round the resource struct length up to the next 32-bit boundary */
  251. resource->length = ACPI_ROUND_UP_to_32_bITS(resource->length);
  252. }
  253. return_ACPI_STATUS(AE_OK);
  254. }
  255. /*******************************************************************************
  256. *
  257. * FUNCTION: acpi_rs_convert_resource_to_aml
  258. *
  259. * PARAMETERS: Resource - Pointer to the resource descriptor
  260. * Aml - Where the AML descriptor is returned
  261. * Info - Pointer to appropriate conversion table
  262. *
  263. * RETURN: Status
  264. *
  265. * DESCRIPTION: Convert an internal resource descriptor to the corresponding
  266. * external AML resource descriptor.
  267. *
  268. ******************************************************************************/
  269. acpi_status
  270. acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
  271. union aml_resource *aml,
  272. struct acpi_rsconvert_info *info)
  273. {
  274. void *source = NULL;
  275. void *destination;
  276. acpi_rsdesc_size aml_length = 0;
  277. u8 count;
  278. u16 temp16 = 0;
  279. u16 item_count = 0;
  280. ACPI_FUNCTION_TRACE("rs_convert_resource_to_aml");
  281. /*
  282. * First table entry must be ACPI_RSC_INITxxx and must contain the
  283. * table length (# of table entries)
  284. */
  285. count = INIT_TABLE_LENGTH(info);
  286. while (count) {
  287. /*
  288. * Source is the internal resource descriptor,
  289. * destination is the external AML byte stream buffer
  290. */
  291. source = ACPI_ADD_PTR(void, resource, info->resource_offset);
  292. destination = ACPI_ADD_PTR(void, aml, info->aml_offset);
  293. switch (info->opcode) {
  294. case ACPI_RSC_INITSET:
  295. ACPI_MEMSET(aml, 0, INIT_RESOURCE_LENGTH(info));
  296. aml_length = INIT_RESOURCE_LENGTH(info);
  297. acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info),
  298. aml_length, aml);
  299. break;
  300. case ACPI_RSC_INITGET:
  301. break;
  302. case ACPI_RSC_FLAGINIT:
  303. /*
  304. * Clear the flag byte
  305. */
  306. ACPI_SET8(destination) = 0;
  307. break;
  308. case ACPI_RSC_1BITFLAG:
  309. /*
  310. * Mask and shift the flag bit
  311. */
  312. ACPI_SET8(destination) |= (u8)
  313. ((ACPI_GET8(source) & 0x01) << info->value);
  314. break;
  315. case ACPI_RSC_2BITFLAG:
  316. /*
  317. * Mask and shift the flag bits
  318. */
  319. ACPI_SET8(destination) |= (u8)
  320. ((ACPI_GET8(source) & 0x03) << info->value);
  321. break;
  322. case ACPI_RSC_COUNT:
  323. item_count = ACPI_GET8(source);
  324. ACPI_SET8(destination) = (u8) item_count;
  325. aml_length =
  326. (u16) (aml_length +
  327. (info->value * (item_count - 1)));
  328. break;
  329. case ACPI_RSC_COUNT16:
  330. item_count = ACPI_GET16(source);
  331. aml_length = (u16) (aml_length + item_count);
  332. acpi_rs_set_resource_length(aml_length, aml);
  333. break;
  334. case ACPI_RSC_LENGTH:
  335. acpi_rs_set_resource_length(info->value, aml);
  336. break;
  337. case ACPI_RSC_MOVE8:
  338. case ACPI_RSC_MOVE16:
  339. case ACPI_RSC_MOVE32:
  340. case ACPI_RSC_MOVE64:
  341. if (info->value) {
  342. item_count = info->value;
  343. }
  344. acpi_rs_move_data(destination, source, item_count,
  345. info->opcode);
  346. break;
  347. case ACPI_RSC_ADDRESS:
  348. /* Set the Resource Type, General Flags, and Type-Specific Flags */
  349. acpi_rs_set_address_common(aml, resource);
  350. break;
  351. case ACPI_RSC_SOURCEX:
  352. /*
  353. * Optional resource_source (Index and String)
  354. */
  355. aml_length =
  356. acpi_rs_set_resource_source(aml,
  357. (acpi_rs_length)
  358. aml_length, source);
  359. acpi_rs_set_resource_length(aml_length, aml);
  360. break;
  361. case ACPI_RSC_SOURCE:
  362. /*
  363. * Optional resource_source (Index and String). This is the more
  364. * complicated case used by the Interrupt() macro
  365. */
  366. aml_length =
  367. acpi_rs_set_resource_source(aml, info->value,
  368. source);
  369. acpi_rs_set_resource_length(aml_length, aml);
  370. break;
  371. case ACPI_RSC_BITMASK:
  372. /*
  373. * 8-bit encoded bitmask (DMA macro)
  374. */
  375. ACPI_SET8(destination) = (u8)
  376. acpi_rs_encode_bitmask(source,
  377. *ACPI_ADD_PTR(u8, resource,
  378. info->value));
  379. break;
  380. case ACPI_RSC_BITMASK16:
  381. /*
  382. * 16-bit encoded bitmask (IRQ macro)
  383. */
  384. temp16 = acpi_rs_encode_bitmask(source,
  385. *ACPI_ADD_PTR(u8,
  386. resource,
  387. info->
  388. value));
  389. ACPI_MOVE_16_TO_16(destination, &temp16);
  390. break;
  391. case ACPI_RSC_EXIT_LE:
  392. /*
  393. * Control - Exit conversion if less than or equal
  394. */
  395. if (item_count <= info->value) {
  396. goto exit;
  397. }
  398. break;
  399. case ACPI_RSC_EXIT_NE:
  400. /*
  401. * Control - Exit conversion if not equal
  402. */
  403. switch (COMPARE_OPCODE(info)) {
  404. case ACPI_RSC_COMPARE_VALUE:
  405. if (*ACPI_ADD_PTR(u8, resource,
  406. COMPARE_TARGET(info)) !=
  407. COMPARE_VALUE(info)) {
  408. goto exit;
  409. }
  410. break;
  411. default:
  412. acpi_os_printf
  413. ("*** Invalid conversion sub-opcode\n");
  414. return_ACPI_STATUS(AE_BAD_PARAMETER);
  415. }
  416. break;
  417. default:
  418. acpi_os_printf("*** Invalid conversion opcode\n");
  419. return_ACPI_STATUS(AE_BAD_PARAMETER);
  420. }
  421. count--;
  422. info++;
  423. }
  424. exit:
  425. return_ACPI_STATUS(AE_OK);
  426. }
  427. #if 0
  428. /* Previous resource validations */
  429. if (aml->ext_address64.revision_iD != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) {
  430. return_ACPI_STATUS(AE_SUPPORT);
  431. }
  432. if (resource->data.start_dpf.performance_robustness >= 3) {
  433. return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
  434. }
  435. if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) {
  436. /*
  437. * Only [active_high, edge_sensitive] or [active_low, level_sensitive]
  438. * polarity/trigger interrupts are allowed (ACPI spec, section
  439. * "IRQ Format"), so 0x00 and 0x09 are illegal.
  440. */
  441. ACPI_REPORT_ERROR(("Invalid interrupt polarity/trigger in resource list, %X\n", aml->irq.flags));
  442. return_ACPI_STATUS(AE_BAD_DATA);
  443. }
  444. resource->data.extended_irq.interrupt_count = temp8;
  445. if (temp8 < 1) {
  446. /* Must have at least one IRQ */
  447. return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
  448. }
  449. if (resource->data.dma.transfer == 0x03) {
  450. ACPI_REPORT_ERROR(("Invalid DMA.Transfer preference (3)\n"));
  451. return_ACPI_STATUS(AE_BAD_DATA);
  452. }
  453. #endif