Ported ACPI CA (from the nice guys at Intel) to ReactOS (ACPI bus driver).
[reactos.git] / reactos / drivers / bus / acpi / dispatcher / dsfield.c
1 /******************************************************************************
2 *
3 * Module Name: dsfield - Dispatcher field routines
4 * $Revision: 1.1 $
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