Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Apr 14-17, 2025
Register
Loading...
v5.9
  1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2/******************************************************************************
  3 *
  4 * Module Name: exserial - field_unit support for serial address spaces
  5 *
  6 * Copyright (C) 2000 - 2020, Intel Corp.
  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
 17ACPI_MODULE_NAME("exserial")
 18
 19/*******************************************************************************
 20 *
 21 * FUNCTION:    acpi_ex_read_gpio
 22 *
 23 * PARAMETERS:  obj_desc            - The named field to read
 24 *              buffer              - Where the return data is returned
 25 *
 26 * RETURN:      Status
 27 *
 28 * DESCRIPTION: Read from a named field that references a Generic Serial Bus
 29 *              field
 30 *
 31 ******************************************************************************/
 32acpi_status acpi_ex_read_gpio(union acpi_operand_object *obj_desc, void *buffer)
 33{
 34	acpi_status status;
 35
 36	ACPI_FUNCTION_TRACE_PTR(ex_read_gpio, obj_desc);
 37
 38	/*
 39	 * For GPIO (general_purpose_io), the Address will be the bit offset
 40	 * from the previous Connection() operator, making it effectively a
 41	 * pin number index. The bit_length is the length of the field, which
 42	 * is thus the number of pins.
 43	 */
 44	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 45			  "GPIO FieldRead [FROM]:  Pin %u Bits %u\n",
 46			  obj_desc->field.pin_number_index,
 47			  obj_desc->field.bit_length));
 48
 49	/* Lock entire transaction if requested */
 50
 51	acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
 52
 53	/* Perform the read */
 54
 55	status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_READ);
 56
 57	acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
 58	return_ACPI_STATUS(status);
 59}
 60
 61/*******************************************************************************
 62 *
 63 * FUNCTION:    acpi_ex_write_gpio
 64 *
 65 * PARAMETERS:  source_desc         - Contains data to write. Expect to be
 66 *                                    an Integer object.
 67 *              obj_desc            - The named field
 68 *              result_desc         - Where the return value is returned, if any
 69 *
 70 * RETURN:      Status
 71 *
 72 * DESCRIPTION: Write to a named field that references a General Purpose I/O
 73 *              field.
 74 *
 75 ******************************************************************************/
 76
 77acpi_status
 78acpi_ex_write_gpio(union acpi_operand_object *source_desc,
 79		   union acpi_operand_object *obj_desc,
 80		   union acpi_operand_object **return_buffer)
 81{
 82	acpi_status status;
 83	void *buffer;
 84
 85	ACPI_FUNCTION_TRACE_PTR(ex_write_gpio, obj_desc);
 86
 87	/*
 88	 * For GPIO (general_purpose_io), we will bypass the entire field
 89	 * mechanism and handoff the bit address and bit width directly to
 90	 * the handler. The Address will be the bit offset
 91	 * from the previous Connection() operator, making it effectively a
 92	 * pin number index. The bit_length is the length of the field, which
 93	 * is thus the number of pins.
 94	 */
 95	if (source_desc->common.type != ACPI_TYPE_INTEGER) {
 96		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 97	}
 98
 99	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
100			  "GPIO FieldWrite [FROM]: (%s:%X), Value %.8X  [TO]: Pin %u Bits %u\n",
101			  acpi_ut_get_type_name(source_desc->common.type),
102			  source_desc->common.type,
103			  (u32)source_desc->integer.value,
104			  obj_desc->field.pin_number_index,
105			  obj_desc->field.bit_length));
106
107	buffer = &source_desc->integer.value;
108
109	/* Lock entire transaction if requested */
110
111	acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
112
113	/* Perform the write */
114
115	status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_WRITE);
116	acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
117	return_ACPI_STATUS(status);
118}
119
120/*******************************************************************************
121 *
122 * FUNCTION:    acpi_ex_read_serial_bus
123 *
124 * PARAMETERS:  obj_desc            - The named field to read
125 *              return_buffer       - Where the return value is returned, if any
126 *
127 * RETURN:      Status
128 *
129 * DESCRIPTION: Read from a named field that references a serial bus
130 *              (SMBus, IPMI, or GSBus).
131 *
132 ******************************************************************************/
133
134acpi_status
135acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc,
136			union acpi_operand_object **return_buffer)
137{
138	acpi_status status;
139	u32 buffer_length;
140	union acpi_operand_object *buffer_desc;
141	u32 function;
142	u16 accessor_type;
143
144	ACPI_FUNCTION_TRACE_PTR(ex_read_serial_bus, obj_desc);
145
146	/*
147	 * This is an SMBus, GSBus or IPMI read. We must create a buffer to
148	 * hold the data and then directly access the region handler.
149	 *
150	 * Note: SMBus and GSBus protocol value is passed in upper 16-bits
151	 * of Function
152	 *
153	 * Common buffer format:
154	 *     Status;    (Byte 0 of the data buffer)
155	 *     Length;    (Byte 1 of the data buffer)
156	 *     Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
157	 */
158	switch (obj_desc->field.region_obj->region.space_id) {
159	case ACPI_ADR_SPACE_SMBUS:
160
161		buffer_length = ACPI_SMBUS_BUFFER_SIZE;
162		function = ACPI_READ | (obj_desc->field.attribute << 16);
163		break;
164
165	case ACPI_ADR_SPACE_IPMI:
166
167		buffer_length = ACPI_IPMI_BUFFER_SIZE;
168		function = ACPI_READ;
169		break;
170
171	case ACPI_ADR_SPACE_GSBUS:
172
173		accessor_type = obj_desc->field.attribute;
174		if (accessor_type == AML_FIELD_ATTRIB_RAW_PROCESS_BYTES) {
175			ACPI_ERROR((AE_INFO,
176				    "Invalid direct read using bidirectional write-then-read protocol"));
177
178			return_ACPI_STATUS(AE_AML_PROTOCOL);
179		}
180
181		status =
182		    acpi_ex_get_protocol_buffer_length(accessor_type,
183						       &buffer_length);
184		if (ACPI_FAILURE(status)) {
185			ACPI_ERROR((AE_INFO,
186				    "Invalid protocol ID for GSBus: 0x%4.4X",
187				    accessor_type));
188
189			return_ACPI_STATUS(status);
190		}
191
192		/* Add header length to get the full size of the buffer */
193
194		buffer_length += ACPI_SERIAL_HEADER_SIZE;
195		function = ACPI_READ | (accessor_type << 16);
196		break;
197
 
 
 
 
 
 
198	default:
199		return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
200	}
201
202	/* Create the local transfer buffer that is returned to the caller */
203
204	buffer_desc = acpi_ut_create_buffer_object(buffer_length);
205	if (!buffer_desc) {
206		return_ACPI_STATUS(AE_NO_MEMORY);
207	}
208
209	/* Lock entire transaction if requested */
210
211	acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
212
213	/* Call the region handler for the write-then-read */
214
215	status = acpi_ex_access_region(obj_desc, 0,
216				       ACPI_CAST_PTR(u64,
217						     buffer_desc->buffer.
218						     pointer), function);
219	acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
220
221	*return_buffer = buffer_desc;
222	return_ACPI_STATUS(status);
223}
224
225/*******************************************************************************
226 *
227 * FUNCTION:    acpi_ex_write_serial_bus
228 *
229 * PARAMETERS:  source_desc         - Contains data to write
230 *              obj_desc            - The named field
231 *              return_buffer       - Where the return value is returned, if any
232 *
233 * RETURN:      Status
234 *
235 * DESCRIPTION: Write to a named field that references a serial bus
236 *              (SMBus, IPMI, GSBus).
237 *
238 ******************************************************************************/
239
240acpi_status
241acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
242			 union acpi_operand_object *obj_desc,
243			 union acpi_operand_object **return_buffer)
244{
245	acpi_status status;
246	u32 buffer_length;
247	u32 data_length;
248	void *buffer;
249	union acpi_operand_object *buffer_desc;
250	u32 function;
251	u16 accessor_type;
252
253	ACPI_FUNCTION_TRACE_PTR(ex_write_serial_bus, obj_desc);
254
255	/*
256	 * This is an SMBus, GSBus or IPMI write. We will bypass the entire
257	 * field mechanism and handoff the buffer directly to the handler.
258	 * For these address spaces, the buffer is bidirectional; on a
259	 * write, return data is returned in the same buffer.
260	 *
261	 * Source must be a buffer of sufficient size, these are fixed size:
262	 * ACPI_SMBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.
263	 *
264	 * Note: SMBus and GSBus protocol type is passed in upper 16-bits
265	 * of Function
266	 *
267	 * Common buffer format:
268	 *     Status;    (Byte 0 of the data buffer)
269	 *     Length;    (Byte 1 of the data buffer)
270	 *     Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
271	 */
272	if (source_desc->common.type != ACPI_TYPE_BUFFER) {
273		ACPI_ERROR((AE_INFO,
274			    "SMBus/IPMI/GenericSerialBus write requires "
275			    "Buffer, found type %s",
276			    acpi_ut_get_object_type_name(source_desc)));
277
278		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
279	}
280
281	switch (obj_desc->field.region_obj->region.space_id) {
282	case ACPI_ADR_SPACE_SMBUS:
283
284		buffer_length = ACPI_SMBUS_BUFFER_SIZE;
285		function = ACPI_WRITE | (obj_desc->field.attribute << 16);
286		break;
287
288	case ACPI_ADR_SPACE_IPMI:
289
290		buffer_length = ACPI_IPMI_BUFFER_SIZE;
291		function = ACPI_WRITE;
292		break;
293
294	case ACPI_ADR_SPACE_GSBUS:
295
296		accessor_type = obj_desc->field.attribute;
297		status =
298		    acpi_ex_get_protocol_buffer_length(accessor_type,
299						       &buffer_length);
300		if (ACPI_FAILURE(status)) {
301			ACPI_ERROR((AE_INFO,
302				    "Invalid protocol ID for GSBus: 0x%4.4X",
303				    accessor_type));
304
305			return_ACPI_STATUS(status);
306		}
307
308		/* Add header length to get the full size of the buffer */
309
310		buffer_length += ACPI_SERIAL_HEADER_SIZE;
311		function = ACPI_WRITE | (accessor_type << 16);
 
 
 
 
 
 
312		break;
313
314	default:
315		return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
316	}
317
318	/* Create the transfer/bidirectional/return buffer */
319
320	buffer_desc = acpi_ut_create_buffer_object(buffer_length);
321	if (!buffer_desc) {
322		return_ACPI_STATUS(AE_NO_MEMORY);
323	}
324
325	/* Copy the input buffer data to the transfer buffer */
326
327	buffer = buffer_desc->buffer.pointer;
328	data_length = (buffer_length < source_desc->buffer.length ?
329		       buffer_length : source_desc->buffer.length);
330	memcpy(buffer, source_desc->buffer.pointer, data_length);
331
332	/* Lock entire transaction if requested */
333
334	acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
335
336	/*
337	 * Perform the write (returns status and perhaps data in the
338	 * same buffer)
339	 */
340	status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function);
341	acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
342
343	*return_buffer = buffer_desc;
344	return_ACPI_STATUS(status);
345}
v5.14.15
  1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2/******************************************************************************
  3 *
  4 * Module Name: exserial - field_unit support for serial address spaces
  5 *
  6 * Copyright (C) 2000 - 2021, Intel Corp.
  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
 17ACPI_MODULE_NAME("exserial")
 18
 19/*******************************************************************************
 20 *
 21 * FUNCTION:    acpi_ex_read_gpio
 22 *
 23 * PARAMETERS:  obj_desc            - The named field to read
 24 *              buffer              - Where the return data is returned
 25 *
 26 * RETURN:      Status
 27 *
 28 * DESCRIPTION: Read from a named field that references a Generic Serial Bus
 29 *              field
 30 *
 31 ******************************************************************************/
 32acpi_status acpi_ex_read_gpio(union acpi_operand_object *obj_desc, void *buffer)
 33{
 34	acpi_status status;
 35
 36	ACPI_FUNCTION_TRACE_PTR(ex_read_gpio, obj_desc);
 37
 38	/*
 39	 * For GPIO (general_purpose_io), the Address will be the bit offset
 40	 * from the previous Connection() operator, making it effectively a
 41	 * pin number index. The bit_length is the length of the field, which
 42	 * is thus the number of pins.
 43	 */
 44	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 45			  "GPIO FieldRead [FROM]:  Pin %u Bits %u\n",
 46			  obj_desc->field.pin_number_index,
 47			  obj_desc->field.bit_length));
 48
 49	/* Lock entire transaction if requested */
 50
 51	acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
 52
 53	/* Perform the read */
 54
 55	status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_READ);
 56
 57	acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
 58	return_ACPI_STATUS(status);
 59}
 60
 61/*******************************************************************************
 62 *
 63 * FUNCTION:    acpi_ex_write_gpio
 64 *
 65 * PARAMETERS:  source_desc         - Contains data to write. Expect to be
 66 *                                    an Integer object.
 67 *              obj_desc            - The named field
 68 *              result_desc         - Where the return value is returned, if any
 69 *
 70 * RETURN:      Status
 71 *
 72 * DESCRIPTION: Write to a named field that references a General Purpose I/O
 73 *              field.
 74 *
 75 ******************************************************************************/
 76
 77acpi_status
 78acpi_ex_write_gpio(union acpi_operand_object *source_desc,
 79		   union acpi_operand_object *obj_desc,
 80		   union acpi_operand_object **return_buffer)
 81{
 82	acpi_status status;
 83	void *buffer;
 84
 85	ACPI_FUNCTION_TRACE_PTR(ex_write_gpio, obj_desc);
 86
 87	/*
 88	 * For GPIO (general_purpose_io), we will bypass the entire field
 89	 * mechanism and handoff the bit address and bit width directly to
 90	 * the handler. The Address will be the bit offset
 91	 * from the previous Connection() operator, making it effectively a
 92	 * pin number index. The bit_length is the length of the field, which
 93	 * is thus the number of pins.
 94	 */
 95	if (source_desc->common.type != ACPI_TYPE_INTEGER) {
 96		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 97	}
 98
 99	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
100			  "GPIO FieldWrite [FROM]: (%s:%X), Value %.8X  [TO]: Pin %u Bits %u\n",
101			  acpi_ut_get_type_name(source_desc->common.type),
102			  source_desc->common.type,
103			  (u32)source_desc->integer.value,
104			  obj_desc->field.pin_number_index,
105			  obj_desc->field.bit_length));
106
107	buffer = &source_desc->integer.value;
108
109	/* Lock entire transaction if requested */
110
111	acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
112
113	/* Perform the write */
114
115	status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_WRITE);
116	acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
117	return_ACPI_STATUS(status);
118}
119
120/*******************************************************************************
121 *
122 * FUNCTION:    acpi_ex_read_serial_bus
123 *
124 * PARAMETERS:  obj_desc            - The named field to read
125 *              return_buffer       - Where the return value is returned, if any
126 *
127 * RETURN:      Status
128 *
129 * DESCRIPTION: Read from a named field that references a serial bus
130 *              (SMBus, IPMI, or GSBus).
131 *
132 ******************************************************************************/
133
134acpi_status
135acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc,
136			union acpi_operand_object **return_buffer)
137{
138	acpi_status status;
139	u32 buffer_length;
140	union acpi_operand_object *buffer_desc;
141	u32 function;
142	u16 accessor_type;
143
144	ACPI_FUNCTION_TRACE_PTR(ex_read_serial_bus, obj_desc);
145
146	/*
147	 * This is an SMBus, GSBus or IPMI read. We must create a buffer to
148	 * hold the data and then directly access the region handler.
149	 *
150	 * Note: SMBus and GSBus protocol value is passed in upper 16-bits
151	 * of Function
152	 *
153	 * Common buffer format:
154	 *     Status;    (Byte 0 of the data buffer)
155	 *     Length;    (Byte 1 of the data buffer)
156	 *     Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
157	 */
158	switch (obj_desc->field.region_obj->region.space_id) {
159	case ACPI_ADR_SPACE_SMBUS:
160
161		buffer_length = ACPI_SMBUS_BUFFER_SIZE;
162		function = ACPI_READ | (obj_desc->field.attribute << 16);
163		break;
164
165	case ACPI_ADR_SPACE_IPMI:
166
167		buffer_length = ACPI_IPMI_BUFFER_SIZE;
168		function = ACPI_READ;
169		break;
170
171	case ACPI_ADR_SPACE_GSBUS:
172
173		accessor_type = obj_desc->field.attribute;
174		if (accessor_type == AML_FIELD_ATTRIB_RAW_PROCESS_BYTES) {
175			ACPI_ERROR((AE_INFO,
176				    "Invalid direct read using bidirectional write-then-read protocol"));
177
178			return_ACPI_STATUS(AE_AML_PROTOCOL);
179		}
180
181		status =
182		    acpi_ex_get_protocol_buffer_length(accessor_type,
183						       &buffer_length);
184		if (ACPI_FAILURE(status)) {
185			ACPI_ERROR((AE_INFO,
186				    "Invalid protocol ID for GSBus: 0x%4.4X",
187				    accessor_type));
188
189			return_ACPI_STATUS(status);
190		}
191
192		/* Add header length to get the full size of the buffer */
193
194		buffer_length += ACPI_SERIAL_HEADER_SIZE;
195		function = ACPI_READ | (accessor_type << 16);
196		break;
197
198	case ACPI_ADR_SPACE_PLATFORM_RT:
199
200		buffer_length = ACPI_PRM_INPUT_BUFFER_SIZE;
201		function = ACPI_READ;
202		break;
203
204	default:
205		return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
206	}
207
208	/* Create the local transfer buffer that is returned to the caller */
209
210	buffer_desc = acpi_ut_create_buffer_object(buffer_length);
211	if (!buffer_desc) {
212		return_ACPI_STATUS(AE_NO_MEMORY);
213	}
214
215	/* Lock entire transaction if requested */
216
217	acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
218
219	/* Call the region handler for the write-then-read */
220
221	status = acpi_ex_access_region(obj_desc, 0,
222				       ACPI_CAST_PTR(u64,
223						     buffer_desc->buffer.
224						     pointer), function);
225	acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
226
227	*return_buffer = buffer_desc;
228	return_ACPI_STATUS(status);
229}
230
231/*******************************************************************************
232 *
233 * FUNCTION:    acpi_ex_write_serial_bus
234 *
235 * PARAMETERS:  source_desc         - Contains data to write
236 *              obj_desc            - The named field
237 *              return_buffer       - Where the return value is returned, if any
238 *
239 * RETURN:      Status
240 *
241 * DESCRIPTION: Write to a named field that references a serial bus
242 *              (SMBus, IPMI, GSBus).
243 *
244 ******************************************************************************/
245
246acpi_status
247acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
248			 union acpi_operand_object *obj_desc,
249			 union acpi_operand_object **return_buffer)
250{
251	acpi_status status;
252	u32 buffer_length;
253	u32 data_length;
254	void *buffer;
255	union acpi_operand_object *buffer_desc;
256	u32 function;
257	u16 accessor_type;
258
259	ACPI_FUNCTION_TRACE_PTR(ex_write_serial_bus, obj_desc);
260
261	/*
262	 * This is an SMBus, GSBus or IPMI write. We will bypass the entire
263	 * field mechanism and handoff the buffer directly to the handler.
264	 * For these address spaces, the buffer is bidirectional; on a
265	 * write, return data is returned in the same buffer.
266	 *
267	 * Source must be a buffer of sufficient size, these are fixed size:
268	 * ACPI_SMBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.
269	 *
270	 * Note: SMBus and GSBus protocol type is passed in upper 16-bits
271	 * of Function
272	 *
273	 * Common buffer format:
274	 *     Status;    (Byte 0 of the data buffer)
275	 *     Length;    (Byte 1 of the data buffer)
276	 *     Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
277	 */
278	if (source_desc->common.type != ACPI_TYPE_BUFFER) {
279		ACPI_ERROR((AE_INFO,
280			    "SMBus/IPMI/GenericSerialBus write requires "
281			    "Buffer, found type %s",
282			    acpi_ut_get_object_type_name(source_desc)));
283
284		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
285	}
286
287	switch (obj_desc->field.region_obj->region.space_id) {
288	case ACPI_ADR_SPACE_SMBUS:
289
290		buffer_length = ACPI_SMBUS_BUFFER_SIZE;
291		function = ACPI_WRITE | (obj_desc->field.attribute << 16);
292		break;
293
294	case ACPI_ADR_SPACE_IPMI:
295
296		buffer_length = ACPI_IPMI_BUFFER_SIZE;
297		function = ACPI_WRITE;
298		break;
299
300	case ACPI_ADR_SPACE_GSBUS:
301
302		accessor_type = obj_desc->field.attribute;
303		status =
304		    acpi_ex_get_protocol_buffer_length(accessor_type,
305						       &buffer_length);
306		if (ACPI_FAILURE(status)) {
307			ACPI_ERROR((AE_INFO,
308				    "Invalid protocol ID for GSBus: 0x%4.4X",
309				    accessor_type));
310
311			return_ACPI_STATUS(status);
312		}
313
314		/* Add header length to get the full size of the buffer */
315
316		buffer_length += ACPI_SERIAL_HEADER_SIZE;
317		function = ACPI_WRITE | (accessor_type << 16);
318		break;
319
320	case ACPI_ADR_SPACE_PLATFORM_RT:
321
322		buffer_length = ACPI_PRM_INPUT_BUFFER_SIZE;
323		function = ACPI_WRITE;
324		break;
325
326	default:
327		return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
328	}
329
330	/* Create the transfer/bidirectional/return buffer */
331
332	buffer_desc = acpi_ut_create_buffer_object(buffer_length);
333	if (!buffer_desc) {
334		return_ACPI_STATUS(AE_NO_MEMORY);
335	}
336
337	/* Copy the input buffer data to the transfer buffer */
338
339	buffer = buffer_desc->buffer.pointer;
340	data_length = (buffer_length < source_desc->buffer.length ?
341		       buffer_length : source_desc->buffer.length);
342	memcpy(buffer, source_desc->buffer.pointer, data_length);
343
344	/* Lock entire transaction if requested */
345
346	acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
347
348	/*
349	 * Perform the write (returns status and perhaps data in the
350	 * same buffer)
351	 */
352	status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function);
353	acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
354
355	*return_buffer = buffer_desc;
356	return_ACPI_STATUS(status);
357}