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