0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acdispat.h"
0013 #include "acinterp.h"
0014 #include "amlcode.h"
0015
0016 #define _COMPONENT ACPI_EXECUTER
0017 ACPI_MODULE_NAME("exserial")
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 acpi_status acpi_ex_read_gpio(union acpi_operand_object *obj_desc, void *buffer)
0033 {
0034 acpi_status status;
0035
0036 ACPI_FUNCTION_TRACE_PTR(ex_read_gpio, obj_desc);
0037
0038
0039
0040
0041
0042
0043
0044 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
0045 "GPIO FieldRead [FROM]: Pin %u Bits %u\n",
0046 obj_desc->field.pin_number_index,
0047 obj_desc->field.bit_length));
0048
0049
0050
0051 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
0052
0053
0054
0055 status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_READ);
0056
0057 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
0058 return_ACPI_STATUS(status);
0059 }
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 acpi_status
0078 acpi_ex_write_gpio(union acpi_operand_object *source_desc,
0079 union acpi_operand_object *obj_desc,
0080 union acpi_operand_object **return_buffer)
0081 {
0082 acpi_status status;
0083 void *buffer;
0084
0085 ACPI_FUNCTION_TRACE_PTR(ex_write_gpio, obj_desc);
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 if (source_desc->common.type != ACPI_TYPE_INTEGER) {
0096 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0097 }
0098
0099 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
0100 "GPIO FieldWrite [FROM]: (%s:%X), Value %.8X [TO]: Pin %u Bits %u\n",
0101 acpi_ut_get_type_name(source_desc->common.type),
0102 source_desc->common.type,
0103 (u32)source_desc->integer.value,
0104 obj_desc->field.pin_number_index,
0105 obj_desc->field.bit_length));
0106
0107 buffer = &source_desc->integer.value;
0108
0109
0110
0111 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
0112
0113
0114
0115 status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_WRITE);
0116 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
0117 return_ACPI_STATUS(status);
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134 acpi_status
0135 acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc,
0136 union acpi_operand_object **return_buffer)
0137 {
0138 acpi_status status;
0139 u32 buffer_length;
0140 union acpi_operand_object *buffer_desc;
0141 u32 function;
0142 u16 accessor_type;
0143
0144 ACPI_FUNCTION_TRACE_PTR(ex_read_serial_bus, obj_desc);
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 switch (obj_desc->field.region_obj->region.space_id) {
0159 case ACPI_ADR_SPACE_SMBUS:
0160
0161 buffer_length = ACPI_SMBUS_BUFFER_SIZE;
0162 function = ACPI_READ | (obj_desc->field.attribute << 16);
0163 break;
0164
0165 case ACPI_ADR_SPACE_IPMI:
0166
0167 buffer_length = ACPI_IPMI_BUFFER_SIZE;
0168 function = ACPI_READ;
0169 break;
0170
0171 case ACPI_ADR_SPACE_GSBUS:
0172
0173 accessor_type = obj_desc->field.attribute;
0174 if (accessor_type == AML_FIELD_ATTRIB_RAW_PROCESS_BYTES) {
0175 ACPI_ERROR((AE_INFO,
0176 "Invalid direct read using bidirectional write-then-read protocol"));
0177
0178 return_ACPI_STATUS(AE_AML_PROTOCOL);
0179 }
0180
0181 status =
0182 acpi_ex_get_protocol_buffer_length(accessor_type,
0183 &buffer_length);
0184 if (ACPI_FAILURE(status)) {
0185 ACPI_ERROR((AE_INFO,
0186 "Invalid protocol ID for GSBus: 0x%4.4X",
0187 accessor_type));
0188
0189 return_ACPI_STATUS(status);
0190 }
0191
0192
0193
0194 buffer_length += ACPI_SERIAL_HEADER_SIZE;
0195 function = ACPI_READ | (accessor_type << 16);
0196 break;
0197
0198 case ACPI_ADR_SPACE_PLATFORM_RT:
0199
0200 buffer_length = ACPI_PRM_INPUT_BUFFER_SIZE;
0201 function = ACPI_READ;
0202 break;
0203
0204 default:
0205 return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
0206 }
0207
0208
0209
0210 buffer_desc = acpi_ut_create_buffer_object(buffer_length);
0211 if (!buffer_desc) {
0212 return_ACPI_STATUS(AE_NO_MEMORY);
0213 }
0214
0215
0216
0217 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
0218
0219
0220
0221 status = acpi_ex_access_region(obj_desc, 0,
0222 ACPI_CAST_PTR(u64,
0223 buffer_desc->buffer.
0224 pointer), function);
0225 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
0226
0227 *return_buffer = buffer_desc;
0228 return_ACPI_STATUS(status);
0229 }
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 acpi_status
0247 acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
0248 union acpi_operand_object *obj_desc,
0249 union acpi_operand_object **return_buffer)
0250 {
0251 acpi_status status;
0252 u32 buffer_length;
0253 u32 data_length;
0254 void *buffer;
0255 union acpi_operand_object *buffer_desc;
0256 u32 function;
0257 u16 accessor_type;
0258
0259 ACPI_FUNCTION_TRACE_PTR(ex_write_serial_bus, obj_desc);
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278 if (source_desc->common.type != ACPI_TYPE_BUFFER) {
0279 ACPI_ERROR((AE_INFO,
0280 "SMBus/IPMI/GenericSerialBus write requires "
0281 "Buffer, found type %s",
0282 acpi_ut_get_object_type_name(source_desc)));
0283
0284 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0285 }
0286
0287 switch (obj_desc->field.region_obj->region.space_id) {
0288 case ACPI_ADR_SPACE_SMBUS:
0289
0290 buffer_length = ACPI_SMBUS_BUFFER_SIZE;
0291 function = ACPI_WRITE | (obj_desc->field.attribute << 16);
0292 break;
0293
0294 case ACPI_ADR_SPACE_IPMI:
0295
0296 buffer_length = ACPI_IPMI_BUFFER_SIZE;
0297 function = ACPI_WRITE;
0298 break;
0299
0300 case ACPI_ADR_SPACE_GSBUS:
0301
0302 accessor_type = obj_desc->field.attribute;
0303 status =
0304 acpi_ex_get_protocol_buffer_length(accessor_type,
0305 &buffer_length);
0306 if (ACPI_FAILURE(status)) {
0307 ACPI_ERROR((AE_INFO,
0308 "Invalid protocol ID for GSBus: 0x%4.4X",
0309 accessor_type));
0310
0311 return_ACPI_STATUS(status);
0312 }
0313
0314
0315
0316 buffer_length += ACPI_SERIAL_HEADER_SIZE;
0317 function = ACPI_WRITE | (accessor_type << 16);
0318 break;
0319
0320 case ACPI_ADR_SPACE_PLATFORM_RT:
0321
0322 buffer_length = ACPI_PRM_INPUT_BUFFER_SIZE;
0323 function = ACPI_WRITE;
0324 break;
0325
0326 default:
0327 return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
0328 }
0329
0330
0331
0332 buffer_desc = acpi_ut_create_buffer_object(buffer_length);
0333 if (!buffer_desc) {
0334 return_ACPI_STATUS(AE_NO_MEMORY);
0335 }
0336
0337
0338
0339 buffer = buffer_desc->buffer.pointer;
0340 data_length = (buffer_length < source_desc->buffer.length ?
0341 buffer_length : source_desc->buffer.length);
0342 memcpy(buffer, source_desc->buffer.pointer, data_length);
0343
0344
0345
0346 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
0347
0348
0349
0350
0351
0352 status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function);
0353 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
0354
0355 *return_buffer = buffer_desc;
0356 return_ACPI_STATUS(status);
0357 }