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