[ACPI] Update ACPICA library to version 20190215.
[reactos.git] / drivers / bus / acpi / acpica / executer / exserial.c
1 /******************************************************************************
2 *
3 * Module Name: exserial - FieldUnit support for serial address spaces
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2019, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acdispat.h"
47 #include "acinterp.h"
48 #include "amlcode.h"
49
50
51 #define _COMPONENT ACPI_EXECUTER
52 ACPI_MODULE_NAME ("exserial")
53
54
55 /*******************************************************************************
56 *
57 * FUNCTION: AcpiExReadGpio
58 *
59 * PARAMETERS: ObjDesc - The named field to read
60 * Buffer - Where the return data is returned
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Read from a named field that references a Generic Serial Bus
65 * field
66 *
67 ******************************************************************************/
68
69 ACPI_STATUS
70 AcpiExReadGpio (
71 ACPI_OPERAND_OBJECT *ObjDesc,
72 void *Buffer)
73 {
74 ACPI_STATUS Status;
75
76
77 ACPI_FUNCTION_TRACE_PTR (ExReadGpio, ObjDesc);
78
79
80 /*
81 * For GPIO (GeneralPurposeIo), the Address will be the bit offset
82 * from the previous Connection() operator, making it effectively a
83 * pin number index. The BitLength is the length of the field, which
84 * is thus the number of pins.
85 */
86 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
87 "GPIO FieldRead [FROM]: Pin %u Bits %u\n",
88 ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength));
89
90 /* Lock entire transaction if requested */
91
92 AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
93
94 /* Perform the read */
95
96 Status = AcpiExAccessRegion (
97 ObjDesc, 0, (UINT64 *) Buffer, ACPI_READ);
98
99 AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
100 return_ACPI_STATUS (Status);
101 }
102
103
104 /*******************************************************************************
105 *
106 * FUNCTION: AcpiExWriteGpio
107 *
108 * PARAMETERS: SourceDesc - Contains data to write. Expect to be
109 * an Integer object.
110 * ObjDesc - The named field
111 * ResultDesc - Where the return value is returned, if any
112 *
113 * RETURN: Status
114 *
115 * DESCRIPTION: Write to a named field that references a General Purpose I/O
116 * field.
117 *
118 ******************************************************************************/
119
120 ACPI_STATUS
121 AcpiExWriteGpio (
122 ACPI_OPERAND_OBJECT *SourceDesc,
123 ACPI_OPERAND_OBJECT *ObjDesc,
124 ACPI_OPERAND_OBJECT **ReturnBuffer)
125 {
126 ACPI_STATUS Status;
127 void *Buffer;
128
129
130 ACPI_FUNCTION_TRACE_PTR (ExWriteGpio, ObjDesc);
131
132
133 /*
134 * For GPIO (GeneralPurposeIo), we will bypass the entire field
135 * mechanism and handoff the bit address and bit width directly to
136 * the handler. The Address will be the bit offset
137 * from the previous Connection() operator, making it effectively a
138 * pin number index. The BitLength is the length of the field, which
139 * is thus the number of pins.
140 */
141 if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER)
142 {
143 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
144 }
145
146 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
147 "GPIO FieldWrite [FROM]: (%s:%X), Value %.8X [TO]: Pin %u Bits %u\n",
148 AcpiUtGetTypeName (SourceDesc->Common.Type),
149 SourceDesc->Common.Type, (UINT32) SourceDesc->Integer.Value,
150 ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength));
151
152 Buffer = &SourceDesc->Integer.Value;
153
154 /* Lock entire transaction if requested */
155
156 AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
157
158 /* Perform the write */
159
160 Status = AcpiExAccessRegion (
161 ObjDesc, 0, (UINT64 *) Buffer, ACPI_WRITE);
162 AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
163 return_ACPI_STATUS (Status);
164 }
165
166
167 /*******************************************************************************
168 *
169 * FUNCTION: AcpiExReadSerialBus
170 *
171 * PARAMETERS: ObjDesc - The named field to read
172 * ReturnBuffer - Where the return value is returned, if any
173 *
174 * RETURN: Status
175 *
176 * DESCRIPTION: Read from a named field that references a serial bus
177 * (SMBus, IPMI, or GSBus).
178 *
179 ******************************************************************************/
180
181 ACPI_STATUS
182 AcpiExReadSerialBus (
183 ACPI_OPERAND_OBJECT *ObjDesc,
184 ACPI_OPERAND_OBJECT **ReturnBuffer)
185 {
186 ACPI_STATUS Status;
187 UINT32 BufferLength;
188 ACPI_OPERAND_OBJECT *BufferDesc;
189 UINT32 Function;
190 UINT16 AccessorType;
191
192
193 ACPI_FUNCTION_TRACE_PTR (ExReadSerialBus, ObjDesc);
194
195
196 /*
197 * This is an SMBus, GSBus or IPMI read. We must create a buffer to
198 * hold the data and then directly access the region handler.
199 *
200 * Note: SMBus and GSBus protocol value is passed in upper 16-bits
201 * of Function
202 *
203 * Common buffer format:
204 * Status; (Byte 0 of the data buffer)
205 * Length; (Byte 1 of the data buffer)
206 * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
207 */
208 switch (ObjDesc->Field.RegionObj->Region.SpaceId)
209 {
210 case ACPI_ADR_SPACE_SMBUS:
211
212 BufferLength = ACPI_SMBUS_BUFFER_SIZE;
213 Function = ACPI_READ | (ObjDesc->Field.Attribute << 16);
214 break;
215
216 case ACPI_ADR_SPACE_IPMI:
217
218 BufferLength = ACPI_IPMI_BUFFER_SIZE;
219 Function = ACPI_READ;
220 break;
221
222 case ACPI_ADR_SPACE_GSBUS:
223
224 AccessorType = ObjDesc->Field.Attribute;
225 if (AccessorType == AML_FIELD_ATTRIB_RAW_PROCESS_BYTES)
226 {
227 ACPI_ERROR ((AE_INFO,
228 "Invalid direct read using bidirectional write-then-read protocol"));
229
230 return_ACPI_STATUS (AE_AML_PROTOCOL);
231 }
232
233 Status = AcpiExGetProtocolBufferLength (AccessorType, &BufferLength);
234 if (ACPI_FAILURE (Status))
235 {
236 ACPI_ERROR ((AE_INFO,
237 "Invalid protocol ID for GSBus: 0x%4.4X", AccessorType));
238
239 return_ACPI_STATUS (Status);
240 }
241
242 /* Add header length to get the full size of the buffer */
243
244 BufferLength += ACPI_SERIAL_HEADER_SIZE;
245 Function = ACPI_READ | (AccessorType << 16);
246 break;
247
248 default:
249 return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID);
250 }
251
252 /* Create the local transfer buffer that is returned to the caller */
253
254 BufferDesc = AcpiUtCreateBufferObject (BufferLength);
255 if (!BufferDesc)
256 {
257 return_ACPI_STATUS (AE_NO_MEMORY);
258 }
259
260 /* Lock entire transaction if requested */
261
262 AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
263
264 /* Call the region handler for the write-then-read */
265
266 Status = AcpiExAccessRegion (ObjDesc, 0,
267 ACPI_CAST_PTR (UINT64, BufferDesc->Buffer.Pointer), Function);
268 AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
269
270 *ReturnBuffer = BufferDesc;
271 return_ACPI_STATUS (Status);
272 }
273
274
275 /*******************************************************************************
276 *
277 * FUNCTION: AcpiExWriteSerialBus
278 *
279 * PARAMETERS: SourceDesc - Contains data to write
280 * ObjDesc - The named field
281 * ReturnBuffer - Where the return value is returned, if any
282 *
283 * RETURN: Status
284 *
285 * DESCRIPTION: Write to a named field that references a serial bus
286 * (SMBus, IPMI, GSBus).
287 *
288 ******************************************************************************/
289
290 ACPI_STATUS
291 AcpiExWriteSerialBus (
292 ACPI_OPERAND_OBJECT *SourceDesc,
293 ACPI_OPERAND_OBJECT *ObjDesc,
294 ACPI_OPERAND_OBJECT **ReturnBuffer)
295 {
296 ACPI_STATUS Status;
297 UINT32 BufferLength;
298 UINT32 DataLength;
299 void *Buffer;
300 ACPI_OPERAND_OBJECT *BufferDesc;
301 UINT32 Function;
302 UINT16 AccessorType;
303
304
305 ACPI_FUNCTION_TRACE_PTR (ExWriteSerialBus, ObjDesc);
306
307
308 /*
309 * This is an SMBus, GSBus or IPMI write. We will bypass the entire
310 * field mechanism and handoff the buffer directly to the handler.
311 * For these address spaces, the buffer is bidirectional; on a
312 * write, return data is returned in the same buffer.
313 *
314 * Source must be a buffer of sufficient size, these are fixed size:
315 * ACPI_SMBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.
316 *
317 * Note: SMBus and GSBus protocol type is passed in upper 16-bits
318 * of Function
319 *
320 * Common buffer format:
321 * Status; (Byte 0 of the data buffer)
322 * Length; (Byte 1 of the data buffer)
323 * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
324 */
325 if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER)
326 {
327 ACPI_ERROR ((AE_INFO,
328 "SMBus/IPMI/GenericSerialBus write requires "
329 "Buffer, found type %s",
330 AcpiUtGetObjectTypeName (SourceDesc)));
331
332 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
333 }
334
335 switch (ObjDesc->Field.RegionObj->Region.SpaceId)
336 {
337 case ACPI_ADR_SPACE_SMBUS:
338
339 BufferLength = ACPI_SMBUS_BUFFER_SIZE;
340 Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16);
341 break;
342
343 case ACPI_ADR_SPACE_IPMI:
344
345 BufferLength = ACPI_IPMI_BUFFER_SIZE;
346 Function = ACPI_WRITE;
347 break;
348
349 case ACPI_ADR_SPACE_GSBUS:
350
351 AccessorType = ObjDesc->Field.Attribute;
352 Status = AcpiExGetProtocolBufferLength (AccessorType, &BufferLength);
353 if (ACPI_FAILURE (Status))
354 {
355 ACPI_ERROR ((AE_INFO,
356 "Invalid protocol ID for GSBus: 0x%4.4X", AccessorType));
357
358 return_ACPI_STATUS (Status);
359 }
360
361 /* Add header length to get the full size of the buffer */
362
363 BufferLength += ACPI_SERIAL_HEADER_SIZE;
364 Function = ACPI_WRITE | (AccessorType << 16);
365 break;
366
367 default:
368 return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID);
369 }
370
371 /* Create the transfer/bidirectional/return buffer */
372
373 BufferDesc = AcpiUtCreateBufferObject (BufferLength);
374 if (!BufferDesc)
375 {
376 return_ACPI_STATUS (AE_NO_MEMORY);
377 }
378
379 /* Copy the input buffer data to the transfer buffer */
380
381 Buffer = BufferDesc->Buffer.Pointer;
382 DataLength = (BufferLength < SourceDesc->Buffer.Length ?
383 BufferLength : SourceDesc->Buffer.Length);
384 memcpy (Buffer, SourceDesc->Buffer.Pointer, DataLength);
385
386 /* Lock entire transaction if requested */
387
388 AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
389
390 /*
391 * Perform the write (returns status and perhaps data in the
392 * same buffer)
393 */
394 Status = AcpiExAccessRegion (
395 ObjDesc, 0, (UINT64 *) Buffer, Function);
396 AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
397
398 *ReturnBuffer = BufferDesc;
399 return_ACPI_STATUS (Status);
400 }