Print this page
update to acpica-unix2-20140114
acpica-unix2-20130823
PANKOVs restructure
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/io/acpica/executer/exfldio.c
+++ new/usr/src/common/acpica/components/executer/exfldio.c
1 1 /******************************************************************************
2 2 *
3 3 * Module Name: exfldio - Aml Field I/O
4 4 *
5 5 *****************************************************************************/
6 6
7 7 /*
8 - * Copyright (C) 2000 - 2011, Intel Corp.
8 + * Copyright (C) 2000 - 2014, Intel Corp.
9 9 * All rights reserved.
10 10 *
11 11 * Redistribution and use in source and binary forms, with or without
12 12 * modification, are permitted provided that the following conditions
13 13 * are met:
14 14 * 1. Redistributions of source code must retain the above copyright
15 15 * notice, this list of conditions, and the following disclaimer,
16 16 * without modification.
17 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 18 * substantially similar to the "NO WARRANTY" disclaimer below
19 19 * ("Disclaimer") and any redistribution must be conditioned upon
20 20 * including a substantially similar Disclaimer requirement for further
21 21 * binary redistribution.
22 22 * 3. Neither the names of the above-listed copyright holders nor the names
23 23 * of any contributors may be used to endorse or promote products derived
24 24 * from this software without specific prior written permission.
25 25 *
26 26 * Alternatively, this software may be distributed under the terms of the
27 27 * GNU General Public License ("GPL") version 2 as published by the Free
28 28 * Software Foundation.
29 29 *
30 30 * NO WARRANTY
31 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 41 * POSSIBILITY OF SUCH DAMAGES.
42 42 */
43 43
44 44
45 45 #define __EXFLDIO_C__
46 46
47 47 #include "acpi.h"
48 48 #include "accommon.h"
49 49 #include "acinterp.h"
50 50 #include "amlcode.h"
51 51 #include "acevents.h"
52 52 #include "acdispat.h"
53 53
54 54
55 55 #define _COMPONENT ACPI_EXECUTER
56 56 ACPI_MODULE_NAME ("exfldio")
57 57
58 58 /* Local prototypes */
59 59
60 60 static ACPI_STATUS
61 61 AcpiExFieldDatumIo (
62 62 ACPI_OPERAND_OBJECT *ObjDesc,
63 63 UINT32 FieldDatumByteOffset,
64 64 UINT64 *Value,
65 65 UINT32 ReadWrite);
66 66
67 67 static BOOLEAN
68 68 AcpiExRegisterOverflow (
69 69 ACPI_OPERAND_OBJECT *ObjDesc,
70 70 UINT64 Value);
71 71
72 72 static ACPI_STATUS
73 73 AcpiExSetupRegion (
74 74 ACPI_OPERAND_OBJECT *ObjDesc,
75 75 UINT32 FieldDatumByteOffset);
76 76
77 77
78 78 /*******************************************************************************
↓ open down ↓ |
60 lines elided |
↑ open up ↑ |
79 79 *
80 80 * FUNCTION: AcpiExSetupRegion
81 81 *
82 82 * PARAMETERS: ObjDesc - Field to be read or written
83 83 * FieldDatumByteOffset - Byte offset of this datum within the
84 84 * parent field
85 85 *
86 86 * RETURN: Status
87 87 *
88 88 * DESCRIPTION: Common processing for AcpiExExtractFromField and
89 - * AcpiExInsertIntoField. Initialize the Region if necessary and
89 + * AcpiExInsertIntoField. Initialize the Region if necessary and
90 90 * validate the request.
91 91 *
92 92 ******************************************************************************/
93 93
94 94 static ACPI_STATUS
95 95 AcpiExSetupRegion (
96 96 ACPI_OPERAND_OBJECT *ObjDesc,
97 97 UINT32 FieldDatumByteOffset)
98 98 {
99 99 ACPI_STATUS Status = AE_OK;
100 100 ACPI_OPERAND_OBJECT *RgnDesc;
101 + UINT8 SpaceId;
101 102
102 103
103 104 ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);
104 105
105 106
106 107 RgnDesc = ObjDesc->CommonField.RegionObj;
107 108
108 109 /* We must have a valid region */
109 110
110 111 if (RgnDesc->Common.Type != ACPI_TYPE_REGION)
111 112 {
112 113 ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
113 114 RgnDesc->Common.Type,
114 115 AcpiUtGetObjectTypeName (RgnDesc)));
115 116
116 117 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
117 118 }
118 119
120 + SpaceId = RgnDesc->Region.SpaceId;
121 +
122 + /* Validate the Space ID */
123 +
124 + if (!AcpiIsValidSpaceId (SpaceId))
125 + {
126 + ACPI_ERROR ((AE_INFO, "Invalid/unknown Address Space ID: 0x%2.2X", SpaceId));
127 + return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID);
128 + }
129 +
119 130 /*
120 131 * If the Region Address and Length have not been previously evaluated,
121 132 * evaluate them now and save the results.
122 133 */
123 134 if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
124 135 {
125 136 Status = AcpiDsGetRegionArguments (RgnDesc);
126 137 if (ACPI_FAILURE (Status))
127 138 {
128 139 return_ACPI_STATUS (Status);
129 140 }
130 141 }
131 142
132 143 /*
133 - * Exit now for SMBus or IPMI address space, it has a non-linear
144 + * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear
134 145 * address space and the request cannot be directly validated
135 146 */
136 - if (RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_SMBUS ||
137 - RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_IPMI)
147 + if (SpaceId == ACPI_ADR_SPACE_SMBUS ||
148 + SpaceId == ACPI_ADR_SPACE_GSBUS ||
149 + SpaceId == ACPI_ADR_SPACE_IPMI)
138 150 {
139 151 /* SMBus or IPMI has a non-linear address space */
140 152
141 153 return_ACPI_STATUS (AE_OK);
142 154 }
143 155
144 156 #ifdef ACPI_UNDER_DEVELOPMENT
145 157 /*
146 158 * If the Field access is AnyAcc, we can now compute the optimal
147 159 * access (because we know know the length of the parent region)
148 160 */
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
149 161 if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
150 162 {
151 163 if (ACPI_FAILURE (Status))
152 164 {
153 165 return_ACPI_STATUS (Status);
154 166 }
155 167 }
156 168 #endif
157 169
158 170 /*
159 - * Validate the request. The entire request from the byte offset for a
171 + * Validate the request. The entire request from the byte offset for a
160 172 * length of one field datum (access width) must fit within the region.
161 173 * (Region length is specified in bytes)
162 174 */
163 175 if (RgnDesc->Region.Length <
164 176 (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset +
165 177 ObjDesc->CommonField.AccessByteWidth))
166 178 {
167 179 if (AcpiGbl_EnableInterpreterSlack)
168 180 {
169 181 /*
170 182 * Slack mode only: We will go ahead and allow access to this
171 183 * field if it is within the region length rounded up to the next
172 184 * access width boundary. ACPI_SIZE cast for 64-bit compile.
173 185 */
174 186 if (ACPI_ROUND_UP (RgnDesc->Region.Length,
175 187 ObjDesc->CommonField.AccessByteWidth) >=
176 188 ((ACPI_SIZE) ObjDesc->CommonField.BaseByteOffset +
177 189 ObjDesc->CommonField.AccessByteWidth +
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
178 190 FieldDatumByteOffset))
179 191 {
180 192 return_ACPI_STATUS (AE_OK);
181 193 }
182 194 }
183 195
184 196 if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth)
185 197 {
186 198 /*
187 199 * This is the case where the AccessType (AccWord, etc.) is wider
188 - * than the region itself. For example, a region of length one
200 + * than the region itself. For example, a region of length one
189 201 * byte, and a field with Dword access specified.
190 202 */
191 203 ACPI_ERROR ((AE_INFO,
192 204 "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)",
193 205 AcpiUtGetNodeName (ObjDesc->CommonField.Node),
194 206 ObjDesc->CommonField.AccessByteWidth,
195 207 AcpiUtGetNodeName (RgnDesc->Region.Node),
196 208 RgnDesc->Region.Length));
197 209 }
198 210
199 211 /*
200 212 * Offset rounded up to next multiple of field width
201 213 * exceeds region length, indicate an error
202 214 */
203 215 ACPI_ERROR ((AE_INFO,
204 216 "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)",
205 217 AcpiUtGetNodeName (ObjDesc->CommonField.Node),
206 218 ObjDesc->CommonField.BaseByteOffset,
207 219 FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
208 220 AcpiUtGetNodeName (RgnDesc->Region.Node),
209 221 RgnDesc->Region.Length));
210 222
211 223 return_ACPI_STATUS (AE_AML_REGION_LIMIT);
212 224 }
213 225
214 226 return_ACPI_STATUS (AE_OK);
215 227 }
216 228
217 229
218 230 /*******************************************************************************
219 231 *
220 232 * FUNCTION: AcpiExAccessRegion
221 233 *
222 234 * PARAMETERS: ObjDesc - Field to be read
223 235 * FieldDatumByteOffset - Byte offset of this datum within the
224 236 * parent field
225 237 * Value - Where to store value (must at least
226 238 * 64 bits)
227 239 * Function - Read or Write flag plus other region-
228 240 * dependent flags
229 241 *
230 242 * RETURN: Status
231 243 *
232 244 * DESCRIPTION: Read or Write a single field datum to an Operation Region.
233 245 *
234 246 ******************************************************************************/
235 247
236 248 ACPI_STATUS
237 249 AcpiExAccessRegion (
238 250 ACPI_OPERAND_OBJECT *ObjDesc,
239 251 UINT32 FieldDatumByteOffset,
240 252 UINT64 *Value,
241 253 UINT32 Function)
242 254 {
243 255 ACPI_STATUS Status;
244 256 ACPI_OPERAND_OBJECT *RgnDesc;
245 257 UINT32 RegionOffset;
246 258
247 259
248 260 ACPI_FUNCTION_TRACE (ExAccessRegion);
249 261
250 262
251 263 /*
252 264 * Ensure that the region operands are fully evaluated and verify
253 265 * the validity of the request
254 266 */
255 267 Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset);
256 268 if (ACPI_FAILURE (Status))
257 269 {
258 270 return_ACPI_STATUS (Status);
259 271 }
260 272
261 273 /*
262 274 * The physical address of this field datum is:
263 275 *
264 276 * 1) The base of the region, plus
265 277 * 2) The base offset of the field, plus
266 278 * 3) The current offset into the field
267 279 */
268 280 RgnDesc = ObjDesc->CommonField.RegionObj;
269 281 RegionOffset =
270 282 ObjDesc->CommonField.BaseByteOffset +
271 283 FieldDatumByteOffset;
272 284
273 285 if ((Function & ACPI_IO_MASK) == ACPI_READ)
274 286 {
275 287 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
276 288 }
277 289 else
278 290 {
279 291 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
280 292 }
281 293
282 294 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
↓ open down ↓ |
84 lines elided |
↑ open up ↑ |
283 295 " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
284 296 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
285 297 RgnDesc->Region.SpaceId,
286 298 ObjDesc->CommonField.AccessByteWidth,
287 299 ObjDesc->CommonField.BaseByteOffset,
288 300 FieldDatumByteOffset,
289 301 ACPI_CAST_PTR (void, (RgnDesc->Region.Address + RegionOffset))));
290 302
291 303 /* Invoke the appropriate AddressSpace/OpRegion handler */
292 304
293 - Status = AcpiEvAddressSpaceDispatch (RgnDesc, Function, RegionOffset,
305 + Status = AcpiEvAddressSpaceDispatch (RgnDesc, ObjDesc,
306 + Function, RegionOffset,
294 307 ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value);
295 308
296 309 if (ACPI_FAILURE (Status))
297 310 {
298 311 if (Status == AE_NOT_IMPLEMENTED)
299 312 {
300 313 ACPI_ERROR ((AE_INFO,
301 314 "Region %s (ID=%u) not implemented",
302 315 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
303 316 RgnDesc->Region.SpaceId));
304 317 }
305 318 else if (Status == AE_NOT_EXIST)
306 319 {
307 320 ACPI_ERROR ((AE_INFO,
308 321 "Region %s (ID=%u) has no handler",
309 322 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
310 323 RgnDesc->Region.SpaceId));
311 324 }
312 325 }
313 326
314 327 return_ACPI_STATUS (Status);
315 328 }
316 329
317 330
318 331 /*******************************************************************************
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
319 332 *
320 333 * FUNCTION: AcpiExRegisterOverflow
321 334 *
322 335 * PARAMETERS: ObjDesc - Register(Field) to be written
323 336 * Value - Value to be stored
324 337 *
325 338 * RETURN: TRUE if value overflows the field, FALSE otherwise
326 339 *
327 340 * DESCRIPTION: Check if a value is out of range of the field being written.
328 341 * Used to check if the values written to Index and Bank registers
329 - * are out of range. Normally, the value is simply truncated
342 + * are out of range. Normally, the value is simply truncated
330 343 * to fit the field, but this case is most likely a serious
331 344 * coding error in the ASL.
332 345 *
333 346 ******************************************************************************/
334 347
335 348 static BOOLEAN
336 349 AcpiExRegisterOverflow (
337 350 ACPI_OPERAND_OBJECT *ObjDesc,
338 351 UINT64 Value)
339 352 {
340 353
341 354 if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE)
342 355 {
343 356 /*
344 357 * The field is large enough to hold the maximum integer, so we can
345 358 * never overflow it.
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
346 359 */
347 360 return (FALSE);
348 361 }
349 362
350 363 if (Value >= ((UINT64) 1 << ObjDesc->CommonField.BitLength))
351 364 {
352 365 /*
353 366 * The Value is larger than the maximum value that can fit into
354 367 * the register.
355 368 */
369 + ACPI_ERROR ((AE_INFO,
370 + "Index value 0x%8.8X%8.8X overflows field width 0x%X",
371 + ACPI_FORMAT_UINT64 (Value),
372 + ObjDesc->CommonField.BitLength));
373 +
356 374 return (TRUE);
357 375 }
358 376
359 377 /* The Value will fit into the field with no truncation */
360 378
361 379 return (FALSE);
362 380 }
363 381
364 382
365 383 /*******************************************************************************
366 384 *
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
367 385 * FUNCTION: AcpiExFieldDatumIo
368 386 *
369 387 * PARAMETERS: ObjDesc - Field to be read
370 388 * FieldDatumByteOffset - Byte offset of this datum within the
371 389 * parent field
372 390 * Value - Where to store value (must be 64 bits)
373 391 * ReadWrite - Read or Write flag
374 392 *
375 393 * RETURN: Status
376 394 *
377 - * DESCRIPTION: Read or Write a single datum of a field. The FieldType is
395 + * DESCRIPTION: Read or Write a single datum of a field. The FieldType is
378 396 * demultiplexed here to handle the different types of fields
379 397 * (BufferField, RegionField, IndexField, BankField)
380 398 *
381 399 ******************************************************************************/
382 400
383 401 static ACPI_STATUS
384 402 AcpiExFieldDatumIo (
385 403 ACPI_OPERAND_OBJECT *ObjDesc,
386 404 UINT32 FieldDatumByteOffset,
387 405 UINT64 *Value,
388 406 UINT32 ReadWrite)
389 407 {
390 408 ACPI_STATUS Status;
391 409 UINT64 LocalValue;
392 410
393 411
394 412 ACPI_FUNCTION_TRACE_U32 (ExFieldDatumIo, FieldDatumByteOffset);
395 413
396 414
397 415 if (ReadWrite == ACPI_READ)
398 416 {
399 417 if (!Value)
400 418 {
401 419 LocalValue = 0;
402 420
403 421 /* To support reads without saving return value */
404 422 Value = &LocalValue;
405 423 }
406 424
407 425 /* Clear the entire return buffer first, [Very Important!] */
408 426
409 427 *Value = 0;
410 428 }
411 429
412 430 /*
413 431 * The four types of fields are:
414 432 *
415 433 * BufferField - Read/write from/to a Buffer
416 434 * RegionField - Read/write from/to a Operation Region.
417 435 * BankField - Write to a Bank Register, then read/write from/to an
418 436 * OperationRegion
419 437 * IndexField - Write to an Index Register, then read/write from/to a
420 438 * Data Register
421 439 */
422 440 switch (ObjDesc->Common.Type)
423 441 {
424 442 case ACPI_TYPE_BUFFER_FIELD:
425 443 /*
426 444 * If the BufferField arguments have not been previously evaluated,
427 445 * evaluate them now and save the results.
428 446 */
429 447 if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
430 448 {
431 449 Status = AcpiDsGetBufferFieldArguments (ObjDesc);
432 450 if (ACPI_FAILURE (Status))
433 451 {
434 452 return_ACPI_STATUS (Status);
435 453 }
436 454 }
437 455
438 456 if (ReadWrite == ACPI_READ)
439 457 {
440 458 /*
441 459 * Copy the data from the source buffer.
442 460 * Length is the field width in bytes.
443 461 */
444 462 ACPI_MEMCPY (Value,
445 463 (ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
446 464 ObjDesc->BufferField.BaseByteOffset +
447 465 FieldDatumByteOffset,
448 466 ObjDesc->CommonField.AccessByteWidth);
449 467 }
450 468 else
451 469 {
452 470 /*
453 471 * Copy the data to the target buffer.
454 472 * Length is the field width in bytes.
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
455 473 */
456 474 ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
457 475 ObjDesc->BufferField.BaseByteOffset +
458 476 FieldDatumByteOffset,
459 477 Value, ObjDesc->CommonField.AccessByteWidth);
460 478 }
461 479
462 480 Status = AE_OK;
463 481 break;
464 482
465 -
466 483 case ACPI_TYPE_LOCAL_BANK_FIELD:
467 -
468 484 /*
469 485 * Ensure that the BankValue is not beyond the capacity of
470 486 * the register
471 487 */
472 488 if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj,
473 489 (UINT64) ObjDesc->BankField.Value))
474 490 {
475 491 return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
476 492 }
477 493
478 494 /*
479 495 * For BankFields, we must write the BankValue to the BankRegister
480 496 * (itself a RegionField) before we can access the data.
481 497 */
482 498 Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj,
483 499 &ObjDesc->BankField.Value,
484 500 sizeof (ObjDesc->BankField.Value));
485 501 if (ACPI_FAILURE (Status))
486 502 {
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
487 503 return_ACPI_STATUS (Status);
488 504 }
489 505
490 506 /*
491 507 * Now that the Bank has been selected, fall through to the
492 508 * RegionField case and write the datum to the Operation Region
493 509 */
494 510
495 511 /*lint -fallthrough */
496 512
497 -
498 513 case ACPI_TYPE_LOCAL_REGION_FIELD:
499 514 /*
500 515 * For simple RegionFields, we just directly access the owning
501 516 * Operation Region.
502 517 */
503 518 Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value,
504 519 ReadWrite);
505 520 break;
506 521
507 -
508 522 case ACPI_TYPE_LOCAL_INDEX_FIELD:
509 -
510 -
511 523 /*
512 524 * Ensure that the IndexValue is not beyond the capacity of
513 525 * the register
514 526 */
515 527 if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj,
516 528 (UINT64) ObjDesc->IndexField.Value))
517 529 {
518 530 return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
519 531 }
520 532
521 533 /* Write the index value to the IndexRegister (itself a RegionField) */
522 534
523 535 FieldDatumByteOffset += ObjDesc->IndexField.Value;
524 536
525 537 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
526 538 "Write to Index Register: Value %8.8X\n",
527 539 FieldDatumByteOffset));
528 540
529 541 Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj,
530 542 &FieldDatumByteOffset,
531 543 sizeof (FieldDatumByteOffset));
532 544 if (ACPI_FAILURE (Status))
533 545 {
534 546 return_ACPI_STATUS (Status);
535 547 }
536 548
537 549 if (ReadWrite == ACPI_READ)
538 550 {
539 551 /* Read the datum from the DataRegister */
540 552
541 553 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
542 554 "Read from Data Register\n"));
543 555
544 556 Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj,
545 557 Value, sizeof (UINT64));
546 558 }
547 559 else
548 560 {
549 561 /* Write the datum to the DataRegister */
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
550 562
551 563 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
552 564 "Write to Data Register: Value %8.8X%8.8X\n",
553 565 ACPI_FORMAT_UINT64 (*Value)));
554 566
555 567 Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj,
556 568 Value, sizeof (UINT64));
557 569 }
558 570 break;
559 571
560 -
561 572 default:
562 573
563 574 ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %u",
564 575 ObjDesc->Common.Type));
565 576 Status = AE_AML_INTERNAL;
566 577 break;
567 578 }
568 579
569 580 if (ACPI_SUCCESS (Status))
570 581 {
571 582 if (ReadWrite == ACPI_READ)
572 583 {
573 584 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
574 585 "Value Read %8.8X%8.8X, Width %u\n",
575 586 ACPI_FORMAT_UINT64 (*Value),
576 587 ObjDesc->CommonField.AccessByteWidth));
577 588 }
578 589 else
579 590 {
580 591 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
581 592 "Value Written %8.8X%8.8X, Width %u\n",
582 593 ACPI_FORMAT_UINT64 (*Value),
583 594 ObjDesc->CommonField.AccessByteWidth));
584 595 }
585 596 }
586 597
587 598 return_ACPI_STATUS (Status);
588 599 }
589 600
590 601
591 602 /*******************************************************************************
592 603 *
593 604 * FUNCTION: AcpiExWriteWithUpdateRule
594 605 *
595 606 * PARAMETERS: ObjDesc - Field to be written
596 607 * Mask - bitmask within field datum
597 608 * FieldValue - Value to write
598 609 * FieldDatumByteOffset - Offset of datum within field
599 610 *
600 611 * RETURN: Status
601 612 *
602 613 * DESCRIPTION: Apply the field update rule to a field write
603 614 *
604 615 ******************************************************************************/
605 616
606 617 ACPI_STATUS
607 618 AcpiExWriteWithUpdateRule (
608 619 ACPI_OPERAND_OBJECT *ObjDesc,
609 620 UINT64 Mask,
610 621 UINT64 FieldValue,
611 622 UINT32 FieldDatumByteOffset)
612 623 {
613 624 ACPI_STATUS Status = AE_OK;
614 625 UINT64 MergedValue;
615 626 UINT64 CurrentValue;
616 627
617 628
618 629 ACPI_FUNCTION_TRACE_U32 (ExWriteWithUpdateRule, Mask);
619 630
620 631
621 632 /* Start with the new bits */
622 633
623 634 MergedValue = FieldValue;
624 635
625 636 /* If the mask is all ones, we don't need to worry about the update rule */
626 637
627 638 if (Mask != ACPI_UINT64_MAX)
628 639 {
629 640 /* Decode the update rule */
630 641
631 642 switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)
632 643 {
633 644 case AML_FIELD_UPDATE_PRESERVE:
634 645 /*
635 646 * Check if update rule needs to be applied (not if mask is all
636 647 * ones) The left shift drops the bits we want to ignore.
637 648 */
638 649 if ((~Mask << (ACPI_MUL_8 (sizeof (Mask)) -
639 650 ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 0)
640 651 {
641 652 /*
642 653 * Read the current contents of the byte/word/dword containing
643 654 * the field, and merge with the new field value.
644 655 */
645 656 Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
646 657 &CurrentValue, ACPI_READ);
647 658 if (ACPI_FAILURE (Status))
648 659 {
649 660 return_ACPI_STATUS (Status);
650 661 }
651 662
652 663 MergedValue |= (CurrentValue & ~Mask);
653 664 }
654 665 break;
655 666
656 667 case AML_FIELD_UPDATE_WRITE_AS_ONES:
657 668
658 669 /* Set positions outside the field to all ones */
659 670
660 671 MergedValue |= ~Mask;
661 672 break;
662 673
663 674 case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
664 675
665 676 /* Set positions outside the field to all zeros */
666 677
667 678 MergedValue &= Mask;
668 679 break;
669 680
670 681 default:
671 682
672 683 ACPI_ERROR ((AE_INFO,
673 684 "Unknown UpdateRule value: 0x%X",
674 685 (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)));
675 686 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
676 687 }
677 688 }
678 689
679 690 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
680 691 "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
681 692 ACPI_FORMAT_UINT64 (Mask),
682 693 FieldDatumByteOffset,
683 694 ObjDesc->CommonField.AccessByteWidth,
684 695 ACPI_FORMAT_UINT64 (FieldValue),
685 696 ACPI_FORMAT_UINT64 (MergedValue)));
686 697
687 698 /* Write the merged value */
688 699
689 700 Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
690 701 &MergedValue, ACPI_WRITE);
691 702
692 703 return_ACPI_STATUS (Status);
693 704 }
694 705
695 706
696 707 /*******************************************************************************
697 708 *
698 709 * FUNCTION: AcpiExExtractFromField
699 710 *
700 711 * PARAMETERS: ObjDesc - Field to be read
701 712 * Buffer - Where to store the field data
702 713 * BufferLength - Length of Buffer
703 714 *
704 715 * RETURN: Status
705 716 *
706 717 * DESCRIPTION: Retrieve the current value of the given field
707 718 *
708 719 ******************************************************************************/
709 720
710 721 ACPI_STATUS
711 722 AcpiExExtractFromField (
712 723 ACPI_OPERAND_OBJECT *ObjDesc,
713 724 void *Buffer,
714 725 UINT32 BufferLength)
715 726 {
716 727 ACPI_STATUS Status;
717 728 UINT64 RawDatum;
718 729 UINT64 MergedDatum;
719 730 UINT32 FieldOffset = 0;
720 731 UINT32 BufferOffset = 0;
721 732 UINT32 BufferTailBits;
722 733 UINT32 DatumCount;
723 734 UINT32 FieldDatumCount;
724 735 UINT32 AccessBitWidth;
725 736 UINT32 i;
726 737
727 738
728 739 ACPI_FUNCTION_TRACE (ExExtractFromField);
729 740
730 741
731 742 /* Validate target buffer and clear it */
732 743
733 744 if (BufferLength <
734 745 ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
735 746 {
736 747 ACPI_ERROR ((AE_INFO,
737 748 "Field size %u (bits) is too large for buffer (%u)",
738 749 ObjDesc->CommonField.BitLength, BufferLength));
739 750
740 751 return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
↓ open down ↓ |
170 lines elided |
↑ open up ↑ |
741 752 }
742 753
743 754 ACPI_MEMSET (Buffer, 0, BufferLength);
744 755 AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
745 756
746 757 /* Handle the simple case here */
747 758
748 759 if ((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
749 760 (ObjDesc->CommonField.BitLength == AccessBitWidth))
750 761 {
751 - Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
762 + if (BufferLength >= sizeof (UINT64))
763 + {
764 + Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
765 + }
766 + else
767 + {
768 + /* Use RawDatum (UINT64) to handle buffers < 64 bits */
769 +
770 + Status = AcpiExFieldDatumIo (ObjDesc, 0, &RawDatum, ACPI_READ);
771 + ACPI_MEMCPY (Buffer, &RawDatum, BufferLength);
772 + }
773 +
752 774 return_ACPI_STATUS (Status);
753 775 }
754 776
755 777 /* TBD: Move to common setup code */
756 778
757 779 /* Field algorithm is limited to sizeof(UINT64), truncate if needed */
758 780
759 781 if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
760 782 {
761 783 ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
762 784 AccessBitWidth = sizeof (UINT64) * 8;
763 785 }
764 786
765 787 /* Compute the number of datums (access width data items) */
766 788
767 789 DatumCount = ACPI_ROUND_UP_TO (
768 790 ObjDesc->CommonField.BitLength, AccessBitWidth);
769 791
770 792 FieldDatumCount = ACPI_ROUND_UP_TO (
771 793 ObjDesc->CommonField.BitLength +
772 794 ObjDesc->CommonField.StartFieldBitOffset, AccessBitWidth);
773 795
774 796 /* Priming read from the field */
775 797
776 798 Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
777 799 if (ACPI_FAILURE (Status))
778 800 {
779 801 return_ACPI_STATUS (Status);
780 802 }
781 803 MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
782 804
783 805 /* Read the rest of the field */
784 806
785 807 for (i = 1; i < FieldDatumCount; i++)
786 808 {
787 809 /* Get next input datum from the field */
788 810
789 811 FieldOffset += ObjDesc->CommonField.AccessByteWidth;
790 812 Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset,
791 813 &RawDatum, ACPI_READ);
792 814 if (ACPI_FAILURE (Status))
793 815 {
794 816 return_ACPI_STATUS (Status);
795 817 }
796 818
797 819 /*
798 820 * Merge with previous datum if necessary.
799 821 *
800 822 * Note: Before the shift, check if the shift value will be larger than
801 823 * the integer size. If so, there is no need to perform the operation.
802 824 * This avoids the differences in behavior between different compilers
803 825 * concerning shift values larger than the target data width.
804 826 */
805 827 if (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset <
806 828 ACPI_INTEGER_BIT_SIZE)
807 829 {
808 830 MergedDatum |= RawDatum <<
809 831 (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
810 832 }
811 833
812 834 if (i == DatumCount)
813 835 {
814 836 break;
815 837 }
816 838
817 839 /* Write merged datum to target buffer */
818 840
819 841 ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
820 842 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
821 843 BufferLength - BufferOffset));
822 844
823 845 BufferOffset += ObjDesc->CommonField.AccessByteWidth;
824 846 MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
825 847 }
826 848
827 849 /* Mask off any extra bits in the last datum */
828 850
829 851 BufferTailBits = ObjDesc->CommonField.BitLength % AccessBitWidth;
830 852 if (BufferTailBits)
831 853 {
832 854 MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
833 855 }
834 856
835 857 /* Write the last datum to the buffer */
836 858
837 859 ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
838 860 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
839 861 BufferLength - BufferOffset));
840 862
841 863 return_ACPI_STATUS (AE_OK);
842 864 }
843 865
844 866
845 867 /*******************************************************************************
846 868 *
847 869 * FUNCTION: AcpiExInsertIntoField
848 870 *
849 871 * PARAMETERS: ObjDesc - Field to be written
850 872 * Buffer - Data to be written
851 873 * BufferLength - Length of Buffer
852 874 *
853 875 * RETURN: Status
854 876 *
855 877 * DESCRIPTION: Store the Buffer contents into the given field
856 878 *
857 879 ******************************************************************************/
858 880
859 881 ACPI_STATUS
860 882 AcpiExInsertIntoField (
861 883 ACPI_OPERAND_OBJECT *ObjDesc,
862 884 void *Buffer,
863 885 UINT32 BufferLength)
864 886 {
865 887 void *NewBuffer;
866 888 ACPI_STATUS Status;
867 889 UINT64 Mask;
868 890 UINT64 WidthMask;
869 891 UINT64 MergedDatum;
870 892 UINT64 RawDatum = 0;
871 893 UINT32 FieldOffset = 0;
872 894 UINT32 BufferOffset = 0;
873 895 UINT32 BufferTailBits;
874 896 UINT32 DatumCount;
875 897 UINT32 FieldDatumCount;
876 898 UINT32 AccessBitWidth;
877 899 UINT32 RequiredLength;
878 900 UINT32 i;
879 901
880 902
↓ open down ↓ |
119 lines elided |
↑ open up ↑ |
881 903 ACPI_FUNCTION_TRACE (ExInsertIntoField);
882 904
883 905
884 906 /* Validate input buffer */
885 907
886 908 NewBuffer = NULL;
887 909 RequiredLength = ACPI_ROUND_BITS_UP_TO_BYTES (
888 910 ObjDesc->CommonField.BitLength);
889 911 /*
890 912 * We must have a buffer that is at least as long as the field
891 - * we are writing to. This is because individual fields are
913 + * we are writing to. This is because individual fields are
892 914 * indivisible and partial writes are not supported -- as per
893 915 * the ACPI specification.
894 916 */
895 917 if (BufferLength < RequiredLength)
896 918 {
897 919 /* We need to create a new buffer */
898 920
899 921 NewBuffer = ACPI_ALLOCATE_ZEROED (RequiredLength);
900 922 if (!NewBuffer)
901 923 {
902 924 return_ACPI_STATUS (AE_NO_MEMORY);
903 925 }
904 926
905 927 /*
906 928 * Copy the original data to the new buffer, starting
907 - * at Byte zero. All unused (upper) bytes of the
929 + * at Byte zero. All unused (upper) bytes of the
908 930 * buffer will be 0.
909 931 */
910 932 ACPI_MEMCPY ((char *) NewBuffer, (char *) Buffer, BufferLength);
911 933 Buffer = NewBuffer;
912 934 BufferLength = RequiredLength;
913 935 }
914 936
915 937 /* TBD: Move to common setup code */
916 938
917 939 /* Algo is limited to sizeof(UINT64), so cut the AccessByteWidth */
918 940 if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
919 941 {
920 942 ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
921 943 }
922 944
923 945 AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
924 946
925 947 /*
926 948 * Create the bitmasks used for bit insertion.
927 949 * Note: This if/else is used to bypass compiler differences with the
928 950 * shift operator
929 951 */
930 952 if (AccessBitWidth == ACPI_INTEGER_BIT_SIZE)
931 953 {
932 954 WidthMask = ACPI_UINT64_MAX;
933 955 }
934 956 else
935 957 {
936 958 WidthMask = ACPI_MASK_BITS_ABOVE (AccessBitWidth);
937 959 }
938 960
939 961 Mask = WidthMask &
940 962 ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);
941 963
942 964 /* Compute the number of datums (access width data items) */
943 965
944 966 DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength,
945 967 AccessBitWidth);
946 968
947 969 FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength +
948 970 ObjDesc->CommonField.StartFieldBitOffset,
949 971 AccessBitWidth);
950 972
951 973 /* Get initial Datum from the input buffer */
952 974
953 975 ACPI_MEMCPY (&RawDatum, Buffer,
954 976 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
955 977 BufferLength - BufferOffset));
956 978
957 979 MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
958 980
959 981 /* Write the entire field */
960 982
961 983 for (i = 1; i < FieldDatumCount; i++)
962 984 {
963 985 /* Write merged datum to the target field */
964 986
965 987 MergedDatum &= Mask;
966 988 Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask,
967 989 MergedDatum, FieldOffset);
968 990 if (ACPI_FAILURE (Status))
969 991 {
970 992 goto Exit;
971 993 }
972 994
973 995 FieldOffset += ObjDesc->CommonField.AccessByteWidth;
974 996
975 997 /*
976 998 * Start new output datum by merging with previous input datum
977 999 * if necessary.
978 1000 *
979 1001 * Note: Before the shift, check if the shift value will be larger than
980 1002 * the integer size. If so, there is no need to perform the operation.
981 1003 * This avoids the differences in behavior between different compilers
982 1004 * concerning shift values larger than the target data width.
983 1005 */
984 1006 if ((AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset) <
985 1007 ACPI_INTEGER_BIT_SIZE)
986 1008 {
987 1009 MergedDatum = RawDatum >>
988 1010 (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
989 1011 }
990 1012 else
991 1013 {
992 1014 MergedDatum = 0;
993 1015 }
994 1016
995 1017 Mask = WidthMask;
996 1018
997 1019 if (i == DatumCount)
998 1020 {
999 1021 break;
1000 1022 }
1001 1023
1002 1024 /* Get the next input datum from the buffer */
1003 1025
1004 1026 BufferOffset += ObjDesc->CommonField.AccessByteWidth;
1005 1027 ACPI_MEMCPY (&RawDatum, ((char *) Buffer) + BufferOffset,
1006 1028 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
1007 1029 BufferLength - BufferOffset));
1008 1030
1009 1031 MergedDatum |= RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
1010 1032 }
1011 1033
1012 1034 /* Mask off any extra bits in the last datum */
1013 1035
1014 1036 BufferTailBits = (ObjDesc->CommonField.BitLength +
1015 1037 ObjDesc->CommonField.StartFieldBitOffset) % AccessBitWidth;
1016 1038 if (BufferTailBits)
1017 1039 {
1018 1040 Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
1019 1041 }
1020 1042
1021 1043 /* Write the last datum to the field */
1022 1044
1023 1045 MergedDatum &= Mask;
1024 1046 Status = AcpiExWriteWithUpdateRule (ObjDesc,
1025 1047 Mask, MergedDatum, FieldOffset);
↓ open down ↓ |
108 lines elided |
↑ open up ↑ |
1026 1048
1027 1049 Exit:
1028 1050 /* Free temporary buffer if we used one */
1029 1051
1030 1052 if (NewBuffer)
1031 1053 {
1032 1054 ACPI_FREE (NewBuffer);
1033 1055 }
1034 1056 return_ACPI_STATUS (Status);
1035 1057 }
1036 -
1037 -
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX