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
50u32
51acpi_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
78void
79acpi_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
146acpi_status
147acpi_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
247u32
248acpi_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
586u32
587acpi_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
700void
701acpi_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
829u32
830acpi_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
908void
909acpi_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}
967