Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6595 serge 1
/*******************************************************************************
2
 *
3
 * Module Name: hwregs - Read/write access functions for the various ACPI
4
 *                       control and status registers.
5
 *
6
 ******************************************************************************/
7
 
8
/*
9
 * Copyright (C) 2000 - 2015, Intel Corp.
10
 * All rights reserved.
11
 *
12
 * Redistribution and use in source and binary forms, with or without
13
 * modification, are permitted provided that the following conditions
14
 * are met:
15
 * 1. Redistributions of source code must retain the above copyright
16
 *    notice, this list of conditions, and the following disclaimer,
17
 *    without modification.
18
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19
 *    substantially similar to the "NO WARRANTY" disclaimer below
20
 *    ("Disclaimer") and any redistribution must be conditioned upon
21
 *    including a substantially similar Disclaimer requirement for further
22
 *    binary redistribution.
23
 * 3. Neither the names of the above-listed copyright holders nor the names
24
 *    of any contributors may be used to endorse or promote products derived
25
 *    from this software without specific prior written permission.
26
 *
27
 * Alternatively, this software may be distributed under the terms of the
28
 * GNU General Public License ("GPL") version 2 as published by the Free
29
 * Software Foundation.
30
 *
31
 * NO WARRANTY
32
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42
 * POSSIBILITY OF SUCH DAMAGES.
43
 */
44
 
45
#include 
46
#include "accommon.h"
47
#include "acevents.h"
48
 
49
#define _COMPONENT          ACPI_HARDWARE
50
ACPI_MODULE_NAME("hwregs")
51
 
52
#if (!ACPI_REDUCED_HARDWARE)
53
/* Local Prototypes */
54
static acpi_status
55
acpi_hw_read_multiple(u32 *value,
56
		      struct acpi_generic_address *register_a,
57
		      struct acpi_generic_address *register_b);
58
 
59
static acpi_status
60
acpi_hw_write_multiple(u32 value,
61
		       struct acpi_generic_address *register_a,
62
		       struct acpi_generic_address *register_b);
63
 
64
#endif				/* !ACPI_REDUCED_HARDWARE */
65
 
66
/******************************************************************************
67
 *
68
 * FUNCTION:    acpi_hw_validate_register
69
 *
70
 * PARAMETERS:  reg                 - GAS register structure
71
 *              max_bit_width       - Max bit_width supported (32 or 64)
72
 *              address             - Pointer to where the gas->address
73
 *                                    is returned
74
 *
75
 * RETURN:      Status
76
 *
77
 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
78
 *              pointer, Address, space_id, bit_width, and bit_offset.
79
 *
80
 ******************************************************************************/
81
 
82
acpi_status
83
acpi_hw_validate_register(struct acpi_generic_address *reg,
84
			  u8 max_bit_width, u64 *address)
85
{
86
 
87
	/* Must have a valid pointer to a GAS structure */
88
 
89
	if (!reg) {
90
		return (AE_BAD_PARAMETER);
91
	}
92
 
93
	/*
94
	 * Copy the target address. This handles possible alignment issues.
95
	 * Address must not be null. A null address also indicates an optional
96
	 * ACPI register that is not supported, so no error message.
97
	 */
98
	ACPI_MOVE_64_TO_64(address, ®->address);
99
	if (!(*address)) {
100
		return (AE_BAD_ADDRESS);
101
	}
102
 
103
	/* Validate the space_ID */
104
 
105
	if ((reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
106
	    (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
107
		ACPI_ERROR((AE_INFO,
108
			    "Unsupported address space: 0x%X", reg->space_id));
109
		return (AE_SUPPORT);
110
	}
111
 
112
	/* Validate the bit_width */
113
 
114
	if ((reg->bit_width != 8) &&
115
	    (reg->bit_width != 16) &&
116
	    (reg->bit_width != 32) && (reg->bit_width != max_bit_width)) {
117
		ACPI_ERROR((AE_INFO,
118
			    "Unsupported register bit width: 0x%X",
119
			    reg->bit_width));
120
		return (AE_SUPPORT);
121
	}
122
 
123
	/* Validate the bit_offset. Just a warning for now. */
124
 
125
	if (reg->bit_offset != 0) {
126
		ACPI_WARNING((AE_INFO,
127
			      "Unsupported register bit offset: 0x%X",
128
			      reg->bit_offset));
129
	}
130
 
131
	return (AE_OK);
132
}
133
 
134
/******************************************************************************
135
 *
136
 * FUNCTION:    acpi_hw_read
137
 *
138
 * PARAMETERS:  value               - Where the value is returned
139
 *              reg                 - GAS register structure
140
 *
141
 * RETURN:      Status
142
 *
143
 * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
144
 *              version of acpi_read, used internally since the overhead of
145
 *              64-bit values is not needed.
146
 *
147
 * LIMITATIONS: 
148
 *      bit_width must be exactly 8, 16, or 32.
149
 *      space_ID must be system_memory or system_IO.
150
 *      bit_offset and access_width are currently ignored, as there has
151
 *          not been a need to implement these.
152
 *
153
 ******************************************************************************/
154
 
155
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
156
{
157
	u64 address;
158
	u64 value64;
159
	acpi_status status;
160
 
161
	ACPI_FUNCTION_NAME(hw_read);
162
 
163
	/* Validate contents of the GAS register */
164
 
165
	status = acpi_hw_validate_register(reg, 32, &address);
166
	if (ACPI_FAILURE(status)) {
167
		return (status);
168
	}
169
 
170
	/* Initialize entire 32-bit return value to zero */
171
 
172
	*value = 0;
173
 
174
	/*
175
	 * Two address spaces supported: Memory or IO. PCI_Config is
176
	 * not supported here because the GAS structure is insufficient
177
	 */
178
	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
179
		status = acpi_os_read_memory((acpi_physical_address)
180
					     address, &value64, reg->bit_width);
181
 
182
		*value = (u32)value64;
183
	} else {		/* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
184
 
185
		status = acpi_hw_read_port((acpi_io_address)
186
					   address, value, reg->bit_width);
187
	}
188
 
189
	ACPI_DEBUG_PRINT((ACPI_DB_IO,
190
			  "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
191
			  *value, reg->bit_width, ACPI_FORMAT_UINT64(address),
192
			  acpi_ut_get_region_name(reg->space_id)));
193
 
194
	return (status);
195
}
196
 
197
/******************************************************************************
198
 *
199
 * FUNCTION:    acpi_hw_write
200
 *
201
 * PARAMETERS:  value               - Value to be written
202
 *              reg                 - GAS register structure
203
 *
204
 * RETURN:      Status
205
 *
206
 * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max
207
 *              version of acpi_write, used internally since the overhead of
208
 *              64-bit values is not needed.
209
 *
210
 ******************************************************************************/
211
 
212
acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
213
{
214
	u64 address;
215
	acpi_status status;
216
 
217
	ACPI_FUNCTION_NAME(hw_write);
218
 
219
	/* Validate contents of the GAS register */
220
 
221
	status = acpi_hw_validate_register(reg, 32, &address);
222
	if (ACPI_FAILURE(status)) {
223
		return (status);
224
	}
225
 
226
	/*
227
	 * Two address spaces supported: Memory or IO. PCI_Config is
228
	 * not supported here because the GAS structure is insufficient
229
	 */
230
	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
231
		status = acpi_os_write_memory((acpi_physical_address)
232
					      address, (u64)value,
233
					      reg->bit_width);
234
	} else {		/* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
235
 
236
		status = acpi_hw_write_port((acpi_io_address)
237
					    address, value, reg->bit_width);
238
	}
239
 
240
	ACPI_DEBUG_PRINT((ACPI_DB_IO,
241
			  "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
242
			  value, reg->bit_width, ACPI_FORMAT_UINT64(address),
243
			  acpi_ut_get_region_name(reg->space_id)));
244
 
245
	return (status);
246
}
247
 
248
#if (!ACPI_REDUCED_HARDWARE)
249
/*******************************************************************************
250
 *
251
 * FUNCTION:    acpi_hw_clear_acpi_status
252
 *
253
 * PARAMETERS:  None
254
 *
255
 * RETURN:      Status
256
 *
257
 * DESCRIPTION: Clears all fixed and general purpose status bits
258
 *
259
 ******************************************************************************/
260
 
261
acpi_status acpi_hw_clear_acpi_status(void)
262
{
263
	acpi_status status;
264
	acpi_cpu_flags lock_flags = 0;
265
 
266
	ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
267
 
268
	ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
269
			  ACPI_BITMASK_ALL_FIXED_STATUS,
270
			  ACPI_FORMAT_UINT64(acpi_gbl_xpm1a_status.address)));
271
 
272
	lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
273
 
274
	/* Clear the fixed events in PM1 A/B */
275
 
276
	status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
277
					ACPI_BITMASK_ALL_FIXED_STATUS);
278
 
279
	acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
280
 
281
	if (ACPI_FAILURE(status)) {
282
		goto exit;
283
	}
284
 
285
	/* Clear the GPE Bits in all GPE registers in all GPE blocks */
286
 
287
	status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
288
 
289
exit:
290
	return_ACPI_STATUS(status);
291
}
292
 
293
/*******************************************************************************
294
 *
295
 * FUNCTION:    acpi_hw_get_bit_register_info
296
 *
297
 * PARAMETERS:  register_id         - Index of ACPI Register to access
298
 *
299
 * RETURN:      The bitmask to be used when accessing the register
300
 *
301
 * DESCRIPTION: Map register_id into a register bitmask.
302
 *
303
 ******************************************************************************/
304
 
305
struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
306
{
307
	ACPI_FUNCTION_ENTRY();
308
 
309
	if (register_id > ACPI_BITREG_MAX) {
310
		ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: 0x%X",
311
			    register_id));
312
		return (NULL);
313
	}
314
 
315
	return (&acpi_gbl_bit_register_info[register_id]);
316
}
317
 
318
/******************************************************************************
319
 *
320
 * FUNCTION:    acpi_hw_write_pm1_control
321
 *
322
 * PARAMETERS:  pm1a_control        - Value to be written to PM1A control
323
 *              pm1b_control        - Value to be written to PM1B control
324
 *
325
 * RETURN:      Status
326
 *
327
 * DESCRIPTION: Write the PM1 A/B control registers. These registers are
328
 *              different than than the PM1 A/B status and enable registers
329
 *              in that different values can be written to the A/B registers.
330
 *              Most notably, the SLP_TYP bits can be different, as per the
331
 *              values returned from the _Sx predefined methods.
332
 *
333
 ******************************************************************************/
334
 
335
acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control)
336
{
337
	acpi_status status;
338
 
339
	ACPI_FUNCTION_TRACE(hw_write_pm1_control);
340
 
341
	status =
342
	    acpi_hw_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block);
343
	if (ACPI_FAILURE(status)) {
344
		return_ACPI_STATUS(status);
345
	}
346
 
347
	if (acpi_gbl_FADT.xpm1b_control_block.address) {
348
		status =
349
		    acpi_hw_write(pm1b_control,
350
				  &acpi_gbl_FADT.xpm1b_control_block);
351
	}
352
	return_ACPI_STATUS(status);
353
}
354
 
355
/******************************************************************************
356
 *
357
 * FUNCTION:    acpi_hw_register_read
358
 *
359
 * PARAMETERS:  register_id         - ACPI Register ID
360
 *              return_value        - Where the register value is returned
361
 *
362
 * RETURN:      Status and the value read.
363
 *
364
 * DESCRIPTION: Read from the specified ACPI register
365
 *
366
 ******************************************************************************/
367
acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value)
368
{
369
	u32 value = 0;
370
	acpi_status status;
371
 
372
	ACPI_FUNCTION_TRACE(hw_register_read);
373
 
374
	switch (register_id) {
375
	case ACPI_REGISTER_PM1_STATUS:	/* PM1 A/B: 16-bit access each */
376
 
377
		status = acpi_hw_read_multiple(&value,
378
					       &acpi_gbl_xpm1a_status,
379
					       &acpi_gbl_xpm1b_status);
380
		break;
381
 
382
	case ACPI_REGISTER_PM1_ENABLE:	/* PM1 A/B: 16-bit access each */
383
 
384
		status = acpi_hw_read_multiple(&value,
385
					       &acpi_gbl_xpm1a_enable,
386
					       &acpi_gbl_xpm1b_enable);
387
		break;
388
 
389
	case ACPI_REGISTER_PM1_CONTROL:	/* PM1 A/B: 16-bit access each */
390
 
391
		status = acpi_hw_read_multiple(&value,
392
					       &acpi_gbl_FADT.
393
					       xpm1a_control_block,
394
					       &acpi_gbl_FADT.
395
					       xpm1b_control_block);
396
 
397
		/*
398
		 * Zero the write-only bits. From the ACPI specification, "Hardware
399
		 * Write-Only Bits": "Upon reads to registers with write-only bits,
400
		 * software masks out all write-only bits."
401
		 */
402
		value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
403
		break;
404
 
405
	case ACPI_REGISTER_PM2_CONTROL:	/* 8-bit access */
406
 
407
		status =
408
		    acpi_hw_read(&value, &acpi_gbl_FADT.xpm2_control_block);
409
		break;
410
 
411
	case ACPI_REGISTER_PM_TIMER:	/* 32-bit access */
412
 
413
		status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm_timer_block);
414
		break;
415
 
416
	case ACPI_REGISTER_SMI_COMMAND_BLOCK:	/* 8-bit access */
417
 
418
		status =
419
		    acpi_hw_read_port(acpi_gbl_FADT.smi_command, &value, 8);
420
		break;
421
 
422
	default:
423
 
424
		ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id));
425
		status = AE_BAD_PARAMETER;
426
		break;
427
	}
428
 
429
	if (ACPI_SUCCESS(status)) {
430
		*return_value = value;
431
	}
432
 
433
	return_ACPI_STATUS(status);
434
}
435
 
436
/******************************************************************************
437
 *
438
 * FUNCTION:    acpi_hw_register_write
439
 *
440
 * PARAMETERS:  register_id         - ACPI Register ID
441
 *              value               - The value to write
442
 *
443
 * RETURN:      Status
444
 *
445
 * DESCRIPTION: Write to the specified ACPI register
446
 *
447
 * NOTE: In accordance with the ACPI specification, this function automatically
448
 * preserves the value of the following bits, meaning that these bits cannot be
449
 * changed via this interface:
450
 *
451
 * PM1_CONTROL[0] = SCI_EN
452
 * PM1_CONTROL[9]
453
 * PM1_STATUS[11]
454
 *
455
 * ACPI References:
456
 * 1) Hardware Ignored Bits: When software writes to a register with ignored
457
 *      bit fields, it preserves the ignored bit fields
458
 * 2) SCI_EN: OSPM always preserves this bit position
459
 *
460
 ******************************************************************************/
461
 
462
acpi_status acpi_hw_register_write(u32 register_id, u32 value)
463
{
464
	acpi_status status;
465
	u32 read_value;
466
 
467
	ACPI_FUNCTION_TRACE(hw_register_write);
468
 
469
	switch (register_id) {
470
	case ACPI_REGISTER_PM1_STATUS:	/* PM1 A/B: 16-bit access each */
471
		/*
472
		 * Handle the "ignored" bit in PM1 Status. According to the ACPI
473
		 * specification, ignored bits are to be preserved when writing.
474
		 * Normally, this would mean a read/modify/write sequence. However,
475
		 * preserving a bit in the status register is different. Writing a
476
		 * one clears the status, and writing a zero preserves the status.
477
		 * Therefore, we must always write zero to the ignored bit.
478
		 *
479
		 * This behavior is clarified in the ACPI 4.0 specification.
480
		 */
481
		value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
482
 
483
		status = acpi_hw_write_multiple(value,
484
						&acpi_gbl_xpm1a_status,
485
						&acpi_gbl_xpm1b_status);
486
		break;
487
 
488
	case ACPI_REGISTER_PM1_ENABLE:	/* PM1 A/B: 16-bit access each */
489
 
490
		status = acpi_hw_write_multiple(value,
491
						&acpi_gbl_xpm1a_enable,
492
						&acpi_gbl_xpm1b_enable);
493
		break;
494
 
495
	case ACPI_REGISTER_PM1_CONTROL:	/* PM1 A/B: 16-bit access each */
496
		/*
497
		 * Perform a read first to preserve certain bits (per ACPI spec)
498
		 * Note: This includes SCI_EN, we never want to change this bit
499
		 */
500
		status = acpi_hw_read_multiple(&read_value,
501
					       &acpi_gbl_FADT.
502
					       xpm1a_control_block,
503
					       &acpi_gbl_FADT.
504
					       xpm1b_control_block);
505
		if (ACPI_FAILURE(status)) {
506
			goto exit;
507
		}
508
 
509
		/* Insert the bits to be preserved */
510
 
511
		ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
512
				 read_value);
513
 
514
		/* Now we can write the data */
515
 
516
		status = acpi_hw_write_multiple(value,
517
						&acpi_gbl_FADT.
518
						xpm1a_control_block,
519
						&acpi_gbl_FADT.
520
						xpm1b_control_block);
521
		break;
522
 
523
	case ACPI_REGISTER_PM2_CONTROL:	/* 8-bit access */
524
		/*
525
		 * For control registers, all reserved bits must be preserved,
526
		 * as per the ACPI spec.
527
		 */
528
		status =
529
		    acpi_hw_read(&read_value,
530
				 &acpi_gbl_FADT.xpm2_control_block);
531
		if (ACPI_FAILURE(status)) {
532
			goto exit;
533
		}
534
 
535
		/* Insert the bits to be preserved */
536
 
537
		ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS,
538
				 read_value);
539
 
540
		status =
541
		    acpi_hw_write(value, &acpi_gbl_FADT.xpm2_control_block);
542
		break;
543
 
544
	case ACPI_REGISTER_PM_TIMER:	/* 32-bit access */
545
 
546
		status = acpi_hw_write(value, &acpi_gbl_FADT.xpm_timer_block);
547
		break;
548
 
549
	case ACPI_REGISTER_SMI_COMMAND_BLOCK:	/* 8-bit access */
550
 
551
		/* SMI_CMD is currently always in IO space */
552
 
553
		status =
554
		    acpi_hw_write_port(acpi_gbl_FADT.smi_command, value, 8);
555
		break;
556
 
557
	default:
558
 
559
		ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id));
560
		status = AE_BAD_PARAMETER;
561
		break;
562
	}
563
 
564
exit:
565
	return_ACPI_STATUS(status);
566
}
567
 
568
/******************************************************************************
569
 *
570
 * FUNCTION:    acpi_hw_read_multiple
571
 *
572
 * PARAMETERS:  value               - Where the register value is returned
573
 *              register_a           - First ACPI register (required)
574
 *              register_b           - Second ACPI register (optional)
575
 *
576
 * RETURN:      Status
577
 *
578
 * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
579
 *
580
 ******************************************************************************/
581
 
582
static acpi_status
583
acpi_hw_read_multiple(u32 *value,
584
		      struct acpi_generic_address *register_a,
585
		      struct acpi_generic_address *register_b)
586
{
587
	u32 value_a = 0;
588
	u32 value_b = 0;
589
	acpi_status status;
590
 
591
	/* The first register is always required */
592
 
593
	status = acpi_hw_read(&value_a, register_a);
594
	if (ACPI_FAILURE(status)) {
595
		return (status);
596
	}
597
 
598
	/* Second register is optional */
599
 
600
	if (register_b->address) {
601
		status = acpi_hw_read(&value_b, register_b);
602
		if (ACPI_FAILURE(status)) {
603
			return (status);
604
		}
605
	}
606
 
607
	/*
608
	 * OR the two return values together. No shifting or masking is necessary,
609
	 * because of how the PM1 registers are defined in the ACPI specification:
610
	 *
611
	 * "Although the bits can be split between the two register blocks (each
612
	 * register block has a unique pointer within the FADT), the bit positions
613
	 * are maintained. The register block with unimplemented bits (that is,
614
	 * those implemented in the other register block) always returns zeros,
615
	 * and writes have no side effects"
616
	 */
617
	*value = (value_a | value_b);
618
	return (AE_OK);
619
}
620
 
621
/******************************************************************************
622
 *
623
 * FUNCTION:    acpi_hw_write_multiple
624
 *
625
 * PARAMETERS:  value               - The value to write
626
 *              register_a           - First ACPI register (required)
627
 *              register_b           - Second ACPI register (optional)
628
 *
629
 * RETURN:      Status
630
 *
631
 * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
632
 *
633
 ******************************************************************************/
634
 
635
static acpi_status
636
acpi_hw_write_multiple(u32 value,
637
		       struct acpi_generic_address *register_a,
638
		       struct acpi_generic_address *register_b)
639
{
640
	acpi_status status;
641
 
642
	/* The first register is always required */
643
 
644
	status = acpi_hw_write(value, register_a);
645
	if (ACPI_FAILURE(status)) {
646
		return (status);
647
	}
648
 
649
	/*
650
	 * Second register is optional
651
	 *
652
	 * No bit shifting or clearing is necessary, because of how the PM1
653
	 * registers are defined in the ACPI specification:
654
	 *
655
	 * "Although the bits can be split between the two register blocks (each
656
	 * register block has a unique pointer within the FADT), the bit positions
657
	 * are maintained. The register block with unimplemented bits (that is,
658
	 * those implemented in the other register block) always returns zeros,
659
	 * and writes have no side effects"
660
	 */
661
	if (register_b->address) {
662
		status = acpi_hw_write(value, register_b);
663
	}
664
 
665
	return (status);
666
}
667
 
668
#endif				/* !ACPI_REDUCED_HARDWARE */