Merge trunk HEAD (46152)
[reactos.git] / drivers / bus / acpi / executer / amprep.c
1
2 /******************************************************************************
3 *
4 * Module Name: amprep - ACPI AML (p-code) execution - field prep utilities
5 * $Revision: 1.1 $
6 *
7 *****************************************************************************/
8
9 /*
10 * Copyright (C) 2000, 2001 R. Byron Moore
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27
28 #include <acpi.h>
29
30
31 #define _COMPONENT ACPI_EXECUTER
32 MODULE_NAME ("amprep")
33
34
35 /*******************************************************************************
36 *
37 * FUNCTION: Acpi_aml_decode_field_access_type
38 *
39 * PARAMETERS: Access - Encoded field access bits
40 *
41 * RETURN: Field granularity (8, 16, or 32)
42 *
43 * DESCRIPTION: Decode the Access_type bits of a field definition.
44 *
45 ******************************************************************************/
46
47 static u32
48 acpi_aml_decode_field_access_type (
49 u32 access,
50 u16 length)
51 {
52
53 switch (access) {
54 case ACCESS_ANY_ACC:
55 if (length <= 8) {
56 return (8);
57 }
58 else if (length <= 16) {
59 return (16);
60 }
61 else if (length <= 32) {
62 return (32);
63 }
64 else {
65 return (8);
66 }
67 break;
68
69 case ACCESS_BYTE_ACC:
70 return (8);
71 break;
72
73 case ACCESS_WORD_ACC:
74 return (16);
75 break;
76
77 case ACCESS_DWORD_ACC:
78 return (32);
79 break;
80
81 default:
82 /* Invalid field access type */
83
84 return (0);
85 }
86 }
87
88
89 /*******************************************************************************
90 *
91 * FUNCTION: Acpi_aml_prep_common_field_objec
92 *
93 * PARAMETERS: Obj_desc - The field object
94 * Field_flags - Access, Lock_rule, or Update_rule.
95 * The format of a Field_flag is described
96 * in the ACPI specification
97 * Field_position - Field position
98 * Field_length - Field length
99 *
100 * RETURN: Status
101 *
102 * DESCRIPTION: Initialize the areas of the field object that are common
103 * to the various types of fields.
104 *
105 ******************************************************************************/
106
107 static ACPI_STATUS
108 acpi_aml_prep_common_field_object (
109 ACPI_OPERAND_OBJECT *obj_desc,
110 u8 field_flags,
111 u8 field_attribute,
112 u32 field_position,
113 u32 field_length)
114 {
115 u32 granularity;
116
117
118 /*
119 * Note: the structure being initialized is the
120 * ACPI_COMMON_FIELD_INFO; Therefore, we can just use the Field union to
121 * access this common area. No structure fields outside of the common area
122 * are initialized by this procedure.
123 */
124
125 /* Decode the Field_flags */
126
127 obj_desc->field.access = (u8) ((field_flags & ACCESS_TYPE_MASK)
128 >> ACCESS_TYPE_SHIFT);
129 obj_desc->field.lock_rule = (u8) ((field_flags & LOCK_RULE_MASK)
130 >> LOCK_RULE_SHIFT);
131 obj_desc->field.update_rule = (u8) ((field_flags & UPDATE_RULE_MASK)
132 >> UPDATE_RULE_SHIFT);
133
134 /* Other misc fields */
135
136 obj_desc->field.length = (u16) field_length;
137 obj_desc->field.access_attribute = field_attribute;
138
139 /* Decode the access type so we can compute offsets */
140
141 granularity = acpi_aml_decode_field_access_type (obj_desc->field.access, obj_desc->field.length);
142 if (!granularity) {
143 return (AE_AML_OPERAND_VALUE);
144 }
145
146 /* Access granularity based fields */
147
148 obj_desc->field.granularity = (u8) granularity;
149 obj_desc->field.bit_offset = (u8) (field_position % granularity);
150 obj_desc->field.offset = (u32) field_position / granularity;
151
152
153 return (AE_OK);
154 }
155
156
157 /*******************************************************************************
158 *
159 * FUNCTION: Acpi_aml_prep_def_field_value
160 *
161 * PARAMETERS: Node - Owning Node
162 * Region - Region in which field is being defined
163 * Field_flags - Access, Lock_rule, or Update_rule.
164 * The format of a Field_flag is described
165 * in the ACPI specification
166 * Field_position - Field position
167 * Field_length - Field length
168 *
169 * RETURN: Status
170 *
171 * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type Def_field and
172 * connect it to the parent Node.
173 *
174 ******************************************************************************/
175
176 ACPI_STATUS
177 acpi_aml_prep_def_field_value (
178 ACPI_NAMESPACE_NODE *node,
179 ACPI_HANDLE region,
180 u8 field_flags,
181 u8 field_attribute,
182 u32 field_position,
183 u32 field_length)
184 {
185 ACPI_OPERAND_OBJECT *obj_desc;
186 u32 type;
187 ACPI_STATUS status;
188
189
190 /* Parameter validation */
191
192 if (!region) {
193 return (AE_AML_NO_OPERAND);
194 }
195
196 type = acpi_ns_get_type (region);
197 if (type != ACPI_TYPE_REGION) {
198 return (AE_AML_OPERAND_TYPE);
199 }
200
201 /* Allocate a new object */
202
203 obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_DEF_FIELD);
204 if (!obj_desc) {
205 return (AE_NO_MEMORY);
206 }
207
208
209 /* Obj_desc and Region valid */
210
211 /* Initialize areas of the object that are common to all fields */
212
213 status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute,
214 field_position, field_length);
215 if (ACPI_FAILURE (status)) {
216 return (status);
217 }
218
219 /* Initialize areas of the object that are specific to this field type */
220
221 obj_desc->field.container = acpi_ns_get_attached_object (region);
222
223 /* An additional reference for the container */
224
225 acpi_cm_add_reference (obj_desc->field.container);
226
227
228 /* Debug info */
229
230 /*
231 * Store the constructed descriptor (Obj_desc) into the Named_obj whose
232 * handle is on TOS, preserving the current type of that Named_obj.
233 */
234 status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc,
235 (u8) acpi_ns_get_type ((ACPI_HANDLE) node));
236
237 return (status);
238 }
239
240
241 /*******************************************************************************
242 *
243 * FUNCTION: Acpi_aml_prep_bank_field_value
244 *
245 * PARAMETERS: Node - Owning Node
246 * Region - Region in which field is being defined
247 * Bank_reg - Bank selection register
248 * Bank_val - Value to store in selection register
249 * Field_flags - Access, Lock_rule, or Update_rule
250 * Field_position - Field position
251 * Field_length - Field length
252 *
253 * RETURN: Status
254 *
255 * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type Bank_field and
256 * connect it to the parent Node.
257 *
258 ******************************************************************************/
259
260 ACPI_STATUS
261 acpi_aml_prep_bank_field_value (
262 ACPI_NAMESPACE_NODE *node,
263 ACPI_HANDLE region,
264 ACPI_HANDLE bank_reg,
265 u32 bank_val,
266 u8 field_flags,
267 u8 field_attribute,
268 u32 field_position,
269 u32 field_length)
270 {
271 ACPI_OPERAND_OBJECT *obj_desc;
272 u32 type;
273 ACPI_STATUS status;
274
275
276 /* Parameter validation */
277
278 if (!region) {
279 return (AE_AML_NO_OPERAND);
280 }
281
282 type = acpi_ns_get_type (region);
283 if (type != ACPI_TYPE_REGION) {
284 return (AE_AML_OPERAND_TYPE);
285 }
286
287 /* Allocate a new object */
288
289 obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_BANK_FIELD);
290 if (!obj_desc) {
291 return (AE_NO_MEMORY);
292 }
293
294 /* Obj_desc and Region valid */
295
296 /* Initialize areas of the object that are common to all fields */
297
298 status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute,
299 field_position, field_length);
300 if (ACPI_FAILURE (status)) {
301 return (status);
302 }
303
304 /* Initialize areas of the object that are specific to this field type */
305
306 obj_desc->bank_field.value = bank_val;
307 obj_desc->bank_field.container = acpi_ns_get_attached_object (region);
308 obj_desc->bank_field.bank_select = acpi_ns_get_attached_object (bank_reg);
309
310 /* An additional reference for the container and bank select */
311 /* TBD: [Restructure] is "Bank_select" ever a real internal object?? */
312
313 acpi_cm_add_reference (obj_desc->bank_field.container);
314 acpi_cm_add_reference (obj_desc->bank_field.bank_select);
315
316 /* Debug info */
317
318 /*
319 * Store the constructed descriptor (Obj_desc) into the Named_obj whose
320 * handle is on TOS, preserving the current type of that Named_obj.
321 */
322 status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc,
323 (u8) acpi_ns_get_type ((ACPI_HANDLE) node));
324
325 return (status);
326 }
327
328
329 /*******************************************************************************
330 *
331 * FUNCTION: Acpi_aml_prep_index_field_value
332 *
333 * PARAMETERS: Node - Owning Node
334 * Index_reg - Index register
335 * Data_reg - Data register
336 * Field_flags - Access, Lock_rule, or Update_rule
337 * Field_position - Field position
338 * Field_length - Field length
339 *
340 * RETURN: Status
341 *
342 * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type Index_field and
343 * connect it to the parent Node.
344 *
345 ******************************************************************************/
346
347 ACPI_STATUS
348 acpi_aml_prep_index_field_value (
349 ACPI_NAMESPACE_NODE *node,
350 ACPI_HANDLE index_reg,
351 ACPI_HANDLE data_reg,
352 u8 field_flags,
353 u8 field_attribute,
354 u32 field_position,
355 u32 field_length)
356 {
357 ACPI_OPERAND_OBJECT *obj_desc;
358 ACPI_STATUS status;
359
360
361 /* Parameter validation */
362
363 if (!index_reg || !data_reg) {
364 return (AE_AML_NO_OPERAND);
365 }
366
367 /* Allocate a new object descriptor */
368
369 obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_INDEX_FIELD);
370 if (!obj_desc) {
371 return (AE_NO_MEMORY);
372 }
373
374 /* Initialize areas of the object that are common to all fields */
375
376 status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute,
377 field_position, field_length);
378 if (ACPI_FAILURE (status)) {
379 return (status);
380 }
381
382 /* Initialize areas of the object that are specific to this field type */
383
384 obj_desc->index_field.value = (u32) (field_position /
385 obj_desc->field.granularity);
386 obj_desc->index_field.index = index_reg;
387 obj_desc->index_field.data = data_reg;
388
389 /* Debug info */
390
391 /*
392 * Store the constructed descriptor (Obj_desc) into the Named_obj whose
393 * handle is on TOS, preserving the current type of that Named_obj.
394 */
395 status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc,
396 (u8) acpi_ns_get_type ((ACPI_HANDLE) node));
397
398 return (status);
399 }
400