rsmisc.c 14 KB

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