:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / dispatcher / dsfield.c
1 /******************************************************************************
2  *
3  * Module Name: dsfield - Dispatcher field routines
4  *              $Revision$
5  *
6  *****************************************************************************/
7
8 /*
9  *  Copyright (C) 2000, 2001 R. Byron Moore
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26
27 #include "acpi.h"
28 #include "amlcode.h"
29 #include "acdispat.h"
30 #include "acinterp.h"
31 #include "acnamesp.h"
32
33
34 #define _COMPONENT          ACPI_DISPATCHER
35          MODULE_NAME         ("dsfield")
36
37
38 /*
39  * Field flags: Bits 00 - 03 : Access_type (Any_acc, Byte_acc, etc.)
40  *                   04      : Lock_rule (1 == Lock)
41  *                   05 - 06 : Update_rule
42  */
43
44 #define FIELD_ACCESS_TYPE_MASK      0x0F
45 #define FIELD_LOCK_RULE_MASK        0x10
46 #define FIELD_UPDATE_RULE_MASK      0x60
47
48
49 /*******************************************************************************
50  *
51  * FUNCTION:    Acpi_ds_create_field
52  *
53  * PARAMETERS:  Op              - Op containing the Field definition and args
54  *              Region_node - Object for the containing Operation Region
55  *
56  * RETURN:      Status
57  *
58  * DESCRIPTION: Create a new field in the specified operation region
59  *
60  ******************************************************************************/
61
62 ACPI_STATUS
63 acpi_ds_create_field (
64         ACPI_PARSE_OBJECT       *op,
65         ACPI_NAMESPACE_NODE     *region_node,
66         ACPI_WALK_STATE         *walk_state)
67 {
68         ACPI_STATUS             status = AE_AML_ERROR;
69         ACPI_PARSE_OBJECT       *arg;
70         ACPI_NAMESPACE_NODE     *node;
71         u8                      field_flags;
72         u8                      access_attribute = 0;
73         u32                     field_bit_position = 0;
74
75
76         /* First arg is the name of the parent Op_region */
77
78         arg = op->value.arg;
79         if (!region_node) {
80                 status = acpi_ns_lookup (walk_state->scope_info, arg->value.name,
81                                  ACPI_TYPE_REGION, IMODE_EXECUTE,
82                                  NS_SEARCH_PARENT, walk_state,
83                                  &region_node);
84
85                 if (ACPI_FAILURE (status)) {
86                         return (status);
87                 }
88         }
89
90         /* Second arg is the field flags */
91
92         arg = arg->next;
93         field_flags = (u8) arg->value.integer;
94
95         /* Each remaining arg is a Named Field */
96
97         arg = arg->next;
98         while (arg) {
99                 switch (arg->opcode) {
100                 case AML_RESERVEDFIELD_OP:
101
102                         field_bit_position += arg->value.size;
103                         break;
104
105
106                 case AML_ACCESSFIELD_OP:
107
108                         /*
109                          * Get a new Access_type and Access_attribute for all
110                          * entries (until end or another Access_as keyword)
111                          */
112
113                         access_attribute = (u8) arg->value.integer;
114                         field_flags     = (u8)
115                                           ((field_flags & FIELD_ACCESS_TYPE_MASK) ||
116                                           ((u8) (arg->value.integer >> 8)));
117                         break;
118
119
120                 case AML_NAMEDFIELD_OP:
121
122                         status = acpi_ns_lookup (walk_state->scope_info,
123                                           (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name,
124                                           INTERNAL_TYPE_DEF_FIELD,
125                                           IMODE_LOAD_PASS1,
126                                           NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
127                                           NULL, &node);
128
129                         if (ACPI_FAILURE (status)) {
130                                 return (status);
131                         }
132
133                         /*
134                          * Initialize an object for the new Node that is on
135                          * the object stack
136                          */
137
138                         status = acpi_aml_prep_def_field_value (node, region_node, field_flags,
139                                           access_attribute, field_bit_position, arg->value.size);
140
141                         if (ACPI_FAILURE (status)) {
142                                 return (status);
143                         }
144
145                         /* Keep track of bit position for *next* field */
146
147                         field_bit_position += arg->value.size;
148                         break;
149                 }
150
151                 arg = arg->next;
152         }
153
154         return (status);
155 }
156
157
158 /*******************************************************************************
159  *
160  * FUNCTION:    Acpi_ds_create_bank_field
161  *
162  * PARAMETERS:  Op              - Op containing the Field definition and args
163  *              Region_node - Object for the containing Operation Region
164  *
165  * RETURN:      Status
166  *
167  * DESCRIPTION: Create a new bank field in the specified operation region
168  *
169  ******************************************************************************/
170
171 ACPI_STATUS
172 acpi_ds_create_bank_field (
173         ACPI_PARSE_OBJECT       *op,
174         ACPI_NAMESPACE_NODE     *region_node,
175         ACPI_WALK_STATE         *walk_state)
176 {
177         ACPI_STATUS             status = AE_AML_ERROR;
178         ACPI_PARSE_OBJECT       *arg;
179         ACPI_NAMESPACE_NODE     *register_node;
180         ACPI_NAMESPACE_NODE     *node;
181         u32                     bank_value;
182         u8                      field_flags;
183         u8                      access_attribute = 0;
184         u32                     field_bit_position = 0;
185
186
187         /* First arg is the name of the parent Op_region */
188
189         arg = op->value.arg;
190         if (!region_node) {
191                 status = acpi_ns_lookup (walk_state->scope_info, arg->value.name,
192                                  ACPI_TYPE_REGION, IMODE_EXECUTE,
193                                  NS_SEARCH_PARENT, walk_state,
194                                  &region_node);
195
196                 if (ACPI_FAILURE (status)) {
197                         return (status);
198                 }
199         }
200
201         /* Second arg is the Bank Register */
202
203         arg = arg->next;
204
205         status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
206                          INTERNAL_TYPE_BANK_FIELD_DEFN,
207                          IMODE_LOAD_PASS1,
208                          NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
209                          NULL, &register_node);
210
211         if (ACPI_FAILURE (status)) {
212                 return (status);
213         }
214
215         /* Third arg is the Bank_value */
216
217         arg = arg->next;
218         bank_value = arg->value.integer;
219
220
221         /* Next arg is the field flags */
222
223         arg = arg->next;
224         field_flags = (u8) arg->value.integer;
225
226         /* Each remaining arg is a Named Field */
227
228         arg = arg->next;
229         while (arg) {
230                 switch (arg->opcode) {
231                 case AML_RESERVEDFIELD_OP:
232
233                         field_bit_position += arg->value.size;
234                         break;
235
236
237                 case AML_ACCESSFIELD_OP:
238
239                         /*
240                          * Get a new Access_type and Access_attribute for
241                          * all entries (until end or another Access_as keyword)
242                          */
243
244                         access_attribute = (u8) arg->value.integer;
245                         field_flags     = (u8)
246                                           ((field_flags & FIELD_ACCESS_TYPE_MASK) ||
247                                           ((u8) (arg->value.integer >> 8)));
248                         break;
249
250
251                 case AML_NAMEDFIELD_OP:
252
253                         status = acpi_ns_lookup (walk_state->scope_info,
254                                           (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name,
255                                           INTERNAL_TYPE_DEF_FIELD,
256                                           IMODE_LOAD_PASS1,
257                                           NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
258                                           NULL, &node);
259
260                         if (ACPI_FAILURE (status)) {
261                                 return (status);
262                         }
263
264                         /*
265                          * Initialize an object for the new Node that is on
266                          * the object stack
267                          */
268
269                         status = acpi_aml_prep_bank_field_value (node, region_node, register_node,
270                                           bank_value, field_flags, access_attribute,
271                                           field_bit_position, arg->value.size);
272
273                         if (ACPI_FAILURE (status)) {
274                                 return (status);
275                         }
276
277                         /* Keep track of bit position for the *next* field */
278
279                         field_bit_position += arg->value.size;
280                         break;
281
282                 }
283
284                 arg = arg->next;
285         }
286
287         return (status);
288 }
289
290
291 /*******************************************************************************
292  *
293  * FUNCTION:    Acpi_ds_create_index_field
294  *
295  * PARAMETERS:  Op              - Op containing the Field definition and args
296  *              Region_node - Object for the containing Operation Region
297  *
298  * RETURN:      Status
299  *
300  * DESCRIPTION: Create a new index field in the specified operation region
301  *
302  ******************************************************************************/
303
304 ACPI_STATUS
305 acpi_ds_create_index_field (
306         ACPI_PARSE_OBJECT       *op,
307         ACPI_HANDLE             region_node,
308         ACPI_WALK_STATE         *walk_state)
309 {
310         ACPI_STATUS             status;
311         ACPI_PARSE_OBJECT       *arg;
312         ACPI_NAMESPACE_NODE     *node;
313         ACPI_NAMESPACE_NODE     *index_register_node;
314         ACPI_NAMESPACE_NODE     *data_register_node;
315         u8                      field_flags;
316         u8                      access_attribute = 0;
317         u32                     field_bit_position = 0;
318
319
320         arg = op->value.arg;
321
322         /* First arg is the name of the Index register */
323
324         status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
325                          ACPI_TYPE_ANY, IMODE_LOAD_PASS1,
326                          NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
327                          NULL, &index_register_node);
328
329         if (ACPI_FAILURE (status)) {
330                 return (status);
331         }
332
333         /* Second arg is the data register */
334
335         arg = arg->next;
336
337         status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
338                          INTERNAL_TYPE_INDEX_FIELD_DEFN,
339                          IMODE_LOAD_PASS1,
340                          NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
341                          NULL, &data_register_node);
342
343         if (ACPI_FAILURE (status)) {
344                 return (status);
345         }
346
347
348         /* Next arg is the field flags */
349
350         arg = arg->next;
351         field_flags = (u8) arg->value.integer;
352
353
354         /* Each remaining arg is a Named Field */
355
356         arg = arg->next;
357         while (arg) {
358                 switch (arg->opcode) {
359                 case AML_RESERVEDFIELD_OP:
360
361                         field_bit_position += arg->value.size;
362                         break;
363
364
365                 case AML_ACCESSFIELD_OP:
366
367                         /*
368                          * Get a new Access_type and Access_attribute for all
369                          * entries (until end or another Access_as keyword)
370                          */
371
372                         access_attribute = (u8) arg->value.integer;
373                         field_flags     = (u8)
374                                            ((field_flags & FIELD_ACCESS_TYPE_MASK) ||
375                                            ((u8) (arg->value.integer >> 8)));
376                         break;
377
378
379                 case AML_NAMEDFIELD_OP:
380
381                         status = acpi_ns_lookup (walk_state->scope_info,
382                                          (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name,
383                                          INTERNAL_TYPE_INDEX_FIELD,
384                                          IMODE_LOAD_PASS1,
385                                          NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
386                                          NULL, &node);
387
388                         if (ACPI_FAILURE (status)) {
389                                 return (status);
390                         }
391
392                         /*
393                          * Initialize an object for the new Node that is on
394                          * the object stack
395                          */
396
397                         status = acpi_aml_prep_index_field_value (node, index_register_node, data_register_node,
398                                           field_flags, access_attribute,
399                                           field_bit_position, arg->value.size);
400
401                         if (ACPI_FAILURE (status)) {
402                                 return (status);
403                         }
404
405                         /* Keep track of bit position for the *next* field */
406
407                         field_bit_position += arg->value.size;
408                         break;
409
410
411                 default:
412
413                         status = AE_AML_ERROR;
414                         break;
415                 }
416
417                 arg = arg->next;
418         }
419
420         return (status);
421 }
422
423