1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <sys/asm_linkage.h>
27#include <sys/asm_misc.h>
28
29#if defined(lint) || defined(__lint)
30#include <sys/types.h>
31#include "acpi.h"
32#endif	/* lint */
33
34/*
35 * Implementation as specific by ACPI 3.0 specification
36 * section 5.2.10.1
37 *
38 * Global Lock Structure within the FACS
39 *
40 * |-----------------------------------------------------------------------|
41 * |  Field  | Bit Length | Bit Offset |           Description             |
42 * |---------|------------|------------|-----------------------------------|
43 * | Pending |     1      |     0      | Non-zero indicates that a request |
44 * |         |            |            | for ownership of the global lock  |
45 * |         |            |            | is pending.                       |
46 * |---------|------------|------------|-----------------------------------|
47 * | Owned   |     1      |     1      | Non-zero indicates that the Global|
48 * |         |            |            | lock is owned.                    |
49 * |---------|------------|------------|-----------------------------------|
50 * | Reserved|     30     |     2      | Reserved for future use           |
51 * |---------|------------|------------|-----------------------------------|
52 */
53
54/* Offset of GlobalLock element in FACS structure */
55#define	GlobalLock	0x10
56
57#if defined(lint) || defined(__lint)
58
59/* ARGSUSED */
60UINT32
61__acpi_acquire_global_lock(void *Facs)
62{ return (0); }
63
64#else	/* lint */
65
66#if defined(__amd64)
67	ENTRY(__acpi_acquire_global_lock)
68	movq	$0xff, %rax		/ error return if FACS is null
69	orq	%rdi, %rdi		/ %rdi contains pointer to FACS
70	jz	1f
71	leaq	GlobalLock(%rdi), %rdi	/ make %rdi point at the lock
720:
73	movl	(%rdi), %eax		/ get current value of Global Lock
74	movl	%eax, %edx
75	andl	$0xFFFFFFFE, %edx	/ Clear pending bit
76	btsl	$1, %edx		/ Check and set owner bit
77	adcl	$0, %edx		/ If owned, set pending bit
78	lock
79	cmpxchgl %edx, (%rdi)		/ Attempt to set new value
80	jnz	0b			/ If not set, try again
81	cmpb	$3, %dl			/ Was it acquired or marked pending?
82	sbbq	%rax, %rax		/ acquired = -1, pending = 0
831:
84	ret
85	SET_SIZE(__acpi_acquire_global_lock)
86
87#elif defined(__i386)
88
89	ENTRY(__acpi_acquire_global_lock)
90	movl	$0xff, %eax		/ error return if FACS is null
91	movl	4(%esp), %ecx		/ %ecx contains pointer to FACS
92	orl	%ecx, %ecx
93	jz	1f
94	leal	GlobalLock(%ecx), %ecx	/ make %ecx point at the lock
950:
96	movl	(%ecx), %eax
97	movl	%eax, %edx
98	andl	$0xFFFFFFFE, %edx
99	btsl	$1, %edx
100	adcl	$0, %edx
101	lock
102	cmpxchgl %edx, (%ecx)
103	jnz	0b
104	cmpb	$3, %dl
105	sbbl	%eax, %eax
1061:
107	ret
108	SET_SIZE(__acpi_acquire_global_lock)
109
110#endif	/* i386 */
111
112#endif	/* lint */
113
114
115#if defined(lint) || defined(__lint)
116
117/* ARGSUSED */
118UINT32
119__acpi_release_global_lock(void *Facs)
120{ return (0); }
121
122#else	/* lint */
123
124#if defined(__amd64)
125	ENTRY(__acpi_release_global_lock)
126	xorq	%rax, %rax	/ error return if FACS is null
127	orq	%rdi, %rdi	/ %rdi contains pointer to FACS
128	jz	1f
129	leaq	GlobalLock(%rdi), %rdi	/ make %rdi point at the lock
1300:
131	movl	(%rdi), %eax
132	movl	%eax, %edx
133	andl	$0xFFFFFFFC, %edx
134	lock
135	cmpxchgl %edx, (%rdi)
136	jnz	0b
137	andq	$1, %rax
1381:
139	ret
140	SET_SIZE(__acpi_release_global_lock)
141
142#elif defined(__i386)
143
144	ENTRY(__acpi_release_global_lock)
145	xorl	%eax, %eax		/ error return if FACS is null
146	movl	4(%esp), %ecx		/ %ecx contains pointer to FACS
147	orl	%ecx, %ecx
148	jz	1f
149	leal	GlobalLock(%ecx), %ecx	/ make %ecx point at the lock
1500:
151	movl	(%ecx), %eax
152	movl	%eax, %edx
153	andl	$0xFFFFFFFC, %edx
154	lock
155	cmpxchgl %edx, (%ecx)
156	jnz	0b
157	andl	$1, %eax
1581:
159	ret
160	SET_SIZE(__acpi_release_global_lock)
161
162#endif	/* i386 */
163
164#endif	/* lint */
165
166
167/*
168 * execute WBINVD instruction
169 */
170
171#if defined(lint) || defined(__lint)
172
173/* ARGSUSED */
174void
175__acpi_wbinvd(void)
176{ }
177
178#else	/* lint */
179
180	ENTRY(__acpi_wbinvd)
181	wbinvd
182	ret
183	SET_SIZE(__acpi_wbinvd)
184
185#endif	/* lint */
186
187