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