This source file includes following definitions.
- acpi_ex_get_protocol_buffer_length
- acpi_ex_read_data_from_field
- acpi_ex_write_data_to_field
1
2
3
4
5
6
7
8
9
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acdispat.h"
13 #include "acinterp.h"
14 #include "amlcode.h"
15
16 #define _COMPONENT ACPI_EXECUTER
17 ACPI_MODULE_NAME("exfield")
18
19
20
21
22
23 #define ACPI_INVALID_PROTOCOL_ID 0x80
24 #define ACPI_MAX_PROTOCOL_ID 0x0F
25 const u8 acpi_protocol_lengths[] = {
26 ACPI_INVALID_PROTOCOL_ID,
27 ACPI_INVALID_PROTOCOL_ID,
28 0x00,
29 ACPI_INVALID_PROTOCOL_ID,
30 0x01,
31 ACPI_INVALID_PROTOCOL_ID,
32 0x01,
33 ACPI_INVALID_PROTOCOL_ID,
34 0x02,
35 ACPI_INVALID_PROTOCOL_ID,
36 0xFF,
37 0xFF,
38 0x02,
39 0xFF,
40 0xFF,
41 0xFF
42 };
43
44 #define PCC_MASTER_SUBSPACE 3
45
46
47
48
49
50
51
52 #define GENERIC_SUBSPACE_COMMAND(a) (4 == a || a == 5)
53 #define MASTER_SUBSPACE_COMMAND(a) (12 <= a && a <= 15)
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 acpi_status
72 acpi_ex_get_protocol_buffer_length(u32 protocol_id, u32 *return_length)
73 {
74
75 if ((protocol_id > ACPI_MAX_PROTOCOL_ID) ||
76 (acpi_protocol_lengths[protocol_id] == ACPI_INVALID_PROTOCOL_ID)) {
77 ACPI_ERROR((AE_INFO,
78 "Invalid Field/AccessAs protocol ID: 0x%4.4X",
79 protocol_id));
80
81 return (AE_AML_PROTOCOL);
82 }
83
84 *return_length = acpi_protocol_lengths[protocol_id];
85 return (AE_OK);
86 }
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 acpi_status
104 acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
105 union acpi_operand_object *obj_desc,
106 union acpi_operand_object **ret_buffer_desc)
107 {
108 acpi_status status;
109 union acpi_operand_object *buffer_desc;
110 void *buffer;
111 u32 buffer_length;
112
113 ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
114
115
116
117 if (!obj_desc) {
118 return_ACPI_STATUS(AE_AML_NO_OPERAND);
119 }
120 if (!ret_buffer_desc) {
121 return_ACPI_STATUS(AE_BAD_PARAMETER);
122 }
123
124 if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) {
125
126
127
128
129 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
130 status = acpi_ds_get_buffer_field_arguments(obj_desc);
131 if (ACPI_FAILURE(status)) {
132 return_ACPI_STATUS(status);
133 }
134 }
135 } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
136 (obj_desc->field.region_obj->region.space_id ==
137 ACPI_ADR_SPACE_SMBUS
138 || obj_desc->field.region_obj->region.space_id ==
139 ACPI_ADR_SPACE_GSBUS
140 || obj_desc->field.region_obj->region.space_id ==
141 ACPI_ADR_SPACE_IPMI)) {
142
143
144
145 status = acpi_ex_read_serial_bus(obj_desc, ret_buffer_desc);
146 return_ACPI_STATUS(status);
147 }
148
149
150
151
152
153
154
155
156
157
158
159 buffer_length =
160 (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
161
162 if (buffer_length > acpi_gbl_integer_byte_width) {
163
164
165
166 buffer_desc = acpi_ut_create_buffer_object(buffer_length);
167 if (!buffer_desc) {
168 return_ACPI_STATUS(AE_NO_MEMORY);
169 }
170 buffer = buffer_desc->buffer.pointer;
171 } else {
172
173
174 buffer_desc = acpi_ut_create_integer_object((u64) 0);
175 if (!buffer_desc) {
176 return_ACPI_STATUS(AE_NO_MEMORY);
177 }
178
179 buffer_length = acpi_gbl_integer_byte_width;
180 buffer = &buffer_desc->integer.value;
181 }
182
183 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
184 (obj_desc->field.region_obj->region.space_id ==
185 ACPI_ADR_SPACE_GPIO)) {
186
187
188
189 status = acpi_ex_read_gpio(obj_desc, buffer);
190 goto exit;
191 } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
192 (obj_desc->field.region_obj->region.space_id ==
193 ACPI_ADR_SPACE_PLATFORM_COMM)) {
194
195
196
197
198 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
199 "PCC FieldRead bits %u\n",
200 obj_desc->field.bit_length));
201
202 memcpy(buffer,
203 obj_desc->field.region_obj->field.internal_pcc_buffer +
204 obj_desc->field.base_byte_offset,
205 (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.
206 bit_length));
207
208 *ret_buffer_desc = buffer_desc;
209 return AE_OK;
210 }
211
212 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
213 "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
214 obj_desc, obj_desc->common.type, buffer,
215 buffer_length));
216 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
217 "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
218 obj_desc->common_field.bit_length,
219 obj_desc->common_field.start_field_bit_offset,
220 obj_desc->common_field.base_byte_offset));
221
222
223
224 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
225
226
227
228 status = acpi_ex_extract_from_field(obj_desc, buffer, buffer_length);
229 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
230
231 exit:
232 if (ACPI_FAILURE(status)) {
233 acpi_ut_remove_reference(buffer_desc);
234 } else {
235 *ret_buffer_desc = buffer_desc;
236 }
237
238 return_ACPI_STATUS(status);
239 }
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 acpi_status
256 acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
257 union acpi_operand_object *obj_desc,
258 union acpi_operand_object **result_desc)
259 {
260 acpi_status status;
261 u32 buffer_length;
262 u32 data_length;
263 void *buffer;
264
265 ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
266
267
268
269 if (!source_desc || !obj_desc) {
270 return_ACPI_STATUS(AE_AML_NO_OPERAND);
271 }
272
273 if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) {
274
275
276
277
278 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
279 status = acpi_ds_get_buffer_field_arguments(obj_desc);
280 if (ACPI_FAILURE(status)) {
281 return_ACPI_STATUS(status);
282 }
283 }
284 } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
285 (obj_desc->field.region_obj->region.space_id ==
286 ACPI_ADR_SPACE_GPIO)) {
287
288
289
290 status = acpi_ex_write_gpio(source_desc, obj_desc, result_desc);
291 return_ACPI_STATUS(status);
292 } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
293 (obj_desc->field.region_obj->region.space_id ==
294 ACPI_ADR_SPACE_SMBUS
295 || obj_desc->field.region_obj->region.space_id ==
296 ACPI_ADR_SPACE_GSBUS
297 || obj_desc->field.region_obj->region.space_id ==
298 ACPI_ADR_SPACE_IPMI)) {
299
300
301
302 status =
303 acpi_ex_write_serial_bus(source_desc, obj_desc,
304 result_desc);
305 return_ACPI_STATUS(status);
306 } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
307 (obj_desc->field.region_obj->region.space_id ==
308 ACPI_ADR_SPACE_PLATFORM_COMM)) {
309
310
311
312
313
314
315
316 data_length =
317 (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.
318 bit_length);
319 memcpy(obj_desc->field.region_obj->field.internal_pcc_buffer +
320 obj_desc->field.base_byte_offset,
321 source_desc->buffer.pointer, data_length);
322
323 if ((obj_desc->field.region_obj->region.address ==
324 PCC_MASTER_SUBSPACE
325 && MASTER_SUBSPACE_COMMAND(obj_desc->field.
326 base_byte_offset))
327 || GENERIC_SUBSPACE_COMMAND(obj_desc->field.
328 base_byte_offset)) {
329
330
331
332 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
333 "PCC COMD field has been written. Invoking PCC handler now.\n"));
334
335 status =
336 acpi_ex_access_region(obj_desc, 0,
337 (u64 *)obj_desc->field.
338 region_obj->field.
339 internal_pcc_buffer,
340 ACPI_WRITE);
341 return_ACPI_STATUS(status);
342 }
343 return (AE_OK);
344 }
345
346
347
348 switch (source_desc->common.type) {
349 case ACPI_TYPE_INTEGER:
350
351 buffer = &source_desc->integer.value;
352 buffer_length = sizeof(source_desc->integer.value);
353 break;
354
355 case ACPI_TYPE_BUFFER:
356
357 buffer = source_desc->buffer.pointer;
358 buffer_length = source_desc->buffer.length;
359 break;
360
361 case ACPI_TYPE_STRING:
362
363 buffer = source_desc->string.pointer;
364 buffer_length = source_desc->string.length;
365 break;
366
367 default:
368 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
369 }
370
371 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
372 "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
373 source_desc,
374 acpi_ut_get_type_name(source_desc->common.type),
375 source_desc->common.type, buffer, buffer_length));
376
377 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
378 "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
379 obj_desc,
380 acpi_ut_get_type_name(obj_desc->common.type),
381 obj_desc->common.type,
382 obj_desc->common_field.bit_length,
383 obj_desc->common_field.start_field_bit_offset,
384 obj_desc->common_field.base_byte_offset));
385
386
387
388 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
389
390
391
392 status = acpi_ex_insert_into_field(obj_desc, buffer, buffer_length);
393 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
394 return_ACPI_STATUS(status);
395 }