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