File: /usr/src/linux/drivers/acpi/hardware/hwregs.c
1
2 /*******************************************************************************
3 *
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 * control and status registers.
6 * $Revision: 109 $
7 *
8 ******************************************************************************/
9
10 /*
11 * Copyright (C) 2000, 2001 R. Byron Moore
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28
29 #include "acpi.h"
30 #include "achware.h"
31 #include "acnamesp.h"
32
33 #define _COMPONENT ACPI_HARDWARE
34 MODULE_NAME ("hwregs")
35
36
37 /*******************************************************************************
38 *
39 * FUNCTION: Acpi_hw_get_bit_shift
40 *
41 * PARAMETERS: Mask - Input mask to determine bit shift from.
42 * Must have at least 1 bit set.
43 *
44 * RETURN: Bit location of the lsb of the mask
45 *
46 * DESCRIPTION: Returns the bit number for the low order bit that's set.
47 *
48 ******************************************************************************/
49
50 u32
51 acpi_hw_get_bit_shift (
52 u32 mask)
53 {
54 u32 shift;
55
56
57 FUNCTION_TRACE ("Hw_get_bit_shift");
58
59
60 for (shift = 0; ((mask >> shift) & 1) == 0; shift++) { ; }
61
62 return_VALUE (shift);
63 }
64
65
66 /*******************************************************************************
67 *
68 * FUNCTION: Acpi_hw_clear_acpi_status
69 *
70 * PARAMETERS: none
71 *
72 * RETURN: none
73 *
74 * DESCRIPTION: Clears all fixed and general purpose status bits
75 *
76 ******************************************************************************/
77
78 void
79 acpi_hw_clear_acpi_status (void)
80 {
81 u16 gpe_length;
82 u16 index;
83
84
85 FUNCTION_TRACE ("Hw_clear_acpi_status");
86
87
88 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
89 ALL_FIXED_STS_BITS,
90 (u16) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address)));
91
92
93 acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
94
95 acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS);
96
97
98 if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) {
99 acpi_os_write_port ((ACPI_IO_ADDRESS)
100 ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address),
101 ALL_FIXED_STS_BITS, 16);
102 }
103
104 /* now clear the GPE Bits */
105
106 if (acpi_gbl_FADT->gpe0blk_len) {
107 gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len);
108
109 for (index = 0; index < gpe_length; index++) {
110 acpi_os_write_port ((ACPI_IO_ADDRESS) (
111 ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + index),
112 0xFF, 8);
113 }
114 }
115
116 if (acpi_gbl_FADT->gpe1_blk_len) {
117 gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len);
118
119 for (index = 0; index < gpe_length; index++) {
120 acpi_os_write_port ((ACPI_IO_ADDRESS) (
121 ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + index),
122 0xFF, 8);
123 }
124 }
125
126 acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
127 return_VOID;
128 }
129
130
131 /*******************************************************************************
132 *
133 * FUNCTION: Acpi_hw_obtain_sleep_type_register_data
134 *
135 * PARAMETERS: Sleep_state - Numeric state requested
136 * *Slp_Typ_a - Pointer to byte to receive SLP_TYPa value
137 * *Slp_Typ_b - Pointer to byte to receive SLP_TYPb value
138 *
139 * RETURN: Status - ACPI status
140 *
141 * DESCRIPTION: Acpi_hw_obtain_sleep_type_register_data() obtains the SLP_TYP and
142 * SLP_TYPb values for the sleep state requested.
143 *
144 ******************************************************************************/
145
146 acpi_status
147 acpi_hw_obtain_sleep_type_register_data (
148 u8 sleep_state,
149 u8 *slp_typ_a,
150 u8 *slp_typ_b)
151 {
152 acpi_status status = AE_OK;
153 acpi_operand_object *obj_desc;
154
155
156 FUNCTION_TRACE ("Hw_obtain_sleep_type_register_data");
157
158
159 /*
160 * Validate parameters
161 */
162 if ((sleep_state > ACPI_S_STATES_MAX) ||
163 !slp_typ_a || !slp_typ_b) {
164 return_ACPI_STATUS (AE_BAD_PARAMETER);
165 }
166
167 /*
168 * Acpi_evaluate the namespace object containing the values for this state
169 */
170 status = acpi_ns_evaluate_by_name ((NATIVE_CHAR *) acpi_gbl_db_sleep_states[sleep_state],
171 NULL, &obj_desc);
172 if (ACPI_FAILURE (status)) {
173 return_ACPI_STATUS (status);
174 }
175
176 if (!obj_desc) {
177 REPORT_ERROR (("Missing Sleep State object\n"));
178 return_ACPI_STATUS (AE_NOT_EXIST);
179 }
180
181 /*
182 * We got something, now ensure it is correct. The object must
183 * be a package and must have at least 2 numeric values as the
184 * two elements
185 */
186
187 /* Even though Acpi_evaluate_object resolves package references,
188 * Ns_evaluate dpesn't. So, we do it here.
189 */
190 status = acpi_ut_resolve_package_references(obj_desc);
191
192 if (obj_desc->package.count < 2) {
193 /* Must have at least two elements */
194
195 REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
196 status = AE_ERROR;
197 }
198
199 else if (((obj_desc->package.elements[0])->common.type !=
200 ACPI_TYPE_INTEGER) ||
201 ((obj_desc->package.elements[1])->common.type !=
202 ACPI_TYPE_INTEGER)) {
203 /* Must have two */
204
205 REPORT_ERROR (("Sleep State package elements are not both of type Number\n"));
206 status = AE_ERROR;
207 }
208
209 else {
210 /*
211 * Valid _Sx_ package size, type, and value
212 */
213 *slp_typ_a = (u8) (obj_desc->package.elements[0])->integer.value;
214
215 *slp_typ_b = (u8) (obj_desc->package.elements[1])->integer.value;
216 }
217
218
219 if (ACPI_FAILURE (status)) {
220 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad Sleep object %p type %X\n",
221 obj_desc, obj_desc->common.type));
222 }
223
224 acpi_ut_remove_reference (obj_desc);
225
226 return_ACPI_STATUS (status);
227 }
228
229
230 /*******************************************************************************
231 *
232 * FUNCTION: Acpi_hw_register_bit_access
233 *
234 * PARAMETERS: Read_write - Either ACPI_READ or ACPI_WRITE.
235 * Use_lock - Lock the hardware
236 * Register_id - index of ACPI Register to access
237 * Value - (only used on write) value to write to the
238 * Register. Shifted all the way right.
239 *
240 * RETURN: Value written to or read from specified Register. This value
241 * is shifted all the way right.
242 *
243 * DESCRIPTION: Generic ACPI Register read/write function.
244 *
245 ******************************************************************************/
246
247 u32
248 acpi_hw_register_bit_access (
249 NATIVE_UINT read_write,
250 u8 use_lock,
251 u32 register_id,
252 ...) /* Value (only used on write) */
253 {
254 u32 register_value = 0;
255 u32 mask = 0;
256 u32 value = 0;
257 va_list marker;
258
259
260 FUNCTION_TRACE ("Hw_register_bit_access");
261
262
263 if (read_write == ACPI_WRITE) {
264 va_start (marker, register_id);
265 value = va_arg (marker, u32);
266 va_end (marker);
267 }
268
269 if (ACPI_MTX_LOCK == use_lock) {
270 acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
271 }
272
273 /*
274 * Decode the Register ID
275 * Register id = Register block id | bit id
276 *
277 * Check bit id to fine locate Register offset.
278 * Check Mask to determine Register offset, and then read-write.
279 */
280 switch (REGISTER_BLOCK_ID (register_id)) {
281 case PM1_STS:
282
283 switch (register_id) {
284 case TMR_STS:
285 mask = TMR_STS_MASK;
286 break;
287
288 case BM_STS:
289 mask = BM_STS_MASK;
290 break;
291
292 case GBL_STS:
293 mask = GBL_STS_MASK;
294 break;
295
296 case PWRBTN_STS:
297 mask = PWRBTN_STS_MASK;
298 break;
299
300 case SLPBTN_STS:
301 mask = SLPBTN_STS_MASK;
302 break;
303
304 case RTC_STS:
305 mask = RTC_STS_MASK;
306 break;
307
308 case WAK_STS:
309 mask = WAK_STS_MASK;
310 break;
311
312 default:
313 mask = 0;
314 break;
315 }
316
317 register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
318
319 if (read_write == ACPI_WRITE) {
320 /*
321 * Status Registers are different from the rest. Clear by
322 * writing 1, writing 0 has no effect. So, the only relevent
323 * information is the single bit we're interested in, all
324 * others should be written as 0 so they will be left
325 * unchanged
326 */
327 value <<= acpi_hw_get_bit_shift (mask);
328 value &= mask;
329
330 if (value) {
331 acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS,
332 (u16) value);
333 register_value = 0;
334 }
335 }
336
337 break;
338
339
340 case PM1_EN:
341
342 switch (register_id) {
343 case TMR_EN:
344 mask = TMR_EN_MASK;
345 break;
346
347 case GBL_EN:
348 mask = GBL_EN_MASK;
349 break;
350
351 case PWRBTN_EN:
352 mask = PWRBTN_EN_MASK;
353 break;
354
355 case SLPBTN_EN:
356 mask = SLPBTN_EN_MASK;
357 break;
358
359 case RTC_EN:
360 mask = RTC_EN_MASK;
361 break;
362
363 default:
364 mask = 0;
365 break;
366 }
367
368 register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN);
369
370 if (read_write == ACPI_WRITE) {
371 register_value &= ~mask;
372 value <<= acpi_hw_get_bit_shift (mask);
373 value &= mask;
374 register_value |= value;
375
376 acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_EN, (u16) register_value);
377 }
378
379 break;
380
381
382 case PM1_CONTROL:
383
384 switch (register_id) {
385 case SCI_EN:
386 mask = SCI_EN_MASK;
387 break;
388
389 case BM_RLD:
390 mask = BM_RLD_MASK;
391 break;
392
393 case GBL_RLS:
394 mask = GBL_RLS_MASK;
395 break;
396
397 case SLP_TYPE_A:
398 case SLP_TYPE_B:
399 mask = SLP_TYPE_X_MASK;
400 break;
401
402 case SLP_EN:
403 mask = SLP_EN_MASK;
404 break;
405
406 default:
407 mask = 0;
408 break;
409 }
410
411
412 /*
413 * Read the PM1 Control register.
414 * Note that at this level, the fact that there are actually TWO
415 * registers (A and B) and that B may not exist, are abstracted.
416 */
417 register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_CONTROL);
418
419 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value));
420
421 if (read_write == ACPI_WRITE) {
422 register_value &= ~mask;
423 value <<= acpi_hw_get_bit_shift (mask);
424 value &= mask;
425 register_value |= value;
426
427 /*
428 * SLP_TYPE_x Registers are written differently
429 * than any other control Registers with
430 * respect to A and B Registers. The value
431 * for A may be different than the value for B
432 *
433 * Therefore, pass the Register_id, not just generic PM1_CONTROL,
434 * because we need to do different things. Yuck.
435 */
436 acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id,
437 (u16) register_value);
438 }
439 break;
440
441
442 case PM2_CONTROL:
443
444 switch (register_id) {
445 case ARB_DIS:
446 mask = ARB_DIS_MASK;
447 break;
448
449 default:
450 mask = 0;
451 break;
452 }
453
454 register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
455
456 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %p\n",
457 register_value, ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address)));
458
459 if (read_write == ACPI_WRITE) {
460 register_value &= ~mask;
461 value <<= acpi_hw_get_bit_shift (mask);
462 value &= mask;
463 register_value |= value;
464
465 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %p\n", register_value,
466 acpi_gbl_FADT->Xpm2_cnt_blk.address));
467
468 acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
469 PM2_CONTROL, (u8) (register_value));
470 }
471 break;
472
473
474 case PM_TIMER:
475
476 mask = TMR_VAL_MASK;
477 register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
478 PM_TIMER);
479 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM_TIMER: Read %X from %p\n",
480 register_value, ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)));
481
482 break;
483
484
485 case GPE1_EN_BLOCK:
486 case GPE1_STS_BLOCK:
487 case GPE0_EN_BLOCK:
488 case GPE0_STS_BLOCK:
489
490 /* Determine the bit to be accessed
491 *
492 * (u32) Register_id:
493 * 31 24 16 8 0
494 * +--------+--------+--------+--------+
495 * | gpe_block_id | gpe_bit_number |
496 * +--------+--------+--------+--------+
497 *
498 * gpe_block_id is one of GPE[01]_EN_BLOCK and GPE[01]_STS_BLOCK
499 * gpe_bit_number is relative from the gpe_block (0x00~0xFF)
500 */
501 mask = REGISTER_BIT_ID(register_id); /* gpe_bit_number */
502 register_id = REGISTER_BLOCK_ID(register_id) | (mask >> 3);
503 mask = acpi_gbl_decode_to8bit [mask % 8];
504
505 /*
506 * The base address of the GPE 0 Register Block
507 * Plus 1/2 the length of the GPE 0 Register Block
508 * The enable Register is the Register following the Status Register
509 * and each Register is defined as 1/2 of the total Register Block
510 */
511
512 /*
513 * This sets the bit within Enable_bit that needs to be written to
514 * the Register indicated in Mask to a 1, all others are 0
515 */
516
517 /* Now get the current Enable Bits in the selected Reg */
518
519 register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, register_id);
520 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "GPE Enable bits: Read %X from %X\n",
521 register_value, register_id));
522
523 if (read_write == ACPI_WRITE) {
524 register_value &= ~mask;
525 value <<= acpi_hw_get_bit_shift (mask);
526 value &= mask;
527 register_value |= value;
528
529 /*
530 * This write will put the Action state into the General Purpose
531 * Enable Register indexed by the value in Mask
532 */
533 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
534 register_value, register_id));
535 acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id,
536 (u8) register_value);
537 register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
538 register_id);
539 }
540 break;
541
542
543 case SMI_CMD_BLOCK:
544 case PROCESSOR_BLOCK:
545
546 /* Not used by any callers at this time - therefore, not implemented */
547
548 default:
549
550 mask = 0;
551 break;
552 }
553
554 if (ACPI_MTX_LOCK == use_lock) {
555 acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
556 }
557
558
559 register_value &= mask;
560 register_value >>= acpi_hw_get_bit_shift (mask);
561
562 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Register I/O: returning %X\n", register_value));
563 return_VALUE (register_value);
564 }
565
566
567 /******************************************************************************
568 *
569 * FUNCTION: Acpi_hw_register_read
570 *
571 * PARAMETERS: Use_lock - Mutex hw access.
572 * Register_id - Register_iD + Offset.
573 *
574 * RETURN: Value read or written.
575 *
576 * DESCRIPTION: Acpi register read function. Registers are read at the
577 * given offset.
578 *
579 ******************************************************************************/
580
581 u32
582 acpi_hw_register_read (
583 u8 use_lock,
584 u32 register_id)
585 {
586 u32 value = 0;
587 u32 bank_offset;
588
589
590 FUNCTION_TRACE ("Hw_register_read");
591
592
593 if (ACPI_MTX_LOCK == use_lock) {
594 acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
595 }
596
597
598 switch (REGISTER_BLOCK_ID(register_id)) {
599 case PM1_STS: /* 16-bit access */
600
601 value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, 0);
602 value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, 0);
603 break;
604
605
606 case PM1_EN: /* 16-bit access*/
607
608 bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len);
609 value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset);
610 value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset);
611 break;
612
613
614 case PM1_CONTROL: /* 16-bit access */
615
616 value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
617 value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
618 break;
619
620
621 case PM2_CONTROL: /* 8-bit access */
622
623 value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
624 break;
625
626
627 case PM_TIMER: /* 32-bit access */
628
629 value = acpi_hw_low_level_read (32, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
630 break;
631
632
633 /*
634 * For the GPE? Blocks, the lower word of Register_id contains the
635 * byte offset for which to read, as each part of each block may be
636 * several bytes long.
637 */
638 case GPE0_STS_BLOCK: /* 8-bit access */
639
640 bank_offset = REGISTER_BIT_ID(register_id);
641 value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
642 break;
643
644 case GPE0_EN_BLOCK: /* 8-bit access */
645
646 bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len) + REGISTER_BIT_ID(register_id);
647 value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
648 break;
649
650 case GPE1_STS_BLOCK: /* 8-bit access */
651
652 bank_offset = REGISTER_BIT_ID(register_id);
653 value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
654 break;
655
656 case GPE1_EN_BLOCK: /* 8-bit access */
657
658 bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len) + REGISTER_BIT_ID(register_id);
659 value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
660 break;
661
662 case SMI_CMD_BLOCK: /* 8bit */
663
664 acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value, 8);
665 break;
666
667 default:
668 /* Value will be returned as 0 */
669 break;
670 }
671
672
673 if (ACPI_MTX_LOCK == use_lock) {
674 acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
675 }
676
677 return_VALUE (value);
678 }
679
680
681 /******************************************************************************
682 *
683 * FUNCTION: Acpi_hw_register_write
684 *
685 * PARAMETERS: Use_lock - Mutex hw access.
686 * Register_id - Register_iD + Offset.
687 *
688 * RETURN: Value read or written.
689 *
690 * DESCRIPTION: Acpi register Write function. Registers are written at the
691 * given offset.
692 *
693 ******************************************************************************/
694
695 void
696 acpi_hw_register_write (
697 u8 use_lock,
698 u32 register_id,
699 u32 value)
700 {
701 u32 bank_offset;
702
703
704 FUNCTION_TRACE ("Hw_register_write");
705
706
707 if (ACPI_MTX_LOCK == use_lock) {
708 acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
709 }
710
711
712 switch (REGISTER_BLOCK_ID (register_id)) {
713 case PM1_STS: /* 16-bit access */
714
715 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, 0);
716 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, 0);
717 break;
718
719
720 case PM1_EN: /* 16-bit access*/
721
722 bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len);
723 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset);
724 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset);
725 break;
726
727
728 case PM1_CONTROL: /* 16-bit access */
729
730 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
731 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
732 break;
733
734
735 case PM1_a_CONTROL: /* 16-bit access */
736
737 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
738 break;
739
740
741 case PM1_b_CONTROL: /* 16-bit access */
742
743 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
744 break;
745
746
747 case PM2_CONTROL: /* 8-bit access */
748
749 acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
750 break;
751
752
753 case PM_TIMER: /* 32-bit access */
754
755 acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
756 break;
757
758
759 case GPE0_STS_BLOCK: /* 8-bit access */
760
761 bank_offset = REGISTER_BIT_ID(register_id);
762 acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
763 break;
764
765
766 case GPE0_EN_BLOCK: /* 8-bit access */
767
768 bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len) + REGISTER_BIT_ID(register_id);
769 acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
770 break;
771
772
773 case GPE1_STS_BLOCK: /* 8-bit access */
774
775 bank_offset = REGISTER_BIT_ID(register_id);
776 acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
777 break;
778
779
780 case GPE1_EN_BLOCK: /* 8-bit access */
781
782 bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len) + REGISTER_BIT_ID(register_id);
783 acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
784 break;
785
786
787 case SMI_CMD_BLOCK: /* 8bit */
788
789 /* For 2.0, SMI_CMD is always in IO space */
790 /* TBD: what about 1.0? 0.71? */
791
792 acpi_os_write_port (acpi_gbl_FADT->smi_cmd, value, 8);
793 break;
794
795
796 default:
797 value = 0;
798 break;
799 }
800
801
802 if (ACPI_MTX_LOCK == use_lock) {
803 acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
804 }
805
806 return_VOID;
807 }
808
809
810 /******************************************************************************
811 *
812 * FUNCTION: Acpi_hw_low_level_read
813 *
814 * PARAMETERS: Register - GAS register structure
815 * Offset - Offset from the base address in the GAS
816 * Width - 8, 16, or 32
817 *
818 * RETURN: Value read
819 *
820 * DESCRIPTION: Read from either memory, IO, or PCI config space.
821 *
822 ******************************************************************************/
823
824 u32
825 acpi_hw_low_level_read (
826 u32 width,
827 acpi_generic_address *reg,
828 u32 offset)
829 {
830 u32 value = 0;
831 ACPI_PHYSICAL_ADDRESS mem_address;
832 ACPI_IO_ADDRESS io_address;
833 acpi_pci_id pci_id;
834 u16 pci_register;
835
836
837 FUNCTION_ENTRY ();
838
839
840 /*
841 * Must have a valid pointer to a GAS structure, and
842 * a non-zero address within
843 */
844 if ((!reg) ||
845 (!ACPI_VALID_ADDRESS (reg->address))) {
846 return 0;
847 }
848
849
850 /*
851 * Three address spaces supported:
852 * Memory, Io, or PCI config.
853 */
854 switch (reg->address_space_id) {
855 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
856
857 mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
858
859 acpi_os_read_memory (mem_address, &value, width);
860 break;
861
862
863 case ACPI_ADR_SPACE_SYSTEM_IO:
864
865 io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
866
867 acpi_os_read_port (io_address, &value, width);
868 break;
869
870
871 case ACPI_ADR_SPACE_PCI_CONFIG:
872
873 pci_id.segment = 0;
874 pci_id.bus = 0;
875 pci_id.device = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address));
876 pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address));
877 pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset);
878
879 acpi_os_read_pci_configuration (&pci_id, pci_register, &value, width);
880 break;
881 }
882
883 return value;
884 }
885
886
887 /******************************************************************************
888 *
889 * FUNCTION: Acpi_hw_low_level_write
890 *
891 * PARAMETERS: Width - 8, 16, or 32
892 * Value - To be written
893 * Register - GAS register structure
894 * Offset - Offset from the base address in the GAS
895 *
896 *
897 * RETURN: Value read
898 *
899 * DESCRIPTION: Read from either memory, IO, or PCI config space.
900 *
901 ******************************************************************************/
902
903 void
904 acpi_hw_low_level_write (
905 u32 width,
906 u32 value,
907 acpi_generic_address *reg,
908 u32 offset)
909 {
910 ACPI_PHYSICAL_ADDRESS mem_address;
911 ACPI_IO_ADDRESS io_address;
912 acpi_pci_id pci_id;
913 u16 pci_register;
914
915
916 FUNCTION_ENTRY ();
917
918
919 /*
920 * Must have a valid pointer to a GAS structure, and
921 * a non-zero address within
922 */
923 if ((!reg) ||
924 (!ACPI_VALID_ADDRESS (reg->address))) {
925 return;
926 }
927
928
929 /*
930 * Three address spaces supported:
931 * Memory, Io, or PCI config.
932 */
933 switch (reg->address_space_id) {
934 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
935
936 mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
937
938 acpi_os_write_memory (mem_address, value, width);
939 break;
940
941
942 case ACPI_ADR_SPACE_SYSTEM_IO:
943
944 io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
945
946 acpi_os_write_port (io_address, value, width);
947 break;
948
949
950 case ACPI_ADR_SPACE_PCI_CONFIG:
951
952 pci_id.segment = 0;
953 pci_id.bus = 0;
954 pci_id.device = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address));
955 pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address));
956 pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset);
957
958 acpi_os_write_pci_configuration (&pci_id, pci_register, value, width);
959 break;
960 }
961 }
962