import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / 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: 1.1.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 /*******************************************************************************
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 %8.8X%8.8X\n",
457                         register_value, HIDWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address),
458                         LODWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address)));
459
460                 if (read_write == ACPI_WRITE) {
461                         register_value &= ~mask;
462                         value          <<= acpi_hw_get_bit_shift (mask);
463                         value          &= mask;
464                         register_value |= value;
465
466                         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
467                                 register_value,
468                                 HIDWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address),
469                                 LODWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address)));
470
471                         acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
472                                            PM2_CONTROL, (u8) (register_value));
473                 }
474                 break;
475
476
477         case PM_TIMER:
478
479                 mask = TMR_VAL_MASK;
480                 register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
481                                  PM_TIMER);
482                 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM_TIMER: Read %X from %8.8X%8.8X\n",
483                         register_value,
484                         HIDWORD(acpi_gbl_FADT->Xpm_tmr_blk.address),
485                         LODWORD(acpi_gbl_FADT->Xpm_tmr_blk.address)));
486
487                 break;
488
489
490         case GPE1_EN_BLOCK:
491         case GPE1_STS_BLOCK:
492         case GPE0_EN_BLOCK:
493         case GPE0_STS_BLOCK:
494
495                 /* Determine the bit to be accessed
496                  *
497                  *  (u32) Register_id:
498                  *      31      24       16       8        0
499                  *      +--------+--------+--------+--------+
500                  *      |  gpe_block_id   |  gpe_bit_number |
501                  *      +--------+--------+--------+--------+
502                  *
503                  *     gpe_block_id is one of GPE[01]_EN_BLOCK and GPE[01]_STS_BLOCK
504                  *     gpe_bit_number is relative from the gpe_block (0x00~0xFF)
505                  */
506                 mask = REGISTER_BIT_ID(register_id); /* gpe_bit_number */
507                 register_id = REGISTER_BLOCK_ID(register_id) | (mask >> 3);
508                 mask = acpi_gbl_decode_to8bit [mask % 8];
509
510                 /*
511                  * The base address of the GPE 0 Register Block
512                  * Plus 1/2 the length of the GPE 0 Register Block
513                  * The enable Register is the Register following the Status Register
514                  * and each Register is defined as 1/2 of the total Register Block
515                  */
516
517                 /*
518                  * This sets the bit within Enable_bit that needs to be written to
519                  * the Register indicated in Mask to a 1, all others are 0
520                  */
521
522                 /* Now get the current Enable Bits in the selected Reg */
523
524                 register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, register_id);
525                 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "GPE Enable bits: Read %X from %X\n",
526                         register_value, register_id));
527
528                 if (read_write == ACPI_WRITE) {
529                         register_value &= ~mask;
530                         value          <<= acpi_hw_get_bit_shift (mask);
531                         value          &= mask;
532                         register_value |= value;
533
534                         /*
535                          * This write will put the Action state into the General Purpose
536                          * Enable Register indexed by the value in Mask
537                          */
538                         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
539                                 register_value, register_id));
540                         acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id,
541                                 (u8) register_value);
542                         register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
543                                            register_id);
544                 }
545                 break;
546
547
548         case SMI_CMD_BLOCK:
549         case PROCESSOR_BLOCK:
550
551                 /* Not used by any callers at this time - therefore, not implemented */
552
553         default:
554
555                 mask = 0;
556                 break;
557         }
558
559         if (ACPI_MTX_LOCK == use_lock) {
560                 acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
561         }
562
563
564         register_value &= mask;
565         register_value >>= acpi_hw_get_bit_shift (mask);
566
567         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Register I/O: returning %X\n", register_value));
568         return_VALUE (register_value);
569 }
570
571
572 /******************************************************************************
573  *
574  * FUNCTION:    Acpi_hw_register_read
575  *
576  * PARAMETERS:  Use_lock               - Mutex hw access.
577  *              Register_id            - Register_iD + Offset.
578  *
579  * RETURN:      Value read or written.
580  *
581  * DESCRIPTION: Acpi register read function.  Registers are read at the
582  *              given offset.
583  *
584  ******************************************************************************/
585
586 u32
587 acpi_hw_register_read (
588         u8                      use_lock,
589         u32                     register_id)
590 {
591         u32                     value = 0;
592         u32                     bank_offset;
593
594
595         FUNCTION_TRACE ("Hw_register_read");
596
597
598         if (ACPI_MTX_LOCK == use_lock) {
599                 acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
600         }
601
602
603         switch (REGISTER_BLOCK_ID(register_id)) {
604         case PM1_STS: /* 16-bit access */
605
606                 value =  acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, 0);
607                 value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, 0);
608                 break;
609
610
611         case PM1_EN: /* 16-bit access*/
612
613                 bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len);
614                 value =  acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset);
615                 value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset);
616                 break;
617
618
619         case PM1_CONTROL: /* 16-bit access */
620
621                 value =  acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
622                 value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
623                 break;
624
625
626         case PM2_CONTROL: /* 8-bit access */
627
628                 value =  acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
629                 break;
630
631
632         case PM_TIMER: /* 32-bit access */
633
634                 value =  acpi_hw_low_level_read (32, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
635                 break;
636
637
638         /*
639          * For the GPE? Blocks, the lower word of Register_id contains the
640          * byte offset for which to read, as each part of each block may be
641          * several bytes long.
642          */
643         case GPE0_STS_BLOCK: /* 8-bit access */
644
645                 bank_offset = REGISTER_BIT_ID(register_id);
646                 value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
647                 break;
648
649         case GPE0_EN_BLOCK: /* 8-bit access */
650
651                 bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len) + REGISTER_BIT_ID(register_id);
652                 value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
653                 break;
654
655         case GPE1_STS_BLOCK: /* 8-bit access */
656
657                 bank_offset = REGISTER_BIT_ID(register_id);
658                 value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
659                 break;
660
661         case GPE1_EN_BLOCK: /* 8-bit access */
662
663                 bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len) + REGISTER_BIT_ID(register_id);
664                 value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
665                 break;
666
667         case SMI_CMD_BLOCK: /* 8bit */
668
669                 acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value, 8);
670                 break;
671
672         default:
673                 /* Value will be returned as 0 */
674                 break;
675         }
676
677
678         if (ACPI_MTX_LOCK == use_lock) {
679                 acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
680         }
681
682         return_VALUE (value);
683 }
684
685
686 /******************************************************************************
687  *
688  * FUNCTION:    Acpi_hw_register_write
689  *
690  * PARAMETERS:  Use_lock               - Mutex hw access.
691  *              Register_id            - Register_iD + Offset.
692  *
693  * RETURN:      Value read or written.
694  *
695  * DESCRIPTION: Acpi register Write function.  Registers are written at the
696  *              given offset.
697  *
698  ******************************************************************************/
699
700 void
701 acpi_hw_register_write (
702         u8                      use_lock,
703         u32                     register_id,
704         u32                     value)
705 {
706         u32                     bank_offset;
707
708
709         FUNCTION_TRACE ("Hw_register_write");
710
711
712         if (ACPI_MTX_LOCK == use_lock) {
713                 acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
714         }
715
716
717         switch (REGISTER_BLOCK_ID (register_id)) {
718         case PM1_STS: /* 16-bit access */
719
720                 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, 0);
721                 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, 0);
722                 break;
723
724
725         case PM1_EN: /* 16-bit access*/
726
727                 bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len);
728                 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset);
729                 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset);
730                 break;
731
732
733         case PM1_CONTROL: /* 16-bit access */
734
735                 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
736                 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
737                 break;
738
739
740         case PM1A_CONTROL: /* 16-bit access */
741
742                 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
743                 break;
744
745
746         case PM1B_CONTROL: /* 16-bit access */
747
748                 acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
749                 break;
750
751
752         case PM2_CONTROL: /* 8-bit access */
753
754                 acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
755                 break;
756
757
758         case PM_TIMER: /* 32-bit access */
759
760                 acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
761                 break;
762
763
764         case GPE0_STS_BLOCK: /* 8-bit access */
765
766                 bank_offset = REGISTER_BIT_ID(register_id);
767                 acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
768                 break;
769
770
771         case GPE0_EN_BLOCK: /* 8-bit access */
772
773                 bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len) + REGISTER_BIT_ID(register_id);
774                 acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
775                 break;
776
777
778         case GPE1_STS_BLOCK: /* 8-bit access */
779
780                 bank_offset = REGISTER_BIT_ID(register_id);
781                 acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
782                 break;
783
784
785         case GPE1_EN_BLOCK: /* 8-bit access */
786
787                 bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len) + REGISTER_BIT_ID(register_id);
788                 acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
789                 break;
790
791
792         case SMI_CMD_BLOCK: /* 8bit */
793
794                 /* For 2.0, SMI_CMD is always in IO space */
795                 /* TBD: what about 1.0? 0.71? */
796
797                 acpi_os_write_port (acpi_gbl_FADT->smi_cmd, value, 8);
798                 break;
799
800
801         default:
802                 value = 0;
803                 break;
804         }
805
806
807         if (ACPI_MTX_LOCK == use_lock) {
808                 acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
809         }
810
811         return_VOID;
812 }
813
814
815 /******************************************************************************
816  *
817  * FUNCTION:    Acpi_hw_low_level_read
818  *
819  * PARAMETERS:  Register            - GAS register structure
820  *              Offset              - Offset from the base address in the GAS
821  *              Width               - 8, 16, or 32
822  *
823  * RETURN:      Value read
824  *
825  * DESCRIPTION: Read from either memory, IO, or PCI config space.
826  *
827  ******************************************************************************/
828
829 u32
830 acpi_hw_low_level_read (
831         u32                     width,
832         acpi_generic_address    *reg,
833         u32                     offset)
834 {
835         u32                     value = 0;
836         ACPI_PHYSICAL_ADDRESS   mem_address;
837         ACPI_IO_ADDRESS         io_address;
838         acpi_pci_id             pci_id;
839         u16                     pci_register;
840
841
842         FUNCTION_ENTRY ();
843
844
845         /*
846          * Must have a valid pointer to a GAS structure, and
847          * a non-zero address within
848          */
849         if ((!reg) ||
850                 (!ACPI_VALID_ADDRESS (reg->address))) {
851                 return 0;
852         }
853
854
855         /*
856          * Three address spaces supported:
857          * Memory, Io, or PCI config.
858          */
859         switch (reg->address_space_id) {
860         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
861
862                 mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
863
864                 acpi_os_read_memory (mem_address, &value, width);
865                 break;
866
867
868         case ACPI_ADR_SPACE_SYSTEM_IO:
869
870                 io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
871
872                 acpi_os_read_port (io_address, &value, width);
873                 break;
874
875
876         case ACPI_ADR_SPACE_PCI_CONFIG:
877
878                 pci_id.segment = 0;
879                 pci_id.bus     = 0;
880                 pci_id.device  = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address));
881                 pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address));
882                 pci_register   = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset);
883
884                 acpi_os_read_pci_configuration (&pci_id, pci_register, &value, width);
885                 break;
886         }
887
888         return value;
889 }
890
891
892 /******************************************************************************
893  *
894  * FUNCTION:    Acpi_hw_low_level_write
895  *
896  * PARAMETERS:  Width               - 8, 16, or 32
897  *              Value               - To be written
898  *              Register            - GAS register structure
899  *              Offset              - Offset from the base address in the GAS
900  *
901  *
902  * RETURN:      Value read
903  *
904  * DESCRIPTION: Read from either memory, IO, or PCI config space.
905  *
906  ******************************************************************************/
907
908 void
909 acpi_hw_low_level_write (
910         u32                     width,
911         u32                     value,
912         acpi_generic_address    *reg,
913         u32                     offset)
914 {
915         ACPI_PHYSICAL_ADDRESS   mem_address;
916         ACPI_IO_ADDRESS         io_address;
917         acpi_pci_id             pci_id;
918         u16                     pci_register;
919
920
921         FUNCTION_ENTRY ();
922
923
924         /*
925          * Must have a valid pointer to a GAS structure, and
926          * a non-zero address within
927          */
928         if ((!reg) ||
929                 (!ACPI_VALID_ADDRESS (reg->address))) {
930                 return;
931         }
932
933
934         /*
935          * Three address spaces supported:
936          * Memory, Io, or PCI config.
937          */
938         switch (reg->address_space_id) {
939         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
940
941                 mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
942
943                 acpi_os_write_memory (mem_address, value, width);
944                 break;
945
946
947         case ACPI_ADR_SPACE_SYSTEM_IO:
948
949                 io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
950
951                 acpi_os_write_port (io_address, value, width);
952                 break;
953
954
955         case ACPI_ADR_SPACE_PCI_CONFIG:
956
957                 pci_id.segment = 0;
958                 pci_id.bus     = 0;
959                 pci_id.device  = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address));
960                 pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address));
961                 pci_register   = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset);
962
963                 acpi_os_write_pci_configuration (&pci_id, pci_register, value, width);
964                 break;
965         }
966 }