aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/acpi
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Kconfig356
-rw-r--r--drivers/acpi/Makefile58
-rw-r--r--drivers/acpi/ac.c354
-rw-r--r--drivers/acpi/acpi_memhotplug.c542
-rw-r--r--drivers/acpi/asus_acpi.c1236
-rw-r--r--drivers/acpi/battery.c846
-rw-r--r--drivers/acpi/blacklist.c169
-rw-r--r--drivers/acpi/bus.c775
-rw-r--r--drivers/acpi/button.c558
-rw-r--r--drivers/acpi/container.c303
-rw-r--r--drivers/acpi/debug.c233
-rw-r--r--drivers/acpi/dispatcher/Makefile9
-rw-r--r--drivers/acpi/dispatcher/dsfield.c601
-rw-r--r--drivers/acpi/dispatcher/dsinit.c235
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c597
-rw-r--r--drivers/acpi/dispatcher/dsmthdat.c715
-rw-r--r--drivers/acpi/dispatcher/dsobject.c618
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c1151
-rw-r--r--drivers/acpi/dispatcher/dsutils.c744
-rw-r--r--drivers/acpi/dispatcher/dswexec.c751
-rw-r--r--drivers/acpi/dispatcher/dswload.c976
-rw-r--r--drivers/acpi/dispatcher/dswscope.c229
-rw-r--r--drivers/acpi/dispatcher/dswstate.c1100
-rw-r--r--drivers/acpi/ec.c1024
-rw-r--r--drivers/acpi/event.c140
-rw-r--r--drivers/acpi/events/Makefile9
-rw-r--r--drivers/acpi/events/evevent.c297
-rw-r--r--drivers/acpi/events/evgpe.c756
-rw-r--r--drivers/acpi/events/evgpeblk.c1141
-rw-r--r--drivers/acpi/events/evmisc.c588
-rw-r--r--drivers/acpi/events/evregion.c1067
-rw-r--r--drivers/acpi/events/evrgnini.c580
-rw-r--r--drivers/acpi/events/evsci.c199
-rw-r--r--drivers/acpi/events/evxface.c834
-rw-r--r--drivers/acpi/events/evxfevnt.c778
-rw-r--r--drivers/acpi/events/evxfregn.c247
-rw-r--r--drivers/acpi/executer/Makefile10
-rw-r--r--drivers/acpi/executer/exconfig.c487
-rw-r--r--drivers/acpi/executer/exconvrt.c708
-rw-r--r--drivers/acpi/executer/excreate.c646
-rw-r--r--drivers/acpi/executer/exdump.c793
-rw-r--r--drivers/acpi/executer/exfield.c367
-rw-r--r--drivers/acpi/executer/exfldio.c835
-rw-r--r--drivers/acpi/executer/exmisc.c738
-rw-r--r--drivers/acpi/executer/exmutex.c363
-rw-r--r--drivers/acpi/executer/exnames.c427
-rw-r--r--drivers/acpi/executer/exoparg1.c1013
-rw-r--r--drivers/acpi/executer/exoparg2.c608
-rw-r--r--drivers/acpi/executer/exoparg3.c256
-rw-r--r--drivers/acpi/executer/exoparg6.c336
-rw-r--r--drivers/acpi/executer/exprep.c530
-rw-r--r--drivers/acpi/executer/exregion.c528
-rw-r--r--drivers/acpi/executer/exresnte.c289
-rw-r--r--drivers/acpi/executer/exresolv.c546
-rw-r--r--drivers/acpi/executer/exresop.c661
-rw-r--r--drivers/acpi/executer/exstore.c536
-rw-r--r--drivers/acpi/executer/exstoren.c306
-rw-r--r--drivers/acpi/executer/exstorob.c216
-rw-r--r--drivers/acpi/executer/exsystem.c378
-rw-r--r--drivers/acpi/executer/exutils.c378
-rw-r--r--drivers/acpi/fan.c302
-rw-r--r--drivers/acpi/hardware/Makefile9
-rw-r--r--drivers/acpi/hardware/hwacpi.c230
-rw-r--r--drivers/acpi/hardware/hwgpe.c444
-rw-r--r--drivers/acpi/hardware/hwregs.c850
-rw-r--r--drivers/acpi/hardware/hwsleep.c582
-rw-r--r--drivers/acpi/hardware/hwtimer.c203
-rw-r--r--drivers/acpi/ibm_acpi.c1242
-rw-r--r--drivers/acpi/motherboard.c177
-rw-r--r--drivers/acpi/namespace/Makefile12
-rw-r--r--drivers/acpi/namespace/nsaccess.c637
-rw-r--r--drivers/acpi/namespace/nsalloc.c685
-rw-r--r--drivers/acpi/namespace/nsdump.c673
-rw-r--r--drivers/acpi/namespace/nsdumpdv.c146
-rw-r--r--drivers/acpi/namespace/nseval.c487
-rw-r--r--drivers/acpi/namespace/nsinit.c441
-rw-r--r--drivers/acpi/namespace/nsload.c460
-rw-r--r--drivers/acpi/namespace/nsnames.c265
-rw-r--r--drivers/acpi/namespace/nsobject.c461
-rw-r--r--drivers/acpi/namespace/nsparse.c171
-rw-r--r--drivers/acpi/namespace/nssearch.c381
-rw-r--r--drivers/acpi/namespace/nsutils.c1069
-rw-r--r--drivers/acpi/namespace/nswalk.c289
-rw-r--r--drivers/acpi/namespace/nsxfeval.c764
-rw-r--r--drivers/acpi/namespace/nsxfname.c369
-rw-r--r--drivers/acpi/namespace/nsxfobj.c262
-rw-r--r--drivers/acpi/numa.c213
-rw-r--r--drivers/acpi/osl.c1162
-rw-r--r--drivers/acpi/parser/Makefile8
-rw-r--r--drivers/acpi/parser/psargs.c746
-rw-r--r--drivers/acpi/parser/psopcode.c778
-rw-r--r--drivers/acpi/parser/psparse.c1266
-rw-r--r--drivers/acpi/parser/psscope.c290
-rw-r--r--drivers/acpi/parser/pstree.c327
-rw-r--r--drivers/acpi/parser/psutils.c309
-rw-r--r--drivers/acpi/parser/pswalk.c115
-rw-r--r--drivers/acpi/parser/psxface.c243
-rw-r--r--drivers/acpi/pci_bind.c384
-rw-r--r--drivers/acpi/pci_irq.c518
-rw-r--r--drivers/acpi/pci_link.c904
-rw-r--r--drivers/acpi/pci_root.c347
-rw-r--r--drivers/acpi/power.c692
-rw-r--r--drivers/acpi/processor_core.c989
-rw-r--r--drivers/acpi/processor_idle.c1017
-rw-r--r--drivers/acpi/processor_perflib.c666
-rw-r--r--drivers/acpi/processor_thermal.c406
-rw-r--r--drivers/acpi/processor_throttling.c351
-rw-r--r--drivers/acpi/resources/Makefile10
-rw-r--r--drivers/acpi/resources/rsaddr.c1225
-rw-r--r--drivers/acpi/resources/rscalc.c841
-rw-r--r--drivers/acpi/resources/rscreate.c428
-rw-r--r--drivers/acpi/resources/rsdump.c1150
-rw-r--r--drivers/acpi/resources/rsio.c545
-rw-r--r--drivers/acpi/resources/rsirq.c592
-rw-r--r--drivers/acpi/resources/rslist.c518
-rw-r--r--drivers/acpi/resources/rsmemory.c566
-rw-r--r--drivers/acpi/resources/rsmisc.c597
-rw-r--r--drivers/acpi/resources/rsutils.c356
-rw-r--r--drivers/acpi/resources/rsxface.c437
-rw-r--r--drivers/acpi/scan.c1379
-rw-r--r--drivers/acpi/sleep/Makefile5
-rw-r--r--drivers/acpi/sleep/main.c234
-rw-r--r--drivers/acpi/sleep/poweroff.c39
-rw-r--r--drivers/acpi/sleep/proc.c509
-rw-r--r--drivers/acpi/sleep/sleep.h8
-rw-r--r--drivers/acpi/sleep/wakeup.c209
-rw-r--r--drivers/acpi/system.c187
-rw-r--r--drivers/acpi/tables.c609
-rw-r--r--drivers/acpi/tables/Makefile8
-rw-r--r--drivers/acpi/tables/tbconvrt.c564
-rw-r--r--drivers/acpi/tables/tbget.c493
-rw-r--r--drivers/acpi/tables/tbgetall.c313
-rw-r--r--drivers/acpi/tables/tbinstal.c553
-rw-r--r--drivers/acpi/tables/tbrsdt.c324
-rw-r--r--drivers/acpi/tables/tbutils.c240
-rw-r--r--drivers/acpi/tables/tbxface.c448
-rw-r--r--drivers/acpi/tables/tbxfroot.c606
-rw-r--r--drivers/acpi/thermal.c1445
-rw-r--r--drivers/acpi/toshiba_acpi.c575
-rw-r--r--drivers/acpi/utilities/Makefile8
-rw-r--r--drivers/acpi/utilities/utalloc.c988
-rw-r--r--drivers/acpi/utilities/utcopy.c930
-rw-r--r--drivers/acpi/utilities/utdebug.c624
-rw-r--r--drivers/acpi/utilities/utdelete.c700
-rw-r--r--drivers/acpi/utilities/uteval.c696
-rw-r--r--drivers/acpi/utilities/utglobal.c935
-rw-r--r--drivers/acpi/utilities/utinit.c266
-rw-r--r--drivers/acpi/utilities/utmath.c333
-rw-r--r--drivers/acpi/utilities/utmisc.c1516
-rw-r--r--drivers/acpi/utilities/utobject.c671
-rw-r--r--drivers/acpi/utilities/utxface.c525
-rw-r--r--drivers/acpi/utils.c423
-rw-r--r--drivers/acpi/video.c1989
153 files changed, 82730 insertions, 0 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
new file mode 100644
index 000000000000..0400a52d5085
--- /dev/null
+++ b/drivers/acpi/Kconfig
@@ -0,0 +1,356 @@
1#
2# ACPI Configuration
3#
4
5menu "ACPI (Advanced Configuration and Power Interface) Support"
6 depends on !X86_VISWS
7 depends on !IA64_HP_SIM
8 depends on IA64 || X86
9
10config ACPI
11 bool "ACPI Support"
12 depends on IA64 || X86
13
14 default y
15 ---help---
16 Advanced Configuration and Power Interface (ACPI) support for
17 Linux requires an ACPI compliant platform (hardware/firmware),
18 and assumes the presence of OS-directed configuration and power
19 management (OSPM) software. This option will enlarge your
20 kernel by about 70K.
21
22 Linux ACPI provides a robust functional replacement for several
23 legacy configuration and power management interfaces, including
24 the Plug-and-Play BIOS specification (PnP BIOS), the
25 MultiProcessor Specification (MPS), and the Advanced Power
26 Management (APM) specification. If both ACPI and APM support
27 are configured, whichever is loaded first shall be used.
28
29 The ACPI SourceForge project contains the latest source code,
30 documentation, tools, mailing list subscription, and other
31 information. This project is available at:
32 <http://sourceforge.net/projects/acpi>
33
34 Linux support for ACPI is based on Intel Corporation's ACPI
35 Component Architecture (ACPI CA). For more information see:
36 <http://developer.intel.com/technology/iapc/acpi>
37
38 ACPI is an open industry specification co-developed by Compaq,
39 Intel, Microsoft, Phoenix, and Toshiba. The specification is
40 available at:
41 <http://www.acpi.info>
42
43config ACPI_BOOT
44 bool
45 depends on ACPI || X86_HT
46 default y
47
48if ACPI
49
50config ACPI_INTERPRETER
51 bool
52 depends on !IA64_SGI_SN
53 default y
54
55if ACPI_INTERPRETER
56
57config ACPI_SLEEP
58 bool "Sleep States (EXPERIMENTAL)"
59 depends on X86
60 depends on EXPERIMENTAL && PM
61 default y
62 ---help---
63 This option adds support for ACPI suspend states.
64
65 With this option, you will be able to put the system "to sleep".
66 Sleep states are low power states for the system and devices. All
67 of the system operating state is saved to either memory or disk
68 (depending on the state), to allow the system to resume operation
69 quickly at your request.
70
71 Although this option sounds really nifty, barely any of the device
72 drivers have been converted to the new driver model and hence few
73 have proper power management support.
74
75 This option is not recommended for anyone except those doing driver
76 power management development.
77
78config ACPI_SLEEP_PROC_FS
79 bool
80 depends on ACPI_SLEEP && PROC_FS
81 default y
82
83config ACPI_AC
84 tristate "AC Adapter"
85 depends on X86
86 default m
87 help
88 This driver adds support for the AC Adapter object, which indicates
89 whether a system is on AC, or not. Typically, only mobile systems
90 have this object, since desktops are always on AC.
91
92config ACPI_BATTERY
93 tristate "Battery"
94 depends on X86
95 default m
96 help
97 This driver adds support for battery information through
98 /proc/acpi/battery. If you have a mobile system with a battery,
99 say Y.
100
101config ACPI_BUTTON
102 tristate "Button"
103 depends on !IA64_SGI_SN
104 default m
105 help
106 This driver registers for events based on buttons, such as the
107 power, sleep, and lid switch. In the future, a daemon will read
108 /proc/acpi/event and perform user-defined actions such as shutting
109 down the system. Until then, you can cat it, and see output when
110 a button is pressed.
111
112config ACPI_VIDEO
113 tristate "Video"
114 depends on EXPERIMENTAL
115 depends on !IA64_SGI_SN
116 default m
117 help
118 This driver implement the ACPI Extensions For Display Adapters
119 for integrated graphics devices on motherboard, as specified in
120 ACPI 2.0 Specification, Appendix B, allowing to perform some basic
121 control like defining the video POST device, retrieving EDID information
122 or to setup a video output, etc.
123 Note that this is an ref. implementation only. It may or may not work
124 for your integrated video device.
125
126config ACPI_FAN
127 tristate "Fan"
128 depends on !IA64_SGI_SN
129 default m
130 help
131 This driver adds support for ACPI fan devices, allowing user-mode
132 applications to perform basic fan control (on, off, status).
133
134config ACPI_PROCESSOR
135 tristate "Processor"
136 depends on !IA64_SGI_SN
137 default m
138 help
139 This driver installs ACPI as the idle handler for Linux, and uses
140 ACPI C2 and C3 processor states to save power, on systems that
141 support it.
142
143config ACPI_HOTPLUG_CPU
144 bool "Processor Hotplug (EXPERIMENTAL)"
145 depends on ACPI_PROCESSOR && HOTPLUG_CPU && EXPERIMENTAL
146 depends on !IA64_SGI_SN
147 select ACPI_CONTAINER
148 default n
149 ---help---
150 Select this option if your platform support physical CPU hotplug.
151
152config ACPI_THERMAL
153 tristate "Thermal Zone"
154 depends on ACPI_PROCESSOR
155 default m
156 help
157 This driver adds support for ACPI thermal zones. Most mobile and
158 some desktop systems support ACPI thermal zones. It is HIGHLY
159 recommended that this option be enabled, as your processor(s)
160 may be damaged without it.
161
162config ACPI_NUMA
163 bool "NUMA support"
164 depends on NUMA
165 depends on (IA64 || X86_64)
166 default y if IA64_GENERIC || IA64_SGI_SN2
167
168config ACPI_ASUS
169 tristate "ASUS/Medion Laptop Extras"
170 depends on X86
171 default m
172 ---help---
173 This driver provides support for extra features of ACPI-compatible
174 ASUS laptops. As some of Medion laptops are made by ASUS, it may also
175 support some Medion laptops (such as 9675 for example). It makes all
176 the extra buttons generate standard ACPI events that go through
177 /proc/acpi/events, and (on some models) adds support for changing the
178 display brightness and output, switching the LCD backlight on and off,
179 and most importantly, allows you to blink those fancy LEDs intended
180 for reporting mail and wireless status.
181
182 Note: display switching code is currently considered EXPERIMENTAL,
183 toying with these values may even lock your machine.
184
185 All settings are changed via /proc/acpi/asus directory entries. Owner
186 and group for these entries can be set with asus_uid and asus_gid
187 parameters.
188
189 More information and a userspace daemon for handling the extra buttons
190 at <http://sourceforge.net/projects/acpi4asus/>.
191
192 If you have an ACPI-compatible ASUS laptop, say Y or M here. This
193 driver is still under development, so if your laptop is unsupported or
194 something works not quite as expected, please use the mailing list
195 available on the above page (acpi4asus-user@lists.sourceforge.net)
196
197config ACPI_IBM
198 tristate "IBM ThinkPad Laptop Extras"
199 depends on X86
200 default m
201 ---help---
202 This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
203 support for Fn-Fx key combinations, Bluetooth control, video
204 output switching, ThinkLight control, UltraBay eject and more.
205 For more information about this driver see <file:Documentation/ibm-acpi.txt>
206 and <http://ibm-acpi.sf.net/> .
207
208 If you have an IBM ThinkPad laptop, say Y or M here.
209
210config ACPI_TOSHIBA
211 tristate "Toshiba Laptop Extras"
212 depends on X86
213 default m
214 ---help---
215 This driver adds support for access to certain system settings
216 on "legacy free" Toshiba laptops. These laptops can be recognized by
217 their lack of a BIOS setup menu and APM support.
218
219 On these machines, all system configuration is handled through the
220 ACPI. This driver is required for access to controls not covered
221 by the general ACPI drivers, such as LCD brightness, video output,
222 etc.
223
224 This driver differs from the non-ACPI Toshiba laptop driver (located
225 under "Processor type and features") in several aspects.
226 Configuration is accessed by reading and writing text files in the
227 /proc tree instead of by program interface to /dev. Furthermore, no
228 power management functions are exposed, as those are handled by the
229 general ACPI drivers.
230
231 More information about this driver is available at
232 <http://memebeam.org/toys/ToshibaAcpiDriver>.
233
234 If you have a legacy free Toshiba laptop (such as the Libretto L1
235 series), say Y.
236
237config ACPI_CUSTOM_DSDT
238 bool "Include Custom DSDT"
239 depends on !STANDALONE
240 default n
241 help
242 Thist option is to load a custom ACPI DSDT
243 If you don't know what that is, say N.
244
245config ACPI_CUSTOM_DSDT_FILE
246 string "Custom DSDT Table file to include"
247 depends on ACPI_CUSTOM_DSDT
248 default ""
249 help
250 Enter the full path name to the file wich includes the AmlCode declaration.
251
252config ACPI_BLACKLIST_YEAR
253 int "Disable ACPI for systems before Jan 1st this year"
254 depends on ACPI_INTERPRETER
255 default 0
256 help
257 enter a 4-digit year, eg. 2001 to disable ACPI by default
258 on platforms with DMI BIOS date before January 1st that year.
259 "acpi=force" can be used to override this mechanism.
260
261 Enter 0 to disable this mechanism and allow ACPI to
262 run by default no matter what the year. (default)
263
264config ACPI_DEBUG
265 bool "Debug Statements"
266 depends on !IA64_SGI_SN
267 default n
268 help
269 The ACPI driver can optionally report errors with a great deal
270 of verbosity. Saying Y enables these statements. This will increase
271 your kernel size by around 50K.
272
273config ACPI_BUS
274 bool
275 depends on !IA64_SGI_SN
276 default y
277
278config ACPI_EC
279 bool
280 depends on X86
281 default y
282 help
283 This driver is required on some systems for the proper operation of
284 the battery and thermal drivers. If you are compiling for a
285 mobile system, say Y.
286
287config ACPI_POWER
288 bool
289 depends on !IA64_SGI_SN
290 default y
291
292config ACPI_PCI
293 bool
294 depends on !IA64_SGI_SN
295 default PCI
296
297config ACPI_SYSTEM
298 bool
299 depends on !IA64_SGI_SN
300 default y
301 help
302 This driver will enable your system to shut down using ACPI, and
303 dump your ACPI DSDT table using /proc/acpi/dsdt.
304
305endif # ACPI_INTERPRETER
306
307config X86_PM_TIMER
308 bool "Power Management Timer Support"
309 depends on X86
310 depends on ACPI_BOOT && EXPERIMENTAL
311 depends on !X86_64
312 default n
313 help
314 The Power Management Timer is available on all ACPI-capable,
315 in most cases even if ACPI is unusable or blacklisted.
316
317 This timing source is not affected by powermanagement features
318 like aggressive processor idling, throttling, frequency and/or
319 voltage scaling, unlike the commonly used Time Stamp Counter
320 (TSC) timing source.
321
322 So, if you see messages like 'Losing too many ticks!' in the
323 kernel logs, and/or you are using this on a notebook which
324 does not yet have an HPET, you should say "Y" here.
325
326config ACPI_CONTAINER
327 tristate "ACPI0004,PNP0A05 and PNP0A06 Container Driver (EXPERIMENTAL)"
328 depends on EXPERIMENTAL
329 default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
330 ---help---
331 This is the ACPI generic container driver which supports
332 ACPI0004, PNP0A05 and PNP0A06 devices
333
334config ACPI_HOTPLUG_MEMORY
335 tristate "Memory Hotplug"
336 depends on ACPI
337 depends on MEMORY_HOTPLUG
338 default n
339 help
340 This driver adds supports for ACPI Memory Hotplug. This driver
341 provides support for fielding notifications on ACPI memory
342 devices (PNP0C80) which represent memory ranges that may be
343 onlined or offlined during runtime.
344
345 Enabling this driver assumes that your platform hardware
346 and firmware have support for hot-plugging physical memory. If
347 your system does not support physically adding or ripping out
348 memory DIMMs at some platfrom defined granularity (individually
349 or as a bank) at runtime, then you need not enable this driver.
350
351 If one selects "m," this driver can be loaded using the following
352 command:
353 $>modprobe acpi_memhotplug
354endif # ACPI
355
356endmenu
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
new file mode 100644
index 000000000000..65c92e20566d
--- /dev/null
+++ b/drivers/acpi/Makefile
@@ -0,0 +1,58 @@
1#
2# Makefile for the Linux ACPI interpreter
3#
4
5export ACPI_CFLAGS
6
7ACPI_CFLAGS := -Os
8
9ifdef CONFIG_ACPI_DEBUG
10 ACPI_CFLAGS += -DACPI_DEBUG_OUTPUT
11endif
12
13EXTRA_CFLAGS += $(ACPI_CFLAGS)
14
15#
16# ACPI Boot-Time Table Parsing
17#
18obj-$(CONFIG_ACPI_BOOT) += tables.o
19obj-$(CONFIG_ACPI_INTERPRETER) += blacklist.o
20
21#
22# ACPI Core Subsystem (Interpreter)
23#
24obj-$(CONFIG_ACPI_INTERPRETER) += osl.o utils.o \
25 dispatcher/ events/ executer/ hardware/ \
26 namespace/ parser/ resources/ tables/ \
27 utilities/
28
29#
30# ACPI Bus and Device Drivers
31#
32processor-objs += processor_core.o processor_throttling.o \
33 processor_idle.o processor_thermal.o
34ifdef CONFIG_CPU_FREQ
35processor-objs += processor_perflib.o
36endif
37
38obj-$(CONFIG_ACPI_BUS) += sleep/
39obj-$(CONFIG_ACPI_BUS) += bus.o
40obj-$(CONFIG_ACPI_AC) += ac.o
41obj-$(CONFIG_ACPI_BATTERY) += battery.o
42obj-$(CONFIG_ACPI_BUTTON) += button.o
43obj-$(CONFIG_ACPI_EC) += ec.o
44obj-$(CONFIG_ACPI_FAN) += fan.o
45obj-$(CONFIG_ACPI_VIDEO) += video.o
46obj-$(CONFIG_ACPI_PCI) += pci_root.o pci_link.o pci_irq.o pci_bind.o
47obj-$(CONFIG_ACPI_POWER) += power.o
48obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
49obj-$(CONFIG_ACPI_CONTAINER) += container.o
50obj-$(CONFIG_ACPI_THERMAL) += thermal.o
51obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
52obj-$(CONFIG_ACPI_DEBUG) += debug.o
53obj-$(CONFIG_ACPI_NUMA) += numa.o
54obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
55obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o
56obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
57obj-$(CONFIG_ACPI_BUS) += scan.o motherboard.o
58obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
new file mode 100644
index 000000000000..23ab761dd721
--- /dev/null
+++ b/drivers/acpi/ac.c
@@ -0,0 +1,354 @@
1/*
2 * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 27 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/types.h>
30#include <linux/proc_fs.h>
31#include <linux/seq_file.h>
32#include <acpi/acpi_bus.h>
33#include <acpi/acpi_drivers.h>
34
35
36#define ACPI_AC_COMPONENT 0x00020000
37#define ACPI_AC_CLASS "ac_adapter"
38#define ACPI_AC_HID "ACPI0003"
39#define ACPI_AC_DRIVER_NAME "ACPI AC Adapter Driver"
40#define ACPI_AC_DEVICE_NAME "AC Adapter"
41#define ACPI_AC_FILE_STATE "state"
42#define ACPI_AC_NOTIFY_STATUS 0x80
43#define ACPI_AC_STATUS_OFFLINE 0x00
44#define ACPI_AC_STATUS_ONLINE 0x01
45#define ACPI_AC_STATUS_UNKNOWN 0xFF
46
47#define _COMPONENT ACPI_AC_COMPONENT
48ACPI_MODULE_NAME ("acpi_ac")
49
50MODULE_AUTHOR("Paul Diefenbaugh");
51MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
52MODULE_LICENSE("GPL");
53
54static int acpi_ac_add (struct acpi_device *device);
55static int acpi_ac_remove (struct acpi_device *device, int type);
56static int acpi_ac_open_fs(struct inode *inode, struct file *file);
57
58static struct acpi_driver acpi_ac_driver = {
59 .name = ACPI_AC_DRIVER_NAME,
60 .class = ACPI_AC_CLASS,
61 .ids = ACPI_AC_HID,
62 .ops = {
63 .add = acpi_ac_add,
64 .remove = acpi_ac_remove,
65 },
66};
67
68struct acpi_ac {
69 acpi_handle handle;
70 unsigned long state;
71};
72
73static struct file_operations acpi_ac_fops = {
74 .open = acpi_ac_open_fs,
75 .read = seq_read,
76 .llseek = seq_lseek,
77 .release = single_release,
78};
79
80/* --------------------------------------------------------------------------
81 AC Adapter Management
82 -------------------------------------------------------------------------- */
83
84static int
85acpi_ac_get_state (
86 struct acpi_ac *ac)
87{
88 acpi_status status = AE_OK;
89
90 ACPI_FUNCTION_TRACE("acpi_ac_get_state");
91
92 if (!ac)
93 return_VALUE(-EINVAL);
94
95 status = acpi_evaluate_integer(ac->handle, "_PSR", NULL, &ac->state);
96 if (ACPI_FAILURE(status)) {
97 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
98 "Error reading AC Adapter state\n"));
99 ac->state = ACPI_AC_STATUS_UNKNOWN;
100 return_VALUE(-ENODEV);
101 }
102
103 return_VALUE(0);
104}
105
106
107/* --------------------------------------------------------------------------
108 FS Interface (/proc)
109 -------------------------------------------------------------------------- */
110
111static struct proc_dir_entry *acpi_ac_dir;
112
113static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
114{
115 struct acpi_ac *ac = (struct acpi_ac *) seq->private;
116
117 ACPI_FUNCTION_TRACE("acpi_ac_seq_show");
118
119 if (!ac)
120 return_VALUE(0);
121
122 if (acpi_ac_get_state(ac)) {
123 seq_puts(seq, "ERROR: Unable to read AC Adapter state\n");
124 return_VALUE(0);
125 }
126
127 seq_puts(seq, "state: ");
128 switch (ac->state) {
129 case ACPI_AC_STATUS_OFFLINE:
130 seq_puts(seq, "off-line\n");
131 break;
132 case ACPI_AC_STATUS_ONLINE:
133 seq_puts(seq, "on-line\n");
134 break;
135 default:
136 seq_puts(seq, "unknown\n");
137 break;
138 }
139
140 return_VALUE(0);
141}
142
143static int acpi_ac_open_fs(struct inode *inode, struct file *file)
144{
145 return single_open(file, acpi_ac_seq_show, PDE(inode)->data);
146}
147
148static int
149acpi_ac_add_fs (
150 struct acpi_device *device)
151{
152 struct proc_dir_entry *entry = NULL;
153
154 ACPI_FUNCTION_TRACE("acpi_ac_add_fs");
155
156 if (!acpi_device_dir(device)) {
157 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
158 acpi_ac_dir);
159 if (!acpi_device_dir(device))
160 return_VALUE(-ENODEV);
161 acpi_device_dir(device)->owner = THIS_MODULE;
162 }
163
164 /* 'state' [R] */
165 entry = create_proc_entry(ACPI_AC_FILE_STATE,
166 S_IRUGO, acpi_device_dir(device));
167 if (!entry)
168 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
169 "Unable to create '%s' fs entry\n",
170 ACPI_AC_FILE_STATE));
171 else {
172 entry->proc_fops = &acpi_ac_fops;
173 entry->data = acpi_driver_data(device);
174 entry->owner = THIS_MODULE;
175 }
176
177 return_VALUE(0);
178}
179
180
181static int
182acpi_ac_remove_fs (
183 struct acpi_device *device)
184{
185 ACPI_FUNCTION_TRACE("acpi_ac_remove_fs");
186
187 if (acpi_device_dir(device)) {
188 remove_proc_entry(ACPI_AC_FILE_STATE,
189 acpi_device_dir(device));
190
191 remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
192 acpi_device_dir(device) = NULL;
193 }
194
195 return_VALUE(0);
196}
197
198
199/* --------------------------------------------------------------------------
200 Driver Model
201 -------------------------------------------------------------------------- */
202
203static void
204acpi_ac_notify (
205 acpi_handle handle,
206 u32 event,
207 void *data)
208{
209 struct acpi_ac *ac = (struct acpi_ac *) data;
210 struct acpi_device *device = NULL;
211
212 ACPI_FUNCTION_TRACE("acpi_ac_notify");
213
214 if (!ac)
215 return_VOID;
216
217 if (acpi_bus_get_device(ac->handle, &device))
218 return_VOID;
219
220 switch (event) {
221 case ACPI_AC_NOTIFY_STATUS:
222 acpi_ac_get_state(ac);
223 acpi_bus_generate_event(device, event, (u32) ac->state);
224 break;
225 default:
226 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
227 "Unsupported event [0x%x]\n", event));
228 break;
229 }
230
231 return_VOID;
232}
233
234
235static int
236acpi_ac_add (
237 struct acpi_device *device)
238{
239 int result = 0;
240 acpi_status status = AE_OK;
241 struct acpi_ac *ac = NULL;
242
243 ACPI_FUNCTION_TRACE("acpi_ac_add");
244
245 if (!device)
246 return_VALUE(-EINVAL);
247
248 ac = kmalloc(sizeof(struct acpi_ac), GFP_KERNEL);
249 if (!ac)
250 return_VALUE(-ENOMEM);
251 memset(ac, 0, sizeof(struct acpi_ac));
252
253 ac->handle = device->handle;
254 strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
255 strcpy(acpi_device_class(device), ACPI_AC_CLASS);
256 acpi_driver_data(device) = ac;
257
258 result = acpi_ac_get_state(ac);
259 if (result)
260 goto end;
261
262 result = acpi_ac_add_fs(device);
263 if (result)
264 goto end;
265
266 status = acpi_install_notify_handler(ac->handle,
267 ACPI_DEVICE_NOTIFY, acpi_ac_notify, ac);
268 if (ACPI_FAILURE(status)) {
269 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
270 "Error installing notify handler\n"));
271 result = -ENODEV;
272 goto end;
273 }
274
275 printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
276 acpi_device_name(device), acpi_device_bid(device),
277 ac->state?"on-line":"off-line");
278
279end:
280 if (result) {
281 acpi_ac_remove_fs(device);
282 kfree(ac);
283 }
284
285 return_VALUE(result);
286}
287
288
289static int
290acpi_ac_remove (
291 struct acpi_device *device,
292 int type)
293{
294 acpi_status status = AE_OK;
295 struct acpi_ac *ac = NULL;
296
297 ACPI_FUNCTION_TRACE("acpi_ac_remove");
298
299 if (!device || !acpi_driver_data(device))
300 return_VALUE(-EINVAL);
301
302 ac = (struct acpi_ac *) acpi_driver_data(device);
303
304 status = acpi_remove_notify_handler(ac->handle,
305 ACPI_DEVICE_NOTIFY, acpi_ac_notify);
306 if (ACPI_FAILURE(status))
307 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
308 "Error removing notify handler\n"));
309
310 acpi_ac_remove_fs(device);
311
312 kfree(ac);
313
314 return_VALUE(0);
315}
316
317
318static int __init
319acpi_ac_init (void)
320{
321 int result = 0;
322
323 ACPI_FUNCTION_TRACE("acpi_ac_init");
324
325 acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
326 if (!acpi_ac_dir)
327 return_VALUE(-ENODEV);
328 acpi_ac_dir->owner = THIS_MODULE;
329
330 result = acpi_bus_register_driver(&acpi_ac_driver);
331 if (result < 0) {
332 remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
333 return_VALUE(-ENODEV);
334 }
335
336 return_VALUE(0);
337}
338
339
340static void __exit
341acpi_ac_exit (void)
342{
343 ACPI_FUNCTION_TRACE("acpi_ac_exit");
344
345 acpi_bus_unregister_driver(&acpi_ac_driver);
346
347 remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
348
349 return_VOID;
350}
351
352
353module_init(acpi_ac_init);
354module_exit(acpi_ac_exit);
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
new file mode 100644
index 000000000000..77285ffe41c5
--- /dev/null
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -0,0 +1,542 @@
1/*
2 * Copyright (C) 2004 Intel Corporation <naveen.b.s@intel.com>
3 *
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14 * NON INFRINGEMENT. See the GNU General Public License for more
15 * details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 *
22 * ACPI based HotPlug driver that supports Memory Hotplug
23 * This driver fields notifications from firmare for memory add
24 * and remove operations and alerts the VM of the affected memory
25 * ranges.
26 */
27
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/types.h>
32#include <linux/memory_hotplug.h>
33#include <acpi/acpi_drivers.h>
34
35
36#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL
37#define ACPI_MEMORY_DEVICE_CLASS "memory"
38#define ACPI_MEMORY_DEVICE_HID "PNP0C80"
39#define ACPI_MEMORY_DEVICE_DRIVER_NAME "Hotplug Mem Driver"
40#define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device"
41
42#define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT
43
44ACPI_MODULE_NAME ("acpi_memory")
45MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
46MODULE_DESCRIPTION(ACPI_MEMORY_DEVICE_DRIVER_NAME);
47MODULE_LICENSE("GPL");
48
49/* ACPI _STA method values */
50#define ACPI_MEMORY_STA_PRESENT (0x00000001UL)
51#define ACPI_MEMORY_STA_ENABLED (0x00000002UL)
52#define ACPI_MEMORY_STA_FUNCTIONAL (0x00000008UL)
53
54/* Memory Device States */
55#define MEMORY_INVALID_STATE 0
56#define MEMORY_POWER_ON_STATE 1
57#define MEMORY_POWER_OFF_STATE 2
58
59static int acpi_memory_device_add (struct acpi_device *device);
60static int acpi_memory_device_remove (struct acpi_device *device, int type);
61
62static struct acpi_driver acpi_memory_device_driver = {
63 .name = ACPI_MEMORY_DEVICE_DRIVER_NAME,
64 .class = ACPI_MEMORY_DEVICE_CLASS,
65 .ids = ACPI_MEMORY_DEVICE_HID,
66 .ops = {
67 .add = acpi_memory_device_add,
68 .remove = acpi_memory_device_remove,
69 },
70};
71
72struct acpi_memory_device {
73 acpi_handle handle;
74 unsigned int state; /* State of the memory device */
75 unsigned short cache_attribute; /* memory cache attribute */
76 unsigned short read_write_attribute;/* memory read/write attribute */
77 u64 start_addr; /* Memory Range start physical addr */
78 u64 end_addr; /* Memory Range end physical addr */
79};
80
81
82static int
83acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
84{
85 acpi_status status;
86 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
87 struct acpi_resource *resource = NULL;
88 struct acpi_resource_address64 address64;
89
90 ACPI_FUNCTION_TRACE("acpi_memory_get_device_resources");
91
92 /* Get the range from the _CRS */
93 status = acpi_get_current_resources(mem_device->handle, &buffer);
94 if (ACPI_FAILURE(status))
95 return_VALUE(-EINVAL);
96
97 resource = (struct acpi_resource *) buffer.pointer;
98 status = acpi_resource_to_address64(resource, &address64);
99 if (ACPI_SUCCESS(status)) {
100 if (address64.resource_type == ACPI_MEMORY_RANGE) {
101 /* Populate the structure */
102 mem_device->cache_attribute =
103 address64.attribute.memory.cache_attribute;
104 mem_device->read_write_attribute =
105 address64.attribute.memory.read_write_attribute;
106 mem_device->start_addr = address64.min_address_range;
107 mem_device->end_addr = address64.max_address_range;
108 }
109 }
110
111 acpi_os_free(buffer.pointer);
112 return_VALUE(0);
113}
114
115static int
116acpi_memory_get_device(acpi_handle handle,
117 struct acpi_memory_device **mem_device)
118{
119 acpi_status status;
120 acpi_handle phandle;
121 struct acpi_device *device = NULL;
122 struct acpi_device *pdevice = NULL;
123
124 ACPI_FUNCTION_TRACE("acpi_memory_get_device");
125
126 if (!acpi_bus_get_device(handle, &device) && device)
127 goto end;
128
129 status = acpi_get_parent(handle, &phandle);
130 if (ACPI_FAILURE(status)) {
131 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
132 "Error in acpi_get_parent\n"));
133 return_VALUE(-EINVAL);
134 }
135
136 /* Get the parent device */
137 status = acpi_bus_get_device(phandle, &pdevice);
138 if (ACPI_FAILURE(status)) {
139 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
140 "Error in acpi_bus_get_device\n"));
141 return_VALUE(-EINVAL);
142 }
143
144 /*
145 * Now add the notified device. This creates the acpi_device
146 * and invokes .add function
147 */
148 status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
149 if (ACPI_FAILURE(status)) {
150 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
151 "Error in acpi_bus_add\n"));
152 return_VALUE(-EINVAL);
153 }
154
155end:
156 *mem_device = acpi_driver_data(device);
157 if (!(*mem_device)) {
158 printk(KERN_ERR "\n driver data not found" );
159 return_VALUE(-ENODEV);
160 }
161
162 return_VALUE(0);
163}
164
165static int
166acpi_memory_check_device(struct acpi_memory_device *mem_device)
167{
168 unsigned long current_status;
169
170 ACPI_FUNCTION_TRACE("acpi_memory_check_device");
171
172 /* Get device present/absent information from the _STA */
173 if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->handle, "_STA",
174 NULL, &current_status)))
175 return_VALUE(-ENODEV);
176 /*
177 * Check for device status. Device should be
178 * present/enabled/functioning.
179 */
180 if (!((current_status & ACPI_MEMORY_STA_PRESENT)
181 && (current_status & ACPI_MEMORY_STA_ENABLED)
182 && (current_status & ACPI_MEMORY_STA_FUNCTIONAL)))
183 return_VALUE(-ENODEV);
184
185 return_VALUE(0);
186}
187
188static int
189acpi_memory_enable_device(struct acpi_memory_device *mem_device)
190{
191 int result;
192
193 ACPI_FUNCTION_TRACE("acpi_memory_enable_device");
194
195 /* Get the range from the _CRS */
196 result = acpi_memory_get_device_resources(mem_device);
197 if (result) {
198 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
199 "\nget_device_resources failed\n"));
200 mem_device->state = MEMORY_INVALID_STATE;
201 return result;
202 }
203
204 /*
205 * Tell the VM there is more memory here...
206 * Note: Assume that this function returns zero on success
207 */
208 result = add_memory(mem_device->start_addr,
209 (mem_device->end_addr - mem_device->start_addr) + 1,
210 mem_device->read_write_attribute);
211 if (result) {
212 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
213 "\nadd_memory failed\n"));
214 mem_device->state = MEMORY_INVALID_STATE;
215 return result;
216 }
217
218 return result;
219}
220
221static int
222acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
223{
224 acpi_status status;
225 struct acpi_object_list arg_list;
226 union acpi_object arg;
227 unsigned long current_status;
228
229 ACPI_FUNCTION_TRACE("acpi_memory_powerdown_device");
230
231 /* Issue the _EJ0 command */
232 arg_list.count = 1;
233 arg_list.pointer = &arg;
234 arg.type = ACPI_TYPE_INTEGER;
235 arg.integer.value = 1;
236 status = acpi_evaluate_object(mem_device->handle,
237 "_EJ0", &arg_list, NULL);
238 /* Return on _EJ0 failure */
239 if (ACPI_FAILURE(status)) {
240 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"_EJ0 failed.\n"));
241 return_VALUE(-ENODEV);
242 }
243
244 /* Evalute _STA to check if the device is disabled */
245 status = acpi_evaluate_integer(mem_device->handle, "_STA",
246 NULL, &current_status);
247 if (ACPI_FAILURE(status))
248 return_VALUE(-ENODEV);
249
250 /* Check for device status. Device should be disabled */
251 if (current_status & ACPI_MEMORY_STA_ENABLED)
252 return_VALUE(-EINVAL);
253
254 return_VALUE(0);
255}
256
257static int
258acpi_memory_disable_device(struct acpi_memory_device *mem_device)
259{
260 int result;
261 u64 start = mem_device->start_addr;
262 u64 len = mem_device->end_addr - start + 1;
263 unsigned long attr = mem_device->read_write_attribute;
264
265 ACPI_FUNCTION_TRACE("acpi_memory_disable_device");
266
267 /*
268 * Ask the VM to offline this memory range.
269 * Note: Assume that this function returns zero on success
270 */
271 result = remove_memory(start, len, attr);
272 if (result) {
273 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hot-Remove failed.\n"));
274 return_VALUE(result);
275 }
276
277 /* Power-off and eject the device */
278 result = acpi_memory_powerdown_device(mem_device);
279 if (result) {
280 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
281 "Device Power Down failed.\n"));
282 /* Set the status of the device to invalid */
283 mem_device->state = MEMORY_INVALID_STATE;
284 return result;
285 }
286
287 mem_device->state = MEMORY_POWER_OFF_STATE;
288 return result;
289}
290
291static void
292acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
293{
294 struct acpi_memory_device *mem_device;
295 struct acpi_device *device;
296
297 ACPI_FUNCTION_TRACE("acpi_memory_device_notify");
298
299 switch (event) {
300 case ACPI_NOTIFY_BUS_CHECK:
301 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
302 "\nReceived BUS CHECK notification for device\n"));
303 /* Fall Through */
304 case ACPI_NOTIFY_DEVICE_CHECK:
305 if (event == ACPI_NOTIFY_DEVICE_CHECK)
306 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
307 "\nReceived DEVICE CHECK notification for device\n"));
308 if (acpi_memory_get_device(handle, &mem_device)) {
309 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
310 "Error in finding driver data\n"));
311 return_VOID;
312 }
313
314 if (!acpi_memory_check_device(mem_device)) {
315 if (acpi_memory_enable_device(mem_device))
316 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
317 "Error in acpi_memory_enable_device\n"));
318 }
319 break;
320 case ACPI_NOTIFY_EJECT_REQUEST:
321 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
322 "\nReceived EJECT REQUEST notification for device\n"));
323
324 if (acpi_bus_get_device(handle, &device)) {
325 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
326 "Device doesn't exist\n"));
327 break;
328 }
329 mem_device = acpi_driver_data(device);
330 if (!mem_device) {
331 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
332 "Driver Data is NULL\n"));
333 break;
334 }
335
336 /*
337 * Currently disabling memory device from kernel mode
338 * TBD: Can also be disabled from user mode scripts
339 * TBD: Can also be disabled by Callback registration
340 * with generic sysfs driver
341 */
342 if (acpi_memory_disable_device(mem_device))
343 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
344 "Error in acpi_memory_disable_device\n"));
345 /*
346 * TBD: Invoke acpi_bus_remove to cleanup data structures
347 */
348 break;
349 default:
350 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
351 "Unsupported event [0x%x]\n", event));
352 break;
353 }
354
355 return_VOID;
356}
357
358static int
359acpi_memory_device_add(struct acpi_device *device)
360{
361 int result;
362 struct acpi_memory_device *mem_device = NULL;
363
364 ACPI_FUNCTION_TRACE("acpi_memory_device_add");
365
366 if (!device)
367 return_VALUE(-EINVAL);
368
369 mem_device = kmalloc(sizeof(struct acpi_memory_device), GFP_KERNEL);
370 if (!mem_device)
371 return_VALUE(-ENOMEM);
372 memset(mem_device, 0, sizeof(struct acpi_memory_device));
373
374 mem_device->handle = device->handle;
375 sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
376 sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
377 acpi_driver_data(device) = mem_device;
378
379 /* Get the range from the _CRS */
380 result = acpi_memory_get_device_resources(mem_device);
381 if (result) {
382 kfree(mem_device);
383 return_VALUE(result);
384 }
385
386 /* Set the device state */
387 mem_device->state = MEMORY_POWER_ON_STATE;
388
389 printk(KERN_INFO "%s \n", acpi_device_name(device));
390
391 return_VALUE(result);
392}
393
394static int
395acpi_memory_device_remove (struct acpi_device *device, int type)
396{
397 struct acpi_memory_device *mem_device = NULL;
398
399 ACPI_FUNCTION_TRACE("acpi_memory_device_remove");
400
401 if (!device || !acpi_driver_data(device))
402 return_VALUE(-EINVAL);
403
404 mem_device = (struct acpi_memory_device *) acpi_driver_data(device);
405 kfree(mem_device);
406
407 return_VALUE(0);
408}
409
410/*
411 * Helper function to check for memory device
412 */
413static acpi_status
414is_memory_device(acpi_handle handle)
415{
416 char *hardware_id;
417 acpi_status status;
418 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
419 struct acpi_device_info *info;
420
421 ACPI_FUNCTION_TRACE("is_memory_device");
422
423 status = acpi_get_object_info(handle, &buffer);
424 if (ACPI_FAILURE(status))
425 return_ACPI_STATUS(AE_ERROR);
426
427 info = buffer.pointer;
428 if (!(info->valid & ACPI_VALID_HID)) {
429 acpi_os_free(buffer.pointer);
430 return_ACPI_STATUS(AE_ERROR);
431 }
432
433 hardware_id = info->hardware_id.value;
434 if ((hardware_id == NULL) ||
435 (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
436 status = AE_ERROR;
437
438 acpi_os_free(buffer.pointer);
439 return_ACPI_STATUS(status);
440}
441
442static acpi_status
443acpi_memory_register_notify_handler (acpi_handle handle,
444 u32 level, void *ctxt, void **retv)
445{
446 acpi_status status;
447
448 ACPI_FUNCTION_TRACE("acpi_memory_register_notify_handler");
449
450 status = is_memory_device(handle);
451 if (ACPI_FAILURE(status))
452 return_ACPI_STATUS(AE_OK); /* continue */
453
454 status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
455 acpi_memory_device_notify, NULL);
456 if (ACPI_FAILURE(status)) {
457 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
458 "Error installing notify handler\n"));
459 return_ACPI_STATUS(AE_OK); /* continue */
460 }
461
462 return_ACPI_STATUS(status);
463}
464
465static acpi_status
466acpi_memory_deregister_notify_handler (acpi_handle handle,
467 u32 level, void *ctxt, void **retv)
468{
469 acpi_status status;
470
471 ACPI_FUNCTION_TRACE("acpi_memory_deregister_notify_handler");
472
473 status = is_memory_device(handle);
474 if (ACPI_FAILURE(status))
475 return_ACPI_STATUS(AE_OK); /* continue */
476
477 status = acpi_remove_notify_handler(handle,
478 ACPI_SYSTEM_NOTIFY, acpi_memory_device_notify);
479 if (ACPI_FAILURE(status)) {
480 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
481 "Error removing notify handler\n"));
482 return_ACPI_STATUS(AE_OK); /* continue */
483 }
484
485 return_ACPI_STATUS(status);
486}
487
488static int __init
489acpi_memory_device_init (void)
490{
491 int result;
492 acpi_status status;
493
494 ACPI_FUNCTION_TRACE("acpi_memory_device_init");
495
496 result = acpi_bus_register_driver(&acpi_memory_device_driver);
497
498 if (result < 0)
499 return_VALUE(-ENODEV);
500
501 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
502 ACPI_UINT32_MAX,
503 acpi_memory_register_notify_handler,
504 NULL, NULL);
505
506 if (ACPI_FAILURE (status)) {
507 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n"));
508 acpi_bus_unregister_driver(&acpi_memory_device_driver);
509 return_VALUE(-ENODEV);
510 }
511
512 return_VALUE(0);
513}
514
515static void __exit
516acpi_memory_device_exit (void)
517{
518 acpi_status status;
519
520 ACPI_FUNCTION_TRACE("acpi_memory_device_exit");
521
522 /*
523 * Adding this to un-install notification handlers for all the device
524 * handles.
525 */
526 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
527 ACPI_UINT32_MAX,
528 acpi_memory_deregister_notify_handler,
529 NULL, NULL);
530
531 if (ACPI_FAILURE (status))
532 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n"));
533
534 acpi_bus_unregister_driver(&acpi_memory_device_driver);
535
536 return_VOID;
537}
538
539module_init(acpi_memory_device_init);
540module_exit(acpi_memory_device_exit);
541
542
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
new file mode 100644
index 000000000000..a75cb565caeb
--- /dev/null
+++ b/drivers/acpi/asus_acpi.c
@@ -0,0 +1,1236 @@
1/*
2 * asus_acpi.c - Asus Laptop ACPI Extras
3 *
4 *
5 * Copyright (C) 2002, 2003, 2004 Julien Lerouge, Karol Kozimor
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 *
22 * The development page for this driver is located at
23 * http://sourceforge.net/projects/acpi4asus/
24 *
25 * Credits:
26 * Pontus Fuchs - Helper functions, cleanup
27 * Johann Wiesner - Small compile fixes
28 * John Belmonte - ACPI code for Toshiba laptop was a good starting point.
29 *
30 * TODO:
31 * add Fn key status
32 * Add mode selection on module loading (parameter) -> still necessary?
33 * Complete display switching -- may require dirty hacks or calling _DOS?
34 */
35
36#include <linux/kernel.h>
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/types.h>
40#include <linux/proc_fs.h>
41#include <acpi/acpi_drivers.h>
42#include <acpi/acpi_bus.h>
43#include <asm/uaccess.h>
44
45#define ASUS_ACPI_VERSION "0.29"
46
47#define PROC_ASUS "asus" //the directory
48#define PROC_MLED "mled"
49#define PROC_WLED "wled"
50#define PROC_TLED "tled"
51#define PROC_INFO "info"
52#define PROC_LCD "lcd"
53#define PROC_BRN "brn"
54#define PROC_DISP "disp"
55
56#define ACPI_HOTK_NAME "Asus Laptop ACPI Extras Driver"
57#define ACPI_HOTK_CLASS "hotkey"
58#define ACPI_HOTK_DEVICE_NAME "Hotkey"
59#define ACPI_HOTK_HID "ATK0100"
60
61/*
62 * Some events we use, same for all Asus
63 */
64#define BR_UP 0x10
65#define BR_DOWN 0x20
66
67/*
68 * Flags for hotk status
69 */
70#define MLED_ON 0x01 //is MLED ON ?
71#define WLED_ON 0x02
72#define TLED_ON 0x04
73
74MODULE_AUTHOR("Julien Lerouge, Karol Kozimor");
75MODULE_DESCRIPTION(ACPI_HOTK_NAME);
76MODULE_LICENSE("GPL");
77
78
79static uid_t asus_uid;
80static gid_t asus_gid;
81module_param(asus_uid, uint, 0);
82MODULE_PARM_DESC(uid, "UID for entries in /proc/acpi/asus.\n");
83module_param(asus_gid, uint, 0);
84MODULE_PARM_DESC(gid, "GID for entries in /proc/acpi/asus.\n");
85
86
87/* For each model, all features implemented,
88 * those marked with R are relative to HOTK, A for absolute */
89struct model_data {
90 char *name; //name of the laptop________________A
91 char *mt_mled; //method to handle mled_____________R
92 char *mled_status; //node to handle mled reading_______A
93 char *mt_wled; //method to handle wled_____________R
94 char *wled_status; //node to handle wled reading_______A
95 char *mt_tled; //method to handle tled_____________R
96 char *tled_status; //node to handle tled reading_______A
97 char *mt_lcd_switch; //method to turn LCD ON/OFF_________A
98 char *lcd_status; //node to read LCD panel state______A
99 char *brightness_up; //method to set brightness up_______A
100 char *brightness_down; //guess what ?______________________A
101 char *brightness_set; //method to set absolute brightness_R
102 char *brightness_get; //method to get absolute brightness_R
103 char *brightness_status; //node to get brightness____________A
104 char *display_set; //method to set video output________R
105 char *display_get; //method to get video output________R
106};
107
108/*
109 * This is the main structure, we can use it to store anything interesting
110 * about the hotk device
111 */
112struct asus_hotk {
113 struct acpi_device *device; //the device we are in
114 acpi_handle handle; //the handle of the hotk device
115 char status; //status of the hotk, for LEDs, ...
116 struct model_data *methods; //methods available on the laptop
117 u8 brightness; //brightness level
118 enum {
119 A1x = 0, //A1340D, A1300F
120 A2x, //A2500H
121 D1x, //D1
122 L2D, //L2000D
123 L3C, //L3800C
124 L3D, //L3400D
125 L3H, //L3H, but also L2000E
126 L4R, //L4500R
127 L5x, //L5800C
128 L8L, //L8400L
129 M1A, //M1300A
130 M2E, //M2400E, L4400L
131 M6N, //M6800N
132 M6R, //M6700R
133 P30, //Samsung P30
134 S1x, //S1300A, but also L1400B and M2400A (L84F)
135 S2x, //S200 (J1 reported), Victor MP-XP7210
136 xxN, //M2400N, M3700N, M5200N, S1300N, S5200N, W1OOON
137 //(Centrino)
138 END_MODEL
139 } model; //Models currently supported
140 u16 event_count[128]; //count for each event TODO make this better
141};
142
143/* Here we go */
144#define A1x_PREFIX "\\_SB.PCI0.ISA.EC0."
145#define L3C_PREFIX "\\_SB.PCI0.PX40.ECD0."
146#define M1A_PREFIX "\\_SB.PCI0.PX40.EC0."
147#define P30_PREFIX "\\_SB.PCI0.LPCB.EC0."
148#define S1x_PREFIX "\\_SB.PCI0.PX40."
149#define S2x_PREFIX A1x_PREFIX
150#define xxN_PREFIX "\\_SB.PCI0.SBRG.EC0."
151
152static struct model_data model_conf[END_MODEL] = {
153 /*
154 * Those pathnames are relative to the HOTK / ATKD device :
155 * - mt_mled
156 * - mt_wled
157 * - brightness_set
158 * - brightness_get
159 * - display_set
160 * - display_get
161 *
162 * TODO I have seen a SWBX and AIBX method on some models, like L1400B,
163 * it seems to be a kind of switch, but what for ?
164 *
165 */
166
167 {
168 .name = "A1x",
169 .mt_mled = "MLED",
170 .mled_status = "\\MAIL",
171 .mt_lcd_switch = A1x_PREFIX "_Q10",
172 .lcd_status = "\\BKLI",
173 .brightness_up = A1x_PREFIX "_Q0E",
174 .brightness_down = A1x_PREFIX "_Q0F"
175 },
176
177 {
178 .name = "A2x",
179 .mt_mled = "MLED",
180 .mt_wled = "WLED",
181 .wled_status = "\\SG66",
182 .mt_lcd_switch = "\\Q10",
183 .lcd_status = "\\BAOF",
184 .brightness_set = "SPLV",
185 .brightness_get = "GPLV",
186 .display_set = "SDSP",
187 .display_get = "\\INFB"
188 },
189
190 {
191 .name = "D1x",
192 .mt_mled = "MLED",
193 .mt_lcd_switch = "\\Q0D",
194 .lcd_status = "\\GP11",
195 .brightness_up = "\\Q0C",
196 .brightness_down = "\\Q0B",
197 .brightness_status = "\\BLVL",
198 .display_set = "SDSP",
199 .display_get = "\\INFB"
200 },
201
202 {
203 .name = "L2D",
204 .mt_mled = "MLED",
205 .mled_status = "\\SGP6",
206 .mt_wled = "WLED",
207 .wled_status = "\\RCP3",
208 .mt_lcd_switch = "\\Q10",
209 .lcd_status = "\\SGP0",
210 .brightness_up = "\\Q0E",
211 .brightness_down = "\\Q0F",
212 .display_set = "SDSP",
213 .display_get = "\\INFB"
214 },
215
216 {
217 .name = "L3C",
218 .mt_mled = "MLED",
219 .mt_wled = "WLED",
220 .mt_lcd_switch = L3C_PREFIX "_Q10",
221 .lcd_status = "\\GL32",
222 .brightness_set = "SPLV",
223 .brightness_get = "GPLV",
224 .display_set = "SDSP",
225 .display_get = "\\_SB.PCI0.PCI1.VGAC.NMAP"
226 },
227
228 {
229 .name = "L3D",
230 .mt_mled = "MLED",
231 .mled_status = "\\MALD",
232 .mt_wled = "WLED",
233 .mt_lcd_switch = "\\Q10",
234 .lcd_status = "\\BKLG",
235 .brightness_set = "SPLV",
236 .brightness_get = "GPLV",
237 .display_set = "SDSP",
238 .display_get = "\\INFB"
239 },
240
241 {
242 .name = "L3H",
243 .mt_mled = "MLED",
244 .mt_wled = "WLED",
245 .mt_lcd_switch = "EHK",
246 .lcd_status = "\\_SB.PCI0.PM.PBC",
247 .brightness_set = "SPLV",
248 .brightness_get = "GPLV",
249 .display_set = "SDSP",
250 .display_get = "\\INFB"
251 },
252
253 {
254 .name = "L4R",
255 .mt_mled = "MLED",
256 .mt_wled = "WLED",
257 .wled_status = "\\_SB.PCI0.SBRG.SG13",
258 .mt_lcd_switch = xxN_PREFIX "_Q10",
259 .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
260 .brightness_set = "SPLV",
261 .brightness_get = "GPLV",
262 .display_set = "SDSP",
263 .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"
264 },
265
266 {
267 .name = "L5x",
268 .mt_mled = "MLED",
269/* WLED present, but not controlled by ACPI */
270 .mt_tled = "TLED",
271 .mt_lcd_switch = "\\Q0D",
272 .lcd_status = "\\BAOF",
273 .brightness_set = "SPLV",
274 .brightness_get = "GPLV",
275 .display_set = "SDSP",
276 .display_get = "\\INFB"
277 },
278
279 {
280 .name = "L8L"
281/* No features, but at least support the hotkeys */
282 },
283
284 {
285 .name = "M1A",
286 .mt_mled = "MLED",
287 .mt_lcd_switch = M1A_PREFIX "Q10",
288 .lcd_status = "\\PNOF",
289 .brightness_up = M1A_PREFIX "Q0E",
290 .brightness_down = M1A_PREFIX "Q0F",
291 .brightness_status = "\\BRIT",
292 .display_set = "SDSP",
293 .display_get = "\\INFB"
294 },
295
296 {
297 .name = "M2E",
298 .mt_mled = "MLED",
299 .mt_wled = "WLED",
300 .mt_lcd_switch = "\\Q10",
301 .lcd_status = "\\GP06",
302 .brightness_set = "SPLV",
303 .brightness_get = "GPLV",
304 .display_set = "SDSP",
305 .display_get = "\\INFB"
306 },
307
308 {
309 .name = "M6N",
310 .mt_mled = "MLED",
311 .mt_wled = "WLED",
312 .wled_status = "\\_SB.PCI0.SBRG.SG13",
313 .mt_lcd_switch = xxN_PREFIX "_Q10",
314 .lcd_status = "\\_SB.BKLT",
315 .brightness_set = "SPLV",
316 .brightness_get = "GPLV",
317 .display_set = "SDSP",
318 .display_get = "\\SSTE"
319 },
320 {
321 .name = "M6R",
322 .mt_mled = "MLED",
323 .mt_wled = "WLED",
324 .mt_lcd_switch = xxN_PREFIX "_Q10",
325 .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
326 .brightness_set = "SPLV",
327 .brightness_get = "GPLV",
328 .display_set = "SDSP",
329 .display_get = "\\SSTE"
330 },
331
332
333 {
334 .name = "P30",
335 .mt_wled = "WLED",
336 .mt_lcd_switch = P30_PREFIX "_Q0E",
337 .lcd_status = "\\BKLT",
338 .brightness_up = P30_PREFIX "_Q68",
339 .brightness_down = P30_PREFIX "_Q69",
340 .brightness_get = "GPLV",
341 .display_set = "SDSP",
342 .display_get = "\\DNXT"
343 },
344
345 {
346 .name = "S1x",
347 .mt_mled = "MLED",
348 .mled_status = "\\EMLE",
349 .mt_wled = "WLED",
350 .mt_lcd_switch = S1x_PREFIX "Q10" ,
351 .lcd_status = "\\PNOF",
352 .brightness_set = "SPLV",
353 .brightness_get = "GPLV"
354 },
355
356 {
357 .name = "S2x",
358 .mt_mled = "MLED",
359 .mled_status = "\\MAIL",
360 .mt_lcd_switch = S2x_PREFIX "_Q10",
361 .lcd_status = "\\BKLI",
362 .brightness_up = S2x_PREFIX "_Q0B",
363 .brightness_down = S2x_PREFIX "_Q0A"
364 },
365
366 {
367 .name = "xxN",
368 .mt_mled = "MLED",
369/* WLED present, but not controlled by ACPI */
370 .mt_lcd_switch = xxN_PREFIX "_Q10",
371 .lcd_status = "\\BKLT",
372 .brightness_set = "SPLV",
373 .brightness_get = "GPLV",
374 .display_set = "SDSP",
375 .display_get = "\\ADVG"
376 }
377};
378
379/* procdir we use */
380static struct proc_dir_entry *asus_proc_dir;
381
382/*
383 * This header is made available to allow proper configuration given model,
384 * revision number , ... this info cannot go in struct asus_hotk because it is
385 * available before the hotk
386 */
387static struct acpi_table_header *asus_info;
388
389/* The actual device the driver binds to */
390static struct asus_hotk *hotk;
391
392/*
393 * The hotkey driver declaration
394 */
395static int asus_hotk_add(struct acpi_device *device);
396static int asus_hotk_remove(struct acpi_device *device, int type);
397static struct acpi_driver asus_hotk_driver = {
398 .name = ACPI_HOTK_NAME,
399 .class = ACPI_HOTK_CLASS,
400 .ids = ACPI_HOTK_HID,
401 .ops = {
402 .add = asus_hotk_add,
403 .remove = asus_hotk_remove,
404 },
405};
406
407/*
408 * This function evaluates an ACPI method, given an int as parameter, the
409 * method is searched within the scope of the handle, can be NULL. The output
410 * of the method is written is output, which can also be NULL
411 *
412 * returns 1 if write is successful, 0 else.
413 */
414static int write_acpi_int(acpi_handle handle, const char *method, int val,
415 struct acpi_buffer *output)
416{
417 struct acpi_object_list params; //list of input parameters (an int here)
418 union acpi_object in_obj; //the only param we use
419 acpi_status status;
420
421 params.count = 1;
422 params.pointer = &in_obj;
423 in_obj.type = ACPI_TYPE_INTEGER;
424 in_obj.integer.value = val;
425
426 status = acpi_evaluate_object(handle, (char *) method, &params, output);
427 return (status == AE_OK);
428}
429
430
431static int read_acpi_int(acpi_handle handle, const char *method, int *val)
432{
433 struct acpi_buffer output;
434 union acpi_object out_obj;
435 acpi_status status;
436
437 output.length = sizeof(out_obj);
438 output.pointer = &out_obj;
439
440 status = acpi_evaluate_object(handle, (char *) method, NULL, &output);
441 *val = out_obj.integer.value;
442 return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER);
443}
444
445/*
446 * We write our info in page, we begin at offset off and cannot write more
447 * than count bytes. We set eof to 1 if we handle those 2 values. We return the
448 * number of bytes written in page
449 */
450static int
451proc_read_info(char *page, char **start, off_t off, int count, int *eof,
452 void *data)
453{
454 int len = 0;
455 int temp;
456 char buf[16]; //enough for all info
457 /*
458 * We use the easy way, we don't care of off and count, so we don't set eof
459 * to 1
460 */
461
462 len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n");
463 len += sprintf(page + len, "Model reference : %s\n",
464 hotk->methods->name);
465 /*
466 * The SFUN method probably allows the original driver to get the list
467 * of features supported by a given model. For now, 0x0100 or 0x0800
468 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
469 * The significance of others is yet to be found.
470 */
471 if (read_acpi_int(hotk->handle, "SFUN", &temp))
472 len += sprintf(page + len, "SFUN value : 0x%04x\n", temp);
473 /*
474 * Another value for userspace: the ASYM method returns 0x02 for
475 * battery low and 0x04 for battery critical, its readings tend to be
476 * more accurate than those provided by _BST.
477 * Note: since not all the laptops provide this method, errors are
478 * silently ignored.
479 */
480 if (read_acpi_int(hotk->handle, "ASYM", &temp))
481 len += sprintf(page + len, "ASYM value : 0x%04x\n", temp);
482 if (asus_info) {
483 snprintf(buf, 16, "%d", asus_info->length);
484 len += sprintf(page + len, "DSDT length : %s\n", buf);
485 snprintf(buf, 16, "%d", asus_info->checksum);
486 len += sprintf(page + len, "DSDT checksum : %s\n", buf);
487 snprintf(buf, 16, "%d", asus_info->revision);
488 len += sprintf(page + len, "DSDT revision : %s\n", buf);
489 snprintf(buf, 7, "%s", asus_info->oem_id);
490 len += sprintf(page + len, "OEM id : %s\n", buf);
491 snprintf(buf, 9, "%s", asus_info->oem_table_id);
492 len += sprintf(page + len, "OEM table id : %s\n", buf);
493 snprintf(buf, 16, "%x", asus_info->oem_revision);
494 len += sprintf(page + len, "OEM revision : 0x%s\n", buf);
495 snprintf(buf, 5, "%s", asus_info->asl_compiler_id);
496 len += sprintf(page + len, "ASL comp vendor id : %s\n", buf);
497 snprintf(buf, 16, "%x", asus_info->asl_compiler_revision);
498 len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf);
499 }
500
501 return len;
502}
503
504
505/*
506 * /proc handlers
507 * We write our info in page, we begin at offset off and cannot write more
508 * than count bytes. We set eof to 1 if we handle those 2 values. We return the
509 * number of bytes written in page
510 */
511
512/* Generic LED functions */
513static int
514read_led(const char *ledname, int ledmask)
515{
516 if (ledname) {
517 int led_status;
518
519 if (read_acpi_int(NULL, ledname, &led_status))
520 return led_status;
521 else
522 printk(KERN_WARNING "Asus ACPI: Error reading LED "
523 "status\n");
524 }
525 return (hotk->status & ledmask) ? 1 : 0;
526}
527
528static int parse_arg(const char __user *buf, unsigned long count, int *val)
529{
530 char s[32];
531 if (!count)
532 return 0;
533 if (count > 31)
534 return -EINVAL;
535 if (copy_from_user(s, buf, count))
536 return -EFAULT;
537 s[count] = 0;
538 if (sscanf(s, "%i", val) != 1)
539 return -EINVAL;
540 return count;
541}
542
543/* FIXME: kill extraneous args so it can be called independently */
544static int
545write_led(const char __user *buffer, unsigned long count,
546 char *ledname, int ledmask, int invert)
547{
548 int value;
549 int led_out = 0;
550
551 count = parse_arg(buffer, count, &value);
552 if (count > 0)
553 led_out = value ? 1 : 0;
554
555 hotk->status =
556 (led_out) ? (hotk->status | ledmask) : (hotk->status & ~ledmask);
557
558 if (invert) /* invert target value */
559 led_out = !led_out & 0x1;
560
561 if (!write_acpi_int(hotk->handle, ledname, led_out, NULL))
562 printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n", ledname);
563
564 return count;
565}
566
567
568/*
569 * Proc handlers for MLED
570 */
571static int
572proc_read_mled(char *page, char **start, off_t off, int count, int *eof,
573 void *data)
574{
575 return sprintf(page, "%d\n", read_led(hotk->methods->mled_status, MLED_ON));
576}
577
578
579static int
580proc_write_mled(struct file *file, const char __user *buffer,
581 unsigned long count, void *data)
582{
583 return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);
584}
585
586/*
587 * Proc handlers for WLED
588 */
589static int
590proc_read_wled(char *page, char **start, off_t off, int count, int *eof,
591 void *data)
592{
593 return sprintf(page, "%d\n", read_led(hotk->methods->wled_status, WLED_ON));
594}
595
596static int
597proc_write_wled(struct file *file, const char __user *buffer,
598 unsigned long count, void *data)
599{
600 return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);
601}
602
603/*
604 * Proc handlers for TLED
605 */
606static int
607proc_read_tled(char *page, char **start, off_t off, int count, int *eof,
608 void *data)
609{
610 return sprintf(page, "%d\n", read_led(hotk->methods->tled_status, TLED_ON));
611}
612
613static int
614proc_write_tled(struct file *file, const char __user *buffer,
615 unsigned long count, void *data)
616{
617 return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0);
618}
619
620
621static int get_lcd_state(void)
622{
623 int lcd = 0;
624
625 if (hotk->model != L3H) {
626 /* We don't have to check anything if we are here */
627 if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd))
628 printk(KERN_WARNING "Asus ACPI: Error reading LCD status\n");
629
630 if (hotk->model == L2D)
631 lcd = ~lcd;
632 } else { /* L3H and the like have to be handled differently */
633 acpi_status status = 0;
634 struct acpi_object_list input;
635 union acpi_object mt_params[2];
636 struct acpi_buffer output;
637 union acpi_object out_obj;
638
639 input.count = 2;
640 input.pointer = mt_params;
641 /* Note: the following values are partly guessed up, but
642 otherwise they seem to work */
643 mt_params[0].type = ACPI_TYPE_INTEGER;
644 mt_params[0].integer.value = 0x02;
645 mt_params[1].type = ACPI_TYPE_INTEGER;
646 mt_params[1].integer.value = 0x02;
647
648 output.length = sizeof(out_obj);
649 output.pointer = &out_obj;
650
651 status = acpi_evaluate_object(NULL, hotk->methods->lcd_status, &input, &output);
652 if (status != AE_OK)
653 return -1;
654 if (out_obj.type == ACPI_TYPE_INTEGER)
655 /* That's what the AML code does */
656 lcd = out_obj.integer.value >> 8;
657 }
658
659 return (lcd & 1);
660}
661
662static int set_lcd_state(int value)
663{
664 int lcd = 0;
665 acpi_status status = 0;
666
667 lcd = value ? 1 : 0;
668 if (lcd != get_lcd_state()) {
669 /* switch */
670 if (hotk->model != L3H) {
671 status =
672 acpi_evaluate_object(NULL, hotk->methods->mt_lcd_switch,
673 NULL, NULL);
674 } else { /* L3H and the like have to be handled differently */
675 if (!write_acpi_int(hotk->handle, hotk->methods->mt_lcd_switch, 0x07, NULL))
676 status = AE_ERROR;
677 /* L3H's AML executes EHK (0x07) upon Fn+F7 keypress,
678 the exact behaviour is simulated here */
679 }
680 if (ACPI_FAILURE(status))
681 printk(KERN_WARNING "Asus ACPI: Error switching LCD\n");
682 }
683 return 0;
684
685}
686
687static int
688proc_read_lcd(char *page, char **start, off_t off, int count, int *eof,
689 void *data)
690{
691 return sprintf(page, "%d\n", get_lcd_state());
692}
693
694
695static int
696proc_write_lcd(struct file *file, const char __user *buffer,
697 unsigned long count, void *data)
698{
699 int value;
700
701 count = parse_arg(buffer, count, &value);
702 if (count > 0)
703 set_lcd_state(value);
704 return count;
705}
706
707
708static int read_brightness(void)
709{
710 int value;
711
712 if(hotk->methods->brightness_get) { /* SPLV/GPLV laptop */
713 if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get,
714 &value))
715 printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
716 } else if (hotk->methods->brightness_status) { /* For D1 for example */
717 if (!read_acpi_int(NULL, hotk->methods->brightness_status,
718 &value))
719 printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
720 } else /* No GPLV method */
721 value = hotk->brightness;
722 return value;
723}
724
725/*
726 * Change the brightness level
727 */
728static void set_brightness(int value)
729{
730 acpi_status status = 0;
731
732 /* SPLV laptop */
733 if(hotk->methods->brightness_set) {
734 if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set,
735 value, NULL))
736 printk(KERN_WARNING "Asus ACPI: Error changing brightness\n");
737 return;
738 }
739
740 /* No SPLV method if we are here, act as appropriate */
741 value -= read_brightness();
742 while (value != 0) {
743 status = acpi_evaluate_object(NULL, (value > 0) ?
744 hotk->methods->brightness_up :
745 hotk->methods->brightness_down,
746 NULL, NULL);
747 (value > 0) ? value-- : value++;
748 if (ACPI_FAILURE(status))
749 printk(KERN_WARNING "Asus ACPI: Error changing brightness\n");
750 }
751 return;
752}
753
754static int
755proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
756 void *data)
757{
758 return sprintf(page, "%d\n", read_brightness());
759}
760
761static int
762proc_write_brn(struct file *file, const char __user *buffer,
763 unsigned long count, void *data)
764{
765 int value;
766
767 count = parse_arg(buffer, count, &value);
768 if (count > 0) {
769 value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
770 /* 0 <= value <= 15 */
771 set_brightness(value);
772 } else if (count < 0) {
773 printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
774 }
775
776 return count;
777}
778
779static void set_display(int value)
780{
781 /* no sanity check needed for now */
782 if (!write_acpi_int(hotk->handle, hotk->methods->display_set,
783 value, NULL))
784 printk(KERN_WARNING "Asus ACPI: Error setting display\n");
785 return;
786}
787
788/*
789 * Now, *this* one could be more user-friendly, but so far, no-one has
790 * complained. The significance of bits is the same as in proc_write_disp()
791 */
792static int
793proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
794 void *data)
795{
796 int value = 0;
797
798 if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value))
799 printk(KERN_WARNING "Asus ACPI: Error reading display status\n");
800 value &= 0x07; /* needed for some models, shouldn't hurt others */
801 return sprintf(page, "%d\n", value);
802}
803
804/*
805 * Experimental support for display switching. As of now: 1 should activate
806 * the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination
807 * (bitwise) of these will suffice. I never actually tested 3 displays hooked up
808 * simultaneously, so be warned. See the acpi4asus README for more info.
809 */
810static int
811proc_write_disp(struct file *file, const char __user *buffer,
812 unsigned long count, void *data)
813{
814 int value;
815
816 count = parse_arg(buffer, count, &value);
817 if (count > 0)
818 set_display(value);
819 else if (count < 0)
820 printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
821
822 return count;
823}
824
825
826typedef int (proc_readfunc)(char *page, char **start, off_t off, int count,
827 int *eof, void *data);
828typedef int (proc_writefunc)(struct file *file, const char __user *buffer,
829 unsigned long count, void *data);
830
831static int
832__init asus_proc_add(char *name, proc_writefunc *writefunc,
833 proc_readfunc *readfunc, mode_t mode,
834 struct acpi_device *device)
835{
836 struct proc_dir_entry *proc = create_proc_entry(name, mode, acpi_device_dir(device));
837 if(!proc) {
838 printk(KERN_WARNING " Unable to create %s fs entry\n", name);
839 return -1;
840 }
841 proc->write_proc = writefunc;
842 proc->read_proc = readfunc;
843 proc->data = acpi_driver_data(device);
844 proc->owner = THIS_MODULE;
845 proc->uid = asus_uid;
846 proc->gid = asus_gid;
847 return 0;
848}
849
850static int __init asus_hotk_add_fs(struct acpi_device *device)
851{
852 struct proc_dir_entry *proc;
853 mode_t mode;
854
855 /*
856 * If parameter uid or gid is not changed, keep the default setting for
857 * our proc entries (-rw-rw-rw-) else, it means we care about security,
858 * and then set to -rw-rw----
859 */
860
861 if ((asus_uid == 0) && (asus_gid == 0)){
862 mode = S_IFREG | S_IRUGO | S_IWUGO;
863 } else {
864 mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
865 }
866
867 acpi_device_dir(device) = asus_proc_dir;
868 if (!acpi_device_dir(device))
869 return -ENODEV;
870
871 proc = create_proc_entry(PROC_INFO, mode, acpi_device_dir(device));
872 if (proc) {
873 proc->read_proc = proc_read_info;
874 proc->data = acpi_driver_data(device);
875 proc->owner = THIS_MODULE;
876 proc->uid = asus_uid;
877 proc->gid = asus_gid;
878 } else {
879 printk(KERN_WARNING " Unable to create " PROC_INFO
880 " fs entry\n");
881 }
882
883 if (hotk->methods->mt_wled) {
884 asus_proc_add(PROC_WLED, &proc_write_wled, &proc_read_wled, mode, device);
885 }
886
887 if (hotk->methods->mt_mled) {
888 asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled, mode, device);
889 }
890
891 if (hotk->methods->mt_tled) {
892 asus_proc_add(PROC_TLED, &proc_write_tled, &proc_read_tled, mode, device);
893 }
894
895 /*
896 * We need both read node and write method as LCD switch is also accessible
897 * from keyboard
898 */
899 if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) {
900 asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode, device);
901 }
902
903 if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
904 (hotk->methods->brightness_get && hotk->methods->brightness_set)) {
905 asus_proc_add(PROC_BRN, &proc_write_brn, &proc_read_brn, mode, device);
906 }
907
908 if (hotk->methods->display_set) {
909 asus_proc_add(PROC_DISP, &proc_write_disp, &proc_read_disp, mode, device);
910 }
911
912 return 0;
913}
914
915static int asus_hotk_remove_fs(struct acpi_device* device)
916{
917 if(acpi_device_dir(device)) {
918 remove_proc_entry(PROC_INFO,acpi_device_dir(device));
919 if (hotk->methods->mt_wled)
920 remove_proc_entry(PROC_WLED,acpi_device_dir(device));
921 if (hotk->methods->mt_mled)
922 remove_proc_entry(PROC_MLED,acpi_device_dir(device));
923 if (hotk->methods->mt_tled)
924 remove_proc_entry(PROC_TLED,acpi_device_dir(device));
925 if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status)
926 remove_proc_entry(PROC_LCD, acpi_device_dir(device));
927 if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
928 (hotk->methods->brightness_get && hotk->methods->brightness_set))
929 remove_proc_entry(PROC_BRN, acpi_device_dir(device));
930 if (hotk->methods->display_set)
931 remove_proc_entry(PROC_DISP, acpi_device_dir(device));
932 }
933 return 0;
934}
935
936
937static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
938{
939 /* TODO Find a better way to handle events count.*/
940 if (!hotk)
941 return;
942
943 if ((event & ~((u32) BR_UP)) < 16) {
944 hotk->brightness = (event & ~((u32) BR_UP));
945 } else if ((event & ~((u32) BR_DOWN)) < 16 ) {
946 hotk->brightness = (event & ~((u32) BR_DOWN));
947 }
948
949 acpi_bus_generate_event(hotk->device, event,
950 hotk->event_count[event % 128]++);
951
952 return;
953}
954
955/*
956 * This function is used to initialize the hotk with right values. In this
957 * method, we can make all the detection we want, and modify the hotk struct
958 */
959static int __init asus_hotk_get_info(void)
960{
961 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
962 struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL };
963 union acpi_object *model = NULL;
964 int bsts_result;
965 acpi_status status;
966
967 /*
968 * Get DSDT headers early enough to allow for differentiating between
969 * models, but late enough to allow acpi_bus_register_driver() to fail
970 * before doing anything ACPI-specific. Should we encounter a machine,
971 * which needs special handling (i.e. its hotkey device has a different
972 * HID), this bit will be moved. A global variable asus_info contains
973 * the DSDT header.
974 */
975 status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt);
976 if (ACPI_FAILURE(status))
977 printk(KERN_WARNING " Couldn't get the DSDT table header\n");
978 else
979 asus_info = (struct acpi_table_header *) dsdt.pointer;
980
981 /* We have to write 0 on init this far for all ASUS models */
982 if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
983 printk(KERN_ERR " Hotkey initialization failed\n");
984 return -ENODEV;
985 }
986
987 /* This needs to be called for some laptops to init properly */
988 if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result))
989 printk(KERN_WARNING " Error calling BSTS\n");
990 else if (bsts_result)
991 printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", bsts_result);
992
993 /* Samsung P30 has a device with a valid _HID whose INIT does not
994 * return anything. Catch this one and any similar here */
995 if (buffer.pointer == NULL) {
996 if (asus_info && /* Samsung P30 */
997 strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
998 hotk->model = P30;
999 printk(KERN_NOTICE " Samsung P30 detected, supported\n");
1000 } else {
1001 hotk->model = M2E;
1002 printk(KERN_WARNING " no string returned by INIT\n");
1003 printk(KERN_WARNING " trying default values, supply "
1004 "the developers with your DSDT\n");
1005 }
1006 hotk->methods = &model_conf[hotk->model];
1007 return AE_OK;
1008 }
1009
1010 model = (union acpi_object *) buffer.pointer;
1011 if (model->type == ACPI_TYPE_STRING) {
1012 printk(KERN_NOTICE " %s model detected, ", model->string.pointer);
1013 }
1014
1015 hotk->model = END_MODEL;
1016 if (strncmp(model->string.pointer, "L3D", 3) == 0)
1017 hotk->model = L3D;
1018 else if (strncmp(model->string.pointer, "L3H", 3) == 0 ||
1019 strncmp(model->string.pointer, "L2E", 3) == 0)
1020 hotk->model = L3H;
1021 else if (strncmp(model->string.pointer, "L3", 2) == 0 ||
1022 strncmp(model->string.pointer, "L2B", 3) == 0)
1023 hotk->model = L3C;
1024 else if (strncmp(model->string.pointer, "L8L", 3) == 0)
1025 hotk->model = L8L;
1026 else if (strncmp(model->string.pointer, "L4R", 3) == 0)
1027 hotk->model = L4R;
1028 else if (strncmp(model->string.pointer, "M6N", 3) == 0)
1029 hotk->model = M6N;
1030 else if (strncmp(model->string.pointer, "M6R", 3) == 0)
1031 hotk->model = M6R;
1032 else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
1033 strncmp(model->string.pointer, "M3N", 3) == 0 ||
1034 strncmp(model->string.pointer, "M5N", 3) == 0 ||
1035 strncmp(model->string.pointer, "M6N", 3) == 0 ||
1036 strncmp(model->string.pointer, "S1N", 3) == 0 ||
1037 strncmp(model->string.pointer, "S5N", 3) == 0 ||
1038 strncmp(model->string.pointer, "W1N", 3) == 0)
1039 hotk->model = xxN;
1040 else if (strncmp(model->string.pointer, "M1", 2) == 0)
1041 hotk->model = M1A;
1042 else if (strncmp(model->string.pointer, "M2", 2) == 0 ||
1043 strncmp(model->string.pointer, "L4E", 3) == 0)
1044 hotk->model = M2E;
1045 else if (strncmp(model->string.pointer, "L2", 2) == 0)
1046 hotk->model = L2D;
1047 else if (strncmp(model->string.pointer, "L8", 2) == 0)
1048 hotk->model = S1x;
1049 else if (strncmp(model->string.pointer, "D1", 2) == 0)
1050 hotk->model = D1x;
1051 else if (strncmp(model->string.pointer, "A1", 2) == 0)
1052 hotk->model = A1x;
1053 else if (strncmp(model->string.pointer, "A2", 2) == 0)
1054 hotk->model = A2x;
1055 else if (strncmp(model->string.pointer, "J1", 2) == 0)
1056 hotk->model = S2x;
1057 else if (strncmp(model->string.pointer, "L5", 2) == 0)
1058 hotk->model = L5x;
1059
1060 if (hotk->model == END_MODEL) {
1061 printk("unsupported, trying default values, supply the "
1062 "developers with your DSDT\n");
1063 hotk->model = M2E;
1064 } else {
1065 printk("supported\n");
1066 }
1067
1068 hotk->methods = &model_conf[hotk->model];
1069
1070 /* Sort of per-model blacklist */
1071 if (strncmp(model->string.pointer, "L2B", 3) == 0)
1072 hotk->methods->lcd_status = NULL;
1073 /* L2B is similar enough to L3C to use its settings, with this only
1074 exception */
1075 else if (strncmp(model->string.pointer, "S5N", 3) == 0 ||
1076 strncmp(model->string.pointer, "M5N", 3) == 0)
1077 hotk->methods->mt_mled = NULL;
1078 /* S5N and M5N have no MLED */
1079 else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
1080 strncmp(model->string.pointer, "W1N", 3) == 0)
1081 hotk->methods->mt_wled = "WLED";
1082 /* M2N and W1N have a usable WLED */
1083 else if (asus_info) {
1084 if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
1085 hotk->methods->mled_status = NULL;
1086 /* S1300A reports L84F, but L1400B too, account for that */
1087 }
1088
1089 acpi_os_free(model);
1090
1091 return AE_OK;
1092}
1093
1094
1095static int __init asus_hotk_check(void)
1096{
1097 int result = 0;
1098
1099 result = acpi_bus_get_status(hotk->device);
1100 if (result)
1101 return result;
1102
1103 if (hotk->device->status.present) {
1104 result = asus_hotk_get_info();
1105 } else {
1106 printk(KERN_ERR " Hotkey device not present, aborting\n");
1107 return -EINVAL;
1108 }
1109
1110 return result;
1111}
1112
1113
1114static int __init asus_hotk_add(struct acpi_device *device)
1115{
1116 acpi_status status = AE_OK;
1117 int result;
1118
1119 if (!device)
1120 return -EINVAL;
1121
1122 printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n",
1123 ASUS_ACPI_VERSION);
1124
1125 hotk =
1126 (struct asus_hotk *) kmalloc(sizeof(struct asus_hotk), GFP_KERNEL);
1127 if (!hotk)
1128 return -ENOMEM;
1129 memset(hotk, 0, sizeof(struct asus_hotk));
1130
1131 hotk->handle = device->handle;
1132 strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME);
1133 strcpy(acpi_device_class(device), ACPI_HOTK_CLASS);
1134 acpi_driver_data(device) = hotk;
1135 hotk->device = device;
1136
1137
1138 result = asus_hotk_check();
1139 if (result)
1140 goto end;
1141
1142 result = asus_hotk_add_fs(device);
1143 if (result)
1144 goto end;
1145
1146 /*
1147 * We install the handler, it will receive the hotk in parameter, so, we
1148 * could add other data to the hotk struct
1149 */
1150 status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
1151 asus_hotk_notify, hotk);
1152 if (ACPI_FAILURE(status))
1153 printk(KERN_ERR " Error installing notify handler\n");
1154
1155 /* For laptops without GPLV: init the hotk->brightness value */
1156 if ((!hotk->methods->brightness_get) && (!hotk->methods->brightness_status) &&
1157 (hotk->methods->brightness_up && hotk->methods->brightness_down)) {
1158 status = acpi_evaluate_object(NULL, hotk->methods->brightness_down,
1159 NULL, NULL);
1160 if (ACPI_FAILURE(status))
1161 printk(KERN_WARNING " Error changing brightness\n");
1162 else {
1163 status = acpi_evaluate_object(NULL, hotk->methods->brightness_up,
1164 NULL, NULL);
1165 if (ACPI_FAILURE(status))
1166 printk(KERN_WARNING " Strange, error changing"
1167 " brightness\n");
1168 }
1169 }
1170
1171 end:
1172 if (result) {
1173 kfree(hotk);
1174 }
1175
1176 return result;
1177}
1178
1179
1180static int asus_hotk_remove(struct acpi_device *device, int type)
1181{
1182 acpi_status status = 0;
1183
1184 if (!device || !acpi_driver_data(device))
1185 return -EINVAL;
1186
1187 status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
1188 asus_hotk_notify);
1189 if (ACPI_FAILURE(status))
1190 printk(KERN_ERR "Asus ACPI: Error removing notify handler\n");
1191
1192 asus_hotk_remove_fs(device);
1193
1194 kfree(hotk);
1195
1196 return 0;
1197}
1198
1199
1200static int __init asus_acpi_init(void)
1201{
1202 int result;
1203
1204 if (acpi_disabled)
1205 return -ENODEV;
1206
1207 asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
1208 if (!asus_proc_dir) {
1209 printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n");
1210 return -ENODEV;
1211 }
1212 asus_proc_dir->owner = THIS_MODULE;
1213
1214 result = acpi_bus_register_driver(&asus_hotk_driver);
1215 if (result < 1) {
1216 acpi_bus_unregister_driver(&asus_hotk_driver);
1217 remove_proc_entry(PROC_ASUS, acpi_root_dir);
1218 return -ENODEV;
1219 }
1220
1221 return 0;
1222}
1223
1224
1225static void __exit asus_acpi_exit(void)
1226{
1227 acpi_bus_unregister_driver(&asus_hotk_driver);
1228 remove_proc_entry(PROC_ASUS, acpi_root_dir);
1229
1230 acpi_os_free(asus_info);
1231
1232 return;
1233}
1234
1235module_init(asus_acpi_init);
1236module_exit(asus_acpi_exit);
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
new file mode 100644
index 000000000000..c55feca9b7d5
--- /dev/null
+++ b/drivers/acpi/battery.c
@@ -0,0 +1,846 @@
1/*
2 * acpi_battery.c - ACPI Battery Driver ($Revision: 37 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/types.h>
30#include <linux/proc_fs.h>
31#include <linux/seq_file.h>
32#include <asm/uaccess.h>
33
34#include <acpi/acpi_bus.h>
35#include <acpi/acpi_drivers.h>
36
37
38#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
39
40#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS"
41#define ACPI_BATTERY_FORMAT_BST "NNNN"
42
43#define ACPI_BATTERY_COMPONENT 0x00040000
44#define ACPI_BATTERY_CLASS "battery"
45#define ACPI_BATTERY_HID "PNP0C0A"
46#define ACPI_BATTERY_DRIVER_NAME "ACPI Battery Driver"
47#define ACPI_BATTERY_DEVICE_NAME "Battery"
48#define ACPI_BATTERY_FILE_INFO "info"
49#define ACPI_BATTERY_FILE_STATUS "state"
50#define ACPI_BATTERY_FILE_ALARM "alarm"
51#define ACPI_BATTERY_NOTIFY_STATUS 0x80
52#define ACPI_BATTERY_NOTIFY_INFO 0x81
53#define ACPI_BATTERY_UNITS_WATTS "mW"
54#define ACPI_BATTERY_UNITS_AMPS "mA"
55
56
57#define _COMPONENT ACPI_BATTERY_COMPONENT
58ACPI_MODULE_NAME ("acpi_battery")
59
60MODULE_AUTHOR("Paul Diefenbaugh");
61MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
62MODULE_LICENSE("GPL");
63
64static int acpi_battery_add (struct acpi_device *device);
65static int acpi_battery_remove (struct acpi_device *device, int type);
66
67static struct acpi_driver acpi_battery_driver = {
68 .name = ACPI_BATTERY_DRIVER_NAME,
69 .class = ACPI_BATTERY_CLASS,
70 .ids = ACPI_BATTERY_HID,
71 .ops = {
72 .add = acpi_battery_add,
73 .remove = acpi_battery_remove,
74 },
75};
76
77struct acpi_battery_status {
78 acpi_integer state;
79 acpi_integer present_rate;
80 acpi_integer remaining_capacity;
81 acpi_integer present_voltage;
82};
83
84struct acpi_battery_info {
85 acpi_integer power_unit;
86 acpi_integer design_capacity;
87 acpi_integer last_full_capacity;
88 acpi_integer battery_technology;
89 acpi_integer design_voltage;
90 acpi_integer design_capacity_warning;
91 acpi_integer design_capacity_low;
92 acpi_integer battery_capacity_granularity_1;
93 acpi_integer battery_capacity_granularity_2;
94 acpi_string model_number;
95 acpi_string serial_number;
96 acpi_string battery_type;
97 acpi_string oem_info;
98};
99
100struct acpi_battery_flags {
101 u8 present:1; /* Bay occupied? */
102 u8 power_unit:1; /* 0=watts, 1=apms */
103 u8 alarm:1; /* _BTP present? */
104 u8 reserved:5;
105};
106
107struct acpi_battery_trips {
108 unsigned long warning;
109 unsigned long low;
110};
111
112struct acpi_battery {
113 acpi_handle handle;
114 struct acpi_battery_flags flags;
115 struct acpi_battery_trips trips;
116 unsigned long alarm;
117 struct acpi_battery_info *info;
118};
119
120
121/* --------------------------------------------------------------------------
122 Battery Management
123 -------------------------------------------------------------------------- */
124
125static int
126acpi_battery_get_info (
127 struct acpi_battery *battery,
128 struct acpi_battery_info **bif)
129{
130 int result = 0;
131 acpi_status status = 0;
132 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
133 struct acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BIF),
134 ACPI_BATTERY_FORMAT_BIF};
135 struct acpi_buffer data = {0, NULL};
136 union acpi_object *package = NULL;
137
138 ACPI_FUNCTION_TRACE("acpi_battery_get_info");
139
140 if (!battery || !bif)
141 return_VALUE(-EINVAL);
142
143 /* Evalute _BIF */
144
145 status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer);
146 if (ACPI_FAILURE(status)) {
147 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n"));
148 return_VALUE(-ENODEV);
149 }
150
151 package = (union acpi_object *) buffer.pointer;
152
153 /* Extract Package Data */
154
155 status = acpi_extract_package(package, &format, &data);
156 if (status != AE_BUFFER_OVERFLOW) {
157 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
158 result = -ENODEV;
159 goto end;
160 }
161
162 data.pointer = kmalloc(data.length, GFP_KERNEL);
163 if (!data.pointer) {
164 result = -ENOMEM;
165 goto end;
166 }
167 memset(data.pointer, 0, data.length);
168
169 status = acpi_extract_package(package, &format, &data);
170 if (ACPI_FAILURE(status)) {
171 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
172 kfree(data.pointer);
173 result = -ENODEV;
174 goto end;
175 }
176
177end:
178 acpi_os_free(buffer.pointer);
179
180 if (!result)
181 (*bif) = (struct acpi_battery_info *) data.pointer;
182
183 return_VALUE(result);
184}
185
186static int
187acpi_battery_get_status (
188 struct acpi_battery *battery,
189 struct acpi_battery_status **bst)
190{
191 int result = 0;
192 acpi_status status = 0;
193 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
194 struct acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BST),
195 ACPI_BATTERY_FORMAT_BST};
196 struct acpi_buffer data = {0, NULL};
197 union acpi_object *package = NULL;
198
199 ACPI_FUNCTION_TRACE("acpi_battery_get_status");
200
201 if (!battery || !bst)
202 return_VALUE(-EINVAL);
203
204 /* Evalute _BST */
205
206 status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer);
207 if (ACPI_FAILURE(status)) {
208 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n"));
209 return_VALUE(-ENODEV);
210 }
211
212 package = (union acpi_object *) buffer.pointer;
213
214 /* Extract Package Data */
215
216 status = acpi_extract_package(package, &format, &data);
217 if (status != AE_BUFFER_OVERFLOW) {
218 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
219 result = -ENODEV;
220 goto end;
221 }
222
223 data.pointer = kmalloc(data.length, GFP_KERNEL);
224 if (!data.pointer) {
225 result = -ENOMEM;
226 goto end;
227 }
228 memset(data.pointer, 0, data.length);
229
230 status = acpi_extract_package(package, &format, &data);
231 if (ACPI_FAILURE(status)) {
232 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
233 kfree(data.pointer);
234 result = -ENODEV;
235 goto end;
236 }
237
238end:
239 acpi_os_free(buffer.pointer);
240
241 if (!result)
242 (*bst) = (struct acpi_battery_status *) data.pointer;
243
244 return_VALUE(result);
245}
246
247
248static int
249acpi_battery_set_alarm (
250 struct acpi_battery *battery,
251 unsigned long alarm)
252{
253 acpi_status status = 0;
254 union acpi_object arg0 = {ACPI_TYPE_INTEGER};
255 struct acpi_object_list arg_list = {1, &arg0};
256
257 ACPI_FUNCTION_TRACE("acpi_battery_set_alarm");
258
259 if (!battery)
260 return_VALUE(-EINVAL);
261
262 if (!battery->flags.alarm)
263 return_VALUE(-ENODEV);
264
265 arg0.integer.value = alarm;
266
267 status = acpi_evaluate_object(battery->handle, "_BTP", &arg_list, NULL);
268 if (ACPI_FAILURE(status))
269 return_VALUE(-ENODEV);
270
271 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm));
272
273 battery->alarm = alarm;
274
275 return_VALUE(0);
276}
277
278
279static int
280acpi_battery_check (
281 struct acpi_battery *battery)
282{
283 int result = 0;
284 acpi_status status = AE_OK;
285 acpi_handle handle = NULL;
286 struct acpi_device *device = NULL;
287 struct acpi_battery_info *bif = NULL;
288
289 ACPI_FUNCTION_TRACE("acpi_battery_check");
290
291 if (!battery)
292 return_VALUE(-EINVAL);
293
294 result = acpi_bus_get_device(battery->handle, &device);
295 if (result)
296 return_VALUE(result);
297
298 result = acpi_bus_get_status(device);
299 if (result)
300 return_VALUE(result);
301
302 /* Insertion? */
303
304 if (!battery->flags.present && device->status.battery_present) {
305
306 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n"));
307
308 /* Evalute _BIF to get certain static information */
309
310 result = acpi_battery_get_info(battery, &bif);
311 if (result)
312 return_VALUE(result);
313
314 battery->flags.power_unit = bif->power_unit;
315 battery->trips.warning = bif->design_capacity_warning;
316 battery->trips.low = bif->design_capacity_low;
317 kfree(bif);
318
319 /* See if alarms are supported, and if so, set default */
320
321 status = acpi_get_handle(battery->handle, "_BTP", &handle);
322 if (ACPI_SUCCESS(status)) {
323 battery->flags.alarm = 1;
324 acpi_battery_set_alarm(battery, battery->trips.warning);
325 }
326 }
327
328 /* Removal? */
329
330 else if (battery->flags.present && !device->status.battery_present) {
331 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
332 }
333
334 battery->flags.present = device->status.battery_present;
335
336 return_VALUE(result);
337}
338
339
340/* --------------------------------------------------------------------------
341 FS Interface (/proc)
342 -------------------------------------------------------------------------- */
343
344static struct proc_dir_entry *acpi_battery_dir;
345static int acpi_battery_read_info(struct seq_file *seq, void *offset)
346{
347 int result = 0;
348 struct acpi_battery *battery = (struct acpi_battery *) seq->private;
349 struct acpi_battery_info *bif = NULL;
350 char *units = "?";
351
352 ACPI_FUNCTION_TRACE("acpi_battery_read_info");
353
354 if (!battery)
355 goto end;
356
357 if (battery->flags.present)
358 seq_printf(seq, "present: yes\n");
359 else {
360 seq_printf(seq, "present: no\n");
361 goto end;
362 }
363
364 /* Battery Info (_BIF) */
365
366 result = acpi_battery_get_info(battery, &bif);
367 if (result || !bif) {
368 seq_printf(seq, "ERROR: Unable to read battery information\n");
369 goto end;
370 }
371
372 units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
373
374 if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
375 seq_printf(seq, "design capacity: unknown\n");
376 else
377 seq_printf(seq, "design capacity: %d %sh\n",
378 (u32) bif->design_capacity, units);
379
380 if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
381 seq_printf(seq, "last full capacity: unknown\n");
382 else
383 seq_printf(seq, "last full capacity: %d %sh\n",
384 (u32) bif->last_full_capacity, units);
385
386 switch ((u32) bif->battery_technology) {
387 case 0:
388 seq_printf(seq, "battery technology: non-rechargeable\n");
389 break;
390 case 1:
391 seq_printf(seq, "battery technology: rechargeable\n");
392 break;
393 default:
394 seq_printf(seq, "battery technology: unknown\n");
395 break;
396 }
397
398 if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
399 seq_printf(seq, "design voltage: unknown\n");
400 else
401 seq_printf(seq, "design voltage: %d mV\n",
402 (u32) bif->design_voltage);
403
404 seq_printf(seq, "design capacity warning: %d %sh\n",
405 (u32) bif->design_capacity_warning, units);
406 seq_printf(seq, "design capacity low: %d %sh\n",
407 (u32) bif->design_capacity_low, units);
408 seq_printf(seq, "capacity granularity 1: %d %sh\n",
409 (u32) bif->battery_capacity_granularity_1, units);
410 seq_printf(seq, "capacity granularity 2: %d %sh\n",
411 (u32) bif->battery_capacity_granularity_2, units);
412 seq_printf(seq, "model number: %s\n",
413 bif->model_number);
414 seq_printf(seq, "serial number: %s\n",
415 bif->serial_number);
416 seq_printf(seq, "battery type: %s\n",
417 bif->battery_type);
418 seq_printf(seq, "OEM info: %s\n",
419 bif->oem_info);
420
421end:
422 kfree(bif);
423
424 return_VALUE(0);
425}
426
427static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
428{
429 return single_open(file, acpi_battery_read_info, PDE(inode)->data);
430}
431
432
433static int
434acpi_battery_read_state (struct seq_file *seq, void *offset)
435{
436 int result = 0;
437 struct acpi_battery *battery = (struct acpi_battery *) seq->private;
438 struct acpi_battery_status *bst = NULL;
439 char *units = "?";
440
441 ACPI_FUNCTION_TRACE("acpi_battery_read_state");
442
443 if (!battery)
444 goto end;
445
446 if (battery->flags.present)
447 seq_printf(seq, "present: yes\n");
448 else {
449 seq_printf(seq, "present: no\n");
450 goto end;
451 }
452
453 /* Battery Units */
454
455 units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
456
457 /* Battery Status (_BST) */
458
459 result = acpi_battery_get_status(battery, &bst);
460 if (result || !bst) {
461 seq_printf(seq, "ERROR: Unable to read battery status\n");
462 goto end;
463 }
464
465 if (!(bst->state & 0x04))
466 seq_printf(seq, "capacity state: ok\n");
467 else
468 seq_printf(seq, "capacity state: critical\n");
469
470 if ((bst->state & 0x01) && (bst->state & 0x02)){
471 seq_printf(seq, "charging state: charging/discharging\n");
472 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
473 "Battery Charging and Discharging?\n"));
474 }
475 else if (bst->state & 0x01)
476 seq_printf(seq, "charging state: discharging\n");
477 else if (bst->state & 0x02)
478 seq_printf(seq, "charging state: charging\n");
479 else {
480 seq_printf(seq, "charging state: charged\n");
481 }
482
483 if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN)
484 seq_printf(seq, "present rate: unknown\n");
485 else
486 seq_printf(seq, "present rate: %d %s\n",
487 (u32) bst->present_rate, units);
488
489 if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
490 seq_printf(seq, "remaining capacity: unknown\n");
491 else
492 seq_printf(seq, "remaining capacity: %d %sh\n",
493 (u32) bst->remaining_capacity, units);
494
495 if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
496 seq_printf(seq, "present voltage: unknown\n");
497 else
498 seq_printf(seq, "present voltage: %d mV\n",
499 (u32) bst->present_voltage);
500
501end:
502 kfree(bst);
503
504 return_VALUE(0);
505}
506
507static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
508{
509 return single_open(file, acpi_battery_read_state, PDE(inode)->data);
510}
511
512
513static int
514acpi_battery_read_alarm (struct seq_file *seq, void *offset)
515{
516 struct acpi_battery *battery = (struct acpi_battery *) seq->private;
517 char *units = "?";
518
519 ACPI_FUNCTION_TRACE("acpi_battery_read_alarm");
520
521 if (!battery)
522 goto end;
523
524 if (!battery->flags.present) {
525 seq_printf(seq, "present: no\n");
526 goto end;
527 }
528
529 /* Battery Units */
530
531 units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
532
533 /* Battery Alarm */
534
535 seq_printf(seq, "alarm: ");
536 if (!battery->alarm)
537 seq_printf(seq, "unsupported\n");
538 else
539 seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units);
540
541end:
542 return_VALUE(0);
543}
544
545
546static ssize_t
547acpi_battery_write_alarm (
548 struct file *file,
549 const char __user *buffer,
550 size_t count,
551 loff_t *ppos)
552{
553 int result = 0;
554 char alarm_string[12] = {'\0'};
555 struct seq_file *m = (struct seq_file *)file->private_data;
556 struct acpi_battery *battery = (struct acpi_battery *)m->private;
557
558 ACPI_FUNCTION_TRACE("acpi_battery_write_alarm");
559
560 if (!battery || (count > sizeof(alarm_string) - 1))
561 return_VALUE(-EINVAL);
562
563 if (!battery->flags.present)
564 return_VALUE(-ENODEV);
565
566 if (copy_from_user(alarm_string, buffer, count))
567 return_VALUE(-EFAULT);
568
569 alarm_string[count] = '\0';
570
571 result = acpi_battery_set_alarm(battery,
572 simple_strtoul(alarm_string, NULL, 0));
573 if (result)
574 return_VALUE(result);
575
576 return_VALUE(count);
577}
578
579static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
580{
581 return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
582}
583
584static struct file_operations acpi_battery_info_ops = {
585 .open = acpi_battery_info_open_fs,
586 .read = seq_read,
587 .llseek = seq_lseek,
588 .release = single_release,
589 .owner = THIS_MODULE,
590};
591
592static struct file_operations acpi_battery_state_ops = {
593 .open = acpi_battery_state_open_fs,
594 .read = seq_read,
595 .llseek = seq_lseek,
596 .release = single_release,
597 .owner = THIS_MODULE,
598};
599
600static struct file_operations acpi_battery_alarm_ops = {
601 .open = acpi_battery_alarm_open_fs,
602 .read = seq_read,
603 .write = acpi_battery_write_alarm,
604 .llseek = seq_lseek,
605 .release = single_release,
606 .owner = THIS_MODULE,
607};
608
609static int
610acpi_battery_add_fs (
611 struct acpi_device *device)
612{
613 struct proc_dir_entry *entry = NULL;
614
615 ACPI_FUNCTION_TRACE("acpi_battery_add_fs");
616
617 if (!acpi_device_dir(device)) {
618 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
619 acpi_battery_dir);
620 if (!acpi_device_dir(device))
621 return_VALUE(-ENODEV);
622 acpi_device_dir(device)->owner = THIS_MODULE;
623 }
624
625 /* 'info' [R] */
626 entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
627 S_IRUGO, acpi_device_dir(device));
628 if (!entry)
629 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
630 "Unable to create '%s' fs entry\n",
631 ACPI_BATTERY_FILE_INFO));
632 else {
633 entry->proc_fops = &acpi_battery_info_ops;
634 entry->data = acpi_driver_data(device);
635 entry->owner = THIS_MODULE;
636 }
637
638 /* 'status' [R] */
639 entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS,
640 S_IRUGO, acpi_device_dir(device));
641 if (!entry)
642 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
643 "Unable to create '%s' fs entry\n",
644 ACPI_BATTERY_FILE_STATUS));
645 else {
646 entry->proc_fops = &acpi_battery_state_ops;
647 entry->data = acpi_driver_data(device);
648 entry->owner = THIS_MODULE;
649 }
650
651 /* 'alarm' [R/W] */
652 entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
653 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
654 if (!entry)
655 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
656 "Unable to create '%s' fs entry\n",
657 ACPI_BATTERY_FILE_ALARM));
658 else {
659 entry->proc_fops = &acpi_battery_alarm_ops;
660 entry->data = acpi_driver_data(device);
661 entry->owner = THIS_MODULE;
662 }
663
664 return_VALUE(0);
665}
666
667
668static int
669acpi_battery_remove_fs (
670 struct acpi_device *device)
671{
672 ACPI_FUNCTION_TRACE("acpi_battery_remove_fs");
673
674 if (acpi_device_dir(device)) {
675 remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
676 acpi_device_dir(device));
677 remove_proc_entry(ACPI_BATTERY_FILE_STATUS,
678 acpi_device_dir(device));
679 remove_proc_entry(ACPI_BATTERY_FILE_INFO,
680 acpi_device_dir(device));
681
682 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
683 acpi_device_dir(device) = NULL;
684 }
685
686 return_VALUE(0);
687}
688
689
690/* --------------------------------------------------------------------------
691 Driver Interface
692 -------------------------------------------------------------------------- */
693
694static void
695acpi_battery_notify (
696 acpi_handle handle,
697 u32 event,
698 void *data)
699{
700 struct acpi_battery *battery = (struct acpi_battery *) data;
701 struct acpi_device *device = NULL;
702
703 ACPI_FUNCTION_TRACE("acpi_battery_notify");
704
705 if (!battery)
706 return_VOID;
707
708 if (acpi_bus_get_device(handle, &device))
709 return_VOID;
710
711 switch (event) {
712 case ACPI_BATTERY_NOTIFY_STATUS:
713 case ACPI_BATTERY_NOTIFY_INFO:
714 acpi_battery_check(battery);
715 acpi_bus_generate_event(device, event, battery->flags.present);
716 break;
717 default:
718 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
719 "Unsupported event [0x%x]\n", event));
720 break;
721 }
722
723 return_VOID;
724}
725
726
727static int
728acpi_battery_add (
729 struct acpi_device *device)
730{
731 int result = 0;
732 acpi_status status = 0;
733 struct acpi_battery *battery = NULL;
734
735 ACPI_FUNCTION_TRACE("acpi_battery_add");
736
737 if (!device)
738 return_VALUE(-EINVAL);
739
740 battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL);
741 if (!battery)
742 return_VALUE(-ENOMEM);
743 memset(battery, 0, sizeof(struct acpi_battery));
744
745 battery->handle = device->handle;
746 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
747 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
748 acpi_driver_data(device) = battery;
749
750 result = acpi_battery_check(battery);
751 if (result)
752 goto end;
753
754 result = acpi_battery_add_fs(device);
755 if (result)
756 goto end;
757
758 status = acpi_install_notify_handler(battery->handle,
759 ACPI_DEVICE_NOTIFY, acpi_battery_notify, battery);
760 if (ACPI_FAILURE(status)) {
761 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
762 "Error installing notify handler\n"));
763 result = -ENODEV;
764 goto end;
765 }
766
767 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
768 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
769 device->status.battery_present?"present":"absent");
770
771end:
772 if (result) {
773 acpi_battery_remove_fs(device);
774 kfree(battery);
775 }
776
777 return_VALUE(result);
778}
779
780
781static int
782acpi_battery_remove (
783 struct acpi_device *device,
784 int type)
785{
786 acpi_status status = 0;
787 struct acpi_battery *battery = NULL;
788
789 ACPI_FUNCTION_TRACE("acpi_battery_remove");
790
791 if (!device || !acpi_driver_data(device))
792 return_VALUE(-EINVAL);
793
794 battery = (struct acpi_battery *) acpi_driver_data(device);
795
796 status = acpi_remove_notify_handler(battery->handle,
797 ACPI_DEVICE_NOTIFY, acpi_battery_notify);
798 if (ACPI_FAILURE(status))
799 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
800 "Error removing notify handler\n"));
801
802 acpi_battery_remove_fs(device);
803
804 kfree(battery);
805
806 return_VALUE(0);
807}
808
809
810static int __init
811acpi_battery_init (void)
812{
813 int result = 0;
814
815 ACPI_FUNCTION_TRACE("acpi_battery_init");
816
817 acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
818 if (!acpi_battery_dir)
819 return_VALUE(-ENODEV);
820 acpi_battery_dir->owner = THIS_MODULE;
821
822 result = acpi_bus_register_driver(&acpi_battery_driver);
823 if (result < 0) {
824 remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
825 return_VALUE(-ENODEV);
826 }
827
828 return_VALUE(0);
829}
830
831
832static void __exit
833acpi_battery_exit (void)
834{
835 ACPI_FUNCTION_TRACE("acpi_battery_exit");
836
837 acpi_bus_unregister_driver(&acpi_battery_driver);
838
839 remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
840
841 return_VOID;
842}
843
844
845module_init(acpi_battery_init);
846module_exit(acpi_battery_exit);
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
new file mode 100644
index 000000000000..4c010e7f11b8
--- /dev/null
+++ b/drivers/acpi/blacklist.c
@@ -0,0 +1,169 @@
1/*
2 * blacklist.c
3 *
4 * Check to see if the given machine has a known bad ACPI BIOS
5 * or if the BIOS is too old.
6 *
7 * Copyright (C) 2004 Len Brown <len.brown@intel.com>
8 * Copyright (C) 2002 Andy Grover <andrew.grover@intel.com>
9 *
10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or (at
15 * your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 *
26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 */
28
29
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/acpi.h>
34#include <acpi/acpi_bus.h>
35#include <linux/dmi.h>
36
37enum acpi_blacklist_predicates
38{
39 all_versions,
40 less_than_or_equal,
41 equal,
42 greater_than_or_equal,
43};
44
45struct acpi_blacklist_item
46{
47 char oem_id[7];
48 char oem_table_id[9];
49 u32 oem_revision;
50 acpi_table_type table;
51 enum acpi_blacklist_predicates oem_revision_predicate;
52 char *reason;
53 u32 is_critical_error;
54};
55
56/*
57 * POLICY: If *anything* doesn't work, put it on the blacklist.
58 * If they are critical errors, mark it critical, and abort driver load.
59 */
60static struct acpi_blacklist_item acpi_blacklist[] __initdata =
61{
62 /* Compaq Presario 1700 */
63 {"PTLTD ", " DSDT ", 0x06040000, ACPI_DSDT, less_than_or_equal, "Multiple problems", 1},
64 /* Sony FX120, FX140, FX150? */
65 {"SONY ", "U0 ", 0x20010313, ACPI_DSDT, less_than_or_equal, "ACPI driver problem", 1},
66 /* Compaq Presario 800, Insyde BIOS */
67 {"INT440", "SYSFexxx", 0x00001001, ACPI_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1},
68 /* IBM 600E - _ADR should return 7, but it returns 1 */
69 {"IBM ", "TP600E ", 0x00000105, ACPI_DSDT, less_than_or_equal, "Incorrect _ADR", 1},
70 {"ASUS\0\0", "P2B-S ", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1},
71
72 {""}
73};
74
75
76#if CONFIG_ACPI_BLACKLIST_YEAR
77
78static int __init
79blacklist_by_year(void)
80{
81 int year;
82 char *s = dmi_get_system_info(DMI_BIOS_DATE);
83
84 if (!s)
85 return 0;
86 if (!*s)
87 return 0;
88
89 s = strrchr(s, '/');
90 if (!s)
91 return 0;
92
93 s += 1;
94
95 year = simple_strtoul(s,NULL,0);
96
97 if (year < 100) { /* 2-digit year */
98 year += 1900;
99 if (year < 1996) /* no dates < spec 1.0 */
100 year += 100;
101 }
102
103 if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
104 printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), "
105 "acpi=force is required to enable ACPI\n",
106 year, CONFIG_ACPI_BLACKLIST_YEAR);
107 return 1;
108 }
109 return 0;
110}
111#else
112static inline int blacklist_by_year(void) { return 0; }
113#endif
114
115int __init
116acpi_blacklisted(void)
117{
118 int i = 0;
119 int blacklisted = 0;
120 struct acpi_table_header *table_header;
121
122 while (acpi_blacklist[i].oem_id[0] != '\0')
123 {
124 if (acpi_get_table_header_early(acpi_blacklist[i].table, &table_header)) {
125 i++;
126 continue;
127 }
128
129 if (strncmp(acpi_blacklist[i].oem_id, table_header->oem_id, 6)) {
130 i++;
131 continue;
132 }
133
134 if (strncmp(acpi_blacklist[i].oem_table_id, table_header->oem_table_id, 8)) {
135 i++;
136 continue;
137 }
138
139 if ((acpi_blacklist[i].oem_revision_predicate == all_versions)
140 || (acpi_blacklist[i].oem_revision_predicate == less_than_or_equal
141 && table_header->oem_revision <= acpi_blacklist[i].oem_revision)
142 || (acpi_blacklist[i].oem_revision_predicate == greater_than_or_equal
143 && table_header->oem_revision >= acpi_blacklist[i].oem_revision)
144 || (acpi_blacklist[i].oem_revision_predicate == equal
145 && table_header->oem_revision == acpi_blacklist[i].oem_revision)) {
146
147 printk(KERN_ERR PREFIX "Vendor \"%6.6s\" System \"%8.8s\" "
148 "Revision 0x%x has a known ACPI BIOS problem.\n",
149 acpi_blacklist[i].oem_id,
150 acpi_blacklist[i].oem_table_id,
151 acpi_blacklist[i].oem_revision);
152
153 printk(KERN_ERR PREFIX "Reason: %s. This is a %s error\n",
154 acpi_blacklist[i].reason,
155 (acpi_blacklist[i].is_critical_error ? "non-recoverable" : "recoverable"));
156
157 blacklisted = acpi_blacklist[i].is_critical_error;
158 break;
159 }
160 else {
161 i++;
162 }
163 }
164
165 blacklisted += blacklist_by_year();
166
167 return blacklisted;
168}
169
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
new file mode 100644
index 000000000000..4edff1738579
--- /dev/null
+++ b/drivers/acpi/bus.c
@@ -0,0 +1,775 @@
1/*
2 * acpi_bus.c - ACPI Bus Driver ($Revision: 80 $)
3 *
4 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/ioport.h>
28#include <linux/list.h>
29#include <linux/sched.h>
30#include <linux/pm.h>
31#include <linux/device.h>
32#include <linux/proc_fs.h>
33#ifdef CONFIG_X86
34#include <asm/mpspec.h>
35#endif
36#include <acpi/acpi_bus.h>
37#include <acpi/acpi_drivers.h>
38
39
40#define _COMPONENT ACPI_BUS_COMPONENT
41ACPI_MODULE_NAME ("acpi_bus")
42
43#ifdef CONFIG_X86
44extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
45#endif
46
47FADT_DESCRIPTOR acpi_fadt;
48EXPORT_SYMBOL(acpi_fadt);
49
50struct acpi_device *acpi_root;
51struct proc_dir_entry *acpi_root_dir;
52EXPORT_SYMBOL(acpi_root_dir);
53
54#define STRUCT_TO_INT(s) (*((int*)&s))
55
56/* --------------------------------------------------------------------------
57 Device Management
58 -------------------------------------------------------------------------- */
59
60int
61acpi_bus_get_device (
62 acpi_handle handle,
63 struct acpi_device **device)
64{
65 acpi_status status = AE_OK;
66
67 ACPI_FUNCTION_TRACE("acpi_bus_get_device");
68
69 if (!device)
70 return_VALUE(-EINVAL);
71
72 /* TBD: Support fixed-feature devices */
73
74 status = acpi_get_data(handle, acpi_bus_data_handler, (void**) device);
75 if (ACPI_FAILURE(status) || !*device) {
76 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "No context for object [%p]\n",
77 handle));
78 return_VALUE(-ENODEV);
79 }
80
81 return_VALUE(0);
82}
83EXPORT_SYMBOL(acpi_bus_get_device);
84
85int
86acpi_bus_get_status (
87 struct acpi_device *device)
88{
89 acpi_status status = AE_OK;
90 unsigned long sta = 0;
91
92 ACPI_FUNCTION_TRACE("acpi_bus_get_status");
93
94 if (!device)
95 return_VALUE(-EINVAL);
96
97 /*
98 * Evaluate _STA if present.
99 */
100 if (device->flags.dynamic_status) {
101 status = acpi_evaluate_integer(device->handle, "_STA", NULL, &sta);
102 if (ACPI_FAILURE(status))
103 return_VALUE(-ENODEV);
104 STRUCT_TO_INT(device->status) = (int) sta;
105 }
106
107 /*
108 * Otherwise we assume the status of our parent (unless we don't
109 * have one, in which case status is implied).
110 */
111 else if (device->parent)
112 device->status = device->parent->status;
113 else
114 STRUCT_TO_INT(device->status) = 0x0F;
115
116 if (device->status.functional && !device->status.present) {
117 printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
118 "functional but not present; setting present\n",
119 device->pnp.bus_id,
120 (u32) STRUCT_TO_INT(device->status));
121 device->status.present = 1;
122 }
123
124 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
125 device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status)));
126
127 return_VALUE(0);
128}
129EXPORT_SYMBOL(acpi_bus_get_status);
130
131
132/* --------------------------------------------------------------------------
133 Power Management
134 -------------------------------------------------------------------------- */
135
136int
137acpi_bus_get_power (
138 acpi_handle handle,
139 int *state)
140{
141 int result = 0;
142 acpi_status status = 0;
143 struct acpi_device *device = NULL;
144 unsigned long psc = 0;
145
146 ACPI_FUNCTION_TRACE("acpi_bus_get_power");
147
148 result = acpi_bus_get_device(handle, &device);
149 if (result)
150 return_VALUE(result);
151
152 *state = ACPI_STATE_UNKNOWN;
153
154 if (!device->flags.power_manageable) {
155 /* TBD: Non-recursive algorithm for walking up hierarchy */
156 if (device->parent)
157 *state = device->parent->power.state;
158 else
159 *state = ACPI_STATE_D0;
160 }
161 else {
162 /*
163 * Get the device's power state either directly (via _PSC) or
164 * indirectly (via power resources).
165 */
166 if (device->power.flags.explicit_get) {
167 status = acpi_evaluate_integer(device->handle, "_PSC",
168 NULL, &psc);
169 if (ACPI_FAILURE(status))
170 return_VALUE(-ENODEV);
171 device->power.state = (int) psc;
172 }
173 else if (device->power.flags.power_resources) {
174 result = acpi_power_get_inferred_state(device);
175 if (result)
176 return_VALUE(result);
177 }
178
179 *state = device->power.state;
180 }
181
182 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n",
183 device->pnp.bus_id, device->power.state));
184
185 return_VALUE(0);
186}
187EXPORT_SYMBOL(acpi_bus_get_power);
188
189
190int
191acpi_bus_set_power (
192 acpi_handle handle,
193 int state)
194{
195 int result = 0;
196 acpi_status status = AE_OK;
197 struct acpi_device *device = NULL;
198 char object_name[5] = {'_','P','S','0'+state,'\0'};
199
200 ACPI_FUNCTION_TRACE("acpi_bus_set_power");
201
202 result = acpi_bus_get_device(handle, &device);
203 if (result)
204 return_VALUE(result);
205
206 if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
207 return_VALUE(-EINVAL);
208
209 /* Make sure this is a valid target state */
210
211 if (!device->flags.power_manageable) {
212 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device is not power manageable\n"));
213 return_VALUE(-ENODEV);
214 }
215 if (state == device->power.state) {
216 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state));
217 return_VALUE(0);
218 }
219 if (!device->power.states[state].flags.valid) {
220 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n", state));
221 return_VALUE(-ENODEV);
222 }
223 if (device->parent && (state < device->parent->power.state)) {
224 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Cannot set device to a higher-powered state than parent\n"));
225 return_VALUE(-ENODEV);
226 }
227
228 /*
229 * Transition Power
230 * ----------------
231 * On transitions to a high-powered state we first apply power (via
232 * power resources) then evalute _PSx. Conversly for transitions to
233 * a lower-powered state.
234 */
235 if (state < device->power.state) {
236 if (device->power.flags.power_resources) {
237 result = acpi_power_transition(device, state);
238 if (result)
239 goto end;
240 }
241 if (device->power.states[state].flags.explicit_set) {
242 status = acpi_evaluate_object(device->handle,
243 object_name, NULL, NULL);
244 if (ACPI_FAILURE(status)) {
245 result = -ENODEV;
246 goto end;
247 }
248 }
249 }
250 else {
251 if (device->power.states[state].flags.explicit_set) {
252 status = acpi_evaluate_object(device->handle,
253 object_name, NULL, NULL);
254 if (ACPI_FAILURE(status)) {
255 result = -ENODEV;
256 goto end;
257 }
258 }
259 if (device->power.flags.power_resources) {
260 result = acpi_power_transition(device, state);
261 if (result)
262 goto end;
263 }
264 }
265
266end:
267 if (result)
268 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error transitioning device [%s] to D%d\n",
269 device->pnp.bus_id, state));
270 else
271 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] transitioned to D%d\n",
272 device->pnp.bus_id, state));
273
274 return_VALUE(result);
275}
276EXPORT_SYMBOL(acpi_bus_set_power);
277
278
279
280/* --------------------------------------------------------------------------
281 Event Management
282 -------------------------------------------------------------------------- */
283
284static DEFINE_SPINLOCK(acpi_bus_event_lock);
285
286LIST_HEAD(acpi_bus_event_list);
287DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
288
289extern int event_is_open;
290
291int
292acpi_bus_generate_event (
293 struct acpi_device *device,
294 u8 type,
295 int data)
296{
297 struct acpi_bus_event *event = NULL;
298 unsigned long flags = 0;
299
300 ACPI_FUNCTION_TRACE("acpi_bus_generate_event");
301
302 if (!device)
303 return_VALUE(-EINVAL);
304
305 /* drop event on the floor if no one's listening */
306 if (!event_is_open)
307 return_VALUE(0);
308
309 event = kmalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC);
310 if (!event)
311 return_VALUE(-ENOMEM);
312
313 strcpy(event->device_class, device->pnp.device_class);
314 strcpy(event->bus_id, device->pnp.bus_id);
315 event->type = type;
316 event->data = data;
317
318 spin_lock_irqsave(&acpi_bus_event_lock, flags);
319 list_add_tail(&event->node, &acpi_bus_event_list);
320 spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
321
322 wake_up_interruptible(&acpi_bus_event_queue);
323
324 return_VALUE(0);
325}
326EXPORT_SYMBOL(acpi_bus_generate_event);
327
328int
329acpi_bus_receive_event (
330 struct acpi_bus_event *event)
331{
332 unsigned long flags = 0;
333 struct acpi_bus_event *entry = NULL;
334
335 DECLARE_WAITQUEUE(wait, current);
336
337 ACPI_FUNCTION_TRACE("acpi_bus_receive_event");
338
339 if (!event)
340 return_VALUE(-EINVAL);
341
342 if (list_empty(&acpi_bus_event_list)) {
343
344 set_current_state(TASK_INTERRUPTIBLE);
345 add_wait_queue(&acpi_bus_event_queue, &wait);
346
347 if (list_empty(&acpi_bus_event_list))
348 schedule();
349
350 remove_wait_queue(&acpi_bus_event_queue, &wait);
351 set_current_state(TASK_RUNNING);
352
353 if (signal_pending(current))
354 return_VALUE(-ERESTARTSYS);
355 }
356
357 spin_lock_irqsave(&acpi_bus_event_lock, flags);
358 entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node);
359 if (entry)
360 list_del(&entry->node);
361 spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
362
363 if (!entry)
364 return_VALUE(-ENODEV);
365
366 memcpy(event, entry, sizeof(struct acpi_bus_event));
367
368 kfree(entry);
369
370 return_VALUE(0);
371}
372EXPORT_SYMBOL(acpi_bus_receive_event);
373
374
375/* --------------------------------------------------------------------------
376 Notification Handling
377 -------------------------------------------------------------------------- */
378
379static int
380acpi_bus_check_device (
381 struct acpi_device *device,
382 int *status_changed)
383{
384 acpi_status status = 0;
385 struct acpi_device_status old_status;
386
387 ACPI_FUNCTION_TRACE("acpi_bus_check_device");
388
389 if (!device)
390 return_VALUE(-EINVAL);
391
392 if (status_changed)
393 *status_changed = 0;
394
395 old_status = device->status;
396
397 /*
398 * Make sure this device's parent is present before we go about
399 * messing with the device.
400 */
401 if (device->parent && !device->parent->status.present) {
402 device->status = device->parent->status;
403 if (STRUCT_TO_INT(old_status) != STRUCT_TO_INT(device->status)) {
404 if (status_changed)
405 *status_changed = 1;
406 }
407 return_VALUE(0);
408 }
409
410 status = acpi_bus_get_status(device);
411 if (ACPI_FAILURE(status))
412 return_VALUE(-ENODEV);
413
414 if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status))
415 return_VALUE(0);
416
417 if (status_changed)
418 *status_changed = 1;
419
420 /*
421 * Device Insertion/Removal
422 */
423 if ((device->status.present) && !(old_status.present)) {
424 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
425 /* TBD: Handle device insertion */
426 }
427 else if (!(device->status.present) && (old_status.present)) {
428 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n"));
429 /* TBD: Handle device removal */
430 }
431
432 return_VALUE(0);
433}
434
435
436static int
437acpi_bus_check_scope (
438 struct acpi_device *device)
439{
440 int result = 0;
441 int status_changed = 0;
442
443 ACPI_FUNCTION_TRACE("acpi_bus_check_scope");
444
445 if (!device)
446 return_VALUE(-EINVAL);
447
448 /* Status Change? */
449 result = acpi_bus_check_device(device, &status_changed);
450 if (result)
451 return_VALUE(result);
452
453 if (!status_changed)
454 return_VALUE(0);
455
456 /*
457 * TBD: Enumerate child devices within this device's scope and
458 * run acpi_bus_check_device()'s on them.
459 */
460
461 return_VALUE(0);
462}
463
464
465/**
466 * acpi_bus_notify
467 * ---------------
468 * Callback for all 'system-level' device notifications (values 0x00-0x7F).
469 */
470static void
471acpi_bus_notify (
472 acpi_handle handle,
473 u32 type,
474 void *data)
475{
476 int result = 0;
477 struct acpi_device *device = NULL;
478
479 ACPI_FUNCTION_TRACE("acpi_bus_notify");
480
481 if (acpi_bus_get_device(handle, &device))
482 return_VOID;
483
484 switch (type) {
485
486 case ACPI_NOTIFY_BUS_CHECK:
487 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS CHECK notification for device [%s]\n",
488 device->pnp.bus_id));
489 result = acpi_bus_check_scope(device);
490 /*
491 * TBD: We'll need to outsource certain events to non-ACPI
492 * drivers via the device manager (device.c).
493 */
494 break;
495
496 case ACPI_NOTIFY_DEVICE_CHECK:
497 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK notification for device [%s]\n",
498 device->pnp.bus_id));
499 result = acpi_bus_check_device(device, NULL);
500 /*
501 * TBD: We'll need to outsource certain events to non-ACPI
502 * drivers via the device manager (device.c).
503 */
504 break;
505
506 case ACPI_NOTIFY_DEVICE_WAKE:
507 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE WAKE notification for device [%s]\n",
508 device->pnp.bus_id));
509 /* TBD */
510 break;
511
512 case ACPI_NOTIFY_EJECT_REQUEST:
513 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received EJECT REQUEST notification for device [%s]\n",
514 device->pnp.bus_id));
515 /* TBD */
516 break;
517
518 case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
519 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK LIGHT notification for device [%s]\n",
520 device->pnp.bus_id));
521 /* TBD: Exactly what does 'light' mean? */
522 break;
523
524 case ACPI_NOTIFY_FREQUENCY_MISMATCH:
525 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received FREQUENCY MISMATCH notification for device [%s]\n",
526 device->pnp.bus_id));
527 /* TBD */
528 break;
529
530 case ACPI_NOTIFY_BUS_MODE_MISMATCH:
531 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS MODE MISMATCH notification for device [%s]\n",
532 device->pnp.bus_id));
533 /* TBD */
534 break;
535
536 case ACPI_NOTIFY_POWER_FAULT:
537 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received POWER FAULT notification for device [%s]\n",
538 device->pnp.bus_id));
539 /* TBD */
540 break;
541
542 default:
543 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received unknown/unsupported notification [%08x]\n",
544 type));
545 break;
546 }
547
548 return_VOID;
549}
550
551/* --------------------------------------------------------------------------
552 Initialization/Cleanup
553 -------------------------------------------------------------------------- */
554
555static int __init
556acpi_bus_init_irq (void)
557{
558 acpi_status status = AE_OK;
559 union acpi_object arg = {ACPI_TYPE_INTEGER};
560 struct acpi_object_list arg_list = {1, &arg};
561 char *message = NULL;
562
563 ACPI_FUNCTION_TRACE("acpi_bus_init_irq");
564
565 /*
566 * Let the system know what interrupt model we are using by
567 * evaluating the \_PIC object, if exists.
568 */
569
570 switch (acpi_irq_model) {
571 case ACPI_IRQ_MODEL_PIC:
572 message = "PIC";
573 break;
574 case ACPI_IRQ_MODEL_IOAPIC:
575 message = "IOAPIC";
576 break;
577 case ACPI_IRQ_MODEL_IOSAPIC:
578 message = "IOSAPIC";
579 break;
580 default:
581 printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n");
582 return_VALUE(-ENODEV);
583 }
584
585 printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message);
586
587 arg.integer.value = acpi_irq_model;
588
589 status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL);
590 if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
591 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PIC\n"));
592 return_VALUE(-ENODEV);
593 }
594
595 return_VALUE(0);
596}
597
598
599void __init
600acpi_early_init (void)
601{
602 acpi_status status = AE_OK;
603 struct acpi_buffer buffer = {sizeof(acpi_fadt), &acpi_fadt};
604
605 ACPI_FUNCTION_TRACE("acpi_early_init");
606
607 if (acpi_disabled)
608 return_VOID;
609
610 /* enable workarounds, unless strict ACPI spec. compliance */
611 if (!acpi_strict)
612 acpi_gbl_enable_interpreter_slack = TRUE;
613
614 status = acpi_initialize_subsystem();
615 if (ACPI_FAILURE(status)) {
616 printk(KERN_ERR PREFIX "Unable to initialize the ACPI Interpreter\n");
617 goto error0;
618 }
619
620 status = acpi_load_tables();
621 if (ACPI_FAILURE(status)) {
622 printk(KERN_ERR PREFIX "Unable to load the System Description Tables\n");
623 goto error0;
624 }
625
626 /*
627 * Get a separate copy of the FADT for use by other drivers.
628 */
629 status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer);
630 if (ACPI_FAILURE(status)) {
631 printk(KERN_ERR PREFIX "Unable to get the FADT\n");
632 goto error0;
633 }
634
635#ifdef CONFIG_X86
636 if (!acpi_ioapic) {
637 extern acpi_interrupt_flags acpi_sci_flags;
638
639 /* compatible (0) means level (3) */
640 if (acpi_sci_flags.trigger == 0)
641 acpi_sci_flags.trigger = 3;
642
643 /* Set PIC-mode SCI trigger type */
644 acpi_pic_sci_set_trigger(acpi_fadt.sci_int, acpi_sci_flags.trigger);
645 } else {
646 extern int acpi_sci_override_gsi;
647 /*
648 * now that acpi_fadt is initialized,
649 * update it with result from INT_SRC_OVR parsing
650 */
651 acpi_fadt.sci_int = acpi_sci_override_gsi;
652 }
653#endif
654
655 status = acpi_enable_subsystem(~(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE));
656 if (ACPI_FAILURE(status)) {
657 printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
658 goto error0;
659 }
660
661 return_VOID;
662
663error0:
664 disable_acpi();
665 return_VOID;
666}
667
668static int __init
669acpi_bus_init (void)
670{
671 int result = 0;
672 acpi_status status = AE_OK;
673 extern acpi_status acpi_os_initialize1(void);
674
675 ACPI_FUNCTION_TRACE("acpi_bus_init");
676
677 status = acpi_os_initialize1();
678
679 status = acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE);
680 if (ACPI_FAILURE(status)) {
681 printk(KERN_ERR PREFIX "Unable to start the ACPI Interpreter\n");
682 goto error1;
683 }
684
685 if (ACPI_FAILURE(status)) {
686 printk(KERN_ERR PREFIX "Unable to initialize ACPI OS objects\n");
687 goto error1;
688 }
689#ifdef CONFIG_ACPI_EC
690 /*
691 * ACPI 2.0 requires the EC driver to be loaded and work before
692 * the EC device is found in the namespace (i.e. before acpi_initialize_objects()
693 * is called).
694 *
695 * This is accomplished by looking for the ECDT table, and getting
696 * the EC parameters out of that.
697 */
698 status = acpi_ec_ecdt_probe();
699 /* Ignore result. Not having an ECDT is not fatal. */
700#endif
701
702 status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
703 if (ACPI_FAILURE(status)) {
704 printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");
705 goto error1;
706 }
707
708 printk(KERN_INFO PREFIX "Interpreter enabled\n");
709
710 /*
711 * Get the system interrupt model and evaluate \_PIC.
712 */
713 result = acpi_bus_init_irq();
714 if (result)
715 goto error1;
716
717 /*
718 * Register the for all standard device notifications.
719 */
720 status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL);
721 if (ACPI_FAILURE(status)) {
722 printk(KERN_ERR PREFIX "Unable to register for device notifications\n");
723 goto error1;
724 }
725
726 /*
727 * Create the top ACPI proc directory
728 */
729 acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL);
730
731 return_VALUE(0);
732
733 /* Mimic structured exception handling */
734error1:
735 acpi_terminate();
736 return_VALUE(-ENODEV);
737}
738
739decl_subsys(acpi,NULL,NULL);
740
741static int __init acpi_init (void)
742{
743 int result = 0;
744
745 ACPI_FUNCTION_TRACE("acpi_init");
746
747 printk(KERN_INFO PREFIX "Subsystem revision %08x\n",
748 ACPI_CA_VERSION);
749
750 if (acpi_disabled) {
751 printk(KERN_INFO PREFIX "Interpreter disabled.\n");
752 return_VALUE(-ENODEV);
753 }
754
755 firmware_register(&acpi_subsys);
756
757 result = acpi_bus_init();
758
759 if (!result) {
760#ifdef CONFIG_PM
761 if (!PM_IS_ACTIVE())
762 pm_active = 1;
763 else {
764 printk(KERN_INFO PREFIX "APM is already active, exiting\n");
765 disable_acpi();
766 result = -ENODEV;
767 }
768#endif
769 } else
770 disable_acpi();
771
772 return_VALUE(result);
773}
774
775subsys_initcall(acpi_init);
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
new file mode 100644
index 000000000000..ec4430e3053f
--- /dev/null
+++ b/drivers/acpi/button.c
@@ -0,0 +1,558 @@
1/*
2 * acpi_button.c - ACPI Button Driver ($Revision: 30 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/types.h>
30#include <linux/proc_fs.h>
31#include <linux/seq_file.h>
32#include <acpi/acpi_bus.h>
33#include <acpi/acpi_drivers.h>
34
35
36#define ACPI_BUTTON_COMPONENT 0x00080000
37#define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver"
38#define ACPI_BUTTON_CLASS "button"
39#define ACPI_BUTTON_FILE_INFO "info"
40#define ACPI_BUTTON_FILE_STATE "state"
41#define ACPI_BUTTON_TYPE_UNKNOWN 0x00
42#define ACPI_BUTTON_NOTIFY_STATUS 0x80
43
44#define ACPI_BUTTON_SUBCLASS_POWER "power"
45#define ACPI_BUTTON_HID_POWER "PNP0C0C"
46#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button (CM)"
47#define ACPI_BUTTON_DEVICE_NAME_POWERF "Power Button (FF)"
48#define ACPI_BUTTON_TYPE_POWER 0x01
49#define ACPI_BUTTON_TYPE_POWERF 0x02
50
51#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep"
52#define ACPI_BUTTON_HID_SLEEP "PNP0C0E"
53#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button (CM)"
54#define ACPI_BUTTON_DEVICE_NAME_SLEEPF "Sleep Button (FF)"
55#define ACPI_BUTTON_TYPE_SLEEP 0x03
56#define ACPI_BUTTON_TYPE_SLEEPF 0x04
57
58#define ACPI_BUTTON_SUBCLASS_LID "lid"
59#define ACPI_BUTTON_HID_LID "PNP0C0D"
60#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch"
61#define ACPI_BUTTON_TYPE_LID 0x05
62
63#define _COMPONENT ACPI_BUTTON_COMPONENT
64ACPI_MODULE_NAME ("acpi_button")
65
66MODULE_AUTHOR("Paul Diefenbaugh");
67MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
68MODULE_LICENSE("GPL");
69
70
71static int acpi_button_add (struct acpi_device *device);
72static int acpi_button_remove (struct acpi_device *device, int type);
73static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
74static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
75
76static struct acpi_driver acpi_button_driver = {
77 .name = ACPI_BUTTON_DRIVER_NAME,
78 .class = ACPI_BUTTON_CLASS,
79 .ids = "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E",
80 .ops = {
81 .add = acpi_button_add,
82 .remove = acpi_button_remove,
83 },
84};
85
86struct acpi_button {
87 acpi_handle handle;
88 struct acpi_device *device; /* Fixed button kludge */
89 u8 type;
90 unsigned long pushed;
91};
92
93static struct file_operations acpi_button_info_fops = {
94 .open = acpi_button_info_open_fs,
95 .read = seq_read,
96 .llseek = seq_lseek,
97 .release = single_release,
98};
99
100static struct file_operations acpi_button_state_fops = {
101 .open = acpi_button_state_open_fs,
102 .read = seq_read,
103 .llseek = seq_lseek,
104 .release = single_release,
105};
106/* --------------------------------------------------------------------------
107 FS Interface (/proc)
108 -------------------------------------------------------------------------- */
109
110static struct proc_dir_entry *acpi_button_dir;
111
112static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
113{
114 struct acpi_button *button = (struct acpi_button *) seq->private;
115
116 ACPI_FUNCTION_TRACE("acpi_button_info_seq_show");
117
118 if (!button || !button->device)
119 return_VALUE(0);
120
121 seq_printf(seq, "type: %s\n",
122 acpi_device_name(button->device));
123
124 return_VALUE(0);
125}
126
127static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
128{
129 return single_open(file, acpi_button_info_seq_show, PDE(inode)->data);
130}
131
132static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
133{
134 struct acpi_button *button = (struct acpi_button *) seq->private;
135 acpi_status status;
136 unsigned long state;
137
138 ACPI_FUNCTION_TRACE("acpi_button_state_seq_show");
139
140 if (!button || !button->device)
141 return_VALUE(0);
142
143 status = acpi_evaluate_integer(button->handle,"_LID",NULL,&state);
144 if (ACPI_FAILURE(status)) {
145 seq_printf(seq, "state: unsupported\n");
146 }
147 else{
148 seq_printf(seq, "state: %s\n", (state ? "open" : "closed"));
149 }
150
151 return_VALUE(0);
152}
153
154static int acpi_button_state_open_fs(struct inode *inode, struct file *file)
155{
156 return single_open(file, acpi_button_state_seq_show, PDE(inode)->data);
157}
158
159static int
160acpi_button_add_fs (
161 struct acpi_device *device)
162{
163 struct proc_dir_entry *entry = NULL;
164 struct acpi_button *button = NULL;
165
166 ACPI_FUNCTION_TRACE("acpi_button_add_fs");
167
168 if (!device || !acpi_driver_data(device))
169 return_VALUE(-EINVAL);
170
171 button = acpi_driver_data(device);
172
173 switch (button->type) {
174 case ACPI_BUTTON_TYPE_POWER:
175 case ACPI_BUTTON_TYPE_POWERF:
176 entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER,
177 acpi_button_dir);
178 break;
179 case ACPI_BUTTON_TYPE_SLEEP:
180 case ACPI_BUTTON_TYPE_SLEEPF:
181 entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP,
182 acpi_button_dir);
183 break;
184 case ACPI_BUTTON_TYPE_LID:
185 entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID,
186 acpi_button_dir);
187 break;
188 }
189
190 if (!entry)
191 return_VALUE(-ENODEV);
192 entry->owner = THIS_MODULE;
193
194 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry);
195 if (!acpi_device_dir(device))
196 return_VALUE(-ENODEV);
197 acpi_device_dir(device)->owner = THIS_MODULE;
198
199 /* 'info' [R] */
200 entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
201 S_IRUGO, acpi_device_dir(device));
202 if (!entry)
203 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
204 "Unable to create '%s' fs entry\n",
205 ACPI_BUTTON_FILE_INFO));
206 else {
207 entry->proc_fops = &acpi_button_info_fops;
208 entry->data = acpi_driver_data(device);
209 entry->owner = THIS_MODULE;
210 }
211
212 /* show lid state [R] */
213 if (button->type == ACPI_BUTTON_TYPE_LID) {
214 entry = create_proc_entry(ACPI_BUTTON_FILE_STATE,
215 S_IRUGO, acpi_device_dir(device));
216 if (!entry)
217 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
218 "Unable to create '%s' fs entry\n",
219 ACPI_BUTTON_FILE_INFO));
220 else {
221 entry->proc_fops = &acpi_button_state_fops;
222 entry->data = acpi_driver_data(device);
223 entry->owner = THIS_MODULE;
224 }
225 }
226
227 return_VALUE(0);
228}
229
230
231static int
232acpi_button_remove_fs (
233 struct acpi_device *device)
234{
235 struct acpi_button *button = NULL;
236
237 ACPI_FUNCTION_TRACE("acpi_button_remove_fs");
238
239 button = acpi_driver_data(device);
240 if (acpi_device_dir(device)) {
241 if (button->type == ACPI_BUTTON_TYPE_LID)
242 remove_proc_entry(ACPI_BUTTON_FILE_STATE,
243 acpi_device_dir(device));
244 remove_proc_entry(ACPI_BUTTON_FILE_INFO,
245 acpi_device_dir(device));
246
247 remove_proc_entry(acpi_device_bid(device),
248 acpi_device_dir(device)->parent);
249
250
251 switch (button->type) {
252 case ACPI_BUTTON_TYPE_POWER:
253 case ACPI_BUTTON_TYPE_POWERF:
254 remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER,
255 acpi_button_dir);
256 break;
257 case ACPI_BUTTON_TYPE_SLEEP:
258 case ACPI_BUTTON_TYPE_SLEEPF:
259 remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP,
260 acpi_button_dir);
261 break;
262 case ACPI_BUTTON_TYPE_LID:
263 remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID,
264 acpi_button_dir);
265 break;
266 }
267 acpi_device_dir(device) = NULL;
268 }
269
270 return_VALUE(0);
271}
272
273
274/* --------------------------------------------------------------------------
275 Driver Interface
276 -------------------------------------------------------------------------- */
277
278static void
279acpi_button_notify (
280 acpi_handle handle,
281 u32 event,
282 void *data)
283{
284 struct acpi_button *button = (struct acpi_button *) data;
285
286 ACPI_FUNCTION_TRACE("acpi_button_notify");
287
288 if (!button || !button->device)
289 return_VOID;
290
291 switch (event) {
292 case ACPI_BUTTON_NOTIFY_STATUS:
293 acpi_bus_generate_event(button->device, event, ++button->pushed);
294 break;
295 default:
296 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
297 "Unsupported event [0x%x]\n", event));
298 break;
299 }
300
301 return_VOID;
302}
303
304
305static acpi_status
306acpi_button_notify_fixed (
307 void *data)
308{
309 struct acpi_button *button = (struct acpi_button *) data;
310
311 ACPI_FUNCTION_TRACE("acpi_button_notify_fixed");
312
313 if (!button)
314 return_ACPI_STATUS(AE_BAD_PARAMETER);
315
316 acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button);
317
318 return_ACPI_STATUS(AE_OK);
319}
320
321
322static int
323acpi_button_add (
324 struct acpi_device *device)
325{
326 int result = 0;
327 acpi_status status = AE_OK;
328 struct acpi_button *button = NULL;
329
330 static struct acpi_device *power_button;
331 static struct acpi_device *sleep_button;
332 static struct acpi_device *lid_button;
333
334 ACPI_FUNCTION_TRACE("acpi_button_add");
335
336 if (!device)
337 return_VALUE(-EINVAL);
338
339 button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL);
340 if (!button)
341 return_VALUE(-ENOMEM);
342 memset(button, 0, sizeof(struct acpi_button));
343
344 button->device = device;
345 button->handle = device->handle;
346 acpi_driver_data(device) = button;
347
348 /*
349 * Determine the button type (via hid), as fixed-feature buttons
350 * need to be handled a bit differently than generic-space.
351 */
352 if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) {
353 button->type = ACPI_BUTTON_TYPE_POWER;
354 strcpy(acpi_device_name(device),
355 ACPI_BUTTON_DEVICE_NAME_POWER);
356 sprintf(acpi_device_class(device), "%s/%s",
357 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
358 }
359 else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) {
360 button->type = ACPI_BUTTON_TYPE_POWERF;
361 strcpy(acpi_device_name(device),
362 ACPI_BUTTON_DEVICE_NAME_POWERF);
363 sprintf(acpi_device_class(device), "%s/%s",
364 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
365 }
366 else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) {
367 button->type = ACPI_BUTTON_TYPE_SLEEP;
368 strcpy(acpi_device_name(device),
369 ACPI_BUTTON_DEVICE_NAME_SLEEP);
370 sprintf(acpi_device_class(device), "%s/%s",
371 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
372 }
373 else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) {
374 button->type = ACPI_BUTTON_TYPE_SLEEPF;
375 strcpy(acpi_device_name(device),
376 ACPI_BUTTON_DEVICE_NAME_SLEEPF);
377 sprintf(acpi_device_class(device), "%s/%s",
378 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
379 }
380 else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) {
381 button->type = ACPI_BUTTON_TYPE_LID;
382 strcpy(acpi_device_name(device),
383 ACPI_BUTTON_DEVICE_NAME_LID);
384 sprintf(acpi_device_class(device), "%s/%s",
385 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
386 }
387 else {
388 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported hid [%s]\n",
389 acpi_device_hid(device)));
390 result = -ENODEV;
391 goto end;
392 }
393
394 /*
395 * Ensure only one button of each type is used.
396 */
397 switch (button->type) {
398 case ACPI_BUTTON_TYPE_POWER:
399 case ACPI_BUTTON_TYPE_POWERF:
400 if (!power_button)
401 power_button = device;
402 else {
403 kfree(button);
404 return_VALUE(-ENODEV);
405 }
406 break;
407 case ACPI_BUTTON_TYPE_SLEEP:
408 case ACPI_BUTTON_TYPE_SLEEPF:
409 if (!sleep_button)
410 sleep_button = device;
411 else {
412 kfree(button);
413 return_VALUE(-ENODEV);
414 }
415 break;
416 case ACPI_BUTTON_TYPE_LID:
417 if (!lid_button)
418 lid_button = device;
419 else {
420 kfree(button);
421 return_VALUE(-ENODEV);
422 }
423 break;
424 }
425
426 result = acpi_button_add_fs(device);
427 if (result)
428 goto end;
429
430 switch (button->type) {
431 case ACPI_BUTTON_TYPE_POWERF:
432 status = acpi_install_fixed_event_handler (
433 ACPI_EVENT_POWER_BUTTON,
434 acpi_button_notify_fixed,
435 button);
436 break;
437 case ACPI_BUTTON_TYPE_SLEEPF:
438 status = acpi_install_fixed_event_handler (
439 ACPI_EVENT_SLEEP_BUTTON,
440 acpi_button_notify_fixed,
441 button);
442 break;
443 default:
444 status = acpi_install_notify_handler (
445 button->handle,
446 ACPI_DEVICE_NOTIFY,
447 acpi_button_notify,
448 button);
449 break;
450 }
451
452 if (ACPI_FAILURE(status)) {
453 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
454 "Error installing notify handler\n"));
455 result = -ENODEV;
456 goto end;
457 }
458
459 if (device->wakeup.flags.valid) {
460 /* Button's GPE is run-wake GPE */
461 acpi_set_gpe_type(device->wakeup.gpe_device,
462 device->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
463 acpi_enable_gpe(device->wakeup.gpe_device,
464 device->wakeup.gpe_number, ACPI_NOT_ISR);
465 device->wakeup.state.enabled = 1;
466 }
467
468 printk(KERN_INFO PREFIX "%s [%s]\n",
469 acpi_device_name(device), acpi_device_bid(device));
470
471end:
472 if (result) {
473 acpi_button_remove_fs(device);
474 kfree(button);
475 }
476
477 return_VALUE(result);
478}
479
480
481static int
482acpi_button_remove (struct acpi_device *device, int type)
483{
484 acpi_status status = 0;
485 struct acpi_button *button = NULL;
486
487 ACPI_FUNCTION_TRACE("acpi_button_remove");
488
489 if (!device || !acpi_driver_data(device))
490 return_VALUE(-EINVAL);
491
492 button = acpi_driver_data(device);
493
494 /* Unregister for device notifications. */
495 switch (button->type) {
496 case ACPI_BUTTON_TYPE_POWERF:
497 status = acpi_remove_fixed_event_handler(
498 ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed);
499 break;
500 case ACPI_BUTTON_TYPE_SLEEPF:
501 status = acpi_remove_fixed_event_handler(
502 ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed);
503 break;
504 default:
505 status = acpi_remove_notify_handler(button->handle,
506 ACPI_DEVICE_NOTIFY, acpi_button_notify);
507 break;
508 }
509
510 if (ACPI_FAILURE(status))
511 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
512 "Error removing notify handler\n"));
513
514 acpi_button_remove_fs(device);
515
516 kfree(button);
517
518 return_VALUE(0);
519}
520
521
522static int __init
523acpi_button_init (void)
524{
525 int result = 0;
526
527 ACPI_FUNCTION_TRACE("acpi_button_init");
528
529 acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
530 if (!acpi_button_dir)
531 return_VALUE(-ENODEV);
532 acpi_button_dir->owner = THIS_MODULE;
533
534 result = acpi_bus_register_driver(&acpi_button_driver);
535 if (result < 0) {
536 remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
537 return_VALUE(-ENODEV);
538 }
539
540 return_VALUE(0);
541}
542
543
544static void __exit
545acpi_button_exit (void)
546{
547 ACPI_FUNCTION_TRACE("acpi_button_exit");
548
549 acpi_bus_unregister_driver(&acpi_button_driver);
550
551 remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
552
553 return_VOID;
554}
555
556
557module_init(acpi_button_init);
558module_exit(acpi_button_exit);
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
new file mode 100644
index 000000000000..5a0adbf8bc04
--- /dev/null
+++ b/drivers/acpi/container.c
@@ -0,0 +1,303 @@
1/*
2 * acpi_container.c - ACPI Generic Container Driver
3 * ($Revision: )
4 *
5 * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
6 * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
7 * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
8 * Copyright (C) 2004 Intel Corp.
9 * Copyright (C) 2004 FUJITSU LIMITED
10 *
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 (at
16 * your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 *
27 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 */
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/types.h>
33#include <linux/acpi.h>
34#include <acpi/acpi_bus.h>
35#include <acpi/acpi_drivers.h>
36#include <acpi/container.h>
37
38#define ACPI_CONTAINER_DRIVER_NAME "ACPI container driver"
39#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device"
40#define ACPI_CONTAINER_CLASS "container"
41
42#define INSTALL_NOTIFY_HANDLER 1
43#define UNINSTALL_NOTIFY_HANDLER 2
44
45#define ACPI_CONTAINER_COMPONENT 0x01000000
46#define _COMPONENT ACPI_CONTAINER_COMPONENT
47ACPI_MODULE_NAME ("acpi_container")
48
49MODULE_AUTHOR("Anil S Keshavamurthy");
50MODULE_DESCRIPTION(ACPI_CONTAINER_DRIVER_NAME);
51MODULE_LICENSE("GPL");
52
53#define ACPI_STA_PRESENT (0x00000001)
54
55static int acpi_container_add(struct acpi_device *device);
56static int acpi_container_remove(struct acpi_device *device, int type);
57
58static struct acpi_driver acpi_container_driver = {
59 .name = ACPI_CONTAINER_DRIVER_NAME,
60 .class = ACPI_CONTAINER_CLASS,
61 .ids = "ACPI0004,PNP0A05,PNP0A06",
62 .ops = {
63 .add = acpi_container_add,
64 .remove = acpi_container_remove,
65 },
66};
67
68
69/*******************************************************************/
70
71static int
72is_device_present(acpi_handle handle)
73{
74 acpi_handle temp;
75 acpi_status status;
76 unsigned long sta;
77
78 ACPI_FUNCTION_TRACE("is_device_present");
79
80 status = acpi_get_handle(handle, "_STA", &temp);
81 if (ACPI_FAILURE(status))
82 return_VALUE(1); /* _STA not found, assmue device present */
83
84 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
85 if (ACPI_FAILURE(status))
86 return_VALUE(0); /* Firmware error */
87
88 return_VALUE((sta & ACPI_STA_PRESENT) == ACPI_STA_PRESENT);
89}
90
91/*******************************************************************/
92static int
93acpi_container_add(struct acpi_device *device)
94{
95 struct acpi_container *container;
96
97 ACPI_FUNCTION_TRACE("acpi_container_add");
98
99 if (!device) {
100 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "device is NULL\n"));
101 return_VALUE(-EINVAL);
102 }
103
104 container = kmalloc(sizeof(struct acpi_container), GFP_KERNEL);
105 if(!container)
106 return_VALUE(-ENOMEM);
107
108 memset(container, 0, sizeof(struct acpi_container));
109 container->handle = device->handle;
110 strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
111 strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
112 acpi_driver_data(device) = container;
113
114 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n", \
115 acpi_device_name(device), acpi_device_bid(device)));
116
117
118 return_VALUE(0);
119}
120
121static int
122acpi_container_remove(struct acpi_device *device, int type)
123{
124 acpi_status status = AE_OK;
125 struct acpi_container *pc = NULL;
126 pc = (struct acpi_container*) acpi_driver_data(device);
127
128 if (pc)
129 kfree(pc);
130
131 return status;
132}
133
134
135static int
136container_device_add(struct acpi_device **device, acpi_handle handle)
137{
138 acpi_handle phandle;
139 struct acpi_device *pdev;
140 int result;
141
142 ACPI_FUNCTION_TRACE("container_device_add");
143
144 if (acpi_get_parent(handle, &phandle)) {
145 return_VALUE(-ENODEV);
146 }
147
148 if (acpi_bus_get_device(phandle, &pdev)) {
149 return_VALUE(-ENODEV);
150 }
151
152 if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) {
153 return_VALUE(-ENODEV);
154 }
155
156 result = acpi_bus_scan(*device);
157
158 return_VALUE(result);
159}
160
161static void
162container_notify_cb(acpi_handle handle, u32 type, void *context)
163{
164 struct acpi_device *device = NULL;
165 int result;
166 int present;
167 acpi_status status;
168
169 ACPI_FUNCTION_TRACE("container_notify_cb");
170
171 present = is_device_present(handle);
172
173 switch (type) {
174 case ACPI_NOTIFY_BUS_CHECK:
175 /* Fall through */
176 case ACPI_NOTIFY_DEVICE_CHECK:
177 printk("Container driver received %s event\n",
178 (type == ACPI_NOTIFY_BUS_CHECK)?
179 "ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK");
180 status = acpi_bus_get_device(handle, &device);
181 if (present) {
182 if (ACPI_FAILURE(status) || !device) {
183 result = container_device_add(&device, handle);
184 if (!result)
185 kobject_hotplug(&device->kobj,
186 KOBJ_ONLINE);
187 else
188 printk("Failed to add container\n");
189 }
190 } else {
191 if (ACPI_SUCCESS(status)) {
192 /* device exist and this is a remove request */
193 kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
194 }
195 }
196 break;
197 case ACPI_NOTIFY_EJECT_REQUEST:
198 if (!acpi_bus_get_device(handle, &device) && device) {
199 kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
200 }
201 break;
202 default:
203 break;
204 }
205 return_VOID;
206}
207
208static acpi_status
209container_walk_namespace_cb(acpi_handle handle,
210 u32 lvl,
211 void *context,
212 void **rv)
213{
214 char *hid = NULL;
215 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
216 struct acpi_device_info *info;
217 acpi_status status;
218 int *action = context;
219
220 ACPI_FUNCTION_TRACE("container_walk_namespace_cb");
221
222 status = acpi_get_object_info(handle, &buffer);
223 if (ACPI_FAILURE(status) || !buffer.pointer) {
224 return_ACPI_STATUS(AE_OK);
225 }
226
227 info = buffer.pointer;
228 if (info->valid & ACPI_VALID_HID)
229 hid = info->hardware_id.value;
230
231 if (hid == NULL) {
232 goto end;
233 }
234
235 if (strcmp(hid, "ACPI0004") && strcmp(hid, "PNP0A05") &&
236 strcmp(hid, "PNP0A06")) {
237 goto end;
238 }
239
240 switch(*action) {
241 case INSTALL_NOTIFY_HANDLER:
242 acpi_install_notify_handler(handle,
243 ACPI_SYSTEM_NOTIFY,
244 container_notify_cb,
245 NULL);
246 break;
247 case UNINSTALL_NOTIFY_HANDLER:
248 acpi_remove_notify_handler(handle,
249 ACPI_SYSTEM_NOTIFY,
250 container_notify_cb);
251 break;
252 default:
253 break;
254 }
255
256end:
257 acpi_os_free(buffer.pointer);
258
259 return_ACPI_STATUS(AE_OK);
260}
261
262
263static int __init
264acpi_container_init(void)
265{
266 int result = 0;
267 int action = INSTALL_NOTIFY_HANDLER;
268
269 result = acpi_bus_register_driver(&acpi_container_driver);
270 if (result < 0) {
271 return(result);
272 }
273
274 /* register notify handler to every container device */
275 acpi_walk_namespace(ACPI_TYPE_DEVICE,
276 ACPI_ROOT_OBJECT,
277 ACPI_UINT32_MAX,
278 container_walk_namespace_cb,
279 &action, NULL);
280
281 return(0);
282}
283
284static void __exit
285acpi_container_exit(void)
286{
287 int action = UNINSTALL_NOTIFY_HANDLER;
288
289 ACPI_FUNCTION_TRACE("acpi_container_exit");
290
291 acpi_walk_namespace(ACPI_TYPE_DEVICE,
292 ACPI_ROOT_OBJECT,
293 ACPI_UINT32_MAX,
294 container_walk_namespace_cb,
295 &action, NULL);
296
297 acpi_bus_unregister_driver(&acpi_container_driver);
298
299 return_VOID;
300}
301
302module_init(acpi_container_init);
303module_exit(acpi_container_exit);
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
new file mode 100644
index 000000000000..2c0dac559f16
--- /dev/null
+++ b/drivers/acpi/debug.c
@@ -0,0 +1,233 @@
1/*
2 * debug.c - ACPI debug interface to userspace.
3 */
4
5#include <linux/proc_fs.h>
6#include <linux/init.h>
7#include <linux/module.h>
8#include <linux/kernel.h>
9#include <linux/moduleparam.h>
10#include <asm/uaccess.h>
11#include <acpi/acpi_drivers.h>
12#include <acpi/acglobal.h>
13
14#define _COMPONENT ACPI_SYSTEM_COMPONENT
15ACPI_MODULE_NAME ("debug")
16
17#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer"
18#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level"
19
20#ifdef MODULE_PARAM_PREFIX
21#undef MODULE_PARAM_PREFIX
22#endif
23
24#define MODULE_PARAM_PREFIX
25module_param(acpi_dbg_layer, uint, 0400);
26module_param(acpi_dbg_level, uint, 0400);
27
28struct acpi_dlayer {
29 const char *name;
30 unsigned long value;
31};
32struct acpi_dlevel {
33 const char *name;
34 unsigned long value;
35};
36#define ACPI_DEBUG_INIT(v) { .name = #v, .value = v }
37
38static const struct acpi_dlayer acpi_debug_layers[] =
39{
40 ACPI_DEBUG_INIT(ACPI_UTILITIES),
41 ACPI_DEBUG_INIT(ACPI_HARDWARE),
42 ACPI_DEBUG_INIT(ACPI_EVENTS),
43 ACPI_DEBUG_INIT(ACPI_TABLES),
44 ACPI_DEBUG_INIT(ACPI_NAMESPACE),
45 ACPI_DEBUG_INIT(ACPI_PARSER),
46 ACPI_DEBUG_INIT(ACPI_DISPATCHER),
47 ACPI_DEBUG_INIT(ACPI_EXECUTER),
48 ACPI_DEBUG_INIT(ACPI_RESOURCES),
49 ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER),
50 ACPI_DEBUG_INIT(ACPI_OS_SERVICES),
51 ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER),
52 ACPI_DEBUG_INIT(ACPI_COMPILER),
53 ACPI_DEBUG_INIT(ACPI_TOOLS),
54};
55
56static const struct acpi_dlevel acpi_debug_levels[] =
57{
58 ACPI_DEBUG_INIT(ACPI_LV_ERROR),
59 ACPI_DEBUG_INIT(ACPI_LV_WARN),
60 ACPI_DEBUG_INIT(ACPI_LV_INIT),
61 ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
62 ACPI_DEBUG_INIT(ACPI_LV_INFO),
63
64 ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES),
65 ACPI_DEBUG_INIT(ACPI_LV_PARSE),
66 ACPI_DEBUG_INIT(ACPI_LV_LOAD),
67 ACPI_DEBUG_INIT(ACPI_LV_DISPATCH),
68 ACPI_DEBUG_INIT(ACPI_LV_EXEC),
69 ACPI_DEBUG_INIT(ACPI_LV_NAMES),
70 ACPI_DEBUG_INIT(ACPI_LV_OPREGION),
71 ACPI_DEBUG_INIT(ACPI_LV_BFIELD),
72 ACPI_DEBUG_INIT(ACPI_LV_TABLES),
73 ACPI_DEBUG_INIT(ACPI_LV_VALUES),
74 ACPI_DEBUG_INIT(ACPI_LV_OBJECTS),
75 ACPI_DEBUG_INIT(ACPI_LV_RESOURCES),
76 ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS),
77 ACPI_DEBUG_INIT(ACPI_LV_PACKAGE),
78
79 ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS),
80 ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS),
81 ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS),
82
83 ACPI_DEBUG_INIT(ACPI_LV_MUTEX),
84 ACPI_DEBUG_INIT(ACPI_LV_THREADS),
85 ACPI_DEBUG_INIT(ACPI_LV_IO),
86 ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS),
87
88 ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE),
89 ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO),
90 ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES),
91 ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
92};
93
94static int
95acpi_system_read_debug (
96 char *page,
97 char **start,
98 off_t off,
99 int count,
100 int *eof,
101 void *data)
102{
103 char *p = page;
104 int size = 0;
105 unsigned int i;
106
107 if (off != 0)
108 goto end;
109
110 p += sprintf(p, "%-25s\tHex SET\n", "Description");
111
112 switch ((unsigned long) data) {
113 case 0:
114 for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
115 p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
116 acpi_debug_layers[i].name,
117 acpi_debug_layers[i].value,
118 (acpi_dbg_layer & acpi_debug_layers[i].value) ?
119 '*' : ' ');
120 }
121 p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
122 ACPI_ALL_DRIVERS,
123 (acpi_dbg_layer & ACPI_ALL_DRIVERS) == ACPI_ALL_DRIVERS?
124 '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 0 ?
125 ' ' : '-');
126 p += sprintf(p,
127 "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
128 acpi_dbg_layer);
129 break;
130 case 1:
131 for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
132 p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
133 acpi_debug_levels[i].name,
134 acpi_debug_levels[i].value,
135 (acpi_dbg_level & acpi_debug_levels[i].value) ?
136 '*' : ' ');
137 }
138 p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n",
139 acpi_dbg_level);
140 break;
141 default:
142 p += sprintf(p, "Invalid debug option\n");
143 break;
144 }
145
146end:
147 size = (p - page);
148 if (size <= off+count) *eof = 1;
149 *start = page + off;
150 size -= off;
151 if (size>count) size = count;
152 if (size<0) size = 0;
153
154 return size;
155}
156
157
158static int
159acpi_system_write_debug (
160 struct file *file,
161 const char __user *buffer,
162 unsigned long count,
163 void *data)
164{
165 char debug_string[12] = {'\0'};
166
167 ACPI_FUNCTION_TRACE("acpi_system_write_debug");
168
169 if (count > sizeof(debug_string) - 1)
170 return_VALUE(-EINVAL);
171
172 if (copy_from_user(debug_string, buffer, count))
173 return_VALUE(-EFAULT);
174
175 debug_string[count] = '\0';
176
177 switch ((unsigned long) data) {
178 case 0:
179 acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0);
180 break;
181 case 1:
182 acpi_dbg_level = simple_strtoul(debug_string, NULL, 0);
183 break;
184 default:
185 return_VALUE(-EINVAL);
186 }
187
188 return_VALUE(count);
189}
190
191static int __init acpi_debug_init(void)
192{
193 struct proc_dir_entry *entry;
194 int error = 0;
195 char * name;
196
197 ACPI_FUNCTION_TRACE("acpi_debug_init");
198
199 if (acpi_disabled)
200 return_VALUE(0);
201
202 /* 'debug_layer' [R/W] */
203 name = ACPI_SYSTEM_FILE_DEBUG_LAYER;
204 entry = create_proc_read_entry(name, S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir,
205 acpi_system_read_debug,(void *)0);
206 if (entry)
207 entry->write_proc = acpi_system_write_debug;
208 else
209 goto Error;
210
211 /* 'debug_level' [R/W] */
212 name = ACPI_SYSTEM_FILE_DEBUG_LEVEL;
213 entry = create_proc_read_entry(name, S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir,
214 acpi_system_read_debug, (void *)1);
215 if (entry)
216 entry->write_proc = acpi_system_write_debug;
217 else
218 goto Error;
219
220 Done:
221 return_VALUE(error);
222
223 Error:
224 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
225 "Unable to create '%s' proc fs entry\n", name));
226
227 remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, acpi_root_dir);
228 remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir);
229 error = -EFAULT;
230 goto Done;
231}
232
233subsys_initcall(acpi_debug_init);
diff --git a/drivers/acpi/dispatcher/Makefile b/drivers/acpi/dispatcher/Makefile
new file mode 100644
index 000000000000..eb7e602a83cd
--- /dev/null
+++ b/drivers/acpi/dispatcher/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for all Linux ACPI interpreter subdirectories
3#
4
5obj-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \
6 dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \
7 dsinit.o
8
9EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c
new file mode 100644
index 000000000000..2779211be756
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsfield.c
@@ -0,0 +1,601 @@
1/******************************************************************************
2 *
3 * Module Name: dsfield - Dispatcher field routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/amlcode.h>
47#include <acpi/acdispat.h>
48#include <acpi/acinterp.h>
49#include <acpi/acnamesp.h>
50#include <acpi/acparser.h>
51
52
53#define _COMPONENT ACPI_DISPATCHER
54 ACPI_MODULE_NAME ("dsfield")
55
56
57/*******************************************************************************
58 *
59 * FUNCTION: acpi_ds_create_buffer_field
60 *
61 * PARAMETERS: Opcode - The opcode to be executed
62 * Operands - List of operands for the opcode
63 * walk_state - Current state
64 *
65 * RETURN: Status
66 *
67 * DESCRIPTION: Execute the create_field operators:
68 * create_bit_field_op,
69 * create_byte_field_op,
70 * create_word_field_op,
71 * create_dword_field_op,
72 * create_qword_field_op,
73 * create_field_op (all of which define fields in buffers)
74 *
75 ******************************************************************************/
76
77acpi_status
78acpi_ds_create_buffer_field (
79 union acpi_parse_object *op,
80 struct acpi_walk_state *walk_state)
81{
82 union acpi_parse_object *arg;
83 struct acpi_namespace_node *node;
84 acpi_status status;
85 union acpi_operand_object *obj_desc;
86 union acpi_operand_object *second_desc = NULL;
87 u32 flags;
88
89
90 ACPI_FUNCTION_TRACE ("ds_create_buffer_field");
91
92
93 /* Get the name_string argument */
94
95 if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
96 arg = acpi_ps_get_arg (op, 3);
97 }
98 else {
99 /* Create Bit/Byte/Word/Dword field */
100
101 arg = acpi_ps_get_arg (op, 2);
102 }
103
104 if (!arg) {
105 return_ACPI_STATUS (AE_AML_NO_OPERAND);
106 }
107
108 if (walk_state->deferred_node) {
109 node = walk_state->deferred_node;
110 status = AE_OK;
111 }
112 else {
113 /*
114 * During the load phase, we want to enter the name of the field into
115 * the namespace. During the execute phase (when we evaluate the size
116 * operand), we want to lookup the name
117 */
118 if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
119 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
120 }
121 else {
122 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND;
123 }
124
125 /*
126 * Enter the name_string into the namespace
127 */
128 status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
129 ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1,
130 flags, walk_state, &(node));
131 if (ACPI_FAILURE (status)) {
132 ACPI_REPORT_NSERROR (arg->common.value.string, status);
133 return_ACPI_STATUS (status);
134 }
135 }
136
137 /* We could put the returned object (Node) on the object stack for later, but
138 * for now, we will put it in the "op" object that the parser uses, so we
139 * can get it again at the end of this scope
140 */
141 op->common.node = node;
142
143 /*
144 * If there is no object attached to the node, this node was just created and
145 * we need to create the field object. Otherwise, this was a lookup of an
146 * existing node and we don't want to create the field object again.
147 */
148 obj_desc = acpi_ns_get_attached_object (node);
149 if (obj_desc) {
150 return_ACPI_STATUS (AE_OK);
151 }
152
153 /*
154 * The Field definition is not fully parsed at this time.
155 * (We must save the address of the AML for the buffer and index operands)
156 */
157
158 /* Create the buffer field object */
159
160 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER_FIELD);
161 if (!obj_desc) {
162 status = AE_NO_MEMORY;
163 goto cleanup;
164 }
165
166 /*
167 * Remember location in AML stream of the field unit
168 * opcode and operands -- since the buffer and index
169 * operands must be evaluated.
170 */
171 second_desc = obj_desc->common.next_object;
172 second_desc->extra.aml_start = op->named.data;
173 second_desc->extra.aml_length = op->named.length;
174 obj_desc->buffer_field.node = node;
175
176 /* Attach constructed field descriptors to parent node */
177
178 status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
179 if (ACPI_FAILURE (status)) {
180 goto cleanup;
181 }
182
183
184cleanup:
185
186 /* Remove local reference to the object */
187
188 acpi_ut_remove_reference (obj_desc);
189 return_ACPI_STATUS (status);
190}
191
192
193/*******************************************************************************
194 *
195 * FUNCTION: acpi_ds_get_field_names
196 *
197 * PARAMETERS: Info - create_field info structure
198 * ` walk_state - Current method state
199 * Arg - First parser arg for the field name list
200 *
201 * RETURN: Status
202 *
203 * DESCRIPTION: Process all named fields in a field declaration. Names are
204 * entered into the namespace.
205 *
206 ******************************************************************************/
207
208acpi_status
209acpi_ds_get_field_names (
210 struct acpi_create_field_info *info,
211 struct acpi_walk_state *walk_state,
212 union acpi_parse_object *arg)
213{
214 acpi_status status;
215 acpi_integer position;
216
217
218 ACPI_FUNCTION_TRACE_PTR ("ds_get_field_names", info);
219
220
221 /* First field starts at bit zero */
222
223 info->field_bit_position = 0;
224
225 /* Process all elements in the field list (of parse nodes) */
226
227 while (arg) {
228 /*
229 * Three types of field elements are handled:
230 * 1) Offset - specifies a bit offset
231 * 2) access_as - changes the access mode
232 * 3) Name - Enters a new named field into the namespace
233 */
234 switch (arg->common.aml_opcode) {
235 case AML_INT_RESERVEDFIELD_OP:
236
237 position = (acpi_integer) info->field_bit_position
238 + (acpi_integer) arg->common.value.size;
239
240 if (position > ACPI_UINT32_MAX) {
241 ACPI_REPORT_ERROR (("Bit offset within field too large (> 0xFFFFFFFF)\n"));
242 return_ACPI_STATUS (AE_SUPPORT);
243 }
244
245 info->field_bit_position = (u32) position;
246 break;
247
248
249 case AML_INT_ACCESSFIELD_OP:
250
251 /*
252 * Get a new access_type and access_attribute -- to be used for all
253 * field units that follow, until field end or another access_as keyword.
254 *
255 * In field_flags, preserve the flag bits other than the ACCESS_TYPE bits
256 */
257 info->field_flags = (u8) ((info->field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
258 ((u8) ((u32) arg->common.value.integer >> 8)));
259
260 info->attribute = (u8) (arg->common.value.integer);
261 break;
262
263
264 case AML_INT_NAMEDFIELD_OP:
265
266 /* Lookup the name */
267
268 status = acpi_ns_lookup (walk_state->scope_info,
269 (char *) &arg->named.name,
270 info->field_type, ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE,
271 walk_state, &info->field_node);
272 if (ACPI_FAILURE (status)) {
273 ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
274 if (status != AE_ALREADY_EXISTS) {
275 return_ACPI_STATUS (status);
276 }
277
278 /* Already exists, ignore error */
279 }
280 else {
281 arg->common.node = info->field_node;
282 info->field_bit_length = arg->common.value.size;
283
284 /* Create and initialize an object for the new Field Node */
285
286 status = acpi_ex_prep_field_value (info);
287 if (ACPI_FAILURE (status)) {
288 return_ACPI_STATUS (status);
289 }
290 }
291
292 /* Keep track of bit position for the next field */
293
294 position = (acpi_integer) info->field_bit_position
295 + (acpi_integer) arg->common.value.size;
296
297 if (position > ACPI_UINT32_MAX) {
298 ACPI_REPORT_ERROR (("Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n",
299 (char *) &info->field_node->name));
300 return_ACPI_STATUS (AE_SUPPORT);
301 }
302
303 info->field_bit_position += info->field_bit_length;
304 break;
305
306
307 default:
308
309 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid opcode in field list: %X\n",
310 arg->common.aml_opcode));
311 return_ACPI_STATUS (AE_AML_BAD_OPCODE);
312 }
313
314 arg = arg->common.next;
315 }
316
317 return_ACPI_STATUS (AE_OK);
318}
319
320
321/*******************************************************************************
322 *
323 * FUNCTION: acpi_ds_create_field
324 *
325 * PARAMETERS: Op - Op containing the Field definition and args
326 * region_node - Object for the containing Operation Region
327 * ` walk_state - Current method state
328 *
329 * RETURN: Status
330 *
331 * DESCRIPTION: Create a new field in the specified operation region
332 *
333 ******************************************************************************/
334
335acpi_status
336acpi_ds_create_field (
337 union acpi_parse_object *op,
338 struct acpi_namespace_node *region_node,
339 struct acpi_walk_state *walk_state)
340{
341 acpi_status status;
342 union acpi_parse_object *arg;
343 struct acpi_create_field_info info;
344
345
346 ACPI_FUNCTION_TRACE_PTR ("ds_create_field", op);
347
348
349 /* First arg is the name of the parent op_region (must already exist) */
350
351 arg = op->common.value.arg;
352 if (!region_node) {
353 status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
354 ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
355 ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
356 if (ACPI_FAILURE (status)) {
357 ACPI_REPORT_NSERROR (arg->common.value.name, status);
358 return_ACPI_STATUS (status);
359 }
360 }
361
362 /* Second arg is the field flags */
363
364 arg = arg->common.next;
365 info.field_flags = (u8) arg->common.value.integer;
366 info.attribute = 0;
367
368 /* Each remaining arg is a Named Field */
369
370 info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
371 info.region_node = region_node;
372
373 status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
374
375 return_ACPI_STATUS (status);
376}
377
378
379/*******************************************************************************
380 *
381 * FUNCTION: acpi_ds_init_field_objects
382 *
383 * PARAMETERS: Op - Op containing the Field definition and args
384 * ` walk_state - Current method state
385 *
386 * RETURN: Status
387 *
388 * DESCRIPTION: For each "Field Unit" name in the argument list that is
389 * part of the field declaration, enter the name into the
390 * namespace.
391 *
392 ******************************************************************************/
393
394acpi_status
395acpi_ds_init_field_objects (
396 union acpi_parse_object *op,
397 struct acpi_walk_state *walk_state)
398{
399 acpi_status status;
400 union acpi_parse_object *arg = NULL;
401 struct acpi_namespace_node *node;
402 u8 type = 0;
403
404
405 ACPI_FUNCTION_TRACE_PTR ("ds_init_field_objects", op);
406
407
408 switch (walk_state->opcode) {
409 case AML_FIELD_OP:
410 arg = acpi_ps_get_arg (op, 2);
411 type = ACPI_TYPE_LOCAL_REGION_FIELD;
412 break;
413
414 case AML_BANK_FIELD_OP:
415 arg = acpi_ps_get_arg (op, 4);
416 type = ACPI_TYPE_LOCAL_BANK_FIELD;
417 break;
418
419 case AML_INDEX_FIELD_OP:
420 arg = acpi_ps_get_arg (op, 3);
421 type = ACPI_TYPE_LOCAL_INDEX_FIELD;
422 break;
423
424 default:
425 return_ACPI_STATUS (AE_BAD_PARAMETER);
426 }
427
428 /*
429 * Walk the list of entries in the field_list
430 */
431 while (arg) {
432 /* Ignore OFFSET and ACCESSAS terms here */
433
434 if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
435 status = acpi_ns_lookup (walk_state->scope_info,
436 (char *) &arg->named.name,
437 type, ACPI_IMODE_LOAD_PASS1,
438 ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND,
439 walk_state, &node);
440 if (ACPI_FAILURE (status)) {
441 ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
442 if (status != AE_ALREADY_EXISTS) {
443 return_ACPI_STATUS (status);
444 }
445
446 /* Name already exists, just ignore this error */
447
448 status = AE_OK;
449 }
450
451 arg->common.node = node;
452 }
453
454 /* Move to next field in the list */
455
456 arg = arg->common.next;
457 }
458
459 return_ACPI_STATUS (AE_OK);
460}
461
462
463/*******************************************************************************
464 *
465 * FUNCTION: acpi_ds_create_bank_field
466 *
467 * PARAMETERS: Op - Op containing the Field definition and args
468 * region_node - Object for the containing Operation Region
469 * ` walk_state - Current method state
470 *
471 * RETURN: Status
472 *
473 * DESCRIPTION: Create a new bank field in the specified operation region
474 *
475 ******************************************************************************/
476
477acpi_status
478acpi_ds_create_bank_field (
479 union acpi_parse_object *op,
480 struct acpi_namespace_node *region_node,
481 struct acpi_walk_state *walk_state)
482{
483 acpi_status status;
484 union acpi_parse_object *arg;
485 struct acpi_create_field_info info;
486
487
488 ACPI_FUNCTION_TRACE_PTR ("ds_create_bank_field", op);
489
490
491 /* First arg is the name of the parent op_region (must already exist) */
492
493 arg = op->common.value.arg;
494 if (!region_node) {
495 status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
496 ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
497 ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
498 if (ACPI_FAILURE (status)) {
499 ACPI_REPORT_NSERROR (arg->common.value.name, status);
500 return_ACPI_STATUS (status);
501 }
502 }
503
504 /* Second arg is the Bank Register (Field) (must already exist) */
505
506 arg = arg->common.next;
507 status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
508 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
509 ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
510 if (ACPI_FAILURE (status)) {
511 ACPI_REPORT_NSERROR (arg->common.value.string, status);
512 return_ACPI_STATUS (status);
513 }
514
515 /* Third arg is the bank_value */
516
517 arg = arg->common.next;
518 info.bank_value = (u32) arg->common.value.integer;
519
520 /* Fourth arg is the field flags */
521
522 arg = arg->common.next;
523 info.field_flags = (u8) arg->common.value.integer;
524
525 /* Each remaining arg is a Named Field */
526
527 info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
528 info.region_node = region_node;
529
530 status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
531
532 return_ACPI_STATUS (status);
533}
534
535
536/*******************************************************************************
537 *
538 * FUNCTION: acpi_ds_create_index_field
539 *
540 * PARAMETERS: Op - Op containing the Field definition and args
541 * region_node - Object for the containing Operation Region
542 * ` walk_state - Current method state
543 *
544 * RETURN: Status
545 *
546 * DESCRIPTION: Create a new index field in the specified operation region
547 *
548 ******************************************************************************/
549
550acpi_status
551acpi_ds_create_index_field (
552 union acpi_parse_object *op,
553 struct acpi_namespace_node *region_node,
554 struct acpi_walk_state *walk_state)
555{
556 acpi_status status;
557 union acpi_parse_object *arg;
558 struct acpi_create_field_info info;
559
560
561 ACPI_FUNCTION_TRACE_PTR ("ds_create_index_field", op);
562
563
564 /* First arg is the name of the Index register (must already exist) */
565
566 arg = op->common.value.arg;
567 status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
568 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
569 ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
570 if (ACPI_FAILURE (status)) {
571 ACPI_REPORT_NSERROR (arg->common.value.string, status);
572 return_ACPI_STATUS (status);
573 }
574
575 /* Second arg is the data register (must already exist) */
576
577 arg = arg->common.next;
578 status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
579 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
580 ACPI_NS_SEARCH_PARENT, walk_state, &info.data_register_node);
581 if (ACPI_FAILURE (status)) {
582 ACPI_REPORT_NSERROR (arg->common.value.string, status);
583 return_ACPI_STATUS (status);
584 }
585
586 /* Next arg is the field flags */
587
588 arg = arg->common.next;
589 info.field_flags = (u8) arg->common.value.integer;
590
591 /* Each remaining arg is a Named Field */
592
593 info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
594 info.region_node = region_node;
595
596 status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
597
598 return_ACPI_STATUS (status);
599}
600
601
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c
new file mode 100644
index 000000000000..b4d264dbbf67
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsinit.c
@@ -0,0 +1,235 @@
1/******************************************************************************
2 *
3 * Module Name: dsinit - Object initialization namespace walk
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acdispat.h>
47#include <acpi/acnamesp.h>
48
49#define _COMPONENT ACPI_DISPATCHER
50 ACPI_MODULE_NAME ("dsinit")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ds_init_one_object
56 *
57 * PARAMETERS: obj_handle - Node
58 * Level - Current nesting level
59 * Context - Points to a init info struct
60 * return_value - Not used
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object
65 * within the namespace.
66 *
67 * Currently, the only objects that require initialization are:
68 * 1) Methods
69 * 2) Operation Regions
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_ds_init_one_object (
75 acpi_handle obj_handle,
76 u32 level,
77 void *context,
78 void **return_value)
79{
80 acpi_object_type type;
81 acpi_status status;
82 struct acpi_init_walk_info *info = (struct acpi_init_walk_info *) context;
83
84
85 ACPI_FUNCTION_NAME ("ds_init_one_object");
86
87
88 /*
89 * We are only interested in objects owned by the table that
90 * was just loaded
91 */
92 if (((struct acpi_namespace_node *) obj_handle)->owner_id !=
93 info->table_desc->table_id) {
94 return (AE_OK);
95 }
96
97 info->object_count++;
98
99 /* And even then, we are only interested in a few object types */
100
101 type = acpi_ns_get_type (obj_handle);
102
103 switch (type) {
104 case ACPI_TYPE_REGION:
105
106 status = acpi_ds_initialize_region (obj_handle);
107 if (ACPI_FAILURE (status)) {
108 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %p [%4.4s] - Init failure, %s\n",
109 obj_handle, acpi_ut_get_node_name (obj_handle),
110 acpi_format_exception (status)));
111 }
112
113 info->op_region_count++;
114 break;
115
116
117 case ACPI_TYPE_METHOD:
118
119 info->method_count++;
120
121 /* Print a dot for each method unless we are going to print the entire pathname */
122
123 if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
124 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
125 }
126
127 /*
128 * Set the execution data width (32 or 64) based upon the
129 * revision number of the parent ACPI table.
130 * TBD: This is really for possible future support of integer width
131 * on a per-table basis. Currently, we just use a global for the width.
132 */
133 if (info->table_desc->pointer->revision == 1) {
134 ((struct acpi_namespace_node *) obj_handle)->flags |= ANOBJ_DATA_WIDTH_32;
135 }
136
137 /*
138 * Always parse methods to detect errors, we will delete
139 * the parse tree below
140 */
141 status = acpi_ds_parse_method (obj_handle);
142 if (ACPI_FAILURE (status)) {
143 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n",
144 obj_handle, acpi_ut_get_node_name (obj_handle),
145 acpi_format_exception (status)));
146
147 /* This parse failed, but we will continue parsing more methods */
148
149 break;
150 }
151
152 /*
153 * Delete the parse tree. We simply re-parse the method
154 * for every execution since there isn't much overhead
155 */
156 acpi_ns_delete_namespace_subtree (obj_handle);
157 acpi_ns_delete_namespace_by_owner (((struct acpi_namespace_node *) obj_handle)->object->method.owning_id);
158 break;
159
160
161 case ACPI_TYPE_DEVICE:
162
163 info->device_count++;
164 break;
165
166
167 default:
168 break;
169 }
170
171 /*
172 * We ignore errors from above, and always return OK, since
173 * we don't want to abort the walk on a single error.
174 */
175 return (AE_OK);
176}
177
178
179/*******************************************************************************
180 *
181 * FUNCTION: acpi_ds_initialize_objects
182 *
183 * PARAMETERS: table_desc - Descriptor for parent ACPI table
184 * start_node - Root of subtree to be initialized.
185 *
186 * RETURN: Status
187 *
188 * DESCRIPTION: Walk the namespace starting at "start_node" and perform any
189 * necessary initialization on the objects found therein
190 *
191 ******************************************************************************/
192
193acpi_status
194acpi_ds_initialize_objects (
195 struct acpi_table_desc *table_desc,
196 struct acpi_namespace_node *start_node)
197{
198 acpi_status status;
199 struct acpi_init_walk_info info;
200
201
202 ACPI_FUNCTION_TRACE ("ds_initialize_objects");
203
204
205 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
206 "**** Starting initialization of namespace objects ****\n"));
207 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Parsing all Control Methods:"));
208
209 info.method_count = 0;
210 info.op_region_count = 0;
211 info.object_count = 0;
212 info.device_count = 0;
213 info.table_desc = table_desc;
214
215 /* Walk entire namespace from the supplied root */
216
217 status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
218 acpi_ds_init_one_object, &info, NULL);
219 if (ACPI_FAILURE (status)) {
220 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed, %s\n",
221 acpi_format_exception (status)));
222 }
223
224 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
225 "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n",
226 table_desc->pointer->signature, table_desc->table_id, info.object_count,
227 info.device_count, info.method_count, info.op_region_count));
228
229 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
230 "%hd Methods, %hd Regions\n", info.method_count, info.op_region_count));
231
232 return_ACPI_STATUS (AE_OK);
233}
234
235
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
new file mode 100644
index 000000000000..9f0456cb9bb5
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -0,0 +1,597 @@
1/******************************************************************************
2 *
3 * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/amlcode.h>
48#include <acpi/acdispat.h>
49#include <acpi/acinterp.h>
50#include <acpi/acnamesp.h>
51
52
53#define _COMPONENT ACPI_DISPATCHER
54 ACPI_MODULE_NAME ("dsmethod")
55
56
57/*******************************************************************************
58 *
59 * FUNCTION: acpi_ds_parse_method
60 *
61 * PARAMETERS: obj_handle - Method node
62 *
63 * RETURN: Status
64 *
65 * DESCRIPTION: Call the parser and parse the AML that is associated with the
66 * method.
67 *
68 * MUTEX: Assumes parser is locked
69 *
70 ******************************************************************************/
71
72acpi_status
73acpi_ds_parse_method (
74 acpi_handle obj_handle)
75{
76 acpi_status status;
77 union acpi_operand_object *obj_desc;
78 union acpi_parse_object *op;
79 struct acpi_namespace_node *node;
80 acpi_owner_id owner_id;
81 struct acpi_walk_state *walk_state;
82
83
84 ACPI_FUNCTION_TRACE_PTR ("ds_parse_method", obj_handle);
85
86
87 /* Parameter Validation */
88
89 if (!obj_handle) {
90 return_ACPI_STATUS (AE_NULL_ENTRY);
91 }
92
93 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n",
94 acpi_ut_get_node_name (obj_handle), obj_handle));
95
96 /* Extract the method object from the method Node */
97
98 node = (struct acpi_namespace_node *) obj_handle;
99 obj_desc = acpi_ns_get_attached_object (node);
100 if (!obj_desc) {
101 return_ACPI_STATUS (AE_NULL_OBJECT);
102 }
103
104 /* Create a mutex for the method if there is a concurrency limit */
105
106 if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
107 (!obj_desc->method.semaphore)) {
108 status = acpi_os_create_semaphore (obj_desc->method.concurrency,
109 obj_desc->method.concurrency,
110 &obj_desc->method.semaphore);
111 if (ACPI_FAILURE (status)) {
112 return_ACPI_STATUS (status);
113 }
114 }
115
116 /*
117 * Allocate a new parser op to be the root of the parsed
118 * method tree
119 */
120 op = acpi_ps_alloc_op (AML_METHOD_OP);
121 if (!op) {
122 return_ACPI_STATUS (AE_NO_MEMORY);
123 }
124
125 /* Init new op with the method name and pointer back to the Node */
126
127 acpi_ps_set_name (op, node->name.integer);
128 op->common.node = node;
129
130 /*
131 * Get a new owner_id for objects created by this method. Namespace
132 * objects (such as Operation Regions) can be created during the
133 * first pass parse.
134 */
135 owner_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
136 obj_desc->method.owning_id = owner_id;
137
138 /* Create and initialize a new walk state */
139
140 walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL);
141 if (!walk_state) {
142 return_ACPI_STATUS (AE_NO_MEMORY);
143 }
144
145 status = acpi_ds_init_aml_walk (walk_state, op, node,
146 obj_desc->method.aml_start,
147 obj_desc->method.aml_length, NULL, 1);
148 if (ACPI_FAILURE (status)) {
149 acpi_ds_delete_walk_state (walk_state);
150 return_ACPI_STATUS (status);
151 }
152
153 /*
154 * Parse the method, first pass
155 *
156 * The first pass load is where newly declared named objects are
157 * added into the namespace. Actual evaluation of
158 * the named objects (what would be called a "second
159 * pass") happens during the actual execution of the
160 * method so that operands to the named objects can
161 * take on dynamic run-time values.
162 */
163 status = acpi_ps_parse_aml (walk_state);
164 if (ACPI_FAILURE (status)) {
165 return_ACPI_STATUS (status);
166 }
167
168 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
169 "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
170 acpi_ut_get_node_name (obj_handle), obj_handle, op));
171
172 acpi_ps_delete_parse_tree (op);
173 return_ACPI_STATUS (status);
174}
175
176
177/*******************************************************************************
178 *
179 * FUNCTION: acpi_ds_begin_method_execution
180 *
181 * PARAMETERS: method_node - Node of the method
182 * obj_desc - The method object
183 * calling_method_node - Caller of this method (if non-null)
184 *
185 * RETURN: Status
186 *
187 * DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
188 * increments the thread count, and waits at the method semaphore
189 * for clearance to execute.
190 *
191 ******************************************************************************/
192
193acpi_status
194acpi_ds_begin_method_execution (
195 struct acpi_namespace_node *method_node,
196 union acpi_operand_object *obj_desc,
197 struct acpi_namespace_node *calling_method_node)
198{
199 acpi_status status = AE_OK;
200
201
202 ACPI_FUNCTION_TRACE_PTR ("ds_begin_method_execution", method_node);
203
204
205 if (!method_node) {
206 return_ACPI_STATUS (AE_NULL_ENTRY);
207 }
208
209 /*
210 * If there is a concurrency limit on this method, we need to
211 * obtain a unit from the method semaphore.
212 */
213 if (obj_desc->method.semaphore) {
214 /*
215 * Allow recursive method calls, up to the reentrancy/concurrency
216 * limit imposed by the SERIALIZED rule and the sync_level method
217 * parameter.
218 *
219 * The point of this code is to avoid permanently blocking a
220 * thread that is making recursive method calls.
221 */
222 if (method_node == calling_method_node) {
223 if (obj_desc->method.thread_count >= obj_desc->method.concurrency) {
224 return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
225 }
226 }
227
228 /*
229 * Get a unit from the method semaphore. This releases the
230 * interpreter if we block
231 */
232 status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore,
233 ACPI_WAIT_FOREVER);
234 }
235
236 /*
237 * Increment the method parse tree thread count since it has been
238 * reentered one more time (even if it is the same thread)
239 */
240 obj_desc->method.thread_count++;
241 return_ACPI_STATUS (status);
242}
243
244
245/*******************************************************************************
246 *
247 * FUNCTION: acpi_ds_call_control_method
248 *
249 * PARAMETERS: Thread - Info for this thread
250 * this_walk_state - Current walk state
251 * Op - Current Op to be walked
252 *
253 * RETURN: Status
254 *
255 * DESCRIPTION: Transfer execution to a called control method
256 *
257 ******************************************************************************/
258
259acpi_status
260acpi_ds_call_control_method (
261 struct acpi_thread_state *thread,
262 struct acpi_walk_state *this_walk_state,
263 union acpi_parse_object *op)
264{
265 acpi_status status;
266 struct acpi_namespace_node *method_node;
267 struct acpi_walk_state *next_walk_state;
268 union acpi_operand_object *obj_desc;
269 struct acpi_parameter_info info;
270 u32 i;
271
272
273 ACPI_FUNCTION_TRACE_PTR ("ds_call_control_method", this_walk_state);
274
275 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n",
276 this_walk_state->prev_op, this_walk_state));
277
278 /*
279 * Get the namespace entry for the control method we are about to call
280 */
281 method_node = this_walk_state->method_call_node;
282 if (!method_node) {
283 return_ACPI_STATUS (AE_NULL_ENTRY);
284 }
285
286 obj_desc = acpi_ns_get_attached_object (method_node);
287 if (!obj_desc) {
288 return_ACPI_STATUS (AE_NULL_OBJECT);
289 }
290
291 obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
292
293 /* Init for new method, wait on concurrency semaphore */
294
295 status = acpi_ds_begin_method_execution (method_node, obj_desc,
296 this_walk_state->method_node);
297 if (ACPI_FAILURE (status)) {
298 return_ACPI_STATUS (status);
299 }
300
301 if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
302 /* 1) Parse: Create a new walk state for the preempting walk */
303
304 next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
305 op, obj_desc, NULL);
306 if (!next_walk_state) {
307 return_ACPI_STATUS (AE_NO_MEMORY);
308 }
309
310 /* Create and init a Root Node */
311
312 op = acpi_ps_create_scope_op ();
313 if (!op) {
314 status = AE_NO_MEMORY;
315 goto cleanup;
316 }
317
318 status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
319 obj_desc->method.aml_start, obj_desc->method.aml_length,
320 NULL, 1);
321 if (ACPI_FAILURE (status)) {
322 acpi_ds_delete_walk_state (next_walk_state);
323 goto cleanup;
324 }
325
326 /* Begin AML parse */
327
328 status = acpi_ps_parse_aml (next_walk_state);
329 acpi_ps_delete_parse_tree (op);
330 }
331
332 /* 2) Execute: Create a new state for the preempting walk */
333
334 next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
335 NULL, obj_desc, thread);
336 if (!next_walk_state) {
337 status = AE_NO_MEMORY;
338 goto cleanup;
339 }
340 /*
341 * The resolved arguments were put on the previous walk state's operand
342 * stack. Operands on the previous walk state stack always
343 * start at index 0.
344 * Null terminate the list of arguments
345 */
346 this_walk_state->operands [this_walk_state->num_operands] = NULL;
347
348 info.parameters = &this_walk_state->operands[0];
349 info.parameter_type = ACPI_PARAM_ARGS;
350
351 status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node,
352 obj_desc->method.aml_start, obj_desc->method.aml_length,
353 &info, 3);
354 if (ACPI_FAILURE (status)) {
355 goto cleanup;
356 }
357
358 /*
359 * Delete the operands on the previous walkstate operand stack
360 * (they were copied to new objects)
361 */
362 for (i = 0; i < obj_desc->method.param_count; i++) {
363 acpi_ut_remove_reference (this_walk_state->operands [i]);
364 this_walk_state->operands [i] = NULL;
365 }
366
367 /* Clear the operand stack */
368
369 this_walk_state->num_operands = 0;
370
371 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
372 "Starting nested execution, newstate=%p\n", next_walk_state));
373
374 if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
375 status = obj_desc->method.implementation (next_walk_state);
376 return_ACPI_STATUS (status);
377 }
378
379 return_ACPI_STATUS (AE_OK);
380
381
382 /* On error, we must delete the new walk state */
383
384cleanup:
385 if (next_walk_state && (next_walk_state->method_desc)) {
386 /* Decrement the thread count on the method parse tree */
387
388 next_walk_state->method_desc->method.thread_count--;
389 }
390 (void) acpi_ds_terminate_control_method (next_walk_state);
391 acpi_ds_delete_walk_state (next_walk_state);
392 return_ACPI_STATUS (status);
393}
394
395
396/*******************************************************************************
397 *
398 * FUNCTION: acpi_ds_restart_control_method
399 *
400 * PARAMETERS: walk_state - State for preempted method (caller)
401 * return_desc - Return value from the called method
402 *
403 * RETURN: Status
404 *
405 * DESCRIPTION: Restart a method that was preempted by another (nested) method
406 * invocation. Handle the return value (if any) from the callee.
407 *
408 ******************************************************************************/
409
410acpi_status
411acpi_ds_restart_control_method (
412 struct acpi_walk_state *walk_state,
413 union acpi_operand_object *return_desc)
414{
415 acpi_status status;
416
417
418 ACPI_FUNCTION_TRACE_PTR ("ds_restart_control_method", walk_state);
419
420
421 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
422 "****Restart [%4.4s] Op %p return_value_from_callee %p\n",
423 (char *) &walk_state->method_node->name, walk_state->method_call_op,
424 return_desc));
425
426 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
427 " return_from_this_method_used?=%X res_stack %p Walk %p\n",
428 walk_state->return_used,
429 walk_state->results, walk_state));
430
431 /* Did the called method return a value? */
432
433 if (return_desc) {
434 /* Are we actually going to use the return value? */
435
436 if (walk_state->return_used) {
437 /* Save the return value from the previous method */
438
439 status = acpi_ds_result_push (return_desc, walk_state);
440 if (ACPI_FAILURE (status)) {
441 acpi_ut_remove_reference (return_desc);
442 return_ACPI_STATUS (status);
443 }
444
445 /*
446 * Save as THIS method's return value in case it is returned
447 * immediately to yet another method
448 */
449 walk_state->return_desc = return_desc;
450 }
451
452 /*
453 * The following code is the
454 * optional support for a so-called "implicit return". Some AML code
455 * assumes that the last value of the method is "implicitly" returned
456 * to the caller. Just save the last result as the return value.
457 * NOTE: this is optional because the ASL language does not actually
458 * support this behavior.
459 */
460 else if (!acpi_ds_do_implicit_return (return_desc, walk_state, FALSE)) {
461 /*
462 * Delete the return value if it will not be used by the
463 * calling method
464 */
465 acpi_ut_remove_reference (return_desc);
466 }
467 }
468
469 return_ACPI_STATUS (AE_OK);
470}
471
472
473/*******************************************************************************
474 *
475 * FUNCTION: acpi_ds_terminate_control_method
476 *
477 * PARAMETERS: walk_state - State of the method
478 *
479 * RETURN: Status
480 *
481 * DESCRIPTION: Terminate a control method. Delete everything that the method
482 * created, delete all locals and arguments, and delete the parse
483 * tree if requested.
484 *
485 ******************************************************************************/
486
487acpi_status
488acpi_ds_terminate_control_method (
489 struct acpi_walk_state *walk_state)
490{
491 union acpi_operand_object *obj_desc;
492 struct acpi_namespace_node *method_node;
493 acpi_status status;
494
495
496 ACPI_FUNCTION_TRACE_PTR ("ds_terminate_control_method", walk_state);
497
498
499 if (!walk_state) {
500 return (AE_BAD_PARAMETER);
501 }
502
503 /* The current method object was saved in the walk state */
504
505 obj_desc = walk_state->method_desc;
506 if (!obj_desc) {
507 return_ACPI_STATUS (AE_OK);
508 }
509
510 /* Delete all arguments and locals */
511
512 acpi_ds_method_data_delete_all (walk_state);
513
514 /*
515 * Lock the parser while we terminate this method.
516 * If this is the last thread executing the method,
517 * we have additional cleanup to perform
518 */
519 status = acpi_ut_acquire_mutex (ACPI_MTX_PARSER);
520 if (ACPI_FAILURE (status)) {
521 return_ACPI_STATUS (status);
522 }
523
524 /* Signal completion of the execution of this method if necessary */
525
526 if (walk_state->method_desc->method.semaphore) {
527 status = acpi_os_signal_semaphore (
528 walk_state->method_desc->method.semaphore, 1);
529 if (ACPI_FAILURE (status)) {
530 ACPI_REPORT_ERROR (("Could not signal method semaphore\n"));
531 status = AE_OK;
532
533 /* Ignore error and continue cleanup */
534 }
535 }
536
537 if (walk_state->method_desc->method.thread_count) {
538 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
539 "*** Not deleting method namespace, there are still %d threads\n",
540 walk_state->method_desc->method.thread_count));
541 }
542
543 if (!walk_state->method_desc->method.thread_count) {
544 /*
545 * Support to dynamically change a method from not_serialized to
546 * Serialized if it appears that the method is written foolishly and
547 * does not support multiple thread execution. The best example of this
548 * is if such a method creates namespace objects and blocks. A second
549 * thread will fail with an AE_ALREADY_EXISTS exception
550 *
551 * This code is here because we must wait until the last thread exits
552 * before creating the synchronization semaphore.
553 */
554 if ((walk_state->method_desc->method.concurrency == 1) &&
555 (!walk_state->method_desc->method.semaphore)) {
556 status = acpi_os_create_semaphore (1,
557 1,
558 &walk_state->method_desc->method.semaphore);
559 }
560
561 /*
562 * There are no more threads executing this method. Perform
563 * additional cleanup.
564 *
565 * The method Node is stored in the walk state
566 */
567 method_node = walk_state->method_node;
568
569 /*
570 * Delete any namespace entries created immediately underneath
571 * the method
572 */
573 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
574 if (ACPI_FAILURE (status)) {
575 return_ACPI_STATUS (status);
576 }
577
578 if (method_node->child) {
579 acpi_ns_delete_namespace_subtree (method_node);
580 }
581
582 /*
583 * Delete any namespace entries created anywhere else within
584 * the namespace
585 */
586 acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id);
587 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
588 if (ACPI_FAILURE (status)) {
589 return_ACPI_STATUS (status);
590 }
591 }
592
593 status = acpi_ut_release_mutex (ACPI_MTX_PARSER);
594 return_ACPI_STATUS (status);
595}
596
597
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
new file mode 100644
index 000000000000..f31d095f9833
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsmthdat.c
@@ -0,0 +1,715 @@
1/*******************************************************************************
2 *
3 * Module Name: dsmthdat - control method arguments and local variables
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acdispat.h>
47#include <acpi/amlcode.h>
48#include <acpi/acnamesp.h>
49#include <acpi/acinterp.h>
50
51
52#define _COMPONENT ACPI_DISPATCHER
53 ACPI_MODULE_NAME ("dsmthdat")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_ds_method_data_init
59 *
60 * PARAMETERS: walk_state - Current walk state object
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Initialize the data structures that hold the method's arguments
65 * and locals. The data struct is an array of NTEs for each.
66 * This allows ref_of and de_ref_of to work properly for these
67 * special data types.
68 *
69 * NOTES: walk_state fields are initialized to zero by the
70 * ACPI_MEM_CALLOCATE().
71 *
72 * A pseudo-Namespace Node is assigned to each argument and local
73 * so that ref_of() can return a pointer to the Node.
74 *
75 ******************************************************************************/
76
77void
78acpi_ds_method_data_init (
79 struct acpi_walk_state *walk_state)
80{
81 u32 i;
82
83
84 ACPI_FUNCTION_TRACE ("ds_method_data_init");
85
86
87 /* Init the method arguments */
88
89 for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
90 ACPI_MOVE_32_TO_32 (&walk_state->arguments[i].name,
91 NAMEOF_ARG_NTE);
92 walk_state->arguments[i].name.integer |= (i << 24);
93 walk_state->arguments[i].descriptor = ACPI_DESC_TYPE_NAMED;
94 walk_state->arguments[i].type = ACPI_TYPE_ANY;
95 walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG;
96 }
97
98 /* Init the method locals */
99
100 for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
101 ACPI_MOVE_32_TO_32 (&walk_state->local_variables[i].name,
102 NAMEOF_LOCAL_NTE);
103
104 walk_state->local_variables[i].name.integer |= (i << 24);
105 walk_state->local_variables[i].descriptor = ACPI_DESC_TYPE_NAMED;
106 walk_state->local_variables[i].type = ACPI_TYPE_ANY;
107 walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL;
108 }
109
110 return_VOID;
111}
112
113
114/*******************************************************************************
115 *
116 * FUNCTION: acpi_ds_method_data_delete_all
117 *
118 * PARAMETERS: walk_state - Current walk state object
119 *
120 * RETURN: None
121 *
122 * DESCRIPTION: Delete method locals and arguments. Arguments are only
123 * deleted if this method was called from another method.
124 *
125 ******************************************************************************/
126
127void
128acpi_ds_method_data_delete_all (
129 struct acpi_walk_state *walk_state)
130{
131 u32 index;
132
133
134 ACPI_FUNCTION_TRACE ("ds_method_data_delete_all");
135
136
137 /* Detach the locals */
138
139 for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) {
140 if (walk_state->local_variables[index].object) {
141 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Local%d=%p\n",
142 index, walk_state->local_variables[index].object));
143
144 /* Detach object (if present) and remove a reference */
145
146 acpi_ns_detach_object (&walk_state->local_variables[index]);
147 }
148 }
149
150 /* Detach the arguments */
151
152 for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) {
153 if (walk_state->arguments[index].object) {
154 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Arg%d=%p\n",
155 index, walk_state->arguments[index].object));
156
157 /* Detach object (if present) and remove a reference */
158
159 acpi_ns_detach_object (&walk_state->arguments[index]);
160 }
161 }
162
163 return_VOID;
164}
165
166
167/*******************************************************************************
168 *
169 * FUNCTION: acpi_ds_method_data_init_args
170 *
171 * PARAMETERS: *Params - Pointer to a parameter list for the method
172 * max_param_count - The arg count for this method
173 * walk_state - Current walk state object
174 *
175 * RETURN: Status
176 *
177 * DESCRIPTION: Initialize arguments for a method. The parameter list is a list
178 * of ACPI operand objects, either null terminated or whose length
179 * is defined by max_param_count.
180 *
181 ******************************************************************************/
182
183acpi_status
184acpi_ds_method_data_init_args (
185 union acpi_operand_object **params,
186 u32 max_param_count,
187 struct acpi_walk_state *walk_state)
188{
189 acpi_status status;
190 u32 index = 0;
191
192
193 ACPI_FUNCTION_TRACE_PTR ("ds_method_data_init_args", params);
194
195
196 if (!params) {
197 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "No param list passed to method\n"));
198 return_ACPI_STATUS (AE_OK);
199 }
200
201 /* Copy passed parameters into the new method stack frame */
202
203 while ((index < ACPI_METHOD_NUM_ARGS) && (index < max_param_count) && params[index]) {
204 /*
205 * A valid parameter.
206 * Store the argument in the method/walk descriptor.
207 * Do not copy the arg in order to implement call by reference
208 */
209 status = acpi_ds_method_data_set_value (AML_ARG_OP, index, params[index], walk_state);
210 if (ACPI_FAILURE (status)) {
211 return_ACPI_STATUS (status);
212 }
213
214 index++;
215 }
216
217 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%d args passed to method\n", index));
218 return_ACPI_STATUS (AE_OK);
219}
220
221
222/*******************************************************************************
223 *
224 * FUNCTION: acpi_ds_method_data_get_node
225 *
226 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
227 * Index - which local_var or argument whose type
228 * to get
229 * walk_state - Current walk state object
230 *
231 * RETURN: Get the Node associated with a local or arg.
232 *
233 ******************************************************************************/
234
235acpi_status
236acpi_ds_method_data_get_node (
237 u16 opcode,
238 u32 index,
239 struct acpi_walk_state *walk_state,
240 struct acpi_namespace_node **node)
241{
242 ACPI_FUNCTION_TRACE ("ds_method_data_get_node");
243
244
245 /*
246 * Method Locals and Arguments are supported
247 */
248 switch (opcode) {
249 case AML_LOCAL_OP:
250
251 if (index > ACPI_METHOD_MAX_LOCAL) {
252 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Local index %d is invalid (max %d)\n",
253 index, ACPI_METHOD_MAX_LOCAL));
254 return_ACPI_STATUS (AE_AML_INVALID_INDEX);
255 }
256
257 /* Return a pointer to the pseudo-node */
258
259 *node = &walk_state->local_variables[index];
260 break;
261
262 case AML_ARG_OP:
263
264 if (index > ACPI_METHOD_MAX_ARG) {
265 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Arg index %d is invalid (max %d)\n",
266 index, ACPI_METHOD_MAX_ARG));
267 return_ACPI_STATUS (AE_AML_INVALID_INDEX);
268 }
269
270 /* Return a pointer to the pseudo-node */
271
272 *node = &walk_state->arguments[index];
273 break;
274
275 default:
276 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Opcode %d is invalid\n", opcode));
277 return_ACPI_STATUS (AE_AML_BAD_OPCODE);
278 }
279
280 return_ACPI_STATUS (AE_OK);
281}
282
283
284/*******************************************************************************
285 *
286 * FUNCTION: acpi_ds_method_data_set_value
287 *
288 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
289 * Index - which local_var or argument to get
290 * Object - Object to be inserted into the stack entry
291 * walk_state - Current walk state object
292 *
293 * RETURN: Status
294 *
295 * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index.
296 * Note: There is no "implicit conversion" for locals.
297 *
298 ******************************************************************************/
299
300acpi_status
301acpi_ds_method_data_set_value (
302 u16 opcode,
303 u32 index,
304 union acpi_operand_object *object,
305 struct acpi_walk_state *walk_state)
306{
307 acpi_status status;
308 struct acpi_namespace_node *node;
309
310
311 ACPI_FUNCTION_TRACE ("ds_method_data_set_value");
312
313
314 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
315 "new_obj %p Opcode %X, Refs=%d [%s]\n", object,
316 opcode, object->common.reference_count,
317 acpi_ut_get_type_name (object->common.type)));
318
319 /* Get the namespace node for the arg/local */
320
321 status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
322 if (ACPI_FAILURE (status)) {
323 return_ACPI_STATUS (status);
324 }
325
326 /*
327 * Increment ref count so object can't be deleted while installed.
328 * NOTE: We do not copy the object in order to preserve the call by
329 * reference semantics of ACPI Control Method invocation.
330 * (See ACPI specification 2.0_c)
331 */
332 acpi_ut_add_reference (object);
333
334 /* Install the object */
335
336 node->object = object;
337 return_ACPI_STATUS (status);
338}
339
340
341/*******************************************************************************
342 *
343 * FUNCTION: acpi_ds_method_data_get_type
344 *
345 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
346 * Index - which local_var or argument whose type
347 * to get
348 * walk_state - Current walk state object
349 *
350 * RETURN: Data type of current value of the selected Arg or Local
351 *
352 ******************************************************************************/
353#ifdef ACPI_FUTURE_USAGE
354acpi_object_type
355acpi_ds_method_data_get_type (
356 u16 opcode,
357 u32 index,
358 struct acpi_walk_state *walk_state)
359{
360 acpi_status status;
361 struct acpi_namespace_node *node;
362 union acpi_operand_object *object;
363
364
365 ACPI_FUNCTION_TRACE ("ds_method_data_get_type");
366
367
368 /* Get the namespace node for the arg/local */
369
370 status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
371 if (ACPI_FAILURE (status)) {
372 return_VALUE ((ACPI_TYPE_NOT_FOUND));
373 }
374
375 /* Get the object */
376
377 object = acpi_ns_get_attached_object (node);
378 if (!object) {
379 /* Uninitialized local/arg, return TYPE_ANY */
380
381 return_VALUE (ACPI_TYPE_ANY);
382 }
383
384 /* Get the object type */
385
386 return_VALUE (ACPI_GET_OBJECT_TYPE (object));
387}
388#endif /* ACPI_FUTURE_USAGE */
389
390
391/*******************************************************************************
392 *
393 * FUNCTION: acpi_ds_method_data_get_value
394 *
395 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
396 * Index - which local_var or argument to get
397 * walk_state - Current walk state object
398 * *dest_desc - Ptr to Descriptor into which selected Arg
399 * or Local value should be copied
400 *
401 * RETURN: Status
402 *
403 * DESCRIPTION: Retrieve value of selected Arg or Local from the method frame
404 * at the current top of the method stack.
405 * Used only in acpi_ex_resolve_to_value().
406 *
407 ******************************************************************************/
408
409acpi_status
410acpi_ds_method_data_get_value (
411 u16 opcode,
412 u32 index,
413 struct acpi_walk_state *walk_state,
414 union acpi_operand_object **dest_desc)
415{
416 acpi_status status;
417 struct acpi_namespace_node *node;
418 union acpi_operand_object *object;
419
420
421 ACPI_FUNCTION_TRACE ("ds_method_data_get_value");
422
423
424 /* Validate the object descriptor */
425
426 if (!dest_desc) {
427 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null object descriptor pointer\n"));
428 return_ACPI_STATUS (AE_BAD_PARAMETER);
429 }
430
431 /* Get the namespace node for the arg/local */
432
433 status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
434 if (ACPI_FAILURE (status)) {
435 return_ACPI_STATUS (status);
436 }
437
438 /* Get the object from the node */
439
440 object = node->object;
441
442 /* Examine the returned object, it must be valid. */
443
444 if (!object) {
445 /*
446 * Index points to uninitialized object.
447 * This means that either 1) The expected argument was
448 * not passed to the method, or 2) A local variable
449 * was referenced by the method (via the ASL)
450 * before it was initialized. Either case is an error.
451 */
452
453 /* If slack enabled, init the local_x/arg_x to an Integer of value zero */
454
455 if (acpi_gbl_enable_interpreter_slack) {
456 object = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
457 if (!object) {
458 return_ACPI_STATUS (AE_NO_MEMORY);
459 }
460
461 object->integer.value = 0;
462 node->object = object;
463 }
464
465 /* Otherwise, return the error */
466
467 else switch (opcode) {
468 case AML_ARG_OP:
469
470 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Arg[%d] at node %p\n",
471 index, node));
472
473 return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG);
474
475 case AML_LOCAL_OP:
476
477 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Local[%d] at node %p\n",
478 index, node));
479
480 return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL);
481
482 default:
483 ACPI_REPORT_ERROR (("Not Arg/Local opcode: %X\n", opcode));
484 return_ACPI_STATUS (AE_AML_INTERNAL);
485 }
486 }
487
488 /*
489 * The Index points to an initialized and valid object.
490 * Return an additional reference to the object
491 */
492 *dest_desc = object;
493 acpi_ut_add_reference (object);
494
495 return_ACPI_STATUS (AE_OK);
496}
497
498
499/*******************************************************************************
500 *
501 * FUNCTION: acpi_ds_method_data_delete_value
502 *
503 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
504 * Index - which local_var or argument to delete
505 * walk_state - Current walk state object
506 *
507 * RETURN: None
508 *
509 * DESCRIPTION: Delete the entry at Opcode:Index on the method stack. Inserts
510 * a null into the stack slot after the object is deleted.
511 *
512 ******************************************************************************/
513
514void
515acpi_ds_method_data_delete_value (
516 u16 opcode,
517 u32 index,
518 struct acpi_walk_state *walk_state)
519{
520 acpi_status status;
521 struct acpi_namespace_node *node;
522 union acpi_operand_object *object;
523
524
525 ACPI_FUNCTION_TRACE ("ds_method_data_delete_value");
526
527
528 /* Get the namespace node for the arg/local */
529
530 status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
531 if (ACPI_FAILURE (status)) {
532 return_VOID;
533 }
534
535 /* Get the associated object */
536
537 object = acpi_ns_get_attached_object (node);
538
539 /*
540 * Undefine the Arg or Local by setting its descriptor
541 * pointer to NULL. Locals/Args can contain both
542 * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs
543 */
544 node->object = NULL;
545
546 if ((object) &&
547 (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_OPERAND)) {
548 /*
549 * There is a valid object.
550 * Decrement the reference count by one to balance the
551 * increment when the object was stored.
552 */
553 acpi_ut_remove_reference (object);
554 }
555
556 return_VOID;
557}
558
559
560/*******************************************************************************
561 *
562 * FUNCTION: acpi_ds_store_object_to_local
563 *
564 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
565 * Index - which local_var or argument to set
566 * obj_desc - Value to be stored
567 * walk_state - Current walk state
568 *
569 * RETURN: Status
570 *
571 * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed
572 * as the new value for the Arg or Local and the reference count
573 * for obj_desc is incremented.
574 *
575 ******************************************************************************/
576
577acpi_status
578acpi_ds_store_object_to_local (
579 u16 opcode,
580 u32 index,
581 union acpi_operand_object *obj_desc,
582 struct acpi_walk_state *walk_state)
583{
584 acpi_status status;
585 struct acpi_namespace_node *node;
586 union acpi_operand_object *current_obj_desc;
587 union acpi_operand_object *new_obj_desc;
588
589
590 ACPI_FUNCTION_TRACE ("ds_store_object_to_local");
591 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n",
592 opcode, index, obj_desc));
593
594 /* Parameter validation */
595
596 if (!obj_desc) {
597 return_ACPI_STATUS (AE_BAD_PARAMETER);
598 }
599
600 /* Get the namespace node for the arg/local */
601
602 status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
603 if (ACPI_FAILURE (status)) {
604 return_ACPI_STATUS (status);
605 }
606
607 current_obj_desc = acpi_ns_get_attached_object (node);
608 if (current_obj_desc == obj_desc) {
609 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n",
610 obj_desc));
611 return_ACPI_STATUS (status);
612 }
613
614 /*
615 * If the reference count on the object is more than one, we must
616 * take a copy of the object before we store. A reference count
617 * of exactly 1 means that the object was just created during the
618 * evaluation of an expression, and we can safely use it since it
619 * is not used anywhere else.
620 */
621 new_obj_desc = obj_desc;
622 if (obj_desc->common.reference_count > 1) {
623 status = acpi_ut_copy_iobject_to_iobject (obj_desc, &new_obj_desc, walk_state);
624 if (ACPI_FAILURE (status)) {
625 return_ACPI_STATUS (status);
626 }
627 }
628
629 /*
630 * If there is an object already in this slot, we either
631 * have to delete it, or if this is an argument and there
632 * is an object reference stored there, we have to do
633 * an indirect store!
634 */
635 if (current_obj_desc) {
636 /*
637 * Check for an indirect store if an argument
638 * contains an object reference (stored as an Node).
639 * We don't allow this automatic dereferencing for
640 * locals, since a store to a local should overwrite
641 * anything there, including an object reference.
642 *
643 * If both Arg0 and Local0 contain ref_of (Local4):
644 *
645 * Store (1, Arg0) - Causes indirect store to local4
646 * Store (1, Local0) - Stores 1 in local0, overwriting
647 * the reference to local4
648 * Store (1, de_refof (Local0)) - Causes indirect store to local4
649 *
650 * Weird, but true.
651 */
652 if (opcode == AML_ARG_OP) {
653 /*
654 * Make sure that the object is the correct type. This may be overkill, but
655 * it is here because references were NS nodes in the past. Now they are
656 * operand objects of type Reference.
657 */
658 if (ACPI_GET_DESCRIPTOR_TYPE (current_obj_desc) != ACPI_DESC_TYPE_OPERAND) {
659 ACPI_REPORT_ERROR (("Invalid descriptor type while storing to method arg: [%s]\n",
660 acpi_ut_get_descriptor_name (current_obj_desc)));
661 return_ACPI_STATUS (AE_AML_INTERNAL);
662 }
663
664 /*
665 * If we have a valid reference object that came from ref_of(), do the
666 * indirect store
667 */
668 if ((current_obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
669 (current_obj_desc->reference.opcode == AML_REF_OF_OP)) {
670 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
671 "Arg (%p) is an obj_ref(Node), storing in node %p\n",
672 new_obj_desc, current_obj_desc));
673
674 /*
675 * Store this object to the Node (perform the indirect store)
676 * NOTE: No implicit conversion is performed, as per the ACPI
677 * specification rules on storing to Locals/Args.
678 */
679 status = acpi_ex_store_object_to_node (new_obj_desc,
680 current_obj_desc->reference.object, walk_state,
681 ACPI_NO_IMPLICIT_CONVERSION);
682
683 /* Remove local reference if we copied the object above */
684
685 if (new_obj_desc != obj_desc) {
686 acpi_ut_remove_reference (new_obj_desc);
687 }
688 return_ACPI_STATUS (status);
689 }
690 }
691
692 /*
693 * Delete the existing object
694 * before storing the new one
695 */
696 acpi_ds_method_data_delete_value (opcode, index, walk_state);
697 }
698
699 /*
700 * Install the Obj descriptor (*new_obj_desc) into
701 * the descriptor for the Arg or Local.
702 * (increments the object reference count by one)
703 */
704 status = acpi_ds_method_data_set_value (opcode, index, new_obj_desc, walk_state);
705
706 /* Remove local reference if we copied the object above */
707
708 if (new_obj_desc != obj_desc) {
709 acpi_ut_remove_reference (new_obj_desc);
710 }
711
712 return_ACPI_STATUS (status);
713}
714
715
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
new file mode 100644
index 000000000000..eb8af4785bcb
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -0,0 +1,618 @@
1/******************************************************************************
2 *
3 * Module Name: dsobject - Dispatcher object management routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/amlcode.h>
48#include <acpi/acdispat.h>
49#include <acpi/acnamesp.h>
50#include <acpi/acinterp.h>
51
52#define _COMPONENT ACPI_DISPATCHER
53 ACPI_MODULE_NAME ("dsobject")
54
55
56#ifndef ACPI_NO_METHOD_EXECUTION
57/*****************************************************************************
58 *
59 * FUNCTION: acpi_ds_build_internal_object
60 *
61 * PARAMETERS: walk_state - Current walk state
62 * Op - Parser object to be translated
63 * obj_desc_ptr - Where the ACPI internal object is returned
64 *
65 * RETURN: Status
66 *
67 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
68 * Simple objects are any objects other than a package object!
69 *
70 ****************************************************************************/
71
72acpi_status
73acpi_ds_build_internal_object (
74 struct acpi_walk_state *walk_state,
75 union acpi_parse_object *op,
76 union acpi_operand_object **obj_desc_ptr)
77{
78 union acpi_operand_object *obj_desc;
79 acpi_status status;
80
81
82 ACPI_FUNCTION_TRACE ("ds_build_internal_object");
83
84
85 *obj_desc_ptr = NULL;
86 if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
87 /*
88 * This is an named object reference. If this name was
89 * previously looked up in the namespace, it was stored in this op.
90 * Otherwise, go ahead and look it up now
91 */
92 if (!op->common.node) {
93 status = acpi_ns_lookup (walk_state->scope_info, op->common.value.string,
94 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
95 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
96 (struct acpi_namespace_node **) &(op->common.node));
97
98 if (ACPI_FAILURE (status)) {
99 ACPI_REPORT_NSERROR (op->common.value.string, status);
100 return_ACPI_STATUS (status);
101 }
102 }
103 }
104
105 /* Create and init the internal ACPI object */
106
107 obj_desc = acpi_ut_create_internal_object ((acpi_ps_get_opcode_info (op->common.aml_opcode))->object_type);
108 if (!obj_desc) {
109 return_ACPI_STATUS (AE_NO_MEMORY);
110 }
111
112 status = acpi_ds_init_object_from_op (walk_state, op, op->common.aml_opcode, &obj_desc);
113 if (ACPI_FAILURE (status)) {
114 acpi_ut_remove_reference (obj_desc);
115 return_ACPI_STATUS (status);
116 }
117
118 *obj_desc_ptr = obj_desc;
119 return_ACPI_STATUS (AE_OK);
120}
121
122
123/*****************************************************************************
124 *
125 * FUNCTION: acpi_ds_build_internal_buffer_obj
126 *
127 * PARAMETERS: walk_state - Current walk state
128 * Op - Parser object to be translated
129 * buffer_length - Length of the buffer
130 * obj_desc_ptr - Where the ACPI internal object is returned
131 *
132 * RETURN: Status
133 *
134 * DESCRIPTION: Translate a parser Op package object to the equivalent
135 * namespace object
136 *
137 ****************************************************************************/
138
139acpi_status
140acpi_ds_build_internal_buffer_obj (
141 struct acpi_walk_state *walk_state,
142 union acpi_parse_object *op,
143 u32 buffer_length,
144 union acpi_operand_object **obj_desc_ptr)
145{
146 union acpi_parse_object *arg;
147 union acpi_operand_object *obj_desc;
148 union acpi_parse_object *byte_list;
149 u32 byte_list_length = 0;
150
151
152 ACPI_FUNCTION_TRACE ("ds_build_internal_buffer_obj");
153
154
155 obj_desc = *obj_desc_ptr;
156 if (obj_desc) {
157 /*
158 * We are evaluating a Named buffer object "Name (xxxx, Buffer)".
159 * The buffer object already exists (from the NS node)
160 */
161 }
162 else {
163 /* Create a new buffer object */
164
165 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
166 *obj_desc_ptr = obj_desc;
167 if (!obj_desc) {
168 return_ACPI_STATUS (AE_NO_MEMORY);
169 }
170 }
171
172 /*
173 * Second arg is the buffer data (optional) byte_list can be either
174 * individual bytes or a string initializer. In either case, a
175 * byte_list appears in the AML.
176 */
177 arg = op->common.value.arg; /* skip first arg */
178
179 byte_list = arg->named.next;
180 if (byte_list) {
181 if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
182 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
183 "Expecting bytelist, got AML opcode %X in op %p\n",
184 byte_list->common.aml_opcode, byte_list));
185
186 acpi_ut_remove_reference (obj_desc);
187 return (AE_TYPE);
188 }
189
190 byte_list_length = (u32) byte_list->common.value.integer;
191 }
192
193 /*
194 * The buffer length (number of bytes) will be the larger of:
195 * 1) The specified buffer length and
196 * 2) The length of the initializer byte list
197 */
198 obj_desc->buffer.length = buffer_length;
199 if (byte_list_length > buffer_length) {
200 obj_desc->buffer.length = byte_list_length;
201 }
202
203 /* Allocate the buffer */
204
205 if (obj_desc->buffer.length == 0) {
206 obj_desc->buffer.pointer = NULL;
207 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
208 "Buffer defined with zero length in AML, creating\n"));
209 }
210 else {
211 obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
212 obj_desc->buffer.length);
213 if (!obj_desc->buffer.pointer) {
214 acpi_ut_delete_object_desc (obj_desc);
215 return_ACPI_STATUS (AE_NO_MEMORY);
216 }
217
218 /* Initialize buffer from the byte_list (if present) */
219
220 if (byte_list) {
221 ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->named.data,
222 byte_list_length);
223 }
224 }
225
226 obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
227 op->common.node = (struct acpi_namespace_node *) obj_desc;
228 return_ACPI_STATUS (AE_OK);
229}
230
231
232/*****************************************************************************
233 *
234 * FUNCTION: acpi_ds_build_internal_package_obj
235 *
236 * PARAMETERS: walk_state - Current walk state
237 * Op - Parser object to be translated
238 * package_length - Number of elements in the package
239 * obj_desc_ptr - Where the ACPI internal object is returned
240 *
241 * RETURN: Status
242 *
243 * DESCRIPTION: Translate a parser Op package object to the equivalent
244 * namespace object
245 *
246 ****************************************************************************/
247
248acpi_status
249acpi_ds_build_internal_package_obj (
250 struct acpi_walk_state *walk_state,
251 union acpi_parse_object *op,
252 u32 package_length,
253 union acpi_operand_object **obj_desc_ptr)
254{
255 union acpi_parse_object *arg;
256 union acpi_parse_object *parent;
257 union acpi_operand_object *obj_desc = NULL;
258 u32 package_list_length;
259 acpi_status status = AE_OK;
260 u32 i;
261
262
263 ACPI_FUNCTION_TRACE ("ds_build_internal_package_obj");
264
265
266 /* Find the parent of a possibly nested package */
267
268 parent = op->common.parent;
269 while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
270 (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
271 parent = parent->common.parent;
272 }
273
274 obj_desc = *obj_desc_ptr;
275 if (obj_desc) {
276 /*
277 * We are evaluating a Named package object "Name (xxxx, Package)".
278 * Get the existing package object from the NS node
279 */
280 }
281 else {
282 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
283 *obj_desc_ptr = obj_desc;
284 if (!obj_desc) {
285 return_ACPI_STATUS (AE_NO_MEMORY);
286 }
287
288 obj_desc->package.node = parent->common.node;
289 }
290
291 obj_desc->package.count = package_length;
292
293 /* Count the number of items in the package list */
294
295 package_list_length = 0;
296 arg = op->common.value.arg;
297 arg = arg->common.next;
298 while (arg) {
299 package_list_length++;
300 arg = arg->common.next;
301 }
302
303 /*
304 * The package length (number of elements) will be the greater
305 * of the specified length and the length of the initializer list
306 */
307 if (package_list_length > package_length) {
308 obj_desc->package.count = package_list_length;
309 }
310
311 /*
312 * Allocate the pointer array (array of pointers to the
313 * individual objects). Add an extra pointer slot so
314 * that the list is always null terminated.
315 */
316 obj_desc->package.elements = ACPI_MEM_CALLOCATE (
317 ((acpi_size) obj_desc->package.count + 1) * sizeof (void *));
318
319 if (!obj_desc->package.elements) {
320 acpi_ut_delete_object_desc (obj_desc);
321 return_ACPI_STATUS (AE_NO_MEMORY);
322 }
323
324 /*
325 * Now init the elements of the package
326 */
327 i = 0;
328 arg = op->common.value.arg;
329 arg = arg->common.next;
330 while (arg) {
331 if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
332 /* Object (package or buffer) is already built */
333
334 obj_desc->package.elements[i] = ACPI_CAST_PTR (union acpi_operand_object, arg->common.node);
335 }
336 else {
337 status = acpi_ds_build_internal_object (walk_state, arg,
338 &obj_desc->package.elements[i]);
339 }
340
341 i++;
342 arg = arg->common.next;
343 }
344
345 obj_desc->package.flags |= AOPOBJ_DATA_VALID;
346 op->common.node = (struct acpi_namespace_node *) obj_desc;
347 return_ACPI_STATUS (status);
348}
349
350
351/*****************************************************************************
352 *
353 * FUNCTION: acpi_ds_create_node
354 *
355 * PARAMETERS: walk_state - Current walk state
356 * Node - NS Node to be initialized
357 * Op - Parser object to be translated
358 *
359 * RETURN: Status
360 *
361 * DESCRIPTION: Create the object to be associated with a namespace node
362 *
363 ****************************************************************************/
364
365acpi_status
366acpi_ds_create_node (
367 struct acpi_walk_state *walk_state,
368 struct acpi_namespace_node *node,
369 union acpi_parse_object *op)
370{
371 acpi_status status;
372 union acpi_operand_object *obj_desc;
373
374
375 ACPI_FUNCTION_TRACE_PTR ("ds_create_node", op);
376
377
378 /*
379 * Because of the execution pass through the non-control-method
380 * parts of the table, we can arrive here twice. Only init
381 * the named object node the first time through
382 */
383 if (acpi_ns_get_attached_object (node)) {
384 return_ACPI_STATUS (AE_OK);
385 }
386
387 if (!op->common.value.arg) {
388 /* No arguments, there is nothing to do */
389
390 return_ACPI_STATUS (AE_OK);
391 }
392
393 /* Build an internal object for the argument(s) */
394
395 status = acpi_ds_build_internal_object (walk_state, op->common.value.arg, &obj_desc);
396 if (ACPI_FAILURE (status)) {
397 return_ACPI_STATUS (status);
398 }
399
400 /* Re-type the object according to its argument */
401
402 node->type = ACPI_GET_OBJECT_TYPE (obj_desc);
403
404 /* Attach obj to node */
405
406 status = acpi_ns_attach_object (node, obj_desc, node->type);
407
408 /* Remove local reference to the object */
409
410 acpi_ut_remove_reference (obj_desc);
411 return_ACPI_STATUS (status);
412}
413
414#endif /* ACPI_NO_METHOD_EXECUTION */
415
416
417/*****************************************************************************
418 *
419 * FUNCTION: acpi_ds_init_object_from_op
420 *
421 * PARAMETERS: walk_state - Current walk state
422 * Op - Parser op used to init the internal object
423 * Opcode - AML opcode associated with the object
424 * ret_obj_desc - Namespace object to be initialized
425 *
426 * RETURN: Status
427 *
428 * DESCRIPTION: Initialize a namespace object from a parser Op and its
429 * associated arguments. The namespace object is a more compact
430 * representation of the Op and its arguments.
431 *
432 ****************************************************************************/
433
434acpi_status
435acpi_ds_init_object_from_op (
436 struct acpi_walk_state *walk_state,
437 union acpi_parse_object *op,
438 u16 opcode,
439 union acpi_operand_object **ret_obj_desc)
440{
441 const struct acpi_opcode_info *op_info;
442 union acpi_operand_object *obj_desc;
443 acpi_status status = AE_OK;
444
445
446 ACPI_FUNCTION_TRACE ("ds_init_object_from_op");
447
448
449 obj_desc = *ret_obj_desc;
450 op_info = acpi_ps_get_opcode_info (opcode);
451 if (op_info->class == AML_CLASS_UNKNOWN) {
452 /* Unknown opcode */
453
454 return_ACPI_STATUS (AE_TYPE);
455 }
456
457 /* Perform per-object initialization */
458
459 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
460 case ACPI_TYPE_BUFFER:
461
462 /*
463 * Defer evaluation of Buffer term_arg operand
464 */
465 obj_desc->buffer.node = (struct acpi_namespace_node *) walk_state->operands[0];
466 obj_desc->buffer.aml_start = op->named.data;
467 obj_desc->buffer.aml_length = op->named.length;
468 break;
469
470
471 case ACPI_TYPE_PACKAGE:
472
473 /*
474 * Defer evaluation of Package term_arg operand
475 */
476 obj_desc->package.node = (struct acpi_namespace_node *) walk_state->operands[0];
477 obj_desc->package.aml_start = op->named.data;
478 obj_desc->package.aml_length = op->named.length;
479 break;
480
481
482 case ACPI_TYPE_INTEGER:
483
484 switch (op_info->type) {
485 case AML_TYPE_CONSTANT:
486 /*
487 * Resolve AML Constants here - AND ONLY HERE!
488 * All constants are integers.
489 * We mark the integer with a flag that indicates that it started life
490 * as a constant -- so that stores to constants will perform as expected (noop).
491 * (zero_op is used as a placeholder for optional target operands.)
492 */
493 obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
494
495 switch (opcode) {
496 case AML_ZERO_OP:
497
498 obj_desc->integer.value = 0;
499 break;
500
501 case AML_ONE_OP:
502
503 obj_desc->integer.value = 1;
504 break;
505
506 case AML_ONES_OP:
507
508 obj_desc->integer.value = ACPI_INTEGER_MAX;
509
510 /* Truncate value if we are executing from a 32-bit ACPI table */
511
512#ifndef ACPI_NO_METHOD_EXECUTION
513 acpi_ex_truncate_for32bit_table (obj_desc);
514#endif
515 break;
516
517 case AML_REVISION_OP:
518
519 obj_desc->integer.value = ACPI_CA_VERSION;
520 break;
521
522 default:
523
524 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown constant opcode %X\n", opcode));
525 status = AE_AML_OPERAND_TYPE;
526 break;
527 }
528 break;
529
530
531 case AML_TYPE_LITERAL:
532
533 obj_desc->integer.value = op->common.value.integer;
534 break;
535
536
537 default:
538 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n", op_info->type));
539 status = AE_AML_OPERAND_TYPE;
540 break;
541 }
542 break;
543
544
545 case ACPI_TYPE_STRING:
546
547 obj_desc->string.pointer = op->common.value.string;
548 obj_desc->string.length = (u32) ACPI_STRLEN (op->common.value.string);
549
550 /*
551 * The string is contained in the ACPI table, don't ever try
552 * to delete it
553 */
554 obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
555 break;
556
557
558 case ACPI_TYPE_METHOD:
559 break;
560
561
562 case ACPI_TYPE_LOCAL_REFERENCE:
563
564 switch (op_info->type) {
565 case AML_TYPE_LOCAL_VARIABLE:
566
567 /* Split the opcode into a base opcode + offset */
568
569 obj_desc->reference.opcode = AML_LOCAL_OP;
570 obj_desc->reference.offset = opcode - AML_LOCAL_OP;
571
572#ifndef ACPI_NO_METHOD_EXECUTION
573 status = acpi_ds_method_data_get_node (AML_LOCAL_OP, obj_desc->reference.offset,
574 walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object);
575#endif
576 break;
577
578
579 case AML_TYPE_METHOD_ARGUMENT:
580
581 /* Split the opcode into a base opcode + offset */
582
583 obj_desc->reference.opcode = AML_ARG_OP;
584 obj_desc->reference.offset = opcode - AML_ARG_OP;
585
586#ifndef ACPI_NO_METHOD_EXECUTION
587 status = acpi_ds_method_data_get_node (AML_ARG_OP, obj_desc->reference.offset,
588 walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object);
589#endif
590 break;
591
592 default: /* Other literals, etc.. */
593
594 if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
595 /* Node was saved in Op */
596
597 obj_desc->reference.node = op->common.node;
598 }
599
600 obj_desc->reference.opcode = opcode;
601 break;
602 }
603 break;
604
605
606 default:
607
608 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n",
609 ACPI_GET_OBJECT_TYPE (obj_desc)));
610
611 status = AE_AML_OPERAND_TYPE;
612 break;
613 }
614
615 return_ACPI_STATUS (status);
616}
617
618
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
new file mode 100644
index 000000000000..5c987a0e7b75
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -0,0 +1,1151 @@
1/******************************************************************************
2 *
3 * Module Name: dsopcode - Dispatcher Op Region support and handling of
4 * "control" opcodes
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acparser.h>
48#include <acpi/amlcode.h>
49#include <acpi/acdispat.h>
50#include <acpi/acinterp.h>
51#include <acpi/acnamesp.h>
52#include <acpi/acevents.h>
53
54#define _COMPONENT ACPI_DISPATCHER
55 ACPI_MODULE_NAME ("dsopcode")
56
57
58/*****************************************************************************
59 *
60 * FUNCTION: acpi_ds_execute_arguments
61 *
62 * PARAMETERS: Node - Parent NS node
63 * aml_length - Length of executable AML
64 * aml_start - Pointer to the AML
65 *
66 * RETURN: Status.
67 *
68 * DESCRIPTION: Late (deferred) execution of region or field arguments
69 *
70 ****************************************************************************/
71
72acpi_status
73acpi_ds_execute_arguments (
74 struct acpi_namespace_node *node,
75 struct acpi_namespace_node *scope_node,
76 u32 aml_length,
77 u8 *aml_start)
78{
79 acpi_status status;
80 union acpi_parse_object *op;
81 struct acpi_walk_state *walk_state;
82
83
84 ACPI_FUNCTION_TRACE ("ds_execute_arguments");
85
86
87 /*
88 * Allocate a new parser op to be the root of the parsed tree
89 */
90 op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP);
91 if (!op) {
92 return_ACPI_STATUS (AE_NO_MEMORY);
93 }
94
95 /* Save the Node for use in acpi_ps_parse_aml */
96
97 op->common.node = scope_node;
98
99 /* Create and initialize a new parser state */
100
101 walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
102 if (!walk_state) {
103 return_ACPI_STATUS (AE_NO_MEMORY);
104 }
105
106 status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
107 aml_length, NULL, 1);
108 if (ACPI_FAILURE (status)) {
109 acpi_ds_delete_walk_state (walk_state);
110 return_ACPI_STATUS (status);
111 }
112
113 /* Mark this parse as a deferred opcode */
114
115 walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;
116 walk_state->deferred_node = node;
117
118 /* Pass1: Parse the entire declaration */
119
120 status = acpi_ps_parse_aml (walk_state);
121 if (ACPI_FAILURE (status)) {
122 acpi_ps_delete_parse_tree (op);
123 return_ACPI_STATUS (status);
124 }
125
126 /* Get and init the Op created above */
127
128 op->common.node = node;
129 acpi_ps_delete_parse_tree (op);
130
131 /* Evaluate the deferred arguments */
132
133 op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP);
134 if (!op) {
135 return_ACPI_STATUS (AE_NO_MEMORY);
136 }
137
138 op->common.node = scope_node;
139
140 /* Create and initialize a new parser state */
141
142 walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
143 if (!walk_state) {
144 return_ACPI_STATUS (AE_NO_MEMORY);
145 }
146
147 /* Execute the opcode and arguments */
148
149 status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
150 aml_length, NULL, 3);
151 if (ACPI_FAILURE (status)) {
152 acpi_ds_delete_walk_state (walk_state);
153 return_ACPI_STATUS (status);
154 }
155
156 /* Mark this execution as a deferred opcode */
157
158 walk_state->deferred_node = node;
159 status = acpi_ps_parse_aml (walk_state);
160 acpi_ps_delete_parse_tree (op);
161 return_ACPI_STATUS (status);
162}
163
164
165/*****************************************************************************
166 *
167 * FUNCTION: acpi_ds_get_buffer_field_arguments
168 *
169 * PARAMETERS: obj_desc - A valid buffer_field object
170 *
171 * RETURN: Status.
172 *
173 * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late
174 * evaluation of these field attributes.
175 *
176 ****************************************************************************/
177
178acpi_status
179acpi_ds_get_buffer_field_arguments (
180 union acpi_operand_object *obj_desc)
181{
182 union acpi_operand_object *extra_desc;
183 struct acpi_namespace_node *node;
184 acpi_status status;
185
186
187 ACPI_FUNCTION_TRACE_PTR ("ds_get_buffer_field_arguments", obj_desc);
188
189
190 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
191 return_ACPI_STATUS (AE_OK);
192 }
193
194 /* Get the AML pointer (method object) and buffer_field node */
195
196 extra_desc = acpi_ns_get_secondary_object (obj_desc);
197 node = obj_desc->buffer_field.node;
198
199 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_BUFFER_FIELD, node, NULL));
200 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] buffer_field Arg Init\n",
201 acpi_ut_get_node_name (node)));
202
203 /* Execute the AML code for the term_arg arguments */
204
205 status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node),
206 extra_desc->extra.aml_length, extra_desc->extra.aml_start);
207 return_ACPI_STATUS (status);
208}
209
210
211/*****************************************************************************
212 *
213 * FUNCTION: acpi_ds_get_buffer_arguments
214 *
215 * PARAMETERS: obj_desc - A valid Buffer object
216 *
217 * RETURN: Status.
218 *
219 * DESCRIPTION: Get Buffer length and initializer byte list. This implements
220 * the late evaluation of these attributes.
221 *
222 ****************************************************************************/
223
224acpi_status
225acpi_ds_get_buffer_arguments (
226 union acpi_operand_object *obj_desc)
227{
228 struct acpi_namespace_node *node;
229 acpi_status status;
230
231
232 ACPI_FUNCTION_TRACE_PTR ("ds_get_buffer_arguments", obj_desc);
233
234
235 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
236 return_ACPI_STATUS (AE_OK);
237 }
238
239 /* Get the Buffer node */
240
241 node = obj_desc->buffer.node;
242 if (!node) {
243 ACPI_REPORT_ERROR ((
244 "No pointer back to NS node in buffer obj %p\n", obj_desc));
245 return_ACPI_STATUS (AE_AML_INTERNAL);
246 }
247
248 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer Arg Init\n"));
249
250 /* Execute the AML code for the term_arg arguments */
251
252 status = acpi_ds_execute_arguments (node, node,
253 obj_desc->buffer.aml_length, obj_desc->buffer.aml_start);
254 return_ACPI_STATUS (status);
255}
256
257
258/*****************************************************************************
259 *
260 * FUNCTION: acpi_ds_get_package_arguments
261 *
262 * PARAMETERS: obj_desc - A valid Package object
263 *
264 * RETURN: Status.
265 *
266 * DESCRIPTION: Get Package length and initializer byte list. This implements
267 * the late evaluation of these attributes.
268 *
269 ****************************************************************************/
270
271acpi_status
272acpi_ds_get_package_arguments (
273 union acpi_operand_object *obj_desc)
274{
275 struct acpi_namespace_node *node;
276 acpi_status status;
277
278
279 ACPI_FUNCTION_TRACE_PTR ("ds_get_package_arguments", obj_desc);
280
281
282 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
283 return_ACPI_STATUS (AE_OK);
284 }
285
286 /* Get the Package node */
287
288 node = obj_desc->package.node;
289 if (!node) {
290 ACPI_REPORT_ERROR ((
291 "No pointer back to NS node in package %p\n", obj_desc));
292 return_ACPI_STATUS (AE_AML_INTERNAL);
293 }
294
295 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package Arg Init\n"));
296
297 /* Execute the AML code for the term_arg arguments */
298
299 status = acpi_ds_execute_arguments (node, node,
300 obj_desc->package.aml_length, obj_desc->package.aml_start);
301 return_ACPI_STATUS (status);
302}
303
304
305/*****************************************************************************
306 *
307 * FUNCTION: acpi_ds_get_region_arguments
308 *
309 * PARAMETERS: obj_desc - A valid region object
310 *
311 * RETURN: Status.
312 *
313 * DESCRIPTION: Get region address and length. This implements the late
314 * evaluation of these region attributes.
315 *
316 ****************************************************************************/
317
318acpi_status
319acpi_ds_get_region_arguments (
320 union acpi_operand_object *obj_desc)
321{
322 struct acpi_namespace_node *node;
323 acpi_status status;
324 union acpi_operand_object *extra_desc;
325
326
327 ACPI_FUNCTION_TRACE_PTR ("ds_get_region_arguments", obj_desc);
328
329
330 if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
331 return_ACPI_STATUS (AE_OK);
332 }
333
334 extra_desc = acpi_ns_get_secondary_object (obj_desc);
335 if (!extra_desc) {
336 return_ACPI_STATUS (AE_NOT_EXIST);
337 }
338
339 /* Get the Region node */
340
341 node = obj_desc->region.node;
342
343 ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_REGION, node, NULL));
344
345 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] op_region Arg Init at AML %p\n",
346 acpi_ut_get_node_name (node), extra_desc->extra.aml_start));
347
348 /* Execute the argument AML */
349
350 status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node),
351 extra_desc->extra.aml_length, extra_desc->extra.aml_start);
352 return_ACPI_STATUS (status);
353}
354
355
356/*****************************************************************************
357 *
358 * FUNCTION: acpi_ds_initialize_region
359 *
360 * PARAMETERS: Op - A valid region Op object
361 *
362 * RETURN: Status
363 *
364 * DESCRIPTION: Front end to ev_initialize_region
365 *
366 ****************************************************************************/
367
368acpi_status
369acpi_ds_initialize_region (
370 acpi_handle obj_handle)
371{
372 union acpi_operand_object *obj_desc;
373 acpi_status status;
374
375
376 obj_desc = acpi_ns_get_attached_object (obj_handle);
377
378 /* Namespace is NOT locked */
379
380 status = acpi_ev_initialize_region (obj_desc, FALSE);
381 return (status);
382}
383
384
385/*****************************************************************************
386 *
387 * FUNCTION: acpi_ds_init_buffer_field
388 *
389 * PARAMETERS: aml_opcode - create_xxx_field
390 * obj_desc - buffer_field object
391 * buffer_desc - Host Buffer
392 * offset_desc - Offset into buffer
393 * Length - Length of field (CREATE_FIELD_OP only)
394 * Result - Where to store the result
395 *
396 * RETURN: Status
397 *
398 * DESCRIPTION: Perform actual initialization of a buffer field
399 *
400 ****************************************************************************/
401
402acpi_status
403acpi_ds_init_buffer_field (
404 u16 aml_opcode,
405 union acpi_operand_object *obj_desc,
406 union acpi_operand_object *buffer_desc,
407 union acpi_operand_object *offset_desc,
408 union acpi_operand_object *length_desc,
409 union acpi_operand_object *result_desc)
410{
411 u32 offset;
412 u32 bit_offset;
413 u32 bit_count;
414 u8 field_flags;
415 acpi_status status;
416
417
418 ACPI_FUNCTION_TRACE_PTR ("ds_init_buffer_field", obj_desc);
419
420
421 /* Host object must be a Buffer */
422
423 if (ACPI_GET_OBJECT_TYPE (buffer_desc) != ACPI_TYPE_BUFFER) {
424 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
425 "Target of Create Field is not a Buffer object - %s\n",
426 acpi_ut_get_object_type_name (buffer_desc)));
427
428 status = AE_AML_OPERAND_TYPE;
429 goto cleanup;
430 }
431
432 /*
433 * The last parameter to all of these opcodes (result_desc) started
434 * out as a name_string, and should therefore now be a NS node
435 * after resolution in acpi_ex_resolve_operands().
436 */
437 if (ACPI_GET_DESCRIPTOR_TYPE (result_desc) != ACPI_DESC_TYPE_NAMED) {
438 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) destination not a NS Node [%s]\n",
439 acpi_ps_get_opcode_name (aml_opcode), acpi_ut_get_descriptor_name (result_desc)));
440
441 status = AE_AML_OPERAND_TYPE;
442 goto cleanup;
443 }
444
445 offset = (u32) offset_desc->integer.value;
446
447 /*
448 * Setup the Bit offsets and counts, according to the opcode
449 */
450 switch (aml_opcode) {
451 case AML_CREATE_FIELD_OP:
452
453 /* Offset is in bits, count is in bits */
454
455 bit_offset = offset;
456 bit_count = (u32) length_desc->integer.value;
457 field_flags = AML_FIELD_ACCESS_BYTE;
458 break;
459
460 case AML_CREATE_BIT_FIELD_OP:
461
462 /* Offset is in bits, Field is one bit */
463
464 bit_offset = offset;
465 bit_count = 1;
466 field_flags = AML_FIELD_ACCESS_BYTE;
467 break;
468
469 case AML_CREATE_BYTE_FIELD_OP:
470
471 /* Offset is in bytes, field is one byte */
472
473 bit_offset = 8 * offset;
474 bit_count = 8;
475 field_flags = AML_FIELD_ACCESS_BYTE;
476 break;
477
478 case AML_CREATE_WORD_FIELD_OP:
479
480 /* Offset is in bytes, field is one word */
481
482 bit_offset = 8 * offset;
483 bit_count = 16;
484 field_flags = AML_FIELD_ACCESS_WORD;
485 break;
486
487 case AML_CREATE_DWORD_FIELD_OP:
488
489 /* Offset is in bytes, field is one dword */
490
491 bit_offset = 8 * offset;
492 bit_count = 32;
493 field_flags = AML_FIELD_ACCESS_DWORD;
494 break;
495
496 case AML_CREATE_QWORD_FIELD_OP:
497
498 /* Offset is in bytes, field is one qword */
499
500 bit_offset = 8 * offset;
501 bit_count = 64;
502 field_flags = AML_FIELD_ACCESS_QWORD;
503 break;
504
505 default:
506
507 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
508 "Unknown field creation opcode %02x\n",
509 aml_opcode));
510 status = AE_AML_BAD_OPCODE;
511 goto cleanup;
512 }
513
514 /* Entire field must fit within the current length of the buffer */
515
516 if ((bit_offset + bit_count) >
517 (8 * (u32) buffer_desc->buffer.length)) {
518 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
519 "Field [%4.4s] size %d exceeds Buffer [%4.4s] size %d (bits)\n",
520 acpi_ut_get_node_name (result_desc),
521 bit_offset + bit_count,
522 acpi_ut_get_node_name (buffer_desc->buffer.node),
523 8 * (u32) buffer_desc->buffer.length));
524 status = AE_AML_BUFFER_LIMIT;
525 goto cleanup;
526 }
527
528 /*
529 * Initialize areas of the field object that are common to all fields
530 * For field_flags, use LOCK_RULE = 0 (NO_LOCK), UPDATE_RULE = 0 (UPDATE_PRESERVE)
531 */
532 status = acpi_ex_prep_common_field_object (obj_desc, field_flags, 0,
533 bit_offset, bit_count);
534 if (ACPI_FAILURE (status)) {
535 goto cleanup;
536 }
537
538 obj_desc->buffer_field.buffer_obj = buffer_desc;
539
540 /* Reference count for buffer_desc inherits obj_desc count */
541
542 buffer_desc->common.reference_count = (u16) (buffer_desc->common.reference_count +
543 obj_desc->common.reference_count);
544
545
546cleanup:
547
548 /* Always delete the operands */
549
550 acpi_ut_remove_reference (offset_desc);
551 acpi_ut_remove_reference (buffer_desc);
552
553 if (aml_opcode == AML_CREATE_FIELD_OP) {
554 acpi_ut_remove_reference (length_desc);
555 }
556
557 /* On failure, delete the result descriptor */
558
559 if (ACPI_FAILURE (status)) {
560 acpi_ut_remove_reference (result_desc); /* Result descriptor */
561 }
562 else {
563 /* Now the address and length are valid for this buffer_field */
564
565 obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
566 }
567
568 return_ACPI_STATUS (status);
569}
570
571
572/*****************************************************************************
573 *
574 * FUNCTION: acpi_ds_eval_buffer_field_operands
575 *
576 * PARAMETERS: walk_state - Current walk
577 * Op - A valid buffer_field Op object
578 *
579 * RETURN: Status
580 *
581 * DESCRIPTION: Get buffer_field Buffer and Index
582 * Called from acpi_ds_exec_end_op during buffer_field parse tree walk
583 *
584 ****************************************************************************/
585
586acpi_status
587acpi_ds_eval_buffer_field_operands (
588 struct acpi_walk_state *walk_state,
589 union acpi_parse_object *op)
590{
591 acpi_status status;
592 union acpi_operand_object *obj_desc;
593 struct acpi_namespace_node *node;
594 union acpi_parse_object *next_op;
595
596
597 ACPI_FUNCTION_TRACE_PTR ("ds_eval_buffer_field_operands", op);
598
599
600 /*
601 * This is where we evaluate the address and length fields of the
602 * create_xxx_field declaration
603 */
604 node = op->common.node;
605
606 /* next_op points to the op that holds the Buffer */
607
608 next_op = op->common.value.arg;
609
610 /* Evaluate/create the address and length operands */
611
612 status = acpi_ds_create_operands (walk_state, next_op);
613 if (ACPI_FAILURE (status)) {
614 return_ACPI_STATUS (status);
615 }
616
617 obj_desc = acpi_ns_get_attached_object (node);
618 if (!obj_desc) {
619 return_ACPI_STATUS (AE_NOT_EXIST);
620 }
621
622 /* Resolve the operands */
623
624 status = acpi_ex_resolve_operands (op->common.aml_opcode,
625 ACPI_WALK_OPERANDS, walk_state);
626
627 ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
628 acpi_ps_get_opcode_name (op->common.aml_opcode),
629 walk_state->num_operands, "after acpi_ex_resolve_operands");
630
631 if (ACPI_FAILURE (status)) {
632 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n",
633 acpi_ps_get_opcode_name (op->common.aml_opcode), status));
634
635 return_ACPI_STATUS (status);
636 }
637
638 /* Initialize the Buffer Field */
639
640 if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
641 /* NOTE: Slightly different operands for this opcode */
642
643 status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc,
644 walk_state->operands[0], walk_state->operands[1],
645 walk_state->operands[2], walk_state->operands[3]);
646 }
647 else {
648 /* All other, create_xxx_field opcodes */
649
650 status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc,
651 walk_state->operands[0], walk_state->operands[1],
652 NULL, walk_state->operands[2]);
653 }
654
655 return_ACPI_STATUS (status);
656}
657
658
659/*****************************************************************************
660 *
661 * FUNCTION: acpi_ds_eval_region_operands
662 *
663 * PARAMETERS: walk_state - Current walk
664 * Op - A valid region Op object
665 *
666 * RETURN: Status
667 *
668 * DESCRIPTION: Get region address and length
669 * Called from acpi_ds_exec_end_op during op_region parse tree walk
670 *
671 ****************************************************************************/
672
673acpi_status
674acpi_ds_eval_region_operands (
675 struct acpi_walk_state *walk_state,
676 union acpi_parse_object *op)
677{
678 acpi_status status;
679 union acpi_operand_object *obj_desc;
680 union acpi_operand_object *operand_desc;
681 struct acpi_namespace_node *node;
682 union acpi_parse_object *next_op;
683
684
685 ACPI_FUNCTION_TRACE_PTR ("ds_eval_region_operands", op);
686
687
688 /*
689 * This is where we evaluate the address and length fields of the op_region declaration
690 */
691 node = op->common.node;
692
693 /* next_op points to the op that holds the space_iD */
694
695 next_op = op->common.value.arg;
696
697 /* next_op points to address op */
698
699 next_op = next_op->common.next;
700
701 /* Evaluate/create the address and length operands */
702
703 status = acpi_ds_create_operands (walk_state, next_op);
704 if (ACPI_FAILURE (status)) {
705 return_ACPI_STATUS (status);
706 }
707
708 /* Resolve the length and address operands to numbers */
709
710 status = acpi_ex_resolve_operands (op->common.aml_opcode, ACPI_WALK_OPERANDS, walk_state);
711 if (ACPI_FAILURE (status)) {
712 return_ACPI_STATUS (status);
713 }
714
715 ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
716 acpi_ps_get_opcode_name (op->common.aml_opcode),
717 1, "after acpi_ex_resolve_operands");
718
719 obj_desc = acpi_ns_get_attached_object (node);
720 if (!obj_desc) {
721 return_ACPI_STATUS (AE_NOT_EXIST);
722 }
723
724 /*
725 * Get the length operand and save it
726 * (at Top of stack)
727 */
728 operand_desc = walk_state->operands[walk_state->num_operands - 1];
729
730 obj_desc->region.length = (u32) operand_desc->integer.value;
731 acpi_ut_remove_reference (operand_desc);
732
733 /*
734 * Get the address and save it
735 * (at top of stack - 1)
736 */
737 operand_desc = walk_state->operands[walk_state->num_operands - 2];
738
739 obj_desc->region.address = (acpi_physical_address) operand_desc->integer.value;
740 acpi_ut_remove_reference (operand_desc);
741
742 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "rgn_obj %p Addr %8.8X%8.8X Len %X\n",
743 obj_desc,
744 ACPI_FORMAT_UINT64 (obj_desc->region.address),
745 obj_desc->region.length));
746
747 /* Now the address and length are valid for this opregion */
748
749 obj_desc->region.flags |= AOPOBJ_DATA_VALID;
750
751 return_ACPI_STATUS (status);
752}
753
754
755/*****************************************************************************
756 *
757 * FUNCTION: acpi_ds_eval_data_object_operands
758 *
759 * PARAMETERS: walk_state - Current walk
760 * Op - A valid data_object Op object
761 * obj_desc - data_object
762 *
763 * RETURN: Status
764 *
765 * DESCRIPTION: Get the operands and complete the following data object types:
766 * Buffer, Package.
767 *
768 ****************************************************************************/
769
770acpi_status
771acpi_ds_eval_data_object_operands (
772 struct acpi_walk_state *walk_state,
773 union acpi_parse_object *op,
774 union acpi_operand_object *obj_desc)
775{
776 acpi_status status;
777 union acpi_operand_object *arg_desc;
778 u32 length;
779
780
781 ACPI_FUNCTION_TRACE ("ds_eval_data_object_operands");
782
783
784 /* The first operand (for all of these data objects) is the length */
785
786 status = acpi_ds_create_operand (walk_state, op->common.value.arg, 1);
787 if (ACPI_FAILURE (status)) {
788 return_ACPI_STATUS (status);
789 }
790
791 status = acpi_ex_resolve_operands (walk_state->opcode,
792 &(walk_state->operands [walk_state->num_operands -1]),
793 walk_state);
794 if (ACPI_FAILURE (status)) {
795 return_ACPI_STATUS (status);
796 }
797
798 /* Extract length operand */
799
800 arg_desc = walk_state->operands [walk_state->num_operands - 1];
801 length = (u32) arg_desc->integer.value;
802
803 /* Cleanup for length operand */
804
805 status = acpi_ds_obj_stack_pop (1, walk_state);
806 if (ACPI_FAILURE (status)) {
807 return_ACPI_STATUS (status);
808 }
809
810 acpi_ut_remove_reference (arg_desc);
811
812 /*
813 * Create the actual data object
814 */
815 switch (op->common.aml_opcode) {
816 case AML_BUFFER_OP:
817
818 status = acpi_ds_build_internal_buffer_obj (walk_state, op, length, &obj_desc);
819 break;
820
821 case AML_PACKAGE_OP:
822 case AML_VAR_PACKAGE_OP:
823
824 status = acpi_ds_build_internal_package_obj (walk_state, op, length, &obj_desc);
825 break;
826
827 default:
828 return_ACPI_STATUS (AE_AML_BAD_OPCODE);
829 }
830
831 if (ACPI_SUCCESS (status)) {
832 /*
833 * Return the object in the walk_state, unless the parent is a package --
834 * in this case, the return object will be stored in the parse tree
835 * for the package.
836 */
837 if ((!op->common.parent) ||
838 ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
839 (op->common.parent->common.aml_opcode != AML_VAR_PACKAGE_OP) &&
840 (op->common.parent->common.aml_opcode != AML_NAME_OP))) {
841 walk_state->result_obj = obj_desc;
842 }
843 }
844
845 return_ACPI_STATUS (status);
846}
847
848
849/*******************************************************************************
850 *
851 * FUNCTION: acpi_ds_exec_begin_control_op
852 *
853 * PARAMETERS: walk_list - The list that owns the walk stack
854 * Op - The control Op
855 *
856 * RETURN: Status
857 *
858 * DESCRIPTION: Handles all control ops encountered during control method
859 * execution.
860 *
861 ******************************************************************************/
862
863acpi_status
864acpi_ds_exec_begin_control_op (
865 struct acpi_walk_state *walk_state,
866 union acpi_parse_object *op)
867{
868 acpi_status status = AE_OK;
869 union acpi_generic_state *control_state;
870
871
872 ACPI_FUNCTION_NAME ("ds_exec_begin_control_op");
873
874
875 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
876 op->common.aml_opcode, walk_state));
877
878 switch (op->common.aml_opcode) {
879 case AML_IF_OP:
880 case AML_WHILE_OP:
881
882 /*
883 * IF/WHILE: Create a new control state to manage these
884 * constructs. We need to manage these as a stack, in order
885 * to handle nesting.
886 */
887 control_state = acpi_ut_create_control_state ();
888 if (!control_state) {
889 status = AE_NO_MEMORY;
890 break;
891 }
892 /*
893 * Save a pointer to the predicate for multiple executions
894 * of a loop
895 */
896 control_state->control.aml_predicate_start = walk_state->parser_state.aml - 1;
897 control_state->control.package_end = walk_state->parser_state.pkg_end;
898 control_state->control.opcode = op->common.aml_opcode;
899
900
901 /* Push the control state on this walk's control stack */
902
903 acpi_ut_push_generic_state (&walk_state->control_state, control_state);
904 break;
905
906 case AML_ELSE_OP:
907
908 /* Predicate is in the state object */
909 /* If predicate is true, the IF was executed, ignore ELSE part */
910
911 if (walk_state->last_predicate) {
912 status = AE_CTRL_TRUE;
913 }
914
915 break;
916
917 case AML_RETURN_OP:
918
919 break;
920
921 default:
922 break;
923 }
924
925 return (status);
926}
927
928
929/*******************************************************************************
930 *
931 * FUNCTION: acpi_ds_exec_end_control_op
932 *
933 * PARAMETERS: walk_list - The list that owns the walk stack
934 * Op - The control Op
935 *
936 * RETURN: Status
937 *
938 * DESCRIPTION: Handles all control ops encountered during control method
939 * execution.
940 *
941 ******************************************************************************/
942
943acpi_status
944acpi_ds_exec_end_control_op (
945 struct acpi_walk_state *walk_state,
946 union acpi_parse_object *op)
947{
948 acpi_status status = AE_OK;
949 union acpi_generic_state *control_state;
950
951
952 ACPI_FUNCTION_NAME ("ds_exec_end_control_op");
953
954
955 switch (op->common.aml_opcode) {
956 case AML_IF_OP:
957
958 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
959
960 /*
961 * Save the result of the predicate in case there is an
962 * ELSE to come
963 */
964 walk_state->last_predicate =
965 (u8) walk_state->control_state->common.value;
966
967 /*
968 * Pop the control state that was created at the start
969 * of the IF and free it
970 */
971 control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
972 acpi_ut_delete_generic_state (control_state);
973 break;
974
975
976 case AML_ELSE_OP:
977
978 break;
979
980
981 case AML_WHILE_OP:
982
983 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
984
985 if (walk_state->control_state->common.value) {
986 /* Predicate was true, go back and evaluate it again! */
987
988 status = AE_CTRL_PENDING;
989 }
990
991 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] termination! Op=%p\n", op));
992
993 /* Pop this control state and free it */
994
995 control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
996
997 walk_state->aml_last_while = control_state->control.aml_predicate_start;
998 acpi_ut_delete_generic_state (control_state);
999 break;
1000
1001
1002 case AML_RETURN_OP:
1003
1004 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1005 "[RETURN_OP] Op=%p Arg=%p\n",op, op->common.value.arg));
1006
1007 /*
1008 * One optional operand -- the return value
1009 * It can be either an immediate operand or a result that
1010 * has been bubbled up the tree
1011 */
1012 if (op->common.value.arg) {
1013 /* Since we have a real Return(), delete any implicit return */
1014
1015 acpi_ds_clear_implicit_return (walk_state);
1016
1017 /* Return statement has an immediate operand */
1018
1019 status = acpi_ds_create_operands (walk_state, op->common.value.arg);
1020 if (ACPI_FAILURE (status)) {
1021 return (status);
1022 }
1023
1024 /*
1025 * If value being returned is a Reference (such as
1026 * an arg or local), resolve it now because it may
1027 * cease to exist at the end of the method.
1028 */
1029 status = acpi_ex_resolve_to_value (&walk_state->operands [0], walk_state);
1030 if (ACPI_FAILURE (status)) {
1031 return (status);
1032 }
1033
1034 /*
1035 * Get the return value and save as the last result
1036 * value. This is the only place where walk_state->return_desc
1037 * is set to anything other than zero!
1038 */
1039 walk_state->return_desc = walk_state->operands[0];
1040 }
1041 else if ((walk_state->results) &&
1042 (walk_state->results->results.num_results > 0)) {
1043 /* Since we have a real Return(), delete any implicit return */
1044
1045 acpi_ds_clear_implicit_return (walk_state);
1046
1047 /*
1048 * The return value has come from a previous calculation.
1049 *
1050 * If value being returned is a Reference (such as
1051 * an arg or local), resolve it now because it may
1052 * cease to exist at the end of the method.
1053 *
1054 * Allow references created by the Index operator to return unchanged.
1055 */
1056 if ((ACPI_GET_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_DESC_TYPE_OPERAND) &&
1057 (ACPI_GET_OBJECT_TYPE (walk_state->results->results.obj_desc [0]) == ACPI_TYPE_LOCAL_REFERENCE) &&
1058 ((walk_state->results->results.obj_desc [0])->reference.opcode != AML_INDEX_OP)) {
1059 status = acpi_ex_resolve_to_value (&walk_state->results->results.obj_desc [0], walk_state);
1060 if (ACPI_FAILURE (status)) {
1061 return (status);
1062 }
1063 }
1064
1065 walk_state->return_desc = walk_state->results->results.obj_desc [0];
1066 }
1067 else {
1068 /* No return operand */
1069
1070 if (walk_state->num_operands) {
1071 acpi_ut_remove_reference (walk_state->operands [0]);
1072 }
1073
1074 walk_state->operands [0] = NULL;
1075 walk_state->num_operands = 0;
1076 walk_state->return_desc = NULL;
1077 }
1078
1079
1080 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1081 "Completed RETURN_OP State=%p, ret_val=%p\n",
1082 walk_state, walk_state->return_desc));
1083
1084 /* End the control method execution right now */
1085
1086 status = AE_CTRL_TERMINATE;
1087 break;
1088
1089
1090 case AML_NOOP_OP:
1091
1092 /* Just do nothing! */
1093 break;
1094
1095
1096 case AML_BREAK_POINT_OP:
1097
1098 /* Call up to the OS service layer to handle this */
1099
1100 status = acpi_os_signal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode");
1101
1102 /* If and when it returns, all done. */
1103
1104 break;
1105
1106
1107 case AML_BREAK_OP:
1108 case AML_CONTINUE_OP: /* ACPI 2.0 */
1109
1110
1111 /* Pop and delete control states until we find a while */
1112
1113 while (walk_state->control_state &&
1114 (walk_state->control_state->control.opcode != AML_WHILE_OP)) {
1115 control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
1116 acpi_ut_delete_generic_state (control_state);
1117 }
1118
1119 /* No while found? */
1120
1121 if (!walk_state->control_state) {
1122 return (AE_AML_NO_WHILE);
1123 }
1124
1125 /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */
1126
1127 walk_state->aml_last_while = walk_state->control_state->control.package_end;
1128
1129 /* Return status depending on opcode */
1130
1131 if (op->common.aml_opcode == AML_BREAK_OP) {
1132 status = AE_CTRL_BREAK;
1133 }
1134 else {
1135 status = AE_CTRL_CONTINUE;
1136 }
1137 break;
1138
1139
1140 default:
1141
1142 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown control opcode=%X Op=%p\n",
1143 op->common.aml_opcode, op));
1144
1145 status = AE_AML_BAD_OPCODE;
1146 break;
1147 }
1148
1149 return (status);
1150}
1151
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
new file mode 100644
index 000000000000..462c5d83e747
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -0,0 +1,744 @@
1/*******************************************************************************
2 *
3 * Module Name: dsutils - Dispatcher utilities
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/amlcode.h>
48#include <acpi/acdispat.h>
49#include <acpi/acinterp.h>
50#include <acpi/acnamesp.h>
51#include <acpi/acdebug.h>
52
53#define _COMPONENT ACPI_DISPATCHER
54 ACPI_MODULE_NAME ("dsutils")
55
56
57/*******************************************************************************
58 *
59 * FUNCTION: acpi_ds_clear_implicit_return
60 *
61 * PARAMETERS: walk_state - Current State
62 *
63 * RETURN: None.
64 *
65 * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
66 * to delete "stale" return values (if enabled, the return value
67 * from every operator is saved at least momentarily, in case the
68 * parent method exits.)
69 *
70 ******************************************************************************/
71
72void
73acpi_ds_clear_implicit_return (
74 struct acpi_walk_state *walk_state)
75{
76 ACPI_FUNCTION_NAME ("ds_clear_implicit_return");
77
78
79 /*
80 * Slack must be enabled for this feature
81 */
82 if (!acpi_gbl_enable_interpreter_slack) {
83 return;
84 }
85
86 if (walk_state->implicit_return_obj) {
87 /*
88 * Delete any "stale" implicit return. However, in
89 * complex statements, the implicit return value can be
90 * bubbled up several levels.
91 */
92 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
93 "Removing reference on stale implicit return obj %p\n",
94 walk_state->implicit_return_obj));
95
96 acpi_ut_remove_reference (walk_state->implicit_return_obj);
97 walk_state->implicit_return_obj = NULL;
98 }
99}
100
101
102#ifndef ACPI_NO_METHOD_EXECUTION
103
104/*******************************************************************************
105 *
106 * FUNCTION: acpi_ds_do_implicit_return
107 *
108 * PARAMETERS: return_desc - The return value
109 * walk_state - Current State
110 * add_reference - True if a reference should be added to the
111 * return object
112 *
113 * RETURN: TRUE if implicit return enabled, FALSE otherwise
114 *
115 * DESCRIPTION: Implements the optional "implicit return". We save the result
116 * of every ASL operator and control method invocation in case the
117 * parent method exit. Before storing a new return value, we
118 * delete the previous return value.
119 *
120 ******************************************************************************/
121
122u8
123acpi_ds_do_implicit_return (
124 union acpi_operand_object *return_desc,
125 struct acpi_walk_state *walk_state,
126 u8 add_reference)
127{
128 ACPI_FUNCTION_NAME ("ds_do_implicit_return");
129
130
131 /*
132 * Slack must be enabled for this feature, and we must
133 * have a valid return object
134 */
135 if ((!acpi_gbl_enable_interpreter_slack) ||
136 (!return_desc)) {
137 return (FALSE);
138 }
139
140 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
141 "Result %p will be implicitly returned; Prev=%p\n",
142 return_desc,
143 walk_state->implicit_return_obj));
144
145 /*
146 * Delete any "stale" implicit return value first. However, in
147 * complex statements, the implicit return value can be
148 * bubbled up several levels, so we don't clear the value if it
149 * is the same as the return_desc.
150 */
151 if (walk_state->implicit_return_obj) {
152 if (walk_state->implicit_return_obj == return_desc) {
153 return (TRUE);
154 }
155 acpi_ds_clear_implicit_return (walk_state);
156 }
157
158 /* Save the implicit return value, add a reference if requested */
159
160 walk_state->implicit_return_obj = return_desc;
161 if (add_reference) {
162 acpi_ut_add_reference (return_desc);
163 }
164
165 return (TRUE);
166}
167
168
169/*******************************************************************************
170 *
171 * FUNCTION: acpi_ds_is_result_used
172 *
173 * PARAMETERS: Op - Current Op
174 * walk_state - Current State
175 *
176 * RETURN: TRUE if result is used, FALSE otherwise
177 *
178 * DESCRIPTION: Check if a result object will be used by the parent
179 *
180 ******************************************************************************/
181
182u8
183acpi_ds_is_result_used (
184 union acpi_parse_object *op,
185 struct acpi_walk_state *walk_state)
186{
187 const struct acpi_opcode_info *parent_info;
188
189 ACPI_FUNCTION_TRACE_PTR ("ds_is_result_used", op);
190
191
192 /* Must have both an Op and a Result Object */
193
194 if (!op) {
195 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
196 return_VALUE (TRUE);
197 }
198
199 /*
200 * We know that this operator is not a
201 * Return() operator (would not come here.) The following code is the
202 * optional support for a so-called "implicit return". Some AML code
203 * assumes that the last value of the method is "implicitly" returned
204 * to the caller. Just save the last result as the return value.
205 * NOTE: this is optional because the ASL language does not actually
206 * support this behavior.
207 */
208 acpi_ds_do_implicit_return (walk_state->result_obj, walk_state, TRUE);
209
210 /*
211 * Now determine if the parent will use the result
212 *
213 * If there is no parent, or the parent is a scope_op, we are executing
214 * at the method level. An executing method typically has no parent,
215 * since each method is parsed separately. A method invoked externally
216 * via execute_control_method has a scope_op as the parent.
217 */
218 if ((!op->common.parent) ||
219 (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
220 /* No parent, the return value cannot possibly be used */
221
222 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "At Method level, result of [%s] not used\n",
223 acpi_ps_get_opcode_name (op->common.aml_opcode)));
224 return_VALUE (FALSE);
225 }
226
227 /* Get info on the parent. The root_op is AML_SCOPE */
228
229 parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
230 if (parent_info->class == AML_CLASS_UNKNOWN) {
231 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown parent opcode. Op=%p\n", op));
232 return_VALUE (FALSE);
233 }
234
235 /*
236 * Decide what to do with the result based on the parent. If
237 * the parent opcode will not use the result, delete the object.
238 * Otherwise leave it as is, it will be deleted when it is used
239 * as an operand later.
240 */
241 switch (parent_info->class) {
242 case AML_CLASS_CONTROL:
243
244 switch (op->common.parent->common.aml_opcode) {
245 case AML_RETURN_OP:
246
247 /* Never delete the return value associated with a return opcode */
248
249 goto result_used;
250
251 case AML_IF_OP:
252 case AML_WHILE_OP:
253
254 /*
255 * If we are executing the predicate AND this is the predicate op,
256 * we will use the return value
257 */
258 if ((walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING) &&
259 (walk_state->control_state->control.predicate_op == op)) {
260 goto result_used;
261 }
262 break;
263
264 default:
265 /* Ignore other control opcodes */
266 break;
267 }
268
269 /* The general control opcode returns no result */
270
271 goto result_not_used;
272
273
274 case AML_CLASS_CREATE:
275
276 /*
277 * These opcodes allow term_arg(s) as operands and therefore
278 * the operands can be method calls. The result is used.
279 */
280 goto result_used;
281
282
283 case AML_CLASS_NAMED_OBJECT:
284
285 if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
286 (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) ||
287 (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
288 (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) ||
289 (op->common.parent->common.aml_opcode == AML_BUFFER_OP) ||
290 (op->common.parent->common.aml_opcode == AML_INT_EVAL_SUBTREE_OP)) {
291 /*
292 * These opcodes allow term_arg(s) as operands and therefore
293 * the operands can be method calls. The result is used.
294 */
295 goto result_used;
296 }
297
298 goto result_not_used;
299
300
301 default:
302
303 /*
304 * In all other cases. the parent will actually use the return
305 * object, so keep it.
306 */
307 goto result_used;
308 }
309
310
311result_used:
312 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] used by Parent [%s] Op=%p\n",
313 acpi_ps_get_opcode_name (op->common.aml_opcode),
314 acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
315
316 return_VALUE (TRUE);
317
318
319result_not_used:
320 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] not used by Parent [%s] Op=%p\n",
321 acpi_ps_get_opcode_name (op->common.aml_opcode),
322 acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
323
324 return_VALUE (FALSE);
325}
326
327
328/*******************************************************************************
329 *
330 * FUNCTION: acpi_ds_delete_result_if_not_used
331 *
332 * PARAMETERS: Op - Current parse Op
333 * result_obj - Result of the operation
334 * walk_state - Current state
335 *
336 * RETURN: Status
337 *
338 * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
339 * result descriptor, check if the parent opcode will actually use
340 * this result. If not, delete the result now so that it will
341 * not become orphaned.
342 *
343 ******************************************************************************/
344
345void
346acpi_ds_delete_result_if_not_used (
347 union acpi_parse_object *op,
348 union acpi_operand_object *result_obj,
349 struct acpi_walk_state *walk_state)
350{
351 union acpi_operand_object *obj_desc;
352 acpi_status status;
353
354
355 ACPI_FUNCTION_TRACE_PTR ("ds_delete_result_if_not_used", result_obj);
356
357
358 if (!op) {
359 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
360 return_VOID;
361 }
362
363 if (!result_obj) {
364 return_VOID;
365 }
366
367 if (!acpi_ds_is_result_used (op, walk_state)) {
368 /* Must pop the result stack (obj_desc should be equal to result_obj) */
369
370 status = acpi_ds_result_pop (&obj_desc, walk_state);
371 if (ACPI_SUCCESS (status)) {
372 acpi_ut_remove_reference (result_obj);
373 }
374 }
375
376 return_VOID;
377}
378
379
380/*******************************************************************************
381 *
382 * FUNCTION: acpi_ds_resolve_operands
383 *
384 * PARAMETERS: walk_state - Current walk state with operands on stack
385 *
386 * RETURN: Status
387 *
388 * DESCRIPTION: Resolve all operands to their values. Used to prepare
389 * arguments to a control method invocation (a call from one
390 * method to another.)
391 *
392 ******************************************************************************/
393
394acpi_status
395acpi_ds_resolve_operands (
396 struct acpi_walk_state *walk_state)
397{
398 u32 i;
399 acpi_status status = AE_OK;
400
401
402 ACPI_FUNCTION_TRACE_PTR ("ds_resolve_operands", walk_state);
403
404
405 /*
406 * Attempt to resolve each of the valid operands
407 * Method arguments are passed by reference, not by value. This means
408 * that the actual objects are passed, not copies of the objects.
409 */
410 for (i = 0; i < walk_state->num_operands; i++) {
411 status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state);
412 if (ACPI_FAILURE (status)) {
413 break;
414 }
415 }
416
417 return_ACPI_STATUS (status);
418}
419
420
421/*******************************************************************************
422 *
423 * FUNCTION: acpi_ds_clear_operands
424 *
425 * PARAMETERS: walk_state - Current walk state with operands on stack
426 *
427 * RETURN: None
428 *
429 * DESCRIPTION: Clear all operands on the current walk state operand stack.
430 *
431 ******************************************************************************/
432
433void
434acpi_ds_clear_operands (
435 struct acpi_walk_state *walk_state)
436{
437 u32 i;
438
439
440 ACPI_FUNCTION_TRACE_PTR ("ds_clear_operands", walk_state);
441
442
443 /* Remove a reference on each operand on the stack */
444
445 for (i = 0; i < walk_state->num_operands; i++) {
446 /*
447 * Remove a reference to all operands, including both
448 * "Arguments" and "Targets".
449 */
450 acpi_ut_remove_reference (walk_state->operands[i]);
451 walk_state->operands[i] = NULL;
452 }
453
454 walk_state->num_operands = 0;
455 return_VOID;
456}
457#endif
458
459
460/*******************************************************************************
461 *
462 * FUNCTION: acpi_ds_create_operand
463 *
464 * PARAMETERS: walk_state - Current walk state
465 * Arg - Parse object for the argument
466 * arg_index - Which argument (zero based)
467 *
468 * RETURN: Status
469 *
470 * DESCRIPTION: Translate a parse tree object that is an argument to an AML
471 * opcode to the equivalent interpreter object. This may include
472 * looking up a name or entering a new name into the internal
473 * namespace.
474 *
475 ******************************************************************************/
476
477acpi_status
478acpi_ds_create_operand (
479 struct acpi_walk_state *walk_state,
480 union acpi_parse_object *arg,
481 u32 arg_index)
482{
483 acpi_status status = AE_OK;
484 char *name_string;
485 u32 name_length;
486 union acpi_operand_object *obj_desc;
487 union acpi_parse_object *parent_op;
488 u16 opcode;
489 acpi_interpreter_mode interpreter_mode;
490 const struct acpi_opcode_info *op_info;
491
492
493 ACPI_FUNCTION_TRACE_PTR ("ds_create_operand", arg);
494
495
496 /* A valid name must be looked up in the namespace */
497
498 if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
499 (arg->common.value.string)) {
500 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", arg));
501
502 /* Get the entire name string from the AML stream */
503
504 status = acpi_ex_get_name_string (ACPI_TYPE_ANY, arg->common.value.buffer,
505 &name_string, &name_length);
506
507 if (ACPI_FAILURE (status)) {
508 return_ACPI_STATUS (status);
509 }
510
511 /* All prefixes have been handled, and the name is in name_string */
512
513 /*
514 * Special handling for buffer_field declarations. This is a deferred
515 * opcode that unfortunately defines the field name as the last
516 * parameter instead of the first. We get here when we are performing
517 * the deferred execution, so the actual name of the field is already
518 * in the namespace. We don't want to attempt to look it up again
519 * because we may be executing in a different scope than where the
520 * actual opcode exists.
521 */
522 if ((walk_state->deferred_node) &&
523 (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) &&
524 (arg_index != 0)) {
525 obj_desc = ACPI_CAST_PTR (union acpi_operand_object, walk_state->deferred_node);
526 status = AE_OK;
527 }
528 else /* All other opcodes */ {
529 /*
530 * Differentiate between a namespace "create" operation
531 * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
532 * IMODE_EXECUTE) in order to support the creation of
533 * namespace objects during the execution of control methods.
534 */
535 parent_op = arg->common.parent;
536 op_info = acpi_ps_get_opcode_info (parent_op->common.aml_opcode);
537 if ((op_info->flags & AML_NSNODE) &&
538 (parent_op->common.aml_opcode != AML_INT_METHODCALL_OP) &&
539 (parent_op->common.aml_opcode != AML_REGION_OP) &&
540 (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) {
541 /* Enter name into namespace if not found */
542
543 interpreter_mode = ACPI_IMODE_LOAD_PASS2;
544 }
545 else {
546 /* Return a failure if name not found */
547
548 interpreter_mode = ACPI_IMODE_EXECUTE;
549 }
550
551 status = acpi_ns_lookup (walk_state->scope_info, name_string,
552 ACPI_TYPE_ANY, interpreter_mode,
553 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
554 walk_state,
555 ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &obj_desc));
556 /*
557 * The only case where we pass through (ignore) a NOT_FOUND
558 * error is for the cond_ref_of opcode.
559 */
560 if (status == AE_NOT_FOUND) {
561 if (parent_op->common.aml_opcode == AML_COND_REF_OF_OP) {
562 /*
563 * For the Conditional Reference op, it's OK if
564 * the name is not found; We just need a way to
565 * indicate this to the interpreter, set the
566 * object to the root
567 */
568 obj_desc = ACPI_CAST_PTR (union acpi_operand_object, acpi_gbl_root_node);
569 status = AE_OK;
570 }
571 else {
572 /*
573 * We just plain didn't find it -- which is a
574 * very serious error at this point
575 */
576 status = AE_AML_NAME_NOT_FOUND;
577 }
578 }
579
580 if (ACPI_FAILURE (status)) {
581 ACPI_REPORT_NSERROR (name_string, status);
582 }
583 }
584
585 /* Free the namestring created above */
586
587 ACPI_MEM_FREE (name_string);
588
589 /* Check status from the lookup */
590
591 if (ACPI_FAILURE (status)) {
592 return_ACPI_STATUS (status);
593 }
594
595 /* Put the resulting object onto the current object stack */
596
597 status = acpi_ds_obj_stack_push (obj_desc, walk_state);
598 if (ACPI_FAILURE (status)) {
599 return_ACPI_STATUS (status);
600 }
601 ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
602 }
603 else {
604 /* Check for null name case */
605
606 if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) {
607 /*
608 * If the name is null, this means that this is an
609 * optional result parameter that was not specified
610 * in the original ASL. Create a Zero Constant for a
611 * placeholder. (Store to a constant is a Noop.)
612 */
613 opcode = AML_ZERO_OP; /* Has no arguments! */
614
615 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Null namepath: Arg=%p\n", arg));
616 }
617 else {
618 opcode = arg->common.aml_opcode;
619 }
620
621 /* Get the object type of the argument */
622
623 op_info = acpi_ps_get_opcode_info (opcode);
624 if (op_info->object_type == ACPI_TYPE_INVALID) {
625 return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
626 }
627
628 if (op_info->flags & AML_HAS_RETVAL) {
629 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
630 "Argument previously created, already stacked \n"));
631
632 ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (
633 walk_state->operands [walk_state->num_operands - 1], walk_state));
634
635 /*
636 * Use value that was already previously returned
637 * by the evaluation of this argument
638 */
639 status = acpi_ds_result_pop_from_bottom (&obj_desc, walk_state);
640 if (ACPI_FAILURE (status)) {
641 /*
642 * Only error is underflow, and this indicates
643 * a missing or null operand!
644 */
645 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Missing or null operand, %s\n",
646 acpi_format_exception (status)));
647 return_ACPI_STATUS (status);
648 }
649 }
650 else {
651 /* Create an ACPI_INTERNAL_OBJECT for the argument */
652
653 obj_desc = acpi_ut_create_internal_object (op_info->object_type);
654 if (!obj_desc) {
655 return_ACPI_STATUS (AE_NO_MEMORY);
656 }
657
658 /* Initialize the new object */
659
660 status = acpi_ds_init_object_from_op (walk_state, arg,
661 opcode, &obj_desc);
662 if (ACPI_FAILURE (status)) {
663 acpi_ut_delete_object_desc (obj_desc);
664 return_ACPI_STATUS (status);
665 }
666 }
667
668 /* Put the operand object on the object stack */
669
670 status = acpi_ds_obj_stack_push (obj_desc, walk_state);
671 if (ACPI_FAILURE (status)) {
672 return_ACPI_STATUS (status);
673 }
674
675 ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
676 }
677
678 return_ACPI_STATUS (AE_OK);
679}
680
681
682/*******************************************************************************
683 *
684 * FUNCTION: acpi_ds_create_operands
685 *
686 * PARAMETERS: walk_state - Current state
687 * first_arg - First argument of a parser argument tree
688 *
689 * RETURN: Status
690 *
691 * DESCRIPTION: Convert an operator's arguments from a parse tree format to
692 * namespace objects and place those argument object on the object
693 * stack in preparation for evaluation by the interpreter.
694 *
695 ******************************************************************************/
696
697acpi_status
698acpi_ds_create_operands (
699 struct acpi_walk_state *walk_state,
700 union acpi_parse_object *first_arg)
701{
702 acpi_status status = AE_OK;
703 union acpi_parse_object *arg;
704 u32 arg_count = 0;
705
706
707 ACPI_FUNCTION_TRACE_PTR ("ds_create_operands", first_arg);
708
709
710 /* For all arguments in the list... */
711
712 arg = first_arg;
713 while (arg) {
714 status = acpi_ds_create_operand (walk_state, arg, arg_count);
715 if (ACPI_FAILURE (status)) {
716 goto cleanup;
717 }
718
719 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%d (%p) done, Arg1=%p\n",
720 arg_count, arg, first_arg));
721
722 /* Move on to next argument, if any */
723
724 arg = arg->common.next;
725 arg_count++;
726 }
727
728 return_ACPI_STATUS (status);
729
730
731cleanup:
732 /*
733 * We must undo everything done above; meaning that we must
734 * pop everything off of the operand stack and delete those
735 * objects
736 */
737 (void) acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state);
738
739 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While creating Arg %d - %s\n",
740 (arg_count + 1), acpi_format_exception (status)));
741 return_ACPI_STATUS (status);
742}
743
744
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
new file mode 100644
index 000000000000..2071a0d2bbbb
--- /dev/null
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -0,0 +1,751 @@
1/******************************************************************************
2 *
3 * Module Name: dswexec - Dispatcher method execution callbacks;
4 * dispatch to interpreter.
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acparser.h>
48#include <acpi/amlcode.h>
49#include <acpi/acdispat.h>
50#include <acpi/acinterp.h>
51#include <acpi/acnamesp.h>
52#include <acpi/acdebug.h>
53#include <acpi/acdisasm.h>
54
55
56#define _COMPONENT ACPI_DISPATCHER
57 ACPI_MODULE_NAME ("dswexec")
58
59/*
60 * Dispatch table for opcode classes
61 */
62static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch [] = {
63 acpi_ex_opcode_0A_0T_1R,
64 acpi_ex_opcode_1A_0T_0R,
65 acpi_ex_opcode_1A_0T_1R,
66 acpi_ex_opcode_1A_1T_0R,
67 acpi_ex_opcode_1A_1T_1R,
68 acpi_ex_opcode_2A_0T_0R,
69 acpi_ex_opcode_2A_0T_1R,
70 acpi_ex_opcode_2A_1T_1R,
71 acpi_ex_opcode_2A_2T_1R,
72 acpi_ex_opcode_3A_0T_0R,
73 acpi_ex_opcode_3A_1T_1R,
74 acpi_ex_opcode_6A_0T_1R};
75
76/*****************************************************************************
77 *
78 * FUNCTION: acpi_ds_get_predicate_value
79 *
80 * PARAMETERS: walk_state - Current state of the parse tree walk
81 *
82 * RETURN: Status
83 *
84 * DESCRIPTION: Get the result of a predicate evaluation
85 *
86 ****************************************************************************/
87
88acpi_status
89acpi_ds_get_predicate_value (
90 struct acpi_walk_state *walk_state,
91 union acpi_operand_object *result_obj) {
92 acpi_status status = AE_OK;
93 union acpi_operand_object *obj_desc;
94 union acpi_operand_object *local_obj_desc = NULL;
95
96
97 ACPI_FUNCTION_TRACE_PTR ("ds_get_predicate_value", walk_state);
98
99
100 walk_state->control_state->common.state = 0;
101
102 if (result_obj) {
103 status = acpi_ds_result_pop (&obj_desc, walk_state);
104 if (ACPI_FAILURE (status)) {
105 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
106 "Could not get result from predicate evaluation, %s\n",
107 acpi_format_exception (status)));
108
109 return_ACPI_STATUS (status);
110 }
111 }
112 else {
113 status = acpi_ds_create_operand (walk_state, walk_state->op, 0);
114 if (ACPI_FAILURE (status)) {
115 return_ACPI_STATUS (status);
116 }
117
118 status = acpi_ex_resolve_to_value (&walk_state->operands [0], walk_state);
119 if (ACPI_FAILURE (status)) {
120 return_ACPI_STATUS (status);
121 }
122
123 obj_desc = walk_state->operands [0];
124 }
125
126 if (!obj_desc) {
127 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No predicate obj_desc=%p State=%p\n",
128 obj_desc, walk_state));
129
130 return_ACPI_STATUS (AE_AML_NO_OPERAND);
131 }
132
133 /*
134 * Result of predicate evaluation must be an Integer
135 * object. Implicitly convert the argument if necessary.
136 */
137 status = acpi_ex_convert_to_integer (obj_desc, &local_obj_desc, 16);
138 if (ACPI_FAILURE (status)) {
139 goto cleanup;
140 }
141
142 if (ACPI_GET_OBJECT_TYPE (local_obj_desc) != ACPI_TYPE_INTEGER) {
143 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
144 "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n",
145 obj_desc, walk_state, ACPI_GET_OBJECT_TYPE (obj_desc)));
146
147 status = AE_AML_OPERAND_TYPE;
148 goto cleanup;
149 }
150
151 /* Truncate the predicate to 32-bits if necessary */
152
153 acpi_ex_truncate_for32bit_table (local_obj_desc);
154
155 /*
156 * Save the result of the predicate evaluation on
157 * the control stack
158 */
159 if (local_obj_desc->integer.value) {
160 walk_state->control_state->common.value = TRUE;
161 }
162 else {
163 /*
164 * Predicate is FALSE, we will just toss the
165 * rest of the package
166 */
167 walk_state->control_state->common.value = FALSE;
168 status = AE_CTRL_FALSE;
169 }
170
171
172cleanup:
173
174 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
175 walk_state->control_state->common.value, walk_state->op));
176
177 /* Break to debugger to display result */
178
179 ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (local_obj_desc, walk_state));
180
181 /*
182 * Delete the predicate result object (we know that
183 * we don't need it anymore)
184 */
185 if (local_obj_desc != obj_desc) {
186 acpi_ut_remove_reference (local_obj_desc);
187 }
188 acpi_ut_remove_reference (obj_desc);
189
190 walk_state->control_state->common.state = ACPI_CONTROL_NORMAL;
191 return_ACPI_STATUS (status);
192}
193
194
195/*****************************************************************************
196 *
197 * FUNCTION: acpi_ds_exec_begin_op
198 *
199 * PARAMETERS: walk_state - Current state of the parse tree walk
200 * out_op - Return op if a new one is created
201 *
202 * RETURN: Status
203 *
204 * DESCRIPTION: Descending callback used during the execution of control
205 * methods. This is where most operators and operands are
206 * dispatched to the interpreter.
207 *
208 ****************************************************************************/
209
210acpi_status
211acpi_ds_exec_begin_op (
212 struct acpi_walk_state *walk_state,
213 union acpi_parse_object **out_op)
214{
215 union acpi_parse_object *op;
216 acpi_status status = AE_OK;
217 u32 opcode_class;
218
219
220 ACPI_FUNCTION_TRACE_PTR ("ds_exec_begin_op", walk_state);
221
222
223 op = walk_state->op;
224 if (!op) {
225 status = acpi_ds_load2_begin_op (walk_state, out_op);
226 if (ACPI_FAILURE (status)) {
227 return_ACPI_STATUS (status);
228 }
229
230 op = *out_op;
231 walk_state->op = op;
232 walk_state->opcode = op->common.aml_opcode;
233 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
234
235 if (acpi_ns_opens_scope (walk_state->op_info->object_type)) {
236 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n",
237 acpi_ut_get_type_name (walk_state->op_info->object_type), op));
238
239 status = acpi_ds_scope_stack_pop (walk_state);
240 if (ACPI_FAILURE (status)) {
241 return_ACPI_STATUS (status);
242 }
243 }
244 }
245
246 if (op == walk_state->origin) {
247 if (out_op) {
248 *out_op = op;
249 }
250
251 return_ACPI_STATUS (AE_OK);
252 }
253
254 /*
255 * If the previous opcode was a conditional, this opcode
256 * must be the beginning of the associated predicate.
257 * Save this knowledge in the current scope descriptor
258 */
259 if ((walk_state->control_state) &&
260 (walk_state->control_state->common.state ==
261 ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
262 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Exec predicate Op=%p State=%p\n",
263 op, walk_state));
264
265 walk_state->control_state->common.state = ACPI_CONTROL_PREDICATE_EXECUTING;
266
267 /* Save start of predicate */
268
269 walk_state->control_state->control.predicate_op = op;
270 }
271
272
273 opcode_class = walk_state->op_info->class;
274
275 /* We want to send namepaths to the load code */
276
277 if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
278 opcode_class = AML_CLASS_NAMED_OBJECT;
279 }
280
281 /*
282 * Handle the opcode based upon the opcode type
283 */
284 switch (opcode_class) {
285 case AML_CLASS_CONTROL:
286
287 status = acpi_ds_result_stack_push (walk_state);
288 if (ACPI_FAILURE (status)) {
289 return_ACPI_STATUS (status);
290 }
291
292 status = acpi_ds_exec_begin_control_op (walk_state, op);
293 break;
294
295
296 case AML_CLASS_NAMED_OBJECT:
297
298 if (walk_state->walk_type == ACPI_WALK_METHOD) {
299 /*
300 * Found a named object declaration during method
301 * execution; we must enter this object into the
302 * namespace. The created object is temporary and
303 * will be deleted upon completion of the execution
304 * of this method.
305 */
306 status = acpi_ds_load2_begin_op (walk_state, NULL);
307 }
308
309 if (op->common.aml_opcode == AML_REGION_OP) {
310 status = acpi_ds_result_stack_push (walk_state);
311 }
312 break;
313
314
315 case AML_CLASS_EXECUTE:
316 case AML_CLASS_CREATE:
317
318 /*
319 * Most operators with arguments.
320 * Start a new result/operand state
321 */
322 status = acpi_ds_result_stack_push (walk_state);
323 break;
324
325
326 default:
327 break;
328 }
329
330 /* Nothing to do here during method execution */
331
332 return_ACPI_STATUS (status);
333}
334
335
336/*****************************************************************************
337 *
338 * FUNCTION: acpi_ds_exec_end_op
339 *
340 * PARAMETERS: walk_state - Current state of the parse tree walk
341 * Op - Op that has been just been completed in the
342 * walk; Arguments have now been evaluated.
343 *
344 * RETURN: Status
345 *
346 * DESCRIPTION: Ascending callback used during the execution of control
347 * methods. The only thing we really need to do here is to
348 * notice the beginning of IF, ELSE, and WHILE blocks.
349 *
350 ****************************************************************************/
351
352acpi_status
353acpi_ds_exec_end_op (
354 struct acpi_walk_state *walk_state)
355{
356 union acpi_parse_object *op;
357 acpi_status status = AE_OK;
358 u32 op_type;
359 u32 op_class;
360 union acpi_parse_object *next_op;
361 union acpi_parse_object *first_arg;
362
363
364 ACPI_FUNCTION_TRACE_PTR ("ds_exec_end_op", walk_state);
365
366
367 op = walk_state->op;
368 op_type = walk_state->op_info->type;
369 op_class = walk_state->op_info->class;
370
371 if (op_class == AML_CLASS_UNKNOWN) {
372 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode %X\n", op->common.aml_opcode));
373 return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
374 }
375
376 first_arg = op->common.value.arg;
377
378 /* Init the walk state */
379
380 walk_state->num_operands = 0;
381 walk_state->return_desc = NULL;
382 walk_state->result_obj = NULL;
383
384 /* Call debugger for single step support (DEBUG build only) */
385
386 ACPI_DEBUGGER_EXEC (status = acpi_db_single_step (walk_state, op, op_class));
387 ACPI_DEBUGGER_EXEC (if (ACPI_FAILURE (status)) {return_ACPI_STATUS (status);});
388
389 /* Decode the Opcode Class */
390
391 switch (op_class) {
392 case AML_CLASS_ARGUMENT: /* constants, literals, etc. -- do nothing */
393 break;
394
395
396 case AML_CLASS_EXECUTE: /* most operators with arguments */
397
398 /* Build resolved operand stack */
399
400 status = acpi_ds_create_operands (walk_state, first_arg);
401 if (ACPI_FAILURE (status)) {
402 goto cleanup;
403 }
404
405 /* Done with this result state (Now that operand stack is built) */
406
407 status = acpi_ds_result_stack_pop (walk_state);
408 if (ACPI_FAILURE (status)) {
409 goto cleanup;
410 }
411
412 /*
413 * All opcodes require operand resolution, with the only exceptions
414 * being the object_type and size_of operators.
415 */
416 if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) {
417 /* Resolve all operands */
418
419 status = acpi_ex_resolve_operands (walk_state->opcode,
420 &(walk_state->operands [walk_state->num_operands -1]),
421 walk_state);
422 if (ACPI_SUCCESS (status)) {
423 ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
424 acpi_ps_get_opcode_name (walk_state->opcode),
425 walk_state->num_operands, "after ex_resolve_operands");
426 }
427 }
428
429 if (ACPI_SUCCESS (status)) {
430 /*
431 * Dispatch the request to the appropriate interpreter handler
432 * routine. There is one routine per opcode "type" based upon the
433 * number of opcode arguments and return type.
434 */
435 status = acpi_gbl_op_type_dispatch[op_type] (walk_state);
436 }
437 else {
438 /*
439 * Treat constructs of the form "Store(local_x,local_x)" as noops when the
440 * Local is uninitialized.
441 */
442 if ((status == AE_AML_UNINITIALIZED_LOCAL) &&
443 (walk_state->opcode == AML_STORE_OP) &&
444 (walk_state->operands[0]->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
445 (walk_state->operands[1]->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
446 (walk_state->operands[0]->reference.opcode ==
447 walk_state->operands[1]->reference.opcode) &&
448 (walk_state->operands[0]->reference.offset ==
449 walk_state->operands[1]->reference.offset)) {
450 status = AE_OK;
451 }
452 else {
453 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
454 "[%s]: Could not resolve operands, %s\n",
455 acpi_ps_get_opcode_name (walk_state->opcode),
456 acpi_format_exception (status)));
457 }
458 }
459
460 /* Always delete the argument objects and clear the operand stack */
461
462 acpi_ds_clear_operands (walk_state);
463
464 /*
465 * If a result object was returned from above, push it on the
466 * current result stack
467 */
468 if (ACPI_SUCCESS (status) &&
469 walk_state->result_obj) {
470 status = acpi_ds_result_push (walk_state->result_obj, walk_state);
471 }
472
473 break;
474
475
476 default:
477
478 switch (op_type) {
479 case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
480
481 /* 1 Operand, 0 external_result, 0 internal_result */
482
483 status = acpi_ds_exec_end_control_op (walk_state, op);
484
485 /* Make sure to properly pop the result stack */
486
487 if (ACPI_SUCCESS (status)) {
488 status = acpi_ds_result_stack_pop (walk_state);
489 }
490 else if (status == AE_CTRL_PENDING) {
491 status = acpi_ds_result_stack_pop (walk_state);
492 if (ACPI_SUCCESS (status)) {
493 status = AE_CTRL_PENDING;
494 }
495 }
496 break;
497
498
499 case AML_TYPE_METHOD_CALL:
500
501 /*
502 * If the method is referenced from within a package
503 * declaration, it is not a invocation of the method, just
504 * a reference to it.
505 */
506 if ((op->asl.parent) &&
507 ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) ||
508 (op->asl.parent->asl.aml_opcode == AML_VAR_PACKAGE_OP))) {
509 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method Reference in a Package, Op=%p\n", op));
510 op->common.node = (struct acpi_namespace_node *) op->asl.value.arg->asl.node->object;
511 acpi_ut_add_reference (op->asl.value.arg->asl.node->object);
512 return_ACPI_STATUS (AE_OK);
513 }
514
515 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", op));
516
517 /*
518 * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
519 * the method Node pointer
520 */
521 /* next_op points to the op that holds the method name */
522
523 next_op = first_arg;
524
525 /* next_op points to first argument op */
526
527 next_op = next_op->common.next;
528
529 /*
530 * Get the method's arguments and put them on the operand stack
531 */
532 status = acpi_ds_create_operands (walk_state, next_op);
533 if (ACPI_FAILURE (status)) {
534 break;
535 }
536
537 /*
538 * Since the operands will be passed to another control method,
539 * we must resolve all local references here (Local variables,
540 * arguments to *this* method, etc.)
541 */
542 status = acpi_ds_resolve_operands (walk_state);
543 if (ACPI_FAILURE (status)) {
544 /* On error, clear all resolved operands */
545
546 acpi_ds_clear_operands (walk_state);
547 break;
548 }
549
550 /*
551 * Tell the walk loop to preempt this running method and
552 * execute the new method
553 */
554 status = AE_CTRL_TRANSFER;
555
556 /*
557 * Return now; we don't want to disturb anything,
558 * especially the operand count!
559 */
560 return_ACPI_STATUS (status);
561
562
563 case AML_TYPE_CREATE_FIELD:
564
565 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
566 "Executing create_field Buffer/Index Op=%p\n", op));
567
568 status = acpi_ds_load2_end_op (walk_state);
569 if (ACPI_FAILURE (status)) {
570 break;
571 }
572
573 status = acpi_ds_eval_buffer_field_operands (walk_state, op);
574 break;
575
576
577 case AML_TYPE_CREATE_OBJECT:
578
579 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
580 "Executing create_object (Buffer/Package) Op=%p\n", op));
581
582 switch (op->common.parent->common.aml_opcode) {
583 case AML_NAME_OP:
584
585 /*
586 * Put the Node on the object stack (Contains the ACPI Name of
587 * this object)
588 */
589 walk_state->operands[0] = (void *) op->common.parent->common.node;
590 walk_state->num_operands = 1;
591
592 status = acpi_ds_create_node (walk_state, op->common.parent->common.node, op->common.parent);
593 if (ACPI_FAILURE (status)) {
594 break;
595 }
596
597 /* Fall through */
598 /*lint -fallthrough */
599
600 case AML_INT_EVAL_SUBTREE_OP:
601
602 status = acpi_ds_eval_data_object_operands (walk_state, op,
603 acpi_ns_get_attached_object (op->common.parent->common.node));
604 break;
605
606 default:
607
608 status = acpi_ds_eval_data_object_operands (walk_state, op, NULL);
609 break;
610 }
611
612 /* Done with this result state (Now that operand stack is built) */
613
614 status = acpi_ds_result_stack_pop (walk_state);
615 if (ACPI_FAILURE (status)) {
616 goto cleanup;
617 }
618
619 /*
620 * If a result object was returned from above, push it on the
621 * current result stack
622 */
623 if (ACPI_SUCCESS (status) &&
624 walk_state->result_obj) {
625 status = acpi_ds_result_push (walk_state->result_obj, walk_state);
626 }
627 break;
628
629
630 case AML_TYPE_NAMED_FIELD:
631 case AML_TYPE_NAMED_COMPLEX:
632 case AML_TYPE_NAMED_SIMPLE:
633 case AML_TYPE_NAMED_NO_OBJ:
634
635 status = acpi_ds_load2_end_op (walk_state);
636 if (ACPI_FAILURE (status)) {
637 break;
638 }
639
640 if (op->common.aml_opcode == AML_REGION_OP) {
641 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
642 "Executing op_region Address/Length Op=%p\n", op));
643
644 status = acpi_ds_eval_region_operands (walk_state, op);
645 if (ACPI_FAILURE (status)) {
646 break;
647 }
648
649 status = acpi_ds_result_stack_pop (walk_state);
650 }
651
652 break;
653
654
655 case AML_TYPE_UNDEFINED:
656
657 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Undefined opcode type Op=%p\n", op));
658 return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
659
660
661 case AML_TYPE_BOGUS:
662
663 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
664 "Internal opcode=%X type Op=%p\n",
665 walk_state->opcode, op));
666 break;
667
668
669 default:
670
671 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
672 "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p\n",
673 op_class, op_type, op->common.aml_opcode, op));
674
675 status = AE_NOT_IMPLEMENTED;
676 break;
677 }
678 }
679
680 /*
681 * ACPI 2.0 support for 64-bit integers: Truncate numeric
682 * result value if we are executing from a 32-bit ACPI table
683 */
684 acpi_ex_truncate_for32bit_table (walk_state->result_obj);
685
686 /*
687 * Check if we just completed the evaluation of a
688 * conditional predicate
689 */
690
691 if ((ACPI_SUCCESS (status)) &&
692 (walk_state->control_state) &&
693 (walk_state->control_state->common.state ==
694 ACPI_CONTROL_PREDICATE_EXECUTING) &&
695 (walk_state->control_state->control.predicate_op == op)) {
696 status = acpi_ds_get_predicate_value (walk_state, walk_state->result_obj);
697 walk_state->result_obj = NULL;
698 }
699
700
701cleanup:
702
703 /* Invoke exception handler on error */
704
705 if (ACPI_FAILURE (status) &&
706 acpi_gbl_exception_handler &&
707 !(status & AE_CODE_CONTROL)) {
708 acpi_ex_exit_interpreter ();
709 status = acpi_gbl_exception_handler (status,
710 walk_state->method_node->name.integer, walk_state->opcode,
711 walk_state->aml_offset, NULL);
712 acpi_ex_enter_interpreter ();
713 }
714
715 if (walk_state->result_obj) {
716 /* Break to debugger to display result */
717
718 ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (walk_state->result_obj, walk_state));
719
720 /*
721 * Delete the result op if and only if:
722 * Parent will not use the result -- such as any
723 * non-nested type2 op in a method (parent will be method)
724 */
725 acpi_ds_delete_result_if_not_used (op, walk_state->result_obj, walk_state);
726 }
727
728#ifdef _UNDER_DEVELOPMENT
729
730 if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) {
731 acpi_db_method_end (walk_state);
732 }
733#endif
734
735 /* Always clear the object stack */
736
737 walk_state->num_operands = 0;
738
739#ifdef ACPI_DISASSEMBLER
740
741 /* On error, display method locals/args */
742
743 if (ACPI_FAILURE (status)) {
744 acpi_dm_dump_method_info (status, walk_state, op);
745 }
746#endif
747
748 return_ACPI_STATUS (status);
749}
750
751
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
new file mode 100644
index 000000000000..06d758679588
--- /dev/null
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -0,0 +1,976 @@
1/******************************************************************************
2 *
3 * Module Name: dswload - Dispatcher namespace load callbacks
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/amlcode.h>
48#include <acpi/acdispat.h>
49#include <acpi/acinterp.h>
50#include <acpi/acnamesp.h>
51#include <acpi/acevents.h>
52
53#ifdef _ACPI_ASL_COMPILER
54#include <acpi/acdisasm.h>
55#endif
56
57#define _COMPONENT ACPI_DISPATCHER
58 ACPI_MODULE_NAME ("dswload")
59
60
61/*******************************************************************************
62 *
63 * FUNCTION: acpi_ds_init_callbacks
64 *
65 * PARAMETERS: walk_state - Current state of the parse tree walk
66 * pass_number - 1, 2, or 3
67 *
68 * RETURN: Status
69 *
70 * DESCRIPTION: Init walk state callbacks
71 *
72 ******************************************************************************/
73
74acpi_status
75acpi_ds_init_callbacks (
76 struct acpi_walk_state *walk_state,
77 u32 pass_number)
78{
79
80 switch (pass_number) {
81 case 1:
82 walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE;
83 walk_state->descending_callback = acpi_ds_load1_begin_op;
84 walk_state->ascending_callback = acpi_ds_load1_end_op;
85 break;
86
87 case 2:
88 walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE;
89 walk_state->descending_callback = acpi_ds_load2_begin_op;
90 walk_state->ascending_callback = acpi_ds_load2_end_op;
91 break;
92
93 case 3:
94#ifndef ACPI_NO_METHOD_EXECUTION
95 walk_state->parse_flags |= ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE;
96 walk_state->descending_callback = acpi_ds_exec_begin_op;
97 walk_state->ascending_callback = acpi_ds_exec_end_op;
98#endif
99 break;
100
101 default:
102 return (AE_BAD_PARAMETER);
103 }
104
105 return (AE_OK);
106}
107
108
109/*******************************************************************************
110 *
111 * FUNCTION: acpi_ds_load1_begin_op
112 *
113 * PARAMETERS: walk_state - Current state of the parse tree walk
114 * Op - Op that has been just been reached in the
115 * walk; Arguments have not been evaluated yet.
116 *
117 * RETURN: Status
118 *
119 * DESCRIPTION: Descending callback used during the loading of ACPI tables.
120 *
121 ******************************************************************************/
122
123acpi_status
124acpi_ds_load1_begin_op (
125 struct acpi_walk_state *walk_state,
126 union acpi_parse_object **out_op)
127{
128 union acpi_parse_object *op;
129 struct acpi_namespace_node *node;
130 acpi_status status;
131 acpi_object_type object_type;
132 char *path;
133 u32 flags;
134
135
136 ACPI_FUNCTION_NAME ("ds_load1_begin_op");
137
138
139 op = walk_state->op;
140 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
141
142 /* We are only interested in opcodes that have an associated name */
143
144 if (op) {
145 if (!(walk_state->op_info->flags & AML_NAMED)) {
146#if 0
147 if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
148 (walk_state->op_info->class == AML_CLASS_CONTROL)) {
149 acpi_os_printf ("\n\n***EXECUTABLE OPCODE %s***\n\n", walk_state->op_info->name);
150 *out_op = op;
151 return (AE_CTRL_SKIP);
152 }
153#endif
154 *out_op = op;
155 return (AE_OK);
156 }
157
158 /* Check if this object has already been installed in the namespace */
159
160 if (op->common.node) {
161 *out_op = op;
162 return (AE_OK);
163 }
164 }
165
166 path = acpi_ps_get_next_namestring (&walk_state->parser_state);
167
168 /* Map the raw opcode into an internal object type */
169
170 object_type = walk_state->op_info->object_type;
171
172 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
173 "State=%p Op=%p [%s]\n", walk_state, op, acpi_ut_get_type_name (object_type)));
174
175 switch (walk_state->opcode) {
176 case AML_SCOPE_OP:
177
178 /*
179 * The target name of the Scope() operator must exist at this point so
180 * that we can actually open the scope to enter new names underneath it.
181 * Allow search-to-root for single namesegs.
182 */
183 status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
184 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
185#ifdef _ACPI_ASL_COMPILER
186 if (status == AE_NOT_FOUND) {
187 /*
188 * Table disassembly:
189 * Target of Scope() not found. Generate an External for it, and
190 * insert the name into the namespace.
191 */
192 acpi_dm_add_to_external_list (path);
193 status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
194 ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
195 }
196#endif
197 if (ACPI_FAILURE (status)) {
198 ACPI_REPORT_NSERROR (path, status);
199 return (status);
200 }
201
202 /*
203 * Check to make sure that the target is
204 * one of the opcodes that actually opens a scope
205 */
206 switch (node->type) {
207 case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
208 case ACPI_TYPE_DEVICE:
209 case ACPI_TYPE_POWER:
210 case ACPI_TYPE_PROCESSOR:
211 case ACPI_TYPE_THERMAL:
212
213 /* These are acceptable types */
214 break;
215
216 case ACPI_TYPE_INTEGER:
217 case ACPI_TYPE_STRING:
218 case ACPI_TYPE_BUFFER:
219
220 /*
221 * These types we will allow, but we will change the type. This
222 * enables some existing code of the form:
223 *
224 * Name (DEB, 0)
225 * Scope (DEB) { ... }
226 *
227 * Note: silently change the type here. On the second pass, we will report a warning
228 */
229
230 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
231 path, acpi_ut_get_type_name (node->type)));
232
233 node->type = ACPI_TYPE_ANY;
234 walk_state->scope_info->common.value = ACPI_TYPE_ANY;
235 break;
236
237 default:
238
239 /* All other types are an error */
240
241 ACPI_REPORT_ERROR (("Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)\n",
242 acpi_ut_get_type_name (node->type), path));
243
244 return (AE_AML_OPERAND_TYPE);
245 }
246 break;
247
248
249 default:
250
251 /*
252 * For all other named opcodes, we will enter the name into the namespace.
253 *
254 * Setup the search flags.
255 * Since we are entering a name into the namespace, we do not want to
256 * enable the search-to-root upsearch.
257 *
258 * There are only two conditions where it is acceptable that the name
259 * already exists:
260 * 1) the Scope() operator can reopen a scoping object that was
261 * previously defined (Scope, Method, Device, etc.)
262 * 2) Whenever we are parsing a deferred opcode (op_region, Buffer,
263 * buffer_field, or Package), the name of the object is already
264 * in the namespace.
265 */
266 if (walk_state->deferred_node) {
267 /* This name is already in the namespace, get the node */
268
269 node = walk_state->deferred_node;
270 status = AE_OK;
271 break;
272 }
273
274 flags = ACPI_NS_NO_UPSEARCH;
275 if ((walk_state->opcode != AML_SCOPE_OP) &&
276 (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
277 flags |= ACPI_NS_ERROR_IF_FOUND;
278 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n",
279 acpi_ut_get_type_name (object_type)));
280 }
281 else {
282 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Both Find or Create allowed\n",
283 acpi_ut_get_type_name (object_type)));
284 }
285
286 /*
287 * Enter the named type into the internal namespace. We enter the name
288 * as we go downward in the parse tree. Any necessary subobjects that involve
289 * arguments to the opcode must be created as we go back up the parse tree later.
290 */
291 status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
292 ACPI_IMODE_LOAD_PASS1, flags, walk_state, &(node));
293 if (ACPI_FAILURE (status)) {
294 ACPI_REPORT_NSERROR (path, status);
295 return (status);
296 }
297 break;
298 }
299
300
301 /* Common exit */
302
303 if (!op) {
304 /* Create a new op */
305
306 op = acpi_ps_alloc_op (walk_state->opcode);
307 if (!op) {
308 return (AE_NO_MEMORY);
309 }
310 }
311
312 /* Initialize */
313
314 op->named.name = node->name.integer;
315
316#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY))
317 op->named.path = (u8 *) path;
318#endif
319
320
321 /*
322 * Put the Node in the "op" object that the parser uses, so we
323 * can get it again quickly when this scope is closed
324 */
325 op->common.node = node;
326 acpi_ps_append_arg (acpi_ps_get_parent_scope (&walk_state->parser_state), op);
327
328 *out_op = op;
329 return (status);
330}
331
332
333/*******************************************************************************
334 *
335 * FUNCTION: acpi_ds_load1_end_op
336 *
337 * PARAMETERS: walk_state - Current state of the parse tree walk
338 * Op - Op that has been just been completed in the
339 * walk; Arguments have now been evaluated.
340 *
341 * RETURN: Status
342 *
343 * DESCRIPTION: Ascending callback used during the loading of the namespace,
344 * both control methods and everything else.
345 *
346 ******************************************************************************/
347
348acpi_status
349acpi_ds_load1_end_op (
350 struct acpi_walk_state *walk_state)
351{
352 union acpi_parse_object *op;
353 acpi_object_type object_type;
354 acpi_status status = AE_OK;
355
356
357 ACPI_FUNCTION_NAME ("ds_load1_end_op");
358
359
360 op = walk_state->op;
361 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
362
363 /* We are only interested in opcodes that have an associated name */
364
365 if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {
366 return (AE_OK);
367 }
368
369 /* Get the object type to determine if we should pop the scope */
370
371 object_type = walk_state->op_info->object_type;
372
373#ifndef ACPI_NO_METHOD_EXECUTION
374 if (walk_state->op_info->flags & AML_FIELD) {
375 if (walk_state->opcode == AML_FIELD_OP ||
376 walk_state->opcode == AML_BANK_FIELD_OP ||
377 walk_state->opcode == AML_INDEX_FIELD_OP) {
378 status = acpi_ds_init_field_objects (op, walk_state);
379 }
380 return (status);
381 }
382
383
384 if (op->common.aml_opcode == AML_REGION_OP) {
385 status = acpi_ex_create_region (op->named.data, op->named.length,
386 (acpi_adr_space_type) ((op->common.value.arg)->common.value.integer), walk_state);
387 if (ACPI_FAILURE (status)) {
388 return (status);
389 }
390 }
391#endif
392
393 if (op->common.aml_opcode == AML_NAME_OP) {
394 /* For Name opcode, get the object type from the argument */
395
396 if (op->common.value.arg) {
397 object_type = (acpi_ps_get_opcode_info ((op->common.value.arg)->common.aml_opcode))->object_type;
398 op->common.node->type = (u8) object_type;
399 }
400 }
401
402 if (op->common.aml_opcode == AML_METHOD_OP) {
403 /*
404 * method_op pkg_length name_string method_flags term_list
405 *
406 * Note: We must create the method node/object pair as soon as we
407 * see the method declaration. This allows later pass1 parsing
408 * of invocations of the method (need to know the number of
409 * arguments.)
410 */
411 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
412 "LOADING-Method: State=%p Op=%p named_obj=%p\n",
413 walk_state, op, op->named.node));
414
415 if (!acpi_ns_get_attached_object (op->named.node)) {
416 walk_state->operands[0] = (void *) op->named.node;
417 walk_state->num_operands = 1;
418
419 status = acpi_ds_create_operands (walk_state, op->common.value.arg);
420 if (ACPI_SUCCESS (status)) {
421 status = acpi_ex_create_method (op->named.data,
422 op->named.length, walk_state);
423 }
424 walk_state->operands[0] = NULL;
425 walk_state->num_operands = 0;
426
427 if (ACPI_FAILURE (status)) {
428 return (status);
429 }
430 }
431 }
432
433 /* Pop the scope stack */
434
435 if (acpi_ns_opens_scope (object_type)) {
436 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n",
437 acpi_ut_get_type_name (object_type), op));
438
439 status = acpi_ds_scope_stack_pop (walk_state);
440 }
441
442 return (status);
443}
444
445
446/*******************************************************************************
447 *
448 * FUNCTION: acpi_ds_load2_begin_op
449 *
450 * PARAMETERS: walk_state - Current state of the parse tree walk
451 * Op - Op that has been just been reached in the
452 * walk; Arguments have not been evaluated yet.
453 *
454 * RETURN: Status
455 *
456 * DESCRIPTION: Descending callback used during the loading of ACPI tables.
457 *
458 ******************************************************************************/
459
460acpi_status
461acpi_ds_load2_begin_op (
462 struct acpi_walk_state *walk_state,
463 union acpi_parse_object **out_op)
464{
465 union acpi_parse_object *op;
466 struct acpi_namespace_node *node;
467 acpi_status status;
468 acpi_object_type object_type;
469 char *buffer_ptr;
470
471
472 ACPI_FUNCTION_TRACE ("ds_load2_begin_op");
473
474
475 op = walk_state->op;
476 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
477
478 if (op) {
479 /* We only care about Namespace opcodes here */
480
481 if ((!(walk_state->op_info->flags & AML_NSOPCODE) && (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
482 (!(walk_state->op_info->flags & AML_NAMED))) {
483 return_ACPI_STATUS (AE_OK);
484 }
485
486 /*
487 * Get the name we are going to enter or lookup in the namespace
488 */
489 if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
490 /* For Namepath op, get the path string */
491
492 buffer_ptr = op->common.value.string;
493 if (!buffer_ptr) {
494 /* No name, just exit */
495
496 return_ACPI_STATUS (AE_OK);
497 }
498 }
499 else {
500 /* Get name from the op */
501
502 buffer_ptr = (char *) &op->named.name;
503 }
504 }
505 else {
506 /* Get the namestring from the raw AML */
507
508 buffer_ptr = acpi_ps_get_next_namestring (&walk_state->parser_state);
509 }
510
511 /* Map the opcode into an internal object type */
512
513 object_type = walk_state->op_info->object_type;
514
515 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
516 "State=%p Op=%p Type=%X\n", walk_state, op, object_type));
517
518
519 switch (walk_state->opcode) {
520 case AML_FIELD_OP:
521 case AML_BANK_FIELD_OP:
522 case AML_INDEX_FIELD_OP:
523
524 node = NULL;
525 status = AE_OK;
526 break;
527
528 case AML_INT_NAMEPATH_OP:
529
530 /*
531 * The name_path is an object reference to an existing object. Don't enter the
532 * name into the namespace, but look it up for use later
533 */
534 status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
535 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
536 break;
537
538 case AML_SCOPE_OP:
539
540 /*
541 * The Path is an object reference to an existing object. Don't enter the
542 * name into the namespace, but look it up for use later
543 */
544 status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
545 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
546 if (ACPI_FAILURE (status)) {
547#ifdef _ACPI_ASL_COMPILER
548 if (status == AE_NOT_FOUND) {
549 status = AE_OK;
550 }
551 else {
552 ACPI_REPORT_NSERROR (buffer_ptr, status);
553 }
554#else
555 ACPI_REPORT_NSERROR (buffer_ptr, status);
556#endif
557 return_ACPI_STATUS (status);
558 }
559 /*
560 * We must check to make sure that the target is
561 * one of the opcodes that actually opens a scope
562 */
563 switch (node->type) {
564 case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
565 case ACPI_TYPE_DEVICE:
566 case ACPI_TYPE_POWER:
567 case ACPI_TYPE_PROCESSOR:
568 case ACPI_TYPE_THERMAL:
569
570 /* These are acceptable types */
571 break;
572
573 case ACPI_TYPE_INTEGER:
574 case ACPI_TYPE_STRING:
575 case ACPI_TYPE_BUFFER:
576
577 /*
578 * These types we will allow, but we will change the type. This
579 * enables some existing code of the form:
580 *
581 * Name (DEB, 0)
582 * Scope (DEB) { ... }
583 */
584
585 ACPI_REPORT_WARNING (("Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
586 buffer_ptr, acpi_ut_get_type_name (node->type)));
587
588 node->type = ACPI_TYPE_ANY;
589 walk_state->scope_info->common.value = ACPI_TYPE_ANY;
590 break;
591
592 default:
593
594 /* All other types are an error */
595
596 ACPI_REPORT_ERROR (("Invalid type (%s) for target of Scope operator [%4.4s]\n",
597 acpi_ut_get_type_name (node->type), buffer_ptr));
598
599 return (AE_AML_OPERAND_TYPE);
600 }
601 break;
602
603 default:
604
605 /* All other opcodes */
606
607 if (op && op->common.node) {
608 /* This op/node was previously entered into the namespace */
609
610 node = op->common.node;
611
612 if (acpi_ns_opens_scope (object_type)) {
613 status = acpi_ds_scope_stack_push (node, object_type, walk_state);
614 if (ACPI_FAILURE (status)) {
615 return_ACPI_STATUS (status);
616 }
617
618 }
619 return_ACPI_STATUS (AE_OK);
620 }
621
622 /*
623 * Enter the named type into the internal namespace. We enter the name
624 * as we go downward in the parse tree. Any necessary subobjects that involve
625 * arguments to the opcode must be created as we go back up the parse tree later.
626 *
627 * Note: Name may already exist if we are executing a deferred opcode.
628 */
629 if (walk_state->deferred_node) {
630 /* This name is already in the namespace, get the node */
631
632 node = walk_state->deferred_node;
633 status = AE_OK;
634 break;
635 }
636
637 status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
638 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, walk_state, &(node));
639 break;
640 }
641
642 if (ACPI_FAILURE (status)) {
643 ACPI_REPORT_NSERROR (buffer_ptr, status);
644 return_ACPI_STATUS (status);
645 }
646
647
648 if (!op) {
649 /* Create a new op */
650
651 op = acpi_ps_alloc_op (walk_state->opcode);
652 if (!op) {
653 return_ACPI_STATUS (AE_NO_MEMORY);
654 }
655
656 /* Initialize the new op */
657
658 if (node) {
659 op->named.name = node->name.integer;
660 }
661 if (out_op) {
662 *out_op = op;
663 }
664 }
665
666 /*
667 * Put the Node in the "op" object that the parser uses, so we
668 * can get it again quickly when this scope is closed
669 */
670 op->common.node = node;
671
672 return_ACPI_STATUS (status);
673}
674
675
676/*******************************************************************************
677 *
678 * FUNCTION: acpi_ds_load2_end_op
679 *
680 * PARAMETERS: walk_state - Current state of the parse tree walk
681 * Op - Op that has been just been completed in the
682 * walk; Arguments have now been evaluated.
683 *
684 * RETURN: Status
685 *
686 * DESCRIPTION: Ascending callback used during the loading of the namespace,
687 * both control methods and everything else.
688 *
689 ******************************************************************************/
690
691acpi_status
692acpi_ds_load2_end_op (
693 struct acpi_walk_state *walk_state)
694{
695 union acpi_parse_object *op;
696 acpi_status status = AE_OK;
697 acpi_object_type object_type;
698 struct acpi_namespace_node *node;
699 union acpi_parse_object *arg;
700 struct acpi_namespace_node *new_node;
701#ifndef ACPI_NO_METHOD_EXECUTION
702 u32 i;
703#endif
704
705
706 ACPI_FUNCTION_TRACE ("ds_load2_end_op");
707
708 op = walk_state->op;
709 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
710 walk_state->op_info->name, op, walk_state));
711
712 /* Only interested in opcodes that have namespace objects */
713
714 if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
715 return_ACPI_STATUS (AE_OK);
716 }
717
718 if (op->common.aml_opcode == AML_SCOPE_OP) {
719 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
720 "Ending scope Op=%p State=%p\n", op, walk_state));
721 }
722
723
724 object_type = walk_state->op_info->object_type;
725
726 /*
727 * Get the Node/name from the earlier lookup
728 * (It was saved in the *op structure)
729 */
730 node = op->common.node;
731
732 /*
733 * Put the Node on the object stack (Contains the ACPI Name of
734 * this object)
735 */
736 walk_state->operands[0] = (void *) node;
737 walk_state->num_operands = 1;
738
739 /* Pop the scope stack */
740
741 if (acpi_ns_opens_scope (object_type) && (op->common.aml_opcode != AML_INT_METHODCALL_OP)) {
742 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n",
743 acpi_ut_get_type_name (object_type), op));
744
745 status = acpi_ds_scope_stack_pop (walk_state);
746 if (ACPI_FAILURE (status)) {
747 goto cleanup;
748 }
749 }
750
751 /*
752 * Named operations are as follows:
753 *
754 * AML_ALIAS
755 * AML_BANKFIELD
756 * AML_CREATEBITFIELD
757 * AML_CREATEBYTEFIELD
758 * AML_CREATEDWORDFIELD
759 * AML_CREATEFIELD
760 * AML_CREATEQWORDFIELD
761 * AML_CREATEWORDFIELD
762 * AML_DATA_REGION
763 * AML_DEVICE
764 * AML_EVENT
765 * AML_FIELD
766 * AML_INDEXFIELD
767 * AML_METHOD
768 * AML_METHODCALL
769 * AML_MUTEX
770 * AML_NAME
771 * AML_NAMEDFIELD
772 * AML_OPREGION
773 * AML_POWERRES
774 * AML_PROCESSOR
775 * AML_SCOPE
776 * AML_THERMALZONE
777 */
778
779 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
780 "Create-Load [%s] State=%p Op=%p named_obj=%p\n",
781 acpi_ps_get_opcode_name (op->common.aml_opcode), walk_state, op, node));
782
783 /* Decode the opcode */
784
785 arg = op->common.value.arg;
786
787 switch (walk_state->op_info->type) {
788#ifndef ACPI_NO_METHOD_EXECUTION
789
790 case AML_TYPE_CREATE_FIELD:
791
792 /*
793 * Create the field object, but the field buffer and index must
794 * be evaluated later during the execution phase
795 */
796 status = acpi_ds_create_buffer_field (op, walk_state);
797 break;
798
799
800 case AML_TYPE_NAMED_FIELD:
801
802 switch (op->common.aml_opcode) {
803 case AML_INDEX_FIELD_OP:
804
805 status = acpi_ds_create_index_field (op, (acpi_handle) arg->common.node,
806 walk_state);
807 break;
808
809 case AML_BANK_FIELD_OP:
810
811 status = acpi_ds_create_bank_field (op, arg->common.node, walk_state);
812 break;
813
814 case AML_FIELD_OP:
815
816 status = acpi_ds_create_field (op, arg->common.node, walk_state);
817 break;
818
819 default:
820 /* All NAMED_FIELD opcodes must be handled above */
821 break;
822 }
823 break;
824
825
826 case AML_TYPE_NAMED_SIMPLE:
827
828 status = acpi_ds_create_operands (walk_state, arg);
829 if (ACPI_FAILURE (status)) {
830 goto cleanup;
831 }
832
833 switch (op->common.aml_opcode) {
834 case AML_PROCESSOR_OP:
835
836 status = acpi_ex_create_processor (walk_state);
837 break;
838
839 case AML_POWER_RES_OP:
840
841 status = acpi_ex_create_power_resource (walk_state);
842 break;
843
844 case AML_MUTEX_OP:
845
846 status = acpi_ex_create_mutex (walk_state);
847 break;
848
849 case AML_EVENT_OP:
850
851 status = acpi_ex_create_event (walk_state);
852 break;
853
854 case AML_DATA_REGION_OP:
855
856 status = acpi_ex_create_table_region (walk_state);
857 break;
858
859 case AML_ALIAS_OP:
860
861 status = acpi_ex_create_alias (walk_state);
862 break;
863
864 default:
865 /* Unknown opcode */
866
867 status = AE_OK;
868 goto cleanup;
869 }
870
871 /* Delete operands */
872
873 for (i = 1; i < walk_state->num_operands; i++) {
874 acpi_ut_remove_reference (walk_state->operands[i]);
875 walk_state->operands[i] = NULL;
876 }
877
878 break;
879#endif /* ACPI_NO_METHOD_EXECUTION */
880
881 case AML_TYPE_NAMED_COMPLEX:
882
883 switch (op->common.aml_opcode) {
884#ifndef ACPI_NO_METHOD_EXECUTION
885 case AML_REGION_OP:
886 /*
887 * The op_region is not fully parsed at this time. Only valid argument is the space_id.
888 * (We must save the address of the AML of the address and length operands)
889 */
890 /*
891 * If we have a valid region, initialize it
892 * Namespace is NOT locked at this point.
893 */
894 status = acpi_ev_initialize_region (acpi_ns_get_attached_object (node), FALSE);
895 if (ACPI_FAILURE (status)) {
896 /*
897 * If AE_NOT_EXIST is returned, it is not fatal
898 * because many regions get created before a handler
899 * is installed for said region.
900 */
901 if (AE_NOT_EXIST == status) {
902 status = AE_OK;
903 }
904 }
905 break;
906
907
908 case AML_NAME_OP:
909
910 status = acpi_ds_create_node (walk_state, node, op);
911 break;
912#endif /* ACPI_NO_METHOD_EXECUTION */
913
914
915 default:
916 /* All NAMED_COMPLEX opcodes must be handled above */
917 /* Note: Method objects were already created in Pass 1 */
918 break;
919 }
920 break;
921
922
923 case AML_CLASS_INTERNAL:
924
925 /* case AML_INT_NAMEPATH_OP: */
926 break;
927
928
929 case AML_CLASS_METHOD_CALL:
930
931 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
932 "RESOLVING-method_call: State=%p Op=%p named_obj=%p\n",
933 walk_state, op, node));
934
935 /*
936 * Lookup the method name and save the Node
937 */
938 status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
939 ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS2,
940 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
941 walk_state, &(new_node));
942 if (ACPI_SUCCESS (status)) {
943 /*
944 * Make sure that what we found is indeed a method
945 * We didn't search for a method on purpose, to see if the name would resolve
946 */
947 if (new_node->type != ACPI_TYPE_METHOD) {
948 status = AE_AML_OPERAND_TYPE;
949 }
950
951 /* We could put the returned object (Node) on the object stack for later, but
952 * for now, we will put it in the "op" object that the parser uses, so we
953 * can get it again at the end of this scope
954 */
955 op->common.node = new_node;
956 }
957 else {
958 ACPI_REPORT_NSERROR (arg->common.value.string, status);
959 }
960 break;
961
962
963 default:
964 break;
965 }
966
967cleanup:
968
969 /* Remove the Node pushed at the very beginning */
970
971 walk_state->operands[0] = NULL;
972 walk_state->num_operands = 0;
973 return_ACPI_STATUS (status);
974}
975
976
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c
new file mode 100644
index 000000000000..65f456151e25
--- /dev/null
+++ b/drivers/acpi/dispatcher/dswscope.c
@@ -0,0 +1,229 @@
1/******************************************************************************
2 *
3 * Module Name: dswscope - Scope stack manipulation
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acdispat.h>
47
48
49#define _COMPONENT ACPI_DISPATCHER
50 ACPI_MODULE_NAME ("dswscope")
51
52
53#define STACK_POP(head) head
54
55
56/****************************************************************************
57 *
58 * FUNCTION: acpi_ds_scope_stack_clear
59 *
60 * PARAMETERS: None
61 *
62 * DESCRIPTION: Pop (and free) everything on the scope stack except the
63 * root scope object (which remains at the stack top.)
64 *
65 ***************************************************************************/
66
67void
68acpi_ds_scope_stack_clear (
69 struct acpi_walk_state *walk_state)
70{
71 union acpi_generic_state *scope_info;
72
73 ACPI_FUNCTION_NAME ("ds_scope_stack_clear");
74
75
76 while (walk_state->scope_info) {
77 /* Pop a scope off the stack */
78
79 scope_info = walk_state->scope_info;
80 walk_state->scope_info = scope_info->scope.next;
81
82 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
83 "Popped object type (%s)\n", acpi_ut_get_type_name (scope_info->common.value)));
84 acpi_ut_delete_generic_state (scope_info);
85 }
86}
87
88
89/****************************************************************************
90 *
91 * FUNCTION: acpi_ds_scope_stack_push
92 *
93 * PARAMETERS: *Node, - Name to be made current
94 * Type, - Type of frame being pushed
95 *
96 * DESCRIPTION: Push the current scope on the scope stack, and make the
97 * passed Node current.
98 *
99 ***************************************************************************/
100
101acpi_status
102acpi_ds_scope_stack_push (
103 struct acpi_namespace_node *node,
104 acpi_object_type type,
105 struct acpi_walk_state *walk_state)
106{
107 union acpi_generic_state *scope_info;
108 union acpi_generic_state *old_scope_info;
109
110
111 ACPI_FUNCTION_TRACE ("ds_scope_stack_push");
112
113
114 if (!node) {
115 /* Invalid scope */
116
117 ACPI_REPORT_ERROR (("ds_scope_stack_push: null scope passed\n"));
118 return_ACPI_STATUS (AE_BAD_PARAMETER);
119 }
120
121 /* Make sure object type is valid */
122
123 if (!acpi_ut_valid_object_type (type)) {
124 ACPI_REPORT_WARNING (("ds_scope_stack_push: Invalid object type: 0x%X\n", type));
125 }
126
127 /* Allocate a new scope object */
128
129 scope_info = acpi_ut_create_generic_state ();
130 if (!scope_info) {
131 return_ACPI_STATUS (AE_NO_MEMORY);
132 }
133
134 /* Init new scope object */
135
136 scope_info->common.data_type = ACPI_DESC_TYPE_STATE_WSCOPE;
137 scope_info->scope.node = node;
138 scope_info->common.value = (u16) type;
139
140 walk_state->scope_depth++;
141
142 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
143 "[%.2d] Pushed scope ", (u32) walk_state->scope_depth));
144
145 old_scope_info = walk_state->scope_info;
146 if (old_scope_info) {
147 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
148 "[%4.4s] (%s)",
149 acpi_ut_get_node_name (old_scope_info->scope.node),
150 acpi_ut_get_type_name (old_scope_info->common.value)));
151 }
152 else {
153 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
154 "[\\___] (%s)", "ROOT"));
155 }
156
157 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
158 ", New scope -> [%4.4s] (%s)\n",
159 acpi_ut_get_node_name (scope_info->scope.node),
160 acpi_ut_get_type_name (scope_info->common.value)));
161
162 /* Push new scope object onto stack */
163
164 acpi_ut_push_generic_state (&walk_state->scope_info, scope_info);
165 return_ACPI_STATUS (AE_OK);
166}
167
168
169/****************************************************************************
170 *
171 * FUNCTION: acpi_ds_scope_stack_pop
172 *
173 * PARAMETERS: Type - The type of frame to be found
174 *
175 * DESCRIPTION: Pop the scope stack until a frame of the requested type
176 * is found.
177 *
178 * RETURN: Count of frames popped. If no frame of the requested type
179 * was found, the count is returned as a negative number and
180 * the scope stack is emptied (which sets the current scope
181 * to the root). If the scope stack was empty at entry, the
182 * function is a no-op and returns 0.
183 *
184 ***************************************************************************/
185
186acpi_status
187acpi_ds_scope_stack_pop (
188 struct acpi_walk_state *walk_state)
189{
190 union acpi_generic_state *scope_info;
191 union acpi_generic_state *new_scope_info;
192
193
194 ACPI_FUNCTION_TRACE ("ds_scope_stack_pop");
195
196
197 /*
198 * Pop scope info object off the stack.
199 */
200 scope_info = acpi_ut_pop_generic_state (&walk_state->scope_info);
201 if (!scope_info) {
202 return_ACPI_STATUS (AE_STACK_UNDERFLOW);
203 }
204
205 walk_state->scope_depth--;
206
207 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
208 "[%.2d] Popped scope [%4.4s] (%s), New scope -> ",
209 (u32) walk_state->scope_depth,
210 acpi_ut_get_node_name (scope_info->scope.node),
211 acpi_ut_get_type_name (scope_info->common.value)));
212
213 new_scope_info = walk_state->scope_info;
214 if (new_scope_info) {
215 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
216 "[%4.4s] (%s)\n",
217 acpi_ut_get_node_name (new_scope_info->scope.node),
218 acpi_ut_get_type_name (new_scope_info->common.value)));
219 }
220 else {
221 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
222 "[\\___] (ROOT)\n"));
223 }
224
225 acpi_ut_delete_generic_state (scope_info);
226 return_ACPI_STATUS (AE_OK);
227}
228
229
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
new file mode 100644
index 000000000000..e555b3fbd5e5
--- /dev/null
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -0,0 +1,1100 @@
1/******************************************************************************
2 *
3 * Module Name: dswstate - Dispatcher parse tree walk management routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/acdispat.h>
48#include <acpi/acnamesp.h>
49
50#define _COMPONENT ACPI_DISPATCHER
51 ACPI_MODULE_NAME ("dswstate")
52
53
54#ifdef ACPI_FUTURE_USAGE
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_ds_result_insert
59 *
60 * PARAMETERS: Object - Object to push
61 * Index - Where to insert the object
62 * walk_state - Current Walk state
63 *
64 * RETURN: Status
65 *
66 * DESCRIPTION: Insert an object onto this walk's result stack
67 *
68 ******************************************************************************/
69
70acpi_status
71acpi_ds_result_insert (
72 void *object,
73 u32 index,
74 struct acpi_walk_state *walk_state)
75{
76 union acpi_generic_state *state;
77
78
79 ACPI_FUNCTION_NAME ("ds_result_insert");
80
81
82 state = walk_state->results;
83 if (!state) {
84 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n",
85 walk_state));
86 return (AE_NOT_EXIST);
87 }
88
89 if (index >= ACPI_OBJ_NUM_OPERANDS) {
90 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
91 "Index out of range: %X Obj=%p State=%p Num=%X\n",
92 index, object, walk_state, state->results.num_results));
93 return (AE_BAD_PARAMETER);
94 }
95
96 if (!object) {
97 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
98 "Null Object! Index=%X Obj=%p State=%p Num=%X\n",
99 index, object, walk_state, state->results.num_results));
100 return (AE_BAD_PARAMETER);
101 }
102
103 state->results.obj_desc [index] = object;
104 state->results.num_results++;
105
106 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
107 "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
108 object, object ? acpi_ut_get_object_type_name ((union acpi_operand_object *) object) : "NULL",
109 walk_state, state->results.num_results, walk_state->current_result));
110
111 return (AE_OK);
112}
113
114
115/*******************************************************************************
116 *
117 * FUNCTION: acpi_ds_result_remove
118 *
119 * PARAMETERS: Object - Where to return the popped object
120 * Index - Where to extract the object
121 * walk_state - Current Walk state
122 *
123 * RETURN: Status
124 *
125 * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
126 * other words, this is a FIFO.
127 *
128 ******************************************************************************/
129
130acpi_status
131acpi_ds_result_remove (
132 union acpi_operand_object **object,
133 u32 index,
134 struct acpi_walk_state *walk_state)
135{
136 union acpi_generic_state *state;
137
138
139 ACPI_FUNCTION_NAME ("ds_result_remove");
140
141
142 state = walk_state->results;
143 if (!state) {
144 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n",
145 walk_state));
146 return (AE_NOT_EXIST);
147 }
148
149 if (index >= ACPI_OBJ_MAX_OPERAND) {
150 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
151 "Index out of range: %X State=%p Num=%X\n",
152 index, walk_state, state->results.num_results));
153 }
154
155 /* Check for a valid result object */
156
157 if (!state->results.obj_desc [index]) {
158 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
159 "Null operand! State=%p #Ops=%X, Index=%X\n",
160 walk_state, state->results.num_results, index));
161 return (AE_AML_NO_RETURN_VALUE);
162 }
163
164 /* Remove the object */
165
166 state->results.num_results--;
167
168 *object = state->results.obj_desc [index];
169 state->results.obj_desc [index] = NULL;
170
171 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
172 "Obj=%p [%s] Index=%X State=%p Num=%X\n",
173 *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
174 index, walk_state, state->results.num_results));
175
176 return (AE_OK);
177}
178
179#endif /* ACPI_FUTURE_USAGE */
180
181
182/*******************************************************************************
183 *
184 * FUNCTION: acpi_ds_result_pop
185 *
186 * PARAMETERS: Object - Where to return the popped object
187 * walk_state - Current Walk state
188 *
189 * RETURN: Status
190 *
191 * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
192 * other words, this is a FIFO.
193 *
194 ******************************************************************************/
195
196acpi_status
197acpi_ds_result_pop (
198 union acpi_operand_object **object,
199 struct acpi_walk_state *walk_state)
200{
201 acpi_native_uint index;
202 union acpi_generic_state *state;
203
204
205 ACPI_FUNCTION_NAME ("ds_result_pop");
206
207
208 state = walk_state->results;
209 if (!state) {
210 return (AE_OK);
211 }
212
213 if (!state->results.num_results) {
214 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Result stack is empty! State=%p\n",
215 walk_state));
216 return (AE_AML_NO_RETURN_VALUE);
217 }
218
219 /* Remove top element */
220
221 state->results.num_results--;
222
223 for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) {
224 /* Check for a valid result object */
225
226 if (state->results.obj_desc [index -1]) {
227 *object = state->results.obj_desc [index -1];
228 state->results.obj_desc [index -1] = NULL;
229
230 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] Index=%X State=%p Num=%X\n",
231 *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
232 (u32) index -1, walk_state, state->results.num_results));
233
234 return (AE_OK);
235 }
236 }
237
238 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n", walk_state));
239 return (AE_AML_NO_RETURN_VALUE);
240}
241
242
243/*******************************************************************************
244 *
245 * FUNCTION: acpi_ds_result_pop_from_bottom
246 *
247 * PARAMETERS: Object - Where to return the popped object
248 * walk_state - Current Walk state
249 *
250 * RETURN: Status
251 *
252 * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
253 * other words, this is a FIFO.
254 *
255 ******************************************************************************/
256
257acpi_status
258acpi_ds_result_pop_from_bottom (
259 union acpi_operand_object **object,
260 struct acpi_walk_state *walk_state)
261{
262 acpi_native_uint index;
263 union acpi_generic_state *state;
264
265
266 ACPI_FUNCTION_NAME ("ds_result_pop_from_bottom");
267
268
269 state = walk_state->results;
270 if (!state) {
271 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
272 "Warning: No result object pushed! State=%p\n", walk_state));
273 return (AE_NOT_EXIST);
274 }
275
276 if (!state->results.num_results) {
277 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n", walk_state));
278 return (AE_AML_NO_RETURN_VALUE);
279 }
280
281 /* Remove Bottom element */
282
283 *object = state->results.obj_desc [0];
284
285 /* Push entire stack down one element */
286
287 for (index = 0; index < state->results.num_results; index++) {
288 state->results.obj_desc [index] = state->results.obj_desc [index + 1];
289 }
290
291 state->results.num_results--;
292
293 /* Check for a valid result object */
294
295 if (!*object) {
296 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null operand! State=%p #Ops=%X, Index=%X\n",
297 walk_state, state->results.num_results, (u32) index));
298 return (AE_AML_NO_RETURN_VALUE);
299 }
300
301 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s], Results=%p State=%p\n",
302 *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
303 state, walk_state));
304
305 return (AE_OK);
306}
307
308
309/*******************************************************************************
310 *
311 * FUNCTION: acpi_ds_result_push
312 *
313 * PARAMETERS: Object - Where to return the popped object
314 * walk_state - Current Walk state
315 *
316 * RETURN: Status
317 *
318 * DESCRIPTION: Push an object onto the current result stack
319 *
320 ******************************************************************************/
321
322acpi_status
323acpi_ds_result_push (
324 union acpi_operand_object *object,
325 struct acpi_walk_state *walk_state)
326{
327 union acpi_generic_state *state;
328
329
330 ACPI_FUNCTION_NAME ("ds_result_push");
331
332
333 state = walk_state->results;
334 if (!state) {
335 ACPI_REPORT_ERROR (("No result stack frame during push\n"));
336 return (AE_AML_INTERNAL);
337 }
338
339 if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) {
340 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
341 "Result stack overflow: Obj=%p State=%p Num=%X\n",
342 object, walk_state, state->results.num_results));
343 return (AE_STACK_OVERFLOW);
344 }
345
346 if (!object) {
347 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Object! Obj=%p State=%p Num=%X\n",
348 object, walk_state, state->results.num_results));
349 return (AE_BAD_PARAMETER);
350 }
351
352 state->results.obj_desc [state->results.num_results] = object;
353 state->results.num_results++;
354
355 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
356 object, object ? acpi_ut_get_object_type_name ((union acpi_operand_object *) object) : "NULL",
357 walk_state, state->results.num_results, walk_state->current_result));
358
359 return (AE_OK);
360}
361
362
363/*******************************************************************************
364 *
365 * FUNCTION: acpi_ds_result_stack_push
366 *
367 * PARAMETERS: walk_state - Current Walk state
368 *
369 * RETURN: Status
370 *
371 * DESCRIPTION: Push an object onto the walk_state result stack.
372 *
373 ******************************************************************************/
374
375acpi_status
376acpi_ds_result_stack_push (
377 struct acpi_walk_state *walk_state)
378{
379 union acpi_generic_state *state;
380
381 ACPI_FUNCTION_NAME ("ds_result_stack_push");
382
383
384 state = acpi_ut_create_generic_state ();
385 if (!state) {
386 return (AE_NO_MEMORY);
387 }
388
389 state->common.data_type = ACPI_DESC_TYPE_STATE_RESULT;
390 acpi_ut_push_generic_state (&walk_state->results, state);
391
392 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Results=%p State=%p\n",
393 state, walk_state));
394
395 return (AE_OK);
396}
397
398
399/*******************************************************************************
400 *
401 * FUNCTION: acpi_ds_result_stack_pop
402 *
403 * PARAMETERS: walk_state - Current Walk state
404 *
405 * RETURN: Status
406 *
407 * DESCRIPTION: Pop an object off of the walk_state result stack.
408 *
409 ******************************************************************************/
410
411acpi_status
412acpi_ds_result_stack_pop (
413 struct acpi_walk_state *walk_state)
414{
415 union acpi_generic_state *state;
416
417 ACPI_FUNCTION_NAME ("ds_result_stack_pop");
418
419
420 /* Check for stack underflow */
421
422 if (walk_state->results == NULL) {
423 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Underflow - State=%p\n",
424 walk_state));
425 return (AE_AML_NO_OPERAND);
426 }
427
428 state = acpi_ut_pop_generic_state (&walk_state->results);
429
430 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
431 "Result=%p remaining_results=%X State=%p\n",
432 state, state->results.num_results, walk_state));
433
434 acpi_ut_delete_generic_state (state);
435
436 return (AE_OK);
437}
438
439
440/*******************************************************************************
441 *
442 * FUNCTION: acpi_ds_obj_stack_delete_all
443 *
444 * PARAMETERS: walk_state - Current Walk state
445 *
446 * RETURN: Status
447 *
448 * DESCRIPTION: Clear the object stack by deleting all objects that are on it.
449 * Should be used with great care, if at all!
450 *
451 ******************************************************************************/
452#ifdef ACPI_FUTURE_USAGE
453acpi_status
454acpi_ds_obj_stack_delete_all (
455 struct acpi_walk_state *walk_state)
456{
457 u32 i;
458
459
460 ACPI_FUNCTION_TRACE_PTR ("ds_obj_stack_delete_all", walk_state);
461
462
463 /* The stack size is configurable, but fixed */
464
465 for (i = 0; i < ACPI_OBJ_NUM_OPERANDS; i++) {
466 if (walk_state->operands[i]) {
467 acpi_ut_remove_reference (walk_state->operands[i]);
468 walk_state->operands[i] = NULL;
469 }
470 }
471
472 return_ACPI_STATUS (AE_OK);
473}
474#endif /* ACPI_FUTURE_USAGE */
475
476
477/*******************************************************************************
478 *
479 * FUNCTION: acpi_ds_obj_stack_push
480 *
481 * PARAMETERS: Object - Object to push
482 * walk_state - Current Walk state
483 *
484 * RETURN: Status
485 *
486 * DESCRIPTION: Push an object onto this walk's object/operand stack
487 *
488 ******************************************************************************/
489
490acpi_status
491acpi_ds_obj_stack_push (
492 void *object,
493 struct acpi_walk_state *walk_state)
494{
495 ACPI_FUNCTION_NAME ("ds_obj_stack_push");
496
497
498 /* Check for stack overflow */
499
500 if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) {
501 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
502 "overflow! Obj=%p State=%p #Ops=%X\n",
503 object, walk_state, walk_state->num_operands));
504 return (AE_STACK_OVERFLOW);
505 }
506
507 /* Put the object onto the stack */
508
509 walk_state->operands [walk_state->num_operands] = object;
510 walk_state->num_operands++;
511
512 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
513 object, acpi_ut_get_object_type_name ((union acpi_operand_object *) object),
514 walk_state, walk_state->num_operands));
515
516 return (AE_OK);
517}
518
519
520#if 0
521/*******************************************************************************
522 *
523 * FUNCTION: acpi_ds_obj_stack_pop_object
524 *
525 * PARAMETERS: pop_count - Number of objects/entries to pop
526 * walk_state - Current Walk state
527 *
528 * RETURN: Status
529 *
530 * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
531 * deleted by this routine.
532 *
533 ******************************************************************************/
534
535acpi_status
536acpi_ds_obj_stack_pop_object (
537 union acpi_operand_object **object,
538 struct acpi_walk_state *walk_state)
539{
540 ACPI_FUNCTION_NAME ("ds_obj_stack_pop_object");
541
542
543 /* Check for stack underflow */
544
545 if (walk_state->num_operands == 0) {
546 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
547 "Missing operand/stack empty! State=%p #Ops=%X\n",
548 walk_state, walk_state->num_operands));
549 *object = NULL;
550 return (AE_AML_NO_OPERAND);
551 }
552
553 /* Pop the stack */
554
555 walk_state->num_operands--;
556
557 /* Check for a valid operand */
558
559 if (!walk_state->operands [walk_state->num_operands]) {
560 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
561 "Null operand! State=%p #Ops=%X\n",
562 walk_state, walk_state->num_operands));
563 *object = NULL;
564 return (AE_AML_NO_OPERAND);
565 }
566
567 /* Get operand and set stack entry to null */
568
569 *object = walk_state->operands [walk_state->num_operands];
570 walk_state->operands [walk_state->num_operands] = NULL;
571
572 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
573 *object, acpi_ut_get_object_type_name (*object),
574 walk_state, walk_state->num_operands));
575
576 return (AE_OK);
577}
578#endif
579
580
581/*******************************************************************************
582 *
583 * FUNCTION: acpi_ds_obj_stack_pop
584 *
585 * PARAMETERS: pop_count - Number of objects/entries to pop
586 * walk_state - Current Walk state
587 *
588 * RETURN: Status
589 *
590 * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
591 * deleted by this routine.
592 *
593 ******************************************************************************/
594
595acpi_status
596acpi_ds_obj_stack_pop (
597 u32 pop_count,
598 struct acpi_walk_state *walk_state)
599{
600 u32 i;
601
602 ACPI_FUNCTION_NAME ("ds_obj_stack_pop");
603
604
605 for (i = 0; i < pop_count; i++) {
606 /* Check for stack underflow */
607
608 if (walk_state->num_operands == 0) {
609 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
610 "Underflow! Count=%X State=%p #Ops=%X\n",
611 pop_count, walk_state, walk_state->num_operands));
612 return (AE_STACK_UNDERFLOW);
613 }
614
615 /* Just set the stack entry to null */
616
617 walk_state->num_operands--;
618 walk_state->operands [walk_state->num_operands] = NULL;
619 }
620
621 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
622 pop_count, walk_state, walk_state->num_operands));
623
624 return (AE_OK);
625}
626
627
628/*******************************************************************************
629 *
630 * FUNCTION: acpi_ds_obj_stack_pop_and_delete
631 *
632 * PARAMETERS: pop_count - Number of objects/entries to pop
633 * walk_state - Current Walk state
634 *
635 * RETURN: Status
636 *
637 * DESCRIPTION: Pop this walk's object stack and delete each object that is
638 * popped off.
639 *
640 ******************************************************************************/
641
642acpi_status
643acpi_ds_obj_stack_pop_and_delete (
644 u32 pop_count,
645 struct acpi_walk_state *walk_state)
646{
647 u32 i;
648 union acpi_operand_object *obj_desc;
649
650
651 ACPI_FUNCTION_NAME ("ds_obj_stack_pop_and_delete");
652
653
654 for (i = 0; i < pop_count; i++) {
655 /* Check for stack underflow */
656
657 if (walk_state->num_operands == 0) {
658 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
659 "Underflow! Count=%X State=%p #Ops=%X\n",
660 pop_count, walk_state, walk_state->num_operands));
661 return (AE_STACK_UNDERFLOW);
662 }
663
664 /* Pop the stack and delete an object if present in this stack entry */
665
666 walk_state->num_operands--;
667 obj_desc = walk_state->operands [walk_state->num_operands];
668 if (obj_desc) {
669 acpi_ut_remove_reference (walk_state->operands [walk_state->num_operands]);
670 walk_state->operands [walk_state->num_operands] = NULL;
671 }
672 }
673
674 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
675 pop_count, walk_state, walk_state->num_operands));
676
677 return (AE_OK);
678}
679
680
681/*******************************************************************************
682 *
683 * FUNCTION: acpi_ds_obj_stack_get_value
684 *
685 * PARAMETERS: Index - Stack index whose value is desired. Based
686 * on the top of the stack (index=0 == top)
687 * walk_state - Current Walk state
688 *
689 * RETURN: Status
690 *
691 * DESCRIPTION: Retrieve an object from this walk's object stack. Index must
692 * be within the range of the current stack pointer.
693 *
694 ******************************************************************************/
695#ifdef ACPI_FUTURE_USAGE
696void *
697acpi_ds_obj_stack_get_value (
698 u32 index,
699 struct acpi_walk_state *walk_state)
700{
701
702 ACPI_FUNCTION_TRACE_PTR ("ds_obj_stack_get_value", walk_state);
703
704
705 /* Can't do it if the stack is empty */
706
707 if (walk_state->num_operands == 0) {
708 return_PTR (NULL);
709 }
710
711 /* or if the index is past the top of the stack */
712
713 if (index > (walk_state->num_operands - (u32) 1)) {
714 return_PTR (NULL);
715 }
716
717 return_PTR (walk_state->operands[(acpi_native_uint)(walk_state->num_operands - 1) -
718 index]);
719}
720#endif /* ACPI_FUTURE_USAGE */
721
722
723/*******************************************************************************
724 *
725 * FUNCTION: acpi_ds_get_current_walk_state
726 *
727 * PARAMETERS: Thread - Get current active state for this Thread
728 *
729 * RETURN: Pointer to the current walk state
730 *
731 * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
732 * walk state.)
733 *
734 ******************************************************************************/
735
736struct acpi_walk_state *
737acpi_ds_get_current_walk_state (
738 struct acpi_thread_state *thread)
739
740{
741 ACPI_FUNCTION_NAME ("ds_get_current_walk_state");
742
743
744 if (!thread) {
745 return (NULL);
746 }
747
748 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Current walk_state %p\n",
749 thread->walk_state_list));
750
751 return (thread->walk_state_list);
752}
753
754
755/*******************************************************************************
756 *
757 * FUNCTION: acpi_ds_push_walk_state
758 *
759 * PARAMETERS: walk_state - State to push
760 * walk_list - The list that owns the walk stack
761 *
762 * RETURN: None
763 *
764 * DESCRIPTION: Place the walk_state at the head of the state list.
765 *
766 ******************************************************************************/
767
768void
769acpi_ds_push_walk_state (
770 struct acpi_walk_state *walk_state,
771 struct acpi_thread_state *thread)
772{
773 ACPI_FUNCTION_TRACE ("ds_push_walk_state");
774
775
776 walk_state->next = thread->walk_state_list;
777 thread->walk_state_list = walk_state;
778
779 return_VOID;
780}
781
782
783/*******************************************************************************
784 *
785 * FUNCTION: acpi_ds_pop_walk_state
786 *
787 * PARAMETERS: walk_list - The list that owns the walk stack
788 *
789 * RETURN: A walk_state object popped from the stack
790 *
791 * DESCRIPTION: Remove and return the walkstate object that is at the head of
792 * the walk stack for the given walk list. NULL indicates that
793 * the list is empty.
794 *
795 ******************************************************************************/
796
797struct acpi_walk_state *
798acpi_ds_pop_walk_state (
799 struct acpi_thread_state *thread)
800{
801 struct acpi_walk_state *walk_state;
802
803
804 ACPI_FUNCTION_TRACE ("ds_pop_walk_state");
805
806
807 walk_state = thread->walk_state_list;
808
809 if (walk_state) {
810 /* Next walk state becomes the current walk state */
811
812 thread->walk_state_list = walk_state->next;
813
814 /*
815 * Don't clear the NEXT field, this serves as an indicator
816 * that there is a parent WALK STATE
817 * NO: walk_state->Next = NULL;
818 */
819 }
820
821 return_PTR (walk_state);
822}
823
824
825/*******************************************************************************
826 *
827 * FUNCTION: acpi_ds_create_walk_state
828 *
829 * PARAMETERS: Origin - Starting point for this walk
830 * Thread - Current thread state
831 *
832 * RETURN: Pointer to the new walk state.
833 *
834 * DESCRIPTION: Allocate and initialize a new walk state. The current walk
835 * state is set to this new state.
836 *
837 ******************************************************************************/
838
839struct acpi_walk_state *
840acpi_ds_create_walk_state (
841 acpi_owner_id owner_id,
842 union acpi_parse_object *origin,
843 union acpi_operand_object *mth_desc,
844 struct acpi_thread_state *thread)
845{
846 struct acpi_walk_state *walk_state;
847 acpi_status status;
848
849
850 ACPI_FUNCTION_TRACE ("ds_create_walk_state");
851
852
853 walk_state = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_WALK);
854 if (!walk_state) {
855 return_PTR (NULL);
856 }
857
858 walk_state->data_type = ACPI_DESC_TYPE_WALK;
859 walk_state->owner_id = owner_id;
860 walk_state->origin = origin;
861 walk_state->method_desc = mth_desc;
862 walk_state->thread = thread;
863
864 walk_state->parser_state.start_op = origin;
865
866 /* Init the method args/local */
867
868#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
869 acpi_ds_method_data_init (walk_state);
870#endif
871
872 /* Create an initial result stack entry */
873
874 status = acpi_ds_result_stack_push (walk_state);
875 if (ACPI_FAILURE (status)) {
876 acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state);
877 return_PTR (NULL);
878 }
879
880 /* Put the new state at the head of the walk list */
881
882 if (thread) {
883 acpi_ds_push_walk_state (walk_state, thread);
884 }
885
886 return_PTR (walk_state);
887}
888
889
890/*******************************************************************************
891 *
892 * FUNCTION: acpi_ds_init_aml_walk
893 *
894 * PARAMETERS: walk_state - New state to be initialized
895 * Op - Current parse op
896 * method_node - Control method NS node, if any
897 * aml_start - Start of AML
898 * aml_length - Length of AML
899 * Params - Method args, if any
900 * return_obj_desc - Where to store a return object, if any
901 * pass_number - 1, 2, or 3
902 *
903 * RETURN: Status
904 *
905 * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk
906 *
907 ******************************************************************************/
908
909acpi_status
910acpi_ds_init_aml_walk (
911 struct acpi_walk_state *walk_state,
912 union acpi_parse_object *op,
913 struct acpi_namespace_node *method_node,
914 u8 *aml_start,
915 u32 aml_length,
916 struct acpi_parameter_info *info,
917 u32 pass_number)
918{
919 acpi_status status;
920 struct acpi_parse_state *parser_state = &walk_state->parser_state;
921 union acpi_parse_object *extra_op;
922
923
924 ACPI_FUNCTION_TRACE ("ds_init_aml_walk");
925
926
927 walk_state->parser_state.aml =
928 walk_state->parser_state.aml_start = aml_start;
929 walk_state->parser_state.aml_end =
930 walk_state->parser_state.pkg_end = aml_start + aml_length;
931
932 /* The next_op of the next_walk will be the beginning of the method */
933
934 walk_state->next_op = NULL;
935
936 if (info) {
937 if (info->parameter_type == ACPI_PARAM_GPE) {
938 walk_state->gpe_event_info = ACPI_CAST_PTR (struct acpi_gpe_event_info,
939 info->parameters);
940 }
941 else {
942 walk_state->params = info->parameters;
943 walk_state->caller_return_desc = &info->return_object;
944 }
945 }
946
947 status = acpi_ps_init_scope (&walk_state->parser_state, op);
948 if (ACPI_FAILURE (status)) {
949 return_ACPI_STATUS (status);
950 }
951
952 if (method_node) {
953 walk_state->parser_state.start_node = method_node;
954 walk_state->walk_type = ACPI_WALK_METHOD;
955 walk_state->method_node = method_node;
956 walk_state->method_desc = acpi_ns_get_attached_object (method_node);
957
958 /* Push start scope on scope stack and make it current */
959
960 status = acpi_ds_scope_stack_push (method_node, ACPI_TYPE_METHOD, walk_state);
961 if (ACPI_FAILURE (status)) {
962 return_ACPI_STATUS (status);
963 }
964
965 /* Init the method arguments */
966
967 status = acpi_ds_method_data_init_args (walk_state->params, ACPI_METHOD_NUM_ARGS, walk_state);
968 if (ACPI_FAILURE (status)) {
969 return_ACPI_STATUS (status);
970 }
971 }
972 else {
973 /*
974 * Setup the current scope.
975 * Find a Named Op that has a namespace node associated with it.
976 * search upwards from this Op. Current scope is the first
977 * Op with a namespace node.
978 */
979 extra_op = parser_state->start_op;
980 while (extra_op && !extra_op->common.node) {
981 extra_op = extra_op->common.parent;
982 }
983
984 if (!extra_op) {
985 parser_state->start_node = NULL;
986 }
987 else {
988 parser_state->start_node = extra_op->common.node;
989 }
990
991 if (parser_state->start_node) {
992 /* Push start scope on scope stack and make it current */
993
994 status = acpi_ds_scope_stack_push (parser_state->start_node,
995 parser_state->start_node->type, walk_state);
996 if (ACPI_FAILURE (status)) {
997 return_ACPI_STATUS (status);
998 }
999 }
1000 }
1001
1002 status = acpi_ds_init_callbacks (walk_state, pass_number);
1003 return_ACPI_STATUS (status);
1004}
1005
1006
1007/*******************************************************************************
1008 *
1009 * FUNCTION: acpi_ds_delete_walk_state
1010 *
1011 * PARAMETERS: walk_state - State to delete
1012 *
1013 * RETURN: Status
1014 *
1015 * DESCRIPTION: Delete a walk state including all internal data structures
1016 *
1017 ******************************************************************************/
1018
1019void
1020acpi_ds_delete_walk_state (
1021 struct acpi_walk_state *walk_state)
1022{
1023 union acpi_generic_state *state;
1024
1025
1026 ACPI_FUNCTION_TRACE_PTR ("ds_delete_walk_state", walk_state);
1027
1028
1029 if (!walk_state) {
1030 return;
1031 }
1032
1033 if (walk_state->data_type != ACPI_DESC_TYPE_WALK) {
1034 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p is not a valid walk state\n", walk_state));
1035 return;
1036 }
1037
1038 if (walk_state->parser_state.scope) {
1039 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p walk still has a scope list\n", walk_state));
1040 }
1041
1042 /* Always must free any linked control states */
1043
1044 while (walk_state->control_state) {
1045 state = walk_state->control_state;
1046 walk_state->control_state = state->common.next;
1047
1048 acpi_ut_delete_generic_state (state);
1049 }
1050
1051 /* Always must free any linked parse states */
1052
1053 while (walk_state->scope_info) {
1054 state = walk_state->scope_info;
1055 walk_state->scope_info = state->common.next;
1056
1057 acpi_ut_delete_generic_state (state);
1058 }
1059
1060 /* Always must free any stacked result states */
1061
1062 while (walk_state->results) {
1063 state = walk_state->results;
1064 walk_state->results = state->common.next;
1065
1066 acpi_ut_delete_generic_state (state);
1067 }
1068
1069 acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state);
1070 return_VOID;
1071}
1072
1073
1074#ifdef ACPI_ENABLE_OBJECT_CACHE
1075/******************************************************************************
1076 *
1077 * FUNCTION: acpi_ds_delete_walk_state_cache
1078 *
1079 * PARAMETERS: None
1080 *
1081 * RETURN: Status
1082 *
1083 * DESCRIPTION: Purge the global state object cache. Used during subsystem
1084 * termination.
1085 *
1086 ******************************************************************************/
1087
1088void
1089acpi_ds_delete_walk_state_cache (
1090 void)
1091{
1092 ACPI_FUNCTION_TRACE ("ds_delete_walk_state_cache");
1093
1094
1095 acpi_ut_delete_generic_cache (ACPI_MEM_LIST_WALK);
1096 return_VOID;
1097}
1098#endif
1099
1100
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
new file mode 100644
index 000000000000..fdf143b405be
--- /dev/null
+++ b/drivers/acpi/ec.c
@@ -0,0 +1,1024 @@
1/*
2 * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 38 $)
3 *
4 * Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
5 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
6 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 */
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/init.h>
30#include <linux/types.h>
31#include <linux/delay.h>
32#include <linux/proc_fs.h>
33#include <linux/seq_file.h>
34#include <asm/io.h>
35#include <acpi/acpi_bus.h>
36#include <acpi/acpi_drivers.h>
37#include <acpi/actypes.h>
38
39#define _COMPONENT ACPI_EC_COMPONENT
40ACPI_MODULE_NAME ("acpi_ec")
41
42#define ACPI_EC_COMPONENT 0x00100000
43#define ACPI_EC_CLASS "embedded_controller"
44#define ACPI_EC_HID "PNP0C09"
45#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver"
46#define ACPI_EC_DEVICE_NAME "Embedded Controller"
47#define ACPI_EC_FILE_INFO "info"
48
49
50#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
51#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
52#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */
53
54#define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */
55#define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */
56
57#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */
58#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */
59#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
60
61#define ACPI_EC_COMMAND_READ 0x80
62#define ACPI_EC_COMMAND_WRITE 0x81
63#define ACPI_EC_COMMAND_QUERY 0x84
64
65static int acpi_ec_add (struct acpi_device *device);
66static int acpi_ec_remove (struct acpi_device *device, int type);
67static int acpi_ec_start (struct acpi_device *device);
68static int acpi_ec_stop (struct acpi_device *device, int type);
69
70static struct acpi_driver acpi_ec_driver = {
71 .name = ACPI_EC_DRIVER_NAME,
72 .class = ACPI_EC_CLASS,
73 .ids = ACPI_EC_HID,
74 .ops = {
75 .add = acpi_ec_add,
76 .remove = acpi_ec_remove,
77 .start = acpi_ec_start,
78 .stop = acpi_ec_stop,
79 },
80};
81
82struct acpi_ec {
83 acpi_handle handle;
84 unsigned long uid;
85 unsigned long gpe_bit;
86 struct acpi_generic_address status_addr;
87 struct acpi_generic_address command_addr;
88 struct acpi_generic_address data_addr;
89 unsigned long global_lock;
90 spinlock_t lock;
91};
92
93/* If we find an EC via the ECDT, we need to keep a ptr to its context */
94static struct acpi_ec *ec_ecdt;
95
96/* External interfaces use first EC only, so remember */
97static struct acpi_device *first_ec;
98
99/* --------------------------------------------------------------------------
100 Transaction Management
101 -------------------------------------------------------------------------- */
102
103static int
104acpi_ec_wait (
105 struct acpi_ec *ec,
106 u8 event)
107{
108 u32 acpi_ec_status = 0;
109 u32 i = ACPI_EC_UDELAY_COUNT;
110
111 if (!ec)
112 return -EINVAL;
113
114 /* Poll the EC status register waiting for the event to occur. */
115 switch (event) {
116 case ACPI_EC_EVENT_OBF:
117 do {
118 acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr);
119 if (acpi_ec_status & ACPI_EC_FLAG_OBF)
120 return 0;
121 udelay(ACPI_EC_UDELAY);
122 } while (--i>0);
123 break;
124 case ACPI_EC_EVENT_IBE:
125 do {
126 acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr);
127 if (!(acpi_ec_status & ACPI_EC_FLAG_IBF))
128 return 0;
129 udelay(ACPI_EC_UDELAY);
130 } while (--i>0);
131 break;
132 default:
133 return -EINVAL;
134 }
135
136 return -ETIME;
137}
138
139
140static int
141acpi_ec_read (
142 struct acpi_ec *ec,
143 u8 address,
144 u32 *data)
145{
146 acpi_status status = AE_OK;
147 int result = 0;
148 unsigned long flags = 0;
149 u32 glk = 0;
150
151 ACPI_FUNCTION_TRACE("acpi_ec_read");
152
153 if (!ec || !data)
154 return_VALUE(-EINVAL);
155
156 *data = 0;
157
158 if (ec->global_lock) {
159 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
160 if (ACPI_FAILURE(status))
161 return_VALUE(-ENODEV);
162 }
163
164 spin_lock_irqsave(&ec->lock, flags);
165
166 acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr);
167 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
168 if (result)
169 goto end;
170
171 acpi_hw_low_level_write(8, address, &ec->data_addr);
172 result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
173 if (result)
174 goto end;
175
176
177 acpi_hw_low_level_read(8, data, &ec->data_addr);
178
179 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
180 *data, address));
181
182end:
183 spin_unlock_irqrestore(&ec->lock, flags);
184
185 if (ec->global_lock)
186 acpi_release_global_lock(glk);
187
188 return_VALUE(result);
189}
190
191
192static int
193acpi_ec_write (
194 struct acpi_ec *ec,
195 u8 address,
196 u8 data)
197{
198 int result = 0;
199 acpi_status status = AE_OK;
200 unsigned long flags = 0;
201 u32 glk = 0;
202
203 ACPI_FUNCTION_TRACE("acpi_ec_write");
204
205 if (!ec)
206 return_VALUE(-EINVAL);
207
208 if (ec->global_lock) {
209 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
210 if (ACPI_FAILURE(status))
211 return_VALUE(-ENODEV);
212 }
213
214 spin_lock_irqsave(&ec->lock, flags);
215
216 acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr);
217 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
218 if (result)
219 goto end;
220
221 acpi_hw_low_level_write(8, address, &ec->data_addr);
222 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
223 if (result)
224 goto end;
225
226 acpi_hw_low_level_write(8, data, &ec->data_addr);
227 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
228 if (result)
229 goto end;
230
231 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
232 data, address));
233
234end:
235 spin_unlock_irqrestore(&ec->lock, flags);
236
237 if (ec->global_lock)
238 acpi_release_global_lock(glk);
239
240 return_VALUE(result);
241}
242
243/*
244 * Externally callable EC access functions. For now, assume 1 EC only
245 */
246int
247ec_read(u8 addr, u8 *val)
248{
249 struct acpi_ec *ec;
250 int err;
251 u32 temp_data;
252
253 if (!first_ec)
254 return -ENODEV;
255
256 ec = acpi_driver_data(first_ec);
257
258 err = acpi_ec_read(ec, addr, &temp_data);
259
260 if (!err) {
261 *val = temp_data;
262 return 0;
263 }
264 else
265 return err;
266}
267EXPORT_SYMBOL(ec_read);
268
269int
270ec_write(u8 addr, u8 val)
271{
272 struct acpi_ec *ec;
273 int err;
274
275 if (!first_ec)
276 return -ENODEV;
277
278 ec = acpi_driver_data(first_ec);
279
280 err = acpi_ec_write(ec, addr, val);
281
282 return err;
283}
284EXPORT_SYMBOL(ec_write);
285
286
287static int
288acpi_ec_query (
289 struct acpi_ec *ec,
290 u32 *data)
291{
292 int result = 0;
293 acpi_status status = AE_OK;
294 unsigned long flags = 0;
295 u32 glk = 0;
296
297 ACPI_FUNCTION_TRACE("acpi_ec_query");
298
299 if (!ec || !data)
300 return_VALUE(-EINVAL);
301
302 *data = 0;
303
304 if (ec->global_lock) {
305 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
306 if (ACPI_FAILURE(status))
307 return_VALUE(-ENODEV);
308 }
309
310 /*
311 * Query the EC to find out which _Qxx method we need to evaluate.
312 * Note that successful completion of the query causes the ACPI_EC_SCI
313 * bit to be cleared (and thus clearing the interrupt source).
314 */
315 spin_lock_irqsave(&ec->lock, flags);
316
317 acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr);
318 result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
319 if (result)
320 goto end;
321
322 acpi_hw_low_level_read(8, data, &ec->data_addr);
323 if (!*data)
324 result = -ENODATA;
325
326end:
327 spin_unlock_irqrestore(&ec->lock, flags);
328
329 if (ec->global_lock)
330 acpi_release_global_lock(glk);
331
332 return_VALUE(result);
333}
334
335
336/* --------------------------------------------------------------------------
337 Event Management
338 -------------------------------------------------------------------------- */
339
340struct acpi_ec_query_data {
341 acpi_handle handle;
342 u8 data;
343};
344
345static void
346acpi_ec_gpe_query (
347 void *ec_cxt)
348{
349 struct acpi_ec *ec = (struct acpi_ec *) ec_cxt;
350 u32 value = 0;
351 unsigned long flags = 0;
352 static char object_name[5] = {'_','Q','0','0','\0'};
353 const char hex[] = {'0','1','2','3','4','5','6','7',
354 '8','9','A','B','C','D','E','F'};
355
356 ACPI_FUNCTION_TRACE("acpi_ec_gpe_query");
357
358 if (!ec_cxt)
359 goto end;
360
361 spin_lock_irqsave(&ec->lock, flags);
362 acpi_hw_low_level_read(8, &value, &ec->command_addr);
363 spin_unlock_irqrestore(&ec->lock, flags);
364
365 /* TBD: Implement asynch events!
366 * NOTE: All we care about are EC-SCI's. Other EC events are
367 * handled via polling (yuck!). This is because some systems
368 * treat EC-SCIs as level (versus EDGE!) triggered, preventing
369 * a purely interrupt-driven approach (grumble, grumble).
370 */
371 if (!(value & ACPI_EC_FLAG_SCI))
372 goto end;
373
374 if (acpi_ec_query(ec, &value))
375 goto end;
376
377 object_name[2] = hex[((value >> 4) & 0x0F)];
378 object_name[3] = hex[(value & 0x0F)];
379
380 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
381
382 acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
383
384end:
385 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
386}
387
388static u32
389acpi_ec_gpe_handler (
390 void *data)
391{
392 acpi_status status = AE_OK;
393 struct acpi_ec *ec = (struct acpi_ec *) data;
394
395 if (!ec)
396 return ACPI_INTERRUPT_NOT_HANDLED;
397
398 acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
399
400 status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
401 acpi_ec_gpe_query, ec);
402
403 if (status == AE_OK)
404 return ACPI_INTERRUPT_HANDLED;
405 else
406 return ACPI_INTERRUPT_NOT_HANDLED;
407}
408
409/* --------------------------------------------------------------------------
410 Address Space Management
411 -------------------------------------------------------------------------- */
412
413static acpi_status
414acpi_ec_space_setup (
415 acpi_handle region_handle,
416 u32 function,
417 void *handler_context,
418 void **return_context)
419{
420 /*
421 * The EC object is in the handler context and is needed
422 * when calling the acpi_ec_space_handler.
423 */
424 if(function == ACPI_REGION_DEACTIVATE)
425 *return_context = NULL;
426 else
427 *return_context = handler_context;
428
429 return AE_OK;
430}
431
432
433static acpi_status
434acpi_ec_space_handler (
435 u32 function,
436 acpi_physical_address address,
437 u32 bit_width,
438 acpi_integer *value,
439 void *handler_context,
440 void *region_context)
441{
442 int result = 0;
443 struct acpi_ec *ec = NULL;
444 u32 temp = 0;
445 acpi_integer f_v = 0;
446 int i = 0;
447
448 ACPI_FUNCTION_TRACE("acpi_ec_space_handler");
449
450 if ((address > 0xFF) || !value || !handler_context)
451 return_VALUE(AE_BAD_PARAMETER);
452
453 if(bit_width != 8) {
454 printk(KERN_WARNING PREFIX "acpi_ec_space_handler: bit_width should be 8\n");
455 if (acpi_strict)
456 return_VALUE(AE_BAD_PARAMETER);
457 }
458
459 ec = (struct acpi_ec *) handler_context;
460
461next_byte:
462 switch (function) {
463 case ACPI_READ:
464 result = acpi_ec_read(ec, (u8) address, &temp);
465 *value = (acpi_integer) temp;
466 break;
467 case ACPI_WRITE:
468 result = acpi_ec_write(ec, (u8) address, (u8) *value);
469 break;
470 default:
471 result = -EINVAL;
472 goto out;
473 break;
474 }
475
476 bit_width -= 8;
477 if(bit_width){
478
479 if(function == ACPI_READ)
480 f_v |= (acpi_integer) (*value) << 8*i;
481 if(function == ACPI_WRITE)
482 (*value) >>=8;
483 i++;
484 goto next_byte;
485 }
486
487
488 if(function == ACPI_READ){
489 f_v |= (acpi_integer) (*value) << 8*i;
490 *value = f_v;
491 }
492
493
494out:
495 switch (result) {
496 case -EINVAL:
497 return_VALUE(AE_BAD_PARAMETER);
498 break;
499 case -ENODEV:
500 return_VALUE(AE_NOT_FOUND);
501 break;
502 case -ETIME:
503 return_VALUE(AE_TIME);
504 break;
505 default:
506 return_VALUE(AE_OK);
507 }
508
509
510}
511
512
513/* --------------------------------------------------------------------------
514 FS Interface (/proc)
515 -------------------------------------------------------------------------- */
516
517static struct proc_dir_entry *acpi_ec_dir;
518
519
520static int
521acpi_ec_read_info (struct seq_file *seq, void *offset)
522{
523 struct acpi_ec *ec = (struct acpi_ec *) seq->private;
524
525 ACPI_FUNCTION_TRACE("acpi_ec_read_info");
526
527 if (!ec)
528 goto end;
529
530 seq_printf(seq, "gpe bit: 0x%02x\n",
531 (u32) ec->gpe_bit);
532 seq_printf(seq, "ports: 0x%02x, 0x%02x\n",
533 (u32) ec->status_addr.address, (u32) ec->data_addr.address);
534 seq_printf(seq, "use global lock: %s\n",
535 ec->global_lock?"yes":"no");
536
537end:
538 return_VALUE(0);
539}
540
541static int acpi_ec_info_open_fs(struct inode *inode, struct file *file)
542{
543 return single_open(file, acpi_ec_read_info, PDE(inode)->data);
544}
545
546static struct file_operations acpi_ec_info_ops = {
547 .open = acpi_ec_info_open_fs,
548 .read = seq_read,
549 .llseek = seq_lseek,
550 .release = single_release,
551 .owner = THIS_MODULE,
552};
553
554static int
555acpi_ec_add_fs (
556 struct acpi_device *device)
557{
558 struct proc_dir_entry *entry = NULL;
559
560 ACPI_FUNCTION_TRACE("acpi_ec_add_fs");
561
562 if (!acpi_device_dir(device)) {
563 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
564 acpi_ec_dir);
565 if (!acpi_device_dir(device))
566 return_VALUE(-ENODEV);
567 }
568
569 entry = create_proc_entry(ACPI_EC_FILE_INFO, S_IRUGO,
570 acpi_device_dir(device));
571 if (!entry)
572 ACPI_DEBUG_PRINT((ACPI_DB_WARN,
573 "Unable to create '%s' fs entry\n",
574 ACPI_EC_FILE_INFO));
575 else {
576 entry->proc_fops = &acpi_ec_info_ops;
577 entry->data = acpi_driver_data(device);
578 entry->owner = THIS_MODULE;
579 }
580
581 return_VALUE(0);
582}
583
584
585static int
586acpi_ec_remove_fs (
587 struct acpi_device *device)
588{
589 ACPI_FUNCTION_TRACE("acpi_ec_remove_fs");
590
591 if (acpi_device_dir(device)) {
592 remove_proc_entry(ACPI_EC_FILE_INFO, acpi_device_dir(device));
593 remove_proc_entry(acpi_device_bid(device), acpi_ec_dir);
594 acpi_device_dir(device) = NULL;
595 }
596
597 return_VALUE(0);
598}
599
600
601/* --------------------------------------------------------------------------
602 Driver Interface
603 -------------------------------------------------------------------------- */
604
605static int
606acpi_ec_add (
607 struct acpi_device *device)
608{
609 int result = 0;
610 acpi_status status = AE_OK;
611 struct acpi_ec *ec = NULL;
612 unsigned long uid;
613
614 ACPI_FUNCTION_TRACE("acpi_ec_add");
615
616 if (!device)
617 return_VALUE(-EINVAL);
618
619 ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
620 if (!ec)
621 return_VALUE(-ENOMEM);
622 memset(ec, 0, sizeof(struct acpi_ec));
623
624 ec->handle = device->handle;
625 ec->uid = -1;
626 spin_lock_init(&ec->lock);
627 strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
628 strcpy(acpi_device_class(device), ACPI_EC_CLASS);
629 acpi_driver_data(device) = ec;
630
631 /* Use the global lock for all EC transactions? */
632 acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock);
633
634 /* If our UID matches the UID for the ECDT-enumerated EC,
635 we now have the *real* EC info, so kill the makeshift one.*/
636 acpi_evaluate_integer(ec->handle, "_UID", NULL, &uid);
637 if (ec_ecdt && ec_ecdt->uid == uid) {
638 acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
639 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
640
641 acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler);
642
643 kfree(ec_ecdt);
644 }
645
646 /* Get GPE bit assignment (EC events). */
647 /* TODO: Add support for _GPE returning a package */
648 status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit);
649 if (ACPI_FAILURE(status)) {
650 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
651 "Error obtaining GPE bit assignment\n"));
652 result = -ENODEV;
653 goto end;
654 }
655
656 result = acpi_ec_add_fs(device);
657 if (result)
658 goto end;
659
660 printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
661 acpi_device_name(device), acpi_device_bid(device),
662 (u32) ec->gpe_bit);
663
664 if (!first_ec)
665 first_ec = device;
666
667end:
668 if (result)
669 kfree(ec);
670
671 return_VALUE(result);
672}
673
674
675static int
676acpi_ec_remove (
677 struct acpi_device *device,
678 int type)
679{
680 struct acpi_ec *ec = NULL;
681
682 ACPI_FUNCTION_TRACE("acpi_ec_remove");
683
684 if (!device)
685 return_VALUE(-EINVAL);
686
687 ec = acpi_driver_data(device);
688
689 acpi_ec_remove_fs(device);
690
691 kfree(ec);
692
693 return_VALUE(0);
694}
695
696
697static acpi_status
698acpi_ec_io_ports (
699 struct acpi_resource *resource,
700 void *context)
701{
702 struct acpi_ec *ec = (struct acpi_ec *) context;
703 struct acpi_generic_address *addr;
704
705 if (resource->id != ACPI_RSTYPE_IO) {
706 return AE_OK;
707 }
708
709 /*
710 * The first address region returned is the data port, and
711 * the second address region returned is the status/command
712 * port.
713 */
714 if (ec->data_addr.register_bit_width == 0) {
715 addr = &ec->data_addr;
716 } else if (ec->command_addr.register_bit_width == 0) {
717 addr = &ec->command_addr;
718 } else {
719 return AE_CTRL_TERMINATE;
720 }
721
722 addr->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO;
723 addr->register_bit_width = 8;
724 addr->register_bit_offset = 0;
725 addr->address = resource->data.io.min_base_address;
726
727 return AE_OK;
728}
729
730
731static int
732acpi_ec_start (
733 struct acpi_device *device)
734{
735 acpi_status status = AE_OK;
736 struct acpi_ec *ec = NULL;
737
738 ACPI_FUNCTION_TRACE("acpi_ec_start");
739
740 if (!device)
741 return_VALUE(-EINVAL);
742
743 ec = acpi_driver_data(device);
744
745 if (!ec)
746 return_VALUE(-EINVAL);
747
748 /*
749 * Get I/O port addresses. Convert to GAS format.
750 */
751 status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS,
752 acpi_ec_io_ports, ec);
753 if (ACPI_FAILURE(status) || ec->command_addr.register_bit_width == 0) {
754 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses"));
755 return_VALUE(-ENODEV);
756 }
757
758 ec->status_addr = ec->command_addr;
759
760 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n",
761 (u32) ec->gpe_bit, (u32) ec->command_addr.address,
762 (u32) ec->data_addr.address));
763
764 /*
765 * Install GPE handler
766 */
767 status = acpi_install_gpe_handler(NULL, ec->gpe_bit,
768 ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec);
769 if (ACPI_FAILURE(status)) {
770 return_VALUE(-ENODEV);
771 }
772 acpi_set_gpe_type (NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
773 acpi_enable_gpe (NULL, ec->gpe_bit, ACPI_NOT_ISR);
774
775 status = acpi_install_address_space_handler (ec->handle,
776 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
777 &acpi_ec_space_setup, ec);
778 if (ACPI_FAILURE(status)) {
779 acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler);
780 return_VALUE(-ENODEV);
781 }
782
783 return_VALUE(AE_OK);
784}
785
786
787static int
788acpi_ec_stop (
789 struct acpi_device *device,
790 int type)
791{
792 acpi_status status = AE_OK;
793 struct acpi_ec *ec = NULL;
794
795 ACPI_FUNCTION_TRACE("acpi_ec_stop");
796
797 if (!device)
798 return_VALUE(-EINVAL);
799
800 ec = acpi_driver_data(device);
801
802 status = acpi_remove_address_space_handler(ec->handle,
803 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
804 if (ACPI_FAILURE(status))
805 return_VALUE(-ENODEV);
806
807 status = acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler);
808 if (ACPI_FAILURE(status))
809 return_VALUE(-ENODEV);
810
811 return_VALUE(0);
812}
813
814static acpi_status __init
815acpi_fake_ecdt_callback (
816 acpi_handle handle,
817 u32 Level,
818 void *context,
819 void **retval)
820{
821 acpi_status status;
822
823 status = acpi_walk_resources(handle, METHOD_NAME__CRS,
824 acpi_ec_io_ports, ec_ecdt);
825 if (ACPI_FAILURE(status))
826 return status;
827 ec_ecdt->status_addr = ec_ecdt->command_addr;
828
829 ec_ecdt->uid = -1;
830 acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid);
831
832 status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe_bit);
833 if (ACPI_FAILURE(status))
834 return status;
835 spin_lock_init(&ec_ecdt->lock);
836 ec_ecdt->global_lock = TRUE;
837 ec_ecdt->handle = handle;
838
839 printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
840 (u32) ec_ecdt->gpe_bit, (u32) ec_ecdt->command_addr.address,
841 (u32) ec_ecdt->data_addr.address);
842
843 return AE_CTRL_TERMINATE;
844}
845
846/*
847 * Some BIOS (such as some from Gateway laptops) access EC region very early
848 * such as in BAT0._INI or EC._INI before an EC device is found and
849 * do not provide an ECDT. According to ACPI spec, ECDT isn't mandatorily
850 * required, but if EC regison is accessed early, it is required.
851 * The routine tries to workaround the BIOS bug by pre-scan EC device
852 * It assumes that _CRS, _HID, _GPE, _UID methods of EC don't touch any
853 * op region (since _REG isn't invoked yet). The assumption is true for
854 * all systems found.
855 */
856static int __init
857acpi_ec_fake_ecdt(void)
858{
859 acpi_status status;
860 int ret = 0;
861
862 printk(KERN_INFO PREFIX "Try to make an fake ECDT\n");
863
864 ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
865 if (!ec_ecdt) {
866 ret = -ENOMEM;
867 goto error;
868 }
869 memset(ec_ecdt, 0, sizeof(struct acpi_ec));
870
871 status = acpi_get_devices (ACPI_EC_HID,
872 acpi_fake_ecdt_callback,
873 NULL,
874 NULL);
875 if (ACPI_FAILURE(status)) {
876 kfree(ec_ecdt);
877 ec_ecdt = NULL;
878 ret = -ENODEV;
879 goto error;
880 }
881 return 0;
882error:
883 printk(KERN_ERR PREFIX "Can't make an fake ECDT\n");
884 return ret;
885}
886
887static int __init
888acpi_ec_get_real_ecdt(void)
889{
890 acpi_status status;
891 struct acpi_table_ecdt *ecdt_ptr;
892
893 status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
894 (struct acpi_table_header **) &ecdt_ptr);
895 if (ACPI_FAILURE(status))
896 return -ENODEV;
897
898 printk(KERN_INFO PREFIX "Found ECDT\n");
899
900 /*
901 * Generate a temporary ec context to use until the namespace is scanned
902 */
903 ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
904 if (!ec_ecdt)
905 return -ENOMEM;
906 memset(ec_ecdt, 0, sizeof(struct acpi_ec));
907
908 ec_ecdt->command_addr = ecdt_ptr->ec_control;
909 ec_ecdt->status_addr = ecdt_ptr->ec_control;
910 ec_ecdt->data_addr = ecdt_ptr->ec_data;
911 ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit;
912 spin_lock_init(&ec_ecdt->lock);
913 /* use the GL just to be safe */
914 ec_ecdt->global_lock = TRUE;
915 ec_ecdt->uid = ecdt_ptr->uid;
916
917 status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle);
918 if (ACPI_FAILURE(status)) {
919 goto error;
920 }
921
922 return 0;
923error:
924 printk(KERN_ERR PREFIX "Could not use ECDT\n");
925 kfree(ec_ecdt);
926 ec_ecdt = NULL;
927
928 return -ENODEV;
929}
930
931static int __initdata acpi_fake_ecdt_enabled;
932int __init
933acpi_ec_ecdt_probe (void)
934{
935 acpi_status status;
936 int ret;
937
938 ret = acpi_ec_get_real_ecdt();
939 /* Try to make a fake ECDT */
940 if (ret && acpi_fake_ecdt_enabled) {
941 ret = acpi_ec_fake_ecdt();
942 }
943
944 if (ret)
945 return 0;
946
947 /*
948 * Install GPE handler
949 */
950 status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit,
951 ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler,
952 ec_ecdt);
953 if (ACPI_FAILURE(status)) {
954 goto error;
955 }
956 acpi_set_gpe_type (NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
957 acpi_enable_gpe (NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR);
958
959 status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT,
960 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
961 &acpi_ec_space_setup, ec_ecdt);
962 if (ACPI_FAILURE(status)) {
963 acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
964 &acpi_ec_gpe_handler);
965 goto error;
966 }
967
968 return 0;
969
970error:
971 printk(KERN_ERR PREFIX "Could not use ECDT\n");
972 kfree(ec_ecdt);
973 ec_ecdt = NULL;
974
975 return -ENODEV;
976}
977
978
979static int __init acpi_ec_init (void)
980{
981 int result = 0;
982
983 ACPI_FUNCTION_TRACE("acpi_ec_init");
984
985 if (acpi_disabled)
986 return_VALUE(0);
987
988 acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir);
989 if (!acpi_ec_dir)
990 return_VALUE(-ENODEV);
991
992 /* Now register the driver for the EC */
993 result = acpi_bus_register_driver(&acpi_ec_driver);
994 if (result < 0) {
995 remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
996 return_VALUE(-ENODEV);
997 }
998
999 return_VALUE(result);
1000}
1001
1002subsys_initcall(acpi_ec_init);
1003
1004/* EC driver currently not unloadable */
1005#if 0
1006static void __exit
1007acpi_ec_exit (void)
1008{
1009 ACPI_FUNCTION_TRACE("acpi_ec_exit");
1010
1011 acpi_bus_unregister_driver(&acpi_ec_driver);
1012
1013 remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
1014
1015 return_VOID;
1016}
1017#endif /* 0 */
1018
1019static int __init acpi_fake_ecdt_setup(char *str)
1020{
1021 acpi_fake_ecdt_enabled = 1;
1022 return 0;
1023}
1024__setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
new file mode 100644
index 000000000000..43c49f66a328
--- /dev/null
+++ b/drivers/acpi/event.c
@@ -0,0 +1,140 @@
1/*
2 * event.c - exporting ACPI events via procfs
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 */
8
9#include <linux/spinlock.h>
10#include <linux/proc_fs.h>
11#include <linux/init.h>
12#include <linux/poll.h>
13#include <acpi/acpi_drivers.h>
14
15#define _COMPONENT ACPI_SYSTEM_COMPONENT
16ACPI_MODULE_NAME ("event")
17
18/* Global vars for handling event proc entry */
19static DEFINE_SPINLOCK(acpi_system_event_lock);
20int event_is_open = 0;
21extern struct list_head acpi_bus_event_list;
22extern wait_queue_head_t acpi_bus_event_queue;
23
24static int
25acpi_system_open_event(struct inode *inode, struct file *file)
26{
27 spin_lock_irq (&acpi_system_event_lock);
28
29 if(event_is_open)
30 goto out_busy;
31
32 event_is_open = 1;
33
34 spin_unlock_irq (&acpi_system_event_lock);
35 return 0;
36
37out_busy:
38 spin_unlock_irq (&acpi_system_event_lock);
39 return -EBUSY;
40}
41
42static ssize_t
43acpi_system_read_event (
44 struct file *file,
45 char __user *buffer,
46 size_t count,
47 loff_t *ppos)
48{
49 int result = 0;
50 struct acpi_bus_event event;
51 static char str[ACPI_MAX_STRING];
52 static int chars_remaining = 0;
53 static char *ptr;
54
55
56 ACPI_FUNCTION_TRACE("acpi_system_read_event");
57
58 if (!chars_remaining) {
59 memset(&event, 0, sizeof(struct acpi_bus_event));
60
61 if ((file->f_flags & O_NONBLOCK)
62 && (list_empty(&acpi_bus_event_list)))
63 return_VALUE(-EAGAIN);
64
65 result = acpi_bus_receive_event(&event);
66 if (result) {
67 return_VALUE(-EIO);
68 }
69
70 chars_remaining = sprintf(str, "%s %s %08x %08x\n",
71 event.device_class?event.device_class:"<unknown>",
72 event.bus_id?event.bus_id:"<unknown>",
73 event.type, event.data);
74 ptr = str;
75 }
76
77 if (chars_remaining < count) {
78 count = chars_remaining;
79 }
80
81 if (copy_to_user(buffer, ptr, count))
82 return_VALUE(-EFAULT);
83
84 *ppos += count;
85 chars_remaining -= count;
86 ptr += count;
87
88 return_VALUE(count);
89}
90
91static int
92acpi_system_close_event(struct inode *inode, struct file *file)
93{
94 spin_lock_irq (&acpi_system_event_lock);
95 event_is_open = 0;
96 spin_unlock_irq (&acpi_system_event_lock);
97 return 0;
98}
99
100static unsigned int
101acpi_system_poll_event(
102 struct file *file,
103 poll_table *wait)
104{
105 poll_wait(file, &acpi_bus_event_queue, wait);
106 if (!list_empty(&acpi_bus_event_list))
107 return POLLIN | POLLRDNORM;
108 return 0;
109}
110
111static struct file_operations acpi_system_event_ops = {
112 .open = acpi_system_open_event,
113 .read = acpi_system_read_event,
114 .release = acpi_system_close_event,
115 .poll = acpi_system_poll_event,
116};
117
118static int __init acpi_event_init(void)
119{
120 struct proc_dir_entry *entry;
121 int error = 0;
122
123 ACPI_FUNCTION_TRACE("acpi_event_init");
124
125 if (acpi_disabled)
126 return_VALUE(0);
127
128 /* 'event' [R] */
129 entry = create_proc_entry("event", S_IRUSR, acpi_root_dir);
130 if (entry)
131 entry->proc_fops = &acpi_system_event_ops;
132 else {
133 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
134 "Unable to create '%s' proc fs entry\n","event" ));
135 error = -EFAULT;
136 }
137 return_VALUE(error);
138}
139
140subsys_initcall(acpi_event_init);
diff --git a/drivers/acpi/events/Makefile b/drivers/acpi/events/Makefile
new file mode 100644
index 000000000000..d29f2ee449cc
--- /dev/null
+++ b/drivers/acpi/events/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for all Linux ACPI interpreter subdirectories
3#
4
5obj-y := evevent.o evregion.o evsci.o evxfevnt.o \
6 evmisc.o evrgnini.o evxface.o evxfregn.o \
7 evgpe.o evgpeblk.o
8
9EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
new file mode 100644
index 000000000000..2a213604ae51
--- /dev/null
+++ b/drivers/acpi/events/evevent.c
@@ -0,0 +1,297 @@
1/******************************************************************************
2 *
3 * Module Name: evevent - Fixed Event handling and dispatch
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include <acpi/acevents.h>
46
47#define _COMPONENT ACPI_EVENTS
48 ACPI_MODULE_NAME ("evevent")
49
50
51/*******************************************************************************
52 *
53 * FUNCTION: acpi_ev_initialize_events
54 *
55 * PARAMETERS: None
56 *
57 * RETURN: Status
58 *
59 * DESCRIPTION: Initialize global data structures for events.
60 *
61 ******************************************************************************/
62
63acpi_status
64acpi_ev_initialize_events (
65 void)
66{
67 acpi_status status;
68
69
70 ACPI_FUNCTION_TRACE ("ev_initialize_events");
71
72
73 /* Make sure we have ACPI tables */
74
75 if (!acpi_gbl_DSDT) {
76 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No ACPI tables present!\n"));
77 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
78 }
79
80 /*
81 * Initialize the Fixed and General Purpose Events. This is
82 * done prior to enabling SCIs to prevent interrupts from
83 * occurring before handers are installed.
84 */
85 status = acpi_ev_fixed_event_initialize ();
86 if (ACPI_FAILURE (status)) {
87 ACPI_REPORT_ERROR ((
88 "Unable to initialize fixed events, %s\n",
89 acpi_format_exception (status)));
90 return_ACPI_STATUS (status);
91 }
92
93 status = acpi_ev_gpe_initialize ();
94 if (ACPI_FAILURE (status)) {
95 ACPI_REPORT_ERROR ((
96 "Unable to initialize general purpose events, %s\n",
97 acpi_format_exception (status)));
98 return_ACPI_STATUS (status);
99 }
100
101 return_ACPI_STATUS (status);
102}
103
104
105/*******************************************************************************
106 *
107 * FUNCTION: acpi_ev_install_xrupt_handlers
108 *
109 * PARAMETERS: None
110 *
111 * RETURN: Status
112 *
113 * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock
114 *
115 ******************************************************************************/
116
117acpi_status
118acpi_ev_install_xrupt_handlers (
119 void)
120{
121 acpi_status status;
122
123
124 ACPI_FUNCTION_TRACE ("ev_install_xrupt_handlers");
125
126
127 /* Install the SCI handler */
128
129 status = acpi_ev_install_sci_handler ();
130 if (ACPI_FAILURE (status)) {
131 ACPI_REPORT_ERROR ((
132 "Unable to install System Control Interrupt Handler, %s\n",
133 acpi_format_exception (status)));
134 return_ACPI_STATUS (status);
135 }
136
137 /* Install the handler for the Global Lock */
138
139 status = acpi_ev_init_global_lock_handler ();
140 if (ACPI_FAILURE (status)) {
141 ACPI_REPORT_ERROR ((
142 "Unable to initialize Global Lock handler, %s\n",
143 acpi_format_exception (status)));
144 return_ACPI_STATUS (status);
145 }
146
147 acpi_gbl_events_initialized = TRUE;
148 return_ACPI_STATUS (status);
149}
150
151
152/*******************************************************************************
153 *
154 * FUNCTION: acpi_ev_fixed_event_initialize
155 *
156 * PARAMETERS: None
157 *
158 * RETURN: Status
159 *
160 * DESCRIPTION: Install the fixed event handlers and enable the fixed events.
161 *
162 ******************************************************************************/
163
164acpi_status
165acpi_ev_fixed_event_initialize (
166 void)
167{
168 acpi_native_uint i;
169 acpi_status status;
170
171
172 /*
173 * Initialize the structure that keeps track of fixed event handlers
174 * and enable the fixed events.
175 */
176 for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
177 acpi_gbl_fixed_event_handlers[i].handler = NULL;
178 acpi_gbl_fixed_event_handlers[i].context = NULL;
179
180 /* Enable the fixed event */
181
182 if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) {
183 status = acpi_set_register (acpi_gbl_fixed_event_info[i].enable_register_id,
184 0, ACPI_MTX_LOCK);
185 if (ACPI_FAILURE (status)) {
186 return (status);
187 }
188 }
189 }
190
191 return (AE_OK);
192}
193
194
195/*******************************************************************************
196 *
197 * FUNCTION: acpi_ev_fixed_event_detect
198 *
199 * PARAMETERS: None
200 *
201 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
202 *
203 * DESCRIPTION: Checks the PM status register for fixed events
204 *
205 ******************************************************************************/
206
207u32
208acpi_ev_fixed_event_detect (
209 void)
210{
211 u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
212 u32 fixed_status;
213 u32 fixed_enable;
214 acpi_native_uint i;
215
216
217 ACPI_FUNCTION_NAME ("ev_fixed_event_detect");
218
219
220 /*
221 * Read the fixed feature status and enable registers, as all the cases
222 * depend on their values. Ignore errors here.
223 */
224 (void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, &fixed_status);
225 (void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
226
227 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
228 "Fixed Event Block: Enable %08X Status %08X\n",
229 fixed_enable, fixed_status));
230
231 /*
232 * Check for all possible Fixed Events and dispatch those that are active
233 */
234 for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
235 /* Both the status and enable bits must be on for this event */
236
237 if ((fixed_status & acpi_gbl_fixed_event_info[i].status_bit_mask) &&
238 (fixed_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) {
239 /* Found an active (signalled) event */
240
241 int_status |= acpi_ev_fixed_event_dispatch ((u32) i);
242 }
243 }
244
245 return (int_status);
246}
247
248
249/*******************************************************************************
250 *
251 * FUNCTION: acpi_ev_fixed_event_dispatch
252 *
253 * PARAMETERS: Event - Event type
254 *
255 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
256 *
257 * DESCRIPTION: Clears the status bit for the requested event, calls the
258 * handler that previously registered for the event.
259 *
260 ******************************************************************************/
261
262u32
263acpi_ev_fixed_event_dispatch (
264 u32 event)
265{
266
267
268 ACPI_FUNCTION_ENTRY ();
269
270
271 /* Clear the status bit */
272
273 (void) acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id,
274 1, ACPI_MTX_DO_NOT_LOCK);
275
276 /*
277 * Make sure we've got a handler. If not, report an error.
278 * The event is disabled to prevent further interrupts.
279 */
280 if (NULL == acpi_gbl_fixed_event_handlers[event].handler) {
281 (void) acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
282 0, ACPI_MTX_DO_NOT_LOCK);
283
284 ACPI_REPORT_ERROR (
285 ("No installed handler for fixed event [%08X]\n",
286 event));
287
288 return (ACPI_INTERRUPT_NOT_HANDLED);
289 }
290
291 /* Invoke the Fixed Event handler */
292
293 return ((acpi_gbl_fixed_event_handlers[event].handler)(
294 acpi_gbl_fixed_event_handlers[event].context));
295}
296
297
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
new file mode 100644
index 000000000000..118d72ac7c76
--- /dev/null
+++ b/drivers/acpi/events/evgpe.c
@@ -0,0 +1,756 @@
1/******************************************************************************
2 *
3 * Module Name: evgpe - General Purpose Event handling and dispatch
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include <acpi/acevents.h>
46#include <acpi/acnamesp.h>
47
48#define _COMPONENT ACPI_EVENTS
49 ACPI_MODULE_NAME ("evgpe")
50
51
52/*******************************************************************************
53 *
54 * FUNCTION: acpi_ev_set_gpe_type
55 *
56 * PARAMETERS: gpe_event_info - GPE to set
57 * Type - New type
58 *
59 * RETURN: Status
60 *
61 * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
62 *
63 ******************************************************************************/
64
65acpi_status
66acpi_ev_set_gpe_type (
67 struct acpi_gpe_event_info *gpe_event_info,
68 u8 type)
69{
70 acpi_status status;
71
72
73 ACPI_FUNCTION_TRACE ("ev_set_gpe_type");
74
75
76 /* Validate type and update register enable masks */
77
78 switch (type) {
79 case ACPI_GPE_TYPE_WAKE:
80 case ACPI_GPE_TYPE_RUNTIME:
81 case ACPI_GPE_TYPE_WAKE_RUN:
82 break;
83
84 default:
85 return_ACPI_STATUS (AE_BAD_PARAMETER);
86 }
87
88 /* Disable the GPE if currently enabled */
89
90 status = acpi_ev_disable_gpe (gpe_event_info);
91
92 /* Type was validated above */
93
94 gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
95 gpe_event_info->flags |= type; /* Insert type */
96 return_ACPI_STATUS (status);
97}
98
99
100/*******************************************************************************
101 *
102 * FUNCTION: acpi_ev_update_gpe_enable_masks
103 *
104 * PARAMETERS: gpe_event_info - GPE to update
105 * Type - What to do: ACPI_GPE_DISABLE or
106 * ACPI_GPE_ENABLE
107 *
108 * RETURN: Status
109 *
110 * DESCRIPTION: Updates GPE register enable masks based on the GPE type
111 *
112 ******************************************************************************/
113
114acpi_status
115acpi_ev_update_gpe_enable_masks (
116 struct acpi_gpe_event_info *gpe_event_info,
117 u8 type)
118{
119 struct acpi_gpe_register_info *gpe_register_info;
120 u8 register_bit;
121
122
123 ACPI_FUNCTION_TRACE ("ev_update_gpe_enable_masks");
124
125
126 gpe_register_info = gpe_event_info->register_info;
127 if (!gpe_register_info) {
128 return_ACPI_STATUS (AE_NOT_EXIST);
129 }
130 register_bit = gpe_event_info->register_bit;
131
132 /* 1) Disable case. Simply clear all enable bits */
133
134 if (type == ACPI_GPE_DISABLE) {
135 ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
136 ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
137 return_ACPI_STATUS (AE_OK);
138 }
139
140 /* 2) Enable case. Set/Clear the appropriate enable bits */
141
142 switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
143 case ACPI_GPE_TYPE_WAKE:
144 ACPI_SET_BIT (gpe_register_info->enable_for_wake, register_bit);
145 ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
146 break;
147
148 case ACPI_GPE_TYPE_RUNTIME:
149 ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
150 ACPI_SET_BIT (gpe_register_info->enable_for_run, register_bit);
151 break;
152
153 case ACPI_GPE_TYPE_WAKE_RUN:
154 ACPI_SET_BIT (gpe_register_info->enable_for_wake, register_bit);
155 ACPI_SET_BIT (gpe_register_info->enable_for_run, register_bit);
156 break;
157
158 default:
159 return_ACPI_STATUS (AE_BAD_PARAMETER);
160 }
161
162 return_ACPI_STATUS (AE_OK);
163}
164
165
166/*******************************************************************************
167 *
168 * FUNCTION: acpi_ev_enable_gpe
169 *
170 * PARAMETERS: gpe_event_info - GPE to enable
171 * write_to_hardware - Enable now, or just mark data structs
172 * (WAKE GPEs should be deferred)
173 *
174 * RETURN: Status
175 *
176 * DESCRIPTION: Enable a GPE based on the GPE type
177 *
178 ******************************************************************************/
179
180acpi_status
181acpi_ev_enable_gpe (
182 struct acpi_gpe_event_info *gpe_event_info,
183 u8 write_to_hardware)
184{
185 acpi_status status;
186
187
188 ACPI_FUNCTION_TRACE ("ev_enable_gpe");
189
190
191 /* Make sure HW enable masks are updated */
192
193 status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_ENABLE);
194 if (ACPI_FAILURE (status)) {
195 return_ACPI_STATUS (status);
196 }
197
198 /* Mark wake-enabled or HW enable, or both */
199
200 switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
201 case ACPI_GPE_TYPE_WAKE:
202
203 ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
204 break;
205
206 case ACPI_GPE_TYPE_WAKE_RUN:
207
208 ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
209
210 /*lint -fallthrough */
211
212 case ACPI_GPE_TYPE_RUNTIME:
213
214 ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
215
216 if (write_to_hardware) {
217 /* Clear the GPE (of stale events), then enable it */
218
219 status = acpi_hw_clear_gpe (gpe_event_info);
220 if (ACPI_FAILURE (status)) {
221 return_ACPI_STATUS (status);
222 }
223
224 /* Enable the requested runtime GPE */
225
226 status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
227 }
228 break;
229
230 default:
231 return_ACPI_STATUS (AE_BAD_PARAMETER);
232 }
233
234 return_ACPI_STATUS (AE_OK);
235}
236
237
238/*******************************************************************************
239 *
240 * FUNCTION: acpi_ev_disable_gpe
241 *
242 * PARAMETERS: gpe_event_info - GPE to disable
243 *
244 * RETURN: Status
245 *
246 * DESCRIPTION: Disable a GPE based on the GPE type
247 *
248 ******************************************************************************/
249
250acpi_status
251acpi_ev_disable_gpe (
252 struct acpi_gpe_event_info *gpe_event_info)
253{
254 acpi_status status;
255
256
257 ACPI_FUNCTION_TRACE ("ev_disable_gpe");
258
259
260 if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
261 return_ACPI_STATUS (AE_OK);
262 }
263
264 /* Make sure HW enable masks are updated */
265
266 status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
267 if (ACPI_FAILURE (status)) {
268 return_ACPI_STATUS (status);
269 }
270
271 /* Mark wake-disabled or HW disable, or both */
272
273 switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
274 case ACPI_GPE_TYPE_WAKE:
275 ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
276 break;
277
278 case ACPI_GPE_TYPE_WAKE_RUN:
279 ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
280
281 /*lint -fallthrough */
282
283 case ACPI_GPE_TYPE_RUNTIME:
284
285 /* Disable the requested runtime GPE */
286
287 ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
288 status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
289 break;
290
291 default:
292 return_ACPI_STATUS (AE_BAD_PARAMETER);
293 }
294
295 return_ACPI_STATUS (AE_OK);
296}
297
298
299/*******************************************************************************
300 *
301 * FUNCTION: acpi_ev_get_gpe_event_info
302 *
303 * PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1
304 * gpe_number - Raw GPE number
305 *
306 * RETURN: A GPE event_info struct. NULL if not a valid GPE
307 *
308 * DESCRIPTION: Returns the event_info struct associated with this GPE.
309 * Validates the gpe_block and the gpe_number
310 *
311 * Should be called only when the GPE lists are semaphore locked
312 * and not subject to change.
313 *
314 ******************************************************************************/
315
316struct acpi_gpe_event_info *
317acpi_ev_get_gpe_event_info (
318 acpi_handle gpe_device,
319 u32 gpe_number)
320{
321 union acpi_operand_object *obj_desc;
322 struct acpi_gpe_block_info *gpe_block;
323 acpi_native_uint i;
324
325
326 ACPI_FUNCTION_ENTRY ();
327
328
329 /* A NULL gpe_block means use the FADT-defined GPE block(s) */
330
331 if (!gpe_device) {
332 /* Examine GPE Block 0 and 1 (These blocks are permanent) */
333
334 for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
335 gpe_block = acpi_gbl_gpe_fadt_blocks[i];
336 if (gpe_block) {
337 if ((gpe_number >= gpe_block->block_base_number) &&
338 (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
339 return (&gpe_block->event_info[gpe_number - gpe_block->block_base_number]);
340 }
341 }
342 }
343
344 /* The gpe_number was not in the range of either FADT GPE block */
345
346 return (NULL);
347 }
348
349 /* A Non-NULL gpe_device means this is a GPE Block Device */
350
351 obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) gpe_device);
352 if (!obj_desc ||
353 !obj_desc->device.gpe_block) {
354 return (NULL);
355 }
356
357 gpe_block = obj_desc->device.gpe_block;
358
359 if ((gpe_number >= gpe_block->block_base_number) &&
360 (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
361 return (&gpe_block->event_info[gpe_number - gpe_block->block_base_number]);
362 }
363
364 return (NULL);
365}
366
367
368/*******************************************************************************
369 *
370 * FUNCTION: acpi_ev_gpe_detect
371 *
372 * PARAMETERS: gpe_xrupt_list - Interrupt block for this interrupt.
373 * Can have multiple GPE blocks attached.
374 *
375 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
376 *
377 * DESCRIPTION: Detect if any GP events have occurred. This function is
378 * executed at interrupt level.
379 *
380 ******************************************************************************/
381
382u32
383acpi_ev_gpe_detect (
384 struct acpi_gpe_xrupt_info *gpe_xrupt_list)
385{
386 u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
387 u8 enabled_status_byte;
388 struct acpi_gpe_register_info *gpe_register_info;
389 u32 status_reg;
390 u32 enable_reg;
391 acpi_status status;
392 struct acpi_gpe_block_info *gpe_block;
393 acpi_native_uint i;
394 acpi_native_uint j;
395
396
397 ACPI_FUNCTION_NAME ("ev_gpe_detect");
398
399 /* Check for the case where there are no GPEs */
400
401 if (!gpe_xrupt_list) {
402 return (int_status);
403 }
404
405 /* Examine all GPE blocks attached to this interrupt level */
406
407 acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR);
408 gpe_block = gpe_xrupt_list->gpe_block_list_head;
409 while (gpe_block) {
410 /*
411 * Read all of the 8-bit GPE status and enable registers
412 * in this GPE block, saving all of them.
413 * Find all currently active GP events.
414 */
415 for (i = 0; i < gpe_block->register_count; i++) {
416 /* Get the next status/enable pair */
417
418 gpe_register_info = &gpe_block->register_info[i];
419
420 /* Read the Status Register */
421
422 status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &status_reg,
423 &gpe_register_info->status_address);
424 if (ACPI_FAILURE (status)) {
425 goto unlock_and_exit;
426 }
427
428 /* Read the Enable Register */
429
430 status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &enable_reg,
431 &gpe_register_info->enable_address);
432 if (ACPI_FAILURE (status)) {
433 goto unlock_and_exit;
434 }
435
436 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
437 "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
438 gpe_register_info->base_gpe_number, status_reg, enable_reg));
439
440 /* First check if there is anything active at all in this register */
441
442 enabled_status_byte = (u8) (status_reg & enable_reg);
443 if (!enabled_status_byte) {
444 /* No active GPEs in this register, move on */
445
446 continue;
447 }
448
449 /* Now look at the individual GPEs in this byte register */
450
451 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
452 /* Examine one GPE bit */
453
454 if (enabled_status_byte & acpi_gbl_decode_to8bit[j]) {
455 /*
456 * Found an active GPE. Dispatch the event to a handler
457 * or method.
458 */
459 int_status |= acpi_ev_gpe_dispatch (
460 &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j],
461 (u32) j + gpe_register_info->base_gpe_number);
462 }
463 }
464 }
465
466 gpe_block = gpe_block->next;
467 }
468
469unlock_and_exit:
470
471 acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
472 return (int_status);
473}
474
475
476/*******************************************************************************
477 *
478 * FUNCTION: acpi_ev_asynch_execute_gpe_method
479 *
480 * PARAMETERS: Context (gpe_event_info) - Info for this GPE
481 *
482 * RETURN: None
483 *
484 * DESCRIPTION: Perform the actual execution of a GPE control method. This
485 * function is called from an invocation of acpi_os_queue_for_execution
486 * (and therefore does NOT execute at interrupt level) so that
487 * the control method itself is not executed in the context of
488 * an interrupt handler.
489 *
490 ******************************************************************************/
491
492static void ACPI_SYSTEM_XFACE
493acpi_ev_asynch_execute_gpe_method (
494 void *context)
495{
496 struct acpi_gpe_event_info *gpe_event_info = (void *) context;
497 u32 gpe_number = 0;
498 acpi_status status;
499 struct acpi_gpe_event_info local_gpe_event_info;
500 struct acpi_parameter_info info;
501
502
503 ACPI_FUNCTION_TRACE ("ev_asynch_execute_gpe_method");
504
505
506 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
507 if (ACPI_FAILURE (status)) {
508 return_VOID;
509 }
510
511 /* Must revalidate the gpe_number/gpe_block */
512
513 if (!acpi_ev_valid_gpe_event (gpe_event_info)) {
514 status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
515 return_VOID;
516 }
517
518 /* Set the GPE flags for return to enabled state */
519
520 (void) acpi_ev_enable_gpe (gpe_event_info, FALSE);
521
522 /*
523 * Take a snapshot of the GPE info for this level - we copy the
524 * info to prevent a race condition with remove_handler/remove_block.
525 */
526 ACPI_MEMCPY (&local_gpe_event_info, gpe_event_info, sizeof (struct acpi_gpe_event_info));
527
528 status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
529 if (ACPI_FAILURE (status)) {
530 return_VOID;
531 }
532
533 /*
534 * Must check for control method type dispatch one more
535 * time to avoid race with ev_gpe_install_handler
536 */
537 if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) {
538 /*
539 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
540 * control method that corresponds to this GPE
541 */
542 info.node = local_gpe_event_info.dispatch.method_node;
543 info.parameters = ACPI_CAST_PTR (union acpi_operand_object *, gpe_event_info);
544 info.parameter_type = ACPI_PARAM_GPE;
545
546 status = acpi_ns_evaluate_by_handle (&info);
547 if (ACPI_FAILURE (status)) {
548 ACPI_REPORT_ERROR ((
549 "%s while evaluating method [%4.4s] for GPE[%2X]\n",
550 acpi_format_exception (status),
551 acpi_ut_get_node_name (local_gpe_event_info.dispatch.method_node),
552 gpe_number));
553 }
554 }
555
556 if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
557 /*
558 * GPE is level-triggered, we clear the GPE status bit after
559 * handling the event.
560 */
561 status = acpi_hw_clear_gpe (&local_gpe_event_info);
562 if (ACPI_FAILURE (status)) {
563 return_VOID;
564 }
565 }
566
567 /* Enable this GPE */
568
569 (void) acpi_hw_write_gpe_enable_reg (&local_gpe_event_info);
570 return_VOID;
571}
572
573
574/*******************************************************************************
575 *
576 * FUNCTION: acpi_ev_gpe_dispatch
577 *
578 * PARAMETERS: gpe_event_info - info for this GPE
579 * gpe_number - Number relative to the parent GPE block
580 *
581 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
582 *
583 * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
584 * or method (e.g. _Lxx/_Exx) handler.
585 *
586 * This function executes at interrupt level.
587 *
588 ******************************************************************************/
589
590u32
591acpi_ev_gpe_dispatch (
592 struct acpi_gpe_event_info *gpe_event_info,
593 u32 gpe_number)
594{
595 acpi_status status;
596
597
598 ACPI_FUNCTION_TRACE ("ev_gpe_dispatch");
599
600
601 /*
602 * If edge-triggered, clear the GPE status bit now. Note that
603 * level-triggered events are cleared after the GPE is serviced.
604 */
605 if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_EDGE_TRIGGERED) {
606 status = acpi_hw_clear_gpe (gpe_event_info);
607 if (ACPI_FAILURE (status)) {
608 ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n",
609 acpi_format_exception (status), gpe_number));
610 return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
611 }
612 }
613
614 /* Save current system state */
615
616 if (acpi_gbl_system_awake_and_running) {
617 ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
618 }
619 else {
620 ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
621 }
622
623 /*
624 * Dispatch the GPE to either an installed handler, or the control
625 * method associated with this GPE (_Lxx or _Exx).
626 * If a handler exists, we invoke it and do not attempt to run the method.
627 * If there is neither a handler nor a method, we disable the level to
628 * prevent further events from coming in here.
629 */
630 switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
631 case ACPI_GPE_DISPATCH_HANDLER:
632
633 /*
634 * Invoke the installed handler (at interrupt level)
635 * Ignore return status for now. TBD: leave GPE disabled on error?
636 */
637 (void) gpe_event_info->dispatch.handler->address (
638 gpe_event_info->dispatch.handler->context);
639
640 /* It is now safe to clear level-triggered events. */
641
642 if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
643 status = acpi_hw_clear_gpe (gpe_event_info);
644 if (ACPI_FAILURE (status)) {
645 ACPI_REPORT_ERROR ((
646 "acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n",
647 acpi_format_exception (status), gpe_number));
648 return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
649 }
650 }
651 break;
652
653 case ACPI_GPE_DISPATCH_METHOD:
654
655 /*
656 * Disable GPE, so it doesn't keep firing before the method has a
657 * chance to run.
658 */
659 status = acpi_ev_disable_gpe (gpe_event_info);
660 if (ACPI_FAILURE (status)) {
661 ACPI_REPORT_ERROR ((
662 "acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n",
663 acpi_format_exception (status), gpe_number));
664 return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
665 }
666
667 /*
668 * Execute the method associated with the GPE
669 * NOTE: Level-triggered GPEs are cleared after the method completes.
670 */
671 status = acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
672 acpi_ev_asynch_execute_gpe_method, gpe_event_info);
673 if (ACPI_FAILURE (status)) {
674 ACPI_REPORT_ERROR ((
675 "acpi_ev_gpe_dispatch: %s, Unable to queue handler for GPE[%2X] - event disabled\n",
676 acpi_format_exception (status), gpe_number));
677 }
678 break;
679
680 default:
681
682 /* No handler or method to run! */
683
684 ACPI_REPORT_ERROR ((
685 "acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n",
686 gpe_number));
687
688 /*
689 * Disable the GPE. The GPE will remain disabled until the ACPI
690 * Core Subsystem is restarted, or a handler is installed.
691 */
692 status = acpi_ev_disable_gpe (gpe_event_info);
693 if (ACPI_FAILURE (status)) {
694 ACPI_REPORT_ERROR ((
695 "acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n",
696 acpi_format_exception (status), gpe_number));
697 return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
698 }
699 break;
700 }
701
702 return_VALUE (ACPI_INTERRUPT_HANDLED);
703}
704
705
706#ifdef ACPI_GPE_NOTIFY_CHECK
707
708/*******************************************************************************
709 * TBD: NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED
710 *
711 * FUNCTION: acpi_ev_check_for_wake_only_gpe
712 *
713 * PARAMETERS: gpe_event_info - info for this GPE
714 *
715 * RETURN: Status
716 *
717 * DESCRIPTION: Determine if a a GPE is "wake-only".
718 *
719 * Called from Notify() code in interpreter when a "device_wake"
720 * Notify comes in.
721 *
722 ******************************************************************************/
723
724acpi_status
725acpi_ev_check_for_wake_only_gpe (
726 struct acpi_gpe_event_info *gpe_event_info)
727{
728 acpi_status status;
729
730
731 ACPI_FUNCTION_TRACE ("ev_check_for_wake_only_gpe");
732
733
734 if ((gpe_event_info) && /* Only >0 for _Lxx/_Exx */
735 ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) /* System state at GPE time */ {
736 /* This must be a wake-only GPE, disable it */
737
738 status = acpi_ev_disable_gpe (gpe_event_info);
739
740 /* Set GPE to wake-only. Do not change wake disabled/enabled status */
741
742 acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
743
744 ACPI_REPORT_INFO (("GPE %p was updated from wake/run to wake-only\n",
745 gpe_event_info));
746
747 /* This was a wake-only GPE */
748
749 return_ACPI_STATUS (AE_WAKE_ONLY_GPE);
750 }
751
752 return_ACPI_STATUS (AE_OK);
753}
754#endif
755
756
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
new file mode 100644
index 000000000000..00d981f53c6a
--- /dev/null
+++ b/drivers/acpi/events/evgpeblk.c
@@ -0,0 +1,1141 @@
1/******************************************************************************
2 *
3 * Module Name: evgpeblk - GPE block creation and initialization.
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include <acpi/acevents.h>
46#include <acpi/acnamesp.h>
47
48#define _COMPONENT ACPI_EVENTS
49 ACPI_MODULE_NAME ("evgpeblk")
50
51
52/*******************************************************************************
53 *
54 * FUNCTION: acpi_ev_valid_gpe_event
55 *
56 * PARAMETERS: gpe_event_info - Info for this GPE
57 *
58 * RETURN: TRUE if the gpe_event is valid
59 *
60 * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
61 * Should be called only when the GPE lists are semaphore locked
62 * and not subject to change.
63 *
64 ******************************************************************************/
65
66u8
67acpi_ev_valid_gpe_event (
68 struct acpi_gpe_event_info *gpe_event_info)
69{
70 struct acpi_gpe_xrupt_info *gpe_xrupt_block;
71 struct acpi_gpe_block_info *gpe_block;
72
73
74 ACPI_FUNCTION_ENTRY ();
75
76
77 /* No need for spin lock since we are not changing any list elements */
78
79 /* Walk the GPE interrupt levels */
80
81 gpe_xrupt_block = acpi_gbl_gpe_xrupt_list_head;
82 while (gpe_xrupt_block) {
83 gpe_block = gpe_xrupt_block->gpe_block_list_head;
84
85 /* Walk the GPE blocks on this interrupt level */
86
87 while (gpe_block) {
88 if ((&gpe_block->event_info[0] <= gpe_event_info) &&
89 (&gpe_block->event_info[((acpi_size) gpe_block->register_count) * 8] > gpe_event_info)) {
90 return (TRUE);
91 }
92
93 gpe_block = gpe_block->next;
94 }
95
96 gpe_xrupt_block = gpe_xrupt_block->next;
97 }
98
99 return (FALSE);
100}
101
102
103/*******************************************************************************
104 *
105 * FUNCTION: acpi_ev_walk_gpe_list
106 *
107 * PARAMETERS: gpe_walk_callback - Routine called for each GPE block
108 * Flags - ACPI_NOT_ISR or ACPI_ISR
109 *
110 * RETURN: Status
111 *
112 * DESCRIPTION: Walk the GPE lists.
113 *
114 ******************************************************************************/
115
116acpi_status
117acpi_ev_walk_gpe_list (
118 ACPI_GPE_CALLBACK gpe_walk_callback,
119 u32 flags)
120{
121 struct acpi_gpe_block_info *gpe_block;
122 struct acpi_gpe_xrupt_info *gpe_xrupt_info;
123 acpi_status status = AE_OK;
124
125
126 ACPI_FUNCTION_TRACE ("ev_walk_gpe_list");
127
128
129 acpi_os_acquire_lock (acpi_gbl_gpe_lock, flags);
130
131 /* Walk the interrupt level descriptor list */
132
133 gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
134 while (gpe_xrupt_info) {
135 /* Walk all Gpe Blocks attached to this interrupt level */
136
137 gpe_block = gpe_xrupt_info->gpe_block_list_head;
138 while (gpe_block) {
139 /* One callback per GPE block */
140
141 status = gpe_walk_callback (gpe_xrupt_info, gpe_block);
142 if (ACPI_FAILURE (status)) {
143 goto unlock_and_exit;
144 }
145
146 gpe_block = gpe_block->next;
147 }
148
149 gpe_xrupt_info = gpe_xrupt_info->next;
150 }
151
152unlock_and_exit:
153 acpi_os_release_lock (acpi_gbl_gpe_lock, flags);
154 return_ACPI_STATUS (status);
155}
156
157
158/******************************************************************************
159 *
160 * FUNCTION: acpi_ev_delete_gpe_handlers
161 *
162 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info
163 * gpe_block - Gpe Block info
164 *
165 * RETURN: Status
166 *
167 * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
168 * Used only prior to termination.
169 *
170 ******************************************************************************/
171
172acpi_status
173acpi_ev_delete_gpe_handlers (
174 struct acpi_gpe_xrupt_info *gpe_xrupt_info,
175 struct acpi_gpe_block_info *gpe_block)
176{
177 struct acpi_gpe_event_info *gpe_event_info;
178 acpi_native_uint i;
179 acpi_native_uint j;
180
181
182 ACPI_FUNCTION_TRACE ("ev_delete_gpe_handlers");
183
184
185 /* Examine each GPE Register within the block */
186
187 for (i = 0; i < gpe_block->register_count; i++) {
188 /* Now look at the individual GPEs in this byte register */
189
190 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
191 gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
192
193 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
194 ACPI_MEM_FREE (gpe_event_info->dispatch.handler);
195 gpe_event_info->dispatch.handler = NULL;
196 gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK;
197 }
198 }
199 }
200
201 return_ACPI_STATUS (AE_OK);
202}
203
204
205/*******************************************************************************
206 *
207 * FUNCTION: acpi_ev_save_method_info
208 *
209 * PARAMETERS: Callback from walk_namespace
210 *
211 * RETURN: Status
212 *
213 * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
214 * control method under the _GPE portion of the namespace.
215 * Extract the name and GPE type from the object, saving this
216 * information for quick lookup during GPE dispatch
217 *
218 * The name of each GPE control method is of the form:
219 * "_Lxx" or "_Exx"
220 * Where:
221 * L - means that the GPE is level triggered
222 * E - means that the GPE is edge triggered
223 * xx - is the GPE number [in HEX]
224 *
225 ******************************************************************************/
226
227static acpi_status
228acpi_ev_save_method_info (
229 acpi_handle obj_handle,
230 u32 level,
231 void *obj_desc,
232 void **return_value)
233{
234 struct acpi_gpe_block_info *gpe_block = (void *) obj_desc;
235 struct acpi_gpe_event_info *gpe_event_info;
236 u32 gpe_number;
237 char name[ACPI_NAME_SIZE + 1];
238 u8 type;
239 acpi_status status;
240
241
242 ACPI_FUNCTION_TRACE ("ev_save_method_info");
243
244
245 /*
246 * _Lxx and _Exx GPE method support
247 *
248 * 1) Extract the name from the object and convert to a string
249 */
250 ACPI_MOVE_32_TO_32 (name,
251 &((struct acpi_namespace_node *) obj_handle)->name.integer);
252 name[ACPI_NAME_SIZE] = 0;
253
254 /*
255 * 2) Edge/Level determination is based on the 2nd character
256 * of the method name
257 *
258 * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
259 * if a _PRW object is found that points to this GPE.
260 */
261 switch (name[1]) {
262 case 'L':
263 type = ACPI_GPE_LEVEL_TRIGGERED;
264 break;
265
266 case 'E':
267 type = ACPI_GPE_EDGE_TRIGGERED;
268 break;
269
270 default:
271 /* Unknown method type, just ignore it! */
272
273 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
274 "Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n",
275 name));
276 return_ACPI_STATUS (AE_OK);
277 }
278
279 /* Convert the last two characters of the name to the GPE Number */
280
281 gpe_number = ACPI_STRTOUL (&name[2], NULL, 16);
282 if (gpe_number == ACPI_UINT32_MAX) {
283 /* Conversion failed; invalid method, just ignore it */
284
285 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
286 "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n",
287 name));
288 return_ACPI_STATUS (AE_OK);
289 }
290
291 /* Ensure that we have a valid GPE number for this GPE block */
292
293 if ((gpe_number < gpe_block->block_base_number) ||
294 (gpe_number >= (gpe_block->block_base_number + (gpe_block->register_count * 8)))) {
295 /*
296 * Not valid for this GPE block, just ignore it
297 * However, it may be valid for a different GPE block, since GPE0 and GPE1
298 * methods both appear under \_GPE.
299 */
300 return_ACPI_STATUS (AE_OK);
301 }
302
303 /*
304 * Now we can add this information to the gpe_event_info block
305 * for use during dispatch of this GPE. Default type is RUNTIME, although
306 * this may change when the _PRW methods are executed later.
307 */
308 gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
309
310 gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD |
311 ACPI_GPE_TYPE_RUNTIME);
312
313 gpe_event_info->dispatch.method_node = (struct acpi_namespace_node *) obj_handle;
314
315 /* Update enable mask, but don't enable the HW GPE as of yet */
316
317 status = acpi_ev_enable_gpe (gpe_event_info, FALSE);
318
319 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
320 "Registered GPE method %s as GPE number 0x%.2X\n",
321 name, gpe_number));
322 return_ACPI_STATUS (status);
323}
324
325
326/*******************************************************************************
327 *
328 * FUNCTION: acpi_ev_match_prw_and_gpe
329 *
330 * PARAMETERS: Callback from walk_namespace
331 *
332 * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is
333 * not aborted on a single _PRW failure.
334 *
335 * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
336 * Device. Run the _PRW method. If present, extract the GPE
337 * number and mark the GPE as a WAKE GPE.
338 *
339 ******************************************************************************/
340
341static acpi_status
342acpi_ev_match_prw_and_gpe (
343 acpi_handle obj_handle,
344 u32 level,
345 void *info,
346 void **return_value)
347{
348 struct acpi_gpe_walk_info *gpe_info = (void *) info;
349 struct acpi_namespace_node *gpe_device;
350 struct acpi_gpe_block_info *gpe_block;
351 struct acpi_namespace_node *target_gpe_device;
352 struct acpi_gpe_event_info *gpe_event_info;
353 union acpi_operand_object *pkg_desc;
354 union acpi_operand_object *obj_desc;
355 u32 gpe_number;
356 acpi_status status;
357
358
359 ACPI_FUNCTION_TRACE ("ev_match_prw_and_gpe");
360
361
362 /* Check for a _PRW method under this device */
363
364 status = acpi_ut_evaluate_object (obj_handle, METHOD_NAME__PRW,
365 ACPI_BTYPE_PACKAGE, &pkg_desc);
366 if (ACPI_FAILURE (status)) {
367 /* Ignore all errors from _PRW, we don't want to abort the subsystem */
368
369 return_ACPI_STATUS (AE_OK);
370 }
371
372 /* The returned _PRW package must have at least two elements */
373
374 if (pkg_desc->package.count < 2) {
375 goto cleanup;
376 }
377
378 /* Extract pointers from the input context */
379
380 gpe_device = gpe_info->gpe_device;
381 gpe_block = gpe_info->gpe_block;
382
383 /*
384 * The _PRW object must return a package, we are only interested
385 * in the first element
386 */
387 obj_desc = pkg_desc->package.elements[0];
388
389 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
390 /* Use FADT-defined GPE device (from definition of _PRW) */
391
392 target_gpe_device = acpi_gbl_fadt_gpe_device;
393
394 /* Integer is the GPE number in the FADT described GPE blocks */
395
396 gpe_number = (u32) obj_desc->integer.value;
397 }
398 else if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
399 /* Package contains a GPE reference and GPE number within a GPE block */
400
401 if ((obj_desc->package.count < 2) ||
402 (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_LOCAL_REFERENCE) ||
403 (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) {
404 goto cleanup;
405 }
406
407 /* Get GPE block reference and decode */
408
409 target_gpe_device = obj_desc->package.elements[0]->reference.node;
410 gpe_number = (u32) obj_desc->package.elements[1]->integer.value;
411 }
412 else {
413 /* Unknown type, just ignore it */
414
415 goto cleanup;
416 }
417
418 /*
419 * Is this GPE within this block?
420 *
421 * TRUE iff these conditions are true:
422 * 1) The GPE devices match.
423 * 2) The GPE index(number) is within the range of the Gpe Block
424 * associated with the GPE device.
425 */
426 if ((gpe_device == target_gpe_device) &&
427 (gpe_number >= gpe_block->block_base_number) &&
428 (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
429 gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
430
431 /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
432
433 gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
434 status = acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
435 if (ACPI_FAILURE (status)) {
436 goto cleanup;
437 }
438 status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
439 }
440
441cleanup:
442 acpi_ut_remove_reference (pkg_desc);
443 return_ACPI_STATUS (AE_OK);
444}
445
446
447/*******************************************************************************
448 *
449 * FUNCTION: acpi_ev_get_gpe_xrupt_block
450 *
451 * PARAMETERS: interrupt_level - Interrupt for a GPE block
452 *
453 * RETURN: A GPE interrupt block
454 *
455 * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
456 * block per unique interrupt level used for GPEs.
457 * Should be called only when the GPE lists are semaphore locked
458 * and not subject to change.
459 *
460 ******************************************************************************/
461
462static struct acpi_gpe_xrupt_info *
463acpi_ev_get_gpe_xrupt_block (
464 u32 interrupt_level)
465{
466 struct acpi_gpe_xrupt_info *next_gpe_xrupt;
467 struct acpi_gpe_xrupt_info *gpe_xrupt;
468 acpi_status status;
469
470
471 ACPI_FUNCTION_TRACE ("ev_get_gpe_xrupt_block");
472
473
474 /* No need for spin lock since we are not changing any list elements here */
475
476 next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
477 while (next_gpe_xrupt) {
478 if (next_gpe_xrupt->interrupt_level == interrupt_level) {
479 return_PTR (next_gpe_xrupt);
480 }
481
482 next_gpe_xrupt = next_gpe_xrupt->next;
483 }
484
485 /* Not found, must allocate a new xrupt descriptor */
486
487 gpe_xrupt = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_xrupt_info));
488 if (!gpe_xrupt) {
489 return_PTR (NULL);
490 }
491
492 gpe_xrupt->interrupt_level = interrupt_level;
493
494 /* Install new interrupt descriptor with spin lock */
495
496 acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
497 if (acpi_gbl_gpe_xrupt_list_head) {
498 next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
499 while (next_gpe_xrupt->next) {
500 next_gpe_xrupt = next_gpe_xrupt->next;
501 }
502
503 next_gpe_xrupt->next = gpe_xrupt;
504 gpe_xrupt->previous = next_gpe_xrupt;
505 }
506 else {
507 acpi_gbl_gpe_xrupt_list_head = gpe_xrupt;
508 }
509 acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
510
511 /* Install new interrupt handler if not SCI_INT */
512
513 if (interrupt_level != acpi_gbl_FADT->sci_int) {
514 status = acpi_os_install_interrupt_handler (interrupt_level,
515 acpi_ev_gpe_xrupt_handler, gpe_xrupt);
516 if (ACPI_FAILURE (status)) {
517 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
518 "Could not install GPE interrupt handler at level 0x%X\n",
519 interrupt_level));
520 return_PTR (NULL);
521 }
522 }
523
524 return_PTR (gpe_xrupt);
525}
526
527
528/*******************************************************************************
529 *
530 * FUNCTION: acpi_ev_delete_gpe_xrupt
531 *
532 * PARAMETERS: gpe_xrupt - A GPE interrupt info block
533 *
534 * RETURN: Status
535 *
536 * DESCRIPTION: Remove and free a gpe_xrupt block. Remove an associated
537 * interrupt handler if not the SCI interrupt.
538 *
539 ******************************************************************************/
540
541static acpi_status
542acpi_ev_delete_gpe_xrupt (
543 struct acpi_gpe_xrupt_info *gpe_xrupt)
544{
545 acpi_status status;
546
547
548 ACPI_FUNCTION_TRACE ("ev_delete_gpe_xrupt");
549
550
551 /* We never want to remove the SCI interrupt handler */
552
553 if (gpe_xrupt->interrupt_level == acpi_gbl_FADT->sci_int) {
554 gpe_xrupt->gpe_block_list_head = NULL;
555 return_ACPI_STATUS (AE_OK);
556 }
557
558 /* Disable this interrupt */
559
560 status = acpi_os_remove_interrupt_handler (gpe_xrupt->interrupt_level,
561 acpi_ev_gpe_xrupt_handler);
562 if (ACPI_FAILURE (status)) {
563 return_ACPI_STATUS (status);
564 }
565
566 /* Unlink the interrupt block with lock */
567
568 acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
569 if (gpe_xrupt->previous) {
570 gpe_xrupt->previous->next = gpe_xrupt->next;
571 }
572
573 if (gpe_xrupt->next) {
574 gpe_xrupt->next->previous = gpe_xrupt->previous;
575 }
576 acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
577
578 /* Free the block */
579
580 ACPI_MEM_FREE (gpe_xrupt);
581 return_ACPI_STATUS (AE_OK);
582}
583
584
585/*******************************************************************************
586 *
587 * FUNCTION: acpi_ev_install_gpe_block
588 *
589 * PARAMETERS: gpe_block - New GPE block
590 * interrupt_level - Level to be associated with this GPE block
591 *
592 * RETURN: Status
593 *
594 * DESCRIPTION: Install new GPE block with mutex support
595 *
596 ******************************************************************************/
597
598static acpi_status
599acpi_ev_install_gpe_block (
600 struct acpi_gpe_block_info *gpe_block,
601 u32 interrupt_level)
602{
603 struct acpi_gpe_block_info *next_gpe_block;
604 struct acpi_gpe_xrupt_info *gpe_xrupt_block;
605 acpi_status status;
606
607
608 ACPI_FUNCTION_TRACE ("ev_install_gpe_block");
609
610
611 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
612 if (ACPI_FAILURE (status)) {
613 return_ACPI_STATUS (status);
614 }
615
616 gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block (interrupt_level);
617 if (!gpe_xrupt_block) {
618 status = AE_NO_MEMORY;
619 goto unlock_and_exit;
620 }
621
622 /* Install the new block at the end of the list for this interrupt with lock */
623
624 acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
625 if (gpe_xrupt_block->gpe_block_list_head) {
626 next_gpe_block = gpe_xrupt_block->gpe_block_list_head;
627 while (next_gpe_block->next) {
628 next_gpe_block = next_gpe_block->next;
629 }
630
631 next_gpe_block->next = gpe_block;
632 gpe_block->previous = next_gpe_block;
633 }
634 else {
635 gpe_xrupt_block->gpe_block_list_head = gpe_block;
636 }
637
638 gpe_block->xrupt_block = gpe_xrupt_block;
639 acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
640
641unlock_and_exit:
642 status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
643 return_ACPI_STATUS (status);
644}
645
646
647/*******************************************************************************
648 *
649 * FUNCTION: acpi_ev_delete_gpe_block
650 *
651 * PARAMETERS: gpe_block - Existing GPE block
652 *
653 * RETURN: Status
654 *
655 * DESCRIPTION: Remove a GPE block
656 *
657 ******************************************************************************/
658
659acpi_status
660acpi_ev_delete_gpe_block (
661 struct acpi_gpe_block_info *gpe_block)
662{
663 acpi_status status;
664
665
666 ACPI_FUNCTION_TRACE ("ev_install_gpe_block");
667
668
669 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
670 if (ACPI_FAILURE (status)) {
671 return_ACPI_STATUS (status);
672 }
673
674 /* Disable all GPEs in this block */
675
676 status = acpi_hw_disable_gpe_block (gpe_block->xrupt_block, gpe_block);
677
678 if (!gpe_block->previous && !gpe_block->next) {
679 /* This is the last gpe_block on this interrupt */
680
681 status = acpi_ev_delete_gpe_xrupt (gpe_block->xrupt_block);
682 if (ACPI_FAILURE (status)) {
683 goto unlock_and_exit;
684 }
685 }
686 else {
687 /* Remove the block on this interrupt with lock */
688
689 acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
690 if (gpe_block->previous) {
691 gpe_block->previous->next = gpe_block->next;
692 }
693 else {
694 gpe_block->xrupt_block->gpe_block_list_head = gpe_block->next;
695 }
696
697 if (gpe_block->next) {
698 gpe_block->next->previous = gpe_block->previous;
699 }
700 acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
701 }
702
703 /* Free the gpe_block */
704
705 ACPI_MEM_FREE (gpe_block->register_info);
706 ACPI_MEM_FREE (gpe_block->event_info);
707 ACPI_MEM_FREE (gpe_block);
708
709unlock_and_exit:
710 status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
711 return_ACPI_STATUS (status);
712}
713
714
715/*******************************************************************************
716 *
717 * FUNCTION: acpi_ev_create_gpe_info_blocks
718 *
719 * PARAMETERS: gpe_block - New GPE block
720 *
721 * RETURN: Status
722 *
723 * DESCRIPTION: Create the register_info and event_info blocks for this GPE block
724 *
725 ******************************************************************************/
726
727static acpi_status
728acpi_ev_create_gpe_info_blocks (
729 struct acpi_gpe_block_info *gpe_block)
730{
731 struct acpi_gpe_register_info *gpe_register_info = NULL;
732 struct acpi_gpe_event_info *gpe_event_info = NULL;
733 struct acpi_gpe_event_info *this_event;
734 struct acpi_gpe_register_info *this_register;
735 acpi_native_uint i;
736 acpi_native_uint j;
737 acpi_status status;
738
739
740 ACPI_FUNCTION_TRACE ("ev_create_gpe_info_blocks");
741
742
743 /* Allocate the GPE register information block */
744
745 gpe_register_info = ACPI_MEM_CALLOCATE (
746 (acpi_size) gpe_block->register_count *
747 sizeof (struct acpi_gpe_register_info));
748 if (!gpe_register_info) {
749 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
750 "Could not allocate the gpe_register_info table\n"));
751 return_ACPI_STATUS (AE_NO_MEMORY);
752 }
753
754 /*
755 * Allocate the GPE event_info block. There are eight distinct GPEs
756 * per register. Initialization to zeros is sufficient.
757 */
758 gpe_event_info = ACPI_MEM_CALLOCATE (
759 ((acpi_size) gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) *
760 sizeof (struct acpi_gpe_event_info));
761 if (!gpe_event_info) {
762 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the gpe_event_info table\n"));
763 status = AE_NO_MEMORY;
764 goto error_exit;
765 }
766
767 /* Save the new Info arrays in the GPE block */
768
769 gpe_block->register_info = gpe_register_info;
770 gpe_block->event_info = gpe_event_info;
771
772 /*
773 * Initialize the GPE Register and Event structures. A goal of these
774 * tables is to hide the fact that there are two separate GPE register sets
775 * in a given gpe hardware block, the status registers occupy the first half,
776 * and the enable registers occupy the second half.
777 */
778 this_register = gpe_register_info;
779 this_event = gpe_event_info;
780
781 for (i = 0; i < gpe_block->register_count; i++) {
782 /* Init the register_info for this GPE register (8 GPEs) */
783
784 this_register->base_gpe_number = (u8) (gpe_block->block_base_number +
785 (i * ACPI_GPE_REGISTER_WIDTH));
786
787 ACPI_STORE_ADDRESS (this_register->status_address.address,
788 (gpe_block->block_address.address
789 + i));
790
791 ACPI_STORE_ADDRESS (this_register->enable_address.address,
792 (gpe_block->block_address.address
793 + i
794 + gpe_block->register_count));
795
796 this_register->status_address.address_space_id = gpe_block->block_address.address_space_id;
797 this_register->enable_address.address_space_id = gpe_block->block_address.address_space_id;
798 this_register->status_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH;
799 this_register->enable_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH;
800 this_register->status_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH;
801 this_register->enable_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH;
802
803 /* Init the event_info for each GPE within this register */
804
805 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
806 this_event->register_bit = acpi_gbl_decode_to8bit[j];
807 this_event->register_info = this_register;
808 this_event++;
809 }
810
811 /*
812 * Clear the status/enable registers. Note that status registers
813 * are cleared by writing a '1', while enable registers are cleared
814 * by writing a '0'.
815 */
816 status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0x00,
817 &this_register->enable_address);
818 if (ACPI_FAILURE (status)) {
819 goto error_exit;
820 }
821
822 status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0xFF,
823 &this_register->status_address);
824 if (ACPI_FAILURE (status)) {
825 goto error_exit;
826 }
827
828 this_register++;
829 }
830
831 return_ACPI_STATUS (AE_OK);
832
833
834error_exit:
835 if (gpe_register_info) {
836 ACPI_MEM_FREE (gpe_register_info);
837 }
838 if (gpe_event_info) {
839 ACPI_MEM_FREE (gpe_event_info);
840 }
841
842 return_ACPI_STATUS (status);
843}
844
845
846/*******************************************************************************
847 *
848 * FUNCTION: acpi_ev_create_gpe_block
849 *
850 * PARAMETERS: gpe_device - Handle to the parent GPE block
851 * gpe_block_address - Address and space_iD
852 * register_count - Number of GPE register pairs in the block
853 * gpe_block_base_number - Starting GPE number for the block
854 * interrupt_level - H/W interrupt for the block
855 * return_gpe_block - Where the new block descriptor is returned
856 *
857 * RETURN: Status
858 *
859 * DESCRIPTION: Create and Install a block of GPE registers
860 *
861 ******************************************************************************/
862
863acpi_status
864acpi_ev_create_gpe_block (
865 struct acpi_namespace_node *gpe_device,
866 struct acpi_generic_address *gpe_block_address,
867 u32 register_count,
868 u8 gpe_block_base_number,
869 u32 interrupt_level,
870 struct acpi_gpe_block_info **return_gpe_block)
871{
872 struct acpi_gpe_block_info *gpe_block;
873 struct acpi_gpe_event_info *gpe_event_info;
874 acpi_native_uint i;
875 acpi_native_uint j;
876 u32 wake_gpe_count;
877 u32 gpe_enabled_count;
878 acpi_status status;
879 struct acpi_gpe_walk_info gpe_info;
880
881
882 ACPI_FUNCTION_TRACE ("ev_create_gpe_block");
883
884
885 if (!register_count) {
886 return_ACPI_STATUS (AE_OK);
887 }
888
889 /* Allocate a new GPE block */
890
891 gpe_block = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_block_info));
892 if (!gpe_block) {
893 return_ACPI_STATUS (AE_NO_MEMORY);
894 }
895
896 /* Initialize the new GPE block */
897
898 gpe_block->register_count = register_count;
899 gpe_block->block_base_number = gpe_block_base_number;
900 gpe_block->node = gpe_device;
901
902 ACPI_MEMCPY (&gpe_block->block_address, gpe_block_address, sizeof (struct acpi_generic_address));
903
904 /* Create the register_info and event_info sub-structures */
905
906 status = acpi_ev_create_gpe_info_blocks (gpe_block);
907 if (ACPI_FAILURE (status)) {
908 ACPI_MEM_FREE (gpe_block);
909 return_ACPI_STATUS (status);
910 }
911
912 /* Install the new block in the global list(s) */
913
914 status = acpi_ev_install_gpe_block (gpe_block, interrupt_level);
915 if (ACPI_FAILURE (status)) {
916 ACPI_MEM_FREE (gpe_block);
917 return_ACPI_STATUS (status);
918 }
919
920 /* Find all GPE methods (_Lxx, _Exx) for this block */
921
922 status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device,
923 ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, acpi_ev_save_method_info,
924 gpe_block, NULL);
925
926 /*
927 * Runtime option: Should Wake GPEs be enabled at runtime? The default
928 * is No, they should only be enabled just as the machine goes to sleep.
929 */
930 if (acpi_gbl_leave_wake_gpes_disabled) {
931 /*
932 * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods.
933 * (Each GPE that has one or more _PRWs that reference it is by
934 * definition a WAKE GPE and will not be enabled while the machine
935 * is running.)
936 */
937 gpe_info.gpe_block = gpe_block;
938 gpe_info.gpe_device = gpe_device;
939
940 status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
941 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_match_prw_and_gpe,
942 &gpe_info, NULL);
943 }
944
945 /*
946 * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs,
947 * and 2) have a corresponding _Lxx or _Exx method. All other GPEs must
948 * be enabled via the acpi_enable_gpe() external interface.
949 */
950 wake_gpe_count = 0;
951 gpe_enabled_count = 0;
952
953 for (i = 0; i < gpe_block->register_count; i++) {
954 for (j = 0; j < 8; j++) {
955 /* Get the info block for this particular GPE */
956
957 gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
958
959 if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) &&
960 (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) {
961 gpe_enabled_count++;
962 }
963
964 if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) {
965 wake_gpe_count++;
966 }
967 }
968 }
969
970 /* Dump info about this GPE block */
971
972 ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
973 "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
974 (u32) gpe_block->block_base_number,
975 (u32) (gpe_block->block_base_number +
976 ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
977 gpe_device->name.ascii,
978 gpe_block->register_count,
979 interrupt_level));
980
981 /* Enable all valid GPEs found above */
982
983 status = acpi_hw_enable_runtime_gpe_block (NULL, gpe_block);
984
985 ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
986 "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
987 wake_gpe_count, gpe_enabled_count));
988
989 /* Return the new block */
990
991 if (return_gpe_block) {
992 (*return_gpe_block) = gpe_block;
993 }
994
995 return_ACPI_STATUS (AE_OK);
996}
997
998
999/*******************************************************************************
1000 *
1001 * FUNCTION: acpi_ev_gpe_initialize
1002 *
1003 * PARAMETERS: None
1004 *
1005 * RETURN: Status
1006 *
1007 * DESCRIPTION: Initialize the GPE data structures
1008 *
1009 ******************************************************************************/
1010
1011acpi_status
1012acpi_ev_gpe_initialize (
1013 void)
1014{
1015 u32 register_count0 = 0;
1016 u32 register_count1 = 0;
1017 u32 gpe_number_max = 0;
1018 acpi_status status;
1019
1020
1021 ACPI_FUNCTION_TRACE ("ev_gpe_initialize");
1022
1023
1024 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
1025 if (ACPI_FAILURE (status)) {
1026 return_ACPI_STATUS (status);
1027 }
1028
1029 /*
1030 * Initialize the GPE Block(s) defined in the FADT
1031 *
1032 * Why the GPE register block lengths are divided by 2: From the ACPI Spec,
1033 * section "General-Purpose Event Registers", we have:
1034 *
1035 * "Each register block contains two registers of equal length
1036 * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
1037 * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
1038 * The length of the GPE1_STS and GPE1_EN registers is equal to
1039 * half the GPE1_LEN. If a generic register block is not supported
1040 * then its respective block pointer and block length values in the
1041 * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
1042 * to be the same size."
1043 */
1044
1045 /*
1046 * Determine the maximum GPE number for this machine.
1047 *
1048 * Note: both GPE0 and GPE1 are optional, and either can exist without
1049 * the other.
1050 *
1051 * If EITHER the register length OR the block address are zero, then that
1052 * particular block is not supported.
1053 */
1054 if (acpi_gbl_FADT->gpe0_blk_len &&
1055 acpi_gbl_FADT->xgpe0_blk.address) {
1056 /* GPE block 0 exists (has both length and address > 0) */
1057
1058 register_count0 = (u16) (acpi_gbl_FADT->gpe0_blk_len / 2);
1059
1060 gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
1061
1062 /* Install GPE Block 0 */
1063
1064 status = acpi_ev_create_gpe_block (acpi_gbl_fadt_gpe_device, &acpi_gbl_FADT->xgpe0_blk,
1065 register_count0, 0, acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[0]);
1066
1067 if (ACPI_FAILURE (status)) {
1068 ACPI_REPORT_ERROR ((
1069 "Could not create GPE Block 0, %s\n",
1070 acpi_format_exception (status)));
1071 }
1072 }
1073
1074 if (acpi_gbl_FADT->gpe1_blk_len &&
1075 acpi_gbl_FADT->xgpe1_blk.address) {
1076 /* GPE block 1 exists (has both length and address > 0) */
1077
1078 register_count1 = (u16) (acpi_gbl_FADT->gpe1_blk_len / 2);
1079
1080 /* Check for GPE0/GPE1 overlap (if both banks exist) */
1081
1082 if ((register_count0) &&
1083 (gpe_number_max >= acpi_gbl_FADT->gpe1_base)) {
1084 ACPI_REPORT_ERROR ((
1085 "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1\n",
1086 gpe_number_max, acpi_gbl_FADT->gpe1_base,
1087 acpi_gbl_FADT->gpe1_base +
1088 ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
1089
1090 /* Ignore GPE1 block by setting the register count to zero */
1091
1092 register_count1 = 0;
1093 }
1094 else {
1095 /* Install GPE Block 1 */
1096
1097 status = acpi_ev_create_gpe_block (acpi_gbl_fadt_gpe_device, &acpi_gbl_FADT->xgpe1_blk,
1098 register_count1, acpi_gbl_FADT->gpe1_base,
1099 acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[1]);
1100
1101 if (ACPI_FAILURE (status)) {
1102 ACPI_REPORT_ERROR ((
1103 "Could not create GPE Block 1, %s\n",
1104 acpi_format_exception (status)));
1105 }
1106
1107 /*
1108 * GPE0 and GPE1 do not have to be contiguous in the GPE number
1109 * space. However, GPE0 always starts at GPE number zero.
1110 */
1111 gpe_number_max = acpi_gbl_FADT->gpe1_base +
1112 ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1);
1113 }
1114 }
1115
1116 /* Exit if there are no GPE registers */
1117
1118 if ((register_count0 + register_count1) == 0) {
1119 /* GPEs are not required by ACPI, this is OK */
1120
1121 ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
1122 "There are no GPE blocks defined in the FADT\n"));
1123 status = AE_OK;
1124 goto cleanup;
1125 }
1126
1127 /* Check for Max GPE number out-of-range */
1128
1129 if (gpe_number_max > ACPI_GPE_MAX) {
1130 ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n",
1131 gpe_number_max));
1132 status = AE_BAD_VALUE;
1133 goto cleanup;
1134 }
1135
1136cleanup:
1137 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
1138 return_ACPI_STATUS (AE_OK);
1139}
1140
1141
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
new file mode 100644
index 000000000000..2548efa7a45f
--- /dev/null
+++ b/drivers/acpi/events/evmisc.c
@@ -0,0 +1,588 @@
1/******************************************************************************
2 *
3 * Module Name: evmisc - Miscellaneous event manager support functions
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include <acpi/acevents.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acinterp.h>
48
49#define _COMPONENT ACPI_EVENTS
50 ACPI_MODULE_NAME ("evmisc")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ev_is_notify_object
56 *
57 * PARAMETERS: Node - Node to check
58 *
59 * RETURN: TRUE if notifies allowed on this object
60 *
61 * DESCRIPTION: Check type of node for a object that supports notifies.
62 *
63 * TBD: This could be replaced by a flag bit in the node.
64 *
65 ******************************************************************************/
66
67u8
68acpi_ev_is_notify_object (
69 struct acpi_namespace_node *node)
70{
71 switch (node->type) {
72 case ACPI_TYPE_DEVICE:
73 case ACPI_TYPE_PROCESSOR:
74 case ACPI_TYPE_POWER:
75 case ACPI_TYPE_THERMAL:
76 /*
77 * These are the ONLY objects that can receive ACPI notifications
78 */
79 return (TRUE);
80
81 default:
82 return (FALSE);
83 }
84}
85
86
87/*******************************************************************************
88 *
89 * FUNCTION: acpi_ev_queue_notify_request
90 *
91 * PARAMETERS: Node - NS node for the notified object
92 * notify_value - Value from the Notify() request
93 *
94 * RETURN: Status
95 *
96 * DESCRIPTION: Dispatch a device notification event to a previously
97 * installed handler.
98 *
99 ******************************************************************************/
100
101#ifdef ACPI_DEBUG_OUTPUT
102static const char *acpi_notify_value_names[] =
103{
104 "Bus Check",
105 "Device Check",
106 "Device Wake",
107 "Eject request",
108 "Device Check Light",
109 "Frequency Mismatch",
110 "Bus Mode Mismatch",
111 "Power Fault"
112};
113#endif
114
115acpi_status
116acpi_ev_queue_notify_request (
117 struct acpi_namespace_node *node,
118 u32 notify_value)
119{
120 union acpi_operand_object *obj_desc;
121 union acpi_operand_object *handler_obj = NULL;
122 union acpi_generic_state *notify_info;
123 acpi_status status = AE_OK;
124
125
126 ACPI_FUNCTION_NAME ("ev_queue_notify_request");
127
128
129 /*
130 * For value 3 (Ejection Request), some device method may need to be run.
131 * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run.
132 * For value 0x80 (Status Change) on the power button or sleep button,
133 * initiate soft-off or sleep operation?
134 */
135 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
136 "Dispatching Notify(%X) on node %p\n", notify_value, node));
137
138 if (notify_value <= 7) {
139 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: %s\n",
140 acpi_notify_value_names[notify_value]));
141 }
142 else {
143 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: 0x%2.2X **Device Specific**\n",
144 notify_value));
145 }
146
147 /* Get the notify object attached to the NS Node */
148
149 obj_desc = acpi_ns_get_attached_object (node);
150 if (obj_desc) {
151 /* We have the notify object, Get the right handler */
152
153 switch (node->type) {
154 case ACPI_TYPE_DEVICE:
155 case ACPI_TYPE_THERMAL:
156 case ACPI_TYPE_PROCESSOR:
157 case ACPI_TYPE_POWER:
158
159 if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
160 handler_obj = obj_desc->common_notify.system_notify;
161 }
162 else {
163 handler_obj = obj_desc->common_notify.device_notify;
164 }
165 break;
166
167 default:
168 /* All other types are not supported */
169 return (AE_TYPE);
170 }
171 }
172
173 /* If there is any handler to run, schedule the dispatcher */
174
175 if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) ||
176 (acpi_gbl_device_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) ||
177 handler_obj) {
178 notify_info = acpi_ut_create_generic_state ();
179 if (!notify_info) {
180 return (AE_NO_MEMORY);
181 }
182
183 notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY;
184 notify_info->notify.node = node;
185 notify_info->notify.value = (u16) notify_value;
186 notify_info->notify.handler_obj = handler_obj;
187
188 status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH,
189 acpi_ev_notify_dispatch, notify_info);
190 if (ACPI_FAILURE (status)) {
191 acpi_ut_delete_generic_state (notify_info);
192 }
193 }
194
195 if (!handler_obj) {
196 /*
197 * There is no per-device notify handler for this device.
198 * This may or may not be a problem.
199 */
200 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
201 "No notify handler for Notify(%4.4s, %X) node %p\n",
202 acpi_ut_get_node_name (node), notify_value, node));
203 }
204
205 return (status);
206}
207
208
209/*******************************************************************************
210 *
211 * FUNCTION: acpi_ev_notify_dispatch
212 *
213 * PARAMETERS: Context - To be passsed to the notify handler
214 *
215 * RETURN: None.
216 *
217 * DESCRIPTION: Dispatch a device notification event to a previously
218 * installed handler.
219 *
220 ******************************************************************************/
221
222void ACPI_SYSTEM_XFACE
223acpi_ev_notify_dispatch (
224 void *context)
225{
226 union acpi_generic_state *notify_info = (union acpi_generic_state *) context;
227 acpi_notify_handler global_handler = NULL;
228 void *global_context = NULL;
229 union acpi_operand_object *handler_obj;
230
231
232 ACPI_FUNCTION_ENTRY ();
233
234
235 /*
236 * We will invoke a global notify handler if installed.
237 * This is done _before_ we invoke the per-device handler attached to the device.
238 */
239 if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) {
240 /* Global system notification handler */
241
242 if (acpi_gbl_system_notify.handler) {
243 global_handler = acpi_gbl_system_notify.handler;
244 global_context = acpi_gbl_system_notify.context;
245 }
246 }
247 else {
248 /* Global driver notification handler */
249
250 if (acpi_gbl_device_notify.handler) {
251 global_handler = acpi_gbl_device_notify.handler;
252 global_context = acpi_gbl_device_notify.context;
253 }
254 }
255
256 /* Invoke the system handler first, if present */
257
258 if (global_handler) {
259 global_handler (notify_info->notify.node, notify_info->notify.value, global_context);
260 }
261
262 /* Now invoke the per-device handler, if present */
263
264 handler_obj = notify_info->notify.handler_obj;
265 if (handler_obj) {
266 handler_obj->notify.handler (notify_info->notify.node, notify_info->notify.value,
267 handler_obj->notify.context);
268 }
269
270 /* All done with the info object */
271
272 acpi_ut_delete_generic_state (notify_info);
273}
274
275
276/*******************************************************************************
277 *
278 * FUNCTION: acpi_ev_global_lock_thread
279 *
280 * PARAMETERS: Context - From thread interface, not used
281 *
282 * RETURN: None
283 *
284 * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the
285 * Global Lock. Simply signal all threads that are waiting
286 * for the lock.
287 *
288 ******************************************************************************/
289
290static void ACPI_SYSTEM_XFACE
291acpi_ev_global_lock_thread (
292 void *context)
293{
294 acpi_status status;
295
296
297 /* Signal threads that are waiting for the lock */
298
299 if (acpi_gbl_global_lock_thread_count) {
300 /* Send sufficient units to the semaphore */
301
302 status = acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore,
303 acpi_gbl_global_lock_thread_count);
304 if (ACPI_FAILURE (status)) {
305 ACPI_REPORT_ERROR (("Could not signal Global Lock semaphore\n"));
306 }
307 }
308}
309
310
311/*******************************************************************************
312 *
313 * FUNCTION: acpi_ev_global_lock_handler
314 *
315 * PARAMETERS: Context - From thread interface, not used
316 *
317 * RETURN: ACPI_INTERRUPT_HANDLED or ACPI_INTERRUPT_NOT_HANDLED
318 *
319 * DESCRIPTION: Invoked directly from the SCI handler when a global lock
320 * release interrupt occurs. Grab the global lock and queue
321 * the global lock thread for execution
322 *
323 ******************************************************************************/
324
325static u32
326acpi_ev_global_lock_handler (
327 void *context)
328{
329 u8 acquired = FALSE;
330 acpi_status status;
331
332
333 /*
334 * Attempt to get the lock
335 * If we don't get it now, it will be marked pending and we will
336 * take another interrupt when it becomes free.
337 */
338 ACPI_ACQUIRE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, acquired);
339 if (acquired) {
340 /* Got the lock, now wake all threads waiting for it */
341
342 acpi_gbl_global_lock_acquired = TRUE;
343
344 /* Run the Global Lock thread which will signal all waiting threads */
345
346 status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH,
347 acpi_ev_global_lock_thread, context);
348 if (ACPI_FAILURE (status)) {
349 ACPI_REPORT_ERROR (("Could not queue Global Lock thread, %s\n",
350 acpi_format_exception (status)));
351
352 return (ACPI_INTERRUPT_NOT_HANDLED);
353 }
354 }
355
356 return (ACPI_INTERRUPT_HANDLED);
357}
358
359
360/*******************************************************************************
361 *
362 * FUNCTION: acpi_ev_init_global_lock_handler
363 *
364 * PARAMETERS: None
365 *
366 * RETURN: Status
367 *
368 * DESCRIPTION: Install a handler for the global lock release event
369 *
370 ******************************************************************************/
371
372acpi_status
373acpi_ev_init_global_lock_handler (void)
374{
375 acpi_status status;
376
377
378 ACPI_FUNCTION_TRACE ("ev_init_global_lock_handler");
379
380
381 acpi_gbl_global_lock_present = TRUE;
382 status = acpi_install_fixed_event_handler (ACPI_EVENT_GLOBAL,
383 acpi_ev_global_lock_handler, NULL);
384
385 /*
386 * If the global lock does not exist on this platform, the attempt
387 * to enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick)
388 * Map to AE_OK, but mark global lock as not present.
389 * Any attempt to actually use the global lock will be flagged
390 * with an error.
391 */
392 if (status == AE_NO_HARDWARE_RESPONSE) {
393 acpi_gbl_global_lock_present = FALSE;
394 status = AE_OK;
395 }
396
397 return_ACPI_STATUS (status);
398}
399
400
401/******************************************************************************
402 *
403 * FUNCTION: acpi_ev_acquire_global_lock
404 *
405 * PARAMETERS: Timeout - Max time to wait for the lock, in millisec.
406 *
407 * RETURN: Status
408 *
409 * DESCRIPTION: Attempt to gain ownership of the Global Lock.
410 *
411 *****************************************************************************/
412
413acpi_status
414acpi_ev_acquire_global_lock (
415 u16 timeout)
416{
417 acpi_status status = AE_OK;
418 u8 acquired = FALSE;
419
420
421 ACPI_FUNCTION_TRACE ("ev_acquire_global_lock");
422
423
424#ifndef ACPI_APPLICATION
425 /* Make sure that we actually have a global lock */
426
427 if (!acpi_gbl_global_lock_present) {
428 return_ACPI_STATUS (AE_NO_GLOBAL_LOCK);
429 }
430#endif
431
432 /* One more thread wants the global lock */
433
434 acpi_gbl_global_lock_thread_count++;
435
436 /* If we (OS side vs. BIOS side) have the hardware lock already, we are done */
437
438 if (acpi_gbl_global_lock_acquired) {
439 return_ACPI_STATUS (AE_OK);
440 }
441
442 /* We must acquire the actual hardware lock */
443
444 ACPI_ACQUIRE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, acquired);
445 if (acquired) {
446 /* We got the lock */
447
448 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Acquired the HW Global Lock\n"));
449
450 acpi_gbl_global_lock_acquired = TRUE;
451 return_ACPI_STATUS (AE_OK);
452 }
453
454 /*
455 * Did not get the lock. The pending bit was set above, and we must now
456 * wait until we get the global lock released interrupt.
457 */
458 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n"));
459
460 /*
461 * Acquire the global lock semaphore first.
462 * Since this wait will block, we must release the interpreter
463 */
464 status = acpi_ex_system_wait_semaphore (acpi_gbl_global_lock_semaphore,
465 timeout);
466 return_ACPI_STATUS (status);
467}
468
469
470/*******************************************************************************
471 *
472 * FUNCTION: acpi_ev_release_global_lock
473 *
474 * PARAMETERS: None
475 *
476 * RETURN: Status
477 *
478 * DESCRIPTION: Releases ownership of the Global Lock.
479 *
480 ******************************************************************************/
481
482acpi_status
483acpi_ev_release_global_lock (void)
484{
485 u8 pending = FALSE;
486 acpi_status status = AE_OK;
487
488
489 ACPI_FUNCTION_TRACE ("ev_release_global_lock");
490
491
492 if (!acpi_gbl_global_lock_thread_count) {
493 ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n"));
494 return_ACPI_STATUS (AE_NOT_ACQUIRED);
495 }
496
497 /* One fewer thread has the global lock */
498
499 acpi_gbl_global_lock_thread_count--;
500 if (acpi_gbl_global_lock_thread_count) {
501 /* There are still some threads holding the lock, cannot release */
502
503 return_ACPI_STATUS (AE_OK);
504 }
505
506 /*
507 * No more threads holding lock, we can do the actual hardware
508 * release
509 */
510 ACPI_RELEASE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, pending);
511 acpi_gbl_global_lock_acquired = FALSE;
512
513 /*
514 * If the pending bit was set, we must write GBL_RLS to the control
515 * register
516 */
517 if (pending) {
518 status = acpi_set_register (ACPI_BITREG_GLOBAL_LOCK_RELEASE, 1, ACPI_MTX_LOCK);
519 }
520
521 return_ACPI_STATUS (status);
522}
523
524
525/******************************************************************************
526 *
527 * FUNCTION: acpi_ev_terminate
528 *
529 * PARAMETERS: none
530 *
531 * RETURN: none
532 *
533 * DESCRIPTION: Disable events and free memory allocated for table storage.
534 *
535 ******************************************************************************/
536
537void
538acpi_ev_terminate (void)
539{
540 acpi_native_uint i;
541 acpi_status status;
542
543
544 ACPI_FUNCTION_TRACE ("ev_terminate");
545
546
547 if (acpi_gbl_events_initialized) {
548 /*
549 * Disable all event-related functionality.
550 * In all cases, on error, print a message but obviously we don't abort.
551 */
552
553 /* Disable all fixed events */
554
555 for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
556 status = acpi_disable_event ((u32) i, 0);
557 if (ACPI_FAILURE (status)) {
558 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not disable fixed event %d\n", (u32) i));
559 }
560 }
561
562 /* Disable all GPEs in all GPE blocks */
563
564 status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, ACPI_NOT_ISR);
565
566 /* Remove SCI handler */
567
568 status = acpi_ev_remove_sci_handler ();
569 if (ACPI_FAILURE(status)) {
570 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not remove SCI handler\n"));
571 }
572 }
573
574 /* Deallocate all handler objects installed within GPE info structs */
575
576 status = acpi_ev_walk_gpe_list (acpi_ev_delete_gpe_handlers, ACPI_NOT_ISR);
577
578 /* Return to original mode if necessary */
579
580 if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
581 status = acpi_disable ();
582 if (ACPI_FAILURE (status)) {
583 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "acpi_disable failed\n"));
584 }
585 }
586 return_VOID;
587}
588
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
new file mode 100644
index 000000000000..772342708a7a
--- /dev/null
+++ b/drivers/acpi/events/evregion.c
@@ -0,0 +1,1067 @@
1/******************************************************************************
2 *
3 * Module Name: evregion - ACPI address_space (op_region) handler dispatch
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acevents.h>
47#include <acpi/acnamesp.h>
48#include <acpi/acinterp.h>
49
50#define _COMPONENT ACPI_EVENTS
51 ACPI_MODULE_NAME ("evregion")
52
53#define ACPI_NUM_DEFAULT_SPACES 4
54
55static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
56 ACPI_ADR_SPACE_SYSTEM_MEMORY,
57 ACPI_ADR_SPACE_SYSTEM_IO,
58 ACPI_ADR_SPACE_PCI_CONFIG,
59 ACPI_ADR_SPACE_DATA_TABLE};
60
61
62/*******************************************************************************
63 *
64 * FUNCTION: acpi_ev_install_region_handlers
65 *
66 * PARAMETERS: None
67 *
68 * RETURN: Status
69 *
70 * DESCRIPTION: Installs the core subsystem default address space handlers.
71 *
72 ******************************************************************************/
73
74acpi_status
75acpi_ev_install_region_handlers (
76 void) {
77 acpi_status status;
78 acpi_native_uint i;
79
80
81 ACPI_FUNCTION_TRACE ("ev_install_region_handlers");
82
83
84 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
85 if (ACPI_FAILURE (status)) {
86 return_ACPI_STATUS (status);
87 }
88
89 /*
90 * All address spaces (PCI Config, EC, SMBus) are scope dependent
91 * and registration must occur for a specific device.
92 *
93 * In the case of the system memory and IO address spaces there is currently
94 * no device associated with the address space. For these we use the root.
95 *
96 * We install the default PCI config space handler at the root so
97 * that this space is immediately available even though the we have
98 * not enumerated all the PCI Root Buses yet. This is to conform
99 * to the ACPI specification which states that the PCI config
100 * space must be always available -- even though we are nowhere
101 * near ready to find the PCI root buses at this point.
102 *
103 * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
104 * has already been installed (via acpi_install_address_space_handler).
105 * Similar for AE_SAME_HANDLER.
106 */
107 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
108 status = acpi_ev_install_space_handler (acpi_gbl_root_node,
109 acpi_gbl_default_address_spaces[i],
110 ACPI_DEFAULT_HANDLER, NULL, NULL);
111 switch (status) {
112 case AE_OK:
113 case AE_SAME_HANDLER:
114 case AE_ALREADY_EXISTS:
115
116 /* These exceptions are all OK */
117
118 status = AE_OK;
119 break;
120
121 default:
122
123 goto unlock_and_exit;
124 }
125 }
126
127unlock_and_exit:
128 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
129 return_ACPI_STATUS (status);
130}
131
132
133/*******************************************************************************
134 *
135 * FUNCTION: acpi_ev_initialize_op_regions
136 *
137 * PARAMETERS: None
138 *
139 * RETURN: Status
140 *
141 * DESCRIPTION: Execute _REG methods for all Operation Regions that have
142 * an installed default region handler.
143 *
144 ******************************************************************************/
145
146acpi_status
147acpi_ev_initialize_op_regions (
148 void)
149{
150 acpi_status status;
151 acpi_native_uint i;
152
153
154 ACPI_FUNCTION_TRACE ("ev_initialize_op_regions");
155
156
157 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
158 if (ACPI_FAILURE (status)) {
159 return_ACPI_STATUS (status);
160 }
161
162 /*
163 * Run the _REG methods for op_regions in each default address space
164 */
165 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
166 /* TBD: Make sure handler is the DEFAULT handler, otherwise
167 * _REG will have already been run.
168 */
169 status = acpi_ev_execute_reg_methods (acpi_gbl_root_node,
170 acpi_gbl_default_address_spaces[i]);
171 }
172
173 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
174 return_ACPI_STATUS (status);
175}
176
177
178/*******************************************************************************
179 *
180 * FUNCTION: acpi_ev_execute_reg_method
181 *
182 * PARAMETERS: region_obj - Object structure
183 * Function - Passed to _REG: On (1) or Off (0)
184 *
185 * RETURN: Status
186 *
187 * DESCRIPTION: Execute _REG method for a region
188 *
189 ******************************************************************************/
190
191acpi_status
192acpi_ev_execute_reg_method (
193 union acpi_operand_object *region_obj,
194 u32 function)
195{
196 struct acpi_parameter_info info;
197 union acpi_operand_object *params[3];
198 union acpi_operand_object *region_obj2;
199 acpi_status status;
200
201
202 ACPI_FUNCTION_TRACE ("ev_execute_reg_method");
203
204
205 region_obj2 = acpi_ns_get_secondary_object (region_obj);
206 if (!region_obj2) {
207 return_ACPI_STATUS (AE_NOT_EXIST);
208 }
209
210 if (region_obj2->extra.method_REG == NULL) {
211 return_ACPI_STATUS (AE_OK);
212 }
213
214 /*
215 * The _REG method has two arguments:
216 *
217 * Arg0, Integer: Operation region space ID
218 * Same value as region_obj->Region.space_id
219 * Arg1, Integer: connection status
220 * 1 for connecting the handler,
221 * 0 for disconnecting the handler
222 * Passed as a parameter
223 */
224 params[0] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
225 if (!params[0]) {
226 return_ACPI_STATUS (AE_NO_MEMORY);
227 }
228
229 params[1] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
230 if (!params[1]) {
231 status = AE_NO_MEMORY;
232 goto cleanup;
233 }
234
235 /* Setup the parameter objects */
236
237 params[0]->integer.value = region_obj->region.space_id;
238 params[1]->integer.value = function;
239 params[2] = NULL;
240
241 info.node = region_obj2->extra.method_REG;
242 info.parameters = params;
243 info.parameter_type = ACPI_PARAM_ARGS;
244
245 /* Execute the method, no return value */
246
247 ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (
248 ACPI_TYPE_METHOD, info.node, NULL));
249 status = acpi_ns_evaluate_by_handle (&info);
250
251 acpi_ut_remove_reference (params[1]);
252
253cleanup:
254 acpi_ut_remove_reference (params[0]);
255
256 return_ACPI_STATUS (status);
257}
258
259
260/*******************************************************************************
261 *
262 * FUNCTION: acpi_ev_address_space_dispatch
263 *
264 * PARAMETERS: region_obj - Internal region object
265 * Function - Read or Write operation
266 * Address - Where in the space to read or write
267 * bit_width - Field width in bits (8, 16, 32, or 64)
268 * Value - Pointer to in or out value
269 *
270 * RETURN: Status
271 *
272 * DESCRIPTION: Dispatch an address space or operation region access to
273 * a previously installed handler.
274 *
275 ******************************************************************************/
276
277acpi_status
278acpi_ev_address_space_dispatch (
279 union acpi_operand_object *region_obj,
280 u32 function,
281 acpi_physical_address address,
282 u32 bit_width,
283 void *value)
284{
285 acpi_status status;
286 acpi_status status2;
287 acpi_adr_space_handler handler;
288 acpi_adr_space_setup region_setup;
289 union acpi_operand_object *handler_desc;
290 union acpi_operand_object *region_obj2;
291 void *region_context = NULL;
292
293
294 ACPI_FUNCTION_TRACE ("ev_address_space_dispatch");
295
296
297 region_obj2 = acpi_ns_get_secondary_object (region_obj);
298 if (!region_obj2) {
299 return_ACPI_STATUS (AE_NOT_EXIST);
300 }
301
302 /* Ensure that there is a handler associated with this region */
303
304 handler_desc = region_obj->region.handler;
305 if (!handler_desc) {
306 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
307 "No handler for Region [%4.4s] (%p) [%s]\n",
308 acpi_ut_get_node_name (region_obj->region.node),
309 region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
310
311 return_ACPI_STATUS (AE_NOT_EXIST);
312 }
313
314 /*
315 * It may be the case that the region has never been initialized
316 * Some types of regions require special init code
317 */
318 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
319 /*
320 * This region has not been initialized yet, do it
321 */
322 region_setup = handler_desc->address_space.setup;
323 if (!region_setup) {
324 /* No initialization routine, exit with error */
325
326 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n",
327 region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
328 return_ACPI_STATUS (AE_NOT_EXIST);
329 }
330
331 /*
332 * We must exit the interpreter because the region setup will potentially
333 * execute control methods (e.g., _REG method for this region)
334 */
335 acpi_ex_exit_interpreter ();
336
337 status = region_setup (region_obj, ACPI_REGION_ACTIVATE,
338 handler_desc->address_space.context, &region_context);
339
340 /* Re-enter the interpreter */
341
342 status2 = acpi_ex_enter_interpreter ();
343 if (ACPI_FAILURE (status2)) {
344 return_ACPI_STATUS (status2);
345 }
346
347 /* Check for failure of the Region Setup */
348
349 if (ACPI_FAILURE (status)) {
350 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
351 acpi_format_exception (status),
352 acpi_ut_get_region_name (region_obj->region.space_id)));
353 return_ACPI_STATUS (status);
354 }
355
356 /*
357 * Region initialization may have been completed by region_setup
358 */
359 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
360 region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
361
362 if (region_obj2->extra.region_context) {
363 /* The handler for this region was already installed */
364
365 ACPI_MEM_FREE (region_context);
366 }
367 else {
368 /*
369 * Save the returned context for use in all accesses to
370 * this particular region
371 */
372 region_obj2->extra.region_context = region_context;
373 }
374 }
375 }
376
377 /* We have everything we need, we can invoke the address space handler */
378
379 handler = handler_desc->address_space.handler;
380
381 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
382 "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
383 &region_obj->region.handler->address_space, handler,
384 ACPI_FORMAT_UINT64 (address),
385 acpi_ut_get_region_name (region_obj->region.space_id)));
386
387 if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
388 /*
389 * For handlers other than the default (supplied) handlers, we must
390 * exit the interpreter because the handler *might* block -- we don't
391 * know what it will do, so we can't hold the lock on the intepreter.
392 */
393 acpi_ex_exit_interpreter();
394 }
395
396 /* Call the handler */
397
398 status = handler (function, address, bit_width, value,
399 handler_desc->address_space.context,
400 region_obj2->extra.region_context);
401
402 if (ACPI_FAILURE (status)) {
403 ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n",
404 acpi_ut_get_region_name (region_obj->region.space_id),
405 acpi_format_exception (status)));
406 }
407
408 if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
409 /*
410 * We just returned from a non-default handler, we must re-enter the
411 * interpreter
412 */
413 status2 = acpi_ex_enter_interpreter ();
414 if (ACPI_FAILURE (status2)) {
415 return_ACPI_STATUS (status2);
416 }
417 }
418
419 return_ACPI_STATUS (status);
420}
421
422
423/*******************************************************************************
424 *
425 * FUNCTION: acpi_ev_detach_region
426 *
427 * PARAMETERS: region_obj - Region Object
428 * acpi_ns_is_locked - Namespace Region Already Locked?
429 *
430 * RETURN: None
431 *
432 * DESCRIPTION: Break the association between the handler and the region
433 * this is a two way association.
434 *
435 ******************************************************************************/
436
437void
438acpi_ev_detach_region(
439 union acpi_operand_object *region_obj,
440 u8 acpi_ns_is_locked)
441{
442 union acpi_operand_object *handler_obj;
443 union acpi_operand_object *obj_desc;
444 union acpi_operand_object **last_obj_ptr;
445 acpi_adr_space_setup region_setup;
446 void **region_context;
447 union acpi_operand_object *region_obj2;
448 acpi_status status;
449
450
451 ACPI_FUNCTION_TRACE ("ev_detach_region");
452
453
454 region_obj2 = acpi_ns_get_secondary_object (region_obj);
455 if (!region_obj2) {
456 return_VOID;
457 }
458 region_context = &region_obj2->extra.region_context;
459
460 /* Get the address handler from the region object */
461
462 handler_obj = region_obj->region.handler;
463 if (!handler_obj) {
464 /* This region has no handler, all done */
465
466 return_VOID;
467 }
468
469 /* Find this region in the handler's list */
470
471 obj_desc = handler_obj->address_space.region_list;
472 last_obj_ptr = &handler_obj->address_space.region_list;
473
474 while (obj_desc) {
475 /* Is this the correct Region? */
476
477 if (obj_desc == region_obj) {
478 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
479 "Removing Region %p from address handler %p\n",
480 region_obj, handler_obj));
481
482 /* This is it, remove it from the handler's list */
483
484 *last_obj_ptr = obj_desc->region.next;
485 obj_desc->region.next = NULL; /* Must clear field */
486
487 if (acpi_ns_is_locked) {
488 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
489 if (ACPI_FAILURE (status)) {
490 return_VOID;
491 }
492 }
493
494 /* Now stop region accesses by executing the _REG method */
495
496 status = acpi_ev_execute_reg_method (region_obj, 0);
497 if (ACPI_FAILURE (status)) {
498 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n",
499 acpi_format_exception (status),
500 acpi_ut_get_region_name (region_obj->region.space_id)));
501 }
502
503 if (acpi_ns_is_locked) {
504 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
505 if (ACPI_FAILURE (status)) {
506 return_VOID;
507 }
508 }
509
510 /* Call the setup handler with the deactivate notification */
511
512 region_setup = handler_obj->address_space.setup;
513 status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
514 handler_obj->address_space.context, region_context);
515
516 /* Init routine may fail, Just ignore errors */
517
518 if (ACPI_FAILURE (status)) {
519 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
520 acpi_format_exception (status),
521 acpi_ut_get_region_name (region_obj->region.space_id)));
522 }
523
524 region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);
525
526 /*
527 * Remove handler reference in the region
528 *
529 * NOTE: this doesn't mean that the region goes away
530 * The region is just inaccessible as indicated to
531 * the _REG method
532 *
533 * If the region is on the handler's list
534 * this better be the region's handler
535 */
536 region_obj->region.handler = NULL;
537 acpi_ut_remove_reference (handler_obj);
538
539 return_VOID;
540 }
541
542 /* Walk the linked list of handlers */
543
544 last_obj_ptr = &obj_desc->region.next;
545 obj_desc = obj_desc->region.next;
546 }
547
548 /* If we get here, the region was not in the handler's region list */
549
550 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
551 "Cannot remove region %p from address handler %p\n",
552 region_obj, handler_obj));
553
554 return_VOID;
555}
556
557
558/*******************************************************************************
559 *
560 * FUNCTION: acpi_ev_attach_region
561 *
562 * PARAMETERS: handler_obj - Handler Object
563 * region_obj - Region Object
564 * acpi_ns_is_locked - Namespace Region Already Locked?
565 *
566 * RETURN: None
567 *
568 * DESCRIPTION: Create the association between the handler and the region
569 * this is a two way association.
570 *
571 ******************************************************************************/
572
573acpi_status
574acpi_ev_attach_region (
575 union acpi_operand_object *handler_obj,
576 union acpi_operand_object *region_obj,
577 u8 acpi_ns_is_locked)
578{
579
580 ACPI_FUNCTION_TRACE ("ev_attach_region");
581
582
583 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
584 "Adding Region [%4.4s] %p to address handler %p [%s]\n",
585 acpi_ut_get_node_name (region_obj->region.node),
586 region_obj, handler_obj,
587 acpi_ut_get_region_name (region_obj->region.space_id)));
588
589 /* Link this region to the front of the handler's list */
590
591 region_obj->region.next = handler_obj->address_space.region_list;
592 handler_obj->address_space.region_list = region_obj;
593
594 /* Install the region's handler */
595
596 if (region_obj->region.handler) {
597 return_ACPI_STATUS (AE_ALREADY_EXISTS);
598 }
599
600 region_obj->region.handler = handler_obj;
601 acpi_ut_add_reference (handler_obj);
602
603 return_ACPI_STATUS (AE_OK);
604}
605
606
607/*******************************************************************************
608 *
609 * FUNCTION: acpi_ev_install_handler
610 *
611 * PARAMETERS: walk_namespace callback
612 *
613 * DESCRIPTION: This routine installs an address handler into objects that are
614 * of type Region or Device.
615 *
616 * If the Object is a Device, and the device has a handler of
617 * the same type then the search is terminated in that branch.
618 *
619 * This is because the existing handler is closer in proximity
620 * to any more regions than the one we are trying to install.
621 *
622 ******************************************************************************/
623
624acpi_status
625acpi_ev_install_handler (
626 acpi_handle obj_handle,
627 u32 level,
628 void *context,
629 void **return_value)
630{
631 union acpi_operand_object *handler_obj;
632 union acpi_operand_object *next_handler_obj;
633 union acpi_operand_object *obj_desc;
634 struct acpi_namespace_node *node;
635 acpi_status status;
636
637
638 ACPI_FUNCTION_NAME ("ev_install_handler");
639
640
641 handler_obj = (union acpi_operand_object *) context;
642
643 /* Parameter validation */
644
645 if (!handler_obj) {
646 return (AE_OK);
647 }
648
649 /* Convert and validate the device handle */
650
651 node = acpi_ns_map_handle_to_node (obj_handle);
652 if (!node) {
653 return (AE_BAD_PARAMETER);
654 }
655
656 /*
657 * We only care about regions.and objects
658 * that are allowed to have address space handlers
659 */
660 if ((node->type != ACPI_TYPE_DEVICE) &&
661 (node->type != ACPI_TYPE_REGION) &&
662 (node != acpi_gbl_root_node)) {
663 return (AE_OK);
664 }
665
666 /* Check for an existing internal object */
667
668 obj_desc = acpi_ns_get_attached_object (node);
669 if (!obj_desc) {
670 /* No object, just exit */
671
672 return (AE_OK);
673 }
674
675 /* Devices are handled different than regions */
676
677 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_DEVICE) {
678 /* Check if this Device already has a handler for this address space */
679
680 next_handler_obj = obj_desc->device.handler;
681 while (next_handler_obj) {
682 /* Found a handler, is it for the same address space? */
683
684 if (next_handler_obj->address_space.space_id == handler_obj->address_space.space_id) {
685 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
686 "Found handler for region [%s] in device %p(%p) handler %p\n",
687 acpi_ut_get_region_name (handler_obj->address_space.space_id),
688 obj_desc, next_handler_obj, handler_obj));
689
690 /*
691 * Since the object we found it on was a device, then it
692 * means that someone has already installed a handler for
693 * the branch of the namespace from this device on. Just
694 * bail out telling the walk routine to not traverse this
695 * branch. This preserves the scoping rule for handlers.
696 */
697 return (AE_CTRL_DEPTH);
698 }
699
700 /* Walk the linked list of handlers attached to this device */
701
702 next_handler_obj = next_handler_obj->address_space.next;
703 }
704
705 /*
706 * As long as the device didn't have a handler for this
707 * space we don't care about it. We just ignore it and
708 * proceed.
709 */
710 return (AE_OK);
711 }
712
713 /* Object is a Region */
714
715 if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
716 /*
717 * This region is for a different address space
718 * -- just ignore it
719 */
720 return (AE_OK);
721 }
722
723 /*
724 * Now we have a region and it is for the handler's address
725 * space type.
726 *
727 * First disconnect region for any previous handler (if any)
728 */
729 acpi_ev_detach_region (obj_desc, FALSE);
730
731 /* Connect the region to the new handler */
732
733 status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE);
734 return (status);
735}
736
737
738/*******************************************************************************
739 *
740 * FUNCTION: acpi_ev_install_space_handler
741 *
742 * PARAMETERS: Node - Namespace node for the device
743 * space_id - The address space ID
744 * Handler - Address of the handler
745 * Setup - Address of the setup function
746 * Context - Value passed to the handler on each access
747 *
748 * RETURN: Status
749 *
750 * DESCRIPTION: Install a handler for all op_regions of a given space_id.
751 * Assumes namespace is locked
752 *
753 ******************************************************************************/
754
755acpi_status
756acpi_ev_install_space_handler (
757 struct acpi_namespace_node *node,
758 acpi_adr_space_type space_id,
759 acpi_adr_space_handler handler,
760 acpi_adr_space_setup setup,
761 void *context)
762{
763 union acpi_operand_object *obj_desc;
764 union acpi_operand_object *handler_obj;
765 acpi_status status;
766 acpi_object_type type;
767 u16 flags = 0;
768
769
770 ACPI_FUNCTION_TRACE ("ev_install_space_handler");
771
772
773 /*
774 * This registration is valid for only the types below
775 * and the root. This is where the default handlers
776 * get placed.
777 */
778 if ((node->type != ACPI_TYPE_DEVICE) &&
779 (node->type != ACPI_TYPE_PROCESSOR) &&
780 (node->type != ACPI_TYPE_THERMAL) &&
781 (node != acpi_gbl_root_node)) {
782 status = AE_BAD_PARAMETER;
783 goto unlock_and_exit;
784 }
785
786 if (handler == ACPI_DEFAULT_HANDLER) {
787 flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
788
789 switch (space_id) {
790 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
791 handler = acpi_ex_system_memory_space_handler;
792 setup = acpi_ev_system_memory_region_setup;
793 break;
794
795 case ACPI_ADR_SPACE_SYSTEM_IO:
796 handler = acpi_ex_system_io_space_handler;
797 setup = acpi_ev_io_space_region_setup;
798 break;
799
800 case ACPI_ADR_SPACE_PCI_CONFIG:
801 handler = acpi_ex_pci_config_space_handler;
802 setup = acpi_ev_pci_config_region_setup;
803 break;
804
805 case ACPI_ADR_SPACE_CMOS:
806 handler = acpi_ex_cmos_space_handler;
807 setup = acpi_ev_cmos_region_setup;
808 break;
809
810 case ACPI_ADR_SPACE_PCI_BAR_TARGET:
811 handler = acpi_ex_pci_bar_space_handler;
812 setup = acpi_ev_pci_bar_region_setup;
813 break;
814
815 case ACPI_ADR_SPACE_DATA_TABLE:
816 handler = acpi_ex_data_table_space_handler;
817 setup = NULL;
818 break;
819
820 default:
821 status = AE_BAD_PARAMETER;
822 goto unlock_and_exit;
823 }
824 }
825
826 /* If the caller hasn't specified a setup routine, use the default */
827
828 if (!setup) {
829 setup = acpi_ev_default_region_setup;
830 }
831
832 /* Check for an existing internal object */
833
834 obj_desc = acpi_ns_get_attached_object (node);
835 if (obj_desc) {
836 /*
837 * The attached device object already exists.
838 * Make sure the handler is not already installed.
839 */
840 handler_obj = obj_desc->device.handler;
841
842 /* Walk the handler list for this device */
843
844 while (handler_obj) {
845 /* Same space_id indicates a handler already installed */
846
847 if (handler_obj->address_space.space_id == space_id) {
848 if (handler_obj->address_space.handler == handler) {
849 /*
850 * It is (relatively) OK to attempt to install the SAME
851 * handler twice. This can easily happen with PCI_Config space.
852 */
853 status = AE_SAME_HANDLER;
854 goto unlock_and_exit;
855 }
856 else {
857 /* A handler is already installed */
858
859 status = AE_ALREADY_EXISTS;
860 }
861 goto unlock_and_exit;
862 }
863
864 /* Walk the linked list of handlers */
865
866 handler_obj = handler_obj->address_space.next;
867 }
868 }
869 else {
870 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
871 "Creating object on Device %p while installing handler\n", node));
872
873 /* obj_desc does not exist, create one */
874
875 if (node->type == ACPI_TYPE_ANY) {
876 type = ACPI_TYPE_DEVICE;
877 }
878 else {
879 type = node->type;
880 }
881
882 obj_desc = acpi_ut_create_internal_object (type);
883 if (!obj_desc) {
884 status = AE_NO_MEMORY;
885 goto unlock_and_exit;
886 }
887
888 /* Init new descriptor */
889
890 obj_desc->common.type = (u8) type;
891
892 /* Attach the new object to the Node */
893
894 status = acpi_ns_attach_object (node, obj_desc, type);
895
896 /* Remove local reference to the object */
897
898 acpi_ut_remove_reference (obj_desc);
899
900 if (ACPI_FAILURE (status)) {
901 goto unlock_and_exit;
902 }
903 }
904
905 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
906 "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
907 acpi_ut_get_region_name (space_id), space_id,
908 acpi_ut_get_node_name (node), node, obj_desc));
909
910 /*
911 * Install the handler
912 *
913 * At this point there is no existing handler.
914 * Just allocate the object for the handler and link it
915 * into the list.
916 */
917 handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
918 if (!handler_obj) {
919 status = AE_NO_MEMORY;
920 goto unlock_and_exit;
921 }
922
923 /* Init handler obj */
924
925 handler_obj->address_space.space_id = (u8) space_id;
926 handler_obj->address_space.hflags = flags;
927 handler_obj->address_space.region_list = NULL;
928 handler_obj->address_space.node = node;
929 handler_obj->address_space.handler = handler;
930 handler_obj->address_space.context = context;
931 handler_obj->address_space.setup = setup;
932
933 /* Install at head of Device.address_space list */
934
935 handler_obj->address_space.next = obj_desc->device.handler;
936
937 /*
938 * The Device object is the first reference on the handler_obj.
939 * Each region that uses the handler adds a reference.
940 */
941 obj_desc->device.handler = handler_obj;
942
943 /*
944 * Walk the namespace finding all of the regions this
945 * handler will manage.
946 *
947 * Start at the device and search the branch toward
948 * the leaf nodes until either the leaf is encountered or
949 * a device is detected that has an address handler of the
950 * same type.
951 *
952 * In either case, back up and search down the remainder
953 * of the branch
954 */
955 status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
956 ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
957 handler_obj, NULL);
958
959unlock_and_exit:
960 return_ACPI_STATUS (status);
961}
962
963
964/*******************************************************************************
965 *
966 * FUNCTION: acpi_ev_execute_reg_methods
967 *
968 * PARAMETERS: Node - Namespace node for the device
969 * space_id - The address space ID
970 *
971 * RETURN: Status
972 *
973 * DESCRIPTION: Run all _REG methods for the input Space ID;
974 * Note: assumes namespace is locked, or system init time.
975 *
976 ******************************************************************************/
977
978acpi_status
979acpi_ev_execute_reg_methods (
980 struct acpi_namespace_node *node,
981 acpi_adr_space_type space_id)
982{
983 acpi_status status;
984
985
986 ACPI_FUNCTION_TRACE ("ev_execute_reg_methods");
987
988
989 /*
990 * Run all _REG methods for all Operation Regions for this
991 * space ID. This is a separate walk in order to handle any
992 * interdependencies between regions and _REG methods. (i.e. handlers
993 * must be installed for all regions of this Space ID before we
994 * can run any _REG methods)
995 */
996 status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
997 ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
998 &space_id, NULL);
999
1000 return_ACPI_STATUS (status);
1001}
1002
1003
1004/*******************************************************************************
1005 *
1006 * FUNCTION: acpi_ev_reg_run
1007 *
1008 * PARAMETERS: walk_namespace callback
1009 *
1010 * DESCRIPTION: Run _REg method for region objects of the requested space_iD
1011 *
1012 ******************************************************************************/
1013
1014acpi_status
1015acpi_ev_reg_run (
1016 acpi_handle obj_handle,
1017 u32 level,
1018 void *context,
1019 void **return_value)
1020{
1021 union acpi_operand_object *obj_desc;
1022 struct acpi_namespace_node *node;
1023 acpi_adr_space_type space_id;
1024 acpi_status status;
1025
1026
1027 space_id = *ACPI_CAST_PTR (acpi_adr_space_type, context);
1028
1029 /* Convert and validate the device handle */
1030
1031 node = acpi_ns_map_handle_to_node (obj_handle);
1032 if (!node) {
1033 return (AE_BAD_PARAMETER);
1034 }
1035
1036 /*
1037 * We only care about regions.and objects
1038 * that are allowed to have address space handlers
1039 */
1040 if ((node->type != ACPI_TYPE_REGION) &&
1041 (node != acpi_gbl_root_node)) {
1042 return (AE_OK);
1043 }
1044
1045 /* Check for an existing internal object */
1046
1047 obj_desc = acpi_ns_get_attached_object (node);
1048 if (!obj_desc) {
1049 /* No object, just exit */
1050
1051 return (AE_OK);
1052 }
1053
1054 /* Object is a Region */
1055
1056 if (obj_desc->region.space_id != space_id) {
1057 /*
1058 * This region is for a different address space
1059 * -- just ignore it
1060 */
1061 return (AE_OK);
1062 }
1063
1064 status = acpi_ev_execute_reg_method (obj_desc, 1);
1065 return (status);
1066}
1067
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
new file mode 100644
index 000000000000..4983a3378be5
--- /dev/null
+++ b/drivers/acpi/events/evrgnini.c
@@ -0,0 +1,580 @@
1/******************************************************************************
2 *
3 * Module Name: evrgnini- ACPI address_space (op_region) init
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acevents.h>
47#include <acpi/acnamesp.h>
48
49#define _COMPONENT ACPI_EVENTS
50 ACPI_MODULE_NAME ("evrgnini")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ev_system_memory_region_setup
56 *
57 * PARAMETERS: Handle - Region we are interested in
58 * Function - Start or stop
59 * handler_context - Address space handler context
60 * region_context - Region specific context
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Do any prep work for region handling, a nop for now
65 *
66 ******************************************************************************/
67
68acpi_status
69acpi_ev_system_memory_region_setup (
70 acpi_handle handle,
71 u32 function,
72 void *handler_context,
73 void **region_context)
74{
75 union acpi_operand_object *region_desc = (union acpi_operand_object *) handle;
76 struct acpi_mem_space_context *local_region_context;
77
78
79 ACPI_FUNCTION_TRACE ("ev_system_memory_region_setup");
80
81
82 if (function == ACPI_REGION_DEACTIVATE) {
83 if (*region_context) {
84 ACPI_MEM_FREE (*region_context);
85 *region_context = NULL;
86 }
87 return_ACPI_STATUS (AE_OK);
88 }
89
90 /* Create a new context */
91
92 local_region_context = ACPI_MEM_CALLOCATE (sizeof (struct acpi_mem_space_context));
93 if (!(local_region_context)) {
94 return_ACPI_STATUS (AE_NO_MEMORY);
95 }
96
97 /* Save the region length and address for use in the handler */
98
99 local_region_context->length = region_desc->region.length;
100 local_region_context->address = region_desc->region.address;
101
102 *region_context = local_region_context;
103 return_ACPI_STATUS (AE_OK);
104}
105
106
107/*******************************************************************************
108 *
109 * FUNCTION: acpi_ev_io_space_region_setup
110 *
111 * PARAMETERS: Handle - Region we are interested in
112 * Function - Start or stop
113 * handler_context - Address space handler context
114 * region_context - Region specific context
115 *
116 * RETURN: Status
117 *
118 * DESCRIPTION: Do any prep work for region handling
119 *
120 ******************************************************************************/
121
122acpi_status
123acpi_ev_io_space_region_setup (
124 acpi_handle handle,
125 u32 function,
126 void *handler_context,
127 void **region_context)
128{
129 ACPI_FUNCTION_TRACE ("ev_io_space_region_setup");
130
131
132 if (function == ACPI_REGION_DEACTIVATE) {
133 *region_context = NULL;
134 }
135 else {
136 *region_context = handler_context;
137 }
138
139 return_ACPI_STATUS (AE_OK);
140}
141
142
143/*******************************************************************************
144 *
145 * FUNCTION: acpi_ev_pci_config_region_setup
146 *
147 * PARAMETERS: Handle - Region we are interested in
148 * Function - Start or stop
149 * handler_context - Address space handler context
150 * region_context - Region specific context
151 *
152 * RETURN: Status
153 *
154 * DESCRIPTION: Do any prep work for region handling
155 *
156 * MUTEX: Assumes namespace is not locked
157 *
158 ******************************************************************************/
159
160acpi_status
161acpi_ev_pci_config_region_setup (
162 acpi_handle handle,
163 u32 function,
164 void *handler_context,
165 void **region_context)
166{
167 acpi_status status = AE_OK;
168 acpi_integer pci_value;
169 struct acpi_pci_id *pci_id = *region_context;
170 union acpi_operand_object *handler_obj;
171 struct acpi_namespace_node *parent_node;
172 struct acpi_namespace_node *pci_root_node;
173 union acpi_operand_object *region_obj = (union acpi_operand_object *) handle;
174 struct acpi_device_id object_hID;
175
176
177 ACPI_FUNCTION_TRACE ("ev_pci_config_region_setup");
178
179
180 handler_obj = region_obj->region.handler;
181 if (!handler_obj) {
182 /*
183 * No installed handler. This shouldn't happen because the dispatch
184 * routine checks before we get here, but we check again just in case.
185 */
186 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
187 "Attempting to init a region %p, with no handler\n", region_obj));
188 return_ACPI_STATUS (AE_NOT_EXIST);
189 }
190
191 *region_context = NULL;
192 if (function == ACPI_REGION_DEACTIVATE) {
193 if (pci_id) {
194 ACPI_MEM_FREE (pci_id);
195 }
196 return_ACPI_STATUS (status);
197 }
198
199 parent_node = acpi_ns_get_parent_node (region_obj->region.node);
200
201 /*
202 * Get the _SEG and _BBN values from the device upon which the handler
203 * is installed.
204 *
205 * We need to get the _SEG and _BBN objects relative to the PCI BUS device.
206 * This is the device the handler has been registered to handle.
207 */
208
209 /*
210 * If the address_space.Node is still pointing to the root, we need
211 * to scan upward for a PCI Root bridge and re-associate the op_region
212 * handlers with that device.
213 */
214 if (handler_obj->address_space.node == acpi_gbl_root_node) {
215 /* Start search from the parent object */
216
217 pci_root_node = parent_node;
218 while (pci_root_node != acpi_gbl_root_node) {
219 status = acpi_ut_execute_HID (pci_root_node, &object_hID);
220 if (ACPI_SUCCESS (status)) {
221 /* Got a valid _HID, check if this is a PCI root */
222
223 if (!(ACPI_STRNCMP (object_hID.value, PCI_ROOT_HID_STRING,
224 sizeof (PCI_ROOT_HID_STRING)))) {
225 /* Install a handler for this PCI root bridge */
226
227 status = acpi_install_address_space_handler ((acpi_handle) pci_root_node,
228 ACPI_ADR_SPACE_PCI_CONFIG,
229 ACPI_DEFAULT_HANDLER, NULL, NULL);
230 if (ACPI_FAILURE (status)) {
231 if (status == AE_SAME_HANDLER) {
232 /*
233 * It is OK if the handler is already installed on the root
234 * bridge. Still need to return a context object for the
235 * new PCI_Config operation region, however.
236 */
237 status = AE_OK;
238 }
239 else {
240 ACPI_REPORT_ERROR ((
241 "Could not install pci_config handler for Root Bridge %4.4s, %s\n",
242 acpi_ut_get_node_name (pci_root_node), acpi_format_exception (status)));
243 }
244 }
245 break;
246 }
247 }
248
249 pci_root_node = acpi_ns_get_parent_node (pci_root_node);
250 }
251
252 /* PCI root bridge not found, use namespace root node */
253 }
254 else {
255 pci_root_node = handler_obj->address_space.node;
256 }
257
258 /*
259 * If this region is now initialized, we are done.
260 * (install_address_space_handler could have initialized it)
261 */
262 if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
263 return_ACPI_STATUS (AE_OK);
264 }
265
266 /* Region is still not initialized. Create a new context */
267
268 pci_id = ACPI_MEM_CALLOCATE (sizeof (struct acpi_pci_id));
269 if (!pci_id) {
270 return_ACPI_STATUS (AE_NO_MEMORY);
271 }
272
273 /*
274 * For PCI_Config space access, we need the segment, bus,
275 * device and function numbers. Acquire them here.
276 */
277
278 /*
279 * Get the PCI device and function numbers from the _ADR object
280 * contained in the parent's scope.
281 */
282 status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, parent_node, &pci_value);
283
284 /*
285 * The default is zero, and since the allocation above zeroed
286 * the data, just do nothing on failure.
287 */
288 if (ACPI_SUCCESS (status)) {
289 pci_id->device = ACPI_HIWORD (ACPI_LODWORD (pci_value));
290 pci_id->function = ACPI_LOWORD (ACPI_LODWORD (pci_value));
291 }
292
293 /* The PCI segment number comes from the _SEG method */
294
295 status = acpi_ut_evaluate_numeric_object (METHOD_NAME__SEG, pci_root_node, &pci_value);
296 if (ACPI_SUCCESS (status)) {
297 pci_id->segment = ACPI_LOWORD (pci_value);
298 }
299
300 /* The PCI bus number comes from the _BBN method */
301
302 status = acpi_ut_evaluate_numeric_object (METHOD_NAME__BBN, pci_root_node, &pci_value);
303 if (ACPI_SUCCESS (status)) {
304 pci_id->bus = ACPI_LOWORD (pci_value);
305 }
306
307 /* Complete this device's pci_id */
308
309 acpi_os_derive_pci_id (pci_root_node, region_obj->region.node, &pci_id);
310
311 *region_context = pci_id;
312 return_ACPI_STATUS (AE_OK);
313}
314
315
316/*******************************************************************************
317 *
318 * FUNCTION: acpi_ev_pci_bar_region_setup
319 *
320 * PARAMETERS: Handle - Region we are interested in
321 * Function - Start or stop
322 * handler_context - Address space handler context
323 * region_context - Region specific context
324 *
325 * RETURN: Status
326 *
327 * DESCRIPTION: Do any prep work for region handling
328 *
329 * MUTEX: Assumes namespace is not locked
330 *
331 ******************************************************************************/
332
333acpi_status
334acpi_ev_pci_bar_region_setup (
335 acpi_handle handle,
336 u32 function,
337 void *handler_context,
338 void **region_context)
339{
340 ACPI_FUNCTION_TRACE ("ev_pci_bar_region_setup");
341
342
343 return_ACPI_STATUS (AE_OK);
344}
345
346
347/*******************************************************************************
348 *
349 * FUNCTION: acpi_ev_cmos_region_setup
350 *
351 * PARAMETERS: Handle - Region we are interested in
352 * Function - Start or stop
353 * handler_context - Address space handler context
354 * region_context - Region specific context
355 *
356 * RETURN: Status
357 *
358 * DESCRIPTION: Do any prep work for region handling
359 *
360 * MUTEX: Assumes namespace is not locked
361 *
362 ******************************************************************************/
363
364acpi_status
365acpi_ev_cmos_region_setup (
366 acpi_handle handle,
367 u32 function,
368 void *handler_context,
369 void **region_context)
370{
371 ACPI_FUNCTION_TRACE ("ev_cmos_region_setup");
372
373
374 return_ACPI_STATUS (AE_OK);
375}
376
377
378/*******************************************************************************
379 *
380 * FUNCTION: acpi_ev_default_region_setup
381 *
382 * PARAMETERS: Handle - Region we are interested in
383 * Function - Start or stop
384 * handler_context - Address space handler context
385 * region_context - Region specific context
386 *
387 * RETURN: Status
388 *
389 * DESCRIPTION: Do any prep work for region handling
390 *
391 ******************************************************************************/
392
393acpi_status
394acpi_ev_default_region_setup (
395 acpi_handle handle,
396 u32 function,
397 void *handler_context,
398 void **region_context)
399{
400 ACPI_FUNCTION_TRACE ("ev_default_region_setup");
401
402
403 if (function == ACPI_REGION_DEACTIVATE) {
404 *region_context = NULL;
405 }
406 else {
407 *region_context = handler_context;
408 }
409
410 return_ACPI_STATUS (AE_OK);
411}
412
413
414/*******************************************************************************
415 *
416 * FUNCTION: acpi_ev_initialize_region
417 *
418 * PARAMETERS: region_obj - Region we are initializing
419 * acpi_ns_locked - Is namespace locked?
420 *
421 * RETURN: Status
422 *
423 * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
424 * for execution at a later time
425 *
426 * Get the appropriate address space handler for a newly
427 * created region.
428 *
429 * This also performs address space specific initialization. For
430 * example, PCI regions must have an _ADR object that contains
431 * a PCI address in the scope of the definition. This address is
432 * required to perform an access to PCI config space.
433 *
434 ******************************************************************************/
435
436acpi_status
437acpi_ev_initialize_region (
438 union acpi_operand_object *region_obj,
439 u8 acpi_ns_locked)
440{
441 union acpi_operand_object *handler_obj;
442 union acpi_operand_object *obj_desc;
443 acpi_adr_space_type space_id;
444 struct acpi_namespace_node *node;
445 acpi_status status;
446 struct acpi_namespace_node *method_node;
447 acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
448 union acpi_operand_object *region_obj2;
449
450
451 ACPI_FUNCTION_TRACE_U32 ("ev_initialize_region", acpi_ns_locked);
452
453
454 if (!region_obj) {
455 return_ACPI_STATUS (AE_BAD_PARAMETER);
456 }
457
458 if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) {
459 return_ACPI_STATUS (AE_OK);
460 }
461
462 region_obj2 = acpi_ns_get_secondary_object (region_obj);
463 if (!region_obj2) {
464 return_ACPI_STATUS (AE_NOT_EXIST);
465 }
466
467 node = acpi_ns_get_parent_node (region_obj->region.node);
468 space_id = region_obj->region.space_id;
469
470 /* Setup defaults */
471
472 region_obj->region.handler = NULL;
473 region_obj2->extra.method_REG = NULL;
474 region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE);
475 region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;
476
477 /* Find any "_REG" method associated with this region definition */
478
479 status = acpi_ns_search_node (*reg_name_ptr, node,
480 ACPI_TYPE_METHOD, &method_node);
481 if (ACPI_SUCCESS (status)) {
482 /*
483 * The _REG method is optional and there can be only one per region
484 * definition. This will be executed when the handler is attached
485 * or removed
486 */
487 region_obj2->extra.method_REG = method_node;
488 }
489
490 /*
491 * The following loop depends upon the root Node having no parent
492 * ie: acpi_gbl_root_node->parent_entry being set to NULL
493 */
494 while (node) {
495 /* Check to see if a handler exists */
496
497 handler_obj = NULL;
498 obj_desc = acpi_ns_get_attached_object (node);
499 if (obj_desc) {
500 /* Can only be a handler if the object exists */
501
502 switch (node->type) {
503 case ACPI_TYPE_DEVICE:
504
505 handler_obj = obj_desc->device.handler;
506 break;
507
508 case ACPI_TYPE_PROCESSOR:
509
510 handler_obj = obj_desc->processor.handler;
511 break;
512
513 case ACPI_TYPE_THERMAL:
514
515 handler_obj = obj_desc->thermal_zone.handler;
516 break;
517
518 default:
519 /* Ignore other objects */
520 break;
521 }
522
523 while (handler_obj) {
524 /* Is this handler of the correct type? */
525
526 if (handler_obj->address_space.space_id == space_id) {
527 /* Found correct handler */
528
529 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
530 "Found handler %p for region %p in obj %p\n",
531 handler_obj, region_obj, obj_desc));
532
533 status = acpi_ev_attach_region (handler_obj, region_obj,
534 acpi_ns_locked);
535
536 /*
537 * Tell all users that this region is usable by running the _REG
538 * method
539 */
540 if (acpi_ns_locked) {
541 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
542 if (ACPI_FAILURE (status)) {
543 return_ACPI_STATUS (status);
544 }
545 }
546
547 status = acpi_ev_execute_reg_method (region_obj, 1);
548
549 if (acpi_ns_locked) {
550 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
551 if (ACPI_FAILURE (status)) {
552 return_ACPI_STATUS (status);
553 }
554 }
555
556 return_ACPI_STATUS (AE_OK);
557 }
558
559 /* Try next handler in the list */
560
561 handler_obj = handler_obj->address_space.next;
562 }
563 }
564
565 /*
566 * This node does not have the handler we need;
567 * Pop up one level
568 */
569 node = acpi_ns_get_parent_node (node);
570 }
571
572 /* If we get here, there is no handler for this region */
573
574 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
575 "No handler for region_type %s(%X) (region_obj %p)\n",
576 acpi_ut_get_region_name (space_id), space_id, region_obj));
577
578 return_ACPI_STATUS (AE_NOT_EXIST);
579}
580
diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c
new file mode 100644
index 000000000000..46b31995c827
--- /dev/null
+++ b/drivers/acpi/events/evsci.c
@@ -0,0 +1,199 @@
1/*******************************************************************************
2 *
3 * Module Name: evsci - System Control Interrupt configuration and
4 * legacy to ACPI mode state transition functions
5 *
6 ******************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <acpi/acpi.h>
46#include <acpi/acevents.h>
47
48
49#define _COMPONENT ACPI_EVENTS
50 ACPI_MODULE_NAME ("evsci")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ev_sci_xrupt_handler
56 *
57 * PARAMETERS: Context - Calling Context
58 *
59 * RETURN: Status code indicates whether interrupt was handled.
60 *
61 * DESCRIPTION: Interrupt handler that will figure out what function or
62 * control method to call to deal with a SCI.
63 *
64 ******************************************************************************/
65
66static u32 ACPI_SYSTEM_XFACE
67acpi_ev_sci_xrupt_handler (
68 void *context)
69{
70 struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
71 u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
72
73
74 ACPI_FUNCTION_TRACE("ev_sci_xrupt_handler");
75
76
77 /*
78 * We are guaranteed by the ACPI CA initialization/shutdown code that
79 * if this interrupt handler is installed, ACPI is enabled.
80 */
81
82 /*
83 * Fixed Events:
84 * Check for and dispatch any Fixed Events that have occurred
85 */
86 interrupt_handled |= acpi_ev_fixed_event_detect ();
87
88 /*
89 * General Purpose Events:
90 * Check for and dispatch any GPEs that have occurred
91 */
92 interrupt_handled |= acpi_ev_gpe_detect (gpe_xrupt_list);
93
94 return_VALUE (interrupt_handled);
95}
96
97
98/*******************************************************************************
99 *
100 * FUNCTION: acpi_ev_gpe_xrupt_handler
101 *
102 * PARAMETERS: Context - Calling Context
103 *
104 * RETURN: Status code indicates whether interrupt was handled.
105 *
106 * DESCRIPTION: Handler for GPE Block Device interrupts
107 *
108 ******************************************************************************/
109
110u32 ACPI_SYSTEM_XFACE
111acpi_ev_gpe_xrupt_handler (
112 void *context)
113{
114 struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
115 u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
116
117
118 ACPI_FUNCTION_TRACE("ev_gpe_xrupt_handler");
119
120
121 /*
122 * We are guaranteed by the ACPI CA initialization/shutdown code that
123 * if this interrupt handler is installed, ACPI is enabled.
124 */
125
126 /*
127 * GPEs:
128 * Check for and dispatch any GPEs that have occurred
129 */
130 interrupt_handled |= acpi_ev_gpe_detect (gpe_xrupt_list);
131
132 return_VALUE (interrupt_handled);
133}
134
135
136/******************************************************************************
137 *
138 * FUNCTION: acpi_ev_install_sci_handler
139 *
140 * PARAMETERS: none
141 *
142 * RETURN: Status
143 *
144 * DESCRIPTION: Installs SCI handler.
145 *
146 ******************************************************************************/
147
148u32
149acpi_ev_install_sci_handler (void)
150{
151 u32 status = AE_OK;
152
153
154 ACPI_FUNCTION_TRACE ("ev_install_sci_handler");
155
156
157 status = acpi_os_install_interrupt_handler ((u32) acpi_gbl_FADT->sci_int,
158 acpi_ev_sci_xrupt_handler, acpi_gbl_gpe_xrupt_list_head);
159 return_ACPI_STATUS (status);
160}
161
162
163/******************************************************************************
164 *
165 * FUNCTION: acpi_ev_remove_sci_handler
166 *
167 * PARAMETERS: none
168 *
169 * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not
170 * installed to begin with
171 *
172 * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
173 * taken.
174 *
175 * Note: It doesn't seem important to disable all events or set the event
176 * enable registers to their original values. The OS should disable
177 * the SCI interrupt level when the handler is removed, so no more
178 * events will come in.
179 *
180 ******************************************************************************/
181
182acpi_status
183acpi_ev_remove_sci_handler (void)
184{
185 acpi_status status;
186
187
188 ACPI_FUNCTION_TRACE ("ev_remove_sci_handler");
189
190
191 /* Just let the OS remove the handler and disable the level */
192
193 status = acpi_os_remove_interrupt_handler ((u32) acpi_gbl_FADT->sci_int,
194 acpi_ev_sci_xrupt_handler);
195
196 return_ACPI_STATUS (status);
197}
198
199
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
new file mode 100644
index 000000000000..0bfec10a5f1e
--- /dev/null
+++ b/drivers/acpi/events/evxface.c
@@ -0,0 +1,834 @@
1/******************************************************************************
2 *
3 * Module Name: evxface - External interfaces for ACPI events
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <linux/module.h>
45
46#include <acpi/acpi.h>
47#include <acpi/acnamesp.h>
48#include <acpi/acevents.h>
49#include <acpi/acinterp.h>
50
51#define _COMPONENT ACPI_EVENTS
52 ACPI_MODULE_NAME ("evxface")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION: acpi_install_exception_handler
58 *
59 * PARAMETERS: Handler - Pointer to the handler function for the
60 * event
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Saves the pointer to the handler function
65 *
66 ******************************************************************************/
67#ifdef ACPI_FUTURE_USAGE
68acpi_status
69acpi_install_exception_handler (
70 acpi_exception_handler handler)
71{
72 acpi_status status;
73
74
75 ACPI_FUNCTION_TRACE ("acpi_install_exception_handler");
76
77
78 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
79 if (ACPI_FAILURE (status)) {
80 return_ACPI_STATUS (status);
81 }
82
83 /* Don't allow two handlers. */
84
85 if (acpi_gbl_exception_handler) {
86 status = AE_ALREADY_EXISTS;
87 goto cleanup;
88 }
89
90 /* Install the handler */
91
92 acpi_gbl_exception_handler = handler;
93
94cleanup:
95 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
96 return_ACPI_STATUS (status);
97}
98#endif /* ACPI_FUTURE_USAGE */
99
100
101/*******************************************************************************
102 *
103 * FUNCTION: acpi_install_fixed_event_handler
104 *
105 * PARAMETERS: Event - Event type to enable.
106 * Handler - Pointer to the handler function for the
107 * event
108 * Context - Value passed to the handler on each GPE
109 *
110 * RETURN: Status
111 *
112 * DESCRIPTION: Saves the pointer to the handler function and then enables the
113 * event.
114 *
115 ******************************************************************************/
116
117acpi_status
118acpi_install_fixed_event_handler (
119 u32 event,
120 acpi_event_handler handler,
121 void *context)
122{
123 acpi_status status;
124
125
126 ACPI_FUNCTION_TRACE ("acpi_install_fixed_event_handler");
127
128
129 /* Parameter validation */
130
131 if (event > ACPI_EVENT_MAX) {
132 return_ACPI_STATUS (AE_BAD_PARAMETER);
133 }
134
135 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
136 if (ACPI_FAILURE (status)) {
137 return_ACPI_STATUS (status);
138 }
139
140 /* Don't allow two handlers. */
141
142 if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {
143 status = AE_ALREADY_EXISTS;
144 goto cleanup;
145 }
146
147 /* Install the handler before enabling the event */
148
149 acpi_gbl_fixed_event_handlers[event].handler = handler;
150 acpi_gbl_fixed_event_handlers[event].context = context;
151
152 status = acpi_clear_event (event);
153 if (ACPI_SUCCESS(status))
154 status = acpi_enable_event (event, 0);
155 if (ACPI_FAILURE (status)) {
156 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n"));
157
158 /* Remove the handler */
159
160 acpi_gbl_fixed_event_handlers[event].handler = NULL;
161 acpi_gbl_fixed_event_handlers[event].context = NULL;
162 }
163 else {
164 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
165 "Enabled fixed event %X, Handler=%p\n", event, handler));
166 }
167
168
169cleanup:
170 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
171 return_ACPI_STATUS (status);
172}
173EXPORT_SYMBOL(acpi_install_fixed_event_handler);
174
175
176/*******************************************************************************
177 *
178 * FUNCTION: acpi_remove_fixed_event_handler
179 *
180 * PARAMETERS: Event - Event type to disable.
181 * Handler - Address of the handler
182 *
183 * RETURN: Status
184 *
185 * DESCRIPTION: Disables the event and unregisters the event handler.
186 *
187 ******************************************************************************/
188
189acpi_status
190acpi_remove_fixed_event_handler (
191 u32 event,
192 acpi_event_handler handler)
193{
194 acpi_status status = AE_OK;
195
196
197 ACPI_FUNCTION_TRACE ("acpi_remove_fixed_event_handler");
198
199
200 /* Parameter validation */
201
202 if (event > ACPI_EVENT_MAX) {
203 return_ACPI_STATUS (AE_BAD_PARAMETER);
204 }
205
206 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
207 if (ACPI_FAILURE (status)) {
208 return_ACPI_STATUS (status);
209 }
210
211 /* Disable the event before removing the handler */
212
213 status = acpi_disable_event (event, 0);
214
215 /* Always Remove the handler */
216
217 acpi_gbl_fixed_event_handlers[event].handler = NULL;
218 acpi_gbl_fixed_event_handlers[event].context = NULL;
219
220 if (ACPI_FAILURE (status)) {
221 ACPI_DEBUG_PRINT ((ACPI_DB_WARN,
222 "Could not write to fixed event enable register.\n"));
223 }
224 else {
225 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X.\n", event));
226 }
227
228 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
229 return_ACPI_STATUS (status);
230}
231EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
232
233
234/*******************************************************************************
235 *
236 * FUNCTION: acpi_install_notify_handler
237 *
238 * PARAMETERS: Device - The device for which notifies will be handled
239 * handler_type - The type of handler:
240 * ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
241 * ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
242 * ACPI_ALL_NOTIFY: both system and device
243 * Handler - Address of the handler
244 * Context - Value passed to the handler on each GPE
245 *
246 * RETURN: Status
247 *
248 * DESCRIPTION: Install a handler for notifies on an ACPI device
249 *
250 ******************************************************************************/
251
252acpi_status
253acpi_install_notify_handler (
254 acpi_handle device,
255 u32 handler_type,
256 acpi_notify_handler handler,
257 void *context)
258{
259 union acpi_operand_object *obj_desc;
260 union acpi_operand_object *notify_obj;
261 struct acpi_namespace_node *node;
262 acpi_status status;
263
264
265 ACPI_FUNCTION_TRACE ("acpi_install_notify_handler");
266
267
268 /* Parameter validation */
269
270 if ((!device) ||
271 (!handler) ||
272 (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
273 return_ACPI_STATUS (AE_BAD_PARAMETER);
274 }
275
276 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
277 if (ACPI_FAILURE (status)) {
278 return_ACPI_STATUS (status);
279 }
280
281 /* Convert and validate the device handle */
282
283 node = acpi_ns_map_handle_to_node (device);
284 if (!node) {
285 status = AE_BAD_PARAMETER;
286 goto unlock_and_exit;
287 }
288
289 /*
290 * Root Object:
291 * Registering a notify handler on the root object indicates that the
292 * caller wishes to receive notifications for all objects. Note that
293 * only one <external> global handler can be regsitered (per notify type).
294 */
295 if (device == ACPI_ROOT_OBJECT) {
296 /* Make sure the handler is not already installed */
297
298 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
299 acpi_gbl_system_notify.handler) ||
300 ((handler_type & ACPI_DEVICE_NOTIFY) &&
301 acpi_gbl_device_notify.handler)) {
302 status = AE_ALREADY_EXISTS;
303 goto unlock_and_exit;
304 }
305
306 if (handler_type & ACPI_SYSTEM_NOTIFY) {
307 acpi_gbl_system_notify.node = node;
308 acpi_gbl_system_notify.handler = handler;
309 acpi_gbl_system_notify.context = context;
310 }
311
312 if (handler_type & ACPI_DEVICE_NOTIFY) {
313 acpi_gbl_device_notify.node = node;
314 acpi_gbl_device_notify.handler = handler;
315 acpi_gbl_device_notify.context = context;
316 }
317
318 /* Global notify handler installed */
319 }
320
321 /*
322 * All Other Objects:
323 * Caller will only receive notifications specific to the target object.
324 * Note that only certain object types can receive notifications.
325 */
326 else {
327 /* Notifies allowed on this object? */
328
329 if (!acpi_ev_is_notify_object (node)) {
330 status = AE_TYPE;
331 goto unlock_and_exit;
332 }
333
334 /* Check for an existing internal object */
335
336 obj_desc = acpi_ns_get_attached_object (node);
337 if (obj_desc) {
338 /* Object exists - make sure there's no handler */
339
340 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
341 obj_desc->common_notify.system_notify) ||
342 ((handler_type & ACPI_DEVICE_NOTIFY) &&
343 obj_desc->common_notify.device_notify)) {
344 status = AE_ALREADY_EXISTS;
345 goto unlock_and_exit;
346 }
347 }
348 else {
349 /* Create a new object */
350
351 obj_desc = acpi_ut_create_internal_object (node->type);
352 if (!obj_desc) {
353 status = AE_NO_MEMORY;
354 goto unlock_and_exit;
355 }
356
357 /* Attach new object to the Node */
358
359 status = acpi_ns_attach_object (device, obj_desc, node->type);
360
361 /* Remove local reference to the object */
362
363 acpi_ut_remove_reference (obj_desc);
364 if (ACPI_FAILURE (status)) {
365 goto unlock_and_exit;
366 }
367 }
368
369 /* Install the handler */
370
371 notify_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_NOTIFY);
372 if (!notify_obj) {
373 status = AE_NO_MEMORY;
374 goto unlock_and_exit;
375 }
376
377 notify_obj->notify.node = node;
378 notify_obj->notify.handler = handler;
379 notify_obj->notify.context = context;
380
381 if (handler_type & ACPI_SYSTEM_NOTIFY) {
382 obj_desc->common_notify.system_notify = notify_obj;
383 }
384
385 if (handler_type & ACPI_DEVICE_NOTIFY) {
386 obj_desc->common_notify.device_notify = notify_obj;
387 }
388
389 if (handler_type == ACPI_ALL_NOTIFY) {
390 /* Extra ref if installed in both */
391
392 acpi_ut_add_reference (notify_obj);
393 }
394 }
395
396
397unlock_and_exit:
398 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
399 return_ACPI_STATUS (status);
400}
401EXPORT_SYMBOL(acpi_install_notify_handler);
402
403
404/*******************************************************************************
405 *
406 * FUNCTION: acpi_remove_notify_handler
407 *
408 * PARAMETERS: Device - The device for which notifies will be handled
409 * handler_type - The type of handler:
410 * ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
411 * ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
412 * ACPI_ALL_NOTIFY: both system and device
413 * Handler - Address of the handler
414 *
415 * RETURN: Status
416 *
417 * DESCRIPTION: Remove a handler for notifies on an ACPI device
418 *
419 ******************************************************************************/
420
421acpi_status
422acpi_remove_notify_handler (
423 acpi_handle device,
424 u32 handler_type,
425 acpi_notify_handler handler)
426{
427 union acpi_operand_object *notify_obj;
428 union acpi_operand_object *obj_desc;
429 struct acpi_namespace_node *node;
430 acpi_status status;
431
432
433 ACPI_FUNCTION_TRACE ("acpi_remove_notify_handler");
434
435
436 /* Parameter validation */
437
438 if ((!device) ||
439 (!handler) ||
440 (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
441 return_ACPI_STATUS (AE_BAD_PARAMETER);
442 }
443
444 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
445 if (ACPI_FAILURE (status)) {
446 return_ACPI_STATUS (status);
447 }
448
449 /* Convert and validate the device handle */
450
451 node = acpi_ns_map_handle_to_node (device);
452 if (!node) {
453 status = AE_BAD_PARAMETER;
454 goto unlock_and_exit;
455 }
456
457 /* Root Object */
458
459 if (device == ACPI_ROOT_OBJECT) {
460 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing notify handler for ROOT object.\n"));
461
462 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
463 !acpi_gbl_system_notify.handler) ||
464 ((handler_type & ACPI_DEVICE_NOTIFY) &&
465 !acpi_gbl_device_notify.handler)) {
466 status = AE_NOT_EXIST;
467 goto unlock_and_exit;
468 }
469
470 /* Make sure all deferred tasks are completed */
471
472 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
473 acpi_os_wait_events_complete(NULL);
474 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
475 if (ACPI_FAILURE (status)) {
476 return_ACPI_STATUS (status);
477 }
478
479 if (handler_type & ACPI_SYSTEM_NOTIFY) {
480 acpi_gbl_system_notify.node = NULL;
481 acpi_gbl_system_notify.handler = NULL;
482 acpi_gbl_system_notify.context = NULL;
483 }
484
485 if (handler_type & ACPI_DEVICE_NOTIFY) {
486 acpi_gbl_device_notify.node = NULL;
487 acpi_gbl_device_notify.handler = NULL;
488 acpi_gbl_device_notify.context = NULL;
489 }
490 }
491
492 /* All Other Objects */
493
494 else {
495 /* Notifies allowed on this object? */
496
497 if (!acpi_ev_is_notify_object (node)) {
498 status = AE_TYPE;
499 goto unlock_and_exit;
500 }
501
502 /* Check for an existing internal object */
503
504 obj_desc = acpi_ns_get_attached_object (node);
505 if (!obj_desc) {
506 status = AE_NOT_EXIST;
507 goto unlock_and_exit;
508 }
509
510 /* Object exists - make sure there's an existing handler */
511
512 if (handler_type & ACPI_SYSTEM_NOTIFY) {
513 notify_obj = obj_desc->common_notify.system_notify;
514 if ((!notify_obj) ||
515 (notify_obj->notify.handler != handler)) {
516 status = AE_BAD_PARAMETER;
517 goto unlock_and_exit;
518 }
519 /* Make sure all deferred tasks are completed */
520
521 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
522 acpi_os_wait_events_complete(NULL);
523 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
524 if (ACPI_FAILURE (status)) {
525 return_ACPI_STATUS (status);
526 }
527
528 /* Remove the handler */
529 obj_desc->common_notify.system_notify = NULL;
530 acpi_ut_remove_reference (notify_obj);
531 }
532
533 if (handler_type & ACPI_DEVICE_NOTIFY) {
534 notify_obj = obj_desc->common_notify.device_notify;
535 if ((!notify_obj) ||
536 (notify_obj->notify.handler != handler)) {
537 status = AE_BAD_PARAMETER;
538 goto unlock_and_exit;
539 }
540 /* Make sure all deferred tasks are completed */
541
542 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
543 acpi_os_wait_events_complete(NULL);
544 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
545 if (ACPI_FAILURE (status)) {
546 return_ACPI_STATUS (status);
547 }
548
549 /* Remove the handler */
550 obj_desc->common_notify.device_notify = NULL;
551 acpi_ut_remove_reference (notify_obj);
552 }
553 }
554
555
556unlock_and_exit:
557 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
558 return_ACPI_STATUS (status);
559}
560EXPORT_SYMBOL(acpi_remove_notify_handler);
561
562
563/*******************************************************************************
564 *
565 * FUNCTION: acpi_install_gpe_handler
566 *
567 * PARAMETERS: gpe_number - The GPE number within the GPE block
568 * gpe_block - GPE block (NULL == FADT GPEs)
569 * Type - Whether this GPE should be treated as an
570 * edge- or level-triggered interrupt.
571 * Address - Address of the handler
572 * Context - Value passed to the handler on each GPE
573 *
574 * RETURN: Status
575 *
576 * DESCRIPTION: Install a handler for a General Purpose Event.
577 *
578 ******************************************************************************/
579
580acpi_status
581acpi_install_gpe_handler (
582 acpi_handle gpe_device,
583 u32 gpe_number,
584 u32 type,
585 acpi_event_handler address,
586 void *context)
587{
588 struct acpi_gpe_event_info *gpe_event_info;
589 struct acpi_handler_info *handler;
590 acpi_status status;
591
592
593 ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler");
594
595
596 /* Parameter validation */
597
598 if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
599 return_ACPI_STATUS (AE_BAD_PARAMETER);
600 }
601
602 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
603 if (ACPI_FAILURE (status)) {
604 return_ACPI_STATUS (status);
605 }
606
607 /* Ensure that we have a valid GPE number */
608
609 gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
610 if (!gpe_event_info) {
611 status = AE_BAD_PARAMETER;
612 goto unlock_and_exit;
613 }
614
615 /* Make sure that there isn't a handler there already */
616
617 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
618 status = AE_ALREADY_EXISTS;
619 goto unlock_and_exit;
620 }
621
622 /* Allocate and init handler object */
623
624 handler = ACPI_MEM_CALLOCATE (sizeof (struct acpi_handler_info));
625 if (!handler) {
626 status = AE_NO_MEMORY;
627 goto unlock_and_exit;
628 }
629
630 handler->address = address;
631 handler->context = context;
632 handler->method_node = gpe_event_info->dispatch.method_node;
633
634 /* Disable the GPE before installing the handler */
635
636 status = acpi_ev_disable_gpe (gpe_event_info);
637 if (ACPI_FAILURE (status)) {
638 goto unlock_and_exit;
639 }
640
641 /* Install the handler */
642
643 acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
644 gpe_event_info->dispatch.handler = handler;
645
646 /* Setup up dispatch flags to indicate handler (vs. method) */
647
648 gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */
649 gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
650
651 acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
652
653
654unlock_and_exit:
655 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
656 return_ACPI_STATUS (status);
657}
658EXPORT_SYMBOL(acpi_install_gpe_handler);
659
660
661/*******************************************************************************
662 *
663 * FUNCTION: acpi_remove_gpe_handler
664 *
665 * PARAMETERS: gpe_number - The event to remove a handler
666 * gpe_block - GPE block (NULL == FADT GPEs)
667 * Address - Address of the handler
668 *
669 * RETURN: Status
670 *
671 * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
672 *
673 ******************************************************************************/
674
675acpi_status
676acpi_remove_gpe_handler (
677 acpi_handle gpe_device,
678 u32 gpe_number,
679 acpi_event_handler address)
680{
681 struct acpi_gpe_event_info *gpe_event_info;
682 struct acpi_handler_info *handler;
683 acpi_status status;
684
685
686 ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler");
687
688
689 /* Parameter validation */
690
691 if (!address) {
692 return_ACPI_STATUS (AE_BAD_PARAMETER);
693 }
694
695 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
696 if (ACPI_FAILURE (status)) {
697 return_ACPI_STATUS (status);
698 }
699
700 /* Ensure that we have a valid GPE number */
701
702 gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
703 if (!gpe_event_info) {
704 status = AE_BAD_PARAMETER;
705 goto unlock_and_exit;
706 }
707
708 /* Make sure that a handler is indeed installed */
709
710 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER) {
711 status = AE_NOT_EXIST;
712 goto unlock_and_exit;
713 }
714
715 /* Make sure that the installed handler is the same */
716
717 if (gpe_event_info->dispatch.handler->address != address) {
718 status = AE_BAD_PARAMETER;
719 goto unlock_and_exit;
720 }
721
722 /* Disable the GPE before removing the handler */
723
724 status = acpi_ev_disable_gpe (gpe_event_info);
725 if (ACPI_FAILURE (status)) {
726 goto unlock_and_exit;
727 }
728
729 /* Make sure all deferred tasks are completed */
730
731 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
732 acpi_os_wait_events_complete(NULL);
733 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
734 if (ACPI_FAILURE (status)) {
735 return_ACPI_STATUS (status);
736 }
737
738 /* Remove the handler */
739
740 acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
741 handler = gpe_event_info->dispatch.handler;
742
743 /* Restore Method node (if any), set dispatch flags */
744
745 gpe_event_info->dispatch.method_node = handler->method_node;
746 gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */
747 if (handler->method_node) {
748 gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD;
749 }
750 acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
751
752 /* Now we can free the handler object */
753
754 ACPI_MEM_FREE (handler);
755
756
757unlock_and_exit:
758 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
759 return_ACPI_STATUS (status);
760}
761EXPORT_SYMBOL(acpi_remove_gpe_handler);
762
763
764/*******************************************************************************
765 *
766 * FUNCTION: acpi_acquire_global_lock
767 *
768 * PARAMETERS: Timeout - How long the caller is willing to wait
769 * out_handle - A handle to the lock if acquired
770 *
771 * RETURN: Status
772 *
773 * DESCRIPTION: Acquire the ACPI Global Lock
774 *
775 ******************************************************************************/
776
777acpi_status
778acpi_acquire_global_lock (
779 u16 timeout,
780 u32 *handle)
781{
782 acpi_status status;
783
784
785 if (!handle) {
786 return (AE_BAD_PARAMETER);
787 }
788
789 status = acpi_ex_enter_interpreter ();
790 if (ACPI_FAILURE (status)) {
791 return (status);
792 }
793
794 status = acpi_ev_acquire_global_lock (timeout);
795 acpi_ex_exit_interpreter ();
796
797 if (ACPI_SUCCESS (status)) {
798 acpi_gbl_global_lock_handle++;
799 *handle = acpi_gbl_global_lock_handle;
800 }
801
802 return (status);
803}
804EXPORT_SYMBOL(acpi_acquire_global_lock);
805
806
807/*******************************************************************************
808 *
809 * FUNCTION: acpi_release_global_lock
810 *
811 * PARAMETERS: Handle - Returned from acpi_acquire_global_lock
812 *
813 * RETURN: Status
814 *
815 * DESCRIPTION: Release the ACPI Global Lock
816 *
817 ******************************************************************************/
818
819acpi_status
820acpi_release_global_lock (
821 u32 handle)
822{
823 acpi_status status;
824
825
826 if (handle != acpi_gbl_global_lock_handle) {
827 return (AE_NOT_ACQUIRED);
828 }
829
830 status = acpi_ev_release_global_lock ();
831 return (status);
832}
833EXPORT_SYMBOL(acpi_release_global_lock);
834
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
new file mode 100644
index 000000000000..fa8d5f25be62
--- /dev/null
+++ b/drivers/acpi/events/evxfevnt.c
@@ -0,0 +1,778 @@
1/******************************************************************************
2 *
3 * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <linux/module.h>
45
46#include <acpi/acpi.h>
47#include <acpi/acevents.h>
48#include <acpi/acnamesp.h>
49
50#define _COMPONENT ACPI_EVENTS
51 ACPI_MODULE_NAME ("evxfevnt")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_enable
57 *
58 * PARAMETERS: None
59 *
60 * RETURN: Status
61 *
62 * DESCRIPTION: Transfers the system into ACPI mode.
63 *
64 ******************************************************************************/
65
66acpi_status
67acpi_enable (void)
68{
69 acpi_status status = AE_OK;
70
71
72 ACPI_FUNCTION_TRACE ("acpi_enable");
73
74
75 /* Make sure we have the FADT*/
76
77 if (!acpi_gbl_FADT) {
78 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n"));
79 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
80 }
81
82 if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
83 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "System is already in ACPI mode\n"));
84 }
85 else {
86 /* Transition to ACPI mode */
87
88 status = acpi_hw_set_mode (ACPI_SYS_MODE_ACPI);
89 if (ACPI_FAILURE (status)) {
90 ACPI_REPORT_ERROR (("Could not transition to ACPI mode.\n"));
91 return_ACPI_STATUS (status);
92 }
93
94 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Transition to ACPI mode successful\n"));
95 }
96
97 return_ACPI_STATUS (status);
98}
99
100
101/*******************************************************************************
102 *
103 * FUNCTION: acpi_disable
104 *
105 * PARAMETERS: None
106 *
107 * RETURN: Status
108 *
109 * DESCRIPTION: Transfers the system into LEGACY mode.
110 *
111 ******************************************************************************/
112
113acpi_status
114acpi_disable (void)
115{
116 acpi_status status = AE_OK;
117
118
119 ACPI_FUNCTION_TRACE ("acpi_disable");
120
121
122 if (!acpi_gbl_FADT) {
123 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n"));
124 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
125 }
126
127 if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
128 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "System is already in legacy (non-ACPI) mode\n"));
129 }
130 else {
131 /* Transition to LEGACY mode */
132
133 status = acpi_hw_set_mode (ACPI_SYS_MODE_LEGACY);
134
135 if (ACPI_FAILURE (status)) {
136 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not exit ACPI mode to legacy mode"));
137 return_ACPI_STATUS (status);
138 }
139
140 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI mode disabled\n"));
141 }
142
143 return_ACPI_STATUS (status);
144}
145
146
147/*******************************************************************************
148 *
149 * FUNCTION: acpi_enable_event
150 *
151 * PARAMETERS: Event - The fixed eventto be enabled
152 * Flags - Reserved
153 *
154 * RETURN: Status
155 *
156 * DESCRIPTION: Enable an ACPI event (fixed)
157 *
158 ******************************************************************************/
159
160acpi_status
161acpi_enable_event (
162 u32 event,
163 u32 flags)
164{
165 acpi_status status = AE_OK;
166 u32 value;
167
168
169 ACPI_FUNCTION_TRACE ("acpi_enable_event");
170
171
172 /* Decode the Fixed Event */
173
174 if (event > ACPI_EVENT_MAX) {
175 return_ACPI_STATUS (AE_BAD_PARAMETER);
176 }
177
178 /*
179 * Enable the requested fixed event (by writing a one to the
180 * enable register bit)
181 */
182 status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
183 1, ACPI_MTX_LOCK);
184 if (ACPI_FAILURE (status)) {
185 return_ACPI_STATUS (status);
186 }
187
188 /* Make sure that the hardware responded */
189
190 status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
191 &value, ACPI_MTX_LOCK);
192 if (ACPI_FAILURE (status)) {
193 return_ACPI_STATUS (status);
194 }
195
196 if (value != 1) {
197 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
198 "Could not enable %s event\n", acpi_ut_get_event_name (event)));
199 return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
200 }
201
202 return_ACPI_STATUS (status);
203}
204EXPORT_SYMBOL(acpi_enable_event);
205
206
207/*******************************************************************************
208 *
209 * FUNCTION: acpi_set_gpe_type
210 *
211 * PARAMETERS: gpe_device - Parent GPE Device
212 * gpe_number - GPE level within the GPE block
213 * Type - New GPE type
214 *
215 * RETURN: Status
216 *
217 * DESCRIPTION: Enable an ACPI event (general purpose)
218 *
219 ******************************************************************************/
220
221acpi_status
222acpi_set_gpe_type (
223 acpi_handle gpe_device,
224 u32 gpe_number,
225 u8 type)
226{
227 acpi_status status = AE_OK;
228 struct acpi_gpe_event_info *gpe_event_info;
229
230
231 ACPI_FUNCTION_TRACE ("acpi_set_gpe_type");
232
233
234 /* Ensure that we have a valid GPE number */
235
236 gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
237 if (!gpe_event_info) {
238 status = AE_BAD_PARAMETER;
239 goto unlock_and_exit;
240 }
241
242 if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
243 return_ACPI_STATUS (AE_OK);
244 }
245
246 /* Set the new type (will disable GPE if currently enabled) */
247
248 status = acpi_ev_set_gpe_type (gpe_event_info, type);
249
250unlock_and_exit:
251 return_ACPI_STATUS (status);
252}
253EXPORT_SYMBOL(acpi_set_gpe_type);
254
255
256/*******************************************************************************
257 *
258 * FUNCTION: acpi_enable_gpe
259 *
260 * PARAMETERS: gpe_device - Parent GPE Device
261 * gpe_number - GPE level within the GPE block
262 * Flags - Just enable, or also wake enable?
263 * Called from ISR or not
264 *
265 * RETURN: Status
266 *
267 * DESCRIPTION: Enable an ACPI event (general purpose)
268 *
269 ******************************************************************************/
270
271acpi_status
272acpi_enable_gpe (
273 acpi_handle gpe_device,
274 u32 gpe_number,
275 u32 flags)
276{
277 acpi_status status = AE_OK;
278 struct acpi_gpe_event_info *gpe_event_info;
279
280
281 ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
282
283
284 /* Use semaphore lock if not executing at interrupt level */
285
286 if (flags & ACPI_NOT_ISR) {
287 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
288 if (ACPI_FAILURE (status)) {
289 return_ACPI_STATUS (status);
290 }
291 }
292
293 /* Ensure that we have a valid GPE number */
294
295 gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
296 if (!gpe_event_info) {
297 status = AE_BAD_PARAMETER;
298 goto unlock_and_exit;
299 }
300
301 /* Perform the enable */
302
303 status = acpi_ev_enable_gpe (gpe_event_info, TRUE);
304
305unlock_and_exit:
306 if (flags & ACPI_NOT_ISR) {
307 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
308 }
309 return_ACPI_STATUS (status);
310}
311EXPORT_SYMBOL(acpi_enable_gpe);
312
313
314/*******************************************************************************
315 *
316 * FUNCTION: acpi_disable_gpe
317 *
318 * PARAMETERS: gpe_device - Parent GPE Device
319 * gpe_number - GPE level within the GPE block
320 * Flags - Just disable, or also wake disable?
321 * Called from ISR or not
322 *
323 * RETURN: Status
324 *
325 * DESCRIPTION: Disable an ACPI event (general purpose)
326 *
327 ******************************************************************************/
328
329acpi_status
330acpi_disable_gpe (
331 acpi_handle gpe_device,
332 u32 gpe_number,
333 u32 flags)
334{
335 acpi_status status = AE_OK;
336 struct acpi_gpe_event_info *gpe_event_info;
337
338
339 ACPI_FUNCTION_TRACE ("acpi_disable_gpe");
340
341
342 /* Use semaphore lock if not executing at interrupt level */
343
344 if (flags & ACPI_NOT_ISR) {
345 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
346 if (ACPI_FAILURE (status)) {
347 return_ACPI_STATUS (status);
348 }
349 }
350
351 /* Ensure that we have a valid GPE number */
352
353 gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
354 if (!gpe_event_info) {
355 status = AE_BAD_PARAMETER;
356 goto unlock_and_exit;
357 }
358
359 status = acpi_ev_disable_gpe (gpe_event_info);
360
361unlock_and_exit:
362 if (flags & ACPI_NOT_ISR) {
363 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
364 }
365 return_ACPI_STATUS (status);
366}
367
368
369/*******************************************************************************
370 *
371 * FUNCTION: acpi_disable_event
372 *
373 * PARAMETERS: Event - The fixed eventto be enabled
374 * Flags - Reserved
375 *
376 * RETURN: Status
377 *
378 * DESCRIPTION: Disable an ACPI event (fixed)
379 *
380 ******************************************************************************/
381
382acpi_status
383acpi_disable_event (
384 u32 event,
385 u32 flags)
386{
387 acpi_status status = AE_OK;
388 u32 value;
389
390
391 ACPI_FUNCTION_TRACE ("acpi_disable_event");
392
393
394 /* Decode the Fixed Event */
395
396 if (event > ACPI_EVENT_MAX) {
397 return_ACPI_STATUS (AE_BAD_PARAMETER);
398 }
399
400 /*
401 * Disable the requested fixed event (by writing a zero to the
402 * enable register bit)
403 */
404 status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
405 0, ACPI_MTX_LOCK);
406 if (ACPI_FAILURE (status)) {
407 return_ACPI_STATUS (status);
408 }
409
410 status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
411 &value, ACPI_MTX_LOCK);
412 if (ACPI_FAILURE (status)) {
413 return_ACPI_STATUS (status);
414 }
415
416 if (value != 0) {
417 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
418 "Could not disable %s events\n", acpi_ut_get_event_name (event)));
419 return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
420 }
421
422 return_ACPI_STATUS (status);
423}
424EXPORT_SYMBOL(acpi_disable_event);
425
426
427/*******************************************************************************
428 *
429 * FUNCTION: acpi_clear_event
430 *
431 * PARAMETERS: Event - The fixed event to be cleared
432 *
433 * RETURN: Status
434 *
435 * DESCRIPTION: Clear an ACPI event (fixed)
436 *
437 ******************************************************************************/
438
439acpi_status
440acpi_clear_event (
441 u32 event)
442{
443 acpi_status status = AE_OK;
444
445
446 ACPI_FUNCTION_TRACE ("acpi_clear_event");
447
448
449 /* Decode the Fixed Event */
450
451 if (event > ACPI_EVENT_MAX) {
452 return_ACPI_STATUS (AE_BAD_PARAMETER);
453 }
454
455 /*
456 * Clear the requested fixed event (By writing a one to the
457 * status register bit)
458 */
459 status = acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id,
460 1, ACPI_MTX_LOCK);
461
462 return_ACPI_STATUS (status);
463}
464EXPORT_SYMBOL(acpi_clear_event);
465
466
467/*******************************************************************************
468 *
469 * FUNCTION: acpi_clear_gpe
470 *
471 * PARAMETERS: gpe_device - Parent GPE Device
472 * gpe_number - GPE level within the GPE block
473 * Flags - Called from an ISR or not
474 *
475 * RETURN: Status
476 *
477 * DESCRIPTION: Clear an ACPI event (general purpose)
478 *
479 ******************************************************************************/
480
481acpi_status
482acpi_clear_gpe (
483 acpi_handle gpe_device,
484 u32 gpe_number,
485 u32 flags)
486{
487 acpi_status status = AE_OK;
488 struct acpi_gpe_event_info *gpe_event_info;
489
490
491 ACPI_FUNCTION_TRACE ("acpi_clear_gpe");
492
493
494 /* Use semaphore lock if not executing at interrupt level */
495
496 if (flags & ACPI_NOT_ISR) {
497 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
498 if (ACPI_FAILURE (status)) {
499 return_ACPI_STATUS (status);
500 }
501 }
502
503 /* Ensure that we have a valid GPE number */
504
505 gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
506 if (!gpe_event_info) {
507 status = AE_BAD_PARAMETER;
508 goto unlock_and_exit;
509 }
510
511 status = acpi_hw_clear_gpe (gpe_event_info);
512
513unlock_and_exit:
514 if (flags & ACPI_NOT_ISR) {
515 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
516 }
517 return_ACPI_STATUS (status);
518}
519
520
521#ifdef ACPI_FUTURE_USAGE
522
523/*******************************************************************************
524 *
525 * FUNCTION: acpi_get_event_status
526 *
527 * PARAMETERS: Event - The fixed event
528 * Event Status - Where the current status of the event will
529 * be returned
530 *
531 * RETURN: Status
532 *
533 * DESCRIPTION: Obtains and returns the current status of the event
534 *
535 ******************************************************************************/
536
537acpi_status
538acpi_get_event_status (
539 u32 event,
540 acpi_event_status *event_status)
541{
542 acpi_status status = AE_OK;
543
544
545 ACPI_FUNCTION_TRACE ("acpi_get_event_status");
546
547
548 if (!event_status) {
549 return_ACPI_STATUS (AE_BAD_PARAMETER);
550 }
551
552 /* Decode the Fixed Event */
553
554 if (event > ACPI_EVENT_MAX) {
555 return_ACPI_STATUS (AE_BAD_PARAMETER);
556 }
557
558 /* Get the status of the requested fixed event */
559
560 status = acpi_get_register (acpi_gbl_fixed_event_info[event].status_register_id,
561 event_status, ACPI_MTX_LOCK);
562
563 return_ACPI_STATUS (status);
564}
565
566
567/*******************************************************************************
568 *
569 * FUNCTION: acpi_get_gpe_status
570 *
571 * PARAMETERS: gpe_device - Parent GPE Device
572 * gpe_number - GPE level within the GPE block
573 * Flags - Called from an ISR or not
574 * Event Status - Where the current status of the event will
575 * be returned
576 *
577 * RETURN: Status
578 *
579 * DESCRIPTION: Get status of an event (general purpose)
580 *
581 ******************************************************************************/
582
583acpi_status
584acpi_get_gpe_status (
585 acpi_handle gpe_device,
586 u32 gpe_number,
587 u32 flags,
588 acpi_event_status *event_status)
589{
590 acpi_status status = AE_OK;
591 struct acpi_gpe_event_info *gpe_event_info;
592
593
594 ACPI_FUNCTION_TRACE ("acpi_get_gpe_status");
595
596
597 /* Use semaphore lock if not executing at interrupt level */
598
599 if (flags & ACPI_NOT_ISR) {
600 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
601 if (ACPI_FAILURE (status)) {
602 return_ACPI_STATUS (status);
603 }
604 }
605
606 /* Ensure that we have a valid GPE number */
607
608 gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
609 if (!gpe_event_info) {
610 status = AE_BAD_PARAMETER;
611 goto unlock_and_exit;
612 }
613
614 /* Obtain status on the requested GPE number */
615
616 status = acpi_hw_get_gpe_status (gpe_event_info, event_status);
617
618unlock_and_exit:
619 if (flags & ACPI_NOT_ISR) {
620 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
621 }
622 return_ACPI_STATUS (status);
623}
624#endif /* ACPI_FUTURE_USAGE */
625
626
627/*******************************************************************************
628 *
629 * FUNCTION: acpi_install_gpe_block
630 *
631 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
632 * gpe_block_address - Address and space_iD
633 * register_count - Number of GPE register pairs in the block
634 * interrupt_level - H/W interrupt for the block
635 *
636 * RETURN: Status
637 *
638 * DESCRIPTION: Create and Install a block of GPE registers
639 *
640 ******************************************************************************/
641
642acpi_status
643acpi_install_gpe_block (
644 acpi_handle gpe_device,
645 struct acpi_generic_address *gpe_block_address,
646 u32 register_count,
647 u32 interrupt_level)
648{
649 acpi_status status;
650 union acpi_operand_object *obj_desc;
651 struct acpi_namespace_node *node;
652 struct acpi_gpe_block_info *gpe_block;
653
654
655 ACPI_FUNCTION_TRACE ("acpi_install_gpe_block");
656
657
658 if ((!gpe_device) ||
659 (!gpe_block_address) ||
660 (!register_count)) {
661 return_ACPI_STATUS (AE_BAD_PARAMETER);
662 }
663
664 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
665 if (ACPI_FAILURE (status)) {
666 return (status);
667 }
668
669 node = acpi_ns_map_handle_to_node (gpe_device);
670 if (!node) {
671 status = AE_BAD_PARAMETER;
672 goto unlock_and_exit;
673 }
674
675 /*
676 * For user-installed GPE Block Devices, the gpe_block_base_number
677 * is always zero
678 */
679 status = acpi_ev_create_gpe_block (node, gpe_block_address, register_count,
680 0, interrupt_level, &gpe_block);
681 if (ACPI_FAILURE (status)) {
682 goto unlock_and_exit;
683 }
684
685 /* Get the device_object attached to the node */
686
687 obj_desc = acpi_ns_get_attached_object (node);
688 if (!obj_desc) {
689 /* No object, create a new one */
690
691 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_DEVICE);
692 if (!obj_desc) {
693 status = AE_NO_MEMORY;
694 goto unlock_and_exit;
695 }
696
697 status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_DEVICE);
698
699 /* Remove local reference to the object */
700
701 acpi_ut_remove_reference (obj_desc);
702
703 if (ACPI_FAILURE (status)) {
704 goto unlock_and_exit;
705 }
706 }
707
708 /* Install the GPE block in the device_object */
709
710 obj_desc->device.gpe_block = gpe_block;
711
712
713unlock_and_exit:
714 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
715 return_ACPI_STATUS (status);
716}
717EXPORT_SYMBOL(acpi_install_gpe_block);
718
719
720/*******************************************************************************
721 *
722 * FUNCTION: acpi_remove_gpe_block
723 *
724 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
725 *
726 * RETURN: Status
727 *
728 * DESCRIPTION: Remove a previously installed block of GPE registers
729 *
730 ******************************************************************************/
731
732acpi_status
733acpi_remove_gpe_block (
734 acpi_handle gpe_device)
735{
736 union acpi_operand_object *obj_desc;
737 acpi_status status;
738 struct acpi_namespace_node *node;
739
740
741 ACPI_FUNCTION_TRACE ("acpi_remove_gpe_block");
742
743
744 if (!gpe_device) {
745 return_ACPI_STATUS (AE_BAD_PARAMETER);
746 }
747
748 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
749 if (ACPI_FAILURE (status)) {
750 return (status);
751 }
752
753 node = acpi_ns_map_handle_to_node (gpe_device);
754 if (!node) {
755 status = AE_BAD_PARAMETER;
756 goto unlock_and_exit;
757 }
758
759 /* Get the device_object attached to the node */
760
761 obj_desc = acpi_ns_get_attached_object (node);
762 if (!obj_desc ||
763 !obj_desc->device.gpe_block) {
764 return_ACPI_STATUS (AE_NULL_OBJECT);
765 }
766
767 /* Delete the GPE block (but not the device_object) */
768
769 status = acpi_ev_delete_gpe_block (obj_desc->device.gpe_block);
770 if (ACPI_SUCCESS (status)) {
771 obj_desc->device.gpe_block = NULL;
772 }
773
774unlock_and_exit:
775 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
776 return_ACPI_STATUS (status);
777}
778EXPORT_SYMBOL(acpi_remove_gpe_block);
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
new file mode 100644
index 000000000000..d058587b3427
--- /dev/null
+++ b/drivers/acpi/events/evxfregn.c
@@ -0,0 +1,247 @@
1/******************************************************************************
2 *
3 * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
4 * Address Spaces.
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <linux/module.h>
46
47#include <acpi/acpi.h>
48#include <acpi/acnamesp.h>
49#include <acpi/acevents.h>
50
51#define _COMPONENT ACPI_EVENTS
52 ACPI_MODULE_NAME ("evxfregn")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION: acpi_install_address_space_handler
58 *
59 * PARAMETERS: Device - Handle for the device
60 * space_id - The address space ID
61 * Handler - Address of the handler
62 * Setup - Address of the setup function
63 * Context - Value passed to the handler on each access
64 *
65 * RETURN: Status
66 *
67 * DESCRIPTION: Install a handler for all op_regions of a given space_id.
68 *
69 ******************************************************************************/
70
71acpi_status
72acpi_install_address_space_handler (
73 acpi_handle device,
74 acpi_adr_space_type space_id,
75 acpi_adr_space_handler handler,
76 acpi_adr_space_setup setup,
77 void *context)
78{
79 struct acpi_namespace_node *node;
80 acpi_status status;
81
82
83 ACPI_FUNCTION_TRACE ("acpi_install_address_space_handler");
84
85
86 /* Parameter validation */
87
88 if (!device) {
89 return_ACPI_STATUS (AE_BAD_PARAMETER);
90 }
91
92 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
93 if (ACPI_FAILURE (status)) {
94 return_ACPI_STATUS (status);
95 }
96
97 /* Convert and validate the device handle */
98
99 node = acpi_ns_map_handle_to_node (device);
100 if (!node) {
101 status = AE_BAD_PARAMETER;
102 goto unlock_and_exit;
103 }
104
105 /* Install the handler for all Regions for this Space ID */
106
107 status = acpi_ev_install_space_handler (node, space_id, handler, setup, context);
108 if (ACPI_FAILURE (status)) {
109 goto unlock_and_exit;
110 }
111
112 /* Run all _REG methods for this address space */
113
114 status = acpi_ev_execute_reg_methods (node, space_id);
115
116unlock_and_exit:
117 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
118 return_ACPI_STATUS (status);
119}
120EXPORT_SYMBOL(acpi_install_address_space_handler);
121
122
123/*******************************************************************************
124 *
125 * FUNCTION: acpi_remove_address_space_handler
126 *
127 * PARAMETERS: Device - Handle for the device
128 * space_id - The address space ID
129 * Handler - Address of the handler
130 *
131 * RETURN: Status
132 *
133 * DESCRIPTION: Remove a previously installed handler.
134 *
135 ******************************************************************************/
136
137acpi_status
138acpi_remove_address_space_handler (
139 acpi_handle device,
140 acpi_adr_space_type space_id,
141 acpi_adr_space_handler handler)
142{
143 union acpi_operand_object *obj_desc;
144 union acpi_operand_object *handler_obj;
145 union acpi_operand_object *region_obj;
146 union acpi_operand_object **last_obj_ptr;
147 struct acpi_namespace_node *node;
148 acpi_status status;
149
150
151 ACPI_FUNCTION_TRACE ("acpi_remove_address_space_handler");
152
153
154 /* Parameter validation */
155
156 if (!device) {
157 return_ACPI_STATUS (AE_BAD_PARAMETER);
158 }
159
160 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
161 if (ACPI_FAILURE (status)) {
162 return_ACPI_STATUS (status);
163 }
164
165 /* Convert and validate the device handle */
166
167 node = acpi_ns_map_handle_to_node (device);
168 if (!node) {
169 status = AE_BAD_PARAMETER;
170 goto unlock_and_exit;
171 }
172
173 /* Make sure the internal object exists */
174
175 obj_desc = acpi_ns_get_attached_object (node);
176 if (!obj_desc) {
177 status = AE_NOT_EXIST;
178 goto unlock_and_exit;
179 }
180
181 /* Find the address handler the user requested */
182
183 handler_obj = obj_desc->device.handler;
184 last_obj_ptr = &obj_desc->device.handler;
185 while (handler_obj) {
186 /* We have a handler, see if user requested this one */
187
188 if (handler_obj->address_space.space_id == space_id) {
189 /* Matched space_id, first dereference this in the Regions */
190
191 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
192 "Removing address handler %p(%p) for region %s on Device %p(%p)\n",
193 handler_obj, handler, acpi_ut_get_region_name (space_id),
194 node, obj_desc));
195
196 region_obj = handler_obj->address_space.region_list;
197
198 /* Walk the handler's region list */
199
200 while (region_obj) {
201 /*
202 * First disassociate the handler from the region.
203 *
204 * NOTE: this doesn't mean that the region goes away
205 * The region is just inaccessible as indicated to
206 * the _REG method
207 */
208 acpi_ev_detach_region (region_obj, TRUE);
209
210 /*
211 * Walk the list: Just grab the head because the
212 * detach_region removed the previous head.
213 */
214 region_obj = handler_obj->address_space.region_list;
215
216 }
217
218 /* Remove this Handler object from the list */
219
220 *last_obj_ptr = handler_obj->address_space.next;
221
222 /* Now we can delete the handler object */
223
224 acpi_ut_remove_reference (handler_obj);
225 goto unlock_and_exit;
226 }
227
228 /* Walk the linked list of handlers */
229
230 last_obj_ptr = &handler_obj->address_space.next;
231 handler_obj = handler_obj->address_space.next;
232 }
233
234 /* The handler does not exist */
235
236 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
237 "Unable to remove address handler %p for %s(%X), dev_node %p, obj %p\n",
238 handler, acpi_ut_get_region_name (space_id), space_id, node, obj_desc));
239
240 status = AE_NOT_EXIST;
241
242unlock_and_exit:
243 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
244 return_ACPI_STATUS (status);
245}
246EXPORT_SYMBOL(acpi_remove_address_space_handler);
247
diff --git a/drivers/acpi/executer/Makefile b/drivers/acpi/executer/Makefile
new file mode 100644
index 000000000000..e09998aa012f
--- /dev/null
+++ b/drivers/acpi/executer/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for all Linux ACPI interpreter subdirectories
3#
4
5obj-y := exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\
6 exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\
7 excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \
8 exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o
9
10EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
new file mode 100644
index 000000000000..ac3c061967f2
--- /dev/null
+++ b/drivers/acpi/executer/exconfig.c
@@ -0,0 +1,487 @@
1/******************************************************************************
2 *
3 * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acinterp.h>
47#include <acpi/amlcode.h>
48#include <acpi/acnamesp.h>
49#include <acpi/acevents.h>
50#include <acpi/actables.h>
51#include <acpi/acdispat.h>
52
53
54#define _COMPONENT ACPI_EXECUTER
55 ACPI_MODULE_NAME ("exconfig")
56
57
58/*******************************************************************************
59 *
60 * FUNCTION: acpi_ex_add_table
61 *
62 * PARAMETERS: Table - Pointer to raw table
63 * parent_node - Where to load the table (scope)
64 * ddb_handle - Where to return the table handle.
65 *
66 * RETURN: Status
67 *
68 * DESCRIPTION: Common function to Install and Load an ACPI table with a
69 * returned table handle.
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_ex_add_table (
75 struct acpi_table_header *table,
76 struct acpi_namespace_node *parent_node,
77 union acpi_operand_object **ddb_handle)
78{
79 acpi_status status;
80 struct acpi_table_desc table_info;
81 union acpi_operand_object *obj_desc;
82
83
84 ACPI_FUNCTION_TRACE ("ex_add_table");
85
86
87 /* Create an object to be the table handle */
88
89 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
90 if (!obj_desc) {
91 return_ACPI_STATUS (AE_NO_MEMORY);
92 }
93
94 /* Install the new table into the local data structures */
95
96 ACPI_MEMSET (&table_info, 0, sizeof (struct acpi_table_desc));
97
98 table_info.type = ACPI_TABLE_SSDT;
99 table_info.pointer = table;
100 table_info.length = (acpi_size) table->length;
101 table_info.allocation = ACPI_MEM_ALLOCATED;
102
103 status = acpi_tb_install_table (&table_info);
104 if (ACPI_FAILURE (status)) {
105 goto cleanup;
106 }
107
108 /* Add the table to the namespace */
109
110 status = acpi_ns_load_table (table_info.installed_desc, parent_node);
111 if (ACPI_FAILURE (status)) {
112 /* Uninstall table on error */
113
114 (void) acpi_tb_uninstall_table (table_info.installed_desc);
115 goto cleanup;
116 }
117
118 /* Init the table handle */
119
120 obj_desc->reference.opcode = AML_LOAD_OP;
121 obj_desc->reference.object = table_info.installed_desc;
122 *ddb_handle = obj_desc;
123 return_ACPI_STATUS (AE_OK);
124
125
126cleanup:
127 acpi_ut_remove_reference (obj_desc);
128 return_ACPI_STATUS (status);
129}
130
131
132/*******************************************************************************
133 *
134 * FUNCTION: acpi_ex_load_table_op
135 *
136 * PARAMETERS: walk_state - Current state with operands
137 * return_desc - Where to store the return object
138 *
139 * RETURN: Status
140 *
141 * DESCRIPTION: Load an ACPI table
142 *
143 ******************************************************************************/
144
145acpi_status
146acpi_ex_load_table_op (
147 struct acpi_walk_state *walk_state,
148 union acpi_operand_object **return_desc)
149{
150 acpi_status status;
151 union acpi_operand_object **operand = &walk_state->operands[0];
152 struct acpi_table_header *table;
153 struct acpi_namespace_node *parent_node;
154 struct acpi_namespace_node *start_node;
155 struct acpi_namespace_node *parameter_node = NULL;
156 union acpi_operand_object *ddb_handle;
157
158
159 ACPI_FUNCTION_TRACE ("ex_load_table_op");
160
161
162#if 0
163 /*
164 * Make sure that the signature does not match one of the tables that
165 * is already loaded.
166 */
167 status = acpi_tb_match_signature (operand[0]->string.pointer, NULL);
168 if (status == AE_OK) {
169 /* Signature matched -- don't allow override */
170
171 return_ACPI_STATUS (AE_ALREADY_EXISTS);
172 }
173#endif
174
175 /* Find the ACPI table */
176
177 status = acpi_tb_find_table (operand[0]->string.pointer,
178 operand[1]->string.pointer,
179 operand[2]->string.pointer, &table);
180 if (ACPI_FAILURE (status)) {
181 if (status != AE_NOT_FOUND) {
182 return_ACPI_STATUS (status);
183 }
184
185 /* Table not found, return an Integer=0 and AE_OK */
186
187 ddb_handle = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
188 if (!ddb_handle) {
189 return_ACPI_STATUS (AE_NO_MEMORY);
190 }
191
192 ddb_handle->integer.value = 0;
193 *return_desc = ddb_handle;
194
195 return_ACPI_STATUS (AE_OK);
196 }
197
198 /* Default nodes */
199
200 start_node = walk_state->scope_info->scope.node;
201 parent_node = acpi_gbl_root_node;
202
203 /* root_path (optional parameter) */
204
205 if (operand[3]->string.length > 0) {
206 /*
207 * Find the node referenced by the root_path_string. This is the
208 * location within the namespace where the table will be loaded.
209 */
210 status = acpi_ns_get_node_by_path (operand[3]->string.pointer, start_node,
211 ACPI_NS_SEARCH_PARENT, &parent_node);
212 if (ACPI_FAILURE (status)) {
213 return_ACPI_STATUS (status);
214 }
215 }
216
217 /* parameter_path (optional parameter) */
218
219 if (operand[4]->string.length > 0) {
220 if ((operand[4]->string.pointer[0] != '\\') &&
221 (operand[4]->string.pointer[0] != '^')) {
222 /*
223 * Path is not absolute, so it will be relative to the node
224 * referenced by the root_path_string (or the NS root if omitted)
225 */
226 start_node = parent_node;
227 }
228
229 /*
230 * Find the node referenced by the parameter_path_string
231 */
232 status = acpi_ns_get_node_by_path (operand[4]->string.pointer, start_node,
233 ACPI_NS_SEARCH_PARENT, &parameter_node);
234 if (ACPI_FAILURE (status)) {
235 return_ACPI_STATUS (status);
236 }
237 }
238
239 /* Load the table into the namespace */
240
241 status = acpi_ex_add_table (table, parent_node, &ddb_handle);
242 if (ACPI_FAILURE (status)) {
243 return_ACPI_STATUS (status);
244 }
245
246 /* Parameter Data (optional) */
247
248 if (parameter_node) {
249 /* Store the parameter data into the optional parameter object */
250
251 status = acpi_ex_store (operand[5], ACPI_CAST_PTR (union acpi_operand_object, parameter_node),
252 walk_state);
253 if (ACPI_FAILURE (status)) {
254 (void) acpi_ex_unload_table (ddb_handle);
255 return_ACPI_STATUS (status);
256 }
257 }
258
259 *return_desc = ddb_handle;
260 return_ACPI_STATUS (status);
261}
262
263
264/*******************************************************************************
265 *
266 * FUNCTION: acpi_ex_load_op
267 *
268 * PARAMETERS: obj_desc - Region or Field where the table will be
269 * obtained
270 * Target - Where a handle to the table will be stored
271 * walk_state - Current state
272 *
273 * RETURN: Status
274 *
275 * DESCRIPTION: Load an ACPI table from a field or operation region
276 *
277 ******************************************************************************/
278
279acpi_status
280acpi_ex_load_op (
281 union acpi_operand_object *obj_desc,
282 union acpi_operand_object *target,
283 struct acpi_walk_state *walk_state)
284{
285 acpi_status status;
286 union acpi_operand_object *ddb_handle;
287 union acpi_operand_object *buffer_desc = NULL;
288 struct acpi_table_header *table_ptr = NULL;
289 acpi_physical_address address;
290 struct acpi_table_header table_header;
291 u32 i;
292
293 ACPI_FUNCTION_TRACE ("ex_load_op");
294
295
296 /* Object can be either an op_region or a Field */
297
298 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
299 case ACPI_TYPE_REGION:
300
301 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n",
302 obj_desc, acpi_ut_get_object_type_name (obj_desc)));
303
304 /*
305 * If the Region Address and Length have not been previously evaluated,
306 * evaluate them now and save the results.
307 */
308 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
309 status = acpi_ds_get_region_arguments (obj_desc);
310 if (ACPI_FAILURE (status)) {
311 return_ACPI_STATUS (status);
312 }
313 }
314
315 /* Get the base physical address of the region */
316
317 address = obj_desc->region.address;
318
319 /* Get the table length from the table header */
320
321 table_header.length = 0;
322 for (i = 0; i < 8; i++) {
323 status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
324 (acpi_physical_address) (i + address), 8,
325 ((u8 *) &table_header) + i);
326 if (ACPI_FAILURE (status)) {
327 return_ACPI_STATUS (status);
328 }
329 }
330
331 /* Sanity check the table length */
332
333 if (table_header.length < sizeof (struct acpi_table_header)) {
334 return_ACPI_STATUS (AE_BAD_HEADER);
335 }
336
337 /* Allocate a buffer for the entire table */
338
339 table_ptr = ACPI_MEM_ALLOCATE (table_header.length);
340 if (!table_ptr) {
341 return_ACPI_STATUS (AE_NO_MEMORY);
342 }
343
344 /* Get the entire table from the op region */
345
346 for (i = 0; i < table_header.length; i++) {
347 status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
348 (acpi_physical_address) (i + address), 8,
349 ((u8 *) table_ptr + i));
350 if (ACPI_FAILURE (status)) {
351 goto cleanup;
352 }
353 }
354 break;
355
356
357 case ACPI_TYPE_LOCAL_REGION_FIELD:
358 case ACPI_TYPE_LOCAL_BANK_FIELD:
359 case ACPI_TYPE_LOCAL_INDEX_FIELD:
360
361 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Field %p %s\n",
362 obj_desc, acpi_ut_get_object_type_name (obj_desc)));
363
364 /*
365 * The length of the field must be at least as large as the table.
366 * Read the entire field and thus the entire table. Buffer is
367 * allocated during the read.
368 */
369 status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc);
370 if (ACPI_FAILURE (status)) {
371 goto cleanup;
372 }
373
374 table_ptr = ACPI_CAST_PTR (struct acpi_table_header, buffer_desc->buffer.pointer);
375
376 /* Sanity check the table length */
377
378 if (table_ptr->length < sizeof (struct acpi_table_header)) {
379 return_ACPI_STATUS (AE_BAD_HEADER);
380 }
381 break;
382
383
384 default:
385 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
386 }
387
388 /* The table must be either an SSDT or a PSDT */
389
390 if ((!ACPI_STRNCMP (table_ptr->signature,
391 acpi_gbl_table_data[ACPI_TABLE_PSDT].signature,
392 acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) &&
393 (!ACPI_STRNCMP (table_ptr->signature,
394 acpi_gbl_table_data[ACPI_TABLE_SSDT].signature,
395 acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) {
396 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
397 "Table has invalid signature [%4.4s], must be SSDT or PSDT\n",
398 table_ptr->signature));
399 status = AE_BAD_SIGNATURE;
400 goto cleanup;
401 }
402
403 /* Install the new table into the local data structures */
404
405 status = acpi_ex_add_table (table_ptr, acpi_gbl_root_node, &ddb_handle);
406 if (ACPI_FAILURE (status)) {
407 goto cleanup;
408 }
409
410 /* Store the ddb_handle into the Target operand */
411
412 status = acpi_ex_store (ddb_handle, target, walk_state);
413 if (ACPI_FAILURE (status)) {
414 (void) acpi_ex_unload_table (ddb_handle);
415 }
416
417 return_ACPI_STATUS (status);
418
419
420cleanup:
421
422 if (buffer_desc) {
423 acpi_ut_remove_reference (buffer_desc);
424 }
425 else {
426 ACPI_MEM_FREE (table_ptr);
427 }
428 return_ACPI_STATUS (status);
429}
430
431
432/*******************************************************************************
433 *
434 * FUNCTION: acpi_ex_unload_table
435 *
436 * PARAMETERS: ddb_handle - Handle to a previously loaded table
437 *
438 * RETURN: Status
439 *
440 * DESCRIPTION: Unload an ACPI table
441 *
442 ******************************************************************************/
443
444acpi_status
445acpi_ex_unload_table (
446 union acpi_operand_object *ddb_handle)
447{
448 acpi_status status = AE_OK;
449 union acpi_operand_object *table_desc = ddb_handle;
450 struct acpi_table_desc *table_info;
451
452
453 ACPI_FUNCTION_TRACE ("ex_unload_table");
454
455
456 /*
457 * Validate the handle
458 * Although the handle is partially validated in acpi_ex_reconfiguration(),
459 * when it calls acpi_ex_resolve_operands(), the handle is more completely
460 * validated here.
461 */
462 if ((!ddb_handle) ||
463 (ACPI_GET_DESCRIPTOR_TYPE (ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
464 (ACPI_GET_OBJECT_TYPE (ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) {
465 return_ACPI_STATUS (AE_BAD_PARAMETER);
466 }
467
468 /* Get the actual table descriptor from the ddb_handle */
469
470 table_info = (struct acpi_table_desc *) table_desc->reference.object;
471
472 /*
473 * Delete the entire namespace under this table Node
474 * (Offset contains the table_id)
475 */
476 acpi_ns_delete_namespace_by_owner (table_info->table_id);
477
478 /* Delete the table itself */
479
480 (void) acpi_tb_uninstall_table (table_info->installed_desc);
481
482 /* Delete the table descriptor (ddb_handle) */
483
484 acpi_ut_remove_reference (table_desc);
485 return_ACPI_STATUS (status);
486}
487
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
new file mode 100644
index 000000000000..df7ba1219bf6
--- /dev/null
+++ b/drivers/acpi/executer/exconvrt.c
@@ -0,0 +1,708 @@
1/******************************************************************************
2 *
3 * Module Name: exconvrt - Object conversion routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acinterp.h>
47#include <acpi/amlcode.h>
48
49
50#define _COMPONENT ACPI_EXECUTER
51 ACPI_MODULE_NAME ("exconvrt")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ex_convert_to_integer
57 *
58 * PARAMETERS: obj_desc - Object to be converted. Must be an
59 * Integer, Buffer, or String
60 * result_desc - Where the new Integer object is returned
61 * Flags - Used for string conversion
62 *
63 * RETURN: Status
64 *
65 * DESCRIPTION: Convert an ACPI Object to an integer.
66 *
67 ******************************************************************************/
68
69acpi_status
70acpi_ex_convert_to_integer (
71 union acpi_operand_object *obj_desc,
72 union acpi_operand_object **result_desc,
73 u32 flags)
74{
75 union acpi_operand_object *return_desc;
76 u8 *pointer;
77 acpi_integer result;
78 u32 i;
79 u32 count;
80 acpi_status status;
81
82
83 ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_integer", obj_desc);
84
85
86 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
87 case ACPI_TYPE_INTEGER:
88
89 /* No conversion necessary */
90
91 *result_desc = obj_desc;
92 return_ACPI_STATUS (AE_OK);
93
94 case ACPI_TYPE_BUFFER:
95 case ACPI_TYPE_STRING:
96
97 /* Note: Takes advantage of common buffer/string fields */
98
99 pointer = obj_desc->buffer.pointer;
100 count = obj_desc->buffer.length;
101 break;
102
103 default:
104 return_ACPI_STATUS (AE_TYPE);
105 }
106
107 /*
108 * Convert the buffer/string to an integer. Note that both buffers and
109 * strings are treated as raw data - we don't convert ascii to hex for
110 * strings.
111 *
112 * There are two terminating conditions for the loop:
113 * 1) The size of an integer has been reached, or
114 * 2) The end of the buffer or string has been reached
115 */
116 result = 0;
117
118 /*
119 * String conversion is different than Buffer conversion
120 */
121 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
122 case ACPI_TYPE_STRING:
123
124 /*
125 * Convert string to an integer - for most cases, the string must be
126 * hexadecimal as per the ACPI specification. The only exception (as
127 * of ACPI 3.0) is that the to_integer() operator allows both decimal
128 * and hexadecimal strings (hex prefixed with "0x").
129 */
130 status = acpi_ut_strtoul64 ((char *) pointer, flags, &result);
131 if (ACPI_FAILURE (status)) {
132 return_ACPI_STATUS (status);
133 }
134 break;
135
136
137 case ACPI_TYPE_BUFFER:
138
139 /* Check for zero-length buffer */
140
141 if (!count) {
142 return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
143 }
144
145 /* Transfer no more than an integer's worth of data */
146
147 if (count > acpi_gbl_integer_byte_width) {
148 count = acpi_gbl_integer_byte_width;
149 }
150
151 /*
152 * Convert buffer to an integer - we simply grab enough raw data
153 * from the buffer to fill an integer
154 */
155 for (i = 0; i < count; i++) {
156 /*
157 * Get next byte and shift it into the Result.
158 * Little endian is used, meaning that the first byte of the buffer
159 * is the LSB of the integer
160 */
161 result |= (((acpi_integer) pointer[i]) << (i * 8));
162 }
163 break;
164
165
166 default:
167 /* No other types can get here */
168 break;
169 }
170
171 /*
172 * Create a new integer
173 */
174 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
175 if (!return_desc) {
176 return_ACPI_STATUS (AE_NO_MEMORY);
177 }
178
179 /* Save the Result */
180
181 return_desc->integer.value = result;
182 acpi_ex_truncate_for32bit_table (return_desc);
183 *result_desc = return_desc;
184 return_ACPI_STATUS (AE_OK);
185}
186
187
188/*******************************************************************************
189 *
190 * FUNCTION: acpi_ex_convert_to_buffer
191 *
192 * PARAMETERS: obj_desc - Object to be converted. Must be an
193 * Integer, Buffer, or String
194 * result_desc - Where the new buffer object is returned
195 *
196 * RETURN: Status
197 *
198 * DESCRIPTION: Convert an ACPI Object to a Buffer
199 *
200 ******************************************************************************/
201
202acpi_status
203acpi_ex_convert_to_buffer (
204 union acpi_operand_object *obj_desc,
205 union acpi_operand_object **result_desc)
206{
207 union acpi_operand_object *return_desc;
208 u8 *new_buf;
209
210
211 ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_buffer", obj_desc);
212
213
214 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
215 case ACPI_TYPE_BUFFER:
216
217 /* No conversion necessary */
218
219 *result_desc = obj_desc;
220 return_ACPI_STATUS (AE_OK);
221
222
223 case ACPI_TYPE_INTEGER:
224
225 /*
226 * Create a new Buffer object.
227 * Need enough space for one integer
228 */
229 return_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width);
230 if (!return_desc) {
231 return_ACPI_STATUS (AE_NO_MEMORY);
232 }
233
234 /* Copy the integer to the buffer, LSB first */
235
236 new_buf = return_desc->buffer.pointer;
237 ACPI_MEMCPY (new_buf,
238 &obj_desc->integer.value,
239 acpi_gbl_integer_byte_width);
240 break;
241
242
243 case ACPI_TYPE_STRING:
244
245 /*
246 * Create a new Buffer object
247 * Size will be the string length
248 *
249 * NOTE: Add one to the string length to include the null terminator.
250 * The ACPI spec is unclear on this subject, but there is existing
251 * ASL/AML code that depends on the null being transferred to the new
252 * buffer.
253 */
254 return_desc = acpi_ut_create_buffer_object ((acpi_size) obj_desc->string.length + 1);
255 if (!return_desc) {
256 return_ACPI_STATUS (AE_NO_MEMORY);
257 }
258
259 /* Copy the string to the buffer */
260
261 new_buf = return_desc->buffer.pointer;
262 ACPI_STRNCPY ((char *) new_buf, (char *) obj_desc->string.pointer,
263 obj_desc->string.length);
264 break;
265
266
267 default:
268 return_ACPI_STATUS (AE_TYPE);
269 }
270
271 /* Mark buffer initialized */
272
273 return_desc->common.flags |= AOPOBJ_DATA_VALID;
274 *result_desc = return_desc;
275 return_ACPI_STATUS (AE_OK);
276}
277
278
279/*******************************************************************************
280 *
281 * FUNCTION: acpi_ex_convert_to_ascii
282 *
283 * PARAMETERS: Integer - Value to be converted
284 * Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX
285 * String - Where the string is returned
286 * data_width - Size of data item to be converted, in bytes
287 *
288 * RETURN: Actual string length
289 *
290 * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string
291 *
292 ******************************************************************************/
293
294u32
295acpi_ex_convert_to_ascii (
296 acpi_integer integer,
297 u16 base,
298 u8 *string,
299 u8 data_width)
300{
301 acpi_integer digit;
302 acpi_native_uint i;
303 acpi_native_uint j;
304 acpi_native_uint k = 0;
305 acpi_native_uint hex_length;
306 acpi_native_uint decimal_length;
307 u32 remainder;
308 u8 supress_zeros;
309
310
311 ACPI_FUNCTION_ENTRY ();
312
313
314 switch (base) {
315 case 10:
316
317 /* Setup max length for the decimal number */
318
319 switch (data_width) {
320 case 1:
321 decimal_length = ACPI_MAX8_DECIMAL_DIGITS;
322 break;
323
324 case 4:
325 decimal_length = ACPI_MAX32_DECIMAL_DIGITS;
326 break;
327
328 case 8:
329 default:
330 decimal_length = ACPI_MAX64_DECIMAL_DIGITS;
331 break;
332 }
333
334 supress_zeros = TRUE; /* No leading zeros */
335 remainder = 0;
336
337 for (i = decimal_length; i > 0; i--) {
338 /* Divide by nth factor of 10 */
339
340 digit = integer;
341 for (j = 0; j < i; j++) {
342 (void) acpi_ut_short_divide (digit, 10, &digit, &remainder);
343 }
344
345 /* Handle leading zeros */
346
347 if (remainder != 0) {
348 supress_zeros = FALSE;
349 }
350
351 if (!supress_zeros) {
352 string[k] = (u8) (ACPI_ASCII_ZERO + remainder);
353 k++;
354 }
355 }
356 break;
357
358 case 16:
359
360 hex_length = ACPI_MUL_2 (data_width); /* 2 ascii hex chars per data byte */
361
362 for (i = 0, j = (hex_length-1); i < hex_length; i++, j--) {
363 /* Get one hex digit, most significant digits first */
364
365 string[k] = (u8) acpi_ut_hex_to_ascii_char (integer, ACPI_MUL_4 (j));
366 k++;
367 }
368 break;
369
370 default:
371 return (0);
372 }
373
374 /*
375 * Since leading zeros are supressed, we must check for the case where
376 * the integer equals 0
377 *
378 * Finally, null terminate the string and return the length
379 */
380 if (!k) {
381 string [0] = ACPI_ASCII_ZERO;
382 k = 1;
383 }
384
385 string [k] = 0;
386 return ((u32) k);
387}
388
389
390/*******************************************************************************
391 *
392 * FUNCTION: acpi_ex_convert_to_string
393 *
394 * PARAMETERS: obj_desc - Object to be converted. Must be an
395 * Integer, Buffer, or String
396 * result_desc - Where the string object is returned
397 * Type - String flags (base and conversion type)
398 *
399 * RETURN: Status
400 *
401 * DESCRIPTION: Convert an ACPI Object to a string
402 *
403 ******************************************************************************/
404
405acpi_status
406acpi_ex_convert_to_string (
407 union acpi_operand_object *obj_desc,
408 union acpi_operand_object **result_desc,
409 u32 type)
410{
411 union acpi_operand_object *return_desc;
412 u8 *new_buf;
413 u32 i;
414 u32 string_length = 0;
415 u16 base = 16;
416 u8 separator = ',';
417
418
419 ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_string", obj_desc);
420
421
422 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
423 case ACPI_TYPE_STRING:
424
425 /* No conversion necessary */
426
427 *result_desc = obj_desc;
428 return_ACPI_STATUS (AE_OK);
429
430
431 case ACPI_TYPE_INTEGER:
432
433 switch (type) {
434 case ACPI_EXPLICIT_CONVERT_DECIMAL:
435
436 /* Make room for maximum decimal number */
437
438 string_length = ACPI_MAX_DECIMAL_DIGITS;
439 base = 10;
440 break;
441
442 default:
443
444 /* Two hex string characters for each integer byte */
445
446 string_length = ACPI_MUL_2 (acpi_gbl_integer_byte_width);
447 break;
448 }
449
450 /*
451 * Create a new String
452 * Need enough space for one ASCII integer (plus null terminator)
453 */
454 return_desc = acpi_ut_create_string_object ((acpi_size) string_length);
455 if (!return_desc) {
456 return_ACPI_STATUS (AE_NO_MEMORY);
457 }
458
459 new_buf = return_desc->buffer.pointer;
460
461 /* Convert integer to string */
462
463 string_length = acpi_ex_convert_to_ascii (obj_desc->integer.value, base,
464 new_buf, acpi_gbl_integer_byte_width);
465
466 /* Null terminate at the correct place */
467
468 return_desc->string.length = string_length;
469 new_buf [string_length] = 0;
470 break;
471
472
473 case ACPI_TYPE_BUFFER:
474
475 /* Setup string length, base, and separator */
476
477 switch (type) {
478 case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string operator */
479 /*
480 * From ACPI: "If Data is a buffer, it is converted to a string of
481 * decimal values separated by commas."
482 */
483 base = 10;
484
485 /*
486 * Calculate the final string length. Individual string values
487 * are variable length (include separator for each)
488 */
489 for (i = 0; i < obj_desc->buffer.length; i++) {
490 if (obj_desc->buffer.pointer[i] >= 100) {
491 string_length += 4;
492 }
493 else if (obj_desc->buffer.pointer[i] >= 10) {
494 string_length += 3;
495 }
496 else {
497 string_length += 2;
498 }
499 }
500 break;
501
502 case ACPI_IMPLICIT_CONVERT_HEX:
503 /*
504 * From the ACPI spec:
505 *"The entire contents of the buffer are converted to a string of
506 * two-character hexadecimal numbers, each separated by a space."
507 */
508 separator = ' ';
509 string_length = (obj_desc->buffer.length * 3);
510 break;
511
512 case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string operator */
513 /*
514 * From ACPI: "If Data is a buffer, it is converted to a string of
515 * hexadecimal values separated by commas."
516 */
517 string_length = (obj_desc->buffer.length * 3);
518 break;
519
520 default:
521 return_ACPI_STATUS (AE_BAD_PARAMETER);
522 }
523
524 /*
525 * Perform the conversion.
526 * (-1 because of extra separator included in string_length from above)
527 */
528 string_length--;
529 if (string_length > ACPI_MAX_STRING_CONVERSION) /* ACPI limit */ {
530 return_ACPI_STATUS (AE_AML_STRING_LIMIT);
531 }
532
533 /*
534 * Create a new string object and string buffer
535 */
536 return_desc = acpi_ut_create_string_object ((acpi_size) string_length);
537 if (!return_desc) {
538 return_ACPI_STATUS (AE_NO_MEMORY);
539 }
540
541 new_buf = return_desc->buffer.pointer;
542
543 /*
544 * Convert buffer bytes to hex or decimal values
545 * (separated by commas or spaces)
546 */
547 for (i = 0; i < obj_desc->buffer.length; i++) {
548 new_buf += acpi_ex_convert_to_ascii (
549 (acpi_integer) obj_desc->buffer.pointer[i], base,
550 new_buf, 1);
551 *new_buf++ = separator; /* each separated by a comma or space */
552 }
553
554 /* Null terminate the string (overwrites final comma/space from above) */
555
556 new_buf--;
557 *new_buf = 0;
558 break;
559
560 default:
561 return_ACPI_STATUS (AE_TYPE);
562 }
563
564 *result_desc = return_desc;
565 return_ACPI_STATUS (AE_OK);
566}
567
568
569/*******************************************************************************
570 *
571 * FUNCTION: acpi_ex_convert_to_target_type
572 *
573 * PARAMETERS: destination_type - Current type of the destination
574 * source_desc - Source object to be converted.
575 * result_desc - Where the converted object is returned
576 * walk_state - Current method state
577 *
578 * RETURN: Status
579 *
580 * DESCRIPTION: Implements "implicit conversion" rules for storing an object.
581 *
582 ******************************************************************************/
583
584acpi_status
585acpi_ex_convert_to_target_type (
586 acpi_object_type destination_type,
587 union acpi_operand_object *source_desc,
588 union acpi_operand_object **result_desc,
589 struct acpi_walk_state *walk_state)
590{
591 acpi_status status = AE_OK;
592
593
594 ACPI_FUNCTION_TRACE ("ex_convert_to_target_type");
595
596
597 /* Default behavior */
598
599 *result_desc = source_desc;
600
601 /*
602 * If required by the target,
603 * perform implicit conversion on the source before we store it.
604 */
605 switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) {
606 case ARGI_SIMPLE_TARGET:
607 case ARGI_FIXED_TARGET:
608 case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */
609
610 switch (destination_type) {
611 case ACPI_TYPE_LOCAL_REGION_FIELD:
612 /*
613 * Named field can always handle conversions
614 */
615 break;
616
617 default:
618 /* No conversion allowed for these types */
619
620 if (destination_type != ACPI_GET_OBJECT_TYPE (source_desc)) {
621 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
622 "Explicit operator, will store (%s) over existing type (%s)\n",
623 acpi_ut_get_object_type_name (source_desc),
624 acpi_ut_get_type_name (destination_type)));
625 status = AE_TYPE;
626 }
627 }
628 break;
629
630
631 case ARGI_TARGETREF:
632
633 switch (destination_type) {
634 case ACPI_TYPE_INTEGER:
635 case ACPI_TYPE_BUFFER_FIELD:
636 case ACPI_TYPE_LOCAL_BANK_FIELD:
637 case ACPI_TYPE_LOCAL_INDEX_FIELD:
638 /*
639 * These types require an Integer operand. We can convert
640 * a Buffer or a String to an Integer if necessary.
641 */
642 status = acpi_ex_convert_to_integer (source_desc, result_desc,
643 16);
644 break;
645
646
647 case ACPI_TYPE_STRING:
648
649 /*
650 * The operand must be a String. We can convert an
651 * Integer or Buffer if necessary
652 */
653 status = acpi_ex_convert_to_string (source_desc, result_desc,
654 ACPI_IMPLICIT_CONVERT_HEX);
655 break;
656
657
658 case ACPI_TYPE_BUFFER:
659
660 /*
661 * The operand must be a Buffer. We can convert an
662 * Integer or String if necessary
663 */
664 status = acpi_ex_convert_to_buffer (source_desc, result_desc);
665 break;
666
667
668 default:
669 ACPI_REPORT_ERROR (("Bad destination type during conversion: %X\n",
670 destination_type));
671 status = AE_AML_INTERNAL;
672 break;
673 }
674 break;
675
676
677 case ARGI_REFERENCE:
678 /*
679 * create_xxxx_field cases - we are storing the field object into the name
680 */
681 break;
682
683
684 default:
685 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
686 "Unknown Target type ID 0x%X Op %s dest_type %s\n",
687 GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args),
688 walk_state->op_info->name, acpi_ut_get_type_name (destination_type)));
689
690 ACPI_REPORT_ERROR (("Bad Target Type (ARGI): %X\n",
691 GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)))
692 status = AE_AML_INTERNAL;
693 }
694
695 /*
696 * Source-to-Target conversion semantics:
697 *
698 * If conversion to the target type cannot be performed, then simply
699 * overwrite the target with the new object and type.
700 */
701 if (status == AE_TYPE) {
702 status = AE_OK;
703 }
704
705 return_ACPI_STATUS (status);
706}
707
708
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
new file mode 100644
index 000000000000..d94c260dac6d
--- /dev/null
+++ b/drivers/acpi/executer/excreate.c
@@ -0,0 +1,646 @@
1/******************************************************************************
2 *
3 * Module Name: excreate - Named object creation
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acinterp.h>
47#include <acpi/amlcode.h>
48#include <acpi/acnamesp.h>
49#include <acpi/acevents.h>
50#include <acpi/actables.h>
51
52
53#define _COMPONENT ACPI_EXECUTER
54 ACPI_MODULE_NAME ("excreate")
55
56
57#ifndef ACPI_NO_METHOD_EXECUTION
58/*****************************************************************************
59 *
60 * FUNCTION: acpi_ex_create_alias
61 *
62 * PARAMETERS: walk_state - Current state, contains operands
63 *
64 * RETURN: Status
65 *
66 * DESCRIPTION: Create a new named alias
67 *
68 ****************************************************************************/
69
70acpi_status
71acpi_ex_create_alias (
72 struct acpi_walk_state *walk_state)
73{
74 struct acpi_namespace_node *target_node;
75 struct acpi_namespace_node *alias_node;
76 acpi_status status = AE_OK;
77
78
79 ACPI_FUNCTION_TRACE ("ex_create_alias");
80
81
82 /* Get the source/alias operands (both namespace nodes) */
83
84 alias_node = (struct acpi_namespace_node *) walk_state->operands[0];
85 target_node = (struct acpi_namespace_node *) walk_state->operands[1];
86
87 if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
88 (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
89 /*
90 * Dereference an existing alias so that we don't create a chain
91 * of aliases. With this code, we guarantee that an alias is
92 * always exactly one level of indirection away from the
93 * actual aliased name.
94 */
95 target_node = ACPI_CAST_PTR (struct acpi_namespace_node, target_node->object);
96 }
97
98 /*
99 * For objects that can never change (i.e., the NS node will
100 * permanently point to the same object), we can simply attach
101 * the object to the new NS node. For other objects (such as
102 * Integers, buffers, etc.), we have to point the Alias node
103 * to the original Node.
104 */
105 switch (target_node->type) {
106 case ACPI_TYPE_INTEGER:
107 case ACPI_TYPE_STRING:
108 case ACPI_TYPE_BUFFER:
109 case ACPI_TYPE_PACKAGE:
110 case ACPI_TYPE_BUFFER_FIELD:
111
112 /*
113 * The new alias has the type ALIAS and points to the original
114 * NS node, not the object itself. This is because for these
115 * types, the object can change dynamically via a Store.
116 */
117 alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
118 alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
119 break;
120
121 case ACPI_TYPE_METHOD:
122
123 /*
124 * The new alias has the type ALIAS and points to the original
125 * NS node, not the object itself. This is because for these
126 * types, the object can change dynamically via a Store.
127 */
128 alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
129 alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
130 break;
131
132 default:
133
134 /* Attach the original source object to the new Alias Node */
135
136 /*
137 * The new alias assumes the type of the target, and it points
138 * to the same object. The reference count of the object has an
139 * additional reference to prevent deletion out from under either the
140 * target node or the alias Node
141 */
142 status = acpi_ns_attach_object (alias_node,
143 acpi_ns_get_attached_object (target_node),
144 target_node->type);
145 break;
146 }
147
148 /* Since both operands are Nodes, we don't need to delete them */
149
150 return_ACPI_STATUS (status);
151}
152
153
154/*****************************************************************************
155 *
156 * FUNCTION: acpi_ex_create_event
157 *
158 * PARAMETERS: walk_state - Current state
159 *
160 * RETURN: Status
161 *
162 * DESCRIPTION: Create a new event object
163 *
164 ****************************************************************************/
165
166acpi_status
167acpi_ex_create_event (
168 struct acpi_walk_state *walk_state)
169{
170 acpi_status status;
171 union acpi_operand_object *obj_desc;
172
173
174 ACPI_FUNCTION_TRACE ("ex_create_event");
175
176
177 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_EVENT);
178 if (!obj_desc) {
179 status = AE_NO_MEMORY;
180 goto cleanup;
181 }
182
183 /*
184 * Create the actual OS semaphore, with zero initial units -- meaning
185 * that the event is created in an unsignalled state
186 */
187 status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0,
188 &obj_desc->event.semaphore);
189 if (ACPI_FAILURE (status)) {
190 goto cleanup;
191 }
192
193 /* Attach object to the Node */
194
195 status = acpi_ns_attach_object ((struct acpi_namespace_node *) walk_state->operands[0],
196 obj_desc, ACPI_TYPE_EVENT);
197
198cleanup:
199 /*
200 * Remove local reference to the object (on error, will cause deletion
201 * of both object and semaphore if present.)
202 */
203 acpi_ut_remove_reference (obj_desc);
204 return_ACPI_STATUS (status);
205}
206
207
208/*****************************************************************************
209 *
210 * FUNCTION: acpi_ex_create_mutex
211 *
212 * PARAMETERS: walk_state - Current state
213 *
214 * RETURN: Status
215 *
216 * DESCRIPTION: Create a new mutex object
217 *
218 * Mutex (Name[0], sync_level[1])
219 *
220 ****************************************************************************/
221
222acpi_status
223acpi_ex_create_mutex (
224 struct acpi_walk_state *walk_state)
225{
226 acpi_status status = AE_OK;
227 union acpi_operand_object *obj_desc;
228
229
230 ACPI_FUNCTION_TRACE_PTR ("ex_create_mutex", ACPI_WALK_OPERANDS);
231
232
233 /* Create the new mutex object */
234
235 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_MUTEX);
236 if (!obj_desc) {
237 status = AE_NO_MEMORY;
238 goto cleanup;
239 }
240
241 /*
242 * Create the actual OS semaphore.
243 * One unit max to make it a mutex, with one initial unit to allow
244 * the mutex to be acquired.
245 */
246 status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore);
247 if (ACPI_FAILURE (status)) {
248 goto cleanup;
249 }
250
251 /* Init object and attach to NS node */
252
253 obj_desc->mutex.sync_level = (u8) walk_state->operands[1]->integer.value;
254 obj_desc->mutex.node = (struct acpi_namespace_node *) walk_state->operands[0];
255
256 status = acpi_ns_attach_object (obj_desc->mutex.node,
257 obj_desc, ACPI_TYPE_MUTEX);
258
259
260cleanup:
261 /*
262 * Remove local reference to the object (on error, will cause deletion
263 * of both object and semaphore if present.)
264 */
265 acpi_ut_remove_reference (obj_desc);
266 return_ACPI_STATUS (status);
267}
268
269
270/*****************************************************************************
271 *
272 * FUNCTION: acpi_ex_create_region
273 *
274 * PARAMETERS: aml_start - Pointer to the region declaration AML
275 * aml_length - Max length of the declaration AML
276 * Operands - List of operands for the opcode
277 * walk_state - Current state
278 *
279 * RETURN: Status
280 *
281 * DESCRIPTION: Create a new operation region object
282 *
283 ****************************************************************************/
284
285acpi_status
286acpi_ex_create_region (
287 u8 *aml_start,
288 u32 aml_length,
289 u8 region_space,
290 struct acpi_walk_state *walk_state)
291{
292 acpi_status status;
293 union acpi_operand_object *obj_desc;
294 struct acpi_namespace_node *node;
295 union acpi_operand_object *region_obj2;
296
297
298 ACPI_FUNCTION_TRACE ("ex_create_region");
299
300
301 /* Get the Namespace Node */
302
303 node = walk_state->op->common.node;
304
305 /*
306 * If the region object is already attached to this node,
307 * just return
308 */
309 if (acpi_ns_get_attached_object (node)) {
310 return_ACPI_STATUS (AE_OK);
311 }
312
313 /*
314 * Space ID must be one of the predefined IDs, or in the user-defined
315 * range
316 */
317 if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
318 (region_space < ACPI_USER_REGION_BEGIN)) {
319 ACPI_REPORT_ERROR (("Invalid address_space type %X\n", region_space));
320 return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID);
321 }
322
323 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (%X)\n",
324 acpi_ut_get_region_name (region_space), region_space));
325
326 /* Create the region descriptor */
327
328 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION);
329 if (!obj_desc) {
330 status = AE_NO_MEMORY;
331 goto cleanup;
332 }
333
334 /*
335 * Remember location in AML stream of address & length
336 * operands since they need to be evaluated at run time.
337 */
338 region_obj2 = obj_desc->common.next_object;
339 region_obj2->extra.aml_start = aml_start;
340 region_obj2->extra.aml_length = aml_length;
341
342 /* Init the region from the operands */
343
344 obj_desc->region.space_id = region_space;
345 obj_desc->region.address = 0;
346 obj_desc->region.length = 0;
347 obj_desc->region.node = node;
348
349 /* Install the new region object in the parent Node */
350
351 status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION);
352
353
354cleanup:
355
356 /* Remove local reference to the object */
357
358 acpi_ut_remove_reference (obj_desc);
359 return_ACPI_STATUS (status);
360}
361
362
363/*****************************************************************************
364 *
365 * FUNCTION: acpi_ex_create_table_region
366 *
367 * PARAMETERS: walk_state - Current state
368 *
369 * RETURN: Status
370 *
371 * DESCRIPTION: Create a new data_table_region object
372 *
373 ****************************************************************************/
374
375acpi_status
376acpi_ex_create_table_region (
377 struct acpi_walk_state *walk_state)
378{
379 acpi_status status;
380 union acpi_operand_object **operand = &walk_state->operands[0];
381 union acpi_operand_object *obj_desc;
382 struct acpi_namespace_node *node;
383 struct acpi_table_header *table;
384 union acpi_operand_object *region_obj2;
385
386
387 ACPI_FUNCTION_TRACE ("ex_create_table_region");
388
389
390 /* Get the Node from the object stack */
391
392 node = walk_state->op->common.node;
393
394 /*
395 * If the region object is already attached to this node,
396 * just return
397 */
398 if (acpi_ns_get_attached_object (node)) {
399 return_ACPI_STATUS (AE_OK);
400 }
401
402 /* Find the ACPI table */
403
404 status = acpi_tb_find_table (operand[1]->string.pointer,
405 operand[2]->string.pointer,
406 operand[3]->string.pointer, &table);
407 if (ACPI_FAILURE (status)) {
408 return_ACPI_STATUS (status);
409 }
410
411 /* Create the region descriptor */
412
413 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION);
414 if (!obj_desc) {
415 return_ACPI_STATUS (AE_NO_MEMORY);
416 }
417
418 region_obj2 = obj_desc->common.next_object;
419 region_obj2->extra.region_context = NULL;
420
421 /* Init the region from the operands */
422
423 obj_desc->region.space_id = REGION_DATA_TABLE;
424 obj_desc->region.address = (acpi_physical_address) ACPI_TO_INTEGER (table);
425 obj_desc->region.length = table->length;
426 obj_desc->region.node = node;
427 obj_desc->region.flags = AOPOBJ_DATA_VALID;
428
429 /* Install the new region object in the parent Node */
430
431 status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION);
432 if (ACPI_FAILURE (status)) {
433 goto cleanup;
434 }
435
436 status = acpi_ev_initialize_region (obj_desc, FALSE);
437 if (ACPI_FAILURE (status)) {
438 if (status == AE_NOT_EXIST) {
439 status = AE_OK;
440 }
441 else {
442 goto cleanup;
443 }
444 }
445
446 obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE;
447
448
449cleanup:
450
451 /* Remove local reference to the object */
452
453 acpi_ut_remove_reference (obj_desc);
454 return_ACPI_STATUS (status);
455}
456
457
458/*****************************************************************************
459 *
460 * FUNCTION: acpi_ex_create_processor
461 *
462 * PARAMETERS: walk_state - Current state
463 *
464 * RETURN: Status
465 *
466 * DESCRIPTION: Create a new processor object and populate the fields
467 *
468 * Processor (Name[0], cpu_iD[1], pblock_addr[2], pblock_length[3])
469 *
470 ****************************************************************************/
471
472acpi_status
473acpi_ex_create_processor (
474 struct acpi_walk_state *walk_state)
475{
476 union acpi_operand_object **operand = &walk_state->operands[0];
477 union acpi_operand_object *obj_desc;
478 acpi_status status;
479
480
481 ACPI_FUNCTION_TRACE_PTR ("ex_create_processor", walk_state);
482
483
484 /* Create the processor object */
485
486 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PROCESSOR);
487 if (!obj_desc) {
488 return_ACPI_STATUS (AE_NO_MEMORY);
489 }
490
491 /*
492 * Initialize the processor object from the operands
493 */
494 obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
495 obj_desc->processor.address = (acpi_io_address) operand[2]->integer.value;
496 obj_desc->processor.length = (u8) operand[3]->integer.value;
497
498 /* Install the processor object in the parent Node */
499
500 status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
501 obj_desc, ACPI_TYPE_PROCESSOR);
502
503 /* Remove local reference to the object */
504
505 acpi_ut_remove_reference (obj_desc);
506 return_ACPI_STATUS (status);
507}
508
509
510/*****************************************************************************
511 *
512 * FUNCTION: acpi_ex_create_power_resource
513 *
514 * PARAMETERS: walk_state - Current state
515 *
516 * RETURN: Status
517 *
518 * DESCRIPTION: Create a new power_resource object and populate the fields
519 *
520 * power_resource (Name[0], system_level[1], resource_order[2])
521 *
522 ****************************************************************************/
523
524acpi_status
525acpi_ex_create_power_resource (
526 struct acpi_walk_state *walk_state)
527{
528 union acpi_operand_object **operand = &walk_state->operands[0];
529 acpi_status status;
530 union acpi_operand_object *obj_desc;
531
532
533 ACPI_FUNCTION_TRACE_PTR ("ex_create_power_resource", walk_state);
534
535
536 /* Create the power resource object */
537
538 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_POWER);
539 if (!obj_desc) {
540 return_ACPI_STATUS (AE_NO_MEMORY);
541 }
542
543 /* Initialize the power object from the operands */
544
545 obj_desc->power_resource.system_level = (u8) operand[1]->integer.value;
546 obj_desc->power_resource.resource_order = (u16) operand[2]->integer.value;
547
548 /* Install the power resource object in the parent Node */
549
550 status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
551 obj_desc, ACPI_TYPE_POWER);
552
553 /* Remove local reference to the object */
554
555 acpi_ut_remove_reference (obj_desc);
556 return_ACPI_STATUS (status);
557}
558
559#endif
560
561/*****************************************************************************
562 *
563 * FUNCTION: acpi_ex_create_method
564 *
565 * PARAMETERS: aml_start - First byte of the method's AML
566 * aml_length - AML byte count for this method
567 * walk_state - Current state
568 *
569 * RETURN: Status
570 *
571 * DESCRIPTION: Create a new method object
572 *
573 ****************************************************************************/
574
575acpi_status
576acpi_ex_create_method (
577 u8 *aml_start,
578 u32 aml_length,
579 struct acpi_walk_state *walk_state)
580{
581 union acpi_operand_object **operand = &walk_state->operands[0];
582 union acpi_operand_object *obj_desc;
583 acpi_status status;
584 u8 method_flags;
585
586
587 ACPI_FUNCTION_TRACE_PTR ("ex_create_method", walk_state);
588
589
590 /* Create a new method object */
591
592 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_METHOD);
593 if (!obj_desc) {
594 return_ACPI_STATUS (AE_NO_MEMORY);
595 }
596
597 /* Save the method's AML pointer and length */
598
599 obj_desc->method.aml_start = aml_start;
600 obj_desc->method.aml_length = aml_length;
601
602 /*
603 * Disassemble the method flags. Split off the Arg Count
604 * for efficiency
605 */
606 method_flags = (u8) operand[1]->integer.value;
607
608 obj_desc->method.method_flags = (u8) (method_flags & ~AML_METHOD_ARG_COUNT);
609 obj_desc->method.param_count = (u8) (method_flags & AML_METHOD_ARG_COUNT);
610
611 /*
612 * Get the concurrency count. If required, a semaphore will be
613 * created for this method when it is parsed.
614 */
615 if (acpi_gbl_all_methods_serialized) {
616 obj_desc->method.concurrency = 1;
617 obj_desc->method.method_flags |= AML_METHOD_SERIALIZED;
618 }
619 else if (method_flags & AML_METHOD_SERIALIZED) {
620 /*
621 * ACPI 1.0: Concurrency = 1
622 * ACPI 2.0: Concurrency = (sync_level (in method declaration) + 1)
623 */
624 obj_desc->method.concurrency = (u8)
625 (((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1);
626 }
627 else {
628 obj_desc->method.concurrency = ACPI_INFINITE_CONCURRENCY;
629 }
630
631 /* Attach the new object to the method Node */
632
633 status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
634 obj_desc, ACPI_TYPE_METHOD);
635
636 /* Remove local reference to the object */
637
638 acpi_ut_remove_reference (obj_desc);
639
640 /* Remove a reference to the operand */
641
642 acpi_ut_remove_reference (operand[1]);
643 return_ACPI_STATUS (status);
644}
645
646
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
new file mode 100644
index 000000000000..e2f7c32f28de
--- /dev/null
+++ b/drivers/acpi/executer/exdump.c
@@ -0,0 +1,793 @@
1/******************************************************************************
2 *
3 * Module Name: exdump - Interpreter debug output routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acinterp.h>
47#include <acpi/amlcode.h>
48#include <acpi/acnamesp.h>
49#include <acpi/acparser.h>
50
51#define _COMPONENT ACPI_EXECUTER
52 ACPI_MODULE_NAME ("exdump")
53
54
55/*
56 * The following routines are used for debug output only
57 */
58#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
59
60/*****************************************************************************
61 *
62 * FUNCTION: acpi_ex_dump_operand
63 *
64 * PARAMETERS: *obj_desc - Pointer to entry to be dumped
65 *
66 * RETURN: None
67 *
68 * DESCRIPTION: Dump an operand object
69 *
70 ****************************************************************************/
71
72void
73acpi_ex_dump_operand (
74 union acpi_operand_object *obj_desc,
75 u32 depth)
76{
77 u32 length;
78 u32 index;
79
80
81 ACPI_FUNCTION_NAME ("ex_dump_operand")
82
83
84 if (!((ACPI_LV_EXEC & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
85 return;
86 }
87
88 if (!obj_desc) {
89 /*
90 * This could be a null element of a package
91 */
92 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Null Object Descriptor\n"));
93 return;
94 }
95
96 if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) {
97 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p is a NS Node: ", obj_desc));
98 ACPI_DUMP_ENTRY (obj_desc, ACPI_LV_EXEC);
99 return;
100 }
101
102 if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) {
103 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
104 "%p is not a node or operand object: [%s]\n",
105 obj_desc, acpi_ut_get_descriptor_name (obj_desc)));
106 ACPI_DUMP_BUFFER (obj_desc, sizeof (union acpi_operand_object));
107 return;
108 }
109
110 /* obj_desc is a valid object */
111
112 if (depth > 0) {
113 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%*s[%u] %p ",
114 depth, " ", depth, obj_desc));
115 }
116 else {
117 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", obj_desc));
118 }
119
120 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
121 case ACPI_TYPE_LOCAL_REFERENCE:
122
123 switch (obj_desc->reference.opcode) {
124 case AML_DEBUG_OP:
125
126 acpi_os_printf ("Reference: Debug\n");
127 break;
128
129
130 case AML_NAME_OP:
131
132 ACPI_DUMP_PATHNAME (obj_desc->reference.object,
133 "Reference: Name: ", ACPI_LV_INFO, _COMPONENT);
134 ACPI_DUMP_ENTRY (obj_desc->reference.object, ACPI_LV_INFO);
135 break;
136
137
138 case AML_INDEX_OP:
139
140 acpi_os_printf ("Reference: Index %p\n",
141 obj_desc->reference.object);
142 break;
143
144
145 case AML_REF_OF_OP:
146
147 acpi_os_printf ("Reference: (ref_of) %p\n",
148 obj_desc->reference.object);
149 break;
150
151
152 case AML_ARG_OP:
153
154 acpi_os_printf ("Reference: Arg%d",
155 obj_desc->reference.offset);
156
157 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
158 /* Value is an Integer */
159
160 acpi_os_printf (" value is [%8.8X%8.8x]",
161 ACPI_FORMAT_UINT64 (obj_desc->integer.value));
162 }
163
164 acpi_os_printf ("\n");
165 break;
166
167
168 case AML_LOCAL_OP:
169
170 acpi_os_printf ("Reference: Local%d",
171 obj_desc->reference.offset);
172
173 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
174
175 /* Value is an Integer */
176
177 acpi_os_printf (" value is [%8.8X%8.8x]",
178 ACPI_FORMAT_UINT64 (obj_desc->integer.value));
179 }
180
181 acpi_os_printf ("\n");
182 break;
183
184
185 case AML_INT_NAMEPATH_OP:
186
187 acpi_os_printf ("Reference.Node->Name %X\n",
188 obj_desc->reference.node->name.integer);
189 break;
190
191
192 default:
193
194 /* Unknown opcode */
195
196 acpi_os_printf ("Unknown Reference opcode=%X\n",
197 obj_desc->reference.opcode);
198 break;
199
200 }
201 break;
202
203
204 case ACPI_TYPE_BUFFER:
205
206 acpi_os_printf ("Buffer len %X @ %p \n",
207 obj_desc->buffer.length, obj_desc->buffer.pointer);
208
209 length = obj_desc->buffer.length;
210 if (length > 64) {
211 length = 64;
212 }
213
214 /* Debug only -- dump the buffer contents */
215
216 if (obj_desc->buffer.pointer) {
217 acpi_os_printf ("Buffer Contents: ");
218
219 for (index = 0; index < length; index++) {
220 acpi_os_printf (" %02x", obj_desc->buffer.pointer[index]);
221 }
222 acpi_os_printf ("\n");
223 }
224 break;
225
226
227 case ACPI_TYPE_INTEGER:
228
229 acpi_os_printf ("Integer %8.8X%8.8X\n",
230 ACPI_FORMAT_UINT64 (obj_desc->integer.value));
231 break;
232
233
234 case ACPI_TYPE_PACKAGE:
235
236 acpi_os_printf ("Package [Len %X] element_array %p\n",
237 obj_desc->package.count, obj_desc->package.elements);
238
239 /*
240 * If elements exist, package element pointer is valid,
241 * and debug_level exceeds 1, dump package's elements.
242 */
243 if (obj_desc->package.count &&
244 obj_desc->package.elements &&
245 acpi_dbg_level > 1) {
246 for (index = 0; index < obj_desc->package.count; index++) {
247 acpi_ex_dump_operand (obj_desc->package.elements[index], depth+1);
248 }
249 }
250 break;
251
252
253 case ACPI_TYPE_REGION:
254
255 acpi_os_printf ("Region %s (%X)",
256 acpi_ut_get_region_name (obj_desc->region.space_id),
257 obj_desc->region.space_id);
258
259 /*
260 * If the address and length have not been evaluated,
261 * don't print them.
262 */
263 if (!(obj_desc->region.flags & AOPOBJ_DATA_VALID)) {
264 acpi_os_printf ("\n");
265 }
266 else {
267 acpi_os_printf (" base %8.8X%8.8X Length %X\n",
268 ACPI_FORMAT_UINT64 (obj_desc->region.address),
269 obj_desc->region.length);
270 }
271 break;
272
273
274 case ACPI_TYPE_STRING:
275
276 acpi_os_printf ("String length %X @ %p ",
277 obj_desc->string.length, obj_desc->string.pointer);
278 acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX);
279 acpi_os_printf ("\n");
280 break;
281
282
283 case ACPI_TYPE_LOCAL_BANK_FIELD:
284
285 acpi_os_printf ("bank_field\n");
286 break;
287
288
289 case ACPI_TYPE_LOCAL_REGION_FIELD:
290
291 acpi_os_printf (
292 "region_field: Bits=%X acc_width=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n",
293 obj_desc->field.bit_length, obj_desc->field.access_byte_width,
294 obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK,
295 obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK,
296 obj_desc->field.base_byte_offset, obj_desc->field.start_field_bit_offset);
297 acpi_ex_dump_operand (obj_desc->field.region_obj, depth+1);
298 break;
299
300
301 case ACPI_TYPE_LOCAL_INDEX_FIELD:
302
303 acpi_os_printf ("index_field\n");
304 break;
305
306
307 case ACPI_TYPE_BUFFER_FIELD:
308
309 acpi_os_printf (
310 "buffer_field: %X bits at byte %X bit %X of \n",
311 obj_desc->buffer_field.bit_length, obj_desc->buffer_field.base_byte_offset,
312 obj_desc->buffer_field.start_field_bit_offset);
313
314 if (!obj_desc->buffer_field.buffer_obj) {
315 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*NULL* \n"));
316 }
317 else if (ACPI_GET_OBJECT_TYPE (obj_desc->buffer_field.buffer_obj) != ACPI_TYPE_BUFFER) {
318 acpi_os_printf ("*not a Buffer* \n");
319 }
320 else {
321 acpi_ex_dump_operand (obj_desc->buffer_field.buffer_obj, depth+1);
322 }
323 break;
324
325
326 case ACPI_TYPE_EVENT:
327
328 acpi_os_printf ("Event\n");
329 break;
330
331
332 case ACPI_TYPE_METHOD:
333
334 acpi_os_printf (
335 "Method(%X) @ %p:%X\n",
336 obj_desc->method.param_count,
337 obj_desc->method.aml_start, obj_desc->method.aml_length);
338 break;
339
340
341 case ACPI_TYPE_MUTEX:
342
343 acpi_os_printf ("Mutex\n");
344 break;
345
346
347 case ACPI_TYPE_DEVICE:
348
349 acpi_os_printf ("Device\n");
350 break;
351
352
353 case ACPI_TYPE_POWER:
354
355 acpi_os_printf ("Power\n");
356 break;
357
358
359 case ACPI_TYPE_PROCESSOR:
360
361 acpi_os_printf ("Processor\n");
362 break;
363
364
365 case ACPI_TYPE_THERMAL:
366
367 acpi_os_printf ("Thermal\n");
368 break;
369
370
371 default:
372 /* Unknown Type */
373
374 acpi_os_printf ("Unknown Type %X\n", ACPI_GET_OBJECT_TYPE (obj_desc));
375 break;
376 }
377
378 return;
379}
380
381
382/*****************************************************************************
383 *
384 * FUNCTION: acpi_ex_dump_operands
385 *
386 * PARAMETERS: Operands - Operand list
387 * interpreter_mode - Load or Exec
388 * Ident - Identification
389 * num_levels - # of stack entries to dump above line
390 * Note - Output notation
391 * module_name - Caller's module name
392 * line_number - Caller's invocation line number
393 *
394 * DESCRIPTION: Dump the object stack
395 *
396 ****************************************************************************/
397
398void
399acpi_ex_dump_operands (
400 union acpi_operand_object **operands,
401 acpi_interpreter_mode interpreter_mode,
402 char *ident,
403 u32 num_levels,
404 char *note,
405 char *module_name,
406 u32 line_number)
407{
408 acpi_native_uint i;
409
410
411 ACPI_FUNCTION_NAME ("ex_dump_operands");
412
413
414 if (!ident) {
415 ident = "?";
416 }
417
418 if (!note) {
419 note = "?";
420 }
421
422 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
423 "************* Operand Stack Contents (Opcode [%s], %d Operands)\n",
424 ident, num_levels));
425
426 if (num_levels == 0) {
427 num_levels = 1;
428 }
429
430 /* Dump the operand stack starting at the top */
431
432 for (i = 0; num_levels > 0; i--, num_levels--) {
433 acpi_ex_dump_operand (operands[i], 0);
434 }
435
436 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
437 "************* Stack dump from %s(%d), %s\n",
438 module_name, line_number, note));
439 return;
440}
441
442
443#ifdef ACPI_FUTURE_USAGE
444
445/*****************************************************************************
446 *
447 * FUNCTION: acpi_ex_out*
448 *
449 * PARAMETERS: Title - Descriptive text
450 * Value - Value to be displayed
451 *
452 * DESCRIPTION: Object dump output formatting functions. These functions
453 * reduce the number of format strings required and keeps them
454 * all in one place for easy modification.
455 *
456 ****************************************************************************/
457
458void
459acpi_ex_out_string (
460 char *title,
461 char *value)
462{
463 acpi_os_printf ("%20s : %s\n", title, value);
464}
465
466void
467acpi_ex_out_pointer (
468 char *title,
469 void *value)
470{
471 acpi_os_printf ("%20s : %p\n", title, value);
472}
473
474void
475acpi_ex_out_integer (
476 char *title,
477 u32 value)
478{
479 acpi_os_printf ("%20s : %X\n", title, value);
480}
481
482void
483acpi_ex_out_address (
484 char *title,
485 acpi_physical_address value)
486{
487
488#if ACPI_MACHINE_WIDTH == 16
489 acpi_os_printf ("%20s : %p\n", title, value);
490#else
491 acpi_os_printf ("%20s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64 (value));
492#endif
493}
494
495
496/*****************************************************************************
497 *
498 * FUNCTION: acpi_ex_dump_node
499 *
500 * PARAMETERS: *Node - Descriptor to dump
501 * Flags - Force display
502 *
503 * DESCRIPTION: Dumps the members of the given.Node
504 *
505 ****************************************************************************/
506
507void
508acpi_ex_dump_node (
509 struct acpi_namespace_node *node,
510 u32 flags)
511{
512
513 ACPI_FUNCTION_ENTRY ();
514
515
516 if (!flags) {
517 if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
518 return;
519 }
520 }
521
522 acpi_os_printf ("%20s : %4.4s\n", "Name", acpi_ut_get_node_name (node));
523 acpi_ex_out_string ("Type", acpi_ut_get_type_name (node->type));
524 acpi_ex_out_integer ("Flags", node->flags);
525 acpi_ex_out_integer ("Owner Id", node->owner_id);
526 acpi_ex_out_integer ("Reference Count", node->reference_count);
527 acpi_ex_out_pointer ("Attached Object", acpi_ns_get_attached_object (node));
528 acpi_ex_out_pointer ("child_list", node->child);
529 acpi_ex_out_pointer ("next_peer", node->peer);
530 acpi_ex_out_pointer ("Parent", acpi_ns_get_parent_node (node));
531}
532
533
534/*****************************************************************************
535 *
536 * FUNCTION: acpi_ex_dump_object_descriptor
537 *
538 * PARAMETERS: *Object - Descriptor to dump
539 * Flags - Force display
540 *
541 * DESCRIPTION: Dumps the members of the object descriptor given.
542 *
543 ****************************************************************************/
544
545void
546acpi_ex_dump_object_descriptor (
547 union acpi_operand_object *obj_desc,
548 u32 flags)
549{
550 u32 i;
551
552
553 ACPI_FUNCTION_TRACE ("ex_dump_object_descriptor");
554
555
556 if (!flags) {
557 if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
558 return_VOID;
559 }
560 }
561
562 if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) {
563 acpi_ex_dump_node ((struct acpi_namespace_node *) obj_desc, flags);
564 acpi_os_printf ("\nAttached Object (%p):\n",
565 ((struct acpi_namespace_node *) obj_desc)->object);
566 acpi_ex_dump_object_descriptor (
567 ((struct acpi_namespace_node *) obj_desc)->object, flags);
568 return_VOID;
569 }
570
571 if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) {
572 acpi_os_printf (
573 "ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n",
574 obj_desc, acpi_ut_get_descriptor_name (obj_desc));
575 return_VOID;
576 }
577
578 /* Common Fields */
579
580 acpi_ex_out_string ("Type", acpi_ut_get_object_type_name (obj_desc));
581 acpi_ex_out_integer ("Reference Count", obj_desc->common.reference_count);
582 acpi_ex_out_integer ("Flags", obj_desc->common.flags);
583
584 /* Object-specific Fields */
585
586 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
587 case ACPI_TYPE_INTEGER:
588
589 acpi_os_printf ("%20s : %8.8X%8.8X\n", "Value",
590 ACPI_FORMAT_UINT64 (obj_desc->integer.value));
591 break;
592
593
594 case ACPI_TYPE_STRING:
595
596 acpi_ex_out_integer ("Length", obj_desc->string.length);
597
598 acpi_os_printf ("%20s : %p ", "Pointer", obj_desc->string.pointer);
599 acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX);
600 acpi_os_printf ("\n");
601 break;
602
603
604 case ACPI_TYPE_BUFFER:
605
606 acpi_ex_out_integer ("Length", obj_desc->buffer.length);
607 acpi_ex_out_pointer ("Pointer", obj_desc->buffer.pointer);
608 ACPI_DUMP_BUFFER (obj_desc->buffer.pointer, obj_desc->buffer.length);
609 break;
610
611
612 case ACPI_TYPE_PACKAGE:
613
614 acpi_ex_out_integer ("Flags", obj_desc->package.flags);
615 acpi_ex_out_integer ("Count", obj_desc->package.count);
616 acpi_ex_out_pointer ("Elements", obj_desc->package.elements);
617
618 /* Dump the package contents */
619
620 if (obj_desc->package.count > 0) {
621 acpi_os_printf ("\nPackage Contents:\n");
622 for (i = 0; i < obj_desc->package.count; i++) {
623 acpi_os_printf ("[%.3d] %p", i, obj_desc->package.elements[i]);
624 if (obj_desc->package.elements[i]) {
625 acpi_os_printf (" %s",
626 acpi_ut_get_object_type_name (obj_desc->package.elements[i]));
627 }
628 acpi_os_printf ("\n");
629 }
630 }
631 break;
632
633
634 case ACPI_TYPE_DEVICE:
635
636 acpi_ex_out_pointer ("Handler", obj_desc->device.handler);
637 acpi_ex_out_pointer ("system_notify", obj_desc->device.system_notify);
638 acpi_ex_out_pointer ("device_notify", obj_desc->device.device_notify);
639 break;
640
641
642 case ACPI_TYPE_EVENT:
643
644 acpi_ex_out_pointer ("Semaphore", obj_desc->event.semaphore);
645 break;
646
647
648 case ACPI_TYPE_METHOD:
649
650 acpi_ex_out_integer ("param_count", obj_desc->method.param_count);
651 acpi_ex_out_integer ("Concurrency", obj_desc->method.concurrency);
652 acpi_ex_out_pointer ("Semaphore", obj_desc->method.semaphore);
653 acpi_ex_out_integer ("owning_id", obj_desc->method.owning_id);
654 acpi_ex_out_integer ("aml_length", obj_desc->method.aml_length);
655 acpi_ex_out_pointer ("aml_start", obj_desc->method.aml_start);
656 break;
657
658
659 case ACPI_TYPE_MUTEX:
660
661 acpi_ex_out_integer ("sync_level", obj_desc->mutex.sync_level);
662 acpi_ex_out_pointer ("owner_thread", obj_desc->mutex.owner_thread);
663 acpi_ex_out_integer ("acquire_depth", obj_desc->mutex.acquisition_depth);
664 acpi_ex_out_pointer ("Semaphore", obj_desc->mutex.semaphore);
665 break;
666
667
668 case ACPI_TYPE_REGION:
669
670 acpi_ex_out_integer ("space_id", obj_desc->region.space_id);
671 acpi_ex_out_integer ("Flags", obj_desc->region.flags);
672 acpi_ex_out_address ("Address", obj_desc->region.address);
673 acpi_ex_out_integer ("Length", obj_desc->region.length);
674 acpi_ex_out_pointer ("Handler", obj_desc->region.handler);
675 acpi_ex_out_pointer ("Next", obj_desc->region.next);
676 break;
677
678
679 case ACPI_TYPE_POWER:
680
681 acpi_ex_out_integer ("system_level", obj_desc->power_resource.system_level);
682 acpi_ex_out_integer ("resource_order", obj_desc->power_resource.resource_order);
683 acpi_ex_out_pointer ("system_notify", obj_desc->power_resource.system_notify);
684 acpi_ex_out_pointer ("device_notify", obj_desc->power_resource.device_notify);
685 break;
686
687
688 case ACPI_TYPE_PROCESSOR:
689
690 acpi_ex_out_integer ("Processor ID", obj_desc->processor.proc_id);
691 acpi_ex_out_integer ("Length", obj_desc->processor.length);
692 acpi_ex_out_address ("Address", (acpi_physical_address) obj_desc->processor.address);
693 acpi_ex_out_pointer ("system_notify", obj_desc->processor.system_notify);
694 acpi_ex_out_pointer ("device_notify", obj_desc->processor.device_notify);
695 acpi_ex_out_pointer ("Handler", obj_desc->processor.handler);
696 break;
697
698
699 case ACPI_TYPE_THERMAL:
700
701 acpi_ex_out_pointer ("system_notify", obj_desc->thermal_zone.system_notify);
702 acpi_ex_out_pointer ("device_notify", obj_desc->thermal_zone.device_notify);
703 acpi_ex_out_pointer ("Handler", obj_desc->thermal_zone.handler);
704 break;
705
706
707 case ACPI_TYPE_BUFFER_FIELD:
708 case ACPI_TYPE_LOCAL_REGION_FIELD:
709 case ACPI_TYPE_LOCAL_BANK_FIELD:
710 case ACPI_TYPE_LOCAL_INDEX_FIELD:
711
712 acpi_ex_out_integer ("field_flags", obj_desc->common_field.field_flags);
713 acpi_ex_out_integer ("access_byte_width",obj_desc->common_field.access_byte_width);
714 acpi_ex_out_integer ("bit_length", obj_desc->common_field.bit_length);
715 acpi_ex_out_integer ("fld_bit_offset", obj_desc->common_field.start_field_bit_offset);
716 acpi_ex_out_integer ("base_byte_offset", obj_desc->common_field.base_byte_offset);
717 acpi_ex_out_pointer ("parent_node", obj_desc->common_field.node);
718
719 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
720 case ACPI_TYPE_BUFFER_FIELD:
721 acpi_ex_out_pointer ("buffer_obj", obj_desc->buffer_field.buffer_obj);
722 break;
723
724 case ACPI_TYPE_LOCAL_REGION_FIELD:
725 acpi_ex_out_pointer ("region_obj", obj_desc->field.region_obj);
726 break;
727
728 case ACPI_TYPE_LOCAL_BANK_FIELD:
729 acpi_ex_out_integer ("Value", obj_desc->bank_field.value);
730 acpi_ex_out_pointer ("region_obj", obj_desc->bank_field.region_obj);
731 acpi_ex_out_pointer ("bank_obj", obj_desc->bank_field.bank_obj);
732 break;
733
734 case ACPI_TYPE_LOCAL_INDEX_FIELD:
735 acpi_ex_out_integer ("Value", obj_desc->index_field.value);
736 acpi_ex_out_pointer ("Index", obj_desc->index_field.index_obj);
737 acpi_ex_out_pointer ("Data", obj_desc->index_field.data_obj);
738 break;
739
740 default:
741 /* All object types covered above */
742 break;
743 }
744 break;
745
746
747 case ACPI_TYPE_LOCAL_REFERENCE:
748
749 acpi_ex_out_integer ("target_type", obj_desc->reference.target_type);
750 acpi_ex_out_string ("Opcode", (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name);
751 acpi_ex_out_integer ("Offset", obj_desc->reference.offset);
752 acpi_ex_out_pointer ("obj_desc", obj_desc->reference.object);
753 acpi_ex_out_pointer ("Node", obj_desc->reference.node);
754 acpi_ex_out_pointer ("Where", obj_desc->reference.where);
755 break;
756
757
758 case ACPI_TYPE_LOCAL_ADDRESS_HANDLER:
759
760 acpi_ex_out_integer ("space_id", obj_desc->address_space.space_id);
761 acpi_ex_out_pointer ("Next", obj_desc->address_space.next);
762 acpi_ex_out_pointer ("region_list", obj_desc->address_space.region_list);
763 acpi_ex_out_pointer ("Node", obj_desc->address_space.node);
764 acpi_ex_out_pointer ("Context", obj_desc->address_space.context);
765 break;
766
767
768 case ACPI_TYPE_LOCAL_NOTIFY:
769
770 acpi_ex_out_pointer ("Node", obj_desc->notify.node);
771 acpi_ex_out_pointer ("Context", obj_desc->notify.context);
772 break;
773
774
775 case ACPI_TYPE_LOCAL_ALIAS:
776 case ACPI_TYPE_LOCAL_METHOD_ALIAS:
777 case ACPI_TYPE_LOCAL_EXTRA:
778 case ACPI_TYPE_LOCAL_DATA:
779 default:
780
781 acpi_os_printf (
782 "ex_dump_object_descriptor: Display not implemented for object type %s\n",
783 acpi_ut_get_object_type_name (obj_desc));
784 break;
785 }
786
787 return_VOID;
788}
789
790#endif /* ACPI_FUTURE_USAGE */
791
792#endif
793
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
new file mode 100644
index 000000000000..be7f2124fa02
--- /dev/null
+++ b/drivers/acpi/executer/exfield.c
@@ -0,0 +1,367 @@
1/******************************************************************************
2 *
3 * Module Name: exfield - ACPI AML (p-code) execution - field manipulation
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acdispat.h>
47#include <acpi/acinterp.h>
48
49
50#define _COMPONENT ACPI_EXECUTER
51 ACPI_MODULE_NAME ("exfield")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ex_read_data_from_field
57 *
58 * PARAMETERS: walk_state - Current execution state
59 * obj_desc - The named field
60 * ret_buffer_desc - Where the return data object is stored
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Read from a named field. Returns either an Integer or a
65 * Buffer, depending on the size of the field.
66 *
67 ******************************************************************************/
68
69acpi_status
70acpi_ex_read_data_from_field (
71 struct acpi_walk_state *walk_state,
72 union acpi_operand_object *obj_desc,
73 union acpi_operand_object **ret_buffer_desc)
74{
75 acpi_status status;
76 union acpi_operand_object *buffer_desc;
77 acpi_size length;
78 void *buffer;
79 u8 locked;
80
81
82 ACPI_FUNCTION_TRACE_PTR ("ex_read_data_from_field", obj_desc);
83
84
85 /* Parameter validation */
86
87 if (!obj_desc) {
88 return_ACPI_STATUS (AE_AML_NO_OPERAND);
89 }
90
91 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
92 /*
93 * If the buffer_field arguments have not been previously evaluated,
94 * evaluate them now and save the results.
95 */
96 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
97 status = acpi_ds_get_buffer_field_arguments (obj_desc);
98 if (ACPI_FAILURE (status)) {
99 return_ACPI_STATUS (status);
100 }
101 }
102 }
103 else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
104 (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) {
105 /*
106 * This is an SMBus read. We must create a buffer to hold the data
107 * and directly access the region handler.
108 */
109 buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE);
110 if (!buffer_desc) {
111 return_ACPI_STATUS (AE_NO_MEMORY);
112 }
113
114 /* Lock entire transaction if requested */
115
116 locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
117
118 /*
119 * Perform the read.
120 * Note: Smbus protocol value is passed in upper 16-bits of Function
121 */
122 status = acpi_ex_access_region (obj_desc, 0,
123 ACPI_CAST_PTR (acpi_integer, buffer_desc->buffer.pointer),
124 ACPI_READ | (obj_desc->field.attribute << 16));
125 acpi_ex_release_global_lock (locked);
126 goto exit;
127 }
128
129 /*
130 * Allocate a buffer for the contents of the field.
131 *
132 * If the field is larger than the size of an acpi_integer, create
133 * a BUFFER to hold it. Otherwise, use an INTEGER. This allows
134 * the use of arithmetic operators on the returned value if the
135 * field size is equal or smaller than an Integer.
136 *
137 * Note: Field.length is in bits.
138 */
139 length = (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->field.bit_length);
140 if (length > acpi_gbl_integer_byte_width) {
141 /* Field is too large for an Integer, create a Buffer instead */
142
143 buffer_desc = acpi_ut_create_buffer_object (length);
144 if (!buffer_desc) {
145 return_ACPI_STATUS (AE_NO_MEMORY);
146 }
147 buffer = buffer_desc->buffer.pointer;
148 }
149 else {
150 /* Field will fit within an Integer (normal case) */
151
152 buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
153 if (!buffer_desc) {
154 return_ACPI_STATUS (AE_NO_MEMORY);
155 }
156
157 length = acpi_gbl_integer_byte_width;
158 buffer_desc->integer.value = 0;
159 buffer = &buffer_desc->integer.value;
160 }
161
162 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
163 "field_read [TO]: Obj %p, Type %X, Buf %p, byte_len %X\n",
164 obj_desc, ACPI_GET_OBJECT_TYPE (obj_desc), buffer, (u32) length));
165 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
166 "field_read [FROM]: bit_len %X, bit_off %X, byte_off %X\n",
167 obj_desc->common_field.bit_length,
168 obj_desc->common_field.start_field_bit_offset,
169 obj_desc->common_field.base_byte_offset));
170
171 /* Lock entire transaction if requested */
172
173 locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
174
175 /* Read from the field */
176
177 status = acpi_ex_extract_from_field (obj_desc, buffer, (u32) length);
178 acpi_ex_release_global_lock (locked);
179
180
181exit:
182 if (ACPI_FAILURE (status)) {
183 acpi_ut_remove_reference (buffer_desc);
184 }
185 else if (ret_buffer_desc) {
186 *ret_buffer_desc = buffer_desc;
187 }
188
189 return_ACPI_STATUS (status);
190}
191
192
193/*******************************************************************************
194 *
195 * FUNCTION: acpi_ex_write_data_to_field
196 *
197 * PARAMETERS: source_desc - Contains data to write
198 * obj_desc - The named field
199 *
200 * RETURN: Status
201 *
202 * DESCRIPTION: Write to a named field
203 *
204 ******************************************************************************/
205
206acpi_status
207acpi_ex_write_data_to_field (
208 union acpi_operand_object *source_desc,
209 union acpi_operand_object *obj_desc,
210 union acpi_operand_object **result_desc)
211{
212 acpi_status status;
213 u32 length;
214 u32 required_length;
215 void *buffer;
216 void *new_buffer;
217 u8 locked;
218 union acpi_operand_object *buffer_desc;
219
220
221 ACPI_FUNCTION_TRACE_PTR ("ex_write_data_to_field", obj_desc);
222
223
224 /* Parameter validation */
225
226 if (!source_desc || !obj_desc) {
227 return_ACPI_STATUS (AE_AML_NO_OPERAND);
228 }
229
230 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
231 /*
232 * If the buffer_field arguments have not been previously evaluated,
233 * evaluate them now and save the results.
234 */
235 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
236 status = acpi_ds_get_buffer_field_arguments (obj_desc);
237 if (ACPI_FAILURE (status)) {
238 return_ACPI_STATUS (status);
239 }
240 }
241 }
242 else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
243 (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) {
244 /*
245 * This is an SMBus write. We will bypass the entire field mechanism
246 * and handoff the buffer directly to the handler.
247 *
248 * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
249 */
250 if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) {
251 ACPI_REPORT_ERROR (("SMBus write requires Buffer, found type %s\n",
252 acpi_ut_get_object_type_name (source_desc)));
253 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
254 }
255
256 if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) {
257 ACPI_REPORT_ERROR (("SMBus write requires Buffer of length %X, found length %X\n",
258 ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length));
259 return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
260 }
261
262 buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE);
263 if (!buffer_desc) {
264 return_ACPI_STATUS (AE_NO_MEMORY);
265 }
266
267 buffer = buffer_desc->buffer.pointer;
268 ACPI_MEMCPY (buffer, source_desc->buffer.pointer, ACPI_SMBUS_BUFFER_SIZE);
269
270 /* Lock entire transaction if requested */
271
272 locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
273
274 /*
275 * Perform the write (returns status and perhaps data in the same buffer)
276 * Note: SMBus protocol type is passed in upper 16-bits of Function.
277 */
278 status = acpi_ex_access_region (obj_desc, 0,
279 (acpi_integer *) buffer,
280 ACPI_WRITE | (obj_desc->field.attribute << 16));
281 acpi_ex_release_global_lock (locked);
282
283 *result_desc = buffer_desc;
284 return_ACPI_STATUS (status);
285 }
286
287 /*
288 * Get a pointer to the data to be written
289 */
290 switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
291 case ACPI_TYPE_INTEGER:
292 buffer = &source_desc->integer.value;
293 length = sizeof (source_desc->integer.value);
294 break;
295
296 case ACPI_TYPE_BUFFER:
297 buffer = source_desc->buffer.pointer;
298 length = source_desc->buffer.length;
299 break;
300
301 case ACPI_TYPE_STRING:
302 buffer = source_desc->string.pointer;
303 length = source_desc->string.length;
304 break;
305
306 default:
307 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
308 }
309
310 /*
311 * We must have a buffer that is at least as long as the field
312 * we are writing to. This is because individual fields are
313 * indivisible and partial writes are not supported -- as per
314 * the ACPI specification.
315 */
316 new_buffer = NULL;
317 required_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);
318
319 if (length < required_length) {
320 /* We need to create a new buffer */
321
322 new_buffer = ACPI_MEM_CALLOCATE (required_length);
323 if (!new_buffer) {
324 return_ACPI_STATUS (AE_NO_MEMORY);
325 }
326
327 /*
328 * Copy the original data to the new buffer, starting
329 * at Byte zero. All unused (upper) bytes of the
330 * buffer will be 0.
331 */
332 ACPI_MEMCPY ((char *) new_buffer, (char *) buffer, length);
333 buffer = new_buffer;
334 length = required_length;
335 }
336
337 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
338 "field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %X\n",
339 source_desc, acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (source_desc)),
340 ACPI_GET_OBJECT_TYPE (source_desc), buffer, length));
341 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
342 "field_write [TO]: Obj %p (%s:%X), bit_len %X, bit_off %X, byte_off %X\n",
343 obj_desc, acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (obj_desc)),
344 ACPI_GET_OBJECT_TYPE (obj_desc),
345 obj_desc->common_field.bit_length,
346 obj_desc->common_field.start_field_bit_offset,
347 obj_desc->common_field.base_byte_offset));
348
349 /* Lock entire transaction if requested */
350
351 locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
352
353 /* Write to the field */
354
355 status = acpi_ex_insert_into_field (obj_desc, buffer, length);
356 acpi_ex_release_global_lock (locked);
357
358 /* Free temporary buffer if we used one */
359
360 if (new_buffer) {
361 ACPI_MEM_FREE (new_buffer);
362 }
363
364 return_ACPI_STATUS (status);
365}
366
367
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
new file mode 100644
index 000000000000..9d0f9d2e9061
--- /dev/null
+++ b/drivers/acpi/executer/exfldio.c
@@ -0,0 +1,835 @@
1/******************************************************************************
2 *
3 * Module Name: exfldio - Aml Field I/O
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acinterp.h>
47#include <acpi/amlcode.h>
48#include <acpi/acevents.h>
49#include <acpi/acdispat.h>
50
51
52#define _COMPONENT ACPI_EXECUTER
53 ACPI_MODULE_NAME ("exfldio")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_ex_setup_region
59 *
60 * PARAMETERS: *obj_desc - Field to be read or written
61 * field_datum_byte_offset - Byte offset of this datum within the
62 * parent field
63 *
64 * RETURN: Status
65 *
66 * DESCRIPTION: Common processing for acpi_ex_extract_from_field and
67 * acpi_ex_insert_into_field. Initialize the Region if necessary and
68 * validate the request.
69 *
70 ******************************************************************************/
71
72acpi_status
73acpi_ex_setup_region (
74 union acpi_operand_object *obj_desc,
75 u32 field_datum_byte_offset)
76{
77 acpi_status status = AE_OK;
78 union acpi_operand_object *rgn_desc;
79
80
81 ACPI_FUNCTION_TRACE_U32 ("ex_setup_region", field_datum_byte_offset);
82
83
84 rgn_desc = obj_desc->common_field.region_obj;
85
86 /* We must have a valid region */
87
88 if (ACPI_GET_OBJECT_TYPE (rgn_desc) != ACPI_TYPE_REGION) {
89 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n",
90 ACPI_GET_OBJECT_TYPE (rgn_desc),
91 acpi_ut_get_object_type_name (rgn_desc)));
92
93 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
94 }
95
96 /*
97 * If the Region Address and Length have not been previously evaluated,
98 * evaluate them now and save the results.
99 */
100 if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
101 status = acpi_ds_get_region_arguments (rgn_desc);
102 if (ACPI_FAILURE (status)) {
103 return_ACPI_STATUS (status);
104 }
105 }
106
107 if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
108 /* SMBus has a non-linear address space */
109
110 return_ACPI_STATUS (AE_OK);
111 }
112
113#ifdef ACPI_UNDER_DEVELOPMENT
114 /*
115 * If the Field access is any_acc, we can now compute the optimal
116 * access (because we know know the length of the parent region)
117 */
118 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
119 if (ACPI_FAILURE (status)) {
120 return_ACPI_STATUS (status);
121 }
122 }
123#endif
124
125 /*
126 * Validate the request. The entire request from the byte offset for a
127 * length of one field datum (access width) must fit within the region.
128 * (Region length is specified in bytes)
129 */
130 if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset
131 + field_datum_byte_offset
132 + obj_desc->common_field.access_byte_width)) {
133 if (acpi_gbl_enable_interpreter_slack) {
134 /*
135 * Slack mode only: We will go ahead and allow access to this
136 * field if it is within the region length rounded up to the next
137 * access width boundary.
138 */
139 if (ACPI_ROUND_UP (rgn_desc->region.length,
140 obj_desc->common_field.access_byte_width) >=
141 (obj_desc->common_field.base_byte_offset +
142 (acpi_native_uint) obj_desc->common_field.access_byte_width +
143 field_datum_byte_offset)) {
144 return_ACPI_STATUS (AE_OK);
145 }
146 }
147
148 if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) {
149 /*
150 * This is the case where the access_type (acc_word, etc.) is wider
151 * than the region itself. For example, a region of length one
152 * byte, and a field with Dword access specified.
153 */
154 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
155 "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
156 acpi_ut_get_node_name (obj_desc->common_field.node),
157 obj_desc->common_field.access_byte_width,
158 acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
159 }
160
161 /*
162 * Offset rounded up to next multiple of field width
163 * exceeds region length, indicate an error
164 */
165 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
166 "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
167 acpi_ut_get_node_name (obj_desc->common_field.node),
168 obj_desc->common_field.base_byte_offset,
169 field_datum_byte_offset, obj_desc->common_field.access_byte_width,
170 acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
171
172 return_ACPI_STATUS (AE_AML_REGION_LIMIT);
173 }
174
175 return_ACPI_STATUS (AE_OK);
176}
177
178
179/*******************************************************************************
180 *
181 * FUNCTION: acpi_ex_access_region
182 *
183 * PARAMETERS: *obj_desc - Field to be read
184 * field_datum_byte_offset - Byte offset of this datum within the
185 * parent field
186 * *Value - Where to store value (must at least
187 * the size of acpi_integer)
188 * Function - Read or Write flag plus other region-
189 * dependent flags
190 *
191 * RETURN: Status
192 *
193 * DESCRIPTION: Read or Write a single field datum to an Operation Region.
194 *
195 ******************************************************************************/
196
197acpi_status
198acpi_ex_access_region (
199 union acpi_operand_object *obj_desc,
200 u32 field_datum_byte_offset,
201 acpi_integer *value,
202 u32 function)
203{
204 acpi_status status;
205 union acpi_operand_object *rgn_desc;
206 acpi_physical_address address;
207
208
209 ACPI_FUNCTION_TRACE ("ex_access_region");
210
211
212 /*
213 * Ensure that the region operands are fully evaluated and verify
214 * the validity of the request
215 */
216 status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset);
217 if (ACPI_FAILURE (status)) {
218 return_ACPI_STATUS (status);
219 }
220
221 /*
222 * The physical address of this field datum is:
223 *
224 * 1) The base of the region, plus
225 * 2) The base offset of the field, plus
226 * 3) The current offset into the field
227 */
228 rgn_desc = obj_desc->common_field.region_obj;
229 address = rgn_desc->region.address
230 + obj_desc->common_field.base_byte_offset
231 + field_datum_byte_offset;
232
233 if ((function & ACPI_IO_MASK) == ACPI_READ) {
234 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
235 }
236 else {
237 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
238 }
239
240 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
241 " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
242 acpi_ut_get_region_name (rgn_desc->region.space_id),
243 rgn_desc->region.space_id,
244 obj_desc->common_field.access_byte_width,
245 obj_desc->common_field.base_byte_offset,
246 field_datum_byte_offset,
247 ACPI_FORMAT_UINT64 (address)));
248
249 /* Invoke the appropriate address_space/op_region handler */
250
251 status = acpi_ev_address_space_dispatch (rgn_desc, function,
252 address, ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value);
253
254 if (ACPI_FAILURE (status)) {
255 if (status == AE_NOT_IMPLEMENTED) {
256 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
257 "Region %s(%X) not implemented\n",
258 acpi_ut_get_region_name (rgn_desc->region.space_id),
259 rgn_desc->region.space_id));
260 }
261 else if (status == AE_NOT_EXIST) {
262 ACPI_REPORT_ERROR ((
263 "Region %s(%X) has no handler\n",
264 acpi_ut_get_region_name (rgn_desc->region.space_id),
265 rgn_desc->region.space_id));
266 }
267 }
268
269 return_ACPI_STATUS (status);
270}
271
272
273/*******************************************************************************
274 *
275 * FUNCTION: acpi_ex_register_overflow
276 *
277 * PARAMETERS: *obj_desc - Register(Field) to be written
278 * Value - Value to be stored
279 *
280 * RETURN: TRUE if value overflows the field, FALSE otherwise
281 *
282 * DESCRIPTION: Check if a value is out of range of the field being written.
283 * Used to check if the values written to Index and Bank registers
284 * are out of range. Normally, the value is simply truncated
285 * to fit the field, but this case is most likely a serious
286 * coding error in the ASL.
287 *
288 ******************************************************************************/
289
290u8
291acpi_ex_register_overflow (
292 union acpi_operand_object *obj_desc,
293 acpi_integer value)
294{
295
296 if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
297 /*
298 * The field is large enough to hold the maximum integer, so we can
299 * never overflow it.
300 */
301 return (FALSE);
302 }
303
304 if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) {
305 /*
306 * The Value is larger than the maximum value that can fit into
307 * the register.
308 */
309 return (TRUE);
310 }
311
312 /* The Value will fit into the field with no truncation */
313
314 return (FALSE);
315}
316
317
318/*******************************************************************************
319 *
320 * FUNCTION: acpi_ex_field_datum_io
321 *
322 * PARAMETERS: *obj_desc - Field to be read
323 * field_datum_byte_offset - Byte offset of this datum within the
324 * parent field
325 * *Value - Where to store value (must be 64 bits)
326 * read_write - Read or Write flag
327 *
328 * RETURN: Status
329 *
330 * DESCRIPTION: Read or Write a single datum of a field. The field_type is
331 * demultiplexed here to handle the different types of fields
332 * (buffer_field, region_field, index_field, bank_field)
333 *
334 ******************************************************************************/
335
336acpi_status
337acpi_ex_field_datum_io (
338 union acpi_operand_object *obj_desc,
339 u32 field_datum_byte_offset,
340 acpi_integer *value,
341 u32 read_write)
342{
343 acpi_status status;
344 acpi_integer local_value;
345
346
347 ACPI_FUNCTION_TRACE_U32 ("ex_field_datum_io", field_datum_byte_offset);
348
349
350 if (read_write == ACPI_READ) {
351 if (!value) {
352 local_value = 0;
353 value = &local_value; /* To support reads without saving return value */
354 }
355
356 /* Clear the entire return buffer first, [Very Important!] */
357
358 *value = 0;
359 }
360
361 /*
362 * The four types of fields are:
363 *
364 * buffer_field - Read/write from/to a Buffer
365 * region_field - Read/write from/to a Operation Region.
366 * bank_field - Write to a Bank Register, then read/write from/to an op_region
367 * index_field - Write to an Index Register, then read/write from/to a Data Register
368 */
369 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
370 case ACPI_TYPE_BUFFER_FIELD:
371 /*
372 * If the buffer_field arguments have not been previously evaluated,
373 * evaluate them now and save the results.
374 */
375 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
376 status = acpi_ds_get_buffer_field_arguments (obj_desc);
377 if (ACPI_FAILURE (status)) {
378 return_ACPI_STATUS (status);
379 }
380 }
381
382 if (read_write == ACPI_READ) {
383 /*
384 * Copy the data from the source buffer.
385 * Length is the field width in bytes.
386 */
387 ACPI_MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer
388 + obj_desc->buffer_field.base_byte_offset
389 + field_datum_byte_offset,
390 obj_desc->common_field.access_byte_width);
391 }
392 else {
393 /*
394 * Copy the data to the target buffer.
395 * Length is the field width in bytes.
396 */
397 ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer
398 + obj_desc->buffer_field.base_byte_offset
399 + field_datum_byte_offset,
400 value, obj_desc->common_field.access_byte_width);
401 }
402
403 status = AE_OK;
404 break;
405
406
407 case ACPI_TYPE_LOCAL_BANK_FIELD:
408
409 /* Ensure that the bank_value is not beyond the capacity of the register */
410
411 if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj,
412 (acpi_integer) obj_desc->bank_field.value)) {
413 return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
414 }
415
416 /*
417 * For bank_fields, we must write the bank_value to the bank_register
418 * (itself a region_field) before we can access the data.
419 */
420 status = acpi_ex_insert_into_field (obj_desc->bank_field.bank_obj,
421 &obj_desc->bank_field.value,
422 sizeof (obj_desc->bank_field.value));
423 if (ACPI_FAILURE (status)) {
424 return_ACPI_STATUS (status);
425 }
426
427 /*
428 * Now that the Bank has been selected, fall through to the
429 * region_field case and write the datum to the Operation Region
430 */
431
432 /*lint -fallthrough */
433
434
435 case ACPI_TYPE_LOCAL_REGION_FIELD:
436 /*
437 * For simple region_fields, we just directly access the owning
438 * Operation Region.
439 */
440 status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value,
441 read_write);
442 break;
443
444
445 case ACPI_TYPE_LOCAL_INDEX_FIELD:
446
447
448 /* Ensure that the index_value is not beyond the capacity of the register */
449
450 if (acpi_ex_register_overflow (obj_desc->index_field.index_obj,
451 (acpi_integer) obj_desc->index_field.value)) {
452 return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
453 }
454
455 /* Write the index value to the index_register (itself a region_field) */
456
457 field_datum_byte_offset += obj_desc->index_field.value;
458
459 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
460 "Write to Index Register: Value %8.8X\n",
461 field_datum_byte_offset));
462
463 status = acpi_ex_insert_into_field (obj_desc->index_field.index_obj,
464 &field_datum_byte_offset,
465 sizeof (field_datum_byte_offset));
466 if (ACPI_FAILURE (status)) {
467 return_ACPI_STATUS (status);
468 }
469
470 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
471 "I/O to Data Register: value_ptr %p\n",
472 value));
473
474 if (read_write == ACPI_READ) {
475 /* Read the datum from the data_register */
476
477 status = acpi_ex_extract_from_field (obj_desc->index_field.data_obj,
478 value, sizeof (acpi_integer));
479 }
480 else {
481 /* Write the datum to the data_register */
482
483 status = acpi_ex_insert_into_field (obj_desc->index_field.data_obj,
484 value, sizeof (acpi_integer));
485 }
486 break;
487
488
489 default:
490
491 ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n",
492 ACPI_GET_OBJECT_TYPE (obj_desc)));
493 status = AE_AML_INTERNAL;
494 break;
495 }
496
497 if (ACPI_SUCCESS (status)) {
498 if (read_write == ACPI_READ) {
499 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n",
500 ACPI_FORMAT_UINT64 (*value),
501 obj_desc->common_field.access_byte_width));
502 }
503 else {
504 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n",
505 ACPI_FORMAT_UINT64 (*value),
506 obj_desc->common_field.access_byte_width));
507 }
508 }
509
510 return_ACPI_STATUS (status);
511}
512
513
514/*******************************************************************************
515 *
516 * FUNCTION: acpi_ex_write_with_update_rule
517 *
518 * PARAMETERS: *obj_desc - Field to be set
519 * Value - Value to store
520 *
521 * RETURN: Status
522 *
523 * DESCRIPTION: Apply the field update rule to a field write
524 *
525 ******************************************************************************/
526
527acpi_status
528acpi_ex_write_with_update_rule (
529 union acpi_operand_object *obj_desc,
530 acpi_integer mask,
531 acpi_integer field_value,
532 u32 field_datum_byte_offset)
533{
534 acpi_status status = AE_OK;
535 acpi_integer merged_value;
536 acpi_integer current_value;
537
538
539 ACPI_FUNCTION_TRACE_U32 ("ex_write_with_update_rule", mask);
540
541
542 /* Start with the new bits */
543
544 merged_value = field_value;
545
546 /* If the mask is all ones, we don't need to worry about the update rule */
547
548 if (mask != ACPI_INTEGER_MAX) {
549 /* Decode the update rule */
550
551 switch (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK) {
552 case AML_FIELD_UPDATE_PRESERVE:
553 /*
554 * Check if update rule needs to be applied (not if mask is all
555 * ones) The left shift drops the bits we want to ignore.
556 */
557 if ((~mask << (ACPI_MUL_8 (sizeof (mask)) -
558 ACPI_MUL_8 (obj_desc->common_field.access_byte_width))) != 0) {
559 /*
560 * Read the current contents of the byte/word/dword containing
561 * the field, and merge with the new field value.
562 */
563 status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
564 &current_value, ACPI_READ);
565 if (ACPI_FAILURE (status)) {
566 return_ACPI_STATUS (status);
567 }
568
569 merged_value |= (current_value & ~mask);
570 }
571 break;
572
573 case AML_FIELD_UPDATE_WRITE_AS_ONES:
574
575 /* Set positions outside the field to all ones */
576
577 merged_value |= ~mask;
578 break;
579
580 case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
581
582 /* Set positions outside the field to all zeros */
583
584 merged_value &= mask;
585 break;
586
587 default:
588
589 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
590 "write_with_update_rule: Unknown update_rule setting: %X\n",
591 (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK)));
592 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
593 }
594 }
595
596 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
597 "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n",
598 ACPI_FORMAT_UINT64 (mask),
599 field_datum_byte_offset,
600 obj_desc->common_field.access_byte_width,
601 ACPI_FORMAT_UINT64 (field_value),
602 ACPI_FORMAT_UINT64 (merged_value)));
603
604 /* Write the merged value */
605
606 status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
607 &merged_value, ACPI_WRITE);
608
609 return_ACPI_STATUS (status);
610}
611
612
613/*******************************************************************************
614 *
615 * FUNCTION: acpi_ex_extract_from_field
616 *
617 * PARAMETERS: obj_desc - Field to be read
618 * Buffer - Where to store the field data
619 * buffer_length - Length of Buffer
620 *
621 * RETURN: Status
622 *
623 * DESCRIPTION: Retrieve the current value of the given field
624 *
625 ******************************************************************************/
626
627acpi_status
628acpi_ex_extract_from_field (
629 union acpi_operand_object *obj_desc,
630 void *buffer,
631 u32 buffer_length)
632{
633 acpi_status status;
634 acpi_integer raw_datum;
635 acpi_integer merged_datum;
636 u32 field_offset = 0;
637 u32 buffer_offset = 0;
638 u32 buffer_tail_bits;
639 u32 datum_count;
640 u32 field_datum_count;
641 u32 i;
642
643
644 ACPI_FUNCTION_TRACE ("ex_extract_from_field");
645
646
647 /* Validate target buffer and clear it */
648
649 if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
650 obj_desc->common_field.bit_length)) {
651 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
652 "Field size %X (bits) is too large for buffer (%X)\n",
653 obj_desc->common_field.bit_length, buffer_length));
654
655 return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
656 }
657 ACPI_MEMSET (buffer, 0, buffer_length);
658
659 /* Compute the number of datums (access width data items) */
660
661 datum_count = ACPI_ROUND_UP_TO (
662 obj_desc->common_field.bit_length,
663 obj_desc->common_field.access_bit_width);
664 field_datum_count = ACPI_ROUND_UP_TO (
665 obj_desc->common_field.bit_length +
666 obj_desc->common_field.start_field_bit_offset,
667 obj_desc->common_field.access_bit_width);
668
669 /* Priming read from the field */
670
671 status = acpi_ex_field_datum_io (obj_desc, field_offset, &raw_datum, ACPI_READ);
672 if (ACPI_FAILURE (status)) {
673 return_ACPI_STATUS (status);
674 }
675 merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
676
677 /* Read the rest of the field */
678
679 for (i = 1; i < field_datum_count; i++) {
680 /* Get next input datum from the field */
681
682 field_offset += obj_desc->common_field.access_byte_width;
683 status = acpi_ex_field_datum_io (obj_desc, field_offset,
684 &raw_datum, ACPI_READ);
685 if (ACPI_FAILURE (status)) {
686 return_ACPI_STATUS (status);
687 }
688
689 /* Merge with previous datum if necessary */
690
691 merged_datum |= raw_datum <<
692 (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset);
693
694 if (i == datum_count) {
695 break;
696 }
697
698 /* Write merged datum to target buffer */
699
700 ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
701 ACPI_MIN(obj_desc->common_field.access_byte_width,
702 buffer_length - buffer_offset));
703
704 buffer_offset += obj_desc->common_field.access_byte_width;
705 merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
706 }
707
708 /* Mask off any extra bits in the last datum */
709
710 buffer_tail_bits = obj_desc->common_field.bit_length % obj_desc->common_field.access_bit_width;
711 if (buffer_tail_bits) {
712 merged_datum &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
713 }
714
715 /* Write the last datum to the buffer */
716
717 ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
718 ACPI_MIN(obj_desc->common_field.access_byte_width,
719 buffer_length - buffer_offset));
720
721 return_ACPI_STATUS (AE_OK);
722}
723
724
725/*******************************************************************************
726 *
727 * FUNCTION: acpi_ex_insert_into_field
728 *
729 * PARAMETERS: obj_desc - Field to be written
730 * Buffer - Data to be written
731 * buffer_length - Length of Buffer
732 *
733 * RETURN: Status
734 *
735 * DESCRIPTION: Store the Buffer contents into the given field
736 *
737 ******************************************************************************/
738
739acpi_status
740acpi_ex_insert_into_field (
741 union acpi_operand_object *obj_desc,
742 void *buffer,
743 u32 buffer_length)
744{
745 acpi_status status;
746 acpi_integer mask;
747 acpi_integer merged_datum;
748 acpi_integer raw_datum = 0;
749 u32 field_offset = 0;
750 u32 buffer_offset = 0;
751 u32 buffer_tail_bits;
752 u32 datum_count;
753 u32 field_datum_count;
754 u32 i;
755
756
757 ACPI_FUNCTION_TRACE ("ex_insert_into_field");
758
759
760 /* Validate input buffer */
761
762 if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
763 obj_desc->common_field.bit_length)) {
764 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
765 "Field size %X (bits) is too large for buffer (%X)\n",
766 obj_desc->common_field.bit_length, buffer_length));
767
768 return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
769 }
770
771 /* Compute the number of datums (access width data items) */
772
773 mask = ACPI_MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset);
774 datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length,
775 obj_desc->common_field.access_bit_width);
776 field_datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length +
777 obj_desc->common_field.start_field_bit_offset,
778 obj_desc->common_field.access_bit_width);
779
780 /* Get initial Datum from the input buffer */
781
782 ACPI_MEMCPY (&raw_datum, buffer,
783 ACPI_MIN(obj_desc->common_field.access_byte_width,
784 buffer_length - buffer_offset));
785
786 merged_datum = raw_datum << obj_desc->common_field.start_field_bit_offset;
787
788 /* Write the entire field */
789
790 for (i = 1; i < field_datum_count; i++) {
791 /* Write merged datum to the target field */
792
793 merged_datum &= mask;
794 status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset);
795 if (ACPI_FAILURE (status)) {
796 return_ACPI_STATUS (status);
797 }
798
799 /* Start new output datum by merging with previous input datum */
800
801 field_offset += obj_desc->common_field.access_byte_width;
802 merged_datum = raw_datum >>
803 (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset);
804 mask = ACPI_INTEGER_MAX;
805
806 if (i == datum_count) {
807 break;
808 }
809
810 /* Get the next input datum from the buffer */
811
812 buffer_offset += obj_desc->common_field.access_byte_width;
813 ACPI_MEMCPY (&raw_datum, ((char *) buffer) + buffer_offset,
814 ACPI_MIN(obj_desc->common_field.access_byte_width,
815 buffer_length - buffer_offset));
816 merged_datum |= raw_datum << obj_desc->common_field.start_field_bit_offset;
817 }
818
819 /* Mask off any extra bits in the last datum */
820
821 buffer_tail_bits = (obj_desc->common_field.bit_length +
822 obj_desc->common_field.start_field_bit_offset) % obj_desc->common_field.access_bit_width;
823 if (buffer_tail_bits) {
824 mask &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
825 }
826
827 /* Write the last datum to the field */
828
829 merged_datum &= mask;
830 status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset);
831
832 return_ACPI_STATUS (status);
833}
834
835
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
new file mode 100644
index 000000000000..b542dcd58c07
--- /dev/null
+++ b/drivers/acpi/executer/exmisc.c
@@ -0,0 +1,738 @@
1
2/******************************************************************************
3 *
4 * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acinterp.h>
48#include <acpi/amlcode.h>
49
50
51#define _COMPONENT ACPI_EXECUTER
52 ACPI_MODULE_NAME ("exmisc")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION: acpi_ex_get_object_reference
58 *
59 * PARAMETERS: obj_desc - Create a reference to this object
60 * return_desc - Where to store the reference
61 * walk_state - Current state
62 *
63 * RETURN: Status
64 *
65 * DESCRIPTION: Obtain and return a "reference" to the target object
66 * Common code for the ref_of_op and the cond_ref_of_op.
67 *
68 ******************************************************************************/
69
70acpi_status
71acpi_ex_get_object_reference (
72 union acpi_operand_object *obj_desc,
73 union acpi_operand_object **return_desc,
74 struct acpi_walk_state *walk_state)
75{
76 union acpi_operand_object *reference_obj;
77 union acpi_operand_object *referenced_obj;
78
79
80 ACPI_FUNCTION_TRACE_PTR ("ex_get_object_reference", obj_desc);
81
82
83 *return_desc = NULL;
84
85 switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
86 case ACPI_DESC_TYPE_OPERAND:
87
88 if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) {
89 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
90 }
91
92 /*
93 * Must be a reference to a Local or Arg
94 */
95 switch (obj_desc->reference.opcode) {
96 case AML_LOCAL_OP:
97 case AML_ARG_OP:
98 case AML_DEBUG_OP:
99
100 /* The referenced object is the pseudo-node for the local/arg */
101
102 referenced_obj = obj_desc->reference.object;
103 break;
104
105 default:
106
107 ACPI_REPORT_ERROR (("Unknown Reference opcode in get_reference %X\n",
108 obj_desc->reference.opcode));
109 return_ACPI_STATUS (AE_AML_INTERNAL);
110 }
111 break;
112
113
114 case ACPI_DESC_TYPE_NAMED:
115
116 /*
117 * A named reference that has already been resolved to a Node
118 */
119 referenced_obj = obj_desc;
120 break;
121
122
123 default:
124
125 ACPI_REPORT_ERROR (("Invalid descriptor type in get_reference: %X\n",
126 ACPI_GET_DESCRIPTOR_TYPE (obj_desc)));
127 return_ACPI_STATUS (AE_TYPE);
128 }
129
130
131 /* Create a new reference object */
132
133 reference_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
134 if (!reference_obj) {
135 return_ACPI_STATUS (AE_NO_MEMORY);
136 }
137
138 reference_obj->reference.opcode = AML_REF_OF_OP;
139 reference_obj->reference.object = referenced_obj;
140 *return_desc = reference_obj;
141
142 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p Type [%s], returning Reference %p\n",
143 obj_desc, acpi_ut_get_object_type_name (obj_desc), *return_desc));
144
145 return_ACPI_STATUS (AE_OK);
146}
147
148
149/*******************************************************************************
150 *
151 * FUNCTION: acpi_ex_concat_template
152 *
153 * PARAMETERS: Operand0 - First source object
154 * Operand1 - Second source object
155 * actual_return_desc - Where to place the return object
156 * walk_state - Current walk state
157 *
158 * RETURN: Status
159 *
160 * DESCRIPTION: Concatenate two resource templates
161 *
162 ******************************************************************************/
163
164acpi_status
165acpi_ex_concat_template (
166 union acpi_operand_object *operand0,
167 union acpi_operand_object *operand1,
168 union acpi_operand_object **actual_return_desc,
169 struct acpi_walk_state *walk_state)
170{
171 union acpi_operand_object *return_desc;
172 u8 *new_buf;
173 u8 *end_tag1;
174 u8 *end_tag2;
175 acpi_size length1;
176 acpi_size length2;
177
178
179 ACPI_FUNCTION_TRACE ("ex_concat_template");
180
181
182 /* Find the end_tags in each resource template */
183
184 end_tag1 = acpi_ut_get_resource_end_tag (operand0);
185 end_tag2 = acpi_ut_get_resource_end_tag (operand1);
186 if (!end_tag1 || !end_tag2) {
187 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
188 }
189
190 /* Compute the length of each part */
191
192 length1 = ACPI_PTR_DIFF (end_tag1, operand0->buffer.pointer);
193 length2 = ACPI_PTR_DIFF (end_tag2, operand1->buffer.pointer) +
194 2; /* Size of END_TAG */
195
196 /* Create a new buffer object for the result */
197
198 return_desc = acpi_ut_create_buffer_object (length1 + length2);
199 if (!return_desc) {
200 return_ACPI_STATUS (AE_NO_MEMORY);
201 }
202
203 /* Copy the templates to the new descriptor */
204
205 new_buf = return_desc->buffer.pointer;
206 ACPI_MEMCPY (new_buf, operand0->buffer.pointer, length1);
207 ACPI_MEMCPY (new_buf + length1, operand1->buffer.pointer, length2);
208
209 /* Compute the new checksum */
210
211 new_buf[return_desc->buffer.length - 1] =
212 acpi_ut_generate_checksum (return_desc->buffer.pointer,
213 (return_desc->buffer.length - 1));
214
215 /* Return the completed template descriptor */
216
217 *actual_return_desc = return_desc;
218 return_ACPI_STATUS (AE_OK);
219}
220
221
222/*******************************************************************************
223 *
224 * FUNCTION: acpi_ex_do_concatenate
225 *
226 * PARAMETERS: Operand0 - First source object
227 * Operand1 - Second source object
228 * actual_return_desc - Where to place the return object
229 * walk_state - Current walk state
230 *
231 * RETURN: Status
232 *
233 * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
234 *
235 ******************************************************************************/
236
237acpi_status
238acpi_ex_do_concatenate (
239 union acpi_operand_object *operand0,
240 union acpi_operand_object *operand1,
241 union acpi_operand_object **actual_return_desc,
242 struct acpi_walk_state *walk_state)
243{
244 union acpi_operand_object *local_operand1 = operand1;
245 union acpi_operand_object *return_desc;
246 char *new_buf;
247 acpi_status status;
248 acpi_size new_length;
249
250
251 ACPI_FUNCTION_TRACE ("ex_do_concatenate");
252
253
254 /*
255 * Convert the second operand if necessary. The first operand
256 * determines the type of the second operand, (See the Data Types
257 * section of the ACPI specification.) Both object types are
258 * guaranteed to be either Integer/String/Buffer by the operand
259 * resolution mechanism.
260 */
261 switch (ACPI_GET_OBJECT_TYPE (operand0)) {
262 case ACPI_TYPE_INTEGER:
263 status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16);
264 break;
265
266 case ACPI_TYPE_STRING:
267 status = acpi_ex_convert_to_string (operand1, &local_operand1,
268 ACPI_IMPLICIT_CONVERT_HEX);
269 break;
270
271 case ACPI_TYPE_BUFFER:
272 status = acpi_ex_convert_to_buffer (operand1, &local_operand1);
273 break;
274
275 default:
276 ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
277 ACPI_GET_OBJECT_TYPE (operand0)));
278 status = AE_AML_INTERNAL;
279 }
280
281 if (ACPI_FAILURE (status)) {
282 goto cleanup;
283 }
284
285 /*
286 * Both operands are now known to be the same object type
287 * (Both are Integer, String, or Buffer), and we can now perform the
288 * concatenation.
289 */
290
291 /*
292 * There are three cases to handle:
293 *
294 * 1) Two Integers concatenated to produce a new Buffer
295 * 2) Two Strings concatenated to produce a new String
296 * 3) Two Buffers concatenated to produce a new Buffer
297 */
298 switch (ACPI_GET_OBJECT_TYPE (operand0)) {
299 case ACPI_TYPE_INTEGER:
300
301 /* Result of two Integers is a Buffer */
302 /* Need enough buffer space for two integers */
303
304 return_desc = acpi_ut_create_buffer_object (
305 ACPI_MUL_2 (acpi_gbl_integer_byte_width));
306 if (!return_desc) {
307 status = AE_NO_MEMORY;
308 goto cleanup;
309 }
310
311 new_buf = (char *) return_desc->buffer.pointer;
312
313 /* Copy the first integer, LSB first */
314
315 ACPI_MEMCPY (new_buf,
316 &operand0->integer.value,
317 acpi_gbl_integer_byte_width);
318
319 /* Copy the second integer (LSB first) after the first */
320
321 ACPI_MEMCPY (new_buf + acpi_gbl_integer_byte_width,
322 &local_operand1->integer.value,
323 acpi_gbl_integer_byte_width);
324 break;
325
326 case ACPI_TYPE_STRING:
327
328 /* Result of two Strings is a String */
329
330 new_length = (acpi_size) operand0->string.length +
331 (acpi_size) local_operand1->string.length;
332 if (new_length > ACPI_MAX_STRING_CONVERSION) {
333 status = AE_AML_STRING_LIMIT;
334 goto cleanup;
335 }
336
337 return_desc = acpi_ut_create_string_object (new_length);
338 if (!return_desc) {
339 status = AE_NO_MEMORY;
340 goto cleanup;
341 }
342
343 new_buf = return_desc->string.pointer;
344
345 /* Concatenate the strings */
346
347 ACPI_STRCPY (new_buf,
348 operand0->string.pointer);
349 ACPI_STRCPY (new_buf + operand0->string.length,
350 local_operand1->string.pointer);
351 break;
352
353 case ACPI_TYPE_BUFFER:
354
355 /* Result of two Buffers is a Buffer */
356
357 return_desc = acpi_ut_create_buffer_object (
358 (acpi_size) operand0->buffer.length +
359 (acpi_size) local_operand1->buffer.length);
360 if (!return_desc) {
361 status = AE_NO_MEMORY;
362 goto cleanup;
363 }
364
365 new_buf = (char *) return_desc->buffer.pointer;
366
367 /* Concatenate the buffers */
368
369 ACPI_MEMCPY (new_buf,
370 operand0->buffer.pointer,
371 operand0->buffer.length);
372 ACPI_MEMCPY (new_buf + operand0->buffer.length,
373 local_operand1->buffer.pointer,
374 local_operand1->buffer.length);
375 break;
376
377 default:
378
379 /* Invalid object type, should not happen here */
380
381 ACPI_REPORT_ERROR (("Concatenate - Invalid object type: %X\n",
382 ACPI_GET_OBJECT_TYPE (operand0)));
383 status =AE_AML_INTERNAL;
384 goto cleanup;
385 }
386
387 *actual_return_desc = return_desc;
388
389cleanup:
390 if (local_operand1 != operand1) {
391 acpi_ut_remove_reference (local_operand1);
392 }
393 return_ACPI_STATUS (status);
394}
395
396
397/*******************************************************************************
398 *
399 * FUNCTION: acpi_ex_do_math_op
400 *
401 * PARAMETERS: Opcode - AML opcode
402 * Integer0 - Integer operand #0
403 * Integer1 - Integer operand #1
404 *
405 * RETURN: Integer result of the operation
406 *
407 * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
408 * math functions here is to prevent a lot of pointer dereferencing
409 * to obtain the operands.
410 *
411 ******************************************************************************/
412
413acpi_integer
414acpi_ex_do_math_op (
415 u16 opcode,
416 acpi_integer integer0,
417 acpi_integer integer1)
418{
419
420 ACPI_FUNCTION_ENTRY ();
421
422
423 switch (opcode) {
424 case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */
425
426 return (integer0 + integer1);
427
428
429 case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */
430
431 return (integer0 & integer1);
432
433
434 case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */
435
436 return (~(integer0 & integer1));
437
438
439 case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */
440
441 return (integer0 | integer1);
442
443
444 case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */
445
446 return (~(integer0 | integer1));
447
448
449 case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */
450
451 return (integer0 ^ integer1);
452
453
454 case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */
455
456 return (integer0 * integer1);
457
458
459 case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */
460
461 return (integer0 << integer1);
462
463
464 case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */
465
466 return (integer0 >> integer1);
467
468
469 case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
470
471 return (integer0 - integer1);
472
473 default:
474
475 return (0);
476 }
477}
478
479
480/*******************************************************************************
481 *
482 * FUNCTION: acpi_ex_do_logical_numeric_op
483 *
484 * PARAMETERS: Opcode - AML opcode
485 * Integer0 - Integer operand #0
486 * Integer1 - Integer operand #1
487 * logical_result - TRUE/FALSE result of the operation
488 *
489 * RETURN: Status
490 *
491 * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
492 * operators (LAnd and LOr), both operands must be integers.
493 *
494 * Note: cleanest machine code seems to be produced by the code
495 * below, rather than using statements of the form:
496 * Result = (Integer0 && Integer1);
497 *
498 ******************************************************************************/
499
500acpi_status
501acpi_ex_do_logical_numeric_op (
502 u16 opcode,
503 acpi_integer integer0,
504 acpi_integer integer1,
505 u8 *logical_result)
506{
507 acpi_status status = AE_OK;
508 u8 local_result = FALSE;
509
510
511 ACPI_FUNCTION_TRACE ("ex_do_logical_numeric_op");
512
513
514 switch (opcode) {
515 case AML_LAND_OP: /* LAnd (Integer0, Integer1) */
516
517 if (integer0 && integer1) {
518 local_result = TRUE;
519 }
520 break;
521
522 case AML_LOR_OP: /* LOr (Integer0, Integer1) */
523
524 if (integer0 || integer1) {
525 local_result = TRUE;
526 }
527 break;
528
529 default:
530 status = AE_AML_INTERNAL;
531 break;
532 }
533
534 /* Return the logical result and status */
535
536 *logical_result = local_result;
537 return_ACPI_STATUS (status);
538}
539
540
541/*******************************************************************************
542 *
543 * FUNCTION: acpi_ex_do_logical_op
544 *
545 * PARAMETERS: Opcode - AML opcode
546 * Operand0 - operand #0
547 * Operand1 - operand #1
548 * logical_result - TRUE/FALSE result of the operation
549 *
550 * RETURN: Status
551 *
552 * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
553 * functions here is to prevent a lot of pointer dereferencing
554 * to obtain the operands and to simplify the generation of the
555 * logical value. For the Numeric operators (LAnd and LOr), both
556 * operands must be integers. For the other logical operators,
557 * operands can be any combination of Integer/String/Buffer. The
558 * first operand determines the type to which the second operand
559 * will be converted.
560 *
561 * Note: cleanest machine code seems to be produced by the code
562 * below, rather than using statements of the form:
563 * Result = (Operand0 == Operand1);
564 *
565 ******************************************************************************/
566
567acpi_status
568acpi_ex_do_logical_op (
569 u16 opcode,
570 union acpi_operand_object *operand0,
571 union acpi_operand_object *operand1,
572 u8 *logical_result)
573{
574 union acpi_operand_object *local_operand1 = operand1;
575 acpi_integer integer0;
576 acpi_integer integer1;
577 u32 length0;
578 u32 length1;
579 acpi_status status = AE_OK;
580 u8 local_result = FALSE;
581 int compare;
582
583
584 ACPI_FUNCTION_TRACE ("ex_do_logical_op");
585
586
587 /*
588 * Convert the second operand if necessary. The first operand
589 * determines the type of the second operand, (See the Data Types
590 * section of the ACPI 3.0+ specification.) Both object types are
591 * guaranteed to be either Integer/String/Buffer by the operand
592 * resolution mechanism.
593 */
594 switch (ACPI_GET_OBJECT_TYPE (operand0)) {
595 case ACPI_TYPE_INTEGER:
596 status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16);
597 break;
598
599 case ACPI_TYPE_STRING:
600 status = acpi_ex_convert_to_string (operand1, &local_operand1,
601 ACPI_IMPLICIT_CONVERT_HEX);
602 break;
603
604 case ACPI_TYPE_BUFFER:
605 status = acpi_ex_convert_to_buffer (operand1, &local_operand1);
606 break;
607
608 default:
609 status = AE_AML_INTERNAL;
610 break;
611 }
612
613 if (ACPI_FAILURE (status)) {
614 goto cleanup;
615 }
616
617 /*
618 * Two cases: 1) Both Integers, 2) Both Strings or Buffers
619 */
620 if (ACPI_GET_OBJECT_TYPE (operand0) == ACPI_TYPE_INTEGER) {
621 /*
622 * 1) Both operands are of type integer
623 * Note: local_operand1 may have changed above
624 */
625 integer0 = operand0->integer.value;
626 integer1 = local_operand1->integer.value;
627
628 switch (opcode) {
629 case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
630
631 if (integer0 == integer1) {
632 local_result = TRUE;
633 }
634 break;
635
636 case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
637
638 if (integer0 > integer1) {
639 local_result = TRUE;
640 }
641 break;
642
643 case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
644
645 if (integer0 < integer1) {
646 local_result = TRUE;
647 }
648 break;
649
650 default:
651 status = AE_AML_INTERNAL;
652 break;
653 }
654 }
655 else {
656 /*
657 * 2) Both operands are Strings or both are Buffers
658 * Note: Code below takes advantage of common Buffer/String
659 * object fields. local_operand1 may have changed above. Use
660 * memcmp to handle nulls in buffers.
661 */
662 length0 = operand0->buffer.length;
663 length1 = local_operand1->buffer.length;
664
665 /* Lexicographic compare: compare the data bytes */
666
667 compare = ACPI_MEMCMP ((const char * ) operand0->buffer.pointer,
668 (const char * ) local_operand1->buffer.pointer,
669 (length0 > length1) ? length1 : length0);
670
671 switch (opcode) {
672 case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
673
674 /* Length and all bytes must be equal */
675
676 if ((length0 == length1) &&
677 (compare == 0)) {
678 /* Length and all bytes match ==> TRUE */
679
680 local_result = TRUE;
681 }
682 break;
683
684 case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
685
686 if (compare > 0) {
687 local_result = TRUE;
688 goto cleanup; /* TRUE */
689 }
690 if (compare < 0) {
691 goto cleanup; /* FALSE */
692 }
693
694 /* Bytes match (to shortest length), compare lengths */
695
696 if (length0 > length1) {
697 local_result = TRUE;
698 }
699 break;
700
701 case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
702
703 if (compare > 0) {
704 goto cleanup; /* FALSE */
705 }
706 if (compare < 0) {
707 local_result = TRUE;
708 goto cleanup; /* TRUE */
709 }
710
711 /* Bytes match (to shortest length), compare lengths */
712
713 if (length0 < length1) {
714 local_result = TRUE;
715 }
716 break;
717
718 default:
719 status = AE_AML_INTERNAL;
720 break;
721 }
722 }
723
724cleanup:
725
726 /* New object was created if implicit conversion performed - delete */
727
728 if (local_operand1 != operand1) {
729 acpi_ut_remove_reference (local_operand1);
730 }
731
732 /* Return the logical result and status */
733
734 *logical_result = local_result;
735 return_ACPI_STATUS (status);
736}
737
738
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
new file mode 100644
index 000000000000..68c4bb1970a5
--- /dev/null
+++ b/drivers/acpi/executer/exmutex.c
@@ -0,0 +1,363 @@
1
2/******************************************************************************
3 *
4 * Module Name: exmutex - ASL Mutex Acquire/Release functions
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acinterp.h>
48
49#define _COMPONENT ACPI_EXECUTER
50 ACPI_MODULE_NAME ("exmutex")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ex_unlink_mutex
56 *
57 * PARAMETERS: obj_desc - The mutex to be unlinked
58 *
59 * RETURN: Status
60 *
61 * DESCRIPTION: Remove a mutex from the "acquired_mutex" list
62 *
63 ******************************************************************************/
64
65void
66acpi_ex_unlink_mutex (
67 union acpi_operand_object *obj_desc)
68{
69 struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
70
71
72 if (!thread) {
73 return;
74 }
75
76 /* Doubly linked list */
77
78 if (obj_desc->mutex.next) {
79 (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev;
80 }
81
82 if (obj_desc->mutex.prev) {
83 (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next;
84 }
85 else {
86 thread->acquired_mutex_list = obj_desc->mutex.next;
87 }
88}
89
90
91/*******************************************************************************
92 *
93 * FUNCTION: acpi_ex_link_mutex
94 *
95 * PARAMETERS: obj_desc - The mutex to be linked
96 * list_head - head of the "acquired_mutex" list
97 *
98 * RETURN: Status
99 *
100 * DESCRIPTION: Add a mutex to the "acquired_mutex" list for this walk
101 *
102 ******************************************************************************/
103
104void
105acpi_ex_link_mutex (
106 union acpi_operand_object *obj_desc,
107 struct acpi_thread_state *thread)
108{
109 union acpi_operand_object *list_head;
110
111
112 list_head = thread->acquired_mutex_list;
113
114 /* This object will be the first object in the list */
115
116 obj_desc->mutex.prev = NULL;
117 obj_desc->mutex.next = list_head;
118
119 /* Update old first object to point back to this object */
120
121 if (list_head) {
122 list_head->mutex.prev = obj_desc;
123 }
124
125 /* Update list head */
126
127 thread->acquired_mutex_list = obj_desc;
128}
129
130
131/*******************************************************************************
132 *
133 * FUNCTION: acpi_ex_acquire_mutex
134 *
135 * PARAMETERS: time_desc - The 'time to delay' object descriptor
136 * obj_desc - The object descriptor for this op
137 *
138 * RETURN: Status
139 *
140 * DESCRIPTION: Acquire an AML mutex
141 *
142 ******************************************************************************/
143
144acpi_status
145acpi_ex_acquire_mutex (
146 union acpi_operand_object *time_desc,
147 union acpi_operand_object *obj_desc,
148 struct acpi_walk_state *walk_state)
149{
150 acpi_status status;
151
152
153 ACPI_FUNCTION_TRACE_PTR ("ex_acquire_mutex", obj_desc);
154
155
156 if (!obj_desc) {
157 return_ACPI_STATUS (AE_BAD_PARAMETER);
158 }
159
160 /* Sanity check -- we must have a valid thread ID */
161
162 if (!walk_state->thread) {
163 ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], null thread info\n",
164 acpi_ut_get_node_name (obj_desc->mutex.node)));
165 return_ACPI_STATUS (AE_AML_INTERNAL);
166 }
167
168 /*
169 * Current Sync must be less than or equal to the sync level of the
170 * mutex. This mechanism provides some deadlock prevention
171 */
172 if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
173 ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], incorrect sync_level\n",
174 acpi_ut_get_node_name (obj_desc->mutex.node)));
175 return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
176 }
177
178 /* Support for multiple acquires by the owning thread */
179
180 if (obj_desc->mutex.owner_thread) {
181 /* Special case for Global Lock, allow all threads */
182
183 if ((obj_desc->mutex.owner_thread->thread_id == walk_state->thread->thread_id) ||
184 (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore)) {
185 /*
186 * The mutex is already owned by this thread,
187 * just increment the acquisition depth
188 */
189 obj_desc->mutex.acquisition_depth++;
190 return_ACPI_STATUS (AE_OK);
191 }
192 }
193
194 /* Acquire the mutex, wait if necessary */
195
196 status = acpi_ex_system_acquire_mutex (time_desc, obj_desc);
197 if (ACPI_FAILURE (status)) {
198 /* Includes failure from a timeout on time_desc */
199
200 return_ACPI_STATUS (status);
201 }
202
203 /* Have the mutex: update mutex and walk info and save the sync_level */
204
205 obj_desc->mutex.owner_thread = walk_state->thread;
206 obj_desc->mutex.acquisition_depth = 1;
207 obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level;
208
209 walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
210
211 /* Link the mutex to the current thread for force-unlock at method exit */
212
213 acpi_ex_link_mutex (obj_desc, walk_state->thread);
214
215 return_ACPI_STATUS (AE_OK);
216}
217
218
219/*******************************************************************************
220 *
221 * FUNCTION: acpi_ex_release_mutex
222 *
223 * PARAMETERS: obj_desc - The object descriptor for this op
224 *
225 * RETURN: Status
226 *
227 * DESCRIPTION: Release a previously acquired Mutex.
228 *
229 ******************************************************************************/
230
231acpi_status
232acpi_ex_release_mutex (
233 union acpi_operand_object *obj_desc,
234 struct acpi_walk_state *walk_state)
235{
236 acpi_status status;
237
238
239 ACPI_FUNCTION_TRACE ("ex_release_mutex");
240
241
242 if (!obj_desc) {
243 return_ACPI_STATUS (AE_BAD_PARAMETER);
244 }
245
246 /* The mutex must have been previously acquired in order to release it */
247
248 if (!obj_desc->mutex.owner_thread) {
249 ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], not acquired\n",
250 acpi_ut_get_node_name (obj_desc->mutex.node)));
251 return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED);
252 }
253
254 /* Sanity check -- we must have a valid thread ID */
255
256 if (!walk_state->thread) {
257 ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], null thread info\n",
258 acpi_ut_get_node_name (obj_desc->mutex.node)));
259 return_ACPI_STATUS (AE_AML_INTERNAL);
260 }
261
262 /*
263 * The Mutex is owned, but this thread must be the owner.
264 * Special case for Global Lock, any thread can release
265 */
266 if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) &&
267 (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) {
268 ACPI_REPORT_ERROR ((
269 "Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n",
270 walk_state->thread->thread_id,
271 acpi_ut_get_node_name (obj_desc->mutex.node),
272 obj_desc->mutex.owner_thread->thread_id));
273 return_ACPI_STATUS (AE_AML_NOT_OWNER);
274 }
275
276 /*
277 * The sync level of the mutex must be less than or
278 * equal to the current sync level
279 */
280 if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
281 ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], incorrect sync_level\n",
282 acpi_ut_get_node_name (obj_desc->mutex.node)));
283 return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
284 }
285
286 /* Match multiple Acquires with multiple Releases */
287
288 obj_desc->mutex.acquisition_depth--;
289 if (obj_desc->mutex.acquisition_depth != 0) {
290 /* Just decrement the depth and return */
291
292 return_ACPI_STATUS (AE_OK);
293 }
294
295 /* Unlink the mutex from the owner's list */
296
297 acpi_ex_unlink_mutex (obj_desc);
298
299 /* Release the mutex */
300
301 status = acpi_ex_system_release_mutex (obj_desc);
302
303 /* Update the mutex and walk state, restore sync_level before acquire */
304
305 obj_desc->mutex.owner_thread = NULL;
306 walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level;
307
308 return_ACPI_STATUS (status);
309}
310
311
312/*******************************************************************************
313 *
314 * FUNCTION: acpi_ex_release_all_mutexes
315 *
316 * PARAMETERS: mutex_list - Head of the mutex list
317 *
318 * RETURN: Status
319 *
320 * DESCRIPTION: Release all mutexes in the list
321 *
322 ******************************************************************************/
323
324void
325acpi_ex_release_all_mutexes (
326 struct acpi_thread_state *thread)
327{
328 union acpi_operand_object *next = thread->acquired_mutex_list;
329 union acpi_operand_object *this;
330 acpi_status status;
331
332
333 ACPI_FUNCTION_ENTRY ();
334
335
336 /* Traverse the list of owned mutexes, releasing each one */
337
338 while (next) {
339 this = next;
340 next = this->mutex.next;
341
342 this->mutex.acquisition_depth = 1;
343 this->mutex.prev = NULL;
344 this->mutex.next = NULL;
345
346 /* Release the mutex */
347
348 status = acpi_ex_system_release_mutex (this);
349 if (ACPI_FAILURE (status)) {
350 continue;
351 }
352
353 /* Mark mutex unowned */
354
355 this->mutex.owner_thread = NULL;
356
357 /* Update Thread sync_level (Last mutex is the important one) */
358
359 thread->current_sync_level = this->mutex.original_sync_level;
360 }
361}
362
363
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c
new file mode 100644
index 000000000000..7911c533c265
--- /dev/null
+++ b/drivers/acpi/executer/exnames.c
@@ -0,0 +1,427 @@
1
2/******************************************************************************
3 *
4 * Module Name: exnames - interpreter/scanner name load/execute
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acinterp.h>
48#include <acpi/amlcode.h>
49
50#define _COMPONENT ACPI_EXECUTER
51 ACPI_MODULE_NAME ("exnames")
52
53
54/* AML Package Length encodings */
55
56#define ACPI_AML_PACKAGE_TYPE1 0x40
57#define ACPI_AML_PACKAGE_TYPE2 0x4000
58#define ACPI_AML_PACKAGE_TYPE3 0x400000
59#define ACPI_AML_PACKAGE_TYPE4 0x40000000
60
61
62/*******************************************************************************
63 *
64 * FUNCTION: acpi_ex_allocate_name_string
65 *
66 * PARAMETERS: prefix_count - Count of parent levels. Special cases:
67 * (-1) = root, 0 = none
68 * num_name_segs - count of 4-character name segments
69 *
70 * RETURN: A pointer to the allocated string segment. This segment must
71 * be deleted by the caller.
72 *
73 * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
74 * string is long enough, and set up prefix if any.
75 *
76 ******************************************************************************/
77
78char *
79acpi_ex_allocate_name_string (
80 u32 prefix_count,
81 u32 num_name_segs)
82{
83 char *temp_ptr;
84 char *name_string;
85 u32 size_needed;
86
87 ACPI_FUNCTION_TRACE ("ex_allocate_name_string");
88
89
90 /*
91 * Allow room for all \ and ^ prefixes, all segments, and a multi_name_prefix.
92 * Also, one byte for the null terminator.
93 * This may actually be somewhat longer than needed.
94 */
95 if (prefix_count == ACPI_UINT32_MAX) {
96 /* Special case for root */
97
98 size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
99 }
100 else {
101 size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
102 }
103
104 /*
105 * Allocate a buffer for the name.
106 * This buffer must be deleted by the caller!
107 */
108 name_string = ACPI_MEM_ALLOCATE (size_needed);
109 if (!name_string) {
110 ACPI_REPORT_ERROR (("ex_allocate_name_string: Could not allocate size %d\n", size_needed));
111 return_PTR (NULL);
112 }
113
114 temp_ptr = name_string;
115
116 /* Set up Root or Parent prefixes if needed */
117
118 if (prefix_count == ACPI_UINT32_MAX) {
119 *temp_ptr++ = AML_ROOT_PREFIX;
120 }
121 else {
122 while (prefix_count--) {
123 *temp_ptr++ = AML_PARENT_PREFIX;
124 }
125 }
126
127
128 /* Set up Dual or Multi prefixes if needed */
129
130 if (num_name_segs > 2) {
131 /* Set up multi prefixes */
132
133 *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP;
134 *temp_ptr++ = (char) num_name_segs;
135 }
136 else if (2 == num_name_segs) {
137 /* Set up dual prefixes */
138
139 *temp_ptr++ = AML_DUAL_NAME_PREFIX;
140 }
141
142 /*
143 * Terminate string following prefixes. acpi_ex_name_segment() will
144 * append the segment(s)
145 */
146 *temp_ptr = 0;
147
148 return_PTR (name_string);
149}
150
151/*******************************************************************************
152 *
153 * FUNCTION: acpi_ex_name_segment
154 *
155 * PARAMETERS: interpreter_mode - Current running mode (load1/Load2/Exec)
156 *
157 * RETURN: Status
158 *
159 * DESCRIPTION: Execute a name segment (4 bytes)
160 *
161 ******************************************************************************/
162
163acpi_status
164acpi_ex_name_segment (
165 u8 **in_aml_address,
166 char *name_string)
167{
168 char *aml_address = (void *) *in_aml_address;
169 acpi_status status = AE_OK;
170 u32 index;
171 char char_buf[5];
172
173
174 ACPI_FUNCTION_TRACE ("ex_name_segment");
175
176
177 /*
178 * If first character is a digit, then we know that we aren't looking at a
179 * valid name segment
180 */
181 char_buf[0] = *aml_address;
182
183 if ('0' <= char_buf[0] && char_buf[0] <= '9') {
184 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "leading digit: %c\n", char_buf[0]));
185 return_ACPI_STATUS (AE_CTRL_PENDING);
186 }
187
188 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n"));
189
190 for (index = 0;
191 (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_character (*aml_address));
192 index++) {
193 char_buf[index] = *aml_address++;
194 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[index]));
195 }
196
197
198 /* Valid name segment */
199
200 if (index == 4) {
201 /* Found 4 valid characters */
202
203 char_buf[4] = '\0';
204
205 if (name_string) {
206 ACPI_STRCAT (name_string, char_buf);
207 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
208 "Appended to - %s \n", name_string));
209 }
210 else {
211 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
212 "No Name string - %s \n", char_buf));
213 }
214 }
215 else if (index == 0) {
216 /*
217 * First character was not a valid name character,
218 * so we are looking at something other than a name.
219 */
220 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
221 "Leading character is not alpha: %02Xh (not a name)\n",
222 char_buf[0]));
223 status = AE_CTRL_PENDING;
224 }
225 else {
226 /* Segment started with one or more valid characters, but fewer than 4 */
227
228 status = AE_AML_BAD_NAME;
229 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad character %02x in name, at %p\n",
230 *aml_address, aml_address));
231 }
232
233 *in_aml_address = (u8 *) aml_address;
234 return_ACPI_STATUS (status);
235}
236
237
238/*******************************************************************************
239 *
240 * FUNCTION: acpi_ex_get_name_string
241 *
242 * PARAMETERS: data_type - Data type to be associated with this name
243 *
244 * RETURN: Status
245 *
246 * DESCRIPTION: Get a name, including any prefixes.
247 *
248 ******************************************************************************/
249
250acpi_status
251acpi_ex_get_name_string (
252 acpi_object_type data_type,
253 u8 *in_aml_address,
254 char **out_name_string,
255 u32 *out_name_length)
256{
257 acpi_status status = AE_OK;
258 u8 *aml_address = in_aml_address;
259 char *name_string = NULL;
260 u32 num_segments;
261 u32 prefix_count = 0;
262 u8 has_prefix = FALSE;
263
264
265 ACPI_FUNCTION_TRACE_PTR ("ex_get_name_string", aml_address);
266
267
268 if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
269 ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
270 ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
271 /* Disallow prefixes for types associated with field_unit names */
272
273 name_string = acpi_ex_allocate_name_string (0, 1);
274 if (!name_string) {
275 status = AE_NO_MEMORY;
276 }
277 else {
278 status = acpi_ex_name_segment (&aml_address, name_string);
279 }
280 }
281 else {
282 /*
283 * data_type is not a field name.
284 * Examine first character of name for root or parent prefix operators
285 */
286 switch (*aml_address) {
287 case AML_ROOT_PREFIX:
288
289 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "root_prefix(\\) at %p\n", aml_address));
290
291 /*
292 * Remember that we have a root_prefix --
293 * see comment in acpi_ex_allocate_name_string()
294 */
295 aml_address++;
296 prefix_count = ACPI_UINT32_MAX;
297 has_prefix = TRUE;
298 break;
299
300
301 case AML_PARENT_PREFIX:
302
303 /* Increment past possibly multiple parent prefixes */
304
305 do {
306 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "parent_prefix (^) at %p\n", aml_address));
307
308 aml_address++;
309 prefix_count++;
310
311 } while (*aml_address == AML_PARENT_PREFIX);
312
313 has_prefix = TRUE;
314 break;
315
316
317 default:
318
319 /* Not a prefix character */
320
321 break;
322 }
323
324
325 /* Examine first character of name for name segment prefix operator */
326
327 switch (*aml_address) {
328 case AML_DUAL_NAME_PREFIX:
329
330 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "dual_name_prefix at %p\n", aml_address));
331
332 aml_address++;
333 name_string = acpi_ex_allocate_name_string (prefix_count, 2);
334 if (!name_string) {
335 status = AE_NO_MEMORY;
336 break;
337 }
338
339 /* Indicate that we processed a prefix */
340
341 has_prefix = TRUE;
342
343 status = acpi_ex_name_segment (&aml_address, name_string);
344 if (ACPI_SUCCESS (status)) {
345 status = acpi_ex_name_segment (&aml_address, name_string);
346 }
347 break;
348
349
350 case AML_MULTI_NAME_PREFIX_OP:
351
352 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "multi_name_prefix at %p\n", aml_address));
353
354 /* Fetch count of segments remaining in name path */
355
356 aml_address++;
357 num_segments = *aml_address;
358
359 name_string = acpi_ex_allocate_name_string (prefix_count, num_segments);
360 if (!name_string) {
361 status = AE_NO_MEMORY;
362 break;
363 }
364
365 /* Indicate that we processed a prefix */
366
367 aml_address++;
368 has_prefix = TRUE;
369
370 while (num_segments &&
371 (status = acpi_ex_name_segment (&aml_address, name_string)) == AE_OK) {
372 num_segments--;
373 }
374
375 break;
376
377
378 case 0:
379
380 /* null_name valid as of 8-12-98 ASL/AML Grammar Update */
381
382 if (prefix_count == ACPI_UINT32_MAX) {
383 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "name_seg is \"\\\" followed by NULL\n"));
384 }
385
386 /* Consume the NULL byte */
387
388 aml_address++;
389 name_string = acpi_ex_allocate_name_string (prefix_count, 0);
390 if (!name_string) {
391 status = AE_NO_MEMORY;
392 break;
393 }
394
395 break;
396
397
398 default:
399
400 /* Name segment string */
401
402 name_string = acpi_ex_allocate_name_string (prefix_count, 1);
403 if (!name_string) {
404 status = AE_NO_MEMORY;
405 break;
406 }
407
408 status = acpi_ex_name_segment (&aml_address, name_string);
409 break;
410 }
411 }
412
413 if (AE_CTRL_PENDING == status && has_prefix) {
414 /* Ran out of segments after processing a prefix */
415
416 ACPI_REPORT_ERROR (
417 ("ex_do_name: Malformed Name at %p\n", name_string));
418 status = AE_AML_BAD_NAME;
419 }
420
421 *out_name_string = name_string;
422 *out_name_length = (u32) (aml_address - in_aml_address);
423
424 return_ACPI_STATUS (status);
425}
426
427
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
new file mode 100644
index 000000000000..8482aefaf38b
--- /dev/null
+++ b/drivers/acpi/executer/exoparg1.c
@@ -0,0 +1,1013 @@
1
2/******************************************************************************
3 *
4 * Module Name: exoparg1 - AML execution - opcodes with 1 argument
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acparser.h>
48#include <acpi/acdispat.h>
49#include <acpi/acinterp.h>
50#include <acpi/amlcode.h>
51#include <acpi/acnamesp.h>
52
53
54#define _COMPONENT ACPI_EXECUTER
55 ACPI_MODULE_NAME ("exoparg1")
56
57
58/*!
59 * Naming convention for AML interpreter execution routines.
60 *
61 * The routines that begin execution of AML opcodes are named with a common
62 * convention based upon the number of arguments, the number of target operands,
63 * and whether or not a value is returned:
64 *
65 * AcpiExOpcode_xA_yT_zR
66 *
67 * Where:
68 *
69 * xA - ARGUMENTS: The number of arguments (input operands) that are
70 * required for this opcode type (0 through 6 args).
71 * yT - TARGETS: The number of targets (output operands) that are required
72 * for this opcode type (0, 1, or 2 targets).
73 * zR - RETURN VALUE: Indicates whether this opcode type returns a value
74 * as the function return (0 or 1).
75 *
76 * The AcpiExOpcode* functions are called via the Dispatcher component with
77 * fully resolved operands.
78!*/
79
80/*******************************************************************************
81 *
82 * FUNCTION: acpi_ex_opcode_0A_0T_1R
83 *
84 * PARAMETERS: walk_state - Current state (contains AML opcode)
85 *
86 * RETURN: Status
87 *
88 * DESCRIPTION: Execute operator with no operands, one return value
89 *
90 ******************************************************************************/
91
92acpi_status
93acpi_ex_opcode_0A_0T_1R (
94 struct acpi_walk_state *walk_state)
95{
96 acpi_status status = AE_OK;
97 union acpi_operand_object *return_desc = NULL;
98
99
100 ACPI_FUNCTION_TRACE_STR ("ex_opcode_0A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
101
102
103 /* Examine the AML opcode */
104
105 switch (walk_state->opcode) {
106 case AML_TIMER_OP: /* Timer () */
107
108 /* Create a return object of type Integer */
109
110 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
111 if (!return_desc) {
112 status = AE_NO_MEMORY;
113 goto cleanup;
114 }
115
116 return_desc->integer.value = acpi_os_get_timer ();
117 break;
118
119 default: /* Unknown opcode */
120
121 ACPI_REPORT_ERROR (("acpi_ex_opcode_0A_0T_1R: Unknown opcode %X\n",
122 walk_state->opcode));
123 status = AE_AML_BAD_OPCODE;
124 break;
125 }
126
127cleanup:
128
129 if (!walk_state->result_obj) {
130 walk_state->result_obj = return_desc;
131 }
132
133 /* Delete return object on error */
134
135 if (ACPI_FAILURE (status)) {
136 acpi_ut_remove_reference (return_desc);
137 }
138
139 return_ACPI_STATUS (status);
140}
141
142
143/*******************************************************************************
144 *
145 * FUNCTION: acpi_ex_opcode_1A_0T_0R
146 *
147 * PARAMETERS: walk_state - Current state (contains AML opcode)
148 *
149 * RETURN: Status
150 *
151 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
152 * object stack
153 *
154 ******************************************************************************/
155
156acpi_status
157acpi_ex_opcode_1A_0T_0R (
158 struct acpi_walk_state *walk_state)
159{
160 union acpi_operand_object **operand = &walk_state->operands[0];
161 acpi_status status = AE_OK;
162
163
164 ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode));
165
166
167 /* Examine the AML opcode */
168
169 switch (walk_state->opcode) {
170 case AML_RELEASE_OP: /* Release (mutex_object) */
171
172 status = acpi_ex_release_mutex (operand[0], walk_state);
173 break;
174
175
176 case AML_RESET_OP: /* Reset (event_object) */
177
178 status = acpi_ex_system_reset_event (operand[0]);
179 break;
180
181
182 case AML_SIGNAL_OP: /* Signal (event_object) */
183
184 status = acpi_ex_system_signal_event (operand[0]);
185 break;
186
187
188 case AML_SLEEP_OP: /* Sleep (msec_time) */
189
190 status = acpi_ex_system_do_suspend (operand[0]->integer.value);
191 break;
192
193
194 case AML_STALL_OP: /* Stall (usec_time) */
195
196 status = acpi_ex_system_do_stall ((u32) operand[0]->integer.value);
197 break;
198
199
200 case AML_UNLOAD_OP: /* Unload (Handle) */
201
202 status = acpi_ex_unload_table (operand[0]);
203 break;
204
205
206 default: /* Unknown opcode */
207
208 ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n",
209 walk_state->opcode));
210 status = AE_AML_BAD_OPCODE;
211 break;
212 }
213
214 return_ACPI_STATUS (status);
215}
216
217
218/*******************************************************************************
219 *
220 * FUNCTION: acpi_ex_opcode_1A_1T_0R
221 *
222 * PARAMETERS: walk_state - Current state (contains AML opcode)
223 *
224 * RETURN: Status
225 *
226 * DESCRIPTION: Execute opcode with one argument, one target, and no
227 * return value.
228 *
229 ******************************************************************************/
230
231acpi_status
232acpi_ex_opcode_1A_1T_0R (
233 struct acpi_walk_state *walk_state)
234{
235 acpi_status status = AE_OK;
236 union acpi_operand_object **operand = &walk_state->operands[0];
237
238
239 ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_1T_0R", acpi_ps_get_opcode_name (walk_state->opcode));
240
241
242 /* Examine the AML opcode */
243
244 switch (walk_state->opcode) {
245 case AML_LOAD_OP:
246
247 status = acpi_ex_load_op (operand[0], operand[1], walk_state);
248 break;
249
250 default: /* Unknown opcode */
251
252 ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n",
253 walk_state->opcode));
254 status = AE_AML_BAD_OPCODE;
255 goto cleanup;
256 }
257
258
259cleanup:
260
261 return_ACPI_STATUS (status);
262}
263
264
265/*******************************************************************************
266 *
267 * FUNCTION: acpi_ex_opcode_1A_1T_1R
268 *
269 * PARAMETERS: walk_state - Current state (contains AML opcode)
270 *
271 * RETURN: Status
272 *
273 * DESCRIPTION: Execute opcode with one argument, one target, and a
274 * return value.
275 *
276 ******************************************************************************/
277
278acpi_status
279acpi_ex_opcode_1A_1T_1R (
280 struct acpi_walk_state *walk_state)
281{
282 acpi_status status = AE_OK;
283 union acpi_operand_object **operand = &walk_state->operands[0];
284 union acpi_operand_object *return_desc = NULL;
285 union acpi_operand_object *return_desc2 = NULL;
286 u32 temp32;
287 u32 i;
288 acpi_integer power_of_ten;
289 acpi_integer digit;
290
291
292 ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
293
294
295 /* Examine the AML opcode */
296
297 switch (walk_state->opcode) {
298 case AML_BIT_NOT_OP:
299 case AML_FIND_SET_LEFT_BIT_OP:
300 case AML_FIND_SET_RIGHT_BIT_OP:
301 case AML_FROM_BCD_OP:
302 case AML_TO_BCD_OP:
303 case AML_COND_REF_OF_OP:
304
305 /* Create a return object of type Integer for these opcodes */
306
307 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
308 if (!return_desc) {
309 status = AE_NO_MEMORY;
310 goto cleanup;
311 }
312
313 switch (walk_state->opcode) {
314 case AML_BIT_NOT_OP: /* Not (Operand, Result) */
315
316 return_desc->integer.value = ~operand[0]->integer.value;
317 break;
318
319
320 case AML_FIND_SET_LEFT_BIT_OP: /* find_set_left_bit (Operand, Result) */
321
322 return_desc->integer.value = operand[0]->integer.value;
323
324 /*
325 * Acpi specification describes Integer type as a little
326 * endian unsigned value, so this boundary condition is valid.
327 */
328 for (temp32 = 0; return_desc->integer.value &&
329 temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
330 return_desc->integer.value >>= 1;
331 }
332
333 return_desc->integer.value = temp32;
334 break;
335
336
337 case AML_FIND_SET_RIGHT_BIT_OP: /* find_set_right_bit (Operand, Result) */
338
339 return_desc->integer.value = operand[0]->integer.value;
340
341 /*
342 * The Acpi specification describes Integer type as a little
343 * endian unsigned value, so this boundary condition is valid.
344 */
345 for (temp32 = 0; return_desc->integer.value &&
346 temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
347 return_desc->integer.value <<= 1;
348 }
349
350 /* Since the bit position is one-based, subtract from 33 (65) */
351
352 return_desc->integer.value = temp32 == 0 ? 0 :
353 (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
354 break;
355
356
357 case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */
358
359 /*
360 * The 64-bit ACPI integer can hold 16 4-bit BCD characters
361 * (if table is 32-bit, integer can hold 8 BCD characters)
362 * Convert each 4-bit BCD value
363 */
364 power_of_ten = 1;
365 return_desc->integer.value = 0;
366 digit = operand[0]->integer.value;
367
368 /* Convert each BCD digit (each is one nybble wide) */
369
370 for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) {
371 /* Get the least significant 4-bit BCD digit */
372
373 temp32 = ((u32) digit) & 0xF;
374
375 /* Check the range of the digit */
376
377 if (temp32 > 9) {
378 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
379 "BCD digit too large (not decimal): 0x%X\n",
380 temp32));
381
382 status = AE_AML_NUMERIC_OVERFLOW;
383 goto cleanup;
384 }
385
386 /* Sum the digit into the result with the current power of 10 */
387
388 return_desc->integer.value += (((acpi_integer) temp32) *
389 power_of_ten);
390
391 /* Shift to next BCD digit */
392
393 digit >>= 4;
394
395 /* Next power of 10 */
396
397 power_of_ten *= 10;
398 }
399 break;
400
401
402 case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */
403
404 return_desc->integer.value = 0;
405 digit = operand[0]->integer.value;
406
407 /* Each BCD digit is one nybble wide */
408
409 for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) {
410 (void) acpi_ut_short_divide (digit, 10, &digit, &temp32);
411
412 /* Insert the BCD digit that resides in the remainder from above */
413
414 return_desc->integer.value |= (((acpi_integer) temp32) <<
415 ACPI_MUL_4 (i));
416 }
417
418 /* Overflow if there is any data left in Digit */
419
420 if (digit > 0) {
421 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
422 "Integer too large to convert to BCD: %8.8X%8.8X\n",
423 ACPI_FORMAT_UINT64 (operand[0]->integer.value)));
424 status = AE_AML_NUMERIC_OVERFLOW;
425 goto cleanup;
426 }
427 break;
428
429
430 case AML_COND_REF_OF_OP: /* cond_ref_of (source_object, Result) */
431
432 /*
433 * This op is a little strange because the internal return value is
434 * different than the return value stored in the result descriptor
435 * (There are really two return values)
436 */
437 if ((struct acpi_namespace_node *) operand[0] == acpi_gbl_root_node) {
438 /*
439 * This means that the object does not exist in the namespace,
440 * return FALSE
441 */
442 return_desc->integer.value = 0;
443 goto cleanup;
444 }
445
446 /* Get the object reference, store it, and remove our reference */
447
448 status = acpi_ex_get_object_reference (operand[0], &return_desc2, walk_state);
449 if (ACPI_FAILURE (status)) {
450 goto cleanup;
451 }
452
453 status = acpi_ex_store (return_desc2, operand[1], walk_state);
454 acpi_ut_remove_reference (return_desc2);
455
456 /* The object exists in the namespace, return TRUE */
457
458 return_desc->integer.value = ACPI_INTEGER_MAX;
459 goto cleanup;
460
461
462 default:
463 /* No other opcodes get here */
464 break;
465 }
466 break;
467
468
469 case AML_STORE_OP: /* Store (Source, Target) */
470
471 /*
472 * A store operand is typically a number, string, buffer or lvalue
473 * Be careful about deleting the source object,
474 * since the object itself may have been stored.
475 */
476 status = acpi_ex_store (operand[0], operand[1], walk_state);
477 if (ACPI_FAILURE (status)) {
478 return_ACPI_STATUS (status);
479 }
480
481 /* It is possible that the Store already produced a return object */
482
483 if (!walk_state->result_obj) {
484 /*
485 * Normally, we would remove a reference on the Operand[0] parameter;
486 * But since it is being used as the internal return object
487 * (meaning we would normally increment it), the two cancel out,
488 * and we simply don't do anything.
489 */
490 walk_state->result_obj = operand[0];
491 walk_state->operands[0] = NULL; /* Prevent deletion */
492 }
493 return_ACPI_STATUS (status);
494
495
496 /*
497 * ACPI 2.0 Opcodes
498 */
499 case AML_COPY_OP: /* Copy (Source, Target) */
500
501 status = acpi_ut_copy_iobject_to_iobject (operand[0], &return_desc,
502 walk_state);
503 break;
504
505
506 case AML_TO_DECSTRING_OP: /* to_decimal_string (Data, Result) */
507
508 status = acpi_ex_convert_to_string (operand[0], &return_desc,
509 ACPI_EXPLICIT_CONVERT_DECIMAL);
510 if (return_desc == operand[0]) {
511 /* No conversion performed, add ref to handle return value */
512 acpi_ut_add_reference (return_desc);
513 }
514 break;
515
516
517 case AML_TO_HEXSTRING_OP: /* to_hex_string (Data, Result) */
518
519 status = acpi_ex_convert_to_string (operand[0], &return_desc,
520 ACPI_EXPLICIT_CONVERT_HEX);
521 if (return_desc == operand[0]) {
522 /* No conversion performed, add ref to handle return value */
523 acpi_ut_add_reference (return_desc);
524 }
525 break;
526
527
528 case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */
529
530 status = acpi_ex_convert_to_buffer (operand[0], &return_desc);
531 if (return_desc == operand[0]) {
532 /* No conversion performed, add ref to handle return value */
533 acpi_ut_add_reference (return_desc);
534 }
535 break;
536
537
538 case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */
539
540 status = acpi_ex_convert_to_integer (operand[0], &return_desc,
541 ACPI_ANY_BASE);
542 if (return_desc == operand[0]) {
543 /* No conversion performed, add ref to handle return value */
544 acpi_ut_add_reference (return_desc);
545 }
546 break;
547
548
549 case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */
550 case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */
551
552 /*
553 * These are two obsolete opcodes
554 */
555 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
556 "%s is obsolete and not implemented\n",
557 acpi_ps_get_opcode_name (walk_state->opcode)));
558 status = AE_SUPPORT;
559 goto cleanup;
560
561
562 default: /* Unknown opcode */
563
564 ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n",
565 walk_state->opcode));
566 status = AE_AML_BAD_OPCODE;
567 goto cleanup;
568 }
569
570 if (ACPI_SUCCESS (status)) {
571 /*
572 * Store the return value computed above into the target object
573 */
574 status = acpi_ex_store (return_desc, operand[1], walk_state);
575 }
576
577
578cleanup:
579
580 if (!walk_state->result_obj) {
581 walk_state->result_obj = return_desc;
582 }
583
584 /* Delete return object on error */
585
586 if (ACPI_FAILURE (status)) {
587 acpi_ut_remove_reference (return_desc);
588 }
589
590 return_ACPI_STATUS (status);
591}
592
593
594/*******************************************************************************
595 *
596 * FUNCTION: acpi_ex_opcode_1A_0T_1R
597 *
598 * PARAMETERS: walk_state - Current state (contains AML opcode)
599 *
600 * RETURN: Status
601 *
602 * DESCRIPTION: Execute opcode with one argument, no target, and a return value
603 *
604 ******************************************************************************/
605
606acpi_status
607acpi_ex_opcode_1A_0T_1R (
608 struct acpi_walk_state *walk_state)
609{
610 union acpi_operand_object **operand = &walk_state->operands[0];
611 union acpi_operand_object *temp_desc;
612 union acpi_operand_object *return_desc = NULL;
613 acpi_status status = AE_OK;
614 u32 type;
615 acpi_integer value;
616
617
618 ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
619
620
621 /* Examine the AML opcode */
622
623 switch (walk_state->opcode) {
624 case AML_LNOT_OP: /* LNot (Operand) */
625
626 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
627 if (!return_desc) {
628 status = AE_NO_MEMORY;
629 goto cleanup;
630 }
631
632 /*
633 * Set result to ONES (TRUE) if Value == 0. Note:
634 * return_desc->Integer.Value is initially == 0 (FALSE) from above.
635 */
636 if (!operand[0]->integer.value) {
637 return_desc->integer.value = ACPI_INTEGER_MAX;
638 }
639 break;
640
641
642 case AML_DECREMENT_OP: /* Decrement (Operand) */
643 case AML_INCREMENT_OP: /* Increment (Operand) */
644
645 /*
646 * Create a new integer. Can't just get the base integer and
647 * increment it because it may be an Arg or Field.
648 */
649 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
650 if (!return_desc) {
651 status = AE_NO_MEMORY;
652 goto cleanup;
653 }
654
655 /*
656 * Since we are expecting a Reference operand, it can be either a
657 * NS Node or an internal object.
658 */
659 temp_desc = operand[0];
660 if (ACPI_GET_DESCRIPTOR_TYPE (temp_desc) == ACPI_DESC_TYPE_OPERAND) {
661 /* Internal reference object - prevent deletion */
662
663 acpi_ut_add_reference (temp_desc);
664 }
665
666 /*
667 * Convert the Reference operand to an Integer (This removes a
668 * reference on the Operand[0] object)
669 *
670 * NOTE: We use LNOT_OP here in order to force resolution of the
671 * reference operand to an actual integer.
672 */
673 status = acpi_ex_resolve_operands (AML_LNOT_OP, &temp_desc, walk_state);
674 if (ACPI_FAILURE (status)) {
675 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s: bad operand(s) %s\n",
676 acpi_ps_get_opcode_name (walk_state->opcode),
677 acpi_format_exception(status)));
678
679 goto cleanup;
680 }
681
682 /*
683 * temp_desc is now guaranteed to be an Integer object --
684 * Perform the actual increment or decrement
685 */
686 if (walk_state->opcode == AML_INCREMENT_OP) {
687 return_desc->integer.value = temp_desc->integer.value +1;
688 }
689 else {
690 return_desc->integer.value = temp_desc->integer.value -1;
691 }
692
693 /* Finished with this Integer object */
694
695 acpi_ut_remove_reference (temp_desc);
696
697 /*
698 * Store the result back (indirectly) through the original
699 * Reference object
700 */
701 status = acpi_ex_store (return_desc, operand[0], walk_state);
702 break;
703
704
705 case AML_TYPE_OP: /* object_type (source_object) */
706
707 /*
708 * Note: The operand is not resolved at this point because we want to
709 * get the associated object, not its value. For example, we don't want
710 * to resolve a field_unit to its value, we want the actual field_unit
711 * object.
712 */
713
714 /* Get the type of the base object */
715
716 status = acpi_ex_resolve_multiple (walk_state, operand[0], &type, NULL);
717 if (ACPI_FAILURE (status)) {
718 goto cleanup;
719 }
720 /* Allocate a descriptor to hold the type. */
721
722 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
723 if (!return_desc) {
724 status = AE_NO_MEMORY;
725 goto cleanup;
726 }
727
728 return_desc->integer.value = type;
729 break;
730
731
732 case AML_SIZE_OF_OP: /* size_of (source_object) */
733
734 /*
735 * Note: The operand is not resolved at this point because we want to
736 * get the associated object, not its value.
737 */
738
739 /* Get the base object */
740
741 status = acpi_ex_resolve_multiple (walk_state, operand[0], &type, &temp_desc);
742 if (ACPI_FAILURE (status)) {
743 goto cleanup;
744 }
745
746 /*
747 * The type of the base object must be integer, buffer, string, or
748 * package. All others are not supported.
749 *
750 * NOTE: Integer is not specifically supported by the ACPI spec,
751 * but is supported implicitly via implicit operand conversion.
752 * rather than bother with conversion, we just use the byte width
753 * global (4 or 8 bytes).
754 */
755 switch (type) {
756 case ACPI_TYPE_INTEGER:
757 value = acpi_gbl_integer_byte_width;
758 break;
759
760 case ACPI_TYPE_BUFFER:
761 value = temp_desc->buffer.length;
762 break;
763
764 case ACPI_TYPE_STRING:
765 value = temp_desc->string.length;
766 break;
767
768 case ACPI_TYPE_PACKAGE:
769 value = temp_desc->package.count;
770 break;
771
772 default:
773 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
774 "size_of - Operand is not Buf/Int/Str/Pkg - found type %s\n",
775 acpi_ut_get_type_name (type)));
776 status = AE_AML_OPERAND_TYPE;
777 goto cleanup;
778 }
779
780 /*
781 * Now that we have the size of the object, create a result
782 * object to hold the value
783 */
784 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
785 if (!return_desc) {
786 status = AE_NO_MEMORY;
787 goto cleanup;
788 }
789
790 return_desc->integer.value = value;
791 break;
792
793
794 case AML_REF_OF_OP: /* ref_of (source_object) */
795
796 status = acpi_ex_get_object_reference (operand[0], &return_desc, walk_state);
797 if (ACPI_FAILURE (status)) {
798 goto cleanup;
799 }
800 break;
801
802
803 case AML_DEREF_OF_OP: /* deref_of (obj_reference | String) */
804
805 /* Check for a method local or argument, or standalone String */
806
807 if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) != ACPI_DESC_TYPE_NAMED) {
808 switch (ACPI_GET_OBJECT_TYPE (operand[0])) {
809 case ACPI_TYPE_LOCAL_REFERENCE:
810 /*
811 * This is a deref_of (local_x | arg_x)
812 *
813 * Must resolve/dereference the local/arg reference first
814 */
815 switch (operand[0]->reference.opcode) {
816 case AML_LOCAL_OP:
817 case AML_ARG_OP:
818
819 /* Set Operand[0] to the value of the local/arg */
820
821 status = acpi_ds_method_data_get_value (operand[0]->reference.opcode,
822 operand[0]->reference.offset, walk_state, &temp_desc);
823 if (ACPI_FAILURE (status)) {
824 goto cleanup;
825 }
826
827 /*
828 * Delete our reference to the input object and
829 * point to the object just retrieved
830 */
831 acpi_ut_remove_reference (operand[0]);
832 operand[0] = temp_desc;
833 break;
834
835 case AML_REF_OF_OP:
836
837 /* Get the object to which the reference refers */
838
839 temp_desc = operand[0]->reference.object;
840 acpi_ut_remove_reference (operand[0]);
841 operand[0] = temp_desc;
842 break;
843
844 default:
845
846 /* Must be an Index op - handled below */
847 break;
848 }
849 break;
850
851
852 case ACPI_TYPE_STRING:
853
854 /*
855 * This is a deref_of (String). The string is a reference to a named ACPI object.
856 *
857 * 1) Find the owning Node
858 * 2) Dereference the node to an actual object. Could be a Field, so we nee
859 * to resolve the node to a value.
860 */
861 status = acpi_ns_get_node_by_path (operand[0]->string.pointer,
862 walk_state->scope_info->scope.node, ACPI_NS_SEARCH_PARENT,
863 ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &return_desc));
864 if (ACPI_FAILURE (status)) {
865 goto cleanup;
866 }
867
868 status = acpi_ex_resolve_node_to_value (
869 ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &return_desc), walk_state);
870 goto cleanup;
871
872
873 default:
874
875 status = AE_AML_OPERAND_TYPE;
876 goto cleanup;
877 }
878 }
879
880 /* Operand[0] may have changed from the code above */
881
882 if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) == ACPI_DESC_TYPE_NAMED) {
883 /*
884 * This is a deref_of (object_reference)
885 * Get the actual object from the Node (This is the dereference).
886 * -- This case may only happen when a local_x or arg_x is dereferenced above.
887 */
888 return_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) operand[0]);
889 }
890 else {
891 /*
892 * This must be a reference object produced by either the Index() or
893 * ref_of() operator
894 */
895 switch (operand[0]->reference.opcode) {
896 case AML_INDEX_OP:
897
898 /*
899 * The target type for the Index operator must be
900 * either a Buffer or a Package
901 */
902 switch (operand[0]->reference.target_type) {
903 case ACPI_TYPE_BUFFER_FIELD:
904
905 temp_desc = operand[0]->reference.object;
906
907 /*
908 * Create a new object that contains one element of the
909 * buffer -- the element pointed to by the index.
910 *
911 * NOTE: index into a buffer is NOT a pointer to a
912 * sub-buffer of the main buffer, it is only a pointer to a
913 * single element (byte) of the buffer!
914 */
915 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
916 if (!return_desc) {
917 status = AE_NO_MEMORY;
918 goto cleanup;
919 }
920
921 /*
922 * Since we are returning the value of the buffer at the
923 * indexed location, we don't need to add an additional
924 * reference to the buffer itself.
925 */
926 return_desc->integer.value =
927 temp_desc->buffer.pointer[operand[0]->reference.offset];
928 break;
929
930
931 case ACPI_TYPE_PACKAGE:
932
933 /*
934 * Return the referenced element of the package. We must add
935 * another reference to the referenced object, however.
936 */
937 return_desc = *(operand[0]->reference.where);
938 if (!return_desc) {
939 /*
940 * We can't return a NULL dereferenced value. This is
941 * an uninitialized package element and is thus a
942 * severe error.
943 */
944 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
945 "NULL package element obj %p\n",
946 operand[0]));
947 status = AE_AML_UNINITIALIZED_ELEMENT;
948 goto cleanup;
949 }
950
951 acpi_ut_add_reference (return_desc);
952 break;
953
954
955 default:
956
957 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
958 "Unknown Index target_type %X in obj %p\n",
959 operand[0]->reference.target_type, operand[0]));
960 status = AE_AML_OPERAND_TYPE;
961 goto cleanup;
962 }
963 break;
964
965
966 case AML_REF_OF_OP:
967
968 return_desc = operand[0]->reference.object;
969
970 if (ACPI_GET_DESCRIPTOR_TYPE (return_desc) == ACPI_DESC_TYPE_NAMED) {
971
972 return_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) return_desc);
973 }
974
975 /* Add another reference to the object! */
976
977 acpi_ut_add_reference (return_desc);
978 break;
979
980
981 default:
982 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
983 "Unknown opcode in ref(%p) - %X\n",
984 operand[0], operand[0]->reference.opcode));
985
986 status = AE_TYPE;
987 goto cleanup;
988 }
989 }
990 break;
991
992
993 default:
994
995 ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n",
996 walk_state->opcode));
997 status = AE_AML_BAD_OPCODE;
998 goto cleanup;
999 }
1000
1001
1002cleanup:
1003
1004 /* Delete return object on error */
1005
1006 if (ACPI_FAILURE (status)) {
1007 acpi_ut_remove_reference (return_desc);
1008 }
1009
1010 walk_state->result_obj = return_desc;
1011 return_ACPI_STATUS (status);
1012}
1013
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
new file mode 100644
index 000000000000..8be4d80ceed5
--- /dev/null
+++ b/drivers/acpi/executer/exoparg2.c
@@ -0,0 +1,608 @@
1/******************************************************************************
2 *
3 * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/acinterp.h>
48#include <acpi/acevents.h>
49#include <acpi/amlcode.h>
50
51
52#define _COMPONENT ACPI_EXECUTER
53 ACPI_MODULE_NAME ("exoparg2")
54
55
56/*!
57 * Naming convention for AML interpreter execution routines.
58 *
59 * The routines that begin execution of AML opcodes are named with a common
60 * convention based upon the number of arguments, the number of target operands,
61 * and whether or not a value is returned:
62 *
63 * AcpiExOpcode_xA_yT_zR
64 *
65 * Where:
66 *
67 * xA - ARGUMENTS: The number of arguments (input operands) that are
68 * required for this opcode type (1 through 6 args).
69 * yT - TARGETS: The number of targets (output operands) that are required
70 * for this opcode type (0, 1, or 2 targets).
71 * zR - RETURN VALUE: Indicates whether this opcode type returns a value
72 * as the function return (0 or 1).
73 *
74 * The AcpiExOpcode* functions are called via the Dispatcher component with
75 * fully resolved operands.
76!*/
77
78
79/*******************************************************************************
80 *
81 * FUNCTION: acpi_ex_opcode_2A_0T_0R
82 *
83 * PARAMETERS: walk_state - Current walk state
84 *
85 * RETURN: Status
86 *
87 * DESCRIPTION: Execute opcode with two arguments, no target, and no return
88 * value.
89 *
90 * ALLOCATION: Deletes both operands
91 *
92 ******************************************************************************/
93
94acpi_status
95acpi_ex_opcode_2A_0T_0R (
96 struct acpi_walk_state *walk_state)
97{
98 union acpi_operand_object **operand = &walk_state->operands[0];
99 struct acpi_namespace_node *node;
100 u32 value;
101 acpi_status status = AE_OK;
102
103
104 ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_0R",
105 acpi_ps_get_opcode_name (walk_state->opcode));
106
107
108 /* Examine the opcode */
109
110 switch (walk_state->opcode) {
111 case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */
112
113 /* The first operand is a namespace node */
114
115 node = (struct acpi_namespace_node *) operand[0];
116
117 /* Second value is the notify value */
118
119 value = (u32) operand[1]->integer.value;
120
121 /* Notifies allowed on this object? */
122
123 if (!acpi_ev_is_notify_object (node)) {
124 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
125 "Unexpected notify object type [%s]\n",
126 acpi_ut_get_type_name (node->type)));
127
128 status = AE_AML_OPERAND_TYPE;
129 break;
130 }
131
132#ifdef ACPI_GPE_NOTIFY_CHECK
133 /*
134 * GPE method wake/notify check. Here, we want to ensure that we
135 * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx
136 * GPE method during system runtime. If we do, the GPE is marked
137 * as "wake-only" and disabled.
138 *
139 * 1) Is the Notify() value == device_wake?
140 * 2) Is this a GPE deferred method? (An _Lxx or _Exx method)
141 * 3) Did the original GPE happen at system runtime?
142 * (versus during wake)
143 *
144 * If all three cases are true, this is a wake-only GPE that should
145 * be disabled at runtime.
146 */
147 if (value == 2) /* device_wake */ {
148 status = acpi_ev_check_for_wake_only_gpe (walk_state->gpe_event_info);
149 if (ACPI_FAILURE (status)) {
150 /* AE_WAKE_ONLY_GPE only error, means ignore this notify */
151
152 return_ACPI_STATUS (AE_OK)
153 }
154 }
155#endif
156
157 /*
158 * Dispatch the notify to the appropriate handler
159 * NOTE: the request is queued for execution after this method
160 * completes. The notify handlers are NOT invoked synchronously
161 * from this thread -- because handlers may in turn run other
162 * control methods.
163 */
164 status = acpi_ev_queue_notify_request (node, value);
165 break;
166
167
168 default:
169
170 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n",
171 walk_state->opcode));
172 status = AE_AML_BAD_OPCODE;
173 }
174
175 return_ACPI_STATUS (status);
176}
177
178
179/*******************************************************************************
180 *
181 * FUNCTION: acpi_ex_opcode_2A_2T_1R
182 *
183 * PARAMETERS: walk_state - Current walk state
184 *
185 * RETURN: Status
186 *
187 * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
188 * and one implicit return value.
189 *
190 ******************************************************************************/
191
192acpi_status
193acpi_ex_opcode_2A_2T_1R (
194 struct acpi_walk_state *walk_state)
195{
196 union acpi_operand_object **operand = &walk_state->operands[0];
197 union acpi_operand_object *return_desc1 = NULL;
198 union acpi_operand_object *return_desc2 = NULL;
199 acpi_status status;
200
201
202 ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_2T_1R",
203 acpi_ps_get_opcode_name (walk_state->opcode));
204
205
206 /*
207 * Execute the opcode
208 */
209 switch (walk_state->opcode) {
210 case AML_DIVIDE_OP: /* Divide (Dividend, Divisor, remainder_result quotient_result) */
211
212 return_desc1 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
213 if (!return_desc1) {
214 status = AE_NO_MEMORY;
215 goto cleanup;
216 }
217
218 return_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
219 if (!return_desc2) {
220 status = AE_NO_MEMORY;
221 goto cleanup;
222 }
223
224 /* Quotient to return_desc1, remainder to return_desc2 */
225
226 status = acpi_ut_divide (operand[0]->integer.value,
227 operand[1]->integer.value,
228 &return_desc1->integer.value,
229 &return_desc2->integer.value);
230 if (ACPI_FAILURE (status)) {
231 goto cleanup;
232 }
233 break;
234
235
236 default:
237
238 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n",
239 walk_state->opcode));
240 status = AE_AML_BAD_OPCODE;
241 goto cleanup;
242 }
243
244
245 /* Store the results to the target reference operands */
246
247 status = acpi_ex_store (return_desc2, operand[2], walk_state);
248 if (ACPI_FAILURE (status)) {
249 goto cleanup;
250 }
251
252 status = acpi_ex_store (return_desc1, operand[3], walk_state);
253 if (ACPI_FAILURE (status)) {
254 goto cleanup;
255 }
256
257 /* Return the remainder */
258
259 walk_state->result_obj = return_desc1;
260
261
262cleanup:
263 /*
264 * Since the remainder is not returned indirectly, remove a reference to
265 * it. Only the quotient is returned indirectly.
266 */
267 acpi_ut_remove_reference (return_desc2);
268
269 if (ACPI_FAILURE (status)) {
270 /* Delete the return object */
271
272 acpi_ut_remove_reference (return_desc1);
273 }
274
275 return_ACPI_STATUS (status);
276}
277
278
279/*******************************************************************************
280 *
281 * FUNCTION: acpi_ex_opcode_2A_1T_1R
282 *
283 * PARAMETERS: walk_state - Current walk state
284 *
285 * RETURN: Status
286 *
287 * DESCRIPTION: Execute opcode with two arguments, one target, and a return
288 * value.
289 *
290 ******************************************************************************/
291
292acpi_status
293acpi_ex_opcode_2A_1T_1R (
294 struct acpi_walk_state *walk_state)
295{
296 union acpi_operand_object **operand = &walk_state->operands[0];
297 union acpi_operand_object *return_desc = NULL;
298 u32 index;
299 acpi_status status = AE_OK;
300 acpi_size length;
301
302
303 ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_1T_1R",
304 acpi_ps_get_opcode_name (walk_state->opcode));
305
306
307 /*
308 * Execute the opcode
309 */
310 if (walk_state->op_info->flags & AML_MATH) {
311 /* All simple math opcodes (add, etc.) */
312
313 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
314 if (!return_desc) {
315 status = AE_NO_MEMORY;
316 goto cleanup;
317 }
318
319 return_desc->integer.value = acpi_ex_do_math_op (walk_state->opcode,
320 operand[0]->integer.value,
321 operand[1]->integer.value);
322 goto store_result_to_target;
323 }
324
325
326 switch (walk_state->opcode) {
327 case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
328
329 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
330 if (!return_desc) {
331 status = AE_NO_MEMORY;
332 goto cleanup;
333 }
334
335 /* return_desc will contain the remainder */
336
337 status = acpi_ut_divide (operand[0]->integer.value,
338 operand[1]->integer.value,
339 NULL,
340 &return_desc->integer.value);
341 break;
342
343
344 case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */
345
346 status = acpi_ex_do_concatenate (operand[0], operand[1],
347 &return_desc, walk_state);
348 break;
349
350
351 case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */
352
353 /*
354 * Input object is guaranteed to be a buffer at this point (it may have
355 * been converted.) Copy the raw buffer data to a new object of type String.
356 */
357
358 /*
359 * Get the length of the new string. It is the smallest of:
360 * 1) Length of the input buffer
361 * 2) Max length as specified in the to_string operator
362 * 3) Length of input buffer up to a zero byte (null terminator)
363 *
364 * NOTE: A length of zero is ok, and will create a zero-length, null
365 * terminated string.
366 */
367 length = 0;
368 while ((length < operand[0]->buffer.length) &&
369 (length < operand[1]->integer.value) &&
370 (operand[0]->buffer.pointer[length])) {
371 length++;
372 if (length > ACPI_MAX_STRING_CONVERSION) {
373 status = AE_AML_STRING_LIMIT;
374 goto cleanup;
375 }
376 }
377
378 /* Allocate a new string object */
379
380 return_desc = acpi_ut_create_string_object (length);
381 if (!return_desc) {
382 status = AE_NO_MEMORY;
383 goto cleanup;
384 }
385
386 /* Copy the raw buffer data with no transform. NULL terminated already. */
387
388 ACPI_MEMCPY (return_desc->string.pointer,
389 operand[0]->buffer.pointer, length);
390 break;
391
392
393 case AML_CONCAT_RES_OP: /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
394
395 status = acpi_ex_concat_template (operand[0], operand[1],
396 &return_desc, walk_state);
397 break;
398
399
400 case AML_INDEX_OP: /* Index (Source Index Result) */
401
402 /* Create the internal return object */
403
404 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
405 if (!return_desc) {
406 status = AE_NO_MEMORY;
407 goto cleanup;
408 }
409
410 index = (u32) operand[1]->integer.value;
411
412 /*
413 * At this point, the Source operand is a Package, Buffer, or String
414 */
415 if (ACPI_GET_OBJECT_TYPE (operand[0]) == ACPI_TYPE_PACKAGE) {
416 /* Object to be indexed is a Package */
417
418 if (index >= operand[0]->package.count) {
419 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
420 "Index value (%X) beyond package end (%X)\n",
421 index, operand[0]->package.count));
422 status = AE_AML_PACKAGE_LIMIT;
423 goto cleanup;
424 }
425
426 return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
427 return_desc->reference.object = operand[0];
428 return_desc->reference.where = &operand[0]->package.elements [index];
429 }
430 else {
431 /* Object to be indexed is a Buffer/String */
432
433 if (index >= operand[0]->buffer.length) {
434 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
435 "Index value (%X) beyond end of buffer (%X)\n",
436 index, operand[0]->buffer.length));
437 status = AE_AML_BUFFER_LIMIT;
438 goto cleanup;
439 }
440
441 return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
442 return_desc->reference.object = operand[0];
443 }
444
445 /*
446 * Add a reference to the target package/buffer/string for the life
447 * of the index.
448 */
449 acpi_ut_add_reference (operand[0]);
450
451 /* Complete the Index reference object */
452
453 return_desc->reference.opcode = AML_INDEX_OP;
454 return_desc->reference.offset = index;
455
456 /* Store the reference to the Target */
457
458 status = acpi_ex_store (return_desc, operand[2], walk_state);
459
460 /* Return the reference */
461
462 walk_state->result_obj = return_desc;
463 goto cleanup;
464
465
466 default:
467
468 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n",
469 walk_state->opcode));
470 status = AE_AML_BAD_OPCODE;
471 break;
472 }
473
474
475store_result_to_target:
476
477 if (ACPI_SUCCESS (status)) {
478 /*
479 * Store the result of the operation (which is now in return_desc) into
480 * the Target descriptor.
481 */
482 status = acpi_ex_store (return_desc, operand[2], walk_state);
483 if (ACPI_FAILURE (status)) {
484 goto cleanup;
485 }
486
487 if (!walk_state->result_obj) {
488 walk_state->result_obj = return_desc;
489 }
490 }
491
492
493cleanup:
494
495 /* Delete return object on error */
496
497 if (ACPI_FAILURE (status)) {
498 acpi_ut_remove_reference (return_desc);
499 }
500
501 return_ACPI_STATUS (status);
502}
503
504
505/*******************************************************************************
506 *
507 * FUNCTION: acpi_ex_opcode_2A_0T_1R
508 *
509 * PARAMETERS: walk_state - Current walk state
510 *
511 * RETURN: Status
512 *
513 * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
514 *
515 ******************************************************************************/
516
517acpi_status
518acpi_ex_opcode_2A_0T_1R (
519 struct acpi_walk_state *walk_state)
520{
521 union acpi_operand_object **operand = &walk_state->operands[0];
522 union acpi_operand_object *return_desc = NULL;
523 acpi_status status = AE_OK;
524 u8 logical_result = FALSE;
525
526
527 ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_1R",
528 acpi_ps_get_opcode_name (walk_state->opcode));
529
530
531 /* Create the internal return object */
532
533 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
534 if (!return_desc) {
535 status = AE_NO_MEMORY;
536 goto cleanup;
537 }
538
539 /*
540 * Execute the Opcode
541 */
542 if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) /* logical_op (Operand0, Operand1) */ {
543 status = acpi_ex_do_logical_numeric_op (walk_state->opcode,
544 operand[0]->integer.value, operand[1]->integer.value,
545 &logical_result);
546 goto store_logical_result;
547 }
548 else if (walk_state->op_info->flags & AML_LOGICAL) /* logical_op (Operand0, Operand1) */ {
549 status = acpi_ex_do_logical_op (walk_state->opcode, operand[0],
550 operand[1], &logical_result);
551 goto store_logical_result;
552 }
553
554
555 switch (walk_state->opcode) {
556 case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */
557
558 status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state);
559 if (status == AE_TIME) {
560 logical_result = TRUE; /* TRUE = Acquire timed out */
561 status = AE_OK;
562 }
563 break;
564
565
566 case AML_WAIT_OP: /* Wait (event_object, Timeout) */
567
568 status = acpi_ex_system_wait_event (operand[1], operand[0]);
569 if (status == AE_TIME) {
570 logical_result = TRUE; /* TRUE, Wait timed out */
571 status = AE_OK;
572 }
573 break;
574
575
576 default:
577
578 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n",
579 walk_state->opcode));
580 status = AE_AML_BAD_OPCODE;
581 goto cleanup;
582 }
583
584
585store_logical_result:
586 /*
587 * Set return value to according to logical_result. logical TRUE (all ones)
588 * Default is FALSE (zero)
589 */
590 if (logical_result) {
591 return_desc->integer.value = ACPI_INTEGER_MAX;
592 }
593
594 walk_state->result_obj = return_desc;
595
596
597cleanup:
598
599 /* Delete return object on error */
600
601 if (ACPI_FAILURE (status)) {
602 acpi_ut_remove_reference (return_desc);
603 }
604
605 return_ACPI_STATUS (status);
606}
607
608
diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c
new file mode 100644
index 000000000000..29d0b167745d
--- /dev/null
+++ b/drivers/acpi/executer/exoparg3.c
@@ -0,0 +1,256 @@
1
2/******************************************************************************
3 *
4 * Module Name: exoparg3 - AML execution - opcodes with 3 arguments
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acinterp.h>
48#include <acpi/acparser.h>
49#include <acpi/amlcode.h>
50
51
52#define _COMPONENT ACPI_EXECUTER
53 ACPI_MODULE_NAME ("exoparg3")
54
55
56/*!
57 * Naming convention for AML interpreter execution routines.
58 *
59 * The routines that begin execution of AML opcodes are named with a common
60 * convention based upon the number of arguments, the number of target operands,
61 * and whether or not a value is returned:
62 *
63 * AcpiExOpcode_xA_yT_zR
64 *
65 * Where:
66 *
67 * xA - ARGUMENTS: The number of arguments (input operands) that are
68 * required for this opcode type (1 through 6 args).
69 * yT - TARGETS: The number of targets (output operands) that are required
70 * for this opcode type (0, 1, or 2 targets).
71 * zR - RETURN VALUE: Indicates whether this opcode type returns a value
72 * as the function return (0 or 1).
73 *
74 * The AcpiExOpcode* functions are called via the Dispatcher component with
75 * fully resolved operands.
76!*/
77
78
79/*******************************************************************************
80 *
81 * FUNCTION: acpi_ex_opcode_3A_0T_0R
82 *
83 * PARAMETERS: walk_state - Current walk state
84 *
85 * RETURN: Status
86 *
87 * DESCRIPTION: Execute Triadic operator (3 operands)
88 *
89 ******************************************************************************/
90
91acpi_status
92acpi_ex_opcode_3A_0T_0R (
93 struct acpi_walk_state *walk_state)
94{
95 union acpi_operand_object **operand = &walk_state->operands[0];
96 struct acpi_signal_fatal_info *fatal;
97 acpi_status status = AE_OK;
98
99
100 ACPI_FUNCTION_TRACE_STR ("ex_opcode_3A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode));
101
102
103 switch (walk_state->opcode) {
104 case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */
105
106 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
107 "fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
108 (u32) operand[0]->integer.value,
109 (u32) operand[1]->integer.value,
110 (u32) operand[2]->integer.value));
111
112 fatal = ACPI_MEM_ALLOCATE (sizeof (struct acpi_signal_fatal_info));
113 if (fatal) {
114 fatal->type = (u32) operand[0]->integer.value;
115 fatal->code = (u32) operand[1]->integer.value;
116 fatal->argument = (u32) operand[2]->integer.value;
117 }
118
119 /*
120 * Always signal the OS!
121 */
122 status = acpi_os_signal (ACPI_SIGNAL_FATAL, fatal);
123
124 /* Might return while OS is shutting down, just continue */
125
126 ACPI_MEM_FREE (fatal);
127 break;
128
129
130 default:
131
132 ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n",
133 walk_state->opcode));
134 status = AE_AML_BAD_OPCODE;
135 goto cleanup;
136 }
137
138
139cleanup:
140
141 return_ACPI_STATUS (status);
142}
143
144
145/*******************************************************************************
146 *
147 * FUNCTION: acpi_ex_opcode_3A_1T_1R
148 *
149 * PARAMETERS: walk_state - Current walk state
150 *
151 * RETURN: Status
152 *
153 * DESCRIPTION: Execute Triadic operator (3 operands)
154 *
155 ******************************************************************************/
156
157acpi_status
158acpi_ex_opcode_3A_1T_1R (
159 struct acpi_walk_state *walk_state)
160{
161 union acpi_operand_object **operand = &walk_state->operands[0];
162 union acpi_operand_object *return_desc = NULL;
163 char *buffer;
164 acpi_status status = AE_OK;
165 acpi_native_uint index;
166 acpi_size length;
167
168
169 ACPI_FUNCTION_TRACE_STR ("ex_opcode_3A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
170
171
172 switch (walk_state->opcode) {
173 case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */
174
175 /*
176 * Create the return object. The Source operand is guaranteed to be
177 * either a String or a Buffer, so just use its type.
178 */
179 return_desc = acpi_ut_create_internal_object (ACPI_GET_OBJECT_TYPE (operand[0]));
180 if (!return_desc) {
181 status = AE_NO_MEMORY;
182 goto cleanup;
183 }
184
185 /* Get the Integer values from the objects */
186
187 index = (acpi_native_uint) operand[1]->integer.value;
188 length = (acpi_size) operand[2]->integer.value;
189
190 /*
191 * If the index is beyond the length of the String/Buffer, or if the
192 * requested length is zero, return a zero-length String/Buffer
193 */
194 if ((index < operand[0]->string.length) &&
195 (length > 0)) {
196 /* Truncate request if larger than the actual String/Buffer */
197
198 if ((index + length) >
199 operand[0]->string.length) {
200 length = (acpi_size) operand[0]->string.length - index;
201 }
202
203 /* Allocate a new buffer for the String/Buffer */
204
205 buffer = ACPI_MEM_CALLOCATE ((acpi_size) length + 1);
206 if (!buffer) {
207 status = AE_NO_MEMORY;
208 goto cleanup;
209 }
210
211 /* Copy the portion requested */
212
213 ACPI_MEMCPY (buffer, operand[0]->string.pointer + index,
214 length);
215
216 /* Set the length of the new String/Buffer */
217
218 return_desc->string.pointer = buffer;
219 return_desc->string.length = (u32) length;
220 }
221
222 /* Mark buffer initialized */
223
224 return_desc->buffer.flags |= AOPOBJ_DATA_VALID;
225 break;
226
227
228 default:
229
230 ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n",
231 walk_state->opcode));
232 status = AE_AML_BAD_OPCODE;
233 goto cleanup;
234 }
235
236 /* Store the result in the target */
237
238 status = acpi_ex_store (return_desc, operand[3], walk_state);
239
240cleanup:
241
242 /* Delete return object on error */
243
244 if (ACPI_FAILURE (status)) {
245 acpi_ut_remove_reference (return_desc);
246 }
247
248 /* Set the return object and exit */
249
250 if (!walk_state->result_obj) {
251 walk_state->result_obj = return_desc;
252 }
253 return_ACPI_STATUS (status);
254}
255
256
diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c
new file mode 100644
index 000000000000..d32624331626
--- /dev/null
+++ b/drivers/acpi/executer/exoparg6.c
@@ -0,0 +1,336 @@
1
2/******************************************************************************
3 *
4 * Module Name: exoparg6 - AML execution - opcodes with 6 arguments
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acinterp.h>
48#include <acpi/acparser.h>
49#include <acpi/amlcode.h>
50
51
52#define _COMPONENT ACPI_EXECUTER
53 ACPI_MODULE_NAME ("exoparg6")
54
55
56/*!
57 * Naming convention for AML interpreter execution routines.
58 *
59 * The routines that begin execution of AML opcodes are named with a common
60 * convention based upon the number of arguments, the number of target operands,
61 * and whether or not a value is returned:
62 *
63 * AcpiExOpcode_xA_yT_zR
64 *
65 * Where:
66 *
67 * xA - ARGUMENTS: The number of arguments (input operands) that are
68 * required for this opcode type (1 through 6 args).
69 * yT - TARGETS: The number of targets (output operands) that are required
70 * for this opcode type (0, 1, or 2 targets).
71 * zR - RETURN VALUE: Indicates whether this opcode type returns a value
72 * as the function return (0 or 1).
73 *
74 * The AcpiExOpcode* functions are called via the Dispatcher component with
75 * fully resolved operands.
76!*/
77
78
79/*******************************************************************************
80 *
81 * FUNCTION: acpi_ex_do_match
82 *
83 * PARAMETERS: match_op - The AML match operand
84 * package_obj - Object from the target package
85 * match_obj - Object to be matched
86 *
87 * RETURN: TRUE if the match is successful, FALSE otherwise
88 *
89 * DESCRIPTION: Implements the low-level match for the ASL Match operator.
90 * Package elements will be implicitly converted to the type of
91 * the match object (Integer/Buffer/String).
92 *
93 ******************************************************************************/
94
95u8
96acpi_ex_do_match (
97 u32 match_op,
98 union acpi_operand_object *package_obj,
99 union acpi_operand_object *match_obj)
100{
101 u8 logical_result = TRUE;
102 acpi_status status;
103
104
105 /*
106 * Note: Since the package_obj/match_obj ordering is opposite to that of
107 * the standard logical operators, we have to reverse them when we call
108 * do_logical_op in order to make the implicit conversion rules work
109 * correctly. However, this means we have to flip the entire equation
110 * also. A bit ugly perhaps, but overall, better than fussing the
111 * parameters around at runtime, over and over again.
112 *
113 * Below, P[i] refers to the package element, M refers to the Match object.
114 */
115 switch (match_op) {
116 case MATCH_MTR:
117
118 /* Always true */
119
120 break;
121
122 case MATCH_MEQ:
123
124 /*
125 * True if equal: (P[i] == M)
126 * Change to: (M == P[i])
127 */
128 status = acpi_ex_do_logical_op (AML_LEQUAL_OP, match_obj, package_obj,
129 &logical_result);
130 if (ACPI_FAILURE (status)) {
131 return (FALSE);
132 }
133 break;
134
135 case MATCH_MLE:
136
137 /*
138 * True if less than or equal: (P[i] <= M) (P[i] not_greater than M)
139 * Change to: (M >= P[i]) (M not_less than P[i])
140 */
141 status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj,
142 &logical_result);
143 if (ACPI_FAILURE (status)) {
144 return (FALSE);
145 }
146 logical_result = (u8) !logical_result;
147 break;
148
149 case MATCH_MLT:
150
151 /*
152 * True if less than: (P[i] < M)
153 * Change to: (M > P[i])
154 */
155 status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj,
156 &logical_result);
157 if (ACPI_FAILURE (status)) {
158 return (FALSE);
159 }
160 break;
161
162 case MATCH_MGE:
163
164 /*
165 * True if greater than or equal: (P[i] >= M) (P[i] not_less than M)
166 * Change to: (M <= P[i]) (M not_greater than P[i])
167 */
168 status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj,
169 &logical_result);
170 if (ACPI_FAILURE (status)) {
171 return (FALSE);
172 }
173 logical_result = (u8)!logical_result;
174 break;
175
176 case MATCH_MGT:
177
178 /*
179 * True if greater than: (P[i] > M)
180 * Change to: (M < P[i])
181 */
182 status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj,
183 &logical_result);
184 if (ACPI_FAILURE (status)) {
185 return (FALSE);
186 }
187 break;
188
189 default:
190
191 /* Undefined */
192
193 return (FALSE);
194 }
195
196 return logical_result;
197}
198
199
200/*******************************************************************************
201 *
202 * FUNCTION: acpi_ex_opcode_6A_0T_1R
203 *
204 * PARAMETERS: walk_state - Current walk state
205 *
206 * RETURN: Status
207 *
208 * DESCRIPTION: Execute opcode with 6 arguments, no target, and a return value
209 *
210 ******************************************************************************/
211
212acpi_status
213acpi_ex_opcode_6A_0T_1R (
214 struct acpi_walk_state *walk_state)
215{
216 union acpi_operand_object **operand = &walk_state->operands[0];
217 union acpi_operand_object *return_desc = NULL;
218 acpi_status status = AE_OK;
219 u32 index;
220 union acpi_operand_object *this_element;
221
222
223 ACPI_FUNCTION_TRACE_STR ("ex_opcode_6A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
224
225
226 switch (walk_state->opcode) {
227 case AML_MATCH_OP:
228 /*
229 * Match (search_pkg[0], match_op1[1], match_obj1[2],
230 * match_op2[3], match_obj2[4], start_index[5])
231 */
232
233 /* Validate both Match Term Operators (MTR, MEQ, etc.) */
234
235 if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
236 (operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
237 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Match operator out of range\n"));
238 status = AE_AML_OPERAND_VALUE;
239 goto cleanup;
240 }
241
242 /* Get the package start_index, validate against the package length */
243
244 index = (u32) operand[5]->integer.value;
245 if (index >= (u32) operand[0]->package.count) {
246 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index beyond package end\n"));
247 status = AE_AML_PACKAGE_LIMIT;
248 goto cleanup;
249 }
250
251 /* Create an integer for the return value */
252
253 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
254 if (!return_desc) {
255 status = AE_NO_MEMORY;
256 goto cleanup;
257
258 }
259
260 /* Default return value if no match found */
261
262 return_desc->integer.value = ACPI_INTEGER_MAX;
263
264 /*
265 * Examine each element until a match is found. Both match conditions
266 * must be satisfied for a match to occur. Within the loop,
267 * "continue" signifies that the current element does not match
268 * and the next should be examined.
269 *
270 * Upon finding a match, the loop will terminate via "break" at
271 * the bottom. If it terminates "normally", match_value will be
272 * ACPI_INTEGER_MAX (Ones) (its initial value) indicating that no
273 * match was found.
274 */
275 for ( ; index < operand[0]->package.count; index++) {
276 /* Get the current package element */
277
278 this_element = operand[0]->package.elements[index];
279
280 /* Treat any uninitialized (NULL) elements as non-matching */
281
282 if (!this_element) {
283 continue;
284 }
285
286 /*
287 * Both match conditions must be satisfied. Execution of a continue
288 * (proceed to next iteration of enclosing for loop) signifies a
289 * non-match.
290 */
291 if (!acpi_ex_do_match ((u32) operand[1]->integer.value,
292 this_element, operand[2])) {
293 continue;
294 }
295
296 if (!acpi_ex_do_match ((u32) operand[3]->integer.value,
297 this_element, operand[4])) {
298 continue;
299 }
300
301 /* Match found: Index is the return value */
302
303 return_desc->integer.value = index;
304 break;
305 }
306 break;
307
308
309 case AML_LOAD_TABLE_OP:
310
311 status = acpi_ex_load_table_op (walk_state, &return_desc);
312 break;
313
314
315 default:
316
317 ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n",
318 walk_state->opcode));
319 status = AE_AML_BAD_OPCODE;
320 goto cleanup;
321 }
322
323
324 walk_state->result_obj = return_desc;
325
326
327cleanup:
328
329 /* Delete return object on error */
330
331 if (ACPI_FAILURE (status)) {
332 acpi_ut_remove_reference (return_desc);
333 }
334
335 return_ACPI_STATUS (status);
336}
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
new file mode 100644
index 000000000000..264ef3bba31b
--- /dev/null
+++ b/drivers/acpi/executer/exprep.c
@@ -0,0 +1,530 @@
1
2/******************************************************************************
3 *
4 * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acinterp.h>
48#include <acpi/amlcode.h>
49#include <acpi/acnamesp.h>
50
51
52#define _COMPONENT ACPI_EXECUTER
53 ACPI_MODULE_NAME ("exprep")
54
55
56#ifdef ACPI_UNDER_DEVELOPMENT
57/*******************************************************************************
58 *
59 * FUNCTION: acpi_ex_generate_access
60 *
61 * PARAMETERS: field_bit_offset - Start of field within parent region/buffer
62 * field_bit_length - Length of field in bits
63 * region_length - Length of parent in bytes
64 *
65 * RETURN: Field granularity (8, 16, 32 or 64) and
66 * byte_alignment (1, 2, 3, or 4)
67 *
68 * DESCRIPTION: Generate an optimal access width for fields defined with the
69 * any_acc keyword.
70 *
71 * NOTE: Need to have the region_length in order to check for boundary
72 * conditions (end-of-region). However, the region_length is a deferred
73 * operation. Therefore, to complete this implementation, the generation
74 * of this access width must be deferred until the region length has
75 * been evaluated.
76 *
77 ******************************************************************************/
78
79static u32
80acpi_ex_generate_access (
81 u32 field_bit_offset,
82 u32 field_bit_length,
83 u32 region_length)
84{
85 u32 field_byte_length;
86 u32 field_byte_offset;
87 u32 field_byte_end_offset;
88 u32 access_byte_width;
89 u32 field_start_offset;
90 u32 field_end_offset;
91 u32 minimum_access_width = 0xFFFFFFFF;
92 u32 minimum_accesses = 0xFFFFFFFF;
93 u32 accesses;
94
95
96 ACPI_FUNCTION_TRACE ("ex_generate_access");
97
98
99 /* Round Field start offset and length to "minimal" byte boundaries */
100
101 field_byte_offset = ACPI_DIV_8 (ACPI_ROUND_DOWN (field_bit_offset, 8));
102 field_byte_end_offset = ACPI_DIV_8 (ACPI_ROUND_UP (field_bit_length + field_bit_offset, 8));
103 field_byte_length = field_byte_end_offset - field_byte_offset;
104
105 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
106 "Bit length %d, Bit offset %d\n",
107 field_bit_length, field_bit_offset));
108 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
109 "Byte Length %d, Byte Offset %d, End Offset %d\n",
110 field_byte_length, field_byte_offset, field_byte_end_offset));
111
112 /*
113 * Iterative search for the maximum access width that is both aligned
114 * and does not go beyond the end of the region
115 *
116 * Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes)
117 */
118 for (access_byte_width = 1; access_byte_width <= 8; access_byte_width <<= 1) {
119 /*
120 * 1) Round end offset up to next access boundary and make sure that this
121 * does not go beyond the end of the parent region.
122 * 2) When the Access width is greater than the field_byte_length, we are done.
123 * (This does not optimize for the perfectly aligned case yet).
124 */
125 if (ACPI_ROUND_UP (field_byte_end_offset, access_byte_width) <= region_length) {
126 field_start_offset = ACPI_ROUND_DOWN (field_byte_offset, access_byte_width) /
127 access_byte_width;
128 field_end_offset = ACPI_ROUND_UP ((field_byte_length + field_byte_offset),
129 access_byte_width) / access_byte_width;
130 accesses = field_end_offset - field_start_offset;
131
132 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
133 "access_width %d end is within region\n", access_byte_width));
134 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
135 "Field Start %d, Field End %d -- requires %d accesses\n",
136 field_start_offset, field_end_offset, accesses));
137
138 /* Single access is optimal */
139
140 if (accesses <= 1) {
141 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
142 "Entire field can be accessed with one operation of size %d\n",
143 access_byte_width));
144 return_VALUE (access_byte_width);
145 }
146
147 /*
148 * Fits in the region, but requires more than one read/write.
149 * try the next wider access on next iteration
150 */
151 if (accesses < minimum_accesses) {
152 minimum_accesses = accesses;
153 minimum_access_width = access_byte_width;
154 }
155 }
156 else {
157 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
158 "access_width %d end is NOT within region\n", access_byte_width));
159 if (access_byte_width == 1) {
160 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
161 "Field goes beyond end-of-region!\n"));
162 return_VALUE (0); /* Field does not fit in the region at all */
163 }
164
165 /* This width goes beyond the end-of-region, back off to previous access */
166
167 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
168 "Backing off to previous optimal access width of %d\n",
169 minimum_access_width));
170 return_VALUE (minimum_access_width);
171 }
172 }
173
174 /* Could not read/write field with one operation, just use max access width */
175
176 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
177 "Cannot access field in one operation, using width 8\n"));
178 return_VALUE (8);
179}
180#endif /* ACPI_UNDER_DEVELOPMENT */
181
182
183/*******************************************************************************
184 *
185 * FUNCTION: acpi_ex_decode_field_access
186 *
187 * PARAMETERS: Access - Encoded field access bits
188 * Length - Field length.
189 *
190 * RETURN: Field granularity (8, 16, 32 or 64) and
191 * byte_alignment (1, 2, 3, or 4)
192 *
193 * DESCRIPTION: Decode the access_type bits of a field definition.
194 *
195 ******************************************************************************/
196
197static u32
198acpi_ex_decode_field_access (
199 union acpi_operand_object *obj_desc,
200 u8 field_flags,
201 u32 *return_byte_alignment)
202{
203 u32 access;
204 u32 byte_alignment;
205 u32 bit_length;
206
207
208 ACPI_FUNCTION_TRACE ("ex_decode_field_access");
209
210
211 access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK);
212
213 switch (access) {
214 case AML_FIELD_ACCESS_ANY:
215
216#ifdef ACPI_UNDER_DEVELOPMENT
217 byte_alignment = acpi_ex_generate_access (obj_desc->common_field.start_field_bit_offset,
218 obj_desc->common_field.bit_length,
219 0xFFFFFFFF /* Temp until we pass region_length as param */);
220 bit_length = byte_alignment * 8;
221#endif
222
223 byte_alignment = 1;
224 bit_length = 8;
225 break;
226
227 case AML_FIELD_ACCESS_BYTE:
228 case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */
229 byte_alignment = 1;
230 bit_length = 8;
231 break;
232
233 case AML_FIELD_ACCESS_WORD:
234 byte_alignment = 2;
235 bit_length = 16;
236 break;
237
238 case AML_FIELD_ACCESS_DWORD:
239 byte_alignment = 4;
240 bit_length = 32;
241 break;
242
243 case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */
244 byte_alignment = 8;
245 bit_length = 64;
246 break;
247
248 default:
249 /* Invalid field access type */
250
251 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
252 "Unknown field access type %X\n",
253 access));
254 return_VALUE (0);
255 }
256
257 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
258 /*
259 * buffer_field access can be on any byte boundary, so the
260 * byte_alignment is always 1 byte -- regardless of any byte_alignment
261 * implied by the field access type.
262 */
263 byte_alignment = 1;
264 }
265
266 *return_byte_alignment = byte_alignment;
267 return_VALUE (bit_length);
268}
269
270
271/*******************************************************************************
272 *
273 * FUNCTION: acpi_ex_prep_common_field_object
274 *
275 * PARAMETERS: obj_desc - The field object
276 * field_flags - Access, lock_rule, and update_rule.
277 * The format of a field_flag is described
278 * in the ACPI specification
279 * field_bit_position - Field start position
280 * field_bit_length - Field length in number of bits
281 *
282 * RETURN: Status
283 *
284 * DESCRIPTION: Initialize the areas of the field object that are common
285 * to the various types of fields. Note: This is very "sensitive"
286 * code because we are solving the general case for field
287 * alignment.
288 *
289 ******************************************************************************/
290
291acpi_status
292acpi_ex_prep_common_field_object (
293 union acpi_operand_object *obj_desc,
294 u8 field_flags,
295 u8 field_attribute,
296 u32 field_bit_position,
297 u32 field_bit_length)
298{
299 u32 access_bit_width;
300 u32 byte_alignment;
301 u32 nearest_byte_address;
302
303
304 ACPI_FUNCTION_TRACE ("ex_prep_common_field_object");
305
306
307 /*
308 * Note: the structure being initialized is the
309 * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common
310 * area are initialized by this procedure.
311 */
312 obj_desc->common_field.field_flags = field_flags;
313 obj_desc->common_field.attribute = field_attribute;
314 obj_desc->common_field.bit_length = field_bit_length;
315
316 /*
317 * Decode the access type so we can compute offsets. The access type gives
318 * two pieces of information - the width of each field access and the
319 * necessary byte_alignment (address granularity) of the access.
320 *
321 * For any_acc, the access_bit_width is the largest width that is both
322 * necessary and possible in an attempt to access the whole field in one
323 * I/O operation. However, for any_acc, the byte_alignment is always one
324 * byte.
325 *
326 * For all Buffer Fields, the byte_alignment is always one byte.
327 *
328 * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
329 * the same (equivalent) as the byte_alignment.
330 */
331 access_bit_width = acpi_ex_decode_field_access (obj_desc, field_flags,
332 &byte_alignment);
333 if (!access_bit_width) {
334 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
335 }
336
337 /* Setup width (access granularity) fields */
338
339 obj_desc->common_field.access_byte_width = (u8)
340 ACPI_DIV_8 (access_bit_width); /* 1, 2, 4, 8 */
341
342 obj_desc->common_field.access_bit_width = (u8) access_bit_width;
343
344 /*
345 * base_byte_offset is the address of the start of the field within the
346 * region. It is the byte address of the first *datum* (field-width data
347 * unit) of the field. (i.e., the first datum that contains at least the
348 * first *bit* of the field.)
349 *
350 * Note: byte_alignment is always either equal to the access_bit_width or 8
351 * (Byte access), and it defines the addressing granularity of the parent
352 * region or buffer.
353 */
354 nearest_byte_address =
355 ACPI_ROUND_BITS_DOWN_TO_BYTES (field_bit_position);
356 obj_desc->common_field.base_byte_offset = (u32)
357 ACPI_ROUND_DOWN (nearest_byte_address, byte_alignment);
358
359 /*
360 * start_field_bit_offset is the offset of the first bit of the field within
361 * a field datum.
362 */
363 obj_desc->common_field.start_field_bit_offset = (u8)
364 (field_bit_position - ACPI_MUL_8 (obj_desc->common_field.base_byte_offset));
365
366 /*
367 * Does the entire field fit within a single field access element? (datum)
368 * (i.e., without crossing a datum boundary)
369 */
370 if ((obj_desc->common_field.start_field_bit_offset + field_bit_length) <=
371 (u16) access_bit_width) {
372 obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM;
373 }
374
375 return_ACPI_STATUS (AE_OK);
376}
377
378
379/*******************************************************************************
380 *
381 * FUNCTION: acpi_ex_prep_field_value
382 *
383 * PARAMETERS: Node - Owning Node
384 * region_node - Region in which field is being defined
385 * field_flags - Access, lock_rule, and update_rule.
386 * field_bit_position - Field start position
387 * field_bit_length - Field length in number of bits
388 *
389 * RETURN: Status
390 *
391 * DESCRIPTION: Construct an union acpi_operand_object of type def_field and
392 * connect it to the parent Node.
393 *
394 ******************************************************************************/
395
396acpi_status
397acpi_ex_prep_field_value (
398 struct acpi_create_field_info *info)
399{
400 union acpi_operand_object *obj_desc;
401 u32 type;
402 acpi_status status;
403
404
405 ACPI_FUNCTION_TRACE ("ex_prep_field_value");
406
407
408 /* Parameter validation */
409
410 if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
411 if (!info->region_node) {
412 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null region_node\n"));
413 return_ACPI_STATUS (AE_AML_NO_OPERAND);
414 }
415
416 type = acpi_ns_get_type (info->region_node);
417 if (type != ACPI_TYPE_REGION) {
418 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
419 "Needed Region, found type %X (%s)\n",
420 type, acpi_ut_get_type_name (type)));
421
422 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
423 }
424 }
425
426 /* Allocate a new field object */
427
428 obj_desc = acpi_ut_create_internal_object (info->field_type);
429 if (!obj_desc) {
430 return_ACPI_STATUS (AE_NO_MEMORY);
431 }
432
433 /* Initialize areas of the object that are common to all fields */
434
435 obj_desc->common_field.node = info->field_node;
436 status = acpi_ex_prep_common_field_object (obj_desc, info->field_flags,
437 info->attribute, info->field_bit_position, info->field_bit_length);
438 if (ACPI_FAILURE (status)) {
439 acpi_ut_delete_object_desc (obj_desc);
440 return_ACPI_STATUS (status);
441 }
442
443 /* Initialize areas of the object that are specific to the field type */
444
445 switch (info->field_type) {
446 case ACPI_TYPE_LOCAL_REGION_FIELD:
447
448 obj_desc->field.region_obj = acpi_ns_get_attached_object (info->region_node);
449
450 /* An additional reference for the container */
451
452 acpi_ut_add_reference (obj_desc->field.region_obj);
453
454 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
455 "region_field: bit_off %X, Off %X, Gran %X, Region %p\n",
456 obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset,
457 obj_desc->field.access_byte_width, obj_desc->field.region_obj));
458 break;
459
460
461 case ACPI_TYPE_LOCAL_BANK_FIELD:
462
463 obj_desc->bank_field.value = info->bank_value;
464 obj_desc->bank_field.region_obj = acpi_ns_get_attached_object (info->region_node);
465 obj_desc->bank_field.bank_obj = acpi_ns_get_attached_object (info->register_node);
466
467 /* An additional reference for the attached objects */
468
469 acpi_ut_add_reference (obj_desc->bank_field.region_obj);
470 acpi_ut_add_reference (obj_desc->bank_field.bank_obj);
471
472 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
473 "Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n",
474 obj_desc->bank_field.start_field_bit_offset,
475 obj_desc->bank_field.base_byte_offset,
476 obj_desc->field.access_byte_width,
477 obj_desc->bank_field.region_obj,
478 obj_desc->bank_field.bank_obj));
479 break;
480
481
482 case ACPI_TYPE_LOCAL_INDEX_FIELD:
483
484 obj_desc->index_field.index_obj = acpi_ns_get_attached_object (info->register_node);
485 obj_desc->index_field.data_obj = acpi_ns_get_attached_object (info->data_register_node);
486 obj_desc->index_field.value = (u32)
487 (info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width));
488
489 if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) {
490 ACPI_REPORT_ERROR (("Null Index Object during field prep\n"));
491 acpi_ut_delete_object_desc (obj_desc);
492 return_ACPI_STATUS (AE_AML_INTERNAL);
493 }
494
495 /* An additional reference for the attached objects */
496
497 acpi_ut_add_reference (obj_desc->index_field.data_obj);
498 acpi_ut_add_reference (obj_desc->index_field.index_obj);
499
500 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
501 "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
502 obj_desc->index_field.start_field_bit_offset,
503 obj_desc->index_field.base_byte_offset,
504 obj_desc->index_field.value,
505 obj_desc->field.access_byte_width,
506 obj_desc->index_field.index_obj,
507 obj_desc->index_field.data_obj));
508 break;
509
510 default:
511 /* No other types should get here */
512 break;
513 }
514
515 /*
516 * Store the constructed descriptor (obj_desc) into the parent Node,
517 * preserving the current type of that named_obj.
518 */
519 status = acpi_ns_attach_object (info->field_node, obj_desc,
520 acpi_ns_get_type (info->field_node));
521
522 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set named_obj %p [%4.4s], obj_desc %p\n",
523 info->field_node, acpi_ut_get_node_name (info->field_node), obj_desc));
524
525 /* Remove local reference to the object */
526
527 acpi_ut_remove_reference (obj_desc);
528 return_ACPI_STATUS (status);
529}
530
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c
new file mode 100644
index 000000000000..7cfd0684c70b
--- /dev/null
+++ b/drivers/acpi/executer/exregion.c
@@ -0,0 +1,528 @@
1
2/******************************************************************************
3 *
4 * Module Name: exregion - ACPI default op_region (address space) handlers
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acinterp.h>
48
49
50#define _COMPONENT ACPI_EXECUTER
51 ACPI_MODULE_NAME ("exregion")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ex_system_memory_space_handler
57 *
58 * PARAMETERS: Function - Read or Write operation
59 * Address - Where in the space to read or write
60 * bit_width - Field width in bits (8, 16, or 32)
61 * Value - Pointer to in or out value
62 * handler_context - Pointer to Handler's context
63 * region_context - Pointer to context specific to the
64 * accessed region
65 *
66 * RETURN: Status
67 *
68 * DESCRIPTION: Handler for the System Memory address space (Op Region)
69 *
70 ******************************************************************************/
71
72acpi_status
73acpi_ex_system_memory_space_handler (
74 u32 function,
75 acpi_physical_address address,
76 u32 bit_width,
77 acpi_integer *value,
78 void *handler_context,
79 void *region_context)
80{
81 acpi_status status = AE_OK;
82 void *logical_addr_ptr = NULL;
83 struct acpi_mem_space_context *mem_info = region_context;
84 u32 length;
85 acpi_size window_size;
86#ifndef ACPI_MISALIGNED_TRANSFERS
87 u32 remainder;
88#endif
89
90 ACPI_FUNCTION_TRACE ("ex_system_memory_space_handler");
91
92
93 /* Validate and translate the bit width */
94
95 switch (bit_width) {
96 case 8:
97 length = 1;
98 break;
99
100 case 16:
101 length = 2;
102 break;
103
104 case 32:
105 length = 4;
106 break;
107
108 case 64:
109 length = 8;
110 break;
111
112 default:
113 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid system_memory width %d\n",
114 bit_width));
115 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
116 }
117
118
119#ifndef ACPI_MISALIGNED_TRANSFERS
120 /*
121 * Hardware does not support non-aligned data transfers, we must verify
122 * the request.
123 */
124 (void) acpi_ut_short_divide ((acpi_integer) address, length, NULL, &remainder);
125 if (remainder != 0) {
126 return_ACPI_STATUS (AE_AML_ALIGNMENT);
127 }
128#endif
129
130 /*
131 * Does the request fit into the cached memory mapping?
132 * Is 1) Address below the current mapping? OR
133 * 2) Address beyond the current mapping?
134 */
135 if ((address < mem_info->mapped_physical_address) ||
136 (((acpi_integer) address + length) >
137 ((acpi_integer) mem_info->mapped_physical_address + mem_info->mapped_length))) {
138 /*
139 * The request cannot be resolved by the current memory mapping;
140 * Delete the existing mapping and create a new one.
141 */
142 if (mem_info->mapped_length) {
143 /* Valid mapping, delete it */
144
145 acpi_os_unmap_memory (mem_info->mapped_logical_address,
146 mem_info->mapped_length);
147 }
148
149 /*
150 * Don't attempt to map memory beyond the end of the region, and
151 * constrain the maximum mapping size to something reasonable.
152 */
153 window_size = (acpi_size) ((mem_info->address + mem_info->length) - address);
154 if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) {
155 window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE;
156 }
157
158 /* Create a new mapping starting at the address given */
159
160 status = acpi_os_map_memory (address, window_size,
161 (void **) &mem_info->mapped_logical_address);
162 if (ACPI_FAILURE (status)) {
163 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X%8.8X, size %X\n",
164 ACPI_FORMAT_UINT64 (address), (u32) window_size));
165 mem_info->mapped_length = 0;
166 return_ACPI_STATUS (status);
167 }
168
169 /* Save the physical address and mapping size */
170
171 mem_info->mapped_physical_address = address;
172 mem_info->mapped_length = window_size;
173 }
174
175 /*
176 * Generate a logical pointer corresponding to the address we want to
177 * access
178 */
179 logical_addr_ptr = mem_info->mapped_logical_address +
180 ((acpi_integer) address - (acpi_integer) mem_info->mapped_physical_address);
181
182 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
183 "system_memory %d (%d width) Address=%8.8X%8.8X\n", function, bit_width,
184 ACPI_FORMAT_UINT64 (address)));
185
186 /*
187 * Perform the memory read or write
188 *
189 * Note: For machines that do not support non-aligned transfers, the target
190 * address was checked for alignment above. We do not attempt to break the
191 * transfer up into smaller (byte-size) chunks because the AML specifically
192 * asked for a transfer width that the hardware may require.
193 */
194 switch (function) {
195 case ACPI_READ:
196
197 *value = 0;
198 switch (bit_width) {
199 case 8:
200 *value = (acpi_integer) *((u8 *) logical_addr_ptr);
201 break;
202
203 case 16:
204 *value = (acpi_integer) *((u16 *) logical_addr_ptr);
205 break;
206
207 case 32:
208 *value = (acpi_integer) *((u32 *) logical_addr_ptr);
209 break;
210
211#if ACPI_MACHINE_WIDTH != 16
212 case 64:
213 *value = (acpi_integer) *((u64 *) logical_addr_ptr);
214 break;
215#endif
216 default:
217 /* bit_width was already validated */
218 break;
219 }
220 break;
221
222 case ACPI_WRITE:
223
224 switch (bit_width) {
225 case 8:
226 *(u8 *) logical_addr_ptr = (u8) *value;
227 break;
228
229 case 16:
230 *(u16 *) logical_addr_ptr = (u16) *value;
231 break;
232
233 case 32:
234 *(u32 *) logical_addr_ptr = (u32) *value;
235 break;
236
237#if ACPI_MACHINE_WIDTH != 16
238 case 64:
239 *(u64 *) logical_addr_ptr = (u64) *value;
240 break;
241#endif
242
243 default:
244 /* bit_width was already validated */
245 break;
246 }
247 break;
248
249 default:
250 status = AE_BAD_PARAMETER;
251 break;
252 }
253
254 return_ACPI_STATUS (status);
255}
256
257
258/*******************************************************************************
259 *
260 * FUNCTION: acpi_ex_system_io_space_handler
261 *
262 * PARAMETERS: Function - Read or Write operation
263 * Address - Where in the space to read or write
264 * bit_width - Field width in bits (8, 16, or 32)
265 * Value - Pointer to in or out value
266 * handler_context - Pointer to Handler's context
267 * region_context - Pointer to context specific to the
268 * accessed region
269 *
270 * RETURN: Status
271 *
272 * DESCRIPTION: Handler for the System IO address space (Op Region)
273 *
274 ******************************************************************************/
275
276acpi_status
277acpi_ex_system_io_space_handler (
278 u32 function,
279 acpi_physical_address address,
280 u32 bit_width,
281 acpi_integer *value,
282 void *handler_context,
283 void *region_context)
284{
285 acpi_status status = AE_OK;
286 u32 value32;
287
288
289 ACPI_FUNCTION_TRACE ("ex_system_io_space_handler");
290
291
292 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
293 "system_iO %d (%d width) Address=%8.8X%8.8X\n", function, bit_width,
294 ACPI_FORMAT_UINT64 (address)));
295
296 /* Decode the function parameter */
297
298 switch (function) {
299 case ACPI_READ:
300
301 status = acpi_os_read_port ((acpi_io_address) address, &value32, bit_width);
302 *value = value32;
303 break;
304
305 case ACPI_WRITE:
306
307 status = acpi_os_write_port ((acpi_io_address) address, (u32) *value, bit_width);
308 break;
309
310 default:
311 status = AE_BAD_PARAMETER;
312 break;
313 }
314
315 return_ACPI_STATUS (status);
316}
317
318
319/*******************************************************************************
320 *
321 * FUNCTION: acpi_ex_pci_config_space_handler
322 *
323 * PARAMETERS: Function - Read or Write operation
324 * Address - Where in the space to read or write
325 * bit_width - Field width in bits (8, 16, or 32)
326 * Value - Pointer to in or out value
327 * handler_context - Pointer to Handler's context
328 * region_context - Pointer to context specific to the
329 * accessed region
330 *
331 * RETURN: Status
332 *
333 * DESCRIPTION: Handler for the PCI Config address space (Op Region)
334 *
335 ******************************************************************************/
336
337acpi_status
338acpi_ex_pci_config_space_handler (
339 u32 function,
340 acpi_physical_address address,
341 u32 bit_width,
342 acpi_integer *value,
343 void *handler_context,
344 void *region_context)
345{
346 acpi_status status = AE_OK;
347 struct acpi_pci_id *pci_id;
348 u16 pci_register;
349
350
351 ACPI_FUNCTION_TRACE ("ex_pci_config_space_handler");
352
353
354 /*
355 * The arguments to acpi_os(Read|Write)pci_configuration are:
356 *
357 * pci_segment is the PCI bus segment range 0-31
358 * pci_bus is the PCI bus number range 0-255
359 * pci_device is the PCI device number range 0-31
360 * pci_function is the PCI device function number
361 * pci_register is the Config space register range 0-255 bytes
362 *
363 * Value - input value for write, output address for read
364 *
365 */
366 pci_id = (struct acpi_pci_id *) region_context;
367 pci_register = (u16) (u32) address;
368
369 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
370 "pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
371 function, bit_width, pci_id->segment, pci_id->bus, pci_id->device,
372 pci_id->function, pci_register));
373
374 switch (function) {
375 case ACPI_READ:
376
377 *value = 0;
378 status = acpi_os_read_pci_configuration (pci_id, pci_register, value, bit_width);
379 break;
380
381 case ACPI_WRITE:
382
383 status = acpi_os_write_pci_configuration (pci_id, pci_register, *value, bit_width);
384 break;
385
386 default:
387
388 status = AE_BAD_PARAMETER;
389 break;
390 }
391
392 return_ACPI_STATUS (status);
393}
394
395
396/*******************************************************************************
397 *
398 * FUNCTION: acpi_ex_cmos_space_handler
399 *
400 * PARAMETERS: Function - Read or Write operation
401 * Address - Where in the space to read or write
402 * bit_width - Field width in bits (8, 16, or 32)
403 * Value - Pointer to in or out value
404 * handler_context - Pointer to Handler's context
405 * region_context - Pointer to context specific to the
406 * accessed region
407 *
408 * RETURN: Status
409 *
410 * DESCRIPTION: Handler for the CMOS address space (Op Region)
411 *
412 ******************************************************************************/
413
414acpi_status
415acpi_ex_cmos_space_handler (
416 u32 function,
417 acpi_physical_address address,
418 u32 bit_width,
419 acpi_integer *value,
420 void *handler_context,
421 void *region_context)
422{
423 acpi_status status = AE_OK;
424
425
426 ACPI_FUNCTION_TRACE ("ex_cmos_space_handler");
427
428
429 return_ACPI_STATUS (status);
430}
431
432
433/*******************************************************************************
434 *
435 * FUNCTION: acpi_ex_pci_bar_space_handler
436 *
437 * PARAMETERS: Function - Read or Write operation
438 * Address - Where in the space to read or write
439 * bit_width - Field width in bits (8, 16, or 32)
440 * Value - Pointer to in or out value
441 * handler_context - Pointer to Handler's context
442 * region_context - Pointer to context specific to the
443 * accessed region
444 *
445 * RETURN: Status
446 *
447 * DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
448 *
449 ******************************************************************************/
450
451acpi_status
452acpi_ex_pci_bar_space_handler (
453 u32 function,
454 acpi_physical_address address,
455 u32 bit_width,
456 acpi_integer *value,
457 void *handler_context,
458 void *region_context)
459{
460 acpi_status status = AE_OK;
461
462
463 ACPI_FUNCTION_TRACE ("ex_pci_bar_space_handler");
464
465
466 return_ACPI_STATUS (status);
467}
468
469
470/*******************************************************************************
471 *
472 * FUNCTION: acpi_ex_data_table_space_handler
473 *
474 * PARAMETERS: Function - Read or Write operation
475 * Address - Where in the space to read or write
476 * bit_width - Field width in bits (8, 16, or 32)
477 * Value - Pointer to in or out value
478 * handler_context - Pointer to Handler's context
479 * region_context - Pointer to context specific to the
480 * accessed region
481 *
482 * RETURN: Status
483 *
484 * DESCRIPTION: Handler for the Data Table address space (Op Region)
485 *
486 ******************************************************************************/
487
488acpi_status
489acpi_ex_data_table_space_handler (
490 u32 function,
491 acpi_physical_address address,
492 u32 bit_width,
493 acpi_integer *value,
494 void *handler_context,
495 void *region_context)
496{
497 acpi_status status = AE_OK;
498 u32 byte_width = ACPI_DIV_8 (bit_width);
499 u32 i;
500 char *logical_addr_ptr;
501
502
503 ACPI_FUNCTION_TRACE ("ex_data_table_space_handler");
504
505
506 logical_addr_ptr = ACPI_PHYSADDR_TO_PTR (address);
507
508
509 /* Perform the memory read or write */
510
511 switch (function) {
512 case ACPI_READ:
513
514 for (i = 0; i < byte_width; i++) {
515 ((char *) value) [i] = logical_addr_ptr[i];
516 }
517 break;
518
519 case ACPI_WRITE:
520 default:
521
522 return_ACPI_STATUS (AE_SUPPORT);
523 }
524
525 return_ACPI_STATUS (status);
526}
527
528
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c
new file mode 100644
index 000000000000..7936329a0e35
--- /dev/null
+++ b/drivers/acpi/executer/exresnte.c
@@ -0,0 +1,289 @@
1
2/******************************************************************************
3 *
4 * Module Name: exresnte - AML Interpreter object resolution
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acdispat.h>
48#include <acpi/acinterp.h>
49#include <acpi/acnamesp.h>
50#include <acpi/acparser.h>
51#include <acpi/amlcode.h>
52
53
54#define _COMPONENT ACPI_EXECUTER
55 ACPI_MODULE_NAME ("exresnte")
56
57
58/*******************************************************************************
59 *
60 * FUNCTION: acpi_ex_resolve_node_to_value
61 *
62 * PARAMETERS: object_ptr - Pointer to a location that contains
63 * a pointer to a NS node, and will receive a
64 * pointer to the resolved object.
65 * walk_state - Current state. Valid only if executing AML
66 * code. NULL if simply resolving an object
67 *
68 * RETURN: Status
69 *
70 * DESCRIPTION: Resolve a Namespace node to a valued object
71 *
72 * Note: for some of the data types, the pointer attached to the Node
73 * can be either a pointer to an actual internal object or a pointer into the
74 * AML stream itself. These types are currently:
75 *
76 * ACPI_TYPE_INTEGER
77 * ACPI_TYPE_STRING
78 * ACPI_TYPE_BUFFER
79 * ACPI_TYPE_MUTEX
80 * ACPI_TYPE_PACKAGE
81 *
82 ******************************************************************************/
83
84acpi_status
85acpi_ex_resolve_node_to_value (
86 struct acpi_namespace_node **object_ptr,
87 struct acpi_walk_state *walk_state)
88
89{
90 acpi_status status = AE_OK;
91 union acpi_operand_object *source_desc;
92 union acpi_operand_object *obj_desc = NULL;
93 struct acpi_namespace_node *node;
94 acpi_object_type entry_type;
95
96
97 ACPI_FUNCTION_TRACE ("ex_resolve_node_to_value");
98
99
100 /*
101 * The stack pointer points to a struct acpi_namespace_node (Node). Get the
102 * object that is attached to the Node.
103 */
104 node = *object_ptr;
105 source_desc = acpi_ns_get_attached_object (node);
106 entry_type = acpi_ns_get_type ((acpi_handle) node);
107
108 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n",
109 node, source_desc, acpi_ut_get_type_name (entry_type)));
110
111 if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) ||
112 (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
113 /* There is always exactly one level of indirection */
114
115 node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
116 source_desc = acpi_ns_get_attached_object (node);
117 entry_type = acpi_ns_get_type ((acpi_handle) node);
118 *object_ptr = node;
119 }
120
121 /*
122 * Several object types require no further processing:
123 * 1) Devices rarely have an attached object, return the Node
124 * 2) Method locals and arguments have a pseudo-Node
125 */
126 if (entry_type == ACPI_TYPE_DEVICE ||
127 (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
128 return_ACPI_STATUS (AE_OK);
129 }
130
131 if (!source_desc) {
132 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No object attached to node %p\n",
133 node));
134 return_ACPI_STATUS (AE_AML_NO_OPERAND);
135 }
136
137 /*
138 * Action is based on the type of the Node, which indicates the type
139 * of the attached object or pointer
140 */
141 switch (entry_type) {
142 case ACPI_TYPE_PACKAGE:
143
144 if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_PACKAGE) {
145 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Package, type %s\n",
146 acpi_ut_get_object_type_name (source_desc)));
147 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
148 }
149
150 status = acpi_ds_get_package_arguments (source_desc);
151 if (ACPI_SUCCESS (status)) {
152 /* Return an additional reference to the object */
153
154 obj_desc = source_desc;
155 acpi_ut_add_reference (obj_desc);
156 }
157 break;
158
159
160 case ACPI_TYPE_BUFFER:
161
162 if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) {
163 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Buffer, type %s\n",
164 acpi_ut_get_object_type_name (source_desc)));
165 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
166 }
167
168 status = acpi_ds_get_buffer_arguments (source_desc);
169 if (ACPI_SUCCESS (status)) {
170 /* Return an additional reference to the object */
171
172 obj_desc = source_desc;
173 acpi_ut_add_reference (obj_desc);
174 }
175 break;
176
177
178 case ACPI_TYPE_STRING:
179
180 if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) {
181 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a String, type %s\n",
182 acpi_ut_get_object_type_name (source_desc)));
183 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
184 }
185
186 /* Return an additional reference to the object */
187
188 obj_desc = source_desc;
189 acpi_ut_add_reference (obj_desc);
190 break;
191
192
193 case ACPI_TYPE_INTEGER:
194
195 if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) {
196 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Integer, type %s\n",
197 acpi_ut_get_object_type_name (source_desc)));
198 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
199 }
200
201 /* Return an additional reference to the object */
202
203 obj_desc = source_desc;
204 acpi_ut_add_reference (obj_desc);
205 break;
206
207
208 case ACPI_TYPE_BUFFER_FIELD:
209 case ACPI_TYPE_LOCAL_REGION_FIELD:
210 case ACPI_TYPE_LOCAL_BANK_FIELD:
211 case ACPI_TYPE_LOCAL_INDEX_FIELD:
212
213 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "field_read Node=%p source_desc=%p Type=%X\n",
214 node, source_desc, entry_type));
215
216 status = acpi_ex_read_data_from_field (walk_state, source_desc, &obj_desc);
217 break;
218
219 /*
220 * For these objects, just return the object attached to the Node
221 */
222 case ACPI_TYPE_MUTEX:
223 case ACPI_TYPE_METHOD:
224 case ACPI_TYPE_POWER:
225 case ACPI_TYPE_PROCESSOR:
226 case ACPI_TYPE_THERMAL:
227 case ACPI_TYPE_EVENT:
228 case ACPI_TYPE_REGION:
229
230 /* Return an additional reference to the object */
231
232 obj_desc = source_desc;
233 acpi_ut_add_reference (obj_desc);
234 break;
235
236
237 /* TYPE_ANY is untyped, and thus there is no object associated with it */
238
239 case ACPI_TYPE_ANY:
240
241 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Untyped entry %p, no attached object!\n",
242 node));
243
244 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */
245
246
247 case ACPI_TYPE_LOCAL_REFERENCE:
248
249 switch (source_desc->reference.opcode) {
250 case AML_LOAD_OP:
251
252 /* This is a ddb_handle */
253 /* Return an additional reference to the object */
254
255 obj_desc = source_desc;
256 acpi_ut_add_reference (obj_desc);
257 break;
258
259 default:
260 /* No named references are allowed here */
261
262 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported Reference opcode %X (%s)\n",
263 source_desc->reference.opcode,
264 acpi_ps_get_opcode_name (source_desc->reference.opcode)));
265
266 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
267 }
268 break;
269
270
271 /* Default case is for unknown types */
272
273 default:
274
275 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Node %p - Unknown object type %X\n",
276 node, entry_type));
277
278 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
279
280 } /* switch (entry_type) */
281
282
283 /* Put the object descriptor on the stack */
284
285 *object_ptr = (void *) obj_desc;
286 return_ACPI_STATUS (status);
287}
288
289
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
new file mode 100644
index 000000000000..7be604911156
--- /dev/null
+++ b/drivers/acpi/executer/exresolv.c
@@ -0,0 +1,546 @@
1
2/******************************************************************************
3 *
4 * Module Name: exresolv - AML Interpreter object resolution
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/amlcode.h>
48#include <acpi/acdispat.h>
49#include <acpi/acinterp.h>
50#include <acpi/acnamesp.h>
51#include <acpi/acparser.h>
52
53
54#define _COMPONENT ACPI_EXECUTER
55 ACPI_MODULE_NAME ("exresolv")
56
57
58/*******************************************************************************
59 *
60 * FUNCTION: acpi_ex_resolve_to_value
61 *
62 * PARAMETERS: **stack_ptr - Points to entry on obj_stack, which can
63 * be either an (union acpi_operand_object *)
64 * or an acpi_handle.
65 * walk_state - Current method state
66 *
67 * RETURN: Status
68 *
69 * DESCRIPTION: Convert Reference objects to values
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_ex_resolve_to_value (
75 union acpi_operand_object **stack_ptr,
76 struct acpi_walk_state *walk_state)
77{
78 acpi_status status;
79
80
81 ACPI_FUNCTION_TRACE_PTR ("ex_resolve_to_value", stack_ptr);
82
83
84 if (!stack_ptr || !*stack_ptr) {
85 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null pointer\n"));
86 return_ACPI_STATUS (AE_AML_NO_OPERAND);
87 }
88
89 /*
90 * The entity pointed to by the stack_ptr can be either
91 * 1) A valid union acpi_operand_object, or
92 * 2) A struct acpi_namespace_node (named_obj)
93 */
94 if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
95 status = acpi_ex_resolve_object_to_value (stack_ptr, walk_state);
96 if (ACPI_FAILURE (status)) {
97 return_ACPI_STATUS (status);
98 }
99 }
100
101 /*
102 * Object on the stack may have changed if acpi_ex_resolve_object_to_value()
103 * was called (i.e., we can't use an _else_ here.)
104 */
105 if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
106 status = acpi_ex_resolve_node_to_value (
107 ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, stack_ptr),
108 walk_state);
109 if (ACPI_FAILURE (status)) {
110 return_ACPI_STATUS (status);
111 }
112 }
113
114 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
115 return_ACPI_STATUS (AE_OK);
116}
117
118
119/*******************************************************************************
120 *
121 * FUNCTION: acpi_ex_resolve_object_to_value
122 *
123 * PARAMETERS: stack_ptr - Pointer to a stack location that contains a
124 * ptr to an internal object.
125 * walk_state - Current method state
126 *
127 * RETURN: Status
128 *
129 * DESCRIPTION: Retrieve the value from an internal object. The Reference type
130 * uses the associated AML opcode to determine the value.
131 *
132 ******************************************************************************/
133
134acpi_status
135acpi_ex_resolve_object_to_value (
136 union acpi_operand_object **stack_ptr,
137 struct acpi_walk_state *walk_state)
138{
139 acpi_status status = AE_OK;
140 union acpi_operand_object *stack_desc;
141 void *temp_node;
142 union acpi_operand_object *obj_desc;
143 u16 opcode;
144
145
146 ACPI_FUNCTION_TRACE ("ex_resolve_object_to_value");
147
148
149 stack_desc = *stack_ptr;
150
151 /* This is an union acpi_operand_object */
152
153 switch (ACPI_GET_OBJECT_TYPE (stack_desc)) {
154 case ACPI_TYPE_LOCAL_REFERENCE:
155
156 opcode = stack_desc->reference.opcode;
157
158 switch (opcode) {
159 case AML_NAME_OP:
160
161 /*
162 * Convert indirect name ptr to a direct name ptr.
163 * Then, acpi_ex_resolve_node_to_value can be used to get the value
164 */
165 temp_node = stack_desc->reference.object;
166
167 /* Delete the Reference Object */
168
169 acpi_ut_remove_reference (stack_desc);
170
171 /* Put direct name pointer onto stack and exit */
172
173 (*stack_ptr) = temp_node;
174 break;
175
176
177 case AML_LOCAL_OP:
178 case AML_ARG_OP:
179
180 /*
181 * Get the local from the method's state info
182 * Note: this increments the local's object reference count
183 */
184 status = acpi_ds_method_data_get_value (opcode,
185 stack_desc->reference.offset, walk_state, &obj_desc);
186 if (ACPI_FAILURE (status)) {
187 return_ACPI_STATUS (status);
188 }
189
190 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] value_obj is %p\n",
191 stack_desc->reference.offset, obj_desc));
192
193 /*
194 * Now we can delete the original Reference Object and
195 * replace it with the resolved value
196 */
197 acpi_ut_remove_reference (stack_desc);
198 *stack_ptr = obj_desc;
199 break;
200
201
202 case AML_INDEX_OP:
203
204 switch (stack_desc->reference.target_type) {
205 case ACPI_TYPE_BUFFER_FIELD:
206
207 /* Just return - leave the Reference on the stack */
208 break;
209
210
211 case ACPI_TYPE_PACKAGE:
212
213 obj_desc = *stack_desc->reference.where;
214 if (obj_desc) {
215 /*
216 * Valid obj descriptor, copy pointer to return value
217 * (i.e., dereference the package index)
218 * Delete the ref object, increment the returned object
219 */
220 acpi_ut_remove_reference (stack_desc);
221 acpi_ut_add_reference (obj_desc);
222 *stack_ptr = obj_desc;
223 }
224 else {
225 /*
226 * A NULL object descriptor means an unitialized element of
227 * the package, can't dereference it
228 */
229 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
230 "Attempt to deref an Index to NULL pkg element Idx=%p\n",
231 stack_desc));
232 status = AE_AML_UNINITIALIZED_ELEMENT;
233 }
234 break;
235
236
237 default:
238
239 /* Invalid reference object */
240
241 ACPI_REPORT_ERROR ((
242 "During resolve, Unknown target_type %X in Index/Reference obj %p\n",
243 stack_desc->reference.target_type, stack_desc));
244 status = AE_AML_INTERNAL;
245 break;
246 }
247 break;
248
249
250 case AML_REF_OF_OP:
251 case AML_DEBUG_OP:
252 case AML_LOAD_OP:
253
254 /* Just leave the object as-is */
255
256 break;
257
258
259 default:
260
261 ACPI_REPORT_ERROR (("During resolve, Unknown Reference opcode %X (%s) in %p\n",
262 opcode, acpi_ps_get_opcode_name (opcode), stack_desc));
263 status = AE_AML_INTERNAL;
264 break;
265 }
266 break;
267
268
269 case ACPI_TYPE_BUFFER:
270
271 status = acpi_ds_get_buffer_arguments (stack_desc);
272 break;
273
274
275 case ACPI_TYPE_PACKAGE:
276
277 status = acpi_ds_get_package_arguments (stack_desc);
278 break;
279
280
281 /*
282 * These cases may never happen here, but just in case..
283 */
284 case ACPI_TYPE_BUFFER_FIELD:
285 case ACPI_TYPE_LOCAL_REGION_FIELD:
286 case ACPI_TYPE_LOCAL_BANK_FIELD:
287 case ACPI_TYPE_LOCAL_INDEX_FIELD:
288
289 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "field_read source_desc=%p Type=%X\n",
290 stack_desc, ACPI_GET_OBJECT_TYPE (stack_desc)));
291
292 status = acpi_ex_read_data_from_field (walk_state, stack_desc, &obj_desc);
293 *stack_ptr = (void *) obj_desc;
294 break;
295
296 default:
297 break;
298 }
299
300 return_ACPI_STATUS (status);
301}
302
303
304/*******************************************************************************
305 *
306 * FUNCTION: acpi_ex_resolve_multiple
307 *
308 * PARAMETERS: walk_state - Current state (contains AML opcode)
309 * Operand - Starting point for resolution
310 * return_type - Where the object type is returned
311 * return_desc - Where the resolved object is returned
312 *
313 * RETURN: Status
314 *
315 * DESCRIPTION: Return the base object and type. Traverse a reference list if
316 * necessary to get to the base object.
317 *
318 ******************************************************************************/
319
320acpi_status
321acpi_ex_resolve_multiple (
322 struct acpi_walk_state *walk_state,
323 union acpi_operand_object *operand,
324 acpi_object_type *return_type,
325 union acpi_operand_object **return_desc)
326{
327 union acpi_operand_object *obj_desc = (void *) operand;
328 struct acpi_namespace_node *node;
329 acpi_object_type type;
330 acpi_status status;
331
332
333 ACPI_FUNCTION_TRACE ("acpi_ex_resolve_multiple");
334
335
336 /*
337 * Operand can be either a namespace node or an operand descriptor
338 */
339 switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
340 case ACPI_DESC_TYPE_OPERAND:
341 type = obj_desc->common.type;
342 break;
343
344 case ACPI_DESC_TYPE_NAMED:
345 type = ((struct acpi_namespace_node *) obj_desc)->type;
346 obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc);
347
348 /* If we had an Alias node, use the attached object for type info */
349
350 if (type == ACPI_TYPE_LOCAL_ALIAS) {
351 type = ((struct acpi_namespace_node *) obj_desc)->type;
352 obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc);
353 }
354 break;
355
356 default:
357 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
358 }
359
360
361 /*
362 * If type is anything other than a reference, we are done
363 */
364 if (type != ACPI_TYPE_LOCAL_REFERENCE) {
365 goto exit;
366 }
367
368 /*
369 * For reference objects created via the ref_of or Index operators,
370 * we need to get to the base object (as per the ACPI specification
371 * of the object_type and size_of operators). This means traversing
372 * the list of possibly many nested references.
373 */
374 while (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
375 switch (obj_desc->reference.opcode) {
376 case AML_REF_OF_OP:
377
378 /* Dereference the reference pointer */
379
380 node = obj_desc->reference.object;
381
382 /* All "References" point to a NS node */
383
384 if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
385 ACPI_REPORT_ERROR (("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n",
386 node, acpi_ut_get_descriptor_name (node)));
387 return_ACPI_STATUS (AE_AML_INTERNAL);
388 }
389
390 /* Get the attached object */
391
392 obj_desc = acpi_ns_get_attached_object (node);
393 if (!obj_desc) {
394 /* No object, use the NS node type */
395
396 type = acpi_ns_get_type (node);
397 goto exit;
398 }
399
400 /* Check for circular references */
401
402 if (obj_desc == operand) {
403 return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE);
404 }
405 break;
406
407
408 case AML_INDEX_OP:
409
410 /* Get the type of this reference (index into another object) */
411
412 type = obj_desc->reference.target_type;
413 if (type != ACPI_TYPE_PACKAGE) {
414 goto exit;
415 }
416
417 /*
418 * The main object is a package, we want to get the type
419 * of the individual package element that is referenced by
420 * the index.
421 *
422 * This could of course in turn be another reference object.
423 */
424 obj_desc = *(obj_desc->reference.where);
425 if (!obj_desc) {
426 /* NULL package elements are allowed */
427
428 type = 0; /* Uninitialized */
429 goto exit;
430 }
431 break;
432
433
434 case AML_INT_NAMEPATH_OP:
435
436 /* Dereference the reference pointer */
437
438 node = obj_desc->reference.node;
439
440 /* All "References" point to a NS node */
441
442 if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
443 ACPI_REPORT_ERROR (("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n",
444 node, acpi_ut_get_descriptor_name (node)));
445 return_ACPI_STATUS (AE_AML_INTERNAL);
446 }
447
448 /* Get the attached object */
449
450 obj_desc = acpi_ns_get_attached_object (node);
451 if (!obj_desc) {
452 /* No object, use the NS node type */
453
454 type = acpi_ns_get_type (node);
455 goto exit;
456 }
457
458 /* Check for circular references */
459
460 if (obj_desc == operand) {
461 return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE);
462 }
463 break;
464
465
466 case AML_LOCAL_OP:
467 case AML_ARG_OP:
468
469 if (return_desc) {
470 status = acpi_ds_method_data_get_value (obj_desc->reference.opcode,
471 obj_desc->reference.offset, walk_state, &obj_desc);
472 if (ACPI_FAILURE (status)) {
473 return_ACPI_STATUS (status);
474 }
475 acpi_ut_remove_reference (obj_desc);
476 }
477 else {
478 status = acpi_ds_method_data_get_node (obj_desc->reference.opcode,
479 obj_desc->reference.offset, walk_state, &node);
480 if (ACPI_FAILURE (status)) {
481 return_ACPI_STATUS (status);
482 }
483
484 obj_desc = acpi_ns_get_attached_object (node);
485 if (!obj_desc) {
486 type = ACPI_TYPE_ANY;
487 goto exit;
488 }
489 }
490 break;
491
492
493 case AML_DEBUG_OP:
494
495 /* The Debug Object is of type "debug_object" */
496
497 type = ACPI_TYPE_DEBUG_OBJECT;
498 goto exit;
499
500
501 default:
502
503 ACPI_REPORT_ERROR (("acpi_ex_resolve_multiple: Unknown Reference subtype %X\n",
504 obj_desc->reference.opcode));
505 return_ACPI_STATUS (AE_AML_INTERNAL);
506 }
507 }
508
509 /*
510 * Now we are guaranteed to have an object that has not been created
511 * via the ref_of or Index operators.
512 */
513 type = ACPI_GET_OBJECT_TYPE (obj_desc);
514
515
516exit:
517 /* Convert internal types to external types */
518
519 switch (type) {
520 case ACPI_TYPE_LOCAL_REGION_FIELD:
521 case ACPI_TYPE_LOCAL_BANK_FIELD:
522 case ACPI_TYPE_LOCAL_INDEX_FIELD:
523
524 type = ACPI_TYPE_FIELD_UNIT;
525 break;
526
527 case ACPI_TYPE_LOCAL_SCOPE:
528
529 /* Per ACPI Specification, Scope is untyped */
530
531 type = ACPI_TYPE_ANY;
532 break;
533
534 default:
535 /* No change to Type required */
536 break;
537 }
538
539 *return_type = type;
540 if (return_desc) {
541 *return_desc = obj_desc;
542 }
543 return_ACPI_STATUS (AE_OK);
544}
545
546
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
new file mode 100644
index 000000000000..c92890220c32
--- /dev/null
+++ b/drivers/acpi/executer/exresop.c
@@ -0,0 +1,661 @@
1
2/******************************************************************************
3 *
4 * Module Name: exresop - AML Interpreter operand/object resolution
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/amlcode.h>
48#include <acpi/acparser.h>
49#include <acpi/acinterp.h>
50
51
52#define _COMPONENT ACPI_EXECUTER
53 ACPI_MODULE_NAME ("exresop")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_ex_check_object_type
59 *
60 * PARAMETERS: type_needed Object type needed
61 * this_type Actual object type
62 * Object Object pointer
63 *
64 * RETURN: Status
65 *
66 * DESCRIPTION: Check required type against actual type
67 *
68 ******************************************************************************/
69
70acpi_status
71acpi_ex_check_object_type (
72 acpi_object_type type_needed,
73 acpi_object_type this_type,
74 void *object)
75{
76 ACPI_FUNCTION_NAME ("ex_check_object_type");
77
78
79 if (type_needed == ACPI_TYPE_ANY) {
80 /* All types OK, so we don't perform any typechecks */
81
82 return (AE_OK);
83 }
84
85 if (type_needed == ACPI_TYPE_LOCAL_REFERENCE) {
86 /*
87 * Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference
88 * objects and thus allow them to be targets. (As per the ACPI
89 * specification, a store to a constant is a noop.)
90 */
91 if ((this_type == ACPI_TYPE_INTEGER) &&
92 (((union acpi_operand_object *) object)->common.flags & AOPOBJ_AML_CONSTANT)) {
93 return (AE_OK);
94 }
95 }
96
97 if (type_needed != this_type) {
98 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
99 "Needed [%s], found [%s] %p\n",
100 acpi_ut_get_type_name (type_needed),
101 acpi_ut_get_type_name (this_type), object));
102
103 return (AE_AML_OPERAND_TYPE);
104 }
105
106 return (AE_OK);
107}
108
109
110/*******************************************************************************
111 *
112 * FUNCTION: acpi_ex_resolve_operands
113 *
114 * PARAMETERS: Opcode - Opcode being interpreted
115 * stack_ptr - Pointer to the operand stack to be
116 * resolved
117 * walk_state - Current state
118 *
119 * RETURN: Status
120 *
121 * DESCRIPTION: Convert multiple input operands to the types required by the
122 * target operator.
123 *
124 * Each 5-bit group in arg_types represents one required
125 * operand and indicates the required Type. The corresponding operand
126 * will be converted to the required type if possible, otherwise we
127 * abort with an exception.
128 *
129 ******************************************************************************/
130
131acpi_status
132acpi_ex_resolve_operands (
133 u16 opcode,
134 union acpi_operand_object **stack_ptr,
135 struct acpi_walk_state *walk_state)
136{
137 union acpi_operand_object *obj_desc;
138 acpi_status status = AE_OK;
139 u8 object_type;
140 void *temp_node;
141 u32 arg_types;
142 const struct acpi_opcode_info *op_info;
143 u32 this_arg_type;
144 acpi_object_type type_needed;
145
146
147 ACPI_FUNCTION_TRACE_U32 ("ex_resolve_operands", opcode);
148
149
150 op_info = acpi_ps_get_opcode_info (opcode);
151 if (op_info->class == AML_CLASS_UNKNOWN) {
152 return_ACPI_STATUS (AE_AML_BAD_OPCODE);
153 }
154
155 arg_types = op_info->runtime_args;
156 if (arg_types == ARGI_INVALID_OPCODE) {
157 ACPI_REPORT_ERROR (("resolve_operands: %X is not a valid AML opcode\n",
158 opcode));
159
160 return_ACPI_STATUS (AE_AML_INTERNAL);
161 }
162
163 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode %X [%s] required_operand_types=%8.8X \n",
164 opcode, op_info->name, arg_types));
165
166 /*
167 * Normal exit is with (arg_types == 0) at end of argument list.
168 * Function will return an exception from within the loop upon
169 * finding an entry which is not (or cannot be converted
170 * to) the required type; if stack underflows; or upon
171 * finding a NULL stack entry (which should not happen).
172 */
173 while (GET_CURRENT_ARG_TYPE (arg_types)) {
174 if (!stack_ptr || !*stack_ptr) {
175 ACPI_REPORT_ERROR (("resolve_operands: Null stack entry at %p\n",
176 stack_ptr));
177
178 return_ACPI_STATUS (AE_AML_INTERNAL);
179 }
180
181 /* Extract useful items */
182
183 obj_desc = *stack_ptr;
184
185 /* Decode the descriptor type */
186
187 switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
188 case ACPI_DESC_TYPE_NAMED:
189
190 /* Node */
191
192 object_type = ((struct acpi_namespace_node *) obj_desc)->type;
193 break;
194
195
196 case ACPI_DESC_TYPE_OPERAND:
197
198 /* ACPI internal object */
199
200 object_type = ACPI_GET_OBJECT_TYPE (obj_desc);
201
202 /* Check for bad acpi_object_type */
203
204 if (!acpi_ut_valid_object_type (object_type)) {
205 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad operand object type [%X]\n",
206 object_type));
207
208 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
209 }
210
211 if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) {
212 /*
213 * Decode the Reference
214 */
215 op_info = acpi_ps_get_opcode_info (opcode);
216 if (op_info->class == AML_CLASS_UNKNOWN) {
217 return_ACPI_STATUS (AE_AML_BAD_OPCODE);
218 }
219
220 switch (obj_desc->reference.opcode) {
221 case AML_DEBUG_OP:
222 case AML_NAME_OP:
223 case AML_INDEX_OP:
224 case AML_REF_OF_OP:
225 case AML_ARG_OP:
226 case AML_LOCAL_OP:
227 case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */
228
229 ACPI_DEBUG_ONLY_MEMBERS (ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
230 "Operand is a Reference, ref_opcode [%s]\n",
231 (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name)));
232 break;
233
234 default:
235 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
236 "Operand is a Reference, Unknown Reference Opcode %X [%s]\n",
237 obj_desc->reference.opcode,
238 (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name));
239
240 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
241 }
242 }
243 break;
244
245
246 default:
247
248 /* Invalid descriptor */
249
250 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
251 "Invalid descriptor %p [%s]\n",
252 obj_desc, acpi_ut_get_descriptor_name (obj_desc)));
253
254 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
255 }
256
257
258 /*
259 * Get one argument type, point to the next
260 */
261 this_arg_type = GET_CURRENT_ARG_TYPE (arg_types);
262 INCREMENT_ARG_LIST (arg_types);
263
264 /*
265 * Handle cases where the object does not need to be
266 * resolved to a value
267 */
268 switch (this_arg_type) {
269 case ARGI_REF_OR_STRING: /* Can be a String or Reference */
270
271 if ((ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) &&
272 (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_STRING)) {
273 /*
274 * String found - the string references a named object and must be
275 * resolved to a node
276 */
277 goto next_operand;
278 }
279
280 /* Else not a string - fall through to the normal Reference case below */
281 /*lint -fallthrough */
282
283 case ARGI_REFERENCE: /* References: */
284 case ARGI_INTEGER_REF:
285 case ARGI_OBJECT_REF:
286 case ARGI_DEVICE_REF:
287 case ARGI_TARGETREF: /* Allows implicit conversion rules before store */
288 case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */
289 case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */
290
291 /* Need an operand of type ACPI_TYPE_LOCAL_REFERENCE */
292
293 if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) /* Node (name) ptr OK as-is */ {
294 goto next_operand;
295 }
296
297 status = acpi_ex_check_object_type (ACPI_TYPE_LOCAL_REFERENCE,
298 object_type, obj_desc);
299 if (ACPI_FAILURE (status)) {
300 return_ACPI_STATUS (status);
301 }
302
303 if (AML_NAME_OP == obj_desc->reference.opcode) {
304 /*
305 * Convert an indirect name ptr to direct name ptr and put
306 * it on the stack
307 */
308 temp_node = obj_desc->reference.object;
309 acpi_ut_remove_reference (obj_desc);
310 (*stack_ptr) = temp_node;
311 }
312 goto next_operand;
313
314
315 case ARGI_DATAREFOBJ: /* Store operator only */
316
317 /*
318 * We don't want to resolve index_op reference objects during
319 * a store because this would be an implicit de_ref_of operation.
320 * Instead, we just want to store the reference object.
321 * -- All others must be resolved below.
322 */
323 if ((opcode == AML_STORE_OP) &&
324 (ACPI_GET_OBJECT_TYPE (*stack_ptr) == ACPI_TYPE_LOCAL_REFERENCE) &&
325 ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) {
326 goto next_operand;
327 }
328 break;
329
330 default:
331 /* All cases covered above */
332 break;
333 }
334
335
336 /*
337 * Resolve this object to a value
338 */
339 status = acpi_ex_resolve_to_value (stack_ptr, walk_state);
340 if (ACPI_FAILURE (status)) {
341 return_ACPI_STATUS (status);
342 }
343
344 /* Get the resolved object */
345
346 obj_desc = *stack_ptr;
347
348 /*
349 * Check the resulting object (value) type
350 */
351 switch (this_arg_type) {
352 /*
353 * For the simple cases, only one type of resolved object
354 * is allowed
355 */
356 case ARGI_MUTEX:
357
358 /* Need an operand of type ACPI_TYPE_MUTEX */
359
360 type_needed = ACPI_TYPE_MUTEX;
361 break;
362
363 case ARGI_EVENT:
364
365 /* Need an operand of type ACPI_TYPE_EVENT */
366
367 type_needed = ACPI_TYPE_EVENT;
368 break;
369
370 case ARGI_PACKAGE: /* Package */
371
372 /* Need an operand of type ACPI_TYPE_PACKAGE */
373
374 type_needed = ACPI_TYPE_PACKAGE;
375 break;
376
377 case ARGI_ANYTYPE:
378
379 /* Any operand type will do */
380
381 type_needed = ACPI_TYPE_ANY;
382 break;
383
384 case ARGI_DDBHANDLE:
385
386 /* Need an operand of type ACPI_TYPE_DDB_HANDLE */
387
388 type_needed = ACPI_TYPE_LOCAL_REFERENCE;
389 break;
390
391
392 /*
393 * The more complex cases allow multiple resolved object types
394 */
395 case ARGI_INTEGER: /* Number */
396
397 /*
398 * Need an operand of type ACPI_TYPE_INTEGER,
399 * But we can implicitly convert from a STRING or BUFFER
400 * Aka - "Implicit Source Operand Conversion"
401 */
402 status = acpi_ex_convert_to_integer (obj_desc, stack_ptr, 16);
403 if (ACPI_FAILURE (status)) {
404 if (status == AE_TYPE) {
405 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
406 "Needed [Integer/String/Buffer], found [%s] %p\n",
407 acpi_ut_get_object_type_name (obj_desc), obj_desc));
408
409 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
410 }
411
412 return_ACPI_STATUS (status);
413 }
414 goto next_operand;
415
416
417 case ARGI_BUFFER:
418
419 /*
420 * Need an operand of type ACPI_TYPE_BUFFER,
421 * But we can implicitly convert from a STRING or INTEGER
422 * Aka - "Implicit Source Operand Conversion"
423 */
424 status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr);
425 if (ACPI_FAILURE (status)) {
426 if (status == AE_TYPE) {
427 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
428 "Needed [Integer/String/Buffer], found [%s] %p\n",
429 acpi_ut_get_object_type_name (obj_desc), obj_desc));
430
431 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
432 }
433
434 return_ACPI_STATUS (status);
435 }
436 goto next_operand;
437
438
439 case ARGI_STRING:
440
441 /*
442 * Need an operand of type ACPI_TYPE_STRING,
443 * But we can implicitly convert from a BUFFER or INTEGER
444 * Aka - "Implicit Source Operand Conversion"
445 */
446 status = acpi_ex_convert_to_string (obj_desc, stack_ptr,
447 ACPI_IMPLICIT_CONVERT_HEX);
448 if (ACPI_FAILURE (status)) {
449 if (status == AE_TYPE) {
450 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
451 "Needed [Integer/String/Buffer], found [%s] %p\n",
452 acpi_ut_get_object_type_name (obj_desc), obj_desc));
453
454 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
455 }
456
457 return_ACPI_STATUS (status);
458 }
459 goto next_operand;
460
461
462 case ARGI_COMPUTEDATA:
463
464 /* Need an operand of type INTEGER, STRING or BUFFER */
465
466 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
467 case ACPI_TYPE_INTEGER:
468 case ACPI_TYPE_STRING:
469 case ACPI_TYPE_BUFFER:
470
471 /* Valid operand */
472 break;
473
474 default:
475 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
476 "Needed [Integer/String/Buffer], found [%s] %p\n",
477 acpi_ut_get_object_type_name (obj_desc), obj_desc));
478
479 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
480 }
481 goto next_operand;
482
483
484 case ARGI_BUFFER_OR_STRING:
485
486 /* Need an operand of type STRING or BUFFER */
487
488 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
489 case ACPI_TYPE_STRING:
490 case ACPI_TYPE_BUFFER:
491
492 /* Valid operand */
493 break;
494
495 case ACPI_TYPE_INTEGER:
496
497 /* Highest priority conversion is to type Buffer */
498
499 status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr);
500 if (ACPI_FAILURE (status)) {
501 return_ACPI_STATUS (status);
502 }
503 break;
504
505 default:
506 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
507 "Needed [Integer/String/Buffer], found [%s] %p\n",
508 acpi_ut_get_object_type_name (obj_desc), obj_desc));
509
510 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
511 }
512 goto next_operand;
513
514
515 case ARGI_DATAOBJECT:
516 /*
517 * ARGI_DATAOBJECT is only used by the size_of operator.
518 * Need a buffer, string, package, or ref_of reference.
519 *
520 * The only reference allowed here is a direct reference to
521 * a namespace node.
522 */
523 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
524 case ACPI_TYPE_PACKAGE:
525 case ACPI_TYPE_STRING:
526 case ACPI_TYPE_BUFFER:
527 case ACPI_TYPE_LOCAL_REFERENCE:
528
529 /* Valid operand */
530 break;
531
532 default:
533 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
534 "Needed [Buffer/String/Package/Reference], found [%s] %p\n",
535 acpi_ut_get_object_type_name (obj_desc), obj_desc));
536
537 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
538 }
539 goto next_operand;
540
541
542 case ARGI_COMPLEXOBJ:
543
544 /* Need a buffer or package or (ACPI 2.0) String */
545
546 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
547 case ACPI_TYPE_PACKAGE:
548 case ACPI_TYPE_STRING:
549 case ACPI_TYPE_BUFFER:
550
551 /* Valid operand */
552 break;
553
554 default:
555 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
556 "Needed [Buffer/String/Package], found [%s] %p\n",
557 acpi_ut_get_object_type_name (obj_desc), obj_desc));
558
559 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
560 }
561 goto next_operand;
562
563
564 case ARGI_REGION_OR_FIELD:
565
566 /* Need an operand of type ACPI_TYPE_REGION or a FIELD in a region */
567
568 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
569 case ACPI_TYPE_REGION:
570 case ACPI_TYPE_LOCAL_REGION_FIELD:
571 case ACPI_TYPE_LOCAL_BANK_FIELD:
572 case ACPI_TYPE_LOCAL_INDEX_FIELD:
573
574 /* Valid operand */
575 break;
576
577 default:
578 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
579 "Needed [Region/region_field], found [%s] %p\n",
580 acpi_ut_get_object_type_name (obj_desc), obj_desc));
581
582 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
583 }
584 goto next_operand;
585
586
587 case ARGI_DATAREFOBJ:
588
589 /* Used by the Store() operator only */
590
591 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
592 case ACPI_TYPE_INTEGER:
593 case ACPI_TYPE_PACKAGE:
594 case ACPI_TYPE_STRING:
595 case ACPI_TYPE_BUFFER:
596 case ACPI_TYPE_BUFFER_FIELD:
597 case ACPI_TYPE_LOCAL_REFERENCE:
598 case ACPI_TYPE_LOCAL_REGION_FIELD:
599 case ACPI_TYPE_LOCAL_BANK_FIELD:
600 case ACPI_TYPE_LOCAL_INDEX_FIELD:
601 case ACPI_TYPE_DDB_HANDLE:
602
603 /* Valid operand */
604 break;
605
606 default:
607
608 if (acpi_gbl_enable_interpreter_slack) {
609 /*
610 * Enable original behavior of Store(), allowing any and all
611 * objects as the source operand. The ACPI spec does not
612 * allow this, however.
613 */
614 break;
615 }
616
617 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
618 "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p\n",
619 acpi_ut_get_object_type_name (obj_desc), obj_desc));
620
621 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
622 }
623 goto next_operand;
624
625
626 default:
627
628 /* Unknown type */
629
630 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
631 "Internal - Unknown ARGI (required operand) type %X\n",
632 this_arg_type));
633
634 return_ACPI_STATUS (AE_BAD_PARAMETER);
635 }
636
637 /*
638 * Make sure that the original object was resolved to the
639 * required object type (Simple cases only).
640 */
641 status = acpi_ex_check_object_type (type_needed,
642 ACPI_GET_OBJECT_TYPE (*stack_ptr), *stack_ptr);
643 if (ACPI_FAILURE (status)) {
644 return_ACPI_STATUS (status);
645 }
646
647next_operand:
648 /*
649 * If more operands needed, decrement stack_ptr to point
650 * to next operand on stack
651 */
652 if (GET_CURRENT_ARG_TYPE (arg_types)) {
653 stack_ptr--;
654 }
655
656 } /* while (*Types) */
657
658 return_ACPI_STATUS (status);
659}
660
661
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
new file mode 100644
index 000000000000..e0fc6aba1253
--- /dev/null
+++ b/drivers/acpi/executer/exstore.c
@@ -0,0 +1,536 @@
1
2/******************************************************************************
3 *
4 * Module Name: exstore - AML Interpreter object store support
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acdispat.h>
48#include <acpi/acinterp.h>
49#include <acpi/amlcode.h>
50#include <acpi/acnamesp.h>
51
52
53#define _COMPONENT ACPI_EXECUTER
54 ACPI_MODULE_NAME ("exstore")
55
56
57/*******************************************************************************
58 *
59 * FUNCTION: acpi_ex_store
60 *
61 * PARAMETERS: *source_desc - Value to be stored
62 * *dest_desc - Where to store it. Must be an NS node
63 * or an union acpi_operand_object of type
64 * Reference;
65 * walk_state - Current walk state
66 *
67 * RETURN: Status
68 *
69 * DESCRIPTION: Store the value described by source_desc into the location
70 * described by dest_desc. Called by various interpreter
71 * functions to store the result of an operation into
72 * the destination operand -- not just simply the actual "Store"
73 * ASL operator.
74 *
75 ******************************************************************************/
76
77acpi_status
78acpi_ex_store (
79 union acpi_operand_object *source_desc,
80 union acpi_operand_object *dest_desc,
81 struct acpi_walk_state *walk_state)
82{
83 acpi_status status = AE_OK;
84 union acpi_operand_object *ref_desc = dest_desc;
85
86
87 ACPI_FUNCTION_TRACE_PTR ("ex_store", dest_desc);
88
89
90 /* Validate parameters */
91
92 if (!source_desc || !dest_desc) {
93 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null parameter\n"));
94 return_ACPI_STATUS (AE_AML_NO_OPERAND);
95 }
96
97 /* dest_desc can be either a namespace node or an ACPI object */
98
99 if (ACPI_GET_DESCRIPTOR_TYPE (dest_desc) == ACPI_DESC_TYPE_NAMED) {
100 /*
101 * Dest is a namespace node,
102 * Storing an object into a Named node.
103 */
104 status = acpi_ex_store_object_to_node (source_desc,
105 (struct acpi_namespace_node *) dest_desc, walk_state,
106 ACPI_IMPLICIT_CONVERSION);
107
108 return_ACPI_STATUS (status);
109 }
110
111 /* Destination object must be a Reference or a Constant object */
112
113 switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
114 case ACPI_TYPE_LOCAL_REFERENCE:
115 break;
116
117 case ACPI_TYPE_INTEGER:
118
119 /* Allow stores to Constants -- a Noop as per ACPI spec */
120
121 if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) {
122 return_ACPI_STATUS (AE_OK);
123 }
124
125 /*lint -fallthrough */
126
127 default:
128
129 /* Destination is not a Reference object */
130
131 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
132 "Target is not a Reference or Constant object - %s [%p]\n",
133 acpi_ut_get_object_type_name (dest_desc), dest_desc));
134
135 ACPI_DUMP_STACK_ENTRY (source_desc);
136 ACPI_DUMP_STACK_ENTRY (dest_desc);
137 ACPI_DUMP_OPERANDS (&dest_desc, ACPI_IMODE_EXECUTE, "ex_store",
138 2, "Target is not a Reference or Constant object");
139
140 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
141 }
142
143 /*
144 * Examine the Reference opcode. These cases are handled:
145 *
146 * 1) Store to Name (Change the object associated with a name)
147 * 2) Store to an indexed area of a Buffer or Package
148 * 3) Store to a Method Local or Arg
149 * 4) Store to the debug object
150 */
151 switch (ref_desc->reference.opcode) {
152 case AML_NAME_OP:
153 case AML_REF_OF_OP:
154
155 /* Storing an object into a Name "container" */
156
157 status = acpi_ex_store_object_to_node (source_desc, ref_desc->reference.object,
158 walk_state, ACPI_IMPLICIT_CONVERSION);
159 break;
160
161
162 case AML_INDEX_OP:
163
164 /* Storing to an Index (pointer into a packager or buffer) */
165
166 status = acpi_ex_store_object_to_index (source_desc, ref_desc, walk_state);
167 break;
168
169
170 case AML_LOCAL_OP:
171 case AML_ARG_OP:
172
173 /* Store to a method local/arg */
174
175 status = acpi_ds_store_object_to_local (ref_desc->reference.opcode,
176 ref_desc->reference.offset, source_desc, walk_state);
177 break;
178
179
180 case AML_DEBUG_OP:
181
182 /*
183 * Storing to the Debug object causes the value stored to be
184 * displayed and otherwise has no effect -- see ACPI Specification
185 */
186 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
187 "**** Write to Debug Object: Object %p %s ****:\n\n",
188 source_desc, acpi_ut_get_object_type_name (source_desc)));
189
190 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %s: ",
191 acpi_ut_get_object_type_name (source_desc)));
192
193 if (!acpi_ut_valid_internal_object (source_desc)) {
194 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT,
195 "%p, Invalid Internal Object!\n", source_desc));
196 break;
197 }
198
199 switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
200 case ACPI_TYPE_INTEGER:
201
202 if (acpi_gbl_integer_byte_width == 4) {
203 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n",
204 (u32) source_desc->integer.value));
205 }
206 else {
207 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n",
208 ACPI_FORMAT_UINT64 (source_desc->integer.value)));
209 }
210 break;
211
212
213 case ACPI_TYPE_BUFFER:
214
215 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]",
216 (u32) source_desc->buffer.length));
217 ACPI_DUMP_BUFFER (source_desc->buffer.pointer,
218 (source_desc->buffer.length < 32) ? source_desc->buffer.length : 32);
219 break;
220
221
222 case ACPI_TYPE_STRING:
223
224 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n",
225 source_desc->string.length, source_desc->string.pointer));
226 break;
227
228
229 case ACPI_TYPE_PACKAGE:
230
231 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] Elements Ptr - %p\n",
232 source_desc->package.count, source_desc->package.elements));
233 break;
234
235
236 default:
237
238 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%p\n",
239 source_desc));
240 break;
241 }
242
243 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n"));
244 break;
245
246
247 default:
248
249 ACPI_REPORT_ERROR (("ex_store: Unknown Reference opcode %X\n",
250 ref_desc->reference.opcode));
251 ACPI_DUMP_ENTRY (ref_desc, ACPI_LV_ERROR);
252
253 status = AE_AML_INTERNAL;
254 break;
255 }
256
257 return_ACPI_STATUS (status);
258}
259
260
261/*******************************************************************************
262 *
263 * FUNCTION: acpi_ex_store_object_to_index
264 *
265 * PARAMETERS: *source_desc - Value to be stored
266 * *dest_desc - Named object to receive the value
267 * walk_state - Current walk state
268 *
269 * RETURN: Status
270 *
271 * DESCRIPTION: Store the object to indexed Buffer or Package element
272 *
273 ******************************************************************************/
274
275acpi_status
276acpi_ex_store_object_to_index (
277 union acpi_operand_object *source_desc,
278 union acpi_operand_object *index_desc,
279 struct acpi_walk_state *walk_state)
280{
281 acpi_status status = AE_OK;
282 union acpi_operand_object *obj_desc;
283 union acpi_operand_object *new_desc;
284 u8 value = 0;
285 u32 i;
286
287
288 ACPI_FUNCTION_TRACE ("ex_store_object_to_index");
289
290
291 /*
292 * Destination must be a reference pointer, and
293 * must point to either a buffer or a package
294 */
295 switch (index_desc->reference.target_type) {
296 case ACPI_TYPE_PACKAGE:
297 /*
298 * Storing to a package element. Copy the object and replace
299 * any existing object with the new object. No implicit
300 * conversion is performed.
301 *
302 * The object at *(index_desc->Reference.Where) is the
303 * element within the package that is to be modified.
304 * The parent package object is at index_desc->Reference.Object
305 */
306 obj_desc = *(index_desc->reference.where);
307
308 status = acpi_ut_copy_iobject_to_iobject (source_desc, &new_desc, walk_state);
309 if (ACPI_FAILURE (status)) {
310 return_ACPI_STATUS (status);
311 }
312
313 if (obj_desc) {
314 /* Decrement reference count by the ref count of the parent package */
315
316 for (i = 0; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) {
317 acpi_ut_remove_reference (obj_desc);
318 }
319 }
320
321 *(index_desc->reference.where) = new_desc;
322
323 /* Increment reference count by the ref count of the parent package -1 */
324
325 for (i = 1; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) {
326 acpi_ut_add_reference (new_desc);
327 }
328
329 break;
330
331
332 case ACPI_TYPE_BUFFER_FIELD:
333
334 /*
335 * Store into a Buffer or String (not actually a real buffer_field)
336 * at a location defined by an Index.
337 *
338 * The first 8-bit element of the source object is written to the
339 * 8-bit Buffer location defined by the Index destination object,
340 * according to the ACPI 2.0 specification.
341 */
342
343 /*
344 * Make sure the target is a Buffer or String. An error should
345 * not happen here, since the reference_object was constructed
346 * by the INDEX_OP code.
347 */
348 obj_desc = index_desc->reference.object;
349 if ((ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_BUFFER) &&
350 (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_STRING)) {
351 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
352 }
353
354 /*
355 * The assignment of the individual elements will be slightly
356 * different for each source type.
357 */
358 switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
359 case ACPI_TYPE_INTEGER:
360
361 /* Use the least-significant byte of the integer */
362
363 value = (u8) (source_desc->integer.value);
364 break;
365
366 case ACPI_TYPE_BUFFER:
367 case ACPI_TYPE_STRING:
368
369 /* Note: Takes advantage of common string/buffer fields */
370
371 value = source_desc->buffer.pointer[0];
372 break;
373
374 default:
375
376 /* All other types are invalid */
377
378 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
379 "Source must be Integer/Buffer/String type, not %s\n",
380 acpi_ut_get_object_type_name (source_desc)));
381 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
382 }
383
384 /* Store the source value into the target buffer byte */
385
386 obj_desc->buffer.pointer[index_desc->reference.offset] = value;
387 break;
388
389
390 default:
391 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
392 "Target is not a Package or buffer_field\n"));
393 status = AE_AML_OPERAND_TYPE;
394 break;
395 }
396
397 return_ACPI_STATUS (status);
398}
399
400
401/*******************************************************************************
402 *
403 * FUNCTION: acpi_ex_store_object_to_node
404 *
405 * PARAMETERS: source_desc - Value to be stored
406 * Node - Named object to receive the value
407 * walk_state - Current walk state
408 * implicit_conversion - Perform implicit conversion (yes/no)
409 *
410 * RETURN: Status
411 *
412 * DESCRIPTION: Store the object to the named object.
413 *
414 * The Assignment of an object to a named object is handled here
415 * The value passed in will replace the current value (if any)
416 * with the input value.
417 *
418 * When storing into an object the data is converted to the
419 * target object type then stored in the object. This means
420 * that the target object type (for an initialized target) will
421 * not be changed by a store operation.
422 *
423 * Assumes parameters are already validated.
424 *
425 ******************************************************************************/
426
427acpi_status
428acpi_ex_store_object_to_node (
429 union acpi_operand_object *source_desc,
430 struct acpi_namespace_node *node,
431 struct acpi_walk_state *walk_state,
432 u8 implicit_conversion)
433{
434 acpi_status status = AE_OK;
435 union acpi_operand_object *target_desc;
436 union acpi_operand_object *new_desc;
437 acpi_object_type target_type;
438
439
440 ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_node", source_desc);
441
442
443 /*
444 * Get current type of the node, and object attached to Node
445 */
446 target_type = acpi_ns_get_type (node);
447 target_desc = acpi_ns_get_attached_object (node);
448
449 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n",
450 source_desc, acpi_ut_get_object_type_name (source_desc),
451 node, acpi_ut_get_type_name (target_type)));
452
453 /*
454 * Resolve the source object to an actual value
455 * (If it is a reference object)
456 */
457 status = acpi_ex_resolve_object (&source_desc, target_type, walk_state);
458 if (ACPI_FAILURE (status)) {
459 return_ACPI_STATUS (status);
460 }
461
462 /* If no implicit conversion, drop into the default case below */
463
464 if (!implicit_conversion) {
465 /* Force execution of default (no implicit conversion) */
466
467 target_type = ACPI_TYPE_ANY;
468 }
469
470 /*
471 * Do the actual store operation
472 */
473 switch (target_type) {
474 case ACPI_TYPE_BUFFER_FIELD:
475 case ACPI_TYPE_LOCAL_REGION_FIELD:
476 case ACPI_TYPE_LOCAL_BANK_FIELD:
477 case ACPI_TYPE_LOCAL_INDEX_FIELD:
478
479 /*
480 * For fields, copy the source data to the target field.
481 */
482 status = acpi_ex_write_data_to_field (source_desc, target_desc, &walk_state->result_obj);
483 break;
484
485
486 case ACPI_TYPE_INTEGER:
487 case ACPI_TYPE_STRING:
488 case ACPI_TYPE_BUFFER:
489
490 /*
491 * These target types are all of type Integer/String/Buffer, and
492 * therefore support implicit conversion before the store.
493 *
494 * Copy and/or convert the source object to a new target object
495 */
496 status = acpi_ex_store_object_to_object (source_desc, target_desc, &new_desc, walk_state);
497 if (ACPI_FAILURE (status)) {
498 return_ACPI_STATUS (status);
499 }
500
501 if (new_desc != target_desc) {
502 /*
503 * Store the new new_desc as the new value of the Name, and set
504 * the Name's type to that of the value being stored in it.
505 * source_desc reference count is incremented by attach_object.
506 *
507 * Note: This may change the type of the node if an explicit store
508 * has been performed such that the node/object type has been
509 * changed.
510 */
511 status = acpi_ns_attach_object (node, new_desc, new_desc->common.type);
512
513 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
514 "Store %s into %s via Convert/Attach\n",
515 acpi_ut_get_object_type_name (source_desc),
516 acpi_ut_get_object_type_name (new_desc)));
517 }
518 break;
519
520
521 default:
522
523 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
524 "Storing %s (%p) directly into node (%p), no implicit conversion\n",
525 acpi_ut_get_object_type_name (source_desc), source_desc, node));
526
527 /* No conversions for all other types. Just attach the source object */
528
529 status = acpi_ns_attach_object (node, source_desc, ACPI_GET_OBJECT_TYPE (source_desc));
530 break;
531 }
532
533 return_ACPI_STATUS (status);
534}
535
536
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
new file mode 100644
index 000000000000..d3677feb07fd
--- /dev/null
+++ b/drivers/acpi/executer/exstoren.c
@@ -0,0 +1,306 @@
1
2/******************************************************************************
3 *
4 * Module Name: exstoren - AML Interpreter object store support,
5 * Store to Node (namespace object)
6 *
7 *****************************************************************************/
8
9/*
10 * Copyright (C) 2000 - 2005, R. Byron Moore
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions, and the following disclaimer,
18 * without modification.
19 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
20 * substantially similar to the "NO WARRANTY" disclaimer below
21 * ("Disclaimer") and any redistribution must be conditioned upon
22 * including a substantially similar Disclaimer requirement for further
23 * binary redistribution.
24 * 3. Neither the names of the above-listed copyright holders nor the names
25 * of any contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * Alternatively, this software may be distributed under the terms of the
29 * GNU General Public License ("GPL") version 2 as published by the Free
30 * Software Foundation.
31 *
32 * NO WARRANTY
33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
34 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
35 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
36 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
42 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 * POSSIBILITY OF SUCH DAMAGES.
44 */
45
46
47#include <acpi/acpi.h>
48#include <acpi/acinterp.h>
49#include <acpi/amlcode.h>
50
51
52#define _COMPONENT ACPI_EXECUTER
53 ACPI_MODULE_NAME ("exstoren")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_ex_resolve_object
59 *
60 * PARAMETERS: source_desc_ptr - Pointer to the source object
61 * target_type - Current type of the target
62 * walk_state - Current walk state
63 *
64 * RETURN: Status, resolved object in source_desc_ptr.
65 *
66 * DESCRIPTION: Resolve an object. If the object is a reference, dereference
67 * it and return the actual object in the source_desc_ptr.
68 *
69 ******************************************************************************/
70
71acpi_status
72acpi_ex_resolve_object (
73 union acpi_operand_object **source_desc_ptr,
74 acpi_object_type target_type,
75 struct acpi_walk_state *walk_state)
76{
77 union acpi_operand_object *source_desc = *source_desc_ptr;
78 acpi_status status = AE_OK;
79
80
81 ACPI_FUNCTION_TRACE ("ex_resolve_object");
82
83
84 /*
85 * Ensure we have a Target that can be stored to
86 */
87 switch (target_type) {
88 case ACPI_TYPE_BUFFER_FIELD:
89 case ACPI_TYPE_LOCAL_REGION_FIELD:
90 case ACPI_TYPE_LOCAL_BANK_FIELD:
91 case ACPI_TYPE_LOCAL_INDEX_FIELD:
92 /*
93 * These cases all require only Integers or values that
94 * can be converted to Integers (Strings or Buffers)
95 */
96
97 case ACPI_TYPE_INTEGER:
98 case ACPI_TYPE_STRING:
99 case ACPI_TYPE_BUFFER:
100
101 /*
102 * Stores into a Field/Region or into a Integer/Buffer/String
103 * are all essentially the same. This case handles the
104 * "interchangeable" types Integer, String, and Buffer.
105 */
106 if (ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
107 /* Resolve a reference object first */
108
109 status = acpi_ex_resolve_to_value (source_desc_ptr, walk_state);
110 if (ACPI_FAILURE (status)) {
111 break;
112 }
113 }
114
115 /* For copy_object, no further validation necessary */
116
117 if (walk_state->opcode == AML_COPY_OP) {
118 break;
119 }
120
121 /*
122 * Must have a Integer, Buffer, or String
123 */
124 if ((ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) &&
125 (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) &&
126 (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) &&
127 !((ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_LOCAL_REFERENCE) && (source_desc->reference.opcode == AML_LOAD_OP))) {
128 /*
129 * Conversion successful but still not a valid type
130 */
131 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
132 "Cannot assign type %s to %s (must be type Int/Str/Buf)\n",
133 acpi_ut_get_object_type_name (source_desc),
134 acpi_ut_get_type_name (target_type)));
135 status = AE_AML_OPERAND_TYPE;
136 }
137 break;
138
139
140 case ACPI_TYPE_LOCAL_ALIAS:
141 case ACPI_TYPE_LOCAL_METHOD_ALIAS:
142
143 /*
144 * Aliases are resolved by acpi_ex_prep_operands
145 */
146 ACPI_REPORT_ERROR (("Store into Alias - should never happen\n"));
147 status = AE_AML_INTERNAL;
148 break;
149
150
151 case ACPI_TYPE_PACKAGE:
152 default:
153
154 /*
155 * All other types than Alias and the various Fields come here,
156 * including the untyped case - ACPI_TYPE_ANY.
157 */
158 break;
159 }
160
161 return_ACPI_STATUS (status);
162}
163
164
165/*******************************************************************************
166 *
167 * FUNCTION: acpi_ex_store_object_to_object
168 *
169 * PARAMETERS: source_desc - Object to store
170 * dest_desc - Object to receive a copy of the source
171 * new_desc - New object if dest_desc is obsoleted
172 * walk_state - Current walk state
173 *
174 * RETURN: Status
175 *
176 * DESCRIPTION: "Store" an object to another object. This may include
177 * converting the source type to the target type (implicit
178 * conversion), and a copy of the value of the source to
179 * the target.
180 *
181 * The Assignment of an object to another (not named) object
182 * is handled here.
183 * The Source passed in will replace the current value (if any)
184 * with the input value.
185 *
186 * When storing into an object the data is converted to the
187 * target object type then stored in the object. This means
188 * that the target object type (for an initialized target) will
189 * not be changed by a store operation.
190 *
191 * This module allows destination types of Number, String,
192 * Buffer, and Package.
193 *
194 * Assumes parameters are already validated. NOTE: source_desc
195 * resolution (from a reference object) must be performed by
196 * the caller if necessary.
197 *
198 ******************************************************************************/
199
200acpi_status
201acpi_ex_store_object_to_object (
202 union acpi_operand_object *source_desc,
203 union acpi_operand_object *dest_desc,
204 union acpi_operand_object **new_desc,
205 struct acpi_walk_state *walk_state)
206{
207 union acpi_operand_object *actual_src_desc;
208 acpi_status status = AE_OK;
209
210
211 ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_object", source_desc);
212
213
214 actual_src_desc = source_desc;
215 if (!dest_desc) {
216 /*
217 * There is no destination object (An uninitialized node or
218 * package element), so we can simply copy the source object
219 * creating a new destination object
220 */
221 status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, new_desc, walk_state);
222 return_ACPI_STATUS (status);
223 }
224
225 if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_GET_OBJECT_TYPE (dest_desc)) {
226 /*
227 * The source type does not match the type of the destination.
228 * Perform the "implicit conversion" of the source to the current type
229 * of the target as per the ACPI specification.
230 *
231 * If no conversion performed, actual_src_desc = source_desc.
232 * Otherwise, actual_src_desc is a temporary object to hold the
233 * converted object.
234 */
235 status = acpi_ex_convert_to_target_type (ACPI_GET_OBJECT_TYPE (dest_desc),
236 source_desc, &actual_src_desc, walk_state);
237 if (ACPI_FAILURE (status)) {
238 return_ACPI_STATUS (status);
239 }
240
241 if (source_desc == actual_src_desc) {
242 /*
243 * No conversion was performed. Return the source_desc as the
244 * new object.
245 */
246 *new_desc = source_desc;
247 return_ACPI_STATUS (AE_OK);
248 }
249 }
250
251 /*
252 * We now have two objects of identical types, and we can perform a
253 * copy of the *value* of the source object.
254 */
255 switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
256 case ACPI_TYPE_INTEGER:
257
258 dest_desc->integer.value = actual_src_desc->integer.value;
259
260 /* Truncate value if we are executing from a 32-bit ACPI table */
261
262 acpi_ex_truncate_for32bit_table (dest_desc);
263 break;
264
265 case ACPI_TYPE_STRING:
266
267 status = acpi_ex_store_string_to_string (actual_src_desc, dest_desc);
268 break;
269
270 case ACPI_TYPE_BUFFER:
271
272 /*
273 * Note: There is different store behavior depending on the original
274 * source type
275 */
276 status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc);
277 break;
278
279 case ACPI_TYPE_PACKAGE:
280
281 status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, &dest_desc,
282 walk_state);
283 break;
284
285 default:
286 /*
287 * All other types come here.
288 */
289 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into type %s not implemented\n",
290 acpi_ut_get_object_type_name (dest_desc)));
291
292 status = AE_NOT_IMPLEMENTED;
293 break;
294 }
295
296 if (actual_src_desc != source_desc) {
297 /* Delete the intermediate (temporary) source object */
298
299 acpi_ut_remove_reference (actual_src_desc);
300 }
301
302 *new_desc = dest_desc;
303 return_ACPI_STATUS (status);
304}
305
306
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
new file mode 100644
index 000000000000..05e1ecae8d92
--- /dev/null
+++ b/drivers/acpi/executer/exstorob.c
@@ -0,0 +1,216 @@
1
2/******************************************************************************
3 *
4 * Module Name: exstorob - AML Interpreter object store support, store to object
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acinterp.h>
48
49
50#define _COMPONENT ACPI_EXECUTER
51 ACPI_MODULE_NAME ("exstorob")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ex_store_buffer_to_buffer
57 *
58 * PARAMETERS: source_desc - Source object to copy
59 * target_desc - Destination object of the copy
60 *
61 * RETURN: Status
62 *
63 * DESCRIPTION: Copy a buffer object to another buffer object.
64 *
65 ******************************************************************************/
66
67acpi_status
68acpi_ex_store_buffer_to_buffer (
69 union acpi_operand_object *source_desc,
70 union acpi_operand_object *target_desc)
71{
72 u32 length;
73 u8 *buffer;
74
75
76 ACPI_FUNCTION_TRACE_PTR ("ex_store_buffer_to_buffer", source_desc);
77
78
79 /* We know that source_desc is a buffer by now */
80
81 buffer = (u8 *) source_desc->buffer.pointer;
82 length = source_desc->buffer.length;
83
84 /*
85 * If target is a buffer of length zero or is a static buffer,
86 * allocate a new buffer of the proper length
87 */
88 if ((target_desc->buffer.length == 0) ||
89 (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
90 target_desc->buffer.pointer = ACPI_MEM_ALLOCATE (length);
91 if (!target_desc->buffer.pointer) {
92 return_ACPI_STATUS (AE_NO_MEMORY);
93 }
94
95 target_desc->buffer.length = length;
96 }
97
98 /* Copy source buffer to target buffer */
99
100 if (length <= target_desc->buffer.length) {
101 /* Clear existing buffer and copy in the new one */
102
103 ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length);
104 ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length);
105
106#ifdef ACPI_OBSOLETE_BEHAVIOR
107 /*
108 * NOTE: ACPI versions up to 3.0 specified that the buffer must be
109 * truncated if the string is smaller than the buffer. However, "other"
110 * implementations of ACPI never did this and thus became the defacto
111 * standard. ACPi 3.0_a changes this behavior such that the buffer
112 * is no longer truncated.
113 */
114
115 /*
116 * OBSOLETE BEHAVIOR:
117 * If the original source was a string, we must truncate the buffer,
118 * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
119 * copy must not truncate the original buffer.
120 */
121 if (original_src_type == ACPI_TYPE_STRING) {
122 /* Set the new length of the target */
123
124 target_desc->buffer.length = length;
125 }
126#endif
127 }
128 else {
129 /* Truncate the source, copy only what will fit */
130
131 ACPI_MEMCPY (target_desc->buffer.pointer, buffer, target_desc->buffer.length);
132
133 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
134 "Truncating source buffer from %X to %X\n",
135 length, target_desc->buffer.length));
136 }
137
138 /* Copy flags */
139
140 target_desc->buffer.flags = source_desc->buffer.flags;
141 target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
142 return_ACPI_STATUS (AE_OK);
143}
144
145
146/*******************************************************************************
147 *
148 * FUNCTION: acpi_ex_store_string_to_string
149 *
150 * PARAMETERS: source_desc - Source object to copy
151 * target_desc - Destination object of the copy
152 *
153 * RETURN: Status
154 *
155 * DESCRIPTION: Copy a String object to another String object
156 *
157 ******************************************************************************/
158
159acpi_status
160acpi_ex_store_string_to_string (
161 union acpi_operand_object *source_desc,
162 union acpi_operand_object *target_desc)
163{
164 u32 length;
165 u8 *buffer;
166
167
168 ACPI_FUNCTION_TRACE_PTR ("ex_store_string_to_string", source_desc);
169
170
171 /* We know that source_desc is a string by now */
172
173 buffer = (u8 *) source_desc->string.pointer;
174 length = source_desc->string.length;
175
176 /*
177 * Replace existing string value if it will fit and the string
178 * pointer is not a static pointer (part of an ACPI table)
179 */
180 if ((length < target_desc->string.length) &&
181 (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
182 /*
183 * String will fit in existing non-static buffer.
184 * Clear old string and copy in the new one
185 */
186 ACPI_MEMSET (target_desc->string.pointer, 0, (acpi_size) target_desc->string.length + 1);
187 ACPI_MEMCPY (target_desc->string.pointer, buffer, length);
188 }
189 else {
190 /*
191 * Free the current buffer, then allocate a new buffer
192 * large enough to hold the value
193 */
194 if (target_desc->string.pointer &&
195 (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
196 /* Only free if not a pointer into the DSDT */
197
198 ACPI_MEM_FREE (target_desc->string.pointer);
199 }
200
201 target_desc->string.pointer = ACPI_MEM_CALLOCATE ((acpi_size) length + 1);
202 if (!target_desc->string.pointer) {
203 return_ACPI_STATUS (AE_NO_MEMORY);
204 }
205
206 target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
207 ACPI_MEMCPY (target_desc->string.pointer, buffer, length);
208 }
209
210 /* Set the new target length */
211
212 target_desc->string.length = length;
213 return_ACPI_STATUS (AE_OK);
214}
215
216
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
new file mode 100644
index 000000000000..f92efc512890
--- /dev/null
+++ b/drivers/acpi/executer/exsystem.c
@@ -0,0 +1,378 @@
1
2/******************************************************************************
3 *
4 * Module Name: exsystem - Interface to OS services
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acinterp.h>
48#include <acpi/acevents.h>
49
50#define _COMPONENT ACPI_EXECUTER
51 ACPI_MODULE_NAME ("exsystem")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ex_system_wait_semaphore
57 *
58 * PARAMETERS: Semaphore - OSD semaphore to wait on
59 * Timeout - Max time to wait
60 *
61 * RETURN: Status
62 *
63 * DESCRIPTION: Implements a semaphore wait with a check to see if the
64 * semaphore is available immediately. If it is not, the
65 * interpreter is released.
66 *
67 ******************************************************************************/
68
69acpi_status
70acpi_ex_system_wait_semaphore (
71 acpi_handle semaphore,
72 u16 timeout)
73{
74 acpi_status status;
75 acpi_status status2;
76
77
78 ACPI_FUNCTION_TRACE ("ex_system_wait_semaphore");
79
80
81 status = acpi_os_wait_semaphore (semaphore, 1, 0);
82 if (ACPI_SUCCESS (status)) {
83 return_ACPI_STATUS (status);
84 }
85
86 if (status == AE_TIME) {
87 /* We must wait, so unlock the interpreter */
88
89 acpi_ex_exit_interpreter ();
90
91 status = acpi_os_wait_semaphore (semaphore, 1, timeout);
92
93 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*** Thread awake after blocking, %s\n",
94 acpi_format_exception (status)));
95
96 /* Reacquire the interpreter */
97
98 status2 = acpi_ex_enter_interpreter ();
99 if (ACPI_FAILURE (status2)) {
100 /* Report fatal error, could not acquire interpreter */
101
102 return_ACPI_STATUS (status2);
103 }
104 }
105
106 return_ACPI_STATUS (status);
107}
108
109
110/*******************************************************************************
111 *
112 * FUNCTION: acpi_ex_system_do_stall
113 *
114 * PARAMETERS: how_long - The amount of time to stall,
115 * in microseconds
116 *
117 * RETURN: Status
118 *
119 * DESCRIPTION: Suspend running thread for specified amount of time.
120 * Note: ACPI specification requires that Stall() does not
121 * relinquish the processor, and delays longer than 100 usec
122 * should use Sleep() instead. We allow stalls up to 255 usec
123 * for compatibility with other interpreters and existing BIOSs.
124 *
125 ******************************************************************************/
126
127acpi_status
128acpi_ex_system_do_stall (
129 u32 how_long)
130{
131 acpi_status status = AE_OK;
132
133
134 ACPI_FUNCTION_ENTRY ();
135
136
137 if (how_long > 255) /* 255 microseconds */ {
138 /*
139 * Longer than 255 usec, this is an error
140 *
141 * (ACPI specifies 100 usec as max, but this gives some slack in
142 * order to support existing BIOSs)
143 */
144 ACPI_REPORT_ERROR (("Stall: Time parameter is too large (%d)\n", how_long));
145 status = AE_AML_OPERAND_VALUE;
146 }
147 else {
148 acpi_os_stall (how_long);
149 }
150
151 return (status);
152}
153
154
155/*******************************************************************************
156 *
157 * FUNCTION: acpi_ex_system_do_suspend
158 *
159 * PARAMETERS: how_long - The amount of time to suspend,
160 * in milliseconds
161 *
162 * RETURN: None
163 *
164 * DESCRIPTION: Suspend running thread for specified amount of time.
165 *
166 ******************************************************************************/
167
168acpi_status
169acpi_ex_system_do_suspend (
170 acpi_integer how_long)
171{
172 acpi_status status;
173
174
175 ACPI_FUNCTION_ENTRY ();
176
177
178 /* Since this thread will sleep, we must release the interpreter */
179
180 acpi_ex_exit_interpreter ();
181
182 acpi_os_sleep (how_long);
183
184 /* And now we must get the interpreter again */
185
186 status = acpi_ex_enter_interpreter ();
187 return (status);
188}
189
190
191/*******************************************************************************
192 *
193 * FUNCTION: acpi_ex_system_acquire_mutex
194 *
195 * PARAMETERS: *time_desc - The 'time to delay' object descriptor
196 * *obj_desc - The object descriptor for this op
197 *
198 * RETURN: Status
199 *
200 * DESCRIPTION: Provides an access point to perform synchronization operations
201 * within the AML. This function will cause a lock to be generated
202 * for the Mutex pointed to by obj_desc.
203 *
204 ******************************************************************************/
205
206acpi_status
207acpi_ex_system_acquire_mutex (
208 union acpi_operand_object *time_desc,
209 union acpi_operand_object *obj_desc)
210{
211 acpi_status status = AE_OK;
212
213
214 ACPI_FUNCTION_TRACE_PTR ("ex_system_acquire_mutex", obj_desc);
215
216
217 if (!obj_desc) {
218 return_ACPI_STATUS (AE_BAD_PARAMETER);
219 }
220
221 /*
222 * Support for the _GL_ Mutex object -- go get the global lock
223 */
224 if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) {
225 status = acpi_ev_acquire_global_lock ((u16) time_desc->integer.value);
226 return_ACPI_STATUS (status);
227 }
228
229 status = acpi_ex_system_wait_semaphore (obj_desc->mutex.semaphore,
230 (u16) time_desc->integer.value);
231 return_ACPI_STATUS (status);
232}
233
234
235/*******************************************************************************
236 *
237 * FUNCTION: acpi_ex_system_release_mutex
238 *
239 * PARAMETERS: *obj_desc - The object descriptor for this op
240 *
241 * RETURN: Status
242 *
243 * DESCRIPTION: Provides an access point to perform synchronization operations
244 * within the AML. This operation is a request to release a
245 * previously acquired Mutex. If the Mutex variable is set then
246 * it will be decremented.
247 *
248 ******************************************************************************/
249
250acpi_status
251acpi_ex_system_release_mutex (
252 union acpi_operand_object *obj_desc)
253{
254 acpi_status status = AE_OK;
255
256
257 ACPI_FUNCTION_TRACE ("ex_system_release_mutex");
258
259
260 if (!obj_desc) {
261 return_ACPI_STATUS (AE_BAD_PARAMETER);
262 }
263
264 /*
265 * Support for the _GL_ Mutex object -- release the global lock
266 */
267 if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) {
268 status = acpi_ev_release_global_lock ();
269 return_ACPI_STATUS (status);
270 }
271
272 status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1);
273 return_ACPI_STATUS (status);
274}
275
276
277/*******************************************************************************
278 *
279 * FUNCTION: acpi_ex_system_signal_event
280 *
281 * PARAMETERS: *obj_desc - The object descriptor for this op
282 *
283 * RETURN: AE_OK
284 *
285 * DESCRIPTION: Provides an access point to perform synchronization operations
286 * within the AML.
287 *
288 ******************************************************************************/
289
290acpi_status
291acpi_ex_system_signal_event (
292 union acpi_operand_object *obj_desc)
293{
294 acpi_status status = AE_OK;
295
296
297 ACPI_FUNCTION_TRACE ("ex_system_signal_event");
298
299
300 if (obj_desc) {
301 status = acpi_os_signal_semaphore (obj_desc->event.semaphore, 1);
302 }
303
304 return_ACPI_STATUS (status);
305}
306
307
308/*******************************************************************************
309 *
310 * FUNCTION: acpi_ex_system_wait_event
311 *
312 * PARAMETERS: *time_desc - The 'time to delay' object descriptor
313 * *obj_desc - The object descriptor for this op
314 *
315 * RETURN: Status
316 *
317 * DESCRIPTION: Provides an access point to perform synchronization operations
318 * within the AML. This operation is a request to wait for an
319 * event.
320 *
321 ******************************************************************************/
322
323acpi_status
324acpi_ex_system_wait_event (
325 union acpi_operand_object *time_desc,
326 union acpi_operand_object *obj_desc)
327{
328 acpi_status status = AE_OK;
329
330
331 ACPI_FUNCTION_TRACE ("ex_system_wait_event");
332
333
334 if (obj_desc) {
335 status = acpi_ex_system_wait_semaphore (obj_desc->event.semaphore,
336 (u16) time_desc->integer.value);
337 }
338
339 return_ACPI_STATUS (status);
340}
341
342
343/*******************************************************************************
344 *
345 * FUNCTION: acpi_ex_system_reset_event
346 *
347 * PARAMETERS: *obj_desc - The object descriptor for this op
348 *
349 * RETURN: Status
350 *
351 * DESCRIPTION: Reset an event to a known state.
352 *
353 ******************************************************************************/
354
355acpi_status
356acpi_ex_system_reset_event (
357 union acpi_operand_object *obj_desc)
358{
359 acpi_status status = AE_OK;
360 void *temp_semaphore;
361
362
363 ACPI_FUNCTION_ENTRY ();
364
365
366 /*
367 * We are going to simply delete the existing semaphore and
368 * create a new one!
369 */
370 status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore);
371 if (ACPI_SUCCESS (status)) {
372 (void) acpi_os_delete_semaphore (obj_desc->event.semaphore);
373 obj_desc->event.semaphore = temp_semaphore;
374 }
375
376 return (status);
377}
378
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
new file mode 100644
index 000000000000..40c6abb8b49a
--- /dev/null
+++ b/drivers/acpi/executer/exutils.c
@@ -0,0 +1,378 @@
1
2/******************************************************************************
3 *
4 * Module Name: exutils - interpreter/scanner utilities
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46/*
47 * DEFINE_AML_GLOBALS is tested in amlcode.h
48 * to determine whether certain global names should be "defined" or only
49 * "declared" in the current compilation. This enhances maintainability
50 * by enabling a single header file to embody all knowledge of the names
51 * in question.
52 *
53 * Exactly one module of any executable should #define DEFINE_GLOBALS
54 * before #including the header files which use this convention. The
55 * names in question will be defined and initialized in that module,
56 * and declared as extern in all other modules which #include those
57 * header files.
58 */
59
60#define DEFINE_AML_GLOBALS
61
62#include <acpi/acpi.h>
63#include <acpi/acinterp.h>
64#include <acpi/amlcode.h>
65#include <acpi/acevents.h>
66
67#define _COMPONENT ACPI_EXECUTER
68 ACPI_MODULE_NAME ("exutils")
69
70
71#ifndef ACPI_NO_METHOD_EXECUTION
72
73/*******************************************************************************
74 *
75 * FUNCTION: acpi_ex_enter_interpreter
76 *
77 * PARAMETERS: None
78 *
79 * DESCRIPTION: Enter the interpreter execution region. Failure to enter
80 * the interpreter region is a fatal system error
81 *
82 ******************************************************************************/
83
84acpi_status
85acpi_ex_enter_interpreter (void)
86{
87 acpi_status status;
88
89 ACPI_FUNCTION_TRACE ("ex_enter_interpreter");
90
91
92 status = acpi_ut_acquire_mutex (ACPI_MTX_EXECUTE);
93 if (ACPI_FAILURE (status)) {
94 ACPI_REPORT_ERROR (("Could not acquire interpreter mutex\n"));
95 }
96
97 return_ACPI_STATUS (status);
98}
99
100
101/*******************************************************************************
102 *
103 * FUNCTION: acpi_ex_exit_interpreter
104 *
105 * PARAMETERS: None
106 *
107 * DESCRIPTION: Exit the interpreter execution region
108 *
109 * Cases where the interpreter is unlocked:
110 * 1) Completion of the execution of a control method
111 * 2) Method blocked on a Sleep() AML opcode
112 * 3) Method blocked on an Acquire() AML opcode
113 * 4) Method blocked on a Wait() AML opcode
114 * 5) Method blocked to acquire the global lock
115 * 6) Method blocked to execute a serialized control method that is
116 * already executing
117 * 7) About to invoke a user-installed opregion handler
118 *
119 ******************************************************************************/
120
121void
122acpi_ex_exit_interpreter (void)
123{
124 acpi_status status;
125
126
127 ACPI_FUNCTION_TRACE ("ex_exit_interpreter");
128
129
130 status = acpi_ut_release_mutex (ACPI_MTX_EXECUTE);
131 if (ACPI_FAILURE (status)) {
132 ACPI_REPORT_ERROR (("Could not release interpreter mutex\n"));
133 }
134
135 return_VOID;
136}
137
138
139/*******************************************************************************
140 *
141 * FUNCTION: acpi_ex_truncate_for32bit_table
142 *
143 * PARAMETERS: obj_desc - Object to be truncated
144 *
145 * RETURN: none
146 *
147 * DESCRIPTION: Truncate a number to 32-bits if the currently executing method
148 * belongs to a 32-bit ACPI table.
149 *
150 ******************************************************************************/
151
152void
153acpi_ex_truncate_for32bit_table (
154 union acpi_operand_object *obj_desc)
155{
156
157 ACPI_FUNCTION_ENTRY ();
158
159
160 /*
161 * Object must be a valid number and we must be executing
162 * a control method
163 */
164 if ((!obj_desc) ||
165 (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER)) {
166 return;
167 }
168
169 if (acpi_gbl_integer_byte_width == 4) {
170 /*
171 * We are running a method that exists in a 32-bit ACPI table.
172 * Truncate the value to 32 bits by zeroing out the upper 32-bit field
173 */
174 obj_desc->integer.value &= (acpi_integer) ACPI_UINT32_MAX;
175 }
176}
177
178
179/*******************************************************************************
180 *
181 * FUNCTION: acpi_ex_acquire_global_lock
182 *
183 * PARAMETERS: field_flags - Flags with Lock rule:
184 * always_lock or never_lock
185 *
186 * RETURN: TRUE/FALSE indicating whether the lock was actually acquired
187 *
188 * DESCRIPTION: Obtain the global lock and keep track of this fact via two
189 * methods. A global variable keeps the state of the lock, and
190 * the state is returned to the caller.
191 *
192 ******************************************************************************/
193
194u8
195acpi_ex_acquire_global_lock (
196 u32 field_flags)
197{
198 u8 locked = FALSE;
199 acpi_status status;
200
201
202 ACPI_FUNCTION_TRACE ("ex_acquire_global_lock");
203
204
205 /* Only attempt lock if the always_lock bit is set */
206
207 if (field_flags & AML_FIELD_LOCK_RULE_MASK) {
208 /* We should attempt to get the lock, wait forever */
209
210 status = acpi_ev_acquire_global_lock (ACPI_WAIT_FOREVER);
211 if (ACPI_SUCCESS (status)) {
212 locked = TRUE;
213 }
214 else {
215 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not acquire Global Lock, %s\n",
216 acpi_format_exception (status)));
217 }
218 }
219
220 return_VALUE (locked);
221}
222
223
224/*******************************************************************************
225 *
226 * FUNCTION: acpi_ex_release_global_lock
227 *
228 * PARAMETERS: locked_by_me - Return value from corresponding call to
229 * acquire_global_lock.
230 *
231 * RETURN: Status
232 *
233 * DESCRIPTION: Release the global lock if it is locked.
234 *
235 ******************************************************************************/
236
237void
238acpi_ex_release_global_lock (
239 u8 locked_by_me)
240{
241 acpi_status status;
242
243
244 ACPI_FUNCTION_TRACE ("ex_release_global_lock");
245
246
247 /* Only attempt unlock if the caller locked it */
248
249 if (locked_by_me) {
250 /* OK, now release the lock */
251
252 status = acpi_ev_release_global_lock ();
253 if (ACPI_FAILURE (status)) {
254 /* Report the error, but there isn't much else we can do */
255
256 ACPI_REPORT_ERROR (("Could not release ACPI Global Lock, %s\n",
257 acpi_format_exception (status)));
258 }
259 }
260
261 return_VOID;
262}
263
264
265/*******************************************************************************
266 *
267 * FUNCTION: acpi_ex_digits_needed
268 *
269 * PARAMETERS: Value - Value to be represented
270 * Base - Base of representation
271 *
272 * RETURN: the number of digits needed to represent Value in Base
273 *
274 ******************************************************************************/
275
276u32
277acpi_ex_digits_needed (
278 acpi_integer value,
279 u32 base)
280{
281 u32 num_digits;
282 acpi_integer current_value;
283
284
285 ACPI_FUNCTION_TRACE ("ex_digits_needed");
286
287
288 /* acpi_integer is unsigned, so we don't worry about a '-' prefix */
289
290 if (value == 0) {
291 return_VALUE (1);
292 }
293
294 current_value = value;
295 num_digits = 0;
296
297 /* Count the digits in the requested base */
298
299 while (current_value) {
300 (void) acpi_ut_short_divide (current_value, base, &current_value, NULL);
301 num_digits++;
302 }
303
304 return_VALUE (num_digits);
305}
306
307
308/*******************************************************************************
309 *
310 * FUNCTION: acpi_ex_eisa_id_to_string
311 *
312 * PARAMETERS: numeric_id - EISA ID to be converted
313 * out_string - Where to put the converted string (8 bytes)
314 *
315 * DESCRIPTION: Convert a numeric EISA ID to string representation
316 *
317 ******************************************************************************/
318
319void
320acpi_ex_eisa_id_to_string (
321 u32 numeric_id,
322 char *out_string)
323{
324 u32 eisa_id;
325
326
327 ACPI_FUNCTION_ENTRY ();
328
329
330 /* Swap ID to big-endian to get contiguous bits */
331
332 eisa_id = acpi_ut_dword_byte_swap (numeric_id);
333
334 out_string[0] = (char) ('@' + (((unsigned long) eisa_id >> 26) & 0x1f));
335 out_string[1] = (char) ('@' + ((eisa_id >> 21) & 0x1f));
336 out_string[2] = (char) ('@' + ((eisa_id >> 16) & 0x1f));
337 out_string[3] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 12);
338 out_string[4] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 8);
339 out_string[5] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 4);
340 out_string[6] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 0);
341 out_string[7] = 0;
342}
343
344
345/*******************************************************************************
346 *
347 * FUNCTION: acpi_ex_unsigned_integer_to_string
348 *
349 * PARAMETERS: Value - Value to be converted
350 * out_string - Where to put the converted string (8 bytes)
351 *
352 * RETURN: Convert a number to string representation
353 *
354 ******************************************************************************/
355
356void
357acpi_ex_unsigned_integer_to_string (
358 acpi_integer value,
359 char *out_string)
360{
361 u32 count;
362 u32 digits_needed;
363 u32 remainder;
364
365
366 ACPI_FUNCTION_ENTRY ();
367
368
369 digits_needed = acpi_ex_digits_needed (value, 10);
370 out_string[digits_needed] = 0;
371
372 for (count = digits_needed; count > 0; count--) {
373 (void) acpi_ut_short_divide (value, 10, &value, &remainder);
374 out_string[count-1] = (char) ('0' + remainder);\
375 }
376}
377
378#endif
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
new file mode 100644
index 000000000000..14192ee55f8f
--- /dev/null
+++ b/drivers/acpi/fan.c
@@ -0,0 +1,302 @@
1/*
2 * acpi_fan.c - ACPI Fan Driver ($Revision: 29 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/types.h>
30#include <linux/proc_fs.h>
31#include <linux/seq_file.h>
32#include <asm/uaccess.h>
33
34#include <acpi/acpi_bus.h>
35#include <acpi/acpi_drivers.h>
36
37
38#define ACPI_FAN_COMPONENT 0x00200000
39#define ACPI_FAN_CLASS "fan"
40#define ACPI_FAN_HID "PNP0C0B"
41#define ACPI_FAN_DRIVER_NAME "ACPI Fan Driver"
42#define ACPI_FAN_DEVICE_NAME "Fan"
43#define ACPI_FAN_FILE_STATE "state"
44#define ACPI_FAN_NOTIFY_STATUS 0x80
45
46#define _COMPONENT ACPI_FAN_COMPONENT
47ACPI_MODULE_NAME ("acpi_fan")
48
49MODULE_AUTHOR("Paul Diefenbaugh");
50MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME);
51MODULE_LICENSE("GPL");
52
53static int acpi_fan_add (struct acpi_device *device);
54static int acpi_fan_remove (struct acpi_device *device, int type);
55
56static struct acpi_driver acpi_fan_driver = {
57 .name = ACPI_FAN_DRIVER_NAME,
58 .class = ACPI_FAN_CLASS,
59 .ids = ACPI_FAN_HID,
60 .ops = {
61 .add = acpi_fan_add,
62 .remove = acpi_fan_remove,
63 },
64};
65
66struct acpi_fan {
67 acpi_handle handle;
68};
69
70
71/* --------------------------------------------------------------------------
72 FS Interface (/proc)
73 -------------------------------------------------------------------------- */
74
75static struct proc_dir_entry *acpi_fan_dir;
76
77
78static int
79acpi_fan_read_state (struct seq_file *seq, void *offset)
80{
81 struct acpi_fan *fan = seq->private;
82 int state = 0;
83
84 ACPI_FUNCTION_TRACE("acpi_fan_read_state");
85
86 if (fan) {
87 if (acpi_bus_get_power(fan->handle, &state))
88 seq_printf(seq, "status: ERROR\n");
89 else
90 seq_printf(seq, "status: %s\n",
91 !state?"on":"off");
92 }
93 return_VALUE(0);
94}
95
96static int acpi_fan_state_open_fs(struct inode *inode, struct file *file)
97{
98 return single_open(file, acpi_fan_read_state, PDE(inode)->data);
99}
100
101static ssize_t
102acpi_fan_write_state (
103 struct file *file,
104 const char __user *buffer,
105 size_t count,
106 loff_t *ppos)
107{
108 int result = 0;
109 struct seq_file *m = (struct seq_file *)file->private_data;
110 struct acpi_fan *fan = (struct acpi_fan *) m->private;
111 char state_string[12] = {'\0'};
112
113 ACPI_FUNCTION_TRACE("acpi_fan_write_state");
114
115 if (!fan || (count > sizeof(state_string) - 1))
116 return_VALUE(-EINVAL);
117
118 if (copy_from_user(state_string, buffer, count))
119 return_VALUE(-EFAULT);
120
121 state_string[count] = '\0';
122
123 result = acpi_bus_set_power(fan->handle,
124 simple_strtoul(state_string, NULL, 0));
125 if (result)
126 return_VALUE(result);
127
128 return_VALUE(count);
129}
130
131static struct file_operations acpi_fan_state_ops = {
132 .open = acpi_fan_state_open_fs,
133 .read = seq_read,
134 .write = acpi_fan_write_state,
135 .llseek = seq_lseek,
136 .release = single_release,
137 .owner = THIS_MODULE,
138};
139
140static int
141acpi_fan_add_fs (
142 struct acpi_device *device)
143{
144 struct proc_dir_entry *entry = NULL;
145
146 ACPI_FUNCTION_TRACE("acpi_fan_add_fs");
147
148 if (!device)
149 return_VALUE(-EINVAL);
150
151 if (!acpi_device_dir(device)) {
152 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
153 acpi_fan_dir);
154 if (!acpi_device_dir(device))
155 return_VALUE(-ENODEV);
156 acpi_device_dir(device)->owner = THIS_MODULE;
157 }
158
159 /* 'status' [R/W] */
160 entry = create_proc_entry(ACPI_FAN_FILE_STATE,
161 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
162 if (!entry)
163 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
164 "Unable to create '%s' fs entry\n",
165 ACPI_FAN_FILE_STATE));
166 else {
167 entry->proc_fops = &acpi_fan_state_ops;
168 entry->data = acpi_driver_data(device);
169 entry->owner = THIS_MODULE;
170 }
171
172 return_VALUE(0);
173}
174
175
176static int
177acpi_fan_remove_fs (
178 struct acpi_device *device)
179{
180 ACPI_FUNCTION_TRACE("acpi_fan_remove_fs");
181
182 if (acpi_device_dir(device)) {
183 remove_proc_entry(ACPI_FAN_FILE_STATE,
184 acpi_device_dir(device));
185 remove_proc_entry(acpi_device_bid(device), acpi_fan_dir);
186 acpi_device_dir(device) = NULL;
187 }
188
189 return_VALUE(0);
190}
191
192
193/* --------------------------------------------------------------------------
194 Driver Interface
195 -------------------------------------------------------------------------- */
196
197static int
198acpi_fan_add (
199 struct acpi_device *device)
200{
201 int result = 0;
202 struct acpi_fan *fan = NULL;
203 int state = 0;
204
205 ACPI_FUNCTION_TRACE("acpi_fan_add");
206
207 if (!device)
208 return_VALUE(-EINVAL);
209
210 fan = kmalloc(sizeof(struct acpi_fan), GFP_KERNEL);
211 if (!fan)
212 return_VALUE(-ENOMEM);
213 memset(fan, 0, sizeof(struct acpi_fan));
214
215 fan->handle = device->handle;
216 strcpy(acpi_device_name(device), ACPI_FAN_DEVICE_NAME);
217 strcpy(acpi_device_class(device), ACPI_FAN_CLASS);
218 acpi_driver_data(device) = fan;
219
220 result = acpi_bus_get_power(fan->handle, &state);
221 if (result) {
222 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
223 "Error reading power state\n"));
224 goto end;
225 }
226
227 result = acpi_fan_add_fs(device);
228 if (result)
229 goto end;
230
231 printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
232 acpi_device_name(device), acpi_device_bid(device),
233 !device->power.state?"on":"off");
234
235end:
236 if (result)
237 kfree(fan);
238
239 return_VALUE(result);
240}
241
242
243static int
244acpi_fan_remove (
245 struct acpi_device *device,
246 int type)
247{
248 struct acpi_fan *fan = NULL;
249
250 ACPI_FUNCTION_TRACE("acpi_fan_remove");
251
252 if (!device || !acpi_driver_data(device))
253 return_VALUE(-EINVAL);
254
255 fan = (struct acpi_fan *) acpi_driver_data(device);
256
257 acpi_fan_remove_fs(device);
258
259 kfree(fan);
260
261 return_VALUE(0);
262}
263
264
265static int __init
266acpi_fan_init (void)
267{
268 int result = 0;
269
270 ACPI_FUNCTION_TRACE("acpi_fan_init");
271
272 acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
273 if (!acpi_fan_dir)
274 return_VALUE(-ENODEV);
275 acpi_fan_dir->owner = THIS_MODULE;
276
277 result = acpi_bus_register_driver(&acpi_fan_driver);
278 if (result < 0) {
279 remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
280 return_VALUE(-ENODEV);
281 }
282
283 return_VALUE(0);
284}
285
286
287static void __exit
288acpi_fan_exit (void)
289{
290 ACPI_FUNCTION_TRACE("acpi_fan_exit");
291
292 acpi_bus_unregister_driver(&acpi_fan_driver);
293
294 remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
295
296 return_VOID;
297}
298
299
300module_init(acpi_fan_init);
301module_exit(acpi_fan_exit);
302
diff --git a/drivers/acpi/hardware/Makefile b/drivers/acpi/hardware/Makefile
new file mode 100644
index 000000000000..438ad373b9ad
--- /dev/null
+++ b/drivers/acpi/hardware/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for all Linux ACPI interpreter subdirectories
3#
4
5obj-y := hwacpi.o hwgpe.o hwregs.o hwsleep.o
6
7obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
8
9EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c
new file mode 100644
index 000000000000..529e922bdc85
--- /dev/null
+++ b/drivers/acpi/hardware/hwacpi.c
@@ -0,0 +1,230 @@
1
2/******************************************************************************
3 *
4 * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47
48
49#define _COMPONENT ACPI_HARDWARE
50 ACPI_MODULE_NAME ("hwacpi")
51
52
53/******************************************************************************
54 *
55 * FUNCTION: acpi_hw_initialize
56 *
57 * PARAMETERS: None
58 *
59 * RETURN: Status
60 *
61 * DESCRIPTION: Initialize and validate various ACPI registers
62 *
63 ******************************************************************************/
64
65acpi_status
66acpi_hw_initialize (
67 void)
68{
69 acpi_status status;
70
71
72 ACPI_FUNCTION_TRACE ("hw_initialize");
73
74
75 /* We must have the ACPI tables by the time we get here */
76
77 if (!acpi_gbl_FADT) {
78 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "A FADT is not loaded\n"));
79
80 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
81 }
82
83 /* Sanity check the FADT for valid values */
84
85 status = acpi_ut_validate_fadt ();
86 if (ACPI_FAILURE (status)) {
87 return_ACPI_STATUS (status);
88 }
89
90 return_ACPI_STATUS (AE_OK);
91}
92
93
94/******************************************************************************
95 *
96 * FUNCTION: acpi_hw_set_mode
97 *
98 * PARAMETERS: Mode - SYS_MODE_ACPI or SYS_MODE_LEGACY
99 *
100 * RETURN: Status
101 *
102 * DESCRIPTION: Transitions the system into the requested mode.
103 *
104 ******************************************************************************/
105
106acpi_status
107acpi_hw_set_mode (
108 u32 mode)
109{
110
111 acpi_status status;
112 u32 retry;
113
114
115 ACPI_FUNCTION_TRACE ("hw_set_mode");
116
117 /*
118 * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
119 * system does not support mode transition.
120 */
121 if (!acpi_gbl_FADT->smi_cmd) {
122 ACPI_REPORT_ERROR (("No SMI_CMD in FADT, mode transition failed.\n"));
123 return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
124 }
125
126 /*
127 * ACPI 2.0 clarified the meaning of ACPI_ENABLE and ACPI_DISABLE
128 * in FADT: If it is zero, enabling or disabling is not supported.
129 * As old systems may have used zero for mode transition,
130 * we make sure both the numbers are zero to determine these
131 * transitions are not supported.
132 */
133 if (!acpi_gbl_FADT->acpi_enable && !acpi_gbl_FADT->acpi_disable) {
134 ACPI_REPORT_ERROR (("No ACPI mode transition supported in this system (enable/disable both zero)\n"));
135 return_ACPI_STATUS (AE_OK);
136 }
137
138 switch (mode) {
139 case ACPI_SYS_MODE_ACPI:
140
141 /* BIOS should have disabled ALL fixed and GP events */
142
143 status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd,
144 (u32) acpi_gbl_FADT->acpi_enable, 8);
145 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n"));
146 break;
147
148 case ACPI_SYS_MODE_LEGACY:
149
150 /*
151 * BIOS should clear all fixed status bits and restore fixed event
152 * enable bits to default
153 */
154 status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd,
155 (u32) acpi_gbl_FADT->acpi_disable, 8);
156 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
157 "Attempting to enable Legacy (non-ACPI) mode\n"));
158 break;
159
160 default:
161 return_ACPI_STATUS (AE_BAD_PARAMETER);
162 }
163
164 if (ACPI_FAILURE (status)) {
165 ACPI_REPORT_ERROR (("Could not write mode change, %s\n", acpi_format_exception (status)));
166 return_ACPI_STATUS (status);
167 }
168
169 /*
170 * Some hardware takes a LONG time to switch modes. Give them 3 sec to
171 * do so, but allow faster systems to proceed more quickly.
172 */
173 retry = 3000;
174 while (retry) {
175 if (acpi_hw_get_mode() == mode) {
176 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", mode));
177 return_ACPI_STATUS (AE_OK);
178 }
179 acpi_os_stall(1000);
180 retry--;
181 }
182
183 ACPI_REPORT_ERROR (("Hardware never changed modes\n"));
184 return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
185}
186
187
188/******************************************************************************
189 *
190 * FUNCTION: acpi_hw_get_mode
191 *
192 * PARAMETERS: none
193 *
194 * RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY
195 *
196 * DESCRIPTION: Return current operating state of system. Determined by
197 * querying the SCI_EN bit.
198 *
199 ******************************************************************************/
200
201u32
202acpi_hw_get_mode (void)
203{
204 acpi_status status;
205 u32 value;
206
207
208 ACPI_FUNCTION_TRACE ("hw_get_mode");
209
210
211 /*
212 * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
213 * system does not support mode transition.
214 */
215 if (!acpi_gbl_FADT->smi_cmd) {
216 return_VALUE (ACPI_SYS_MODE_ACPI);
217 }
218
219 status = acpi_get_register (ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK);
220 if (ACPI_FAILURE (status)) {
221 return_VALUE (ACPI_SYS_MODE_LEGACY);
222 }
223
224 if (value) {
225 return_VALUE (ACPI_SYS_MODE_ACPI);
226 }
227 else {
228 return_VALUE (ACPI_SYS_MODE_LEGACY);
229 }
230}
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
new file mode 100644
index 000000000000..9ac1d639bf51
--- /dev/null
+++ b/drivers/acpi/hardware/hwgpe.c
@@ -0,0 +1,444 @@
1
2/******************************************************************************
3 *
4 * Module Name: hwgpe - Low level GPE enable/disable/clear functions
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <acpi/acpi.h>
46#include <acpi/acevents.h>
47
48#define _COMPONENT ACPI_HARDWARE
49 ACPI_MODULE_NAME ("hwgpe")
50
51
52/******************************************************************************
53 *
54 * FUNCTION: acpi_hw_write_gpe_enable_reg
55 *
56 * PARAMETERS: gpe_event_info - Info block for the GPE to be enabled
57 *
58 * RETURN: Status
59 *
60 * DESCRIPTION: Write a GPE enable register. Note: The bit for this GPE must
61 * already be cleared or set in the parent register
62 * enable_for_run mask.
63 *
64 ******************************************************************************/
65
66acpi_status
67acpi_hw_write_gpe_enable_reg (
68 struct acpi_gpe_event_info *gpe_event_info)
69{
70 struct acpi_gpe_register_info *gpe_register_info;
71 acpi_status status;
72
73
74 ACPI_FUNCTION_ENTRY ();
75
76
77 /* Get the info block for the entire GPE register */
78
79 gpe_register_info = gpe_event_info->register_info;
80 if (!gpe_register_info) {
81 return (AE_NOT_EXIST);
82 }
83
84 /* Write the entire GPE (runtime) enable register */
85
86 status = acpi_hw_low_level_write (8, gpe_register_info->enable_for_run,
87 &gpe_register_info->enable_address);
88
89 return (status);
90}
91
92
93/******************************************************************************
94 *
95 * FUNCTION: acpi_hw_clear_gpe
96 *
97 * PARAMETERS: gpe_event_info - Info block for the GPE to be cleared
98 *
99 * RETURN: Status
100 *
101 * DESCRIPTION: Clear the status bit for a single GPE.
102 *
103 ******************************************************************************/
104
105acpi_status
106acpi_hw_clear_gpe (
107 struct acpi_gpe_event_info *gpe_event_info)
108{
109 acpi_status status;
110
111
112 ACPI_FUNCTION_ENTRY ();
113
114
115 /*
116 * Write a one to the appropriate bit in the status register to
117 * clear this GPE.
118 */
119 status = acpi_hw_low_level_write (8, gpe_event_info->register_bit,
120 &gpe_event_info->register_info->status_address);
121
122 return (status);
123}
124
125
126/******************************************************************************
127 *
128 * FUNCTION: acpi_hw_get_gpe_status
129 *
130 * PARAMETERS: gpe_event_info - Info block for the GPE to queried
131 * event_status - Where the GPE status is returned
132 *
133 * RETURN: Status
134 *
135 * DESCRIPTION: Return the status of a single GPE.
136 *
137 ******************************************************************************/
138#ifdef ACPI_FUTURE_USAGE
139acpi_status
140acpi_hw_get_gpe_status (
141 struct acpi_gpe_event_info *gpe_event_info,
142 acpi_event_status *event_status)
143{
144 u32 in_byte;
145 u8 register_bit;
146 struct acpi_gpe_register_info *gpe_register_info;
147 acpi_status status;
148 acpi_event_status local_event_status = 0;
149
150
151 ACPI_FUNCTION_ENTRY ();
152
153
154 if (!event_status) {
155 return (AE_BAD_PARAMETER);
156 }
157
158 /* Get the info block for the entire GPE register */
159
160 gpe_register_info = gpe_event_info->register_info;
161
162 /* Get the register bitmask for this GPE */
163
164 register_bit = gpe_event_info->register_bit;
165
166 /* GPE currently enabled? (enabled for runtime?) */
167
168 if (register_bit & gpe_register_info->enable_for_run) {
169 local_event_status |= ACPI_EVENT_FLAG_ENABLED;
170 }
171
172 /* GPE enabled for wake? */
173
174 if (register_bit & gpe_register_info->enable_for_wake) {
175 local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
176 }
177
178 /* GPE currently active (status bit == 1)? */
179
180 status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address);
181 if (ACPI_FAILURE (status)) {
182 goto unlock_and_exit;
183 }
184
185 if (register_bit & in_byte) {
186 local_event_status |= ACPI_EVENT_FLAG_SET;
187 }
188
189 /* Set return value */
190
191 (*event_status) = local_event_status;
192
193
194unlock_and_exit:
195 return (status);
196}
197#endif /* ACPI_FUTURE_USAGE */
198
199
200/******************************************************************************
201 *
202 * FUNCTION: acpi_hw_disable_gpe_block
203 *
204 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info
205 * gpe_block - Gpe Block info
206 *
207 * RETURN: Status
208 *
209 * DESCRIPTION: Disable all GPEs within a GPE block
210 *
211 ******************************************************************************/
212
213acpi_status
214acpi_hw_disable_gpe_block (
215 struct acpi_gpe_xrupt_info *gpe_xrupt_info,
216 struct acpi_gpe_block_info *gpe_block)
217{
218 u32 i;
219 acpi_status status;
220
221
222 /* Examine each GPE Register within the block */
223
224 for (i = 0; i < gpe_block->register_count; i++) {
225 /* Disable all GPEs in this register */
226
227 status = acpi_hw_low_level_write (8, 0x00,
228 &gpe_block->register_info[i].enable_address);
229 if (ACPI_FAILURE (status)) {
230 return (status);
231 }
232 }
233
234 return (AE_OK);
235}
236
237
238/******************************************************************************
239 *
240 * FUNCTION: acpi_hw_clear_gpe_block
241 *
242 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info
243 * gpe_block - Gpe Block info
244 *
245 * RETURN: Status
246 *
247 * DESCRIPTION: Clear status bits for all GPEs within a GPE block
248 *
249 ******************************************************************************/
250
251acpi_status
252acpi_hw_clear_gpe_block (
253 struct acpi_gpe_xrupt_info *gpe_xrupt_info,
254 struct acpi_gpe_block_info *gpe_block)
255{
256 u32 i;
257 acpi_status status;
258
259
260 /* Examine each GPE Register within the block */
261
262 for (i = 0; i < gpe_block->register_count; i++) {
263 /* Clear status on all GPEs in this register */
264
265 status = acpi_hw_low_level_write (8, 0xFF,
266 &gpe_block->register_info[i].status_address);
267 if (ACPI_FAILURE (status)) {
268 return (status);
269 }
270 }
271
272 return (AE_OK);
273}
274
275
276/******************************************************************************
277 *
278 * FUNCTION: acpi_hw_enable_runtime_gpe_block
279 *
280 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info
281 * gpe_block - Gpe Block info
282 *
283 * RETURN: Status
284 *
285 * DESCRIPTION: Enable all "runtime" GPEs within a GPE block. (Includes
286 * combination wake/run GPEs.)
287 *
288 ******************************************************************************/
289
290acpi_status
291acpi_hw_enable_runtime_gpe_block (
292 struct acpi_gpe_xrupt_info *gpe_xrupt_info,
293 struct acpi_gpe_block_info *gpe_block)
294{
295 u32 i;
296 acpi_status status;
297
298
299 /* NOTE: assumes that all GPEs are currently disabled */
300
301 /* Examine each GPE Register within the block */
302
303 for (i = 0; i < gpe_block->register_count; i++) {
304 if (!gpe_block->register_info[i].enable_for_run) {
305 continue;
306 }
307
308 /* Enable all "runtime" GPEs in this register */
309
310 status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_run,
311 &gpe_block->register_info[i].enable_address);
312 if (ACPI_FAILURE (status)) {
313 return (status);
314 }
315 }
316
317 return (AE_OK);
318}
319
320
321/******************************************************************************
322 *
323 * FUNCTION: acpi_hw_enable_wakeup_gpe_block
324 *
325 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info
326 * gpe_block - Gpe Block info
327 *
328 * RETURN: Status
329 *
330 * DESCRIPTION: Enable all "wake" GPEs within a GPE block. (Includes
331 * combination wake/run GPEs.)
332 *
333 ******************************************************************************/
334
335acpi_status
336acpi_hw_enable_wakeup_gpe_block (
337 struct acpi_gpe_xrupt_info *gpe_xrupt_info,
338 struct acpi_gpe_block_info *gpe_block)
339{
340 u32 i;
341 acpi_status status;
342
343
344 /* Examine each GPE Register within the block */
345
346 for (i = 0; i < gpe_block->register_count; i++) {
347 if (!gpe_block->register_info[i].enable_for_wake) {
348 continue;
349 }
350
351 /* Enable all "wake" GPEs in this register */
352
353 status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_wake,
354 &gpe_block->register_info[i].enable_address);
355 if (ACPI_FAILURE (status)) {
356 return (status);
357 }
358 }
359
360 return (AE_OK);
361}
362
363
364/******************************************************************************
365 *
366 * FUNCTION: acpi_hw_disable_all_gpes
367 *
368 * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR
369 *
370 * RETURN: Status
371 *
372 * DESCRIPTION: Disable and clear all GPEs
373 *
374 ******************************************************************************/
375
376acpi_status
377acpi_hw_disable_all_gpes (
378 u32 flags)
379{
380 acpi_status status;
381
382
383 ACPI_FUNCTION_TRACE ("hw_disable_all_gpes");
384
385
386 status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, flags);
387 status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, flags);
388 return_ACPI_STATUS (status);
389}
390
391
392/******************************************************************************
393 *
394 * FUNCTION: acpi_hw_enable_all_runtime_gpes
395 *
396 * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR
397 *
398 * RETURN: Status
399 *
400 * DESCRIPTION: Enable all GPEs of the given type
401 *
402 ******************************************************************************/
403
404acpi_status
405acpi_hw_enable_all_runtime_gpes (
406 u32 flags)
407{
408 acpi_status status;
409
410
411 ACPI_FUNCTION_TRACE ("hw_enable_all_runtime_gpes");
412
413
414 status = acpi_ev_walk_gpe_list (acpi_hw_enable_runtime_gpe_block, flags);
415 return_ACPI_STATUS (status);
416}
417
418
419/******************************************************************************
420 *
421 * FUNCTION: acpi_hw_enable_all_wakeup_gpes
422 *
423 * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR
424 *
425 * RETURN: Status
426 *
427 * DESCRIPTION: Enable all GPEs of the given type
428 *
429 ******************************************************************************/
430
431acpi_status
432acpi_hw_enable_all_wakeup_gpes (
433 u32 flags)
434{
435 acpi_status status;
436
437
438 ACPI_FUNCTION_TRACE ("hw_enable_all_wakeup_gpes");
439
440
441 status = acpi_ev_walk_gpe_list (acpi_hw_enable_wakeup_gpe_block, flags);
442 return_ACPI_STATUS (status);
443}
444
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
new file mode 100644
index 000000000000..91af0c2ddcf7
--- /dev/null
+++ b/drivers/acpi/hardware/hwregs.c
@@ -0,0 +1,850 @@
1
2/*******************************************************************************
3 *
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 * control and status registers.
6 *
7 ******************************************************************************/
8
9/*
10 * Copyright (C) 2000 - 2005, R. Byron Moore
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions, and the following disclaimer,
18 * without modification.
19 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
20 * substantially similar to the "NO WARRANTY" disclaimer below
21 * ("Disclaimer") and any redistribution must be conditioned upon
22 * including a substantially similar Disclaimer requirement for further
23 * binary redistribution.
24 * 3. Neither the names of the above-listed copyright holders nor the names
25 * of any contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * Alternatively, this software may be distributed under the terms of the
29 * GNU General Public License ("GPL") version 2 as published by the Free
30 * Software Foundation.
31 *
32 * NO WARRANTY
33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
34 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
35 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
36 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
42 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 * POSSIBILITY OF SUCH DAMAGES.
44 */
45
46#include <linux/module.h>
47
48#include <acpi/acpi.h>
49#include <acpi/acnamesp.h>
50#include <acpi/acevents.h>
51
52#define _COMPONENT ACPI_HARDWARE
53 ACPI_MODULE_NAME ("hwregs")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_hw_clear_acpi_status
59 *
60 * PARAMETERS: Flags - Lock the hardware or not
61 *
62 * RETURN: none
63 *
64 * DESCRIPTION: Clears all fixed and general purpose status bits
65 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
66 *
67 ******************************************************************************/
68
69acpi_status
70acpi_hw_clear_acpi_status (
71 u32 flags)
72{
73 acpi_status status;
74
75
76 ACPI_FUNCTION_TRACE ("hw_clear_acpi_status");
77
78
79 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
80 ACPI_BITMASK_ALL_FIXED_STATUS,
81 (u16) acpi_gbl_FADT->xpm1a_evt_blk.address));
82
83 if (flags & ACPI_MTX_LOCK) {
84 status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
85 if (ACPI_FAILURE (status)) {
86 return_ACPI_STATUS (status);
87 }
88 }
89
90 status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS,
91 ACPI_BITMASK_ALL_FIXED_STATUS);
92 if (ACPI_FAILURE (status)) {
93 goto unlock_and_exit;
94 }
95
96 /* Clear the fixed events */
97
98 if (acpi_gbl_FADT->xpm1b_evt_blk.address) {
99 status = acpi_hw_low_level_write (16, ACPI_BITMASK_ALL_FIXED_STATUS,
100 &acpi_gbl_FADT->xpm1b_evt_blk);
101 if (ACPI_FAILURE (status)) {
102 goto unlock_and_exit;
103 }
104 }
105
106 /* Clear the GPE Bits in all GPE registers in all GPE blocks */
107
108 status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, ACPI_ISR);
109
110unlock_and_exit:
111 if (flags & ACPI_MTX_LOCK) {
112 (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
113 }
114 return_ACPI_STATUS (status);
115}
116
117
118/*******************************************************************************
119 *
120 * FUNCTION: acpi_get_sleep_type_data
121 *
122 * PARAMETERS: sleep_state - Numeric sleep state
123 * *sleep_type_a - Where SLP_TYPa is returned
124 * *sleep_type_b - Where SLP_TYPb is returned
125 *
126 * RETURN: Status - ACPI status
127 *
128 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
129 * state.
130 *
131 ******************************************************************************/
132
133acpi_status
134acpi_get_sleep_type_data (
135 u8 sleep_state,
136 u8 *sleep_type_a,
137 u8 *sleep_type_b)
138{
139 acpi_status status = AE_OK;
140 struct acpi_parameter_info info;
141
142
143 ACPI_FUNCTION_TRACE ("acpi_get_sleep_type_data");
144
145
146 /*
147 * Validate parameters
148 */
149 if ((sleep_state > ACPI_S_STATES_MAX) ||
150 !sleep_type_a || !sleep_type_b) {
151 return_ACPI_STATUS (AE_BAD_PARAMETER);
152 }
153
154 /*
155 * Evaluate the namespace object containing the values for this state
156 */
157 info.parameters = NULL;
158 status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_sleep_state_names[sleep_state],
159 &info);
160 if (ACPI_FAILURE (status)) {
161 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating sleep_state [%s]\n",
162 acpi_format_exception (status), acpi_gbl_sleep_state_names[sleep_state]));
163
164 return_ACPI_STATUS (status);
165 }
166
167 /* Must have a return object */
168
169 if (!info.return_object) {
170 ACPI_REPORT_ERROR (("Missing Sleep State object\n"));
171 status = AE_NOT_EXIST;
172 }
173
174 /* It must be of type Package */
175
176 else if (ACPI_GET_OBJECT_TYPE (info.return_object) != ACPI_TYPE_PACKAGE) {
177 ACPI_REPORT_ERROR (("Sleep State object not a Package\n"));
178 status = AE_AML_OPERAND_TYPE;
179 }
180
181 /* The package must have at least two elements */
182
183 else if (info.return_object->package.count < 2) {
184 ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
185 status = AE_AML_NO_OPERAND;
186 }
187
188 /* The first two elements must both be of type Integer */
189
190 else if ((ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[0]) != ACPI_TYPE_INTEGER) ||
191 (ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[1]) != ACPI_TYPE_INTEGER)) {
192 ACPI_REPORT_ERROR (("Sleep State package elements are not both Integers (%s, %s)\n",
193 acpi_ut_get_object_type_name (info.return_object->package.elements[0]),
194 acpi_ut_get_object_type_name (info.return_object->package.elements[1])));
195 status = AE_AML_OPERAND_TYPE;
196 }
197 else {
198 /*
199 * Valid _Sx_ package size, type, and value
200 */
201 *sleep_type_a = (u8) (info.return_object->package.elements[0])->integer.value;
202 *sleep_type_b = (u8) (info.return_object->package.elements[1])->integer.value;
203 }
204
205 if (ACPI_FAILURE (status)) {
206 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
207 "While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
208 acpi_gbl_sleep_state_names[sleep_state], info.return_object,
209 acpi_ut_get_object_type_name (info.return_object)));
210 }
211
212 acpi_ut_remove_reference (info.return_object);
213 return_ACPI_STATUS (status);
214}
215EXPORT_SYMBOL(acpi_get_sleep_type_data);
216
217
218/*******************************************************************************
219 *
220 * FUNCTION: acpi_hw_get_register_bit_mask
221 *
222 * PARAMETERS: register_id - Index of ACPI Register to access
223 *
224 * RETURN: The bit mask to be used when accessing the register
225 *
226 * DESCRIPTION: Map register_id into a register bit mask.
227 *
228 ******************************************************************************/
229
230struct acpi_bit_register_info *
231acpi_hw_get_bit_register_info (
232 u32 register_id)
233{
234 ACPI_FUNCTION_NAME ("hw_get_bit_register_info");
235
236
237 if (register_id > ACPI_BITREG_MAX) {
238 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid bit_register ID: %X\n", register_id));
239 return (NULL);
240 }
241
242 return (&acpi_gbl_bit_register_info[register_id]);
243}
244
245
246/*******************************************************************************
247 *
248 * FUNCTION: acpi_get_register
249 *
250 * PARAMETERS: register_id - ID of ACPI bit_register to access
251 * return_value - Value that was read from the register
252 * Flags - Lock the hardware or not
253 *
254 * RETURN: Status and the value read from specified Register. Value
255 * returned is normalized to bit0 (is shifted all the way right)
256 *
257 * DESCRIPTION: ACPI bit_register read function.
258 *
259 ******************************************************************************/
260
261acpi_status
262acpi_get_register (
263 u32 register_id,
264 u32 *return_value,
265 u32 flags)
266{
267 u32 register_value = 0;
268 struct acpi_bit_register_info *bit_reg_info;
269 acpi_status status;
270
271
272 ACPI_FUNCTION_TRACE ("acpi_get_register");
273
274
275 /* Get the info structure corresponding to the requested ACPI Register */
276
277 bit_reg_info = acpi_hw_get_bit_register_info (register_id);
278 if (!bit_reg_info) {
279 return_ACPI_STATUS (AE_BAD_PARAMETER);
280 }
281
282 if (flags & ACPI_MTX_LOCK) {
283 status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
284 if (ACPI_FAILURE (status)) {
285 return_ACPI_STATUS (status);
286 }
287 }
288
289 /* Read from the register */
290
291 status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
292 bit_reg_info->parent_register, &register_value);
293
294 if (flags & ACPI_MTX_LOCK) {
295 (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
296 }
297
298 if (ACPI_SUCCESS (status)) {
299 /* Normalize the value that was read */
300
301 register_value = ((register_value & bit_reg_info->access_bit_mask)
302 >> bit_reg_info->bit_position);
303
304 *return_value = register_value;
305
306 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
307 register_value, bit_reg_info->parent_register));
308 }
309
310 return_ACPI_STATUS (status);
311}
312EXPORT_SYMBOL(acpi_get_register);
313
314
315/*******************************************************************************
316 *
317 * FUNCTION: acpi_set_register
318 *
319 * PARAMETERS: register_id - ID of ACPI bit_register to access
320 * Value - (only used on write) value to write to the
321 * Register, NOT pre-normalized to the bit pos
322 * Flags - Lock the hardware or not
323 *
324 * RETURN: Status
325 *
326 * DESCRIPTION: ACPI Bit Register write function.
327 *
328 ******************************************************************************/
329
330acpi_status
331acpi_set_register (
332 u32 register_id,
333 u32 value,
334 u32 flags)
335{
336 u32 register_value = 0;
337 struct acpi_bit_register_info *bit_reg_info;
338 acpi_status status;
339
340
341 ACPI_FUNCTION_TRACE_U32 ("acpi_set_register", register_id);
342
343
344 /* Get the info structure corresponding to the requested ACPI Register */
345
346 bit_reg_info = acpi_hw_get_bit_register_info (register_id);
347 if (!bit_reg_info) {
348 ACPI_REPORT_ERROR (("Bad ACPI HW register_id: %X\n", register_id));
349 return_ACPI_STATUS (AE_BAD_PARAMETER);
350 }
351
352 if (flags & ACPI_MTX_LOCK) {
353 status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
354 if (ACPI_FAILURE (status)) {
355 return_ACPI_STATUS (status);
356 }
357 }
358
359 /* Always do a register read first so we can insert the new bits */
360
361 status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
362 bit_reg_info->parent_register, &register_value);
363 if (ACPI_FAILURE (status)) {
364 goto unlock_and_exit;
365 }
366
367 /*
368 * Decode the Register ID
369 * Register ID = [Register block ID] | [bit ID]
370 *
371 * Check bit ID to fine locate Register offset.
372 * Check Mask to determine Register offset, and then read-write.
373 */
374 switch (bit_reg_info->parent_register) {
375 case ACPI_REGISTER_PM1_STATUS:
376
377 /*
378 * Status Registers are different from the rest. Clear by
379 * writing 1, and writing 0 has no effect. So, the only relevant
380 * information is the single bit we're interested in, all others should
381 * be written as 0 so they will be left unchanged.
382 */
383 value = ACPI_REGISTER_PREPARE_BITS (value,
384 bit_reg_info->bit_position, bit_reg_info->access_bit_mask);
385 if (value) {
386 status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
387 ACPI_REGISTER_PM1_STATUS, (u16) value);
388 register_value = 0;
389 }
390 break;
391
392
393 case ACPI_REGISTER_PM1_ENABLE:
394
395 ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
396 bit_reg_info->access_bit_mask, value);
397
398 status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
399 ACPI_REGISTER_PM1_ENABLE, (u16) register_value);
400 break;
401
402
403 case ACPI_REGISTER_PM1_CONTROL:
404
405 /*
406 * Write the PM1 Control register.
407 * Note that at this level, the fact that there are actually TWO
408 * registers (A and B - and B may not exist) is abstracted.
409 */
410 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value));
411
412 ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
413 bit_reg_info->access_bit_mask, value);
414
415 status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
416 ACPI_REGISTER_PM1_CONTROL, (u16) register_value);
417 break;
418
419
420 case ACPI_REGISTER_PM2_CONTROL:
421
422 status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
423 ACPI_REGISTER_PM2_CONTROL, &register_value);
424 if (ACPI_FAILURE (status)) {
425 goto unlock_and_exit;
426 }
427
428 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
429 register_value,
430 ACPI_FORMAT_UINT64 (acpi_gbl_FADT->xpm2_cnt_blk.address)));
431
432 ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
433 bit_reg_info->access_bit_mask, value);
434
435 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n",
436 register_value,
437 ACPI_FORMAT_UINT64 (acpi_gbl_FADT->xpm2_cnt_blk.address)));
438
439 status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
440 ACPI_REGISTER_PM2_CONTROL, (u8) (register_value));
441 break;
442
443
444 default:
445 break;
446 }
447
448
449unlock_and_exit:
450
451 if (flags & ACPI_MTX_LOCK) {
452 (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
453 }
454
455 /* Normalize the value that was read */
456
457 ACPI_DEBUG_EXEC (register_value = ((register_value & bit_reg_info->access_bit_mask) >> bit_reg_info->bit_position));
458
459 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
460 value, register_value, bit_reg_info->parent_register));
461 return_ACPI_STATUS (status);
462}
463EXPORT_SYMBOL(acpi_set_register);
464
465
466/******************************************************************************
467 *
468 * FUNCTION: acpi_hw_register_read
469 *
470 * PARAMETERS: use_lock - Mutex hw access
471 * register_id - register_iD + Offset
472 * return_value - Value that was read from the register
473 *
474 * RETURN: Status and the value read.
475 *
476 * DESCRIPTION: Acpi register read function. Registers are read at the
477 * given offset.
478 *
479 ******************************************************************************/
480
481acpi_status
482acpi_hw_register_read (
483 u8 use_lock,
484 u32 register_id,
485 u32 *return_value)
486{
487 u32 value1 = 0;
488 u32 value2 = 0;
489 acpi_status status;
490
491
492 ACPI_FUNCTION_TRACE ("hw_register_read");
493
494
495 if (ACPI_MTX_LOCK == use_lock) {
496 status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
497 if (ACPI_FAILURE (status)) {
498 return_ACPI_STATUS (status);
499 }
500 }
501
502 switch (register_id) {
503 case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
504
505 status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_evt_blk);
506 if (ACPI_FAILURE (status)) {
507 goto unlock_and_exit;
508 }
509
510 /* PM1B is optional */
511
512 status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_evt_blk);
513 value1 |= value2;
514 break;
515
516
517 case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
518
519 status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_xpm1a_enable);
520 if (ACPI_FAILURE (status)) {
521 goto unlock_and_exit;
522 }
523
524 /* PM1B is optional */
525
526 status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_xpm1b_enable);
527 value1 |= value2;
528 break;
529
530
531 case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
532
533 status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_cnt_blk);
534 if (ACPI_FAILURE (status)) {
535 goto unlock_and_exit;
536 }
537
538 status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_cnt_blk);
539 value1 |= value2;
540 break;
541
542
543 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
544
545 status = acpi_hw_low_level_read (8, &value1, &acpi_gbl_FADT->xpm2_cnt_blk);
546 break;
547
548
549 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
550
551 status = acpi_hw_low_level_read (32, &value1, &acpi_gbl_FADT->xpm_tmr_blk);
552 break;
553
554 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
555
556 status = acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value1, 8);
557 break;
558
559 default:
560 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Register ID: %X\n", register_id));
561 status = AE_BAD_PARAMETER;
562 break;
563 }
564
565unlock_and_exit:
566 if (ACPI_MTX_LOCK == use_lock) {
567 (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
568 }
569
570 if (ACPI_SUCCESS (status)) {
571 *return_value = value1;
572 }
573
574 return_ACPI_STATUS (status);
575}
576
577
578/******************************************************************************
579 *
580 * FUNCTION: acpi_hw_register_write
581 *
582 * PARAMETERS: use_lock - Mutex hw access
583 * register_id - register_iD + Offset
584 * Value - The value to write
585 *
586 * RETURN: Status
587 *
588 * DESCRIPTION: Acpi register Write function. Registers are written at the
589 * given offset.
590 *
591 ******************************************************************************/
592
593acpi_status
594acpi_hw_register_write (
595 u8 use_lock,
596 u32 register_id,
597 u32 value)
598{
599 acpi_status status;
600
601
602 ACPI_FUNCTION_TRACE ("hw_register_write");
603
604
605 if (ACPI_MTX_LOCK == use_lock) {
606 status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
607 if (ACPI_FAILURE (status)) {
608 return_ACPI_STATUS (status);
609 }
610 }
611
612 switch (register_id) {
613 case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
614
615 status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_evt_blk);
616 if (ACPI_FAILURE (status)) {
617 goto unlock_and_exit;
618 }
619
620 /* PM1B is optional */
621
622 status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_evt_blk);
623 break;
624
625
626 case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/
627
628 status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1a_enable);
629 if (ACPI_FAILURE (status)) {
630 goto unlock_and_exit;
631 }
632
633 /* PM1B is optional */
634
635 status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1b_enable);
636 break;
637
638
639 case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
640
641 status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk);
642 if (ACPI_FAILURE (status)) {
643 goto unlock_and_exit;
644 }
645
646 status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk);
647 break;
648
649
650 case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */
651
652 status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk);
653 break;
654
655
656 case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */
657
658 status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk);
659 break;
660
661
662 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
663
664 status = acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->xpm2_cnt_blk);
665 break;
666
667
668 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
669
670 status = acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->xpm_tmr_blk);
671 break;
672
673
674 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
675
676 /* SMI_CMD is currently always in IO space */
677
678 status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, value, 8);
679 break;
680
681
682 default:
683 status = AE_BAD_PARAMETER;
684 break;
685 }
686
687unlock_and_exit:
688 if (ACPI_MTX_LOCK == use_lock) {
689 (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
690 }
691
692 return_ACPI_STATUS (status);
693}
694
695
696/******************************************************************************
697 *
698 * FUNCTION: acpi_hw_low_level_read
699 *
700 * PARAMETERS: Width - 8, 16, or 32
701 * Value - Where the value is returned
702 * Reg - GAS register structure
703 *
704 * RETURN: Status
705 *
706 * DESCRIPTION: Read from either memory or IO space.
707 *
708 ******************************************************************************/
709
710acpi_status
711acpi_hw_low_level_read (
712 u32 width,
713 u32 *value,
714 struct acpi_generic_address *reg)
715{
716 u64 address;
717 acpi_status status;
718
719
720 ACPI_FUNCTION_NAME ("hw_low_level_read");
721
722
723 /*
724 * Must have a valid pointer to a GAS structure, and
725 * a non-zero address within. However, don't return an error
726 * because the PM1A/B code must not fail if B isn't present.
727 */
728 if (!reg) {
729 return (AE_OK);
730 }
731
732 /* Get a local copy of the address. Handles possible alignment issues */
733
734 ACPI_MOVE_64_TO_64 (&address, &reg->address);
735 if (!address) {
736 return (AE_OK);
737 }
738 *value = 0;
739
740 /*
741 * Two address spaces supported: Memory or IO.
742 * PCI_Config is not supported here because the GAS struct is insufficient
743 */
744 switch (reg->address_space_id) {
745 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
746
747 status = acpi_os_read_memory (
748 (acpi_physical_address) address,
749 value, width);
750 break;
751
752
753 case ACPI_ADR_SPACE_SYSTEM_IO:
754
755 status = acpi_os_read_port ((acpi_io_address) address,
756 value, width);
757 break;
758
759
760 default:
761 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
762 "Unsupported address space: %X\n", reg->address_space_id));
763 return (AE_BAD_PARAMETER);
764 }
765
766 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
767 *value, width,
768 ACPI_FORMAT_UINT64 (address),
769 acpi_ut_get_region_name (reg->address_space_id)));
770
771 return (status);
772}
773
774
775/******************************************************************************
776 *
777 * FUNCTION: acpi_hw_low_level_write
778 *
779 * PARAMETERS: Width - 8, 16, or 32
780 * Value - To be written
781 * Reg - GAS register structure
782 *
783 * RETURN: Status
784 *
785 * DESCRIPTION: Write to either memory or IO space.
786 *
787 ******************************************************************************/
788
789acpi_status
790acpi_hw_low_level_write (
791 u32 width,
792 u32 value,
793 struct acpi_generic_address *reg)
794{
795 u64 address;
796 acpi_status status;
797
798
799 ACPI_FUNCTION_NAME ("hw_low_level_write");
800
801
802 /*
803 * Must have a valid pointer to a GAS structure, and
804 * a non-zero address within. However, don't return an error
805 * because the PM1A/B code must not fail if B isn't present.
806 */
807 if (!reg) {
808 return (AE_OK);
809 }
810
811 /* Get a local copy of the address. Handles possible alignment issues */
812
813 ACPI_MOVE_64_TO_64 (&address, &reg->address);
814 if (!address) {
815 return (AE_OK);
816 }
817
818 /*
819 * Two address spaces supported: Memory or IO.
820 * PCI_Config is not supported here because the GAS struct is insufficient
821 */
822 switch (reg->address_space_id) {
823 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
824
825 status = acpi_os_write_memory (
826 (acpi_physical_address) address,
827 value, width);
828 break;
829
830
831 case ACPI_ADR_SPACE_SYSTEM_IO:
832
833 status = acpi_os_write_port ((acpi_io_address) address,
834 value, width);
835 break;
836
837
838 default:
839 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
840 "Unsupported address space: %X\n", reg->address_space_id));
841 return (AE_BAD_PARAMETER);
842 }
843
844 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
845 value, width,
846 ACPI_FORMAT_UINT64 (address),
847 acpi_ut_get_region_name (reg->address_space_id)));
848
849 return (status);
850}
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
new file mode 100644
index 000000000000..77b3e9a8550b
--- /dev/null
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -0,0 +1,582 @@
1
2/******************************************************************************
3 *
4 * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <linux/module.h>
46
47#include <acpi/acpi.h>
48
49#define _COMPONENT ACPI_HARDWARE
50 ACPI_MODULE_NAME ("hwsleep")
51
52
53#define METHOD_NAME__BFS "\\_BFS"
54#define METHOD_NAME__GTS "\\_GTS"
55#define METHOD_NAME__PTS "\\_PTS"
56#define METHOD_NAME__SST "\\_SI._SST"
57#define METHOD_NAME__WAK "\\_WAK"
58
59#define ACPI_SST_INDICATOR_OFF 0
60#define ACPI_SST_WORKING 1
61#define ACPI_SST_WAKING 2
62#define ACPI_SST_SLEEPING 3
63#define ACPI_SST_SLEEP_CONTEXT 4
64
65
66/******************************************************************************
67 *
68 * FUNCTION: acpi_set_firmware_waking_vector
69 *
70 * PARAMETERS: physical_address - Physical address of ACPI real mode
71 * entry point.
72 *
73 * RETURN: Status
74 *
75 * DESCRIPTION: access function for d_firmware_waking_vector field in FACS
76 *
77 ******************************************************************************/
78
79acpi_status
80acpi_set_firmware_waking_vector (
81 acpi_physical_address physical_address)
82{
83
84 ACPI_FUNCTION_TRACE ("acpi_set_firmware_waking_vector");
85
86
87 /* Set the vector */
88
89 if (acpi_gbl_common_fACS.vector_width == 32) {
90 *(ACPI_CAST_PTR (u32, acpi_gbl_common_fACS.firmware_waking_vector))
91 = (u32) physical_address;
92 }
93 else {
94 *acpi_gbl_common_fACS.firmware_waking_vector
95 = physical_address;
96 }
97
98 return_ACPI_STATUS (AE_OK);
99}
100
101
102/******************************************************************************
103 *
104 * FUNCTION: acpi_get_firmware_waking_vector
105 *
106 * PARAMETERS: *physical_address - Output buffer where contents of
107 * the firmware_waking_vector field of
108 * the FACS will be stored.
109 *
110 * RETURN: Status
111 *
112 * DESCRIPTION: Access function for firmware_waking_vector field in FACS
113 *
114 ******************************************************************************/
115#ifdef ACPI_FUTURE_USAGE
116acpi_status
117acpi_get_firmware_waking_vector (
118 acpi_physical_address *physical_address)
119{
120
121 ACPI_FUNCTION_TRACE ("acpi_get_firmware_waking_vector");
122
123
124 if (!physical_address) {
125 return_ACPI_STATUS (AE_BAD_PARAMETER);
126 }
127
128 /* Get the vector */
129
130 if (acpi_gbl_common_fACS.vector_width == 32) {
131 *physical_address = (acpi_physical_address)
132 *(ACPI_CAST_PTR (u32, acpi_gbl_common_fACS.firmware_waking_vector));
133 }
134 else {
135 *physical_address =
136 *acpi_gbl_common_fACS.firmware_waking_vector;
137 }
138
139 return_ACPI_STATUS (AE_OK);
140}
141#endif
142
143
144/******************************************************************************
145 *
146 * FUNCTION: acpi_enter_sleep_state_prep
147 *
148 * PARAMETERS: sleep_state - Which sleep state to enter
149 *
150 * RETURN: Status
151 *
152 * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231)
153 * This function must execute with interrupts enabled.
154 * We break sleeping into 2 stages so that OSPM can handle
155 * various OS-specific tasks between the two steps.
156 *
157 ******************************************************************************/
158
159acpi_status
160acpi_enter_sleep_state_prep (
161 u8 sleep_state)
162{
163 acpi_status status;
164 struct acpi_object_list arg_list;
165 union acpi_object arg;
166
167
168 ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state_prep");
169
170
171 /*
172 * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
173 */
174 status = acpi_get_sleep_type_data (sleep_state,
175 &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b);
176 if (ACPI_FAILURE (status)) {
177 return_ACPI_STATUS (status);
178 }
179
180 /* Setup parameter object */
181
182 arg_list.count = 1;
183 arg_list.pointer = &arg;
184
185 arg.type = ACPI_TYPE_INTEGER;
186 arg.integer.value = sleep_state;
187
188 /* Run the _PTS and _GTS methods */
189
190 status = acpi_evaluate_object (NULL, METHOD_NAME__PTS, &arg_list, NULL);
191 if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
192 return_ACPI_STATUS (status);
193 }
194
195 status = acpi_evaluate_object (NULL, METHOD_NAME__GTS, &arg_list, NULL);
196 if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
197 return_ACPI_STATUS (status);
198 }
199
200 /* Setup the argument to _SST */
201
202 switch (sleep_state) {
203 case ACPI_STATE_S0:
204 arg.integer.value = ACPI_SST_WORKING;
205 break;
206
207 case ACPI_STATE_S1:
208 case ACPI_STATE_S2:
209 case ACPI_STATE_S3:
210 arg.integer.value = ACPI_SST_SLEEPING;
211 break;
212
213 case ACPI_STATE_S4:
214 arg.integer.value = ACPI_SST_SLEEP_CONTEXT;
215 break;
216
217 default:
218 arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is indicator off */
219 break;
220 }
221
222 /* Set the system indicators to show the desired sleep state. */
223
224 status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
225 if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
226 ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
227 }
228
229 return_ACPI_STATUS (AE_OK);
230}
231
232
233/******************************************************************************
234 *
235 * FUNCTION: acpi_enter_sleep_state
236 *
237 * PARAMETERS: sleep_state - Which sleep state to enter
238 *
239 * RETURN: Status
240 *
241 * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
242 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
243 *
244 ******************************************************************************/
245
246acpi_status asmlinkage
247acpi_enter_sleep_state (
248 u8 sleep_state)
249{
250 u32 PM1Acontrol;
251 u32 PM1Bcontrol;
252 struct acpi_bit_register_info *sleep_type_reg_info;
253 struct acpi_bit_register_info *sleep_enable_reg_info;
254 u32 in_value;
255 acpi_status status;
256
257
258 ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state");
259
260
261 if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
262 (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
263 ACPI_REPORT_ERROR (("Sleep values out of range: A=%X B=%X\n",
264 acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
265 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
266 }
267
268 sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
269 sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
270
271 /* Clear wake status */
272
273 status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
274 if (ACPI_FAILURE (status)) {
275 return_ACPI_STATUS (status);
276 }
277
278 /* Clear all fixed and general purpose status bits */
279
280 status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
281 if (ACPI_FAILURE (status)) {
282 return_ACPI_STATUS (status);
283 }
284
285 /*
286 * 1) Disable/Clear all GPEs
287 * 2) Enable all wakeup GPEs
288 */
289 status = acpi_hw_disable_all_gpes (ACPI_ISR);
290 if (ACPI_FAILURE (status)) {
291 return_ACPI_STATUS (status);
292 }
293 acpi_gbl_system_awake_and_running = FALSE;
294
295 status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
296 if (ACPI_FAILURE (status)) {
297 return_ACPI_STATUS (status);
298 }
299
300 /* Get current value of PM1A control */
301
302 status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
303 if (ACPI_FAILURE (status)) {
304 return_ACPI_STATUS (status);
305 }
306 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Entering sleep state [S%d]\n", sleep_state));
307
308 /* Clear SLP_EN and SLP_TYP fields */
309
310 PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | sleep_enable_reg_info->access_bit_mask);
311 PM1Bcontrol = PM1Acontrol;
312
313 /* Insert SLP_TYP bits */
314
315 PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
316 PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
317
318 /*
319 * We split the writes of SLP_TYP and SLP_EN to workaround
320 * poorly implemented hardware.
321 */
322
323 /* Write #1: fill in SLP_TYP data */
324
325 status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
326 if (ACPI_FAILURE (status)) {
327 return_ACPI_STATUS (status);
328 }
329
330 status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
331 if (ACPI_FAILURE (status)) {
332 return_ACPI_STATUS (status);
333 }
334
335 /* Insert SLP_ENABLE bit */
336
337 PM1Acontrol |= sleep_enable_reg_info->access_bit_mask;
338 PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask;
339
340 /* Write #2: SLP_TYP + SLP_EN */
341
342 ACPI_FLUSH_CPU_CACHE ();
343
344 status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
345 if (ACPI_FAILURE (status)) {
346 return_ACPI_STATUS (status);
347 }
348
349 status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
350 if (ACPI_FAILURE (status)) {
351 return_ACPI_STATUS (status);
352 }
353
354 if (sleep_state > ACPI_STATE_S3) {
355 /*
356 * We wanted to sleep > S3, but it didn't happen (by virtue of the fact that
357 * we are still executing!)
358 *
359 * Wait ten seconds, then try again. This is to get S4/S5 to work on all machines.
360 *
361 * We wait so long to allow chipsets that poll this reg very slowly to
362 * still read the right value. Ideally, this block would go
363 * away entirely.
364 */
365 acpi_os_stall (10000000);
366
367 status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL,
368 sleep_enable_reg_info->access_bit_mask);
369 if (ACPI_FAILURE (status)) {
370 return_ACPI_STATUS (status);
371 }
372 }
373
374 /* Wait until we enter sleep state */
375
376 do {
377 status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value, ACPI_MTX_DO_NOT_LOCK);
378 if (ACPI_FAILURE (status)) {
379 return_ACPI_STATUS (status);
380 }
381
382 /* Spin until we wake */
383
384 } while (!in_value);
385
386 return_ACPI_STATUS (AE_OK);
387}
388EXPORT_SYMBOL(acpi_enter_sleep_state);
389
390
391/******************************************************************************
392 *
393 * FUNCTION: acpi_enter_sleep_state_s4bios
394 *
395 * PARAMETERS: None
396 *
397 * RETURN: Status
398 *
399 * DESCRIPTION: Perform a S4 bios request.
400 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
401 *
402 ******************************************************************************/
403
404acpi_status asmlinkage
405acpi_enter_sleep_state_s4bios (
406 void)
407{
408 u32 in_value;
409 acpi_status status;
410
411
412 ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state_s4bios");
413
414
415 status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
416 if (ACPI_FAILURE (status)) {
417 return_ACPI_STATUS (status);
418 }
419
420 status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
421 if (ACPI_FAILURE (status)) {
422 return_ACPI_STATUS (status);
423 }
424
425 /*
426 * 1) Disable/Clear all GPEs
427 * 2) Enable all wakeup GPEs
428 */
429 status = acpi_hw_disable_all_gpes (ACPI_ISR);
430 if (ACPI_FAILURE (status)) {
431 return_ACPI_STATUS (status);
432 }
433 acpi_gbl_system_awake_and_running = FALSE;
434
435 status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
436 if (ACPI_FAILURE (status)) {
437 return_ACPI_STATUS (status);
438 }
439
440 ACPI_FLUSH_CPU_CACHE ();
441
442 status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, (u32) acpi_gbl_FADT->S4bios_req, 8);
443
444 do {
445 acpi_os_stall(1000);
446 status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value, ACPI_MTX_DO_NOT_LOCK);
447 if (ACPI_FAILURE (status)) {
448 return_ACPI_STATUS (status);
449 }
450 } while (!in_value);
451
452 return_ACPI_STATUS (AE_OK);
453}
454EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios);
455
456
457/******************************************************************************
458 *
459 * FUNCTION: acpi_leave_sleep_state
460 *
461 * PARAMETERS: sleep_state - Which sleep state we just exited
462 *
463 * RETURN: Status
464 *
465 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
466 * Called with interrupts ENABLED.
467 *
468 ******************************************************************************/
469
470acpi_status
471acpi_leave_sleep_state (
472 u8 sleep_state)
473{
474 struct acpi_object_list arg_list;
475 union acpi_object arg;
476 acpi_status status;
477 struct acpi_bit_register_info *sleep_type_reg_info;
478 struct acpi_bit_register_info *sleep_enable_reg_info;
479 u32 PM1Acontrol;
480 u32 PM1Bcontrol;
481
482
483 ACPI_FUNCTION_TRACE ("acpi_leave_sleep_state");
484
485
486 /*
487 * Set SLP_TYPE and SLP_EN to state S0.
488 * This is unclear from the ACPI Spec, but it is required
489 * by some machines.
490 */
491 status = acpi_get_sleep_type_data (ACPI_STATE_S0,
492 &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b);
493 if (ACPI_SUCCESS (status)) {
494 sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
495 sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
496
497 /* Get current value of PM1A control */
498
499 status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
500 ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
501 if (ACPI_SUCCESS (status)) {
502 /* Clear SLP_EN and SLP_TYP fields */
503
504 PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
505 sleep_enable_reg_info->access_bit_mask);
506 PM1Bcontrol = PM1Acontrol;
507
508 /* Insert SLP_TYP bits */
509
510 PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
511 PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
512
513 /* Just ignore any errors */
514
515 (void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
516 ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
517 (void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
518 ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
519 }
520 }
521
522 /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
523
524 acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
525
526 /* Setup parameter object */
527
528 arg_list.count = 1;
529 arg_list.pointer = &arg;
530 arg.type = ACPI_TYPE_INTEGER;
531
532 /* Ignore any errors from these methods */
533
534 arg.integer.value = ACPI_SST_WAKING;
535 status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
536 if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
537 ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
538 }
539
540 arg.integer.value = sleep_state;
541 status = acpi_evaluate_object (NULL, METHOD_NAME__BFS, &arg_list, NULL);
542 if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
543 ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", acpi_format_exception (status)));
544 }
545
546 status = acpi_evaluate_object (NULL, METHOD_NAME__WAK, &arg_list, NULL);
547 if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
548 ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", acpi_format_exception (status)));
549 }
550 /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
551
552 /*
553 * Restore the GPEs:
554 * 1) Disable/Clear all GPEs
555 * 2) Enable all runtime GPEs
556 */
557 status = acpi_hw_disable_all_gpes (ACPI_NOT_ISR);
558 if (ACPI_FAILURE (status)) {
559 return_ACPI_STATUS (status);
560 }
561 acpi_gbl_system_awake_and_running = TRUE;
562
563 status = acpi_hw_enable_all_runtime_gpes (ACPI_NOT_ISR);
564 if (ACPI_FAILURE (status)) {
565 return_ACPI_STATUS (status);
566 }
567
568 /* Enable power button */
569
570 (void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
571 1, ACPI_MTX_DO_NOT_LOCK);
572 (void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
573 1, ACPI_MTX_DO_NOT_LOCK);
574
575 arg.integer.value = ACPI_SST_WORKING;
576 status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
577 if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
578 ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
579 }
580
581 return_ACPI_STATUS (status);
582}
diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
new file mode 100644
index 000000000000..1906167d7294
--- /dev/null
+++ b/drivers/acpi/hardware/hwtimer.c
@@ -0,0 +1,203 @@
1
2/******************************************************************************
3 *
4 * Name: hwtimer.c - ACPI Power Management Timer Interface
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <linux/module.h>
46
47#include <acpi/acpi.h>
48
49#define _COMPONENT ACPI_HARDWARE
50 ACPI_MODULE_NAME ("hwtimer")
51
52
53/******************************************************************************
54 *
55 * FUNCTION: acpi_get_timer_resolution
56 *
57 * PARAMETERS: Resolution - Where the resolution is returned
58 *
59 * RETURN: Status and timer resolution
60 *
61 * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
62 *
63 ******************************************************************************/
64
65acpi_status
66acpi_get_timer_resolution (
67 u32 *resolution)
68{
69 ACPI_FUNCTION_TRACE ("acpi_get_timer_resolution");
70
71
72 if (!resolution) {
73 return_ACPI_STATUS (AE_BAD_PARAMETER);
74 }
75
76 if (0 == acpi_gbl_FADT->tmr_val_ext) {
77 *resolution = 24;
78 }
79 else {
80 *resolution = 32;
81 }
82
83 return_ACPI_STATUS (AE_OK);
84}
85
86
87/******************************************************************************
88 *
89 * FUNCTION: acpi_get_timer
90 *
91 * PARAMETERS: Ticks - Where the timer value is returned
92 *
93 * RETURN: Status and current ticks
94 *
95 * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
96 *
97 ******************************************************************************/
98
99acpi_status
100acpi_get_timer (
101 u32 *ticks)
102{
103 acpi_status status;
104
105
106 ACPI_FUNCTION_TRACE ("acpi_get_timer");
107
108
109 if (!ticks) {
110 return_ACPI_STATUS (AE_BAD_PARAMETER);
111 }
112
113 status = acpi_hw_low_level_read (32, ticks, &acpi_gbl_FADT->xpm_tmr_blk);
114
115 return_ACPI_STATUS (status);
116}
117EXPORT_SYMBOL(acpi_get_timer);
118
119
120/******************************************************************************
121 *
122 * FUNCTION: acpi_get_timer_duration
123 *
124 * PARAMETERS: start_ticks - Starting timestamp
125 * end_ticks - End timestamp
126 * time_elapsed - Where the elapsed time is returned
127 *
128 * RETURN: Status and time_elapsed
129 *
130 * DESCRIPTION: Computes the time elapsed (in microseconds) between two
131 * PM Timer time stamps, taking into account the possibility of
132 * rollovers, the timer resolution, and timer frequency.
133 *
134 * The PM Timer's clock ticks at roughly 3.6 times per
135 * _microsecond_, and its clock continues through Cx state
136 * transitions (unlike many CPU timestamp counters) -- making it
137 * a versatile and accurate timer.
138 *
139 * Note that this function accommodates only a single timer
140 * rollover. Thus for 24-bit timers, this function should only
141 * be used for calculating durations less than ~4.6 seconds
142 * (~20 minutes for 32-bit timers) -- calculations below:
143 *
144 * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
145 * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
146 *
147 ******************************************************************************/
148
149acpi_status
150acpi_get_timer_duration (
151 u32 start_ticks,
152 u32 end_ticks,
153 u32 *time_elapsed)
154{
155 acpi_status status;
156 u32 delta_ticks;
157 acpi_integer quotient;
158
159
160 ACPI_FUNCTION_TRACE ("acpi_get_timer_duration");
161
162
163 if (!time_elapsed) {
164 return_ACPI_STATUS (AE_BAD_PARAMETER);
165 }
166
167 /*
168 * Compute Tick Delta:
169 * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
170 */
171 if (start_ticks < end_ticks) {
172 delta_ticks = end_ticks - start_ticks;
173 }
174 else if (start_ticks > end_ticks) {
175 if (0 == acpi_gbl_FADT->tmr_val_ext) {
176 /* 24-bit Timer */
177
178 delta_ticks = (((0x00FFFFFF - start_ticks) + end_ticks) & 0x00FFFFFF);
179 }
180 else {
181 /* 32-bit Timer */
182
183 delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks;
184 }
185 }
186 else /* start_ticks == end_ticks */ {
187 *time_elapsed = 0;
188 return_ACPI_STATUS (AE_OK);
189 }
190
191 /*
192 * Compute Duration (Requires a 64-bit multiply and divide):
193 *
194 * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY;
195 */
196 status = acpi_ut_short_divide (((u64) delta_ticks) * 1000000,
197 PM_TIMER_FREQUENCY, &quotient, NULL);
198
199 *time_elapsed = (u32) quotient;
200 return_ACPI_STATUS (status);
201}
202EXPORT_SYMBOL(acpi_get_timer_duration);
203
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
new file mode 100644
index 000000000000..0fb731a470dc
--- /dev/null
+++ b/drivers/acpi/ibm_acpi.c
@@ -0,0 +1,1242 @@
1/*
2 * ibm_acpi.c - IBM ThinkPad ACPI Extras
3 *
4 *
5 * Copyright (C) 2004 Borislav Deianov
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * Changelog:
22 *
23 * 2004-08-09 0.1 initial release, support for X series
24 * 2004-08-14 0.2 support for T series, X20
25 * bluetooth enable/disable
26 * hotkey events disabled by default
27 * removed fan control, currently useless
28 * 2004-08-17 0.3 support for R40
29 * lcd off, brightness control
30 * thinklight on/off
31 * 2004-09-16 0.4 support for module parameters
32 * hotkey mask can be prefixed by 0x
33 * video output switching
34 * video expansion control
35 * ultrabay eject support
36 * removed lcd brightness/on/off control, didn't work
37 * 2004-10-18 0.5 thinklight support on A21e, G40, R32, T20, T21, X20
38 * proc file format changed
39 * video_switch command
40 * experimental cmos control
41 * experimental led control
42 * experimental acpi sounds
43 * 2004-10-19 0.6 use acpi_bus_register_driver() to claim HKEY device
44 * 2004-10-23 0.7 fix module loading on A21e, A22p, T20, T21, X20
45 * fix LED control on A21e
46 * 2004-11-08 0.8 fix init error case, don't return from a macro
47 * thanks to Chris Wright <chrisw@osdl.org>
48 */
49
50#define IBM_VERSION "0.8"
51
52#include <linux/kernel.h>
53#include <linux/module.h>
54#include <linux/init.h>
55#include <linux/types.h>
56#include <linux/proc_fs.h>
57#include <asm/uaccess.h>
58
59#include <acpi/acpi_drivers.h>
60#include <acpi/acnamesp.h>
61
62#define IBM_NAME "ibm"
63#define IBM_DESC "IBM ThinkPad ACPI Extras"
64#define IBM_FILE "ibm_acpi"
65#define IBM_URL "http://ibm-acpi.sf.net/"
66
67#define IBM_DIR IBM_NAME
68
69#define IBM_LOG IBM_FILE ": "
70#define IBM_ERR KERN_ERR IBM_LOG
71#define IBM_NOTICE KERN_NOTICE IBM_LOG
72#define IBM_INFO KERN_INFO IBM_LOG
73#define IBM_DEBUG KERN_DEBUG IBM_LOG
74
75#define IBM_MAX_ACPI_ARGS 3
76
77#define __unused __attribute__ ((unused))
78
79static int experimental;
80module_param(experimental, int, 0);
81
82static acpi_handle root_handle = NULL;
83
84#define IBM_HANDLE(object, parent, paths...) \
85 static acpi_handle object##_handle; \
86 static acpi_handle *object##_parent = &parent##_handle; \
87 static char *object##_paths[] = { paths }
88
89IBM_HANDLE(ec, root,
90 "\\_SB.PCI0.ISA.EC", /* A21e, A22p, T20, T21, X20 */
91 "\\_SB.PCI0.LPC.EC", /* all others */
92);
93
94IBM_HANDLE(vid, root,
95 "\\_SB.PCI0.VID", /* A21e, G40, X30, X40 */
96 "\\_SB.PCI0.AGP.VID", /* all others */
97);
98
99IBM_HANDLE(cmos, root,
100 "\\UCMS", /* R50, R50p, R51, T4x, X31, X40 */
101 "\\CMOS", /* A3x, G40, R32, T23, T30, X22, X24, X30 */
102 "\\CMS", /* R40, R40e */
103); /* A21e, A22p, T20, T21, X20 */
104
105IBM_HANDLE(dock, root,
106 "\\_SB.GDCK", /* X30, X31, X40 */
107 "\\_SB.PCI0.DOCK", /* A22p, T20, T21, X20 */
108 "\\_SB.PCI0.PCI1.DOCK", /* all others */
109); /* A21e, G40, R32, R40, R40e */
110
111IBM_HANDLE(bay, root,
112 "\\_SB.PCI0.IDE0.SCND.MSTR"); /* all except A21e */
113IBM_HANDLE(bayej, root,
114 "\\_SB.PCI0.IDE0.SCND.MSTR._EJ0"); /* all except A2x, A3x */
115
116IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A22p, T20, T21, X20 */
117IBM_HANDLE(hkey, ec, "HKEY"); /* all */
118IBM_HANDLE(led, ec, "LED"); /* all except A21e, A22p, T20, T21, X20 */
119IBM_HANDLE(sysl, ec, "SYSL"); /* A21e, A22p, T20, T21, X20 */
120IBM_HANDLE(bled, ec, "BLED"); /* A22p, T20, T21, X20 */
121IBM_HANDLE(beep, ec, "BEEP"); /* all models */
122
123struct ibm_struct {
124 char *name;
125
126 char *hid;
127 struct acpi_driver *driver;
128
129 int (*init) (struct ibm_struct *);
130 int (*read) (struct ibm_struct *, char *);
131 int (*write) (struct ibm_struct *, char *);
132 void (*exit) (struct ibm_struct *);
133
134 void (*notify) (struct ibm_struct *, u32);
135 acpi_handle *handle;
136 int type;
137 struct acpi_device *device;
138
139 int driver_registered;
140 int proc_created;
141 int init_called;
142 int notify_installed;
143
144 int supported;
145 union {
146 struct {
147 int status;
148 int mask;
149 } hotkey;
150 struct {
151 int autoswitch;
152 } video;
153 } state;
154
155 int experimental;
156};
157
158static struct proc_dir_entry *proc_dir = NULL;
159
160#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
161#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
162#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
163
164static int acpi_evalf(acpi_handle handle,
165 void *res, char *method, char *fmt, ...)
166{
167 char *fmt0 = fmt;
168 struct acpi_object_list params;
169 union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
170 struct acpi_buffer result;
171 union acpi_object out_obj;
172 acpi_status status;
173 va_list ap;
174 char res_type;
175 int success;
176 int quiet;
177
178 if (!*fmt) {
179 printk(IBM_ERR "acpi_evalf() called with empty format\n");
180 return 0;
181 }
182
183 if (*fmt == 'q') {
184 quiet = 1;
185 fmt++;
186 } else
187 quiet = 0;
188
189 res_type = *(fmt++);
190
191 params.count = 0;
192 params.pointer = &in_objs[0];
193
194 va_start(ap, fmt);
195 while (*fmt) {
196 char c = *(fmt++);
197 switch (c) {
198 case 'd': /* int */
199 in_objs[params.count].integer.value = va_arg(ap, int);
200 in_objs[params.count++].type = ACPI_TYPE_INTEGER;
201 break;
202 /* add more types as needed */
203 default:
204 printk(IBM_ERR "acpi_evalf() called "
205 "with invalid format character '%c'\n", c);
206 return 0;
207 }
208 }
209 va_end(ap);
210
211 result.length = sizeof(out_obj);
212 result.pointer = &out_obj;
213
214 status = acpi_evaluate_object(handle, method, &params, &result);
215
216 switch (res_type) {
217 case 'd': /* int */
218 if (res)
219 *(int *)res = out_obj.integer.value;
220 success = status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER;
221 break;
222 case 'v': /* void */
223 success = status == AE_OK;
224 break;
225 /* add more types as needed */
226 default:
227 printk(IBM_ERR "acpi_evalf() called "
228 "with invalid format character '%c'\n", res_type);
229 return 0;
230 }
231
232 if (!success && !quiet)
233 printk(IBM_ERR "acpi_evalf(%s, %s, ...) failed: %d\n",
234 method, fmt0, status);
235
236 return success;
237}
238
239static void __unused acpi_print_int(acpi_handle handle, char *method)
240{
241 int i;
242
243 if (acpi_evalf(handle, &i, method, "d"))
244 printk(IBM_INFO "%s = 0x%x\n", method, i);
245 else
246 printk(IBM_ERR "error calling %s\n", method);
247}
248
249static char *next_cmd(char **cmds)
250{
251 char *start = *cmds;
252 char *end;
253
254 while ((end = strchr(start, ',')) && end == start)
255 start = end + 1;
256
257 if (!end)
258 return NULL;
259
260 *end = 0;
261 *cmds = end + 1;
262 return start;
263}
264
265static int driver_init(struct ibm_struct *ibm)
266{
267 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
268 printk(IBM_INFO "%s\n", IBM_URL);
269
270 return 0;
271}
272
273static int driver_read(struct ibm_struct *ibm, char *p)
274{
275 int len = 0;
276
277 len += sprintf(p + len, "driver:\t\t%s\n", IBM_DESC);
278 len += sprintf(p + len, "version:\t%s\n", IBM_VERSION);
279
280 return len;
281}
282
283static int hotkey_get(struct ibm_struct *ibm, int *status, int *mask)
284{
285 if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
286 return -EIO;
287 if (ibm->supported) {
288 if (!acpi_evalf(hkey_handle, mask, "DHKN", "qd"))
289 return -EIO;
290 } else {
291 *mask = ibm->state.hotkey.mask;
292 }
293 return 0;
294}
295
296static int hotkey_set(struct ibm_struct *ibm, int status, int mask)
297{
298 int i;
299
300 if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
301 return -EIO;
302
303 if (!ibm->supported)
304 return 0;
305
306 for (i=0; i<32; i++) {
307 int bit = ((1 << i) & mask) != 0;
308 if (!acpi_evalf(hkey_handle, NULL, "MHKM", "vdd", i+1, bit))
309 return -EIO;
310 }
311
312 return 0;
313}
314
315static int hotkey_init(struct ibm_struct *ibm)
316{
317 int ret;
318
319 ibm->supported = 1;
320 ret = hotkey_get(ibm,
321 &ibm->state.hotkey.status,
322 &ibm->state.hotkey.mask);
323 if (ret < 0) {
324 /* mask not supported on A21e, A22p, T20, T21, X20, X22, X24 */
325 ibm->supported = 0;
326 ret = hotkey_get(ibm,
327 &ibm->state.hotkey.status,
328 &ibm->state.hotkey.mask);
329 }
330
331 return ret;
332}
333
334static int hotkey_read(struct ibm_struct *ibm, char *p)
335{
336 int status, mask;
337 int len = 0;
338
339 if (hotkey_get(ibm, &status, &mask) < 0)
340 return -EIO;
341
342 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
343 if (ibm->supported) {
344 len += sprintf(p + len, "mask:\t\t0x%04x\n", mask);
345 len += sprintf(p + len,
346 "commands:\tenable, disable, reset, <mask>\n");
347 } else {
348 len += sprintf(p + len, "mask:\t\tnot supported\n");
349 len += sprintf(p + len, "commands:\tenable, disable, reset\n");
350 }
351
352 return len;
353}
354
355static int hotkey_write(struct ibm_struct *ibm, char *buf)
356{
357 int status, mask;
358 char *cmd;
359 int do_cmd = 0;
360
361 if (hotkey_get(ibm, &status, &mask) < 0)
362 return -ENODEV;
363
364 while ((cmd = next_cmd(&buf))) {
365 if (strlencmp(cmd, "enable") == 0) {
366 status = 1;
367 } else if (strlencmp(cmd, "disable") == 0) {
368 status = 0;
369 } else if (strlencmp(cmd, "reset") == 0) {
370 status = ibm->state.hotkey.status;
371 mask = ibm->state.hotkey.mask;
372 } else if (sscanf(cmd, "0x%x", &mask) == 1) {
373 /* mask set */
374 } else if (sscanf(cmd, "%x", &mask) == 1) {
375 /* mask set */
376 } else
377 return -EINVAL;
378 do_cmd = 1;
379 }
380
381 if (do_cmd && hotkey_set(ibm, status, mask) < 0)
382 return -EIO;
383
384 return 0;
385}
386
387static void hotkey_exit(struct ibm_struct *ibm)
388{
389 hotkey_set(ibm, ibm->state.hotkey.status, ibm->state.hotkey.mask);
390}
391
392static void hotkey_notify(struct ibm_struct *ibm, u32 event)
393{
394 int hkey;
395
396 if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d"))
397 acpi_bus_generate_event(ibm->device, event, hkey);
398 else {
399 printk(IBM_ERR "unknown hotkey event %d\n", event);
400 acpi_bus_generate_event(ibm->device, event, 0);
401 }
402}
403
404static int bluetooth_init(struct ibm_struct *ibm)
405{
406 /* bluetooth not supported on A21e, G40, T20, T21, X20 */
407 ibm->supported = acpi_evalf(hkey_handle, NULL, "GBDC", "qv");
408
409 return 0;
410}
411
412static int bluetooth_status(struct ibm_struct *ibm)
413{
414 int status;
415
416 if (!ibm->supported || !acpi_evalf(hkey_handle, &status, "GBDC", "d"))
417 status = 0;
418
419 return status;
420}
421
422static int bluetooth_read(struct ibm_struct *ibm, char *p)
423{
424 int len = 0;
425 int status = bluetooth_status(ibm);
426
427 if (!ibm->supported)
428 len += sprintf(p + len, "status:\t\tnot supported\n");
429 else if (!(status & 1))
430 len += sprintf(p + len, "status:\t\tnot installed\n");
431 else {
432 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1));
433 len += sprintf(p + len, "commands:\tenable, disable\n");
434 }
435
436 return len;
437}
438
439static int bluetooth_write(struct ibm_struct *ibm, char *buf)
440{
441 int status = bluetooth_status(ibm);
442 char *cmd;
443 int do_cmd = 0;
444
445 if (!ibm->supported)
446 return -EINVAL;
447
448 while ((cmd = next_cmd(&buf))) {
449 if (strlencmp(cmd, "enable") == 0) {
450 status |= 2;
451 } else if (strlencmp(cmd, "disable") == 0) {
452 status &= ~2;
453 } else
454 return -EINVAL;
455 do_cmd = 1;
456 }
457
458 if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
459 return -EIO;
460
461 return 0;
462}
463
464static int video_init(struct ibm_struct *ibm)
465{
466 if (!acpi_evalf(vid_handle,
467 &ibm->state.video.autoswitch, "^VDEE", "d"))
468 return -ENODEV;
469
470 return 0;
471}
472
473static int video_status(struct ibm_struct *ibm)
474{
475 int status = 0;
476 int i;
477
478 acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1);
479 if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
480 status |= 0x02 * i;
481
482 acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0);
483 if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
484 status |= 0x01 * i;
485 if (acpi_evalf(NULL, &i, "\\VCDD", "d"))
486 status |= 0x08 * i;
487
488 if (acpi_evalf(vid_handle, &i, "^VDEE", "d"))
489 status |= 0x10 * (i & 1);
490
491 return status;
492}
493
494static int video_read(struct ibm_struct *ibm, char *p)
495{
496 int status = video_status(ibm);
497 int len = 0;
498
499 len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
500 len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
501 len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
502 len += sprintf(p + len, "auto:\t\t%s\n", enabled(status, 4));
503 len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable, "
504 "crt_enable, crt_disable\n");
505 len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable, "
506 "auto_enable, auto_disable\n");
507 len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
508
509 return len;
510}
511
512static int video_write(struct ibm_struct *ibm, char *buf)
513{
514 char *cmd;
515 int enable, disable, status;
516
517 enable = disable = 0;
518
519 while ((cmd = next_cmd(&buf))) {
520 if (strlencmp(cmd, "lcd_enable") == 0) {
521 enable |= 0x01;
522 } else if (strlencmp(cmd, "lcd_disable") == 0) {
523 disable |= 0x01;
524 } else if (strlencmp(cmd, "crt_enable") == 0) {
525 enable |= 0x02;
526 } else if (strlencmp(cmd, "crt_disable") == 0) {
527 disable |= 0x02;
528 } else if (strlencmp(cmd, "dvi_enable") == 0) {
529 enable |= 0x08;
530 } else if (strlencmp(cmd, "dvi_disable") == 0) {
531 disable |= 0x08;
532 } else if (strlencmp(cmd, "auto_enable") == 0) {
533 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
534 return -EIO;
535 } else if (strlencmp(cmd, "auto_disable") == 0) {
536 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 0))
537 return -EIO;
538 } else if (strlencmp(cmd, "video_switch") == 0) {
539 int autoswitch;
540 if (!acpi_evalf(vid_handle, &autoswitch, "^VDEE", "d"))
541 return -EIO;
542 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
543 return -EIO;
544 if (!acpi_evalf(vid_handle, NULL, "VSWT", "v"))
545 return -EIO;
546 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd",
547 autoswitch))
548 return -EIO;
549 } else if (strlencmp(cmd, "expand_toggle") == 0) {
550 if (!acpi_evalf(NULL, NULL, "\\VEXP", "v"))
551 return -EIO;
552 } else
553 return -EINVAL;
554 }
555
556 if (enable || disable) {
557 status = (video_status(ibm) & 0x0f & ~disable) | enable;
558 if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80))
559 return -EIO;
560 if (!acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1))
561 return -EIO;
562 }
563
564 return 0;
565}
566
567static void video_exit(struct ibm_struct *ibm)
568{
569 acpi_evalf(vid_handle, NULL, "_DOS", "vd",
570 ibm->state.video.autoswitch);
571}
572
573static int light_init(struct ibm_struct *ibm)
574{
575 /* kblt not supported on G40, R32, X20 */
576 ibm->supported = acpi_evalf(ec_handle, NULL, "KBLT", "qv");
577
578 return 0;
579}
580
581static int light_read(struct ibm_struct *ibm, char *p)
582{
583 int len = 0;
584 int status = 0;
585
586 if (ibm->supported) {
587 if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
588 return -EIO;
589 len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
590 } else
591 len += sprintf(p + len, "status:\t\tunknown\n");
592
593 len += sprintf(p + len, "commands:\ton, off\n");
594
595 return len;
596}
597
598static int light_write(struct ibm_struct *ibm, char *buf)
599{
600 int cmos_cmd, lght_cmd;
601 char *cmd;
602 int success;
603
604 while ((cmd = next_cmd(&buf))) {
605 if (strlencmp(cmd, "on") == 0) {
606 cmos_cmd = 0x0c;
607 lght_cmd = 1;
608 } else if (strlencmp(cmd, "off") == 0) {
609 cmos_cmd = 0x0d;
610 lght_cmd = 0;
611 } else
612 return -EINVAL;
613
614 success = cmos_handle ?
615 acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
616 acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
617 if (!success)
618 return -EIO;
619 }
620
621 return 0;
622}
623
624static int _sta(acpi_handle handle)
625{
626 int status;
627
628 if (!handle || !acpi_evalf(handle, &status, "_STA", "d"))
629 status = 0;
630
631 return status;
632}
633
634#define dock_docked() (_sta(dock_handle) & 1)
635
636static int dock_read(struct ibm_struct *ibm, char *p)
637{
638 int len = 0;
639 int docked = dock_docked();
640
641 if (!dock_handle)
642 len += sprintf(p + len, "status:\t\tnot supported\n");
643 else if (!docked)
644 len += sprintf(p + len, "status:\t\tundocked\n");
645 else {
646 len += sprintf(p + len, "status:\t\tdocked\n");
647 len += sprintf(p + len, "commands:\tdock, undock\n");
648 }
649
650 return len;
651}
652
653static int dock_write(struct ibm_struct *ibm, char *buf)
654{
655 char *cmd;
656
657 if (!dock_docked())
658 return -EINVAL;
659
660 while ((cmd = next_cmd(&buf))) {
661 if (strlencmp(cmd, "undock") == 0) {
662 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0))
663 return -EIO;
664 if (!acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
665 return -EIO;
666 } else if (strlencmp(cmd, "dock") == 0) {
667 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1))
668 return -EIO;
669 } else
670 return -EINVAL;
671 }
672
673 return 0;
674}
675
676static void dock_notify(struct ibm_struct *ibm, u32 event)
677{
678 int docked = dock_docked();
679
680 if (event == 3 && docked)
681 acpi_bus_generate_event(ibm->device, event, 1); /* button */
682 else if (event == 3 && !docked)
683 acpi_bus_generate_event(ibm->device, event, 2); /* undock */
684 else if (event == 0 && docked)
685 acpi_bus_generate_event(ibm->device, event, 3); /* dock */
686 else {
687 printk(IBM_ERR "unknown dock event %d, status %d\n",
688 event, _sta(dock_handle));
689 acpi_bus_generate_event(ibm->device, event, 0); /* unknown */
690 }
691}
692
693#define bay_occupied() (_sta(bay_handle) & 1)
694
695static int bay_init(struct ibm_struct *ibm)
696{
697 /* bay not supported on A21e, A22p, A31, A31p, G40, R32, R40e */
698 ibm->supported = bay_handle && bayej_handle &&
699 acpi_evalf(bay_handle, NULL, "_STA", "qv");
700
701 return 0;
702}
703
704static int bay_read(struct ibm_struct *ibm, char *p)
705{
706 int len = 0;
707 int occupied = bay_occupied();
708
709 if (!ibm->supported)
710 len += sprintf(p + len, "status:\t\tnot supported\n");
711 else if (!occupied)
712 len += sprintf(p + len, "status:\t\tunoccupied\n");
713 else {
714 len += sprintf(p + len, "status:\t\toccupied\n");
715 len += sprintf(p + len, "commands:\teject\n");
716 }
717
718 return len;
719}
720
721static int bay_write(struct ibm_struct *ibm, char *buf)
722{
723 char *cmd;
724
725 while ((cmd = next_cmd(&buf))) {
726 if (strlencmp(cmd, "eject") == 0) {
727 if (!ibm->supported ||
728 !acpi_evalf(bay_handle, NULL, "_EJ0", "vd", 1))
729 return -EIO;
730 } else
731 return -EINVAL;
732 }
733
734 return 0;
735}
736
737static void bay_notify(struct ibm_struct *ibm, u32 event)
738{
739 acpi_bus_generate_event(ibm->device, event, 0);
740}
741
742static int cmos_read(struct ibm_struct *ibm, char *p)
743{
744 int len = 0;
745
746 /* cmos not supported on A21e, A22p, T20, T21, X20 */
747 if (!cmos_handle)
748 len += sprintf(p + len, "status:\t\tnot supported\n");
749 else {
750 len += sprintf(p + len, "status:\t\tsupported\n");
751 len += sprintf(p + len, "commands:\t<int>\n");
752 }
753
754 return len;
755}
756
757static int cmos_write(struct ibm_struct *ibm, char *buf)
758{
759 char *cmd;
760 int cmos_cmd;
761
762 if (!cmos_handle)
763 return -EINVAL;
764
765 while ((cmd = next_cmd(&buf))) {
766 if (sscanf(cmd, "%u", &cmos_cmd) == 1) {
767 /* cmos_cmd set */
768 } else
769 return -EINVAL;
770
771 if (!acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd))
772 return -EIO;
773 }
774
775 return 0;
776}
777
778static int led_read(struct ibm_struct *ibm, char *p)
779{
780 int len = 0;
781
782 len += sprintf(p + len, "commands:\t"
783 "<int> on, <int> off, <int> blink\n");
784
785 return len;
786}
787
788static int led_write(struct ibm_struct *ibm, char *buf)
789{
790 char *cmd;
791 unsigned int led;
792 int led_cmd, sysl_cmd, bled_a, bled_b;
793
794 while ((cmd = next_cmd(&buf))) {
795 if (sscanf(cmd, "%u", &led) != 1)
796 return -EINVAL;
797
798 if (strstr(cmd, "blink")) {
799 led_cmd = 0xc0;
800 sysl_cmd = 2;
801 bled_a = 2;
802 bled_b = 1;
803 } else if (strstr(cmd, "on")) {
804 led_cmd = 0x80;
805 sysl_cmd = 1;
806 bled_a = 2;
807 bled_b = 0;
808 } else if (strstr(cmd, "off")) {
809 led_cmd = sysl_cmd = bled_a = bled_b = 0;
810 } else
811 return -EINVAL;
812
813 if (led_handle) {
814 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
815 led, led_cmd))
816 return -EIO;
817 } else if (led < 2) {
818 if (acpi_evalf(sysl_handle, NULL, NULL, "vdd",
819 led, sysl_cmd))
820 return -EIO;
821 } else if (led == 2 && bled_handle) {
822 if (acpi_evalf(bled_handle, NULL, NULL, "vdd",
823 bled_a, bled_b))
824 return -EIO;
825 } else
826 return -EINVAL;
827 }
828
829 return 0;
830}
831
832static int beep_read(struct ibm_struct *ibm, char *p)
833{
834 int len = 0;
835
836 len += sprintf(p + len, "commands:\t<int>\n");
837
838 return len;
839}
840
841static int beep_write(struct ibm_struct *ibm, char *buf)
842{
843 char *cmd;
844 int beep_cmd;
845
846 while ((cmd = next_cmd(&buf))) {
847 if (sscanf(cmd, "%u", &beep_cmd) == 1) {
848 /* beep_cmd set */
849 } else
850 return -EINVAL;
851
852 if (!acpi_evalf(beep_handle, NULL, NULL, "vd", beep_cmd))
853 return -EIO;
854 }
855
856 return 0;
857}
858
859static struct ibm_struct ibms[] = {
860 {
861 .name = "driver",
862 .init = driver_init,
863 .read = driver_read,
864 },
865 {
866 .name = "hotkey",
867 .hid = "IBM0068",
868 .init = hotkey_init,
869 .read = hotkey_read,
870 .write = hotkey_write,
871 .exit = hotkey_exit,
872 .notify = hotkey_notify,
873 .handle = &hkey_handle,
874 .type = ACPI_DEVICE_NOTIFY,
875 },
876 {
877 .name = "bluetooth",
878 .init = bluetooth_init,
879 .read = bluetooth_read,
880 .write = bluetooth_write,
881 },
882 {
883 .name = "video",
884 .init = video_init,
885 .read = video_read,
886 .write = video_write,
887 .exit = video_exit,
888 },
889 {
890 .name = "light",
891 .init = light_init,
892 .read = light_read,
893 .write = light_write,
894 },
895 {
896 .name = "dock",
897 .read = dock_read,
898 .write = dock_write,
899 .notify = dock_notify,
900 .handle = &dock_handle,
901 .type = ACPI_SYSTEM_NOTIFY,
902 },
903 {
904 .name = "bay",
905 .init = bay_init,
906 .read = bay_read,
907 .write = bay_write,
908 .notify = bay_notify,
909 .handle = &bay_handle,
910 .type = ACPI_SYSTEM_NOTIFY,
911 },
912 {
913 .name = "cmos",
914 .read = cmos_read,
915 .write = cmos_write,
916 .experimental = 1,
917 },
918 {
919 .name = "led",
920 .read = led_read,
921 .write = led_write,
922 .experimental = 1,
923 },
924 {
925 .name = "beep",
926 .read = beep_read,
927 .write = beep_write,
928 .experimental = 1,
929 },
930};
931#define NUM_IBMS (sizeof(ibms)/sizeof(ibms[0]))
932
933static int dispatch_read(char *page, char **start, off_t off, int count,
934 int *eof, void *data)
935{
936 struct ibm_struct *ibm = (struct ibm_struct *)data;
937 int len;
938
939 if (!ibm || !ibm->read)
940 return -EINVAL;
941
942 len = ibm->read(ibm, page);
943 if (len < 0)
944 return len;
945
946 if (len <= off + count)
947 *eof = 1;
948 *start = page + off;
949 len -= off;
950 if (len > count)
951 len = count;
952 if (len < 0)
953 len = 0;
954
955 return len;
956}
957
958static int dispatch_write(struct file *file, const char __user *userbuf,
959 unsigned long count, void *data)
960{
961 struct ibm_struct *ibm = (struct ibm_struct *)data;
962 char *kernbuf;
963 int ret;
964
965 if (!ibm || !ibm->write)
966 return -EINVAL;
967
968 kernbuf = kmalloc(count + 2, GFP_KERNEL);
969 if (!kernbuf)
970 return -ENOMEM;
971
972 if (copy_from_user(kernbuf, userbuf, count)) {
973 kfree(kernbuf);
974 return -EFAULT;
975 }
976
977 kernbuf[count] = 0;
978 strcat(kernbuf, ",");
979 ret = ibm->write(ibm, kernbuf);
980 if (ret == 0)
981 ret = count;
982
983 kfree(kernbuf);
984
985 return ret;
986}
987
988static void dispatch_notify(acpi_handle handle, u32 event, void *data)
989{
990 struct ibm_struct *ibm = (struct ibm_struct *)data;
991
992 if (!ibm || !ibm->notify)
993 return;
994
995 ibm->notify(ibm, event);
996}
997
998static int setup_notify(struct ibm_struct *ibm)
999{
1000 acpi_status status;
1001 int ret;
1002
1003 if (!*ibm->handle)
1004 return 0;
1005
1006 ret = acpi_bus_get_device(*ibm->handle, &ibm->device);
1007 if (ret < 0) {
1008 printk(IBM_ERR "%s device not present\n", ibm->name);
1009 return 0;
1010 }
1011
1012 acpi_driver_data(ibm->device) = ibm;
1013 sprintf(acpi_device_class(ibm->device), "%s/%s", IBM_NAME, ibm->name);
1014
1015 status = acpi_install_notify_handler(*ibm->handle, ibm->type,
1016 dispatch_notify, ibm);
1017 if (ACPI_FAILURE(status)) {
1018 printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n",
1019 ibm->name, status);
1020 return -ENODEV;
1021 }
1022
1023 ibm->notify_installed = 1;
1024
1025 return 0;
1026}
1027
1028static int device_add(struct acpi_device *device)
1029{
1030 return 0;
1031}
1032
1033static int register_driver(struct ibm_struct *ibm)
1034{
1035 int ret;
1036
1037 ibm->driver = kmalloc(sizeof(struct acpi_driver), GFP_KERNEL);
1038 if (!ibm->driver) {
1039 printk(IBM_ERR "kmalloc(ibm->driver) failed\n");
1040 return -1;
1041 }
1042
1043 memset(ibm->driver, 0, sizeof(struct acpi_driver));
1044 sprintf(ibm->driver->name, "%s/%s", IBM_NAME, ibm->name);
1045 ibm->driver->ids = ibm->hid;
1046 ibm->driver->ops.add = &device_add;
1047
1048 ret = acpi_bus_register_driver(ibm->driver);
1049 if (ret < 0) {
1050 printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n",
1051 ibm->hid, ret);
1052 kfree(ibm->driver);
1053 }
1054
1055 return ret;
1056}
1057
1058static int ibm_init(struct ibm_struct *ibm)
1059{
1060 int ret;
1061 struct proc_dir_entry *entry;
1062
1063 if (ibm->experimental && !experimental)
1064 return 0;
1065
1066 if (ibm->hid) {
1067 ret = register_driver(ibm);
1068 if (ret < 0)
1069 return ret;
1070 ibm->driver_registered = 1;
1071 }
1072
1073 if (ibm->init) {
1074 ret = ibm->init(ibm);
1075 if (ret != 0)
1076 return ret;
1077 ibm->init_called = 1;
1078 }
1079
1080 entry = create_proc_entry(ibm->name, S_IFREG | S_IRUGO | S_IWUSR,
1081 proc_dir);
1082 if (!entry) {
1083 printk(IBM_ERR "unable to create proc entry %s\n", ibm->name);
1084 return -ENODEV;
1085 }
1086 entry->owner = THIS_MODULE;
1087 ibm->proc_created = 1;
1088
1089 entry->data = ibm;
1090 if (ibm->read)
1091 entry->read_proc = &dispatch_read;
1092 if (ibm->write)
1093 entry->write_proc = &dispatch_write;
1094
1095 if (ibm->notify) {
1096 ret = setup_notify(ibm);
1097 if (ret < 0)
1098 return ret;
1099 }
1100
1101 return 0;
1102}
1103
1104static void ibm_exit(struct ibm_struct *ibm)
1105{
1106 if (ibm->notify_installed)
1107 acpi_remove_notify_handler(*ibm->handle, ibm->type,
1108 dispatch_notify);
1109
1110 if (ibm->proc_created)
1111 remove_proc_entry(ibm->name, proc_dir);
1112
1113 if (ibm->init_called && ibm->exit)
1114 ibm->exit(ibm);
1115
1116 if (ibm->driver_registered) {
1117 acpi_bus_unregister_driver(ibm->driver);
1118 kfree(ibm->driver);
1119 }
1120}
1121
1122static int ibm_handle_init(char *name,
1123 acpi_handle *handle, acpi_handle parent,
1124 char **paths, int num_paths, int required)
1125{
1126 int i;
1127 acpi_status status;
1128
1129 for (i=0; i<num_paths; i++) {
1130 status = acpi_get_handle(parent, paths[i], handle);
1131 if (ACPI_SUCCESS(status))
1132 return 0;
1133 }
1134
1135 *handle = NULL;
1136
1137 if (required) {
1138 printk(IBM_ERR "%s object not found\n", name);
1139 return -1;
1140 }
1141
1142 return 0;
1143}
1144
1145#define IBM_HANDLE_INIT(object, required) \
1146 ibm_handle_init(#object, &object##_handle, *object##_parent, \
1147 object##_paths, sizeof(object##_paths)/sizeof(char*), required)
1148
1149
1150static int set_ibm_param(const char *val, struct kernel_param *kp)
1151{
1152 unsigned int i;
1153 char arg_with_comma[32];
1154
1155 if (strlen(val) > 30)
1156 return -ENOSPC;
1157
1158 strcpy(arg_with_comma, val);
1159 strcat(arg_with_comma, ",");
1160
1161 for (i=0; i<NUM_IBMS; i++)
1162 if (strcmp(ibms[i].name, kp->name) == 0)
1163 return ibms[i].write(&ibms[i], arg_with_comma);
1164 BUG();
1165 return -EINVAL;
1166}
1167
1168#define IBM_PARAM(feature) \
1169 module_param_call(feature, set_ibm_param, NULL, NULL, 0)
1170
1171static void acpi_ibm_exit(void)
1172{
1173 int i;
1174
1175 for (i=NUM_IBMS-1; i>=0; i--)
1176 ibm_exit(&ibms[i]);
1177
1178 remove_proc_entry(IBM_DIR, acpi_root_dir);
1179}
1180
1181static int __init acpi_ibm_init(void)
1182{
1183 int ret, i;
1184
1185 if (acpi_disabled)
1186 return -ENODEV;
1187
1188 /* these handles are required */
1189 if (IBM_HANDLE_INIT(ec, 1) < 0 ||
1190 IBM_HANDLE_INIT(hkey, 1) < 0 ||
1191 IBM_HANDLE_INIT(vid, 1) < 0 ||
1192 IBM_HANDLE_INIT(beep, 1) < 0)
1193 return -ENODEV;
1194
1195 /* these handles have alternatives */
1196 IBM_HANDLE_INIT(lght, 0);
1197 if (IBM_HANDLE_INIT(cmos, !lght_handle) < 0)
1198 return -ENODEV;
1199 IBM_HANDLE_INIT(sysl, 0);
1200 if (IBM_HANDLE_INIT(led, !sysl_handle) < 0)
1201 return -ENODEV;
1202
1203 /* these handles are not required */
1204 IBM_HANDLE_INIT(dock, 0);
1205 IBM_HANDLE_INIT(bay, 0);
1206 IBM_HANDLE_INIT(bayej, 0);
1207 IBM_HANDLE_INIT(bled, 0);
1208
1209 proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir);
1210 if (!proc_dir) {
1211 printk(IBM_ERR "unable to create proc dir %s", IBM_DIR);
1212 return -ENODEV;
1213 }
1214 proc_dir->owner = THIS_MODULE;
1215
1216 for (i=0; i<NUM_IBMS; i++) {
1217 ret = ibm_init(&ibms[i]);
1218 if (ret < 0) {
1219 acpi_ibm_exit();
1220 return ret;
1221 }
1222 }
1223
1224 return 0;
1225}
1226
1227module_init(acpi_ibm_init);
1228module_exit(acpi_ibm_exit);
1229
1230MODULE_AUTHOR("Borislav Deianov");
1231MODULE_DESCRIPTION(IBM_DESC);
1232MODULE_LICENSE("GPL");
1233
1234IBM_PARAM(hotkey);
1235IBM_PARAM(bluetooth);
1236IBM_PARAM(video);
1237IBM_PARAM(light);
1238IBM_PARAM(dock);
1239IBM_PARAM(bay);
1240IBM_PARAM(cmos);
1241IBM_PARAM(led);
1242IBM_PARAM(beep);
diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c
new file mode 100644
index 000000000000..61ea70742d49
--- /dev/null
+++ b/drivers/acpi/motherboard.c
@@ -0,0 +1,177 @@
1/*
2 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or (at
6 * your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16 *
17 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18 */
19
20/* Purpose: Prevent PCMCIA cards from using motherboard resources. */
21
22#include <linux/kernel.h>
23#include <linux/init.h>
24#include <linux/types.h>
25#include <linux/pci.h>
26#include <linux/ioport.h>
27#include <asm/io.h>
28
29#include <acpi/acpi_bus.h>
30#include <acpi/acpi_drivers.h>
31
32#define _COMPONENT ACPI_SYSTEM_COMPONENT
33ACPI_MODULE_NAME ("acpi_motherboard")
34
35/* Dell use PNP0C01 instead of PNP0C02 */
36#define ACPI_MB_HID1 "PNP0C01"
37#define ACPI_MB_HID2 "PNP0C02"
38
39/**
40 * Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved
41 * Doesn't care about the failure of 'request_region', since other may reserve
42 * the io ports as well
43 */
44#define IS_RESERVED_ADDR(base, len) \
45 (((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \
46 && ((base) + (len) > PCIBIOS_MIN_IO))
47
48/*
49 * Clearing the flag (IORESOURCE_BUSY) allows drivers to use
50 * the io ports if they really know they can use it, while
51 * still preventing hotplug PCI devices from using it.
52 */
53
54static acpi_status
55acpi_reserve_io_ranges (struct acpi_resource *res, void *data)
56{
57 struct resource *requested_res = NULL;
58
59 ACPI_FUNCTION_TRACE("acpi_reserve_io_ranges");
60
61 if (res->id == ACPI_RSTYPE_IO) {
62 struct acpi_resource_io *io_res = &res->data.io;
63
64 if (io_res->min_base_address != io_res->max_base_address)
65 return_VALUE(AE_OK);
66 if (IS_RESERVED_ADDR(io_res->min_base_address, io_res->range_length)) {
67 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
68 io_res->min_base_address,
69 io_res->min_base_address + io_res->range_length));
70 requested_res = request_region(io_res->min_base_address,
71 io_res->range_length, "motherboard");
72 }
73 } else if (res->id == ACPI_RSTYPE_FIXED_IO) {
74 struct acpi_resource_fixed_io *fixed_io_res = &res->data.fixed_io;
75
76 if (IS_RESERVED_ADDR(fixed_io_res->base_address, fixed_io_res->range_length)) {
77 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
78 fixed_io_res->base_address,
79 fixed_io_res->base_address + fixed_io_res->range_length));
80 requested_res = request_region(fixed_io_res->base_address,
81 fixed_io_res->range_length, "motherboard");
82 }
83 } else {
84 /* Memory mapped IO? */
85 }
86
87 if (requested_res)
88 requested_res->flags &= ~IORESOURCE_BUSY;
89 return_VALUE(AE_OK);
90}
91
92static int acpi_motherboard_add (struct acpi_device *device)
93{
94 if (!device)
95 return -EINVAL;
96 acpi_walk_resources(device->handle, METHOD_NAME__CRS,
97 acpi_reserve_io_ranges, NULL);
98
99 return 0;
100}
101
102static struct acpi_driver acpi_motherboard_driver1 = {
103 .name = "motherboard",
104 .class = "",
105 .ids = ACPI_MB_HID1,
106 .ops = {
107 .add = acpi_motherboard_add,
108 },
109};
110
111static struct acpi_driver acpi_motherboard_driver2 = {
112 .name = "motherboard",
113 .class = "",
114 .ids = ACPI_MB_HID2,
115 .ops = {
116 .add = acpi_motherboard_add,
117 },
118};
119
120static void __init
121acpi_reserve_resources (void)
122{
123 if (acpi_gbl_FADT->xpm1a_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
124 request_region(acpi_gbl_FADT->xpm1a_evt_blk.address,
125 acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK");
126
127 if (acpi_gbl_FADT->xpm1b_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
128 request_region(acpi_gbl_FADT->xpm1b_evt_blk.address,
129 acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK");
130
131 if (acpi_gbl_FADT->xpm1a_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
132 request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address,
133 acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK");
134
135 if (acpi_gbl_FADT->xpm1b_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
136 request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address,
137 acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK");
138
139 if (acpi_gbl_FADT->xpm_tmr_blk.address && acpi_gbl_FADT->pm_tm_len == 4)
140 request_region(acpi_gbl_FADT->xpm_tmr_blk.address,
141 4, "PM_TMR");
142
143 if (acpi_gbl_FADT->xpm2_cnt_blk.address && acpi_gbl_FADT->pm2_cnt_len)
144 request_region(acpi_gbl_FADT->xpm2_cnt_blk.address,
145 acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK");
146
147 /* Length of GPE blocks must be a non-negative multiple of 2 */
148
149 if (acpi_gbl_FADT->xgpe0_blk.address && acpi_gbl_FADT->gpe0_blk_len &&
150 !(acpi_gbl_FADT->gpe0_blk_len & 0x1))
151 request_region(acpi_gbl_FADT->xgpe0_blk.address,
152 acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK");
153
154 if (acpi_gbl_FADT->xgpe1_blk.address && acpi_gbl_FADT->gpe1_blk_len &&
155 !(acpi_gbl_FADT->gpe1_blk_len & 0x1))
156 request_region(acpi_gbl_FADT->xgpe1_blk.address,
157 acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK");
158}
159
160static int __init acpi_motherboard_init(void)
161{
162 acpi_bus_register_driver(&acpi_motherboard_driver1);
163 acpi_bus_register_driver(&acpi_motherboard_driver2);
164 /*
165 * Guarantee motherboard IO reservation first
166 * This module must run after scan.c
167 */
168 if (!acpi_disabled)
169 acpi_reserve_resources ();
170 return 0;
171}
172
173/**
174 * Reserve motherboard resources after PCI claim BARs,
175 * but before PCI assign resources for uninitialized PCI devices
176 */
177fs_initcall(acpi_motherboard_init);
diff --git a/drivers/acpi/namespace/Makefile b/drivers/acpi/namespace/Makefile
new file mode 100644
index 000000000000..3f63d3640696
--- /dev/null
+++ b/drivers/acpi/namespace/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile for all Linux ACPI interpreter subdirectories
3#
4
5obj-y := nsaccess.o nsload.o nssearch.o nsxfeval.o \
6 nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
7 nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
8 nsparse.o
9
10obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
11
12EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
new file mode 100644
index 000000000000..1c0c12336c57
--- /dev/null
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -0,0 +1,637 @@
1/*******************************************************************************
2 *
3 * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/amlcode.h>
47#include <acpi/acnamesp.h>
48#include <acpi/acdispat.h>
49
50
51#define _COMPONENT ACPI_NAMESPACE
52 ACPI_MODULE_NAME ("nsaccess")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION: acpi_ns_root_initialize
58 *
59 * PARAMETERS: None
60 *
61 * RETURN: Status
62 *
63 * DESCRIPTION: Allocate and initialize the default root named objects
64 *
65 * MUTEX: Locks namespace for entire execution
66 *
67 ******************************************************************************/
68
69acpi_status
70acpi_ns_root_initialize (void)
71{
72 acpi_status status;
73 const struct acpi_predefined_names *init_val = NULL;
74 struct acpi_namespace_node *new_node;
75 union acpi_operand_object *obj_desc;
76 acpi_string val = NULL;
77
78
79 ACPI_FUNCTION_TRACE ("ns_root_initialize");
80
81
82 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
83 if (ACPI_FAILURE (status)) {
84 return_ACPI_STATUS (status);
85 }
86
87 /*
88 * The global root ptr is initially NULL, so a non-NULL value indicates
89 * that acpi_ns_root_initialize() has already been called; just return.
90 */
91 if (acpi_gbl_root_node) {
92 status = AE_OK;
93 goto unlock_and_exit;
94 }
95
96 /*
97 * Tell the rest of the subsystem that the root is initialized
98 * (This is OK because the namespace is locked)
99 */
100 acpi_gbl_root_node = &acpi_gbl_root_node_struct;
101
102 /* Enter the pre-defined names in the name table */
103
104 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
105 "Entering predefined entries into namespace\n"));
106
107 for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) {
108 /* _OSI is optional for now, will be permanent later */
109
110 if (!ACPI_STRCMP (init_val->name, "_OSI") && !acpi_gbl_create_osi_method) {
111 continue;
112 }
113
114 status = acpi_ns_lookup (NULL, init_val->name, init_val->type,
115 ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
116 NULL, &new_node);
117
118 if (ACPI_FAILURE (status) || (!new_node)) /* Must be on same line for code converter */ {
119 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
120 "Could not create predefined name %s, %s\n",
121 init_val->name, acpi_format_exception (status)));
122 }
123
124 /*
125 * Name entered successfully.
126 * If entry in pre_defined_names[] specifies an
127 * initial value, create the initial value.
128 */
129 if (init_val->val) {
130 status = acpi_os_predefined_override (init_val, &val);
131 if (ACPI_FAILURE (status)) {
132 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
133 "Could not override predefined %s\n",
134 init_val->name));
135 }
136
137 if (!val) {
138 val = init_val->val;
139 }
140
141 /*
142 * Entry requests an initial value, allocate a
143 * descriptor for it.
144 */
145 obj_desc = acpi_ut_create_internal_object (init_val->type);
146 if (!obj_desc) {
147 status = AE_NO_MEMORY;
148 goto unlock_and_exit;
149 }
150
151 /*
152 * Convert value string from table entry to
153 * internal representation. Only types actually
154 * used for initial values are implemented here.
155 */
156 switch (init_val->type) {
157 case ACPI_TYPE_METHOD:
158 obj_desc->method.param_count = (u8) ACPI_TO_INTEGER (val);
159 obj_desc->common.flags |= AOPOBJ_DATA_VALID;
160
161#if defined (_ACPI_ASL_COMPILER) || defined (_ACPI_DUMP_App)
162
163 /*
164 * i_aSL Compiler cheats by putting parameter count
165 * in the owner_iD
166 */
167 new_node->owner_id = obj_desc->method.param_count;
168#else
169 /* Mark this as a very SPECIAL method */
170
171 obj_desc->method.method_flags = AML_METHOD_INTERNAL_ONLY;
172 obj_desc->method.implementation = acpi_ut_osi_implementation;
173#endif
174 break;
175
176 case ACPI_TYPE_INTEGER:
177
178 obj_desc->integer.value = ACPI_TO_INTEGER (val);
179 break;
180
181
182 case ACPI_TYPE_STRING:
183
184 /*
185 * Build an object around the static string
186 */
187 obj_desc->string.length = (u32) ACPI_STRLEN (val);
188 obj_desc->string.pointer = val;
189 obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
190 break;
191
192
193 case ACPI_TYPE_MUTEX:
194
195 obj_desc->mutex.node = new_node;
196 obj_desc->mutex.sync_level = (u8) (ACPI_TO_INTEGER (val) - 1);
197
198 if (ACPI_STRCMP (init_val->name, "_GL_") == 0) {
199 /*
200 * Create a counting semaphore for the
201 * global lock
202 */
203 status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT,
204 1, &obj_desc->mutex.semaphore);
205 if (ACPI_FAILURE (status)) {
206 acpi_ut_remove_reference (obj_desc);
207 goto unlock_and_exit;
208 }
209
210 /*
211 * We just created the mutex for the
212 * global lock, save it
213 */
214 acpi_gbl_global_lock_semaphore = obj_desc->mutex.semaphore;
215 }
216 else {
217 /* Create a mutex */
218
219 status = acpi_os_create_semaphore (1, 1,
220 &obj_desc->mutex.semaphore);
221 if (ACPI_FAILURE (status)) {
222 acpi_ut_remove_reference (obj_desc);
223 goto unlock_and_exit;
224 }
225 }
226 break;
227
228
229 default:
230
231 ACPI_REPORT_ERROR (("Unsupported initial type value %X\n",
232 init_val->type));
233 acpi_ut_remove_reference (obj_desc);
234 obj_desc = NULL;
235 continue;
236 }
237
238 /* Store pointer to value descriptor in the Node */
239
240 status = acpi_ns_attach_object (new_node, obj_desc,
241 ACPI_GET_OBJECT_TYPE (obj_desc));
242
243 /* Remove local reference to the object */
244
245 acpi_ut_remove_reference (obj_desc);
246 }
247 }
248
249
250unlock_and_exit:
251 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
252
253 /* Save a handle to "_GPE", it is always present */
254
255 if (ACPI_SUCCESS (status)) {
256 status = acpi_ns_get_node_by_path ("\\_GPE", NULL, ACPI_NS_NO_UPSEARCH,
257 &acpi_gbl_fadt_gpe_device);
258 }
259
260 return_ACPI_STATUS (status);
261}
262
263
264/*******************************************************************************
265 *
266 * FUNCTION: acpi_ns_lookup
267 *
268 * PARAMETERS: prefix_node - Search scope if name is not fully qualified
269 * Pathname - Search pathname, in internal format
270 * (as represented in the AML stream)
271 * Type - Type associated with name
272 * interpreter_mode - IMODE_LOAD_PASS2 => add name if not found
273 * Flags - Flags describing the search restrictions
274 * walk_state - Current state of the walk
275 * return_node - Where the Node is placed (if found
276 * or created successfully)
277 *
278 * RETURN: Status
279 *
280 * DESCRIPTION: Find or enter the passed name in the name space.
281 * Log an error if name not found in Exec mode.
282 *
283 * MUTEX: Assumes namespace is locked.
284 *
285 ******************************************************************************/
286
287acpi_status
288acpi_ns_lookup (
289 union acpi_generic_state *scope_info,
290 char *pathname,
291 acpi_object_type type,
292 acpi_interpreter_mode interpreter_mode,
293 u32 flags,
294 struct acpi_walk_state *walk_state,
295 struct acpi_namespace_node **return_node)
296{
297 acpi_status status;
298 char *path = pathname;
299 struct acpi_namespace_node *prefix_node;
300 struct acpi_namespace_node *current_node = NULL;
301 struct acpi_namespace_node *this_node = NULL;
302 u32 num_segments;
303 u32 num_carats;
304 acpi_name simple_name;
305 acpi_object_type type_to_check_for;
306 acpi_object_type this_search_type;
307 u32 search_parent_flag = ACPI_NS_SEARCH_PARENT;
308 u32 local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND |
309 ACPI_NS_SEARCH_PARENT);
310
311
312 ACPI_FUNCTION_TRACE ("ns_lookup");
313
314
315 if (!return_node) {
316 return_ACPI_STATUS (AE_BAD_PARAMETER);
317 }
318
319 acpi_gbl_ns_lookup_count++;
320 *return_node = ACPI_ENTRY_NOT_FOUND;
321
322 if (!acpi_gbl_root_node) {
323 return_ACPI_STATUS (AE_NO_NAMESPACE);
324 }
325
326 /*
327 * Get the prefix scope.
328 * A null scope means use the root scope
329 */
330 if ((!scope_info) ||
331 (!scope_info->scope.node)) {
332 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
333 "Null scope prefix, using root node (%p)\n",
334 acpi_gbl_root_node));
335
336 prefix_node = acpi_gbl_root_node;
337 }
338 else {
339 prefix_node = scope_info->scope.node;
340 if (ACPI_GET_DESCRIPTOR_TYPE (prefix_node) != ACPI_DESC_TYPE_NAMED) {
341 ACPI_REPORT_ERROR (("ns_lookup: %p is not a namespace node [%s]\n",
342 prefix_node, acpi_ut_get_descriptor_name (prefix_node)));
343 return_ACPI_STATUS (AE_AML_INTERNAL);
344 }
345
346 /*
347 * This node might not be a actual "scope" node (such as a
348 * Device/Method, etc.) It could be a Package or other object node.
349 * Backup up the tree to find the containing scope node.
350 */
351 while (!acpi_ns_opens_scope (prefix_node->type) &&
352 prefix_node->type != ACPI_TYPE_ANY) {
353 prefix_node = acpi_ns_get_parent_node (prefix_node);
354 }
355 }
356
357 /* Save type TBD: may be no longer necessary */
358
359 type_to_check_for = type;
360
361 /*
362 * Begin examination of the actual pathname
363 */
364 if (!pathname) {
365 /* A Null name_path is allowed and refers to the root */
366
367 num_segments = 0;
368 this_node = acpi_gbl_root_node;
369 path = "";
370
371 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
372 "Null Pathname (Zero segments), Flags=%X\n", flags));
373 }
374 else {
375 /*
376 * Name pointer is valid (and must be in internal name format)
377 *
378 * Check for scope prefixes:
379 *
380 * As represented in the AML stream, a namepath consists of an
381 * optional scope prefix followed by a name segment part.
382 *
383 * If present, the scope prefix is either a Root Prefix (in
384 * which case the name is fully qualified), or one or more
385 * Parent Prefixes (in which case the name's scope is relative
386 * to the current scope).
387 */
388 if (*path == (u8) AML_ROOT_PREFIX) {
389 /* Pathname is fully qualified, start from the root */
390
391 this_node = acpi_gbl_root_node;
392 search_parent_flag = ACPI_NS_NO_UPSEARCH;
393
394 /* Point to name segment part */
395
396 path++;
397
398 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
399 "Path is absolute from root [%p]\n", this_node));
400 }
401 else {
402 /* Pathname is relative to current scope, start there */
403
404 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
405 "Searching relative to prefix scope [%4.4s] (%p)\n",
406 acpi_ut_get_node_name (prefix_node), prefix_node));
407
408 /*
409 * Handle multiple Parent Prefixes (carat) by just getting
410 * the parent node for each prefix instance.
411 */
412 this_node = prefix_node;
413 num_carats = 0;
414 while (*path == (u8) AML_PARENT_PREFIX) {
415 /* Name is fully qualified, no search rules apply */
416
417 search_parent_flag = ACPI_NS_NO_UPSEARCH;
418 /*
419 * Point past this prefix to the name segment
420 * part or the next Parent Prefix
421 */
422 path++;
423
424 /* Backup to the parent node */
425
426 num_carats++;
427 this_node = acpi_ns_get_parent_node (this_node);
428 if (!this_node) {
429 /* Current scope has no parent scope */
430
431 ACPI_REPORT_ERROR (
432 ("ACPI path has too many parent prefixes (^) - reached beyond root node\n"));
433 return_ACPI_STATUS (AE_NOT_FOUND);
434 }
435 }
436
437 if (search_parent_flag == ACPI_NS_NO_UPSEARCH) {
438 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
439 "Search scope is [%4.4s], path has %d carat(s)\n",
440 acpi_ut_get_node_name (this_node), num_carats));
441 }
442 }
443
444 /*
445 * Determine the number of ACPI name segments in this pathname.
446 *
447 * The segment part consists of either:
448 * - A Null name segment (0)
449 * - A dual_name_prefix followed by two 4-byte name segments
450 * - A multi_name_prefix followed by a byte indicating the
451 * number of segments and the segments themselves.
452 * - A single 4-byte name segment
453 *
454 * Examine the name prefix opcode, if any, to determine the number of
455 * segments.
456 */
457 switch (*path) {
458 case 0:
459 /*
460 * Null name after a root or parent prefixes. We already
461 * have the correct target node and there are no name segments.
462 */
463 num_segments = 0;
464 type = this_node->type;
465
466 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
467 "Prefix-only Pathname (Zero name segments), Flags=%X\n",
468 flags));
469 break;
470
471 case AML_DUAL_NAME_PREFIX:
472
473 /* More than one name_seg, search rules do not apply */
474
475 search_parent_flag = ACPI_NS_NO_UPSEARCH;
476
477 /* Two segments, point to first name segment */
478
479 num_segments = 2;
480 path++;
481
482 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
483 "Dual Pathname (2 segments, Flags=%X)\n", flags));
484 break;
485
486 case AML_MULTI_NAME_PREFIX_OP:
487
488 /* More than one name_seg, search rules do not apply */
489
490 search_parent_flag = ACPI_NS_NO_UPSEARCH;
491
492 /* Extract segment count, point to first name segment */
493
494 path++;
495 num_segments = (u32) (u8) *path;
496 path++;
497
498 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
499 "Multi Pathname (%d Segments, Flags=%X) \n",
500 num_segments, flags));
501 break;
502
503 default:
504 /*
505 * Not a Null name, no Dual or Multi prefix, hence there is
506 * only one name segment and Pathname is already pointing to it.
507 */
508 num_segments = 1;
509
510 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
511 "Simple Pathname (1 segment, Flags=%X)\n", flags));
512 break;
513 }
514
515 ACPI_DEBUG_EXEC (acpi_ns_print_pathname (num_segments, path));
516 }
517
518
519 /*
520 * Search namespace for each segment of the name. Loop through and
521 * verify (or add to the namespace) each name segment.
522 *
523 * The object type is significant only at the last name
524 * segment. (We don't care about the types along the path, only
525 * the type of the final target object.)
526 */
527 this_search_type = ACPI_TYPE_ANY;
528 current_node = this_node;
529 while (num_segments && current_node) {
530 num_segments--;
531 if (!num_segments) {
532 /*
533 * This is the last segment, enable typechecking
534 */
535 this_search_type = type;
536
537 /*
538 * Only allow automatic parent search (search rules) if the caller
539 * requested it AND we have a single, non-fully-qualified name_seg
540 */
541 if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) &&
542 (flags & ACPI_NS_SEARCH_PARENT)) {
543 local_flags |= ACPI_NS_SEARCH_PARENT;
544 }
545
546 /* Set error flag according to caller */
547
548 if (flags & ACPI_NS_ERROR_IF_FOUND) {
549 local_flags |= ACPI_NS_ERROR_IF_FOUND;
550 }
551 }
552
553 /* Extract one ACPI name from the front of the pathname */
554
555 ACPI_MOVE_32_TO_32 (&simple_name, path);
556
557 /* Try to find the single (4 character) ACPI name */
558
559 status = acpi_ns_search_and_enter (simple_name, walk_state, current_node,
560 interpreter_mode, this_search_type, local_flags, &this_node);
561 if (ACPI_FAILURE (status)) {
562 if (status == AE_NOT_FOUND) {
563 /* Name not found in ACPI namespace */
564
565 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
566 "Name [%4.4s] not found in scope [%4.4s] %p\n",
567 (char *) &simple_name, (char *) &current_node->name,
568 current_node));
569 }
570
571 *return_node = this_node;
572 return_ACPI_STATUS (status);
573 }
574
575 /*
576 * Sanity typecheck of the target object:
577 *
578 * If 1) This is the last segment (num_segments == 0)
579 * 2) And we are looking for a specific type
580 * (Not checking for TYPE_ANY)
581 * 3) Which is not an alias
582 * 4) Which is not a local type (TYPE_SCOPE)
583 * 5) And the type of target object is known (not TYPE_ANY)
584 * 6) And target object does not match what we are looking for
585 *
586 * Then we have a type mismatch. Just warn and ignore it.
587 */
588 if ((num_segments == 0) &&
589 (type_to_check_for != ACPI_TYPE_ANY) &&
590 (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
591 (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
592 (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
593 (this_node->type != ACPI_TYPE_ANY) &&
594 (this_node->type != type_to_check_for)) {
595 /* Complain about a type mismatch */
596
597 ACPI_REPORT_WARNING (
598 ("ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)\n",
599 (char *) &simple_name, acpi_ut_get_type_name (this_node->type),
600 acpi_ut_get_type_name (type_to_check_for)));
601 }
602
603 /*
604 * If this is the last name segment and we are not looking for a
605 * specific type, but the type of found object is known, use that type
606 * to see if it opens a scope.
607 */
608 if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) {
609 type = this_node->type;
610 }
611
612 /* Point to next name segment and make this node current */
613
614 path += ACPI_NAME_SIZE;
615 current_node = this_node;
616 }
617
618 /*
619 * Always check if we need to open a new scope
620 */
621 if (!(flags & ACPI_NS_DONT_OPEN_SCOPE) && (walk_state)) {
622 /*
623 * If entry is a type which opens a scope, push the new scope on the
624 * scope stack.
625 */
626 if (acpi_ns_opens_scope (type)) {
627 status = acpi_ds_scope_stack_push (this_node, type, walk_state);
628 if (ACPI_FAILURE (status)) {
629 return_ACPI_STATUS (status);
630 }
631 }
632 }
633
634 *return_node = this_node;
635 return_ACPI_STATUS (AE_OK);
636}
637
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
new file mode 100644
index 000000000000..bfd922c5c7d1
--- /dev/null
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -0,0 +1,685 @@
1/*******************************************************************************
2 *
3 * Module Name: nsalloc - Namespace allocation and deletion utilities
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47
48
49#define _COMPONENT ACPI_NAMESPACE
50 ACPI_MODULE_NAME ("nsalloc")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ns_create_node
56 *
57 * PARAMETERS: acpi_name - Name of the new node
58 *
59 * RETURN: None
60 *
61 * DESCRIPTION: Create a namespace node
62 *
63 ******************************************************************************/
64
65struct acpi_namespace_node *
66acpi_ns_create_node (
67 u32 name)
68{
69 struct acpi_namespace_node *node;
70
71
72 ACPI_FUNCTION_TRACE ("ns_create_node");
73
74
75 node = ACPI_MEM_CALLOCATE (sizeof (struct acpi_namespace_node));
76 if (!node) {
77 return_PTR (NULL);
78 }
79
80 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_allocated++);
81
82 node->name.integer = name;
83 node->reference_count = 1;
84 ACPI_SET_DESCRIPTOR_TYPE (node, ACPI_DESC_TYPE_NAMED);
85
86 return_PTR (node);
87}
88
89
90/*******************************************************************************
91 *
92 * FUNCTION: acpi_ns_delete_node
93 *
94 * PARAMETERS: Node - Node to be deleted
95 *
96 * RETURN: None
97 *
98 * DESCRIPTION: Delete a namespace node
99 *
100 ******************************************************************************/
101
102void
103acpi_ns_delete_node (
104 struct acpi_namespace_node *node)
105{
106 struct acpi_namespace_node *parent_node;
107 struct acpi_namespace_node *prev_node;
108 struct acpi_namespace_node *next_node;
109
110
111 ACPI_FUNCTION_TRACE_PTR ("ns_delete_node", node);
112
113
114 parent_node = acpi_ns_get_parent_node (node);
115
116 prev_node = NULL;
117 next_node = parent_node->child;
118
119 /* Find the node that is the previous peer in the parent's child list */
120
121 while (next_node != node) {
122 prev_node = next_node;
123 next_node = prev_node->peer;
124 }
125
126 if (prev_node) {
127 /* Node is not first child, unlink it */
128
129 prev_node->peer = next_node->peer;
130 if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
131 prev_node->flags |= ANOBJ_END_OF_PEER_LIST;
132 }
133 }
134 else {
135 /* Node is first child (has no previous peer) */
136
137 if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
138 /* No peers at all */
139
140 parent_node->child = NULL;
141 }
142 else { /* Link peer list to parent */
143
144 parent_node->child = next_node->peer;
145 }
146 }
147
148
149 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++);
150
151 /*
152 * Detach an object if there is one then delete the node
153 */
154 acpi_ns_detach_object (node);
155 ACPI_MEM_FREE (node);
156 return_VOID;
157}
158
159
160#ifdef ACPI_ALPHABETIC_NAMESPACE
161/*******************************************************************************
162 *
163 * FUNCTION: acpi_ns_compare_names
164 *
165 * PARAMETERS: Name1 - First name to compare
166 * Name2 - Second name to compare
167 *
168 * RETURN: value from strncmp
169 *
170 * DESCRIPTION: Compare two ACPI names. Names that are prefixed with an
171 * underscore are forced to be alphabetically first.
172 *
173 ******************************************************************************/
174
175int
176acpi_ns_compare_names (
177 char *name1,
178 char *name2)
179{
180 char reversed_name1[ACPI_NAME_SIZE];
181 char reversed_name2[ACPI_NAME_SIZE];
182 u32 i;
183 u32 j;
184
185
186 /*
187 * Replace all instances of "underscore" with a value that is smaller so
188 * that all names that are prefixed with underscore(s) are alphabetically
189 * first.
190 *
191 * Reverse the name bytewise so we can just do a 32-bit compare instead
192 * of a strncmp.
193 */
194 for (i = 0, j= (ACPI_NAME_SIZE - 1); i < ACPI_NAME_SIZE; i++, j--) {
195 reversed_name1[j] = name1[i];
196 if (name1[i] == '_') {
197 reversed_name1[j] = '*';
198 }
199
200 reversed_name2[j] = name2[i];
201 if (name2[i] == '_') {
202 reversed_name2[j] = '*';
203 }
204 }
205
206 return (*(int *) reversed_name1 - *(int *) reversed_name2);
207}
208#endif
209
210
211/*******************************************************************************
212 *
213 * FUNCTION: acpi_ns_install_node
214 *
215 * PARAMETERS: walk_state - Current state of the walk
216 * parent_node - The parent of the new Node
217 * Node - The new Node to install
218 * Type - ACPI object type of the new Node
219 *
220 * RETURN: None
221 *
222 * DESCRIPTION: Initialize a new namespace node and install it amongst
223 * its peers.
224 *
225 * Note: Current namespace lookup is linear search. However, the
226 * nodes are linked in alphabetical order to 1) put all reserved
227 * names (start with underscore) first, and to 2) make a readable
228 * namespace dump.
229 *
230 ******************************************************************************/
231
232void
233acpi_ns_install_node (
234 struct acpi_walk_state *walk_state,
235 struct acpi_namespace_node *parent_node, /* Parent */
236 struct acpi_namespace_node *node, /* New Child*/
237 acpi_object_type type)
238{
239 u16 owner_id = 0;
240 struct acpi_namespace_node *child_node;
241#ifdef ACPI_ALPHABETIC_NAMESPACE
242
243 struct acpi_namespace_node *previous_child_node;
244#endif
245
246
247 ACPI_FUNCTION_TRACE ("ns_install_node");
248
249
250 /*
251 * Get the owner ID from the Walk state
252 * The owner ID is used to track table deletion and
253 * deletion of objects created by methods
254 */
255 if (walk_state) {
256 owner_id = walk_state->owner_id;
257 }
258
259 /* Link the new entry into the parent and existing children */
260
261 child_node = parent_node->child;
262 if (!child_node) {
263 parent_node->child = node;
264 node->flags |= ANOBJ_END_OF_PEER_LIST;
265 node->peer = parent_node;
266 }
267 else {
268#ifdef ACPI_ALPHABETIC_NAMESPACE
269 /*
270 * Walk the list whilst searching for the correct
271 * alphabetic placement.
272 */
273 previous_child_node = NULL;
274 while (acpi_ns_compare_names (acpi_ut_get_node_name (child_node), acpi_ut_get_node_name (node)) < 0) {
275 if (child_node->flags & ANOBJ_END_OF_PEER_LIST) {
276 /* Last peer; Clear end-of-list flag */
277
278 child_node->flags &= ~ANOBJ_END_OF_PEER_LIST;
279
280 /* This node is the new peer to the child node */
281
282 child_node->peer = node;
283
284 /* This node is the new end-of-list */
285
286 node->flags |= ANOBJ_END_OF_PEER_LIST;
287 node->peer = parent_node;
288 break;
289 }
290
291 /* Get next peer */
292
293 previous_child_node = child_node;
294 child_node = child_node->peer;
295 }
296
297 /* Did the node get inserted at the end-of-list? */
298
299 if (!(node->flags & ANOBJ_END_OF_PEER_LIST)) {
300 /*
301 * Loop above terminated without reaching the end-of-list.
302 * Insert the new node at the current location
303 */
304 if (previous_child_node) {
305 /* Insert node alphabetically */
306
307 node->peer = child_node;
308 previous_child_node->peer = node;
309 }
310 else {
311 /* Insert node alphabetically at start of list */
312
313 node->peer = child_node;
314 parent_node->child = node;
315 }
316 }
317#else
318 while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) {
319 child_node = child_node->peer;
320 }
321
322 child_node->peer = node;
323
324 /* Clear end-of-list flag */
325
326 child_node->flags &= ~ANOBJ_END_OF_PEER_LIST;
327 node->flags |= ANOBJ_END_OF_PEER_LIST;
328 node->peer = parent_node;
329#endif
330 }
331
332 /* Init the new entry */
333
334 node->owner_id = owner_id;
335 node->type = (u8) type;
336
337 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
338 "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
339 acpi_ut_get_node_name (node), acpi_ut_get_type_name (node->type), node, owner_id,
340 acpi_ut_get_node_name (parent_node), acpi_ut_get_type_name (parent_node->type),
341 parent_node));
342
343 /*
344 * Increment the reference count(s) of all parents up to
345 * the root!
346 */
347 while ((node = acpi_ns_get_parent_node (node)) != NULL) {
348 node->reference_count++;
349 }
350
351 return_VOID;
352}
353
354
355/*******************************************************************************
356 *
357 * FUNCTION: acpi_ns_delete_children
358 *
359 * PARAMETERS: parent_node - Delete this objects children
360 *
361 * RETURN: None.
362 *
363 * DESCRIPTION: Delete all children of the parent object. In other words,
364 * deletes a "scope".
365 *
366 ******************************************************************************/
367
368void
369acpi_ns_delete_children (
370 struct acpi_namespace_node *parent_node)
371{
372 struct acpi_namespace_node *child_node;
373 struct acpi_namespace_node *next_node;
374 struct acpi_namespace_node *node;
375 u8 flags;
376
377
378 ACPI_FUNCTION_TRACE_PTR ("ns_delete_children", parent_node);
379
380
381 if (!parent_node) {
382 return_VOID;
383 }
384
385 /* If no children, all done! */
386
387 child_node = parent_node->child;
388 if (!child_node) {
389 return_VOID;
390 }
391
392 /*
393 * Deallocate all children at this level
394 */
395 do {
396 /* Get the things we need */
397
398 next_node = child_node->peer;
399 flags = child_node->flags;
400
401 /* Grandchildren should have all been deleted already */
402
403 if (child_node->child) {
404 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found a grandchild! P=%p C=%p\n",
405 parent_node, child_node));
406 }
407
408 /* Now we can free this child object */
409
410 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++);
411
412 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p, Remaining %X\n",
413 child_node, acpi_gbl_current_node_count));
414
415 /*
416 * Detach an object if there is one, then free the child node
417 */
418 acpi_ns_detach_object (child_node);
419
420 /*
421 * Decrement the reference count(s) of all parents up to
422 * the root! (counts were incremented when the node was created)
423 */
424 node = child_node;
425 while ((node = acpi_ns_get_parent_node (node)) != NULL) {
426 node->reference_count--;
427 }
428
429 /* There should be only one reference remaining on this node */
430
431 if (child_node->reference_count != 1) {
432 ACPI_REPORT_WARNING (("Existing references (%d) on node being deleted (%p)\n",
433 child_node->reference_count, child_node));
434 }
435
436 /* Now we can delete the node */
437
438 ACPI_MEM_FREE (child_node);
439
440 /* And move on to the next child in the list */
441
442 child_node = next_node;
443
444 } while (!(flags & ANOBJ_END_OF_PEER_LIST));
445
446
447 /* Clear the parent's child pointer */
448
449 parent_node->child = NULL;
450
451 return_VOID;
452}
453
454
455/*******************************************************************************
456 *
457 * FUNCTION: acpi_ns_delete_namespace_subtree
458 *
459 * PARAMETERS: parent_node - Root of the subtree to be deleted
460 *
461 * RETURN: None.
462 *
463 * DESCRIPTION: Delete a subtree of the namespace. This includes all objects
464 * stored within the subtree.
465 *
466 ******************************************************************************/
467
468void
469acpi_ns_delete_namespace_subtree (
470 struct acpi_namespace_node *parent_node)
471{
472 struct acpi_namespace_node *child_node = NULL;
473 u32 level = 1;
474
475
476 ACPI_FUNCTION_TRACE ("ns_delete_namespace_subtree");
477
478
479 if (!parent_node) {
480 return_VOID;
481 }
482
483 /*
484 * Traverse the tree of objects until we bubble back up
485 * to where we started.
486 */
487 while (level > 0) {
488 /* Get the next node in this scope (NULL if none) */
489
490 child_node = acpi_ns_get_next_node (ACPI_TYPE_ANY, parent_node,
491 child_node);
492 if (child_node) {
493 /* Found a child node - detach any attached object */
494
495 acpi_ns_detach_object (child_node);
496
497 /* Check if this node has any children */
498
499 if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
500 /*
501 * There is at least one child of this node,
502 * visit the node
503 */
504 level++;
505 parent_node = child_node;
506 child_node = NULL;
507 }
508 }
509 else {
510 /*
511 * No more children of this parent node.
512 * Move up to the grandparent.
513 */
514 level--;
515
516 /*
517 * Now delete all of the children of this parent
518 * all at the same time.
519 */
520 acpi_ns_delete_children (parent_node);
521
522 /* New "last child" is this parent node */
523
524 child_node = parent_node;
525
526 /* Move up the tree to the grandparent */
527
528 parent_node = acpi_ns_get_parent_node (parent_node);
529 }
530 }
531
532 return_VOID;
533}
534
535
536/*******************************************************************************
537 *
538 * FUNCTION: acpi_ns_remove_reference
539 *
540 * PARAMETERS: Node - Named node whose reference count is to be
541 * decremented
542 *
543 * RETURN: None.
544 *
545 * DESCRIPTION: Remove a Node reference. Decrements the reference count
546 * of all parent Nodes up to the root. Any node along
547 * the way that reaches zero references is freed.
548 *
549 ******************************************************************************/
550
551void
552acpi_ns_remove_reference (
553 struct acpi_namespace_node *node)
554{
555 struct acpi_namespace_node *parent_node;
556 struct acpi_namespace_node *this_node;
557
558
559 ACPI_FUNCTION_ENTRY ();
560
561
562 /*
563 * Decrement the reference count(s) of this node and all
564 * nodes up to the root, Delete anything with zero remaining references.
565 */
566 this_node = node;
567 while (this_node) {
568 /* Prepare to move up to parent */
569
570 parent_node = acpi_ns_get_parent_node (this_node);
571
572 /* Decrement the reference count on this node */
573
574 this_node->reference_count--;
575
576 /* Delete the node if no more references */
577
578 if (!this_node->reference_count) {
579 /* Delete all children and delete the node */
580
581 acpi_ns_delete_children (this_node);
582 acpi_ns_delete_node (this_node);
583 }
584
585 this_node = parent_node;
586 }
587}
588
589
590/*******************************************************************************
591 *
592 * FUNCTION: acpi_ns_delete_namespace_by_owner
593 *
594 * PARAMETERS: owner_id - All nodes with this owner will be deleted
595 *
596 * RETURN: Status
597 *
598 * DESCRIPTION: Delete entries within the namespace that are owned by a
599 * specific ID. Used to delete entire ACPI tables. All
600 * reference counts are updated.
601 *
602 ******************************************************************************/
603
604void
605acpi_ns_delete_namespace_by_owner (
606 u16 owner_id)
607{
608 struct acpi_namespace_node *child_node;
609 struct acpi_namespace_node *deletion_node;
610 u32 level;
611 struct acpi_namespace_node *parent_node;
612
613
614 ACPI_FUNCTION_TRACE_U32 ("ns_delete_namespace_by_owner", owner_id);
615
616
617 parent_node = acpi_gbl_root_node;
618 child_node = NULL;
619 deletion_node = NULL;
620 level = 1;
621
622 /*
623 * Traverse the tree of nodes until we bubble back up
624 * to where we started.
625 */
626 while (level > 0) {
627 /*
628 * Get the next child of this parent node. When child_node is NULL,
629 * the first child of the parent is returned
630 */
631 child_node = acpi_ns_get_next_node (ACPI_TYPE_ANY, parent_node, child_node);
632
633 if (deletion_node) {
634 acpi_ns_remove_reference (deletion_node);
635 deletion_node = NULL;
636 }
637
638 if (child_node) {
639 if (child_node->owner_id == owner_id) {
640 /* Found a matching child node - detach any attached object */
641
642 acpi_ns_detach_object (child_node);
643 }
644
645 /* Check if this node has any children */
646
647 if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
648 /*
649 * There is at least one child of this node,
650 * visit the node
651 */
652 level++;
653 parent_node = child_node;
654 child_node = NULL;
655 }
656 else if (child_node->owner_id == owner_id) {
657 deletion_node = child_node;
658 }
659 }
660 else {
661 /*
662 * No more children of this parent node.
663 * Move up to the grandparent.
664 */
665 level--;
666 if (level != 0) {
667 if (parent_node->owner_id == owner_id) {
668 deletion_node = parent_node;
669 }
670 }
671
672 /* New "last child" is this parent node */
673
674 child_node = parent_node;
675
676 /* Move up the tree to the grandparent */
677
678 parent_node = acpi_ns_get_parent_node (parent_node);
679 }
680 }
681
682 return_VOID;
683}
684
685
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
new file mode 100644
index 000000000000..1f6af3eb6c91
--- /dev/null
+++ b/drivers/acpi/namespace/nsdump.c
@@ -0,0 +1,673 @@
1/******************************************************************************
2 *
3 * Module Name: nsdump - table dumping routines for debug
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acparser.h>
48
49
50#define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsdump")
52
53
54#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_ns_print_pathname
59 *
60 * PARAMETERS: num_segment - Number of ACPI name segments
61 * Pathname - The compressed (internal) path
62 *
63 * DESCRIPTION: Print an object's full namespace pathname
64 *
65 ******************************************************************************/
66
67void
68acpi_ns_print_pathname (
69 u32 num_segments,
70 char *pathname)
71{
72 ACPI_FUNCTION_NAME ("ns_print_pathname");
73
74
75 if (!(acpi_dbg_level & ACPI_LV_NAMES) || !(acpi_dbg_layer & ACPI_NAMESPACE)) {
76 return;
77 }
78
79 /* Print the entire name */
80
81 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "["));
82
83 while (num_segments) {
84 acpi_os_printf ("%4.4s", pathname);
85 pathname += ACPI_NAME_SIZE;
86
87 num_segments--;
88 if (num_segments) {
89 acpi_os_printf (".");
90 }
91 }
92
93 acpi_os_printf ("]\n");
94}
95
96
97/*******************************************************************************
98 *
99 * FUNCTION: acpi_ns_dump_pathname
100 *
101 * PARAMETERS: Handle - Object
102 * Msg - Prefix message
103 * Level - Desired debug level
104 * Component - Caller's component ID
105 *
106 * DESCRIPTION: Print an object's full namespace pathname
107 * Manages allocation/freeing of a pathname buffer
108 *
109 ******************************************************************************/
110
111void
112acpi_ns_dump_pathname (
113 acpi_handle handle,
114 char *msg,
115 u32 level,
116 u32 component)
117{
118
119 ACPI_FUNCTION_TRACE ("ns_dump_pathname");
120
121
122 /* Do this only if the requested debug level and component are enabled */
123
124 if (!(acpi_dbg_level & level) || !(acpi_dbg_layer & component)) {
125 return_VOID;
126 }
127
128 /* Convert handle to a full pathname and print it (with supplied message) */
129
130 acpi_ns_print_node_pathname (handle, msg);
131 acpi_os_printf ("\n");
132 return_VOID;
133}
134
135
136/*******************************************************************************
137 *
138 * FUNCTION: acpi_ns_dump_one_object
139 *
140 * PARAMETERS: Handle - Node to be dumped
141 * Level - Nesting level of the handle
142 * Context - Passed into walk_namespace
143 *
144 * DESCRIPTION: Dump a single Node
145 * This procedure is a user_function called by acpi_ns_walk_namespace.
146 *
147 ******************************************************************************/
148
149acpi_status
150acpi_ns_dump_one_object (
151 acpi_handle obj_handle,
152 u32 level,
153 void *context,
154 void **return_value)
155{
156 struct acpi_walk_info *info = (struct acpi_walk_info *) context;
157 struct acpi_namespace_node *this_node;
158 union acpi_operand_object *obj_desc = NULL;
159 acpi_object_type obj_type;
160 acpi_object_type type;
161 u32 bytes_to_dump;
162 u32 dbg_level;
163 u32 i;
164
165
166 ACPI_FUNCTION_NAME ("ns_dump_one_object");
167
168
169 /* Is output enabled? */
170
171 if (!(acpi_dbg_level & info->debug_level)) {
172 return (AE_OK);
173 }
174
175 if (!obj_handle) {
176 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Null object handle\n"));
177 return (AE_OK);
178 }
179
180 this_node = acpi_ns_map_handle_to_node (obj_handle);
181 type = this_node->type;
182
183 /* Check if the owner matches */
184
185 if ((info->owner_id != ACPI_UINT32_MAX) &&
186 (info->owner_id != this_node->owner_id)) {
187 return (AE_OK);
188 }
189
190 /* Indent the object according to the level */
191
192 acpi_os_printf ("%2d%*s", (u32) level - 1, (int) level * 2, " ");
193
194 /* Check the node type and name */
195
196 if (type > ACPI_TYPE_LOCAL_MAX) {
197 ACPI_REPORT_WARNING (("Invalid ACPI Type %08X\n", type));
198 }
199
200 if (!acpi_ut_valid_acpi_name (this_node->name.integer)) {
201 ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n",
202 this_node->name.integer));
203 }
204
205 /*
206 * Now we can print out the pertinent information
207 */
208 acpi_os_printf ("%4.4s %-12s %p ",
209 acpi_ut_get_node_name (this_node), acpi_ut_get_type_name (type), this_node);
210
211 dbg_level = acpi_dbg_level;
212 acpi_dbg_level = 0;
213 obj_desc = acpi_ns_get_attached_object (this_node);
214 acpi_dbg_level = dbg_level;
215
216 switch (info->display_type) {
217 case ACPI_DISPLAY_SUMMARY:
218
219 if (!obj_desc) {
220 /* No attached object, we are done */
221
222 acpi_os_printf ("\n");
223 return (AE_OK);
224 }
225
226 switch (type) {
227 case ACPI_TYPE_PROCESSOR:
228
229 acpi_os_printf ("ID %X Len %.4X Addr %p\n",
230 obj_desc->processor.proc_id, obj_desc->processor.length,
231 (char *) obj_desc->processor.address);
232 break;
233
234
235 case ACPI_TYPE_DEVICE:
236
237 acpi_os_printf ("Notify Object: %p\n", obj_desc);
238 break;
239
240
241 case ACPI_TYPE_METHOD:
242
243 acpi_os_printf ("Args %X Len %.4X Aml %p\n",
244 (u32) obj_desc->method.param_count,
245 obj_desc->method.aml_length, obj_desc->method.aml_start);
246 break;
247
248
249 case ACPI_TYPE_INTEGER:
250
251 acpi_os_printf ("= %8.8X%8.8X\n",
252 ACPI_FORMAT_UINT64 (obj_desc->integer.value));
253 break;
254
255
256 case ACPI_TYPE_PACKAGE:
257
258 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
259 acpi_os_printf ("Elements %.2X\n",
260 obj_desc->package.count);
261 }
262 else {
263 acpi_os_printf ("[Length not yet evaluated]\n");
264 }
265 break;
266
267
268 case ACPI_TYPE_BUFFER:
269
270 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
271 acpi_os_printf ("Len %.2X",
272 obj_desc->buffer.length);
273
274 /* Dump some of the buffer */
275
276 if (obj_desc->buffer.length > 0) {
277 acpi_os_printf (" =");
278 for (i = 0; (i < obj_desc->buffer.length && i < 12); i++) {
279 acpi_os_printf (" %.2hX", obj_desc->buffer.pointer[i]);
280 }
281 }
282 acpi_os_printf ("\n");
283 }
284 else {
285 acpi_os_printf ("[Length not yet evaluated]\n");
286 }
287 break;
288
289
290 case ACPI_TYPE_STRING:
291
292 acpi_os_printf ("Len %.2X ", obj_desc->string.length);
293 acpi_ut_print_string (obj_desc->string.pointer, 32);
294 acpi_os_printf ("\n");
295 break;
296
297
298 case ACPI_TYPE_REGION:
299
300 acpi_os_printf ("[%s]",
301 acpi_ut_get_region_name (obj_desc->region.space_id));
302 if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
303 acpi_os_printf (" Addr %8.8X%8.8X Len %.4X\n",
304 ACPI_FORMAT_UINT64 (obj_desc->region.address),
305 obj_desc->region.length);
306 }
307 else {
308 acpi_os_printf (" [Address/Length not yet evaluated]\n");
309 }
310 break;
311
312
313 case ACPI_TYPE_LOCAL_REFERENCE:
314
315 acpi_os_printf ("[%s]\n",
316 acpi_ps_get_opcode_name (obj_desc->reference.opcode));
317 break;
318
319
320 case ACPI_TYPE_BUFFER_FIELD:
321
322 if (obj_desc->buffer_field.buffer_obj &&
323 obj_desc->buffer_field.buffer_obj->buffer.node) {
324 acpi_os_printf ("Buf [%4.4s]",
325 acpi_ut_get_node_name (obj_desc->buffer_field.buffer_obj->buffer.node));
326 }
327 break;
328
329
330 case ACPI_TYPE_LOCAL_REGION_FIELD:
331
332 acpi_os_printf ("Rgn [%4.4s]",
333 acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node));
334 break;
335
336
337 case ACPI_TYPE_LOCAL_BANK_FIELD:
338
339 acpi_os_printf ("Rgn [%4.4s] Bnk [%4.4s]",
340 acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node),
341 acpi_ut_get_node_name (obj_desc->bank_field.bank_obj->common_field.node));
342 break;
343
344
345 case ACPI_TYPE_LOCAL_INDEX_FIELD:
346
347 acpi_os_printf ("Idx [%4.4s] Dat [%4.4s]",
348 acpi_ut_get_node_name (obj_desc->index_field.index_obj->common_field.node),
349 acpi_ut_get_node_name (obj_desc->index_field.data_obj->common_field.node));
350 break;
351
352
353 case ACPI_TYPE_LOCAL_ALIAS:
354 case ACPI_TYPE_LOCAL_METHOD_ALIAS:
355
356 acpi_os_printf ("Target %4.4s (%p)\n",
357 acpi_ut_get_node_name (obj_desc), obj_desc);
358 break;
359
360 default:
361
362 acpi_os_printf ("Object %p\n", obj_desc);
363 break;
364 }
365
366 /* Common field handling */
367
368 switch (type) {
369 case ACPI_TYPE_BUFFER_FIELD:
370 case ACPI_TYPE_LOCAL_REGION_FIELD:
371 case ACPI_TYPE_LOCAL_BANK_FIELD:
372 case ACPI_TYPE_LOCAL_INDEX_FIELD:
373
374 acpi_os_printf (" Off %.3X Len %.2X Acc %.2hd\n",
375 (obj_desc->common_field.base_byte_offset * 8)
376 + obj_desc->common_field.start_field_bit_offset,
377 obj_desc->common_field.bit_length,
378 obj_desc->common_field.access_byte_width);
379 break;
380
381 default:
382 break;
383 }
384 break;
385
386
387 case ACPI_DISPLAY_OBJECTS:
388
389 acpi_os_printf ("O:%p", obj_desc);
390 if (!obj_desc) {
391 /* No attached object, we are done */
392
393 acpi_os_printf ("\n");
394 return (AE_OK);
395 }
396
397 acpi_os_printf ("(R%d)",
398 obj_desc->common.reference_count);
399
400 switch (type) {
401 case ACPI_TYPE_METHOD:
402
403 /* Name is a Method and its AML offset/length are set */
404
405 acpi_os_printf (" M:%p-%X\n", obj_desc->method.aml_start,
406 obj_desc->method.aml_length);
407 break;
408
409 case ACPI_TYPE_INTEGER:
410
411 acpi_os_printf (" I:%8.8X8.8%X\n",
412 ACPI_FORMAT_UINT64 (obj_desc->integer.value));
413 break;
414
415 case ACPI_TYPE_STRING:
416
417 acpi_os_printf (" S:%p-%X\n", obj_desc->string.pointer,
418 obj_desc->string.length);
419 break;
420
421 case ACPI_TYPE_BUFFER:
422
423 acpi_os_printf (" B:%p-%X\n", obj_desc->buffer.pointer,
424 obj_desc->buffer.length);
425 break;
426
427 default:
428
429 acpi_os_printf ("\n");
430 break;
431 }
432 break;
433
434
435 default:
436 acpi_os_printf ("\n");
437 break;
438 }
439
440 /* If debug turned off, done */
441
442 if (!(acpi_dbg_level & ACPI_LV_VALUES)) {
443 return (AE_OK);
444 }
445
446
447 /* If there is an attached object, display it */
448
449 dbg_level = acpi_dbg_level;
450 acpi_dbg_level = 0;
451 obj_desc = acpi_ns_get_attached_object (this_node);
452 acpi_dbg_level = dbg_level;
453
454 /* Dump attached objects */
455
456 while (obj_desc) {
457 obj_type = ACPI_TYPE_INVALID;
458 acpi_os_printf (" Attached Object %p: ", obj_desc);
459
460 /* Decode the type of attached object and dump the contents */
461
462 switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
463 case ACPI_DESC_TYPE_NAMED:
464
465 acpi_os_printf ("(Ptr to Node)\n");
466 bytes_to_dump = sizeof (struct acpi_namespace_node);
467 break;
468
469
470 case ACPI_DESC_TYPE_OPERAND:
471
472 obj_type = ACPI_GET_OBJECT_TYPE (obj_desc);
473
474 if (obj_type > ACPI_TYPE_LOCAL_MAX) {
475 acpi_os_printf ("(Ptr to ACPI Object type %X [UNKNOWN])\n",
476 obj_type);
477 bytes_to_dump = 32;
478 }
479 else {
480 acpi_os_printf ("(Ptr to ACPI Object type %s, %X)\n",
481 acpi_ut_get_type_name (obj_type), obj_type);
482 bytes_to_dump = sizeof (union acpi_operand_object);
483 }
484 break;
485
486
487 default:
488
489 acpi_os_printf (
490 "(String or Buffer ptr - not an object descriptor) [%s]\n",
491 acpi_ut_get_descriptor_name (obj_desc));
492 bytes_to_dump = 16;
493 break;
494 }
495
496 ACPI_DUMP_BUFFER (obj_desc, bytes_to_dump);
497
498 /* If value is NOT an internal object, we are done */
499
500 if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) {
501 goto cleanup;
502 }
503
504 /*
505 * Valid object, get the pointer to next level, if any
506 */
507 switch (obj_type) {
508 case ACPI_TYPE_STRING:
509 obj_desc = (void *) obj_desc->string.pointer;
510 break;
511
512 case ACPI_TYPE_BUFFER:
513 obj_desc = (void *) obj_desc->buffer.pointer;
514 break;
515
516 case ACPI_TYPE_BUFFER_FIELD:
517 obj_desc = (union acpi_operand_object *) obj_desc->buffer_field.buffer_obj;
518 break;
519
520 case ACPI_TYPE_PACKAGE:
521 obj_desc = (void *) obj_desc->package.elements;
522 break;
523
524 case ACPI_TYPE_METHOD:
525 obj_desc = (void *) obj_desc->method.aml_start;
526 break;
527
528 case ACPI_TYPE_LOCAL_REGION_FIELD:
529 obj_desc = (void *) obj_desc->field.region_obj;
530 break;
531
532 case ACPI_TYPE_LOCAL_BANK_FIELD:
533 obj_desc = (void *) obj_desc->bank_field.region_obj;
534 break;
535
536 case ACPI_TYPE_LOCAL_INDEX_FIELD:
537 obj_desc = (void *) obj_desc->index_field.index_obj;
538 break;
539
540 default:
541 goto cleanup;
542 }
543
544 obj_type = ACPI_TYPE_INVALID; /* Terminate loop after next pass */
545 }
546
547cleanup:
548 acpi_os_printf ("\n");
549 return (AE_OK);
550}
551
552
553#ifdef ACPI_FUTURE_USAGE
554
555/*******************************************************************************
556 *
557 * FUNCTION: acpi_ns_dump_objects
558 *
559 * PARAMETERS: Type - Object type to be dumped
560 * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX
561 * for an effectively unlimited depth.
562 * owner_id - Dump only objects owned by this ID. Use
563 * ACPI_UINT32_MAX to match all owners.
564 * start_handle - Where in namespace to start/end search
565 *
566 * DESCRIPTION: Dump typed objects within the loaded namespace.
567 * Uses acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object.
568 *
569 ******************************************************************************/
570
571void
572acpi_ns_dump_objects (
573 acpi_object_type type,
574 u8 display_type,
575 u32 max_depth,
576 u32 owner_id,
577 acpi_handle start_handle)
578{
579 struct acpi_walk_info info;
580
581
582 ACPI_FUNCTION_ENTRY ();
583
584
585 info.debug_level = ACPI_LV_TABLES;
586 info.owner_id = owner_id;
587 info.display_type = display_type;
588
589 (void) acpi_ns_walk_namespace (type, start_handle, max_depth,
590 ACPI_NS_WALK_NO_UNLOCK, acpi_ns_dump_one_object,
591 (void *) &info, NULL);
592}
593
594
595/*******************************************************************************
596 *
597 * FUNCTION: acpi_ns_dump_tables
598 *
599 * PARAMETERS: search_base - Root of subtree to be dumped, or
600 * NS_ALL to dump the entire namespace
601 * max_depth - Maximum depth of dump. Use INT_MAX
602 * for an effectively unlimited depth.
603 *
604 * DESCRIPTION: Dump the name space, or a portion of it.
605 *
606 ******************************************************************************/
607
608void
609acpi_ns_dump_tables (
610 acpi_handle search_base,
611 u32 max_depth)
612{
613 acpi_handle search_handle = search_base;
614
615
616 ACPI_FUNCTION_TRACE ("ns_dump_tables");
617
618
619 if (!acpi_gbl_root_node) {
620 /*
621 * If the name space has not been initialized,
622 * there is nothing to dump.
623 */
624 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "namespace not initialized!\n"));
625 return_VOID;
626 }
627
628 if (ACPI_NS_ALL == search_base) {
629 /* entire namespace */
630
631 search_handle = acpi_gbl_root_node;
632 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "\\\n"));
633 }
634
635 acpi_ns_dump_objects (ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, max_depth,
636 ACPI_UINT32_MAX, search_handle);
637 return_VOID;
638}
639
640#endif /* ACPI_FUTURE_USAGE */
641
642
643/*******************************************************************************
644 *
645 * FUNCTION: acpi_ns_dump_entry
646 *
647 * PARAMETERS: Handle - Node to be dumped
648 * debug_level - Output level
649 *
650 * DESCRIPTION: Dump a single Node
651 *
652 ******************************************************************************/
653
654void
655acpi_ns_dump_entry (
656 acpi_handle handle,
657 u32 debug_level)
658{
659 struct acpi_walk_info info;
660
661
662 ACPI_FUNCTION_ENTRY ();
663
664
665 info.debug_level = debug_level;
666 info.owner_id = ACPI_UINT32_MAX;
667 info.display_type = ACPI_DISPLAY_SUMMARY;
668
669 (void) acpi_ns_dump_one_object (handle, 1, &info, NULL);
670}
671
672#endif
673
diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c
new file mode 100644
index 000000000000..d30a59e6b07d
--- /dev/null
+++ b/drivers/acpi/namespace/nsdumpdv.c
@@ -0,0 +1,146 @@
1/******************************************************************************
2 *
3 * Module Name: nsdump - table dumping routines for debug
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47
48
49#define _COMPONENT ACPI_NAMESPACE
50 ACPI_MODULE_NAME ("nsdumpdv")
51
52
53#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
54
55/*******************************************************************************
56 *
57 * FUNCTION: acpi_ns_dump_one_device
58 *
59 * PARAMETERS: Handle - Node to be dumped
60 * Level - Nesting level of the handle
61 * Context - Passed into walk_namespace
62 *
63 * DESCRIPTION: Dump a single Node that represents a device
64 * This procedure is a user_function called by acpi_ns_walk_namespace.
65 *
66 ******************************************************************************/
67
68acpi_status
69acpi_ns_dump_one_device (
70 acpi_handle obj_handle,
71 u32 level,
72 void *context,
73 void **return_value)
74{
75 struct acpi_buffer buffer;
76 struct acpi_device_info *info;
77 acpi_status status;
78 u32 i;
79
80
81 ACPI_FUNCTION_NAME ("ns_dump_one_device");
82
83
84 status = acpi_ns_dump_one_object (obj_handle, level, context, return_value);
85
86 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
87 status = acpi_get_object_info (obj_handle, &buffer);
88 if (ACPI_SUCCESS (status)) {
89 info = buffer.pointer;
90 for (i = 0; i < level; i++) {
91 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " "));
92 }
93
94 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES,
95 " HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
96 info->hardware_id.value, ACPI_FORMAT_UINT64 (info->address),
97 info->current_status));
98 ACPI_MEM_FREE (info);
99 }
100
101 return (status);
102}
103
104
105/*******************************************************************************
106 *
107 * FUNCTION: acpi_ns_dump_root_devices
108 *
109 * PARAMETERS: None
110 *
111 * DESCRIPTION: Dump all objects of type "device"
112 *
113 ******************************************************************************/
114
115void
116acpi_ns_dump_root_devices (void)
117{
118 acpi_handle sys_bus_handle;
119 acpi_status status;
120
121
122 ACPI_FUNCTION_NAME ("ns_dump_root_devices");
123
124
125 /* Only dump the table if tracing is enabled */
126
127 if (!(ACPI_LV_TABLES & acpi_dbg_level)) {
128 return;
129 }
130
131 status = acpi_get_handle(NULL, ACPI_NS_SYSTEM_BUS, &sys_bus_handle);
132 if (ACPI_FAILURE (status)) {
133 return;
134 }
135
136 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
137 "Display of all devices in the namespace:\n"));
138
139 status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, sys_bus_handle,
140 ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
141 acpi_ns_dump_one_device, NULL, NULL);
142}
143
144#endif
145
146
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
new file mode 100644
index 000000000000..0d008d53657e
--- /dev/null
+++ b/drivers/acpi/namespace/nseval.c
@@ -0,0 +1,487 @@
1/*******************************************************************************
2 *
3 * Module Name: nseval - Object evaluation interfaces -- includes control
4 * method lookup and execution.
5 *
6 ******************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acparser.h>
48#include <acpi/acinterp.h>
49#include <acpi/acnamesp.h>
50
51
52#define _COMPONENT ACPI_NAMESPACE
53 ACPI_MODULE_NAME ("nseval")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_ns_evaluate_relative
59 *
60 * PARAMETERS: Pathname - Name of method to execute, If NULL, the
61 * handle is the object to execute
62 * Info - Method info block
63 *
64 * RETURN: Status
65 *
66 * DESCRIPTION: Find and execute the requested method using the handle as a
67 * scope
68 *
69 * MUTEX: Locks Namespace
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_ns_evaluate_relative (
75 char *pathname,
76 struct acpi_parameter_info *info)
77{
78 acpi_status status;
79 struct acpi_namespace_node *node = NULL;
80 union acpi_generic_state *scope_info;
81 char *internal_path = NULL;
82
83
84 ACPI_FUNCTION_TRACE ("ns_evaluate_relative");
85
86
87 /*
88 * Must have a valid object handle
89 */
90 if (!info || !info->node) {
91 return_ACPI_STATUS (AE_BAD_PARAMETER);
92 }
93
94 /* Build an internal name string for the method */
95
96 status = acpi_ns_internalize_name (pathname, &internal_path);
97 if (ACPI_FAILURE (status)) {
98 return_ACPI_STATUS (status);
99 }
100
101 scope_info = acpi_ut_create_generic_state ();
102 if (!scope_info) {
103 goto cleanup1;
104 }
105
106 /* Get the prefix handle and Node */
107
108 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
109 if (ACPI_FAILURE (status)) {
110 goto cleanup;
111 }
112
113 info->node = acpi_ns_map_handle_to_node (info->node);
114 if (!info->node) {
115 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
116 status = AE_BAD_PARAMETER;
117 goto cleanup;
118 }
119
120 /* Lookup the name in the namespace */
121
122 scope_info->scope.node = info->node;
123 status = acpi_ns_lookup (scope_info, internal_path, ACPI_TYPE_ANY,
124 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
125 &node);
126
127 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
128
129 if (ACPI_FAILURE (status)) {
130 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Object [%s] not found [%s]\n",
131 pathname, acpi_format_exception (status)));
132 goto cleanup;
133 }
134
135 /*
136 * Now that we have a handle to the object, we can attempt to evaluate it.
137 */
138 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
139 pathname, node, acpi_ns_get_attached_object (node)));
140
141 info->node = node;
142 status = acpi_ns_evaluate_by_handle (info);
143
144 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
145 pathname));
146
147cleanup:
148 acpi_ut_delete_generic_state (scope_info);
149
150cleanup1:
151 ACPI_MEM_FREE (internal_path);
152 return_ACPI_STATUS (status);
153}
154
155
156/*******************************************************************************
157 *
158 * FUNCTION: acpi_ns_evaluate_by_name
159 *
160 * PARAMETERS: Pathname - Fully qualified pathname to the object
161 * Info - Contains:
162 * return_object - Where to put method's return value (if
163 * any). If NULL, no value is returned.
164 * Params - List of parameters to pass to the method,
165 * terminated by NULL. Params itself may be
166 * NULL if no parameters are being passed.
167 *
168 * RETURN: Status
169 *
170 * DESCRIPTION: Find and execute the requested method passing the given
171 * parameters
172 *
173 * MUTEX: Locks Namespace
174 *
175 ******************************************************************************/
176
177acpi_status
178acpi_ns_evaluate_by_name (
179 char *pathname,
180 struct acpi_parameter_info *info)
181{
182 acpi_status status;
183 char *internal_path = NULL;
184
185
186 ACPI_FUNCTION_TRACE ("ns_evaluate_by_name");
187
188
189 /* Build an internal name string for the method */
190
191 status = acpi_ns_internalize_name (pathname, &internal_path);
192 if (ACPI_FAILURE (status)) {
193 return_ACPI_STATUS (status);
194 }
195
196 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
197 if (ACPI_FAILURE (status)) {
198 goto cleanup;
199 }
200
201 /* Lookup the name in the namespace */
202
203 status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY,
204 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
205 &info->node);
206
207 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
208
209 if (ACPI_FAILURE (status)) {
210 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
211 "Object at [%s] was not found, status=%.4X\n",
212 pathname, status));
213 goto cleanup;
214 }
215
216 /*
217 * Now that we have a handle to the object, we can attempt to evaluate it.
218 */
219 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
220 pathname, info->node, acpi_ns_get_attached_object (info->node)));
221
222 status = acpi_ns_evaluate_by_handle (info);
223
224 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
225 pathname));
226
227
228cleanup:
229
230 /* Cleanup */
231
232 if (internal_path) {
233 ACPI_MEM_FREE (internal_path);
234 }
235
236 return_ACPI_STATUS (status);
237}
238
239
240/*******************************************************************************
241 *
242 * FUNCTION: acpi_ns_evaluate_by_handle
243 *
244 * PARAMETERS: Handle - Method Node to execute
245 * Params - List of parameters to pass to the method,
246 * terminated by NULL. Params itself may be
247 * NULL if no parameters are being passed.
248 * param_type - Type of Parameter list
249 * return_object - Where to put method's return value (if
250 * any). If NULL, no value is returned.
251 *
252 * RETURN: Status
253 *
254 * DESCRIPTION: Execute the requested method passing the given parameters
255 *
256 * MUTEX: Locks Namespace
257 *
258 ******************************************************************************/
259
260acpi_status
261acpi_ns_evaluate_by_handle (
262 struct acpi_parameter_info *info)
263{
264 acpi_status status;
265
266
267 ACPI_FUNCTION_TRACE ("ns_evaluate_by_handle");
268
269
270 /* Check if namespace has been initialized */
271
272 if (!acpi_gbl_root_node) {
273 return_ACPI_STATUS (AE_NO_NAMESPACE);
274 }
275
276 /* Parameter Validation */
277
278 if (!info) {
279 return_ACPI_STATUS (AE_BAD_PARAMETER);
280 }
281
282 /* Initialize the return value to an invalid object */
283
284 info->return_object = NULL;
285
286 /* Get the prefix handle and Node */
287
288 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
289 if (ACPI_FAILURE (status)) {
290 return_ACPI_STATUS (status);
291 }
292
293 info->node = acpi_ns_map_handle_to_node (info->node);
294 if (!info->node) {
295 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
296 return_ACPI_STATUS (AE_BAD_PARAMETER);
297 }
298
299 /*
300 * For a method alias, we must grab the actual method node so that proper
301 * scoping context will be established before execution.
302 */
303 if (acpi_ns_get_type (info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
304 info->node = ACPI_CAST_PTR (struct acpi_namespace_node, info->node->object);
305 }
306
307 /*
308 * Two major cases here:
309 * 1) The object is an actual control method -- execute it.
310 * 2) The object is not a method -- just return it's current value
311 *
312 * In both cases, the namespace is unlocked by the acpi_ns* procedure
313 */
314 if (acpi_ns_get_type (info->node) == ACPI_TYPE_METHOD) {
315 /*
316 * Case 1) We have an actual control method to execute
317 */
318 status = acpi_ns_execute_control_method (info);
319 }
320 else {
321 /*
322 * Case 2) Object is NOT a method, just return its current value
323 */
324 status = acpi_ns_get_object_value (info);
325 }
326
327 /*
328 * Check if there is a return value on the stack that must be dealt with
329 */
330 if (status == AE_CTRL_RETURN_VALUE) {
331 /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
332
333 status = AE_OK;
334 }
335
336 /*
337 * Namespace was unlocked by the handling acpi_ns* function, so we
338 * just return
339 */
340 return_ACPI_STATUS (status);
341}
342
343
344/*******************************************************************************
345 *
346 * FUNCTION: acpi_ns_execute_control_method
347 *
348 * PARAMETERS: Info - Method info block (w/params)
349 *
350 * RETURN: Status
351 *
352 * DESCRIPTION: Execute the requested method passing the given parameters
353 *
354 * MUTEX: Assumes namespace is locked
355 *
356 ******************************************************************************/
357
358acpi_status
359acpi_ns_execute_control_method (
360 struct acpi_parameter_info *info)
361{
362 acpi_status status;
363 union acpi_operand_object *obj_desc;
364
365
366 ACPI_FUNCTION_TRACE ("ns_execute_control_method");
367
368
369 /* Verify that there is a method associated with this object */
370
371 obj_desc = acpi_ns_get_attached_object (info->node);
372 if (!obj_desc) {
373 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n"));
374
375 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
376 return_ACPI_STATUS (AE_NULL_OBJECT);
377 }
378
379 ACPI_DUMP_PATHNAME (info->node, "Execute Method:",
380 ACPI_LV_INFO, _COMPONENT);
381
382 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
383 obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1));
384
385 /*
386 * Unlock the namespace before execution. This allows namespace access
387 * via the external Acpi* interfaces while a method is being executed.
388 * However, any namespace deletion must acquire both the namespace and
389 * interpreter locks to ensure that no thread is using the portion of the
390 * namespace that is being deleted.
391 */
392 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
393 if (ACPI_FAILURE (status)) {
394 return_ACPI_STATUS (status);
395 }
396
397 /*
398 * Execute the method via the interpreter. The interpreter is locked
399 * here before calling into the AML parser
400 */
401 status = acpi_ex_enter_interpreter ();
402 if (ACPI_FAILURE (status)) {
403 return_ACPI_STATUS (status);
404 }
405
406 status = acpi_psx_execute (info);
407 acpi_ex_exit_interpreter ();
408
409 return_ACPI_STATUS (status);
410}
411
412
413/*******************************************************************************
414 *
415 * FUNCTION: acpi_ns_get_object_value
416 *
417 * PARAMETERS: Info - Method info block (w/params)
418 *
419 * RETURN: Status
420 *
421 * DESCRIPTION: Return the current value of the object
422 *
423 * MUTEX: Assumes namespace is locked, leaves namespace unlocked
424 *
425 ******************************************************************************/
426
427acpi_status
428acpi_ns_get_object_value (
429 struct acpi_parameter_info *info)
430{
431 acpi_status status = AE_OK;
432 struct acpi_namespace_node *resolved_node = info->node;
433
434
435 ACPI_FUNCTION_TRACE ("ns_get_object_value");
436
437
438 /*
439 * Objects require additional resolution steps (e.g., the Node may be a
440 * field that must be read, etc.) -- we can't just grab the object out of
441 * the node.
442 */
443
444 /*
445 * Use resolve_node_to_value() to get the associated value. This call always
446 * deletes obj_desc (allocated above).
447 *
448 * NOTE: we can get away with passing in NULL for a walk state because
449 * obj_desc is guaranteed to not be a reference to either a method local or
450 * a method argument (because this interface can only be called from the
451 * acpi_evaluate external interface, never called from a running method.)
452 *
453 * Even though we do not directly invoke the interpreter for this, we must
454 * enter it because we could access an opregion. The opregion access code
455 * assumes that the interpreter is locked.
456 *
457 * We must release the namespace lock before entering the intepreter.
458 */
459 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
460 if (ACPI_FAILURE (status)) {
461 return_ACPI_STATUS (status);
462 }
463
464 status = acpi_ex_enter_interpreter ();
465 if (ACPI_SUCCESS (status)) {
466 status = acpi_ex_resolve_node_to_value (&resolved_node, NULL);
467 /*
468 * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed
469 * in resolved_node.
470 */
471 acpi_ex_exit_interpreter ();
472
473 if (ACPI_SUCCESS (status)) {
474 status = AE_CTRL_RETURN_VALUE;
475 info->return_object = ACPI_CAST_PTR
476 (union acpi_operand_object, resolved_node);
477 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
478 info->return_object,
479 acpi_ut_get_object_type_name (info->return_object)));
480 }
481 }
482
483 /* Namespace is unlocked */
484
485 return_ACPI_STATUS (status);
486}
487
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
new file mode 100644
index 000000000000..4a46b380605b
--- /dev/null
+++ b/drivers/acpi/namespace/nsinit.c
@@ -0,0 +1,441 @@
1/******************************************************************************
2 *
3 * Module Name: nsinit - namespace initialization
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acdispat.h>
48#include <acpi/acinterp.h>
49
50#define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsinit")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ns_initialize_objects
57 *
58 * PARAMETERS: None
59 *
60 * RETURN: Status
61 *
62 * DESCRIPTION: Walk the entire namespace and perform any necessary
63 * initialization on the objects found therein
64 *
65 ******************************************************************************/
66
67acpi_status
68acpi_ns_initialize_objects (
69 void)
70{
71 acpi_status status;
72 struct acpi_init_walk_info info;
73
74
75 ACPI_FUNCTION_TRACE ("ns_initialize_objects");
76
77
78 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
79 "**** Starting initialization of namespace objects ****\n"));
80 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
81 "Completing Region/Field/Buffer/Package initialization:"));
82
83 /* Set all init info to zero */
84
85 ACPI_MEMSET (&info, 0, sizeof (struct acpi_init_walk_info));
86
87 /* Walk entire namespace from the supplied root */
88
89 status = acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
90 ACPI_UINT32_MAX, acpi_ns_init_one_object,
91 &info, NULL);
92 if (ACPI_FAILURE (status)) {
93 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
94 acpi_format_exception (status)));
95 }
96
97 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
98 "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd Buffers %hd/%hd Packages (%hd nodes)\n",
99 info.op_region_init, info.op_region_count,
100 info.field_init, info.field_count,
101 info.buffer_init, info.buffer_count,
102 info.package_init, info.package_count, info.object_count));
103
104 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
105 "%hd Control Methods found\n", info.method_count));
106 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
107 "%hd Op Regions found\n", info.op_region_count));
108
109 return_ACPI_STATUS (AE_OK);
110}
111
112
113/*******************************************************************************
114 *
115 * FUNCTION: acpi_ns_initialize_devices
116 *
117 * PARAMETERS: None
118 *
119 * RETURN: acpi_status
120 *
121 * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
122 * This means running _INI on all present devices.
123 *
124 * Note: We install PCI config space handler on region access,
125 * not here.
126 *
127 ******************************************************************************/
128
129acpi_status
130acpi_ns_initialize_devices (
131 void)
132{
133 acpi_status status;
134 struct acpi_device_walk_info info;
135
136
137 ACPI_FUNCTION_TRACE ("ns_initialize_devices");
138
139
140 /* Init counters */
141
142 info.device_count = 0;
143 info.num_STA = 0;
144 info.num_INI = 0;
145
146 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
147 "Executing all Device _STA and_INI methods:"));
148
149 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
150 if (ACPI_FAILURE (status)) {
151 return_ACPI_STATUS (status);
152 }
153
154 /* Walk namespace for all objects */
155
156 status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
157 ACPI_UINT32_MAX, TRUE, acpi_ns_init_one_device, &info, NULL);
158
159 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
160
161 if (ACPI_FAILURE (status)) {
162 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
163 acpi_format_exception (status)));
164 }
165
166 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
167 "\n%hd Devices found containing: %hd _STA, %hd _INI methods\n",
168 info.device_count, info.num_STA, info.num_INI));
169
170 return_ACPI_STATUS (status);
171}
172
173
174/*******************************************************************************
175 *
176 * FUNCTION: acpi_ns_init_one_object
177 *
178 * PARAMETERS: obj_handle - Node
179 * Level - Current nesting level
180 * Context - Points to a init info struct
181 * return_value - Not used
182 *
183 * RETURN: Status
184 *
185 * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object
186 * within the namespace.
187 *
188 * Currently, the only objects that require initialization are:
189 * 1) Methods
190 * 2) Op Regions
191 *
192 ******************************************************************************/
193
194acpi_status
195acpi_ns_init_one_object (
196 acpi_handle obj_handle,
197 u32 level,
198 void *context,
199 void **return_value)
200{
201 acpi_object_type type;
202 acpi_status status;
203 struct acpi_init_walk_info *info = (struct acpi_init_walk_info *) context;
204 struct acpi_namespace_node *node = (struct acpi_namespace_node *) obj_handle;
205 union acpi_operand_object *obj_desc;
206
207
208 ACPI_FUNCTION_NAME ("ns_init_one_object");
209
210
211 info->object_count++;
212
213 /* And even then, we are only interested in a few object types */
214
215 type = acpi_ns_get_type (obj_handle);
216 obj_desc = acpi_ns_get_attached_object (node);
217 if (!obj_desc) {
218 return (AE_OK);
219 }
220
221 /* Increment counters for object types we are looking for */
222
223 switch (type) {
224 case ACPI_TYPE_REGION:
225 info->op_region_count++;
226 break;
227
228 case ACPI_TYPE_BUFFER_FIELD:
229 info->field_count++;
230 break;
231
232 case ACPI_TYPE_BUFFER:
233 info->buffer_count++;
234 break;
235
236 case ACPI_TYPE_PACKAGE:
237 info->package_count++;
238 break;
239
240 default:
241
242 /* No init required, just exit now */
243 return (AE_OK);
244 }
245
246 /*
247 * If the object is already initialized, nothing else to do
248 */
249 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
250 return (AE_OK);
251 }
252
253 /*
254 * Must lock the interpreter before executing AML code
255 */
256 status = acpi_ex_enter_interpreter ();
257 if (ACPI_FAILURE (status)) {
258 return (status);
259 }
260
261 /*
262 * Each of these types can contain executable AML code within the
263 * declaration.
264 */
265 switch (type) {
266 case ACPI_TYPE_REGION:
267
268 info->op_region_init++;
269 status = acpi_ds_get_region_arguments (obj_desc);
270 break;
271
272 case ACPI_TYPE_BUFFER_FIELD:
273
274 info->field_init++;
275 status = acpi_ds_get_buffer_field_arguments (obj_desc);
276 break;
277
278 case ACPI_TYPE_BUFFER:
279
280 info->buffer_init++;
281 status = acpi_ds_get_buffer_arguments (obj_desc);
282 break;
283
284 case ACPI_TYPE_PACKAGE:
285
286 info->package_init++;
287 status = acpi_ds_get_package_arguments (obj_desc);
288 break;
289
290 default:
291 /* No other types can get here */
292 break;
293 }
294
295 if (ACPI_FAILURE (status)) {
296 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
297 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
298 "Could not execute arguments for [%4.4s] (%s), %s\n",
299 acpi_ut_get_node_name (node), acpi_ut_get_type_name (type),
300 acpi_format_exception (status)));
301 }
302
303 /*
304 * Print a dot for each object unless we are going to print the entire
305 * pathname
306 */
307 if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
308 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
309 }
310
311 /*
312 * We ignore errors from above, and always return OK, since we don't want
313 * to abort the walk on any single error.
314 */
315 acpi_ex_exit_interpreter ();
316 return (AE_OK);
317}
318
319
320/*******************************************************************************
321 *
322 * FUNCTION: acpi_ns_init_one_device
323 *
324 * PARAMETERS: acpi_walk_callback
325 *
326 * RETURN: acpi_status
327 *
328 * DESCRIPTION: This is called once per device soon after ACPI is enabled
329 * to initialize each device. It determines if the device is
330 * present, and if so, calls _INI.
331 *
332 ******************************************************************************/
333
334acpi_status
335acpi_ns_init_one_device (
336 acpi_handle obj_handle,
337 u32 nesting_level,
338 void *context,
339 void **return_value)
340{
341 struct acpi_device_walk_info *info = (struct acpi_device_walk_info *) context;
342 struct acpi_parameter_info pinfo;
343 u32 flags;
344 acpi_status status;
345
346
347 ACPI_FUNCTION_TRACE ("ns_init_one_device");
348
349
350 pinfo.parameters = NULL;
351 pinfo.parameter_type = ACPI_PARAM_ARGS;
352
353 pinfo.node = acpi_ns_map_handle_to_node (obj_handle);
354 if (!pinfo.node) {
355 return_ACPI_STATUS (AE_BAD_PARAMETER);
356 }
357
358 /*
359 * We will run _STA/_INI on Devices, Processors and thermal_zones only
360 */
361 if ((pinfo.node->type != ACPI_TYPE_DEVICE) &&
362 (pinfo.node->type != ACPI_TYPE_PROCESSOR) &&
363 (pinfo.node->type != ACPI_TYPE_THERMAL)) {
364 return_ACPI_STATUS (AE_OK);
365 }
366
367 if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) &&
368 (!(acpi_dbg_level & ACPI_LV_INFO))) {
369 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
370 }
371
372 info->device_count++;
373
374 /*
375 * Run _STA to determine if we can run _INI on the device.
376 */
377 ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_STA"));
378 status = acpi_ut_execute_STA (pinfo.node, &flags);
379
380 if (ACPI_FAILURE (status)) {
381 if (pinfo.node->type == ACPI_TYPE_DEVICE) {
382 /* Ignore error and move on to next device */
383
384 return_ACPI_STATUS (AE_OK);
385 }
386
387 /* _STA is not required for Processor or thermal_zone objects */
388 }
389 else {
390 info->num_STA++;
391
392 if (!(flags & 0x01)) {
393 /* Don't look at children of a not present device */
394
395 return_ACPI_STATUS(AE_CTRL_DEPTH);
396 }
397 }
398
399 /*
400 * The device is present. Run _INI.
401 */
402 ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_INI"));
403 status = acpi_ns_evaluate_relative ("_INI", &pinfo);
404 if (ACPI_FAILURE (status)) {
405 /* No _INI (AE_NOT_FOUND) means device requires no initialization */
406
407 if (status != AE_NOT_FOUND) {
408 /* Ignore error and move on to next device */
409
410#ifdef ACPI_DEBUG_OUTPUT
411 char *scope_name = acpi_ns_get_external_pathname (pinfo.node);
412
413 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n",
414 scope_name, acpi_format_exception (status)));
415
416 ACPI_MEM_FREE (scope_name);
417#endif
418 }
419
420 status = AE_OK;
421 }
422 else {
423 /* Delete any return object (especially if implicit_return is enabled) */
424
425 if (pinfo.return_object) {
426 acpi_ut_remove_reference (pinfo.return_object);
427 }
428
429 /* Count of successful INIs */
430
431 info->num_INI++;
432 }
433
434 if (acpi_gbl_init_handler) {
435 /* External initialization handler is present, call it */
436
437 status = acpi_gbl_init_handler (pinfo.node, ACPI_INIT_DEVICE_INI);
438 }
439
440 return_ACPI_STATUS (status);
441}
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
new file mode 100644
index 000000000000..1d7aedf68a77
--- /dev/null
+++ b/drivers/acpi/namespace/nsload.c
@@ -0,0 +1,460 @@
1/******************************************************************************
2 *
3 * Module Name: nsload - namespace loading/expanding/contracting procedures
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acdispat.h>
48
49
50#define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsload")
52
53
54#ifndef ACPI_NO_METHOD_EXECUTION
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_ns_load_table
59 *
60 * PARAMETERS: table_desc - Descriptor for table to be loaded
61 * Node - Owning NS node
62 *
63 * RETURN: Status
64 *
65 * DESCRIPTION: Load one ACPI table into the namespace
66 *
67 ******************************************************************************/
68
69acpi_status
70acpi_ns_load_table (
71 struct acpi_table_desc *table_desc,
72 struct acpi_namespace_node *node)
73{
74 acpi_status status;
75
76
77 ACPI_FUNCTION_TRACE ("ns_load_table");
78
79
80 /* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */
81
82 if (!(acpi_gbl_table_data[table_desc->type].flags & ACPI_TABLE_EXECUTABLE)) {
83 /* Just ignore this table */
84
85 return_ACPI_STATUS (AE_OK);
86 }
87
88 /* Check validity of the AML start and length */
89
90 if (!table_desc->aml_start) {
91 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null AML pointer\n"));
92 return_ACPI_STATUS (AE_BAD_PARAMETER);
93 }
94
95 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AML block at %p\n",
96 table_desc->aml_start));
97
98 /* Ignore table if there is no AML contained within */
99
100 if (!table_desc->aml_length) {
101 ACPI_REPORT_WARNING (("Zero-length AML block in table [%4.4s]\n",
102 table_desc->pointer->signature));
103 return_ACPI_STATUS (AE_OK);
104 }
105
106 /*
107 * Parse the table and load the namespace with all named
108 * objects found within. Control methods are NOT parsed
109 * at this time. In fact, the control methods cannot be
110 * parsed until the entire namespace is loaded, because
111 * if a control method makes a forward reference (call)
112 * to another control method, we can't continue parsing
113 * because we don't know how many arguments to parse next!
114 */
115 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
116 "**** Loading table into namespace ****\n"));
117
118 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
119 if (ACPI_FAILURE (status)) {
120 return_ACPI_STATUS (status);
121 }
122
123 status = acpi_ns_parse_table (table_desc, node->child);
124 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
125
126 if (ACPI_FAILURE (status)) {
127 return_ACPI_STATUS (status);
128 }
129
130 /*
131 * Now we can parse the control methods. We always parse
132 * them here for a sanity check, and if configured for
133 * just-in-time parsing, we delete the control method
134 * parse trees.
135 */
136 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
137 "**** Begin Table Method Parsing and Object Initialization ****\n"));
138
139 status = acpi_ds_initialize_objects (table_desc, node);
140
141 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
142 "**** Completed Table Method Parsing and Object Initialization ****\n"));
143
144 return_ACPI_STATUS (status);
145}
146
147
148/*******************************************************************************
149 *
150 * FUNCTION: acpi_ns_load_table_by_type
151 *
152 * PARAMETERS: table_type - Id of the table type to load
153 *
154 * RETURN: Status
155 *
156 * DESCRIPTION: Load an ACPI table or tables into the namespace. All tables
157 * of the given type are loaded. The mechanism allows this
158 * routine to be called repeatedly.
159 *
160 ******************************************************************************/
161
162acpi_status
163acpi_ns_load_table_by_type (
164 acpi_table_type table_type)
165{
166 u32 i;
167 acpi_status status;
168 struct acpi_table_desc *table_desc;
169
170
171 ACPI_FUNCTION_TRACE ("ns_load_table_by_type");
172
173
174 status = acpi_ut_acquire_mutex (ACPI_MTX_TABLES);
175 if (ACPI_FAILURE (status)) {
176 return_ACPI_STATUS (status);
177 }
178
179 /*
180 * Table types supported are:
181 * DSDT (one), SSDT/PSDT (multiple)
182 */
183 switch (table_type) {
184 case ACPI_TABLE_DSDT:
185
186 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading DSDT\n"));
187
188 table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next;
189
190 /* If table already loaded into namespace, just return */
191
192 if (table_desc->loaded_into_namespace) {
193 goto unlock_and_exit;
194 }
195
196 /* Now load the single DSDT */
197
198 status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
199 if (ACPI_SUCCESS (status)) {
200 table_desc->loaded_into_namespace = TRUE;
201 }
202 break;
203
204
205 case ACPI_TABLE_SSDT:
206
207 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d SSDTs\n",
208 acpi_gbl_table_lists[ACPI_TABLE_SSDT].count));
209
210 /*
211 * Traverse list of SSDT tables
212 */
213 table_desc = acpi_gbl_table_lists[ACPI_TABLE_SSDT].next;
214 for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_SSDT].count; i++) {
215 /*
216 * Only attempt to load table if it is not
217 * already loaded!
218 */
219 if (!table_desc->loaded_into_namespace) {
220 status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
221 if (ACPI_FAILURE (status)) {
222 break;
223 }
224
225 table_desc->loaded_into_namespace = TRUE;
226 }
227
228 table_desc = table_desc->next;
229 }
230 break;
231
232
233 case ACPI_TABLE_PSDT:
234
235 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d PSDTs\n",
236 acpi_gbl_table_lists[ACPI_TABLE_PSDT].count));
237
238 /*
239 * Traverse list of PSDT tables
240 */
241 table_desc = acpi_gbl_table_lists[ACPI_TABLE_PSDT].next;
242
243 for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_PSDT].count; i++) {
244 /* Only attempt to load table if it is not already loaded! */
245
246 if (!table_desc->loaded_into_namespace) {
247 status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
248 if (ACPI_FAILURE (status)) {
249 break;
250 }
251
252 table_desc->loaded_into_namespace = TRUE;
253 }
254
255 table_desc = table_desc->next;
256 }
257 break;
258
259
260 default:
261 status = AE_SUPPORT;
262 break;
263 }
264
265
266unlock_and_exit:
267 (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
268 return_ACPI_STATUS (status);
269}
270
271
272/*******************************************************************************
273 *
274 * FUNCTION: acpi_load_namespace
275 *
276 * PARAMETERS: None
277 *
278 * RETURN: Status
279 *
280 * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
281 * (DSDT points to either the BIOS or a buffer.)
282 *
283 ******************************************************************************/
284
285acpi_status
286acpi_ns_load_namespace (
287 void)
288{
289 acpi_status status;
290
291
292 ACPI_FUNCTION_TRACE ("acpi_load_name_space");
293
294
295 /* There must be at least a DSDT installed */
296
297 if (acpi_gbl_DSDT == NULL) {
298 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memory\n"));
299 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
300 }
301
302 /*
303 * Load the namespace. The DSDT is required,
304 * but the SSDT and PSDT tables are optional.
305 */
306 status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT);
307 if (ACPI_FAILURE (status)) {
308 return_ACPI_STATUS (status);
309 }
310
311 /* Ignore exceptions from these */
312
313 (void) acpi_ns_load_table_by_type (ACPI_TABLE_SSDT);
314 (void) acpi_ns_load_table_by_type (ACPI_TABLE_PSDT);
315
316 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
317 "ACPI Namespace successfully loaded at root %p\n",
318 acpi_gbl_root_node));
319
320 return_ACPI_STATUS (status);
321}
322
323
324#ifdef ACPI_FUTURE_USAGE
325
326/*******************************************************************************
327 *
328 * FUNCTION: acpi_ns_delete_subtree
329 *
330 * PARAMETERS: start_handle - Handle in namespace where search begins
331 *
332 * RETURNS Status
333 *
334 * DESCRIPTION: Walks the namespace starting at the given handle and deletes
335 * all objects, entries, and scopes in the entire subtree.
336 *
337 * Namespace/Interpreter should be locked or the subsystem should
338 * be in shutdown before this routine is called.
339 *
340 ******************************************************************************/
341
342acpi_status
343acpi_ns_delete_subtree (
344 acpi_handle start_handle)
345{
346 acpi_status status;
347 acpi_handle child_handle;
348 acpi_handle parent_handle;
349 acpi_handle next_child_handle;
350 acpi_handle dummy;
351 u32 level;
352
353
354 ACPI_FUNCTION_TRACE ("ns_delete_subtree");
355
356
357 parent_handle = start_handle;
358 child_handle = NULL;
359 level = 1;
360
361 /*
362 * Traverse the tree of objects until we bubble back up
363 * to where we started.
364 */
365 while (level > 0) {
366 /* Attempt to get the next object in this scope */
367
368 status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle,
369 child_handle, &next_child_handle);
370
371 child_handle = next_child_handle;
372
373 /* Did we get a new object? */
374
375 if (ACPI_SUCCESS (status)) {
376 /* Check if this object has any children */
377
378 if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle,
379 NULL, &dummy))) {
380 /*
381 * There is at least one child of this object,
382 * visit the object
383 */
384 level++;
385 parent_handle = child_handle;
386 child_handle = NULL;
387 }
388 }
389 else {
390 /*
391 * No more children in this object, go back up to
392 * the object's parent
393 */
394 level--;
395
396 /* Delete all children now */
397
398 acpi_ns_delete_children (child_handle);
399
400 child_handle = parent_handle;
401 status = acpi_get_parent (parent_handle, &parent_handle);
402 if (ACPI_FAILURE (status)) {
403 return_ACPI_STATUS (status);
404 }
405 }
406 }
407
408 /* Now delete the starting object, and we are done */
409
410 acpi_ns_delete_node (child_handle);
411
412 return_ACPI_STATUS (AE_OK);
413}
414
415
416/*******************************************************************************
417 *
418 * FUNCTION: acpi_ns_unload_name_space
419 *
420 * PARAMETERS: Handle - Root of namespace subtree to be deleted
421 *
422 * RETURN: Status
423 *
424 * DESCRIPTION: Shrinks the namespace, typically in response to an undocking
425 * event. Deletes an entire subtree starting from (and
426 * including) the given handle.
427 *
428 ******************************************************************************/
429
430acpi_status
431acpi_ns_unload_namespace (
432 acpi_handle handle)
433{
434 acpi_status status;
435
436
437 ACPI_FUNCTION_TRACE ("ns_unload_name_space");
438
439
440 /* Parameter validation */
441
442 if (!acpi_gbl_root_node) {
443 return_ACPI_STATUS (AE_NO_NAMESPACE);
444 }
445
446 if (!handle) {
447 return_ACPI_STATUS (AE_BAD_PARAMETER);
448 }
449
450 /* This function does the real work */
451
452 status = acpi_ns_delete_subtree (handle);
453
454 return_ACPI_STATUS (status);
455}
456
457#endif /* ACPI_FUTURE_USAGE */
458
459#endif
460
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
new file mode 100644
index 000000000000..b6f8f910eff0
--- /dev/null
+++ b/drivers/acpi/namespace/nsnames.c
@@ -0,0 +1,265 @@
1/*******************************************************************************
2 *
3 * Module Name: nsnames - Name manipulation and search
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/amlcode.h>
47#include <acpi/acnamesp.h>
48
49
50#define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsnames")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ns_build_external_path
57 *
58 * PARAMETERS: Node - NS node whose pathname is needed
59 * Size - Size of the pathname
60 * *name_buffer - Where to return the pathname
61 *
62 * RETURN: Places the pathname into the name_buffer, in external format
63 * (name segments separated by path separators)
64 *
65 * DESCRIPTION: Generate a full pathaname
66 *
67 ******************************************************************************/
68
69void
70acpi_ns_build_external_path (
71 struct acpi_namespace_node *node,
72 acpi_size size,
73 char *name_buffer)
74{
75 acpi_size index;
76 struct acpi_namespace_node *parent_node;
77
78
79 ACPI_FUNCTION_NAME ("ns_build_external_path");
80
81
82 /* Special case for root */
83
84 index = size - 1;
85 if (index < ACPI_NAME_SIZE) {
86 name_buffer[0] = AML_ROOT_PREFIX;
87 name_buffer[1] = 0;
88 return;
89 }
90
91 /* Store terminator byte, then build name backwards */
92
93 parent_node = node;
94 name_buffer[index] = 0;
95
96 while ((index > ACPI_NAME_SIZE) && (parent_node != acpi_gbl_root_node)) {
97 index -= ACPI_NAME_SIZE;
98
99 /* Put the name into the buffer */
100
101 ACPI_MOVE_32_TO_32 ((name_buffer + index), &parent_node->name);
102 parent_node = acpi_ns_get_parent_node (parent_node);
103
104 /* Prefix name with the path separator */
105
106 index--;
107 name_buffer[index] = ACPI_PATH_SEPARATOR;
108 }
109
110 /* Overwrite final separator with the root prefix character */
111
112 name_buffer[index] = AML_ROOT_PREFIX;
113
114 if (index != 0) {
115 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
116 "Could not construct pathname; index=%X, size=%X, Path=%s\n",
117 (u32) index, (u32) size, &name_buffer[size]));
118 }
119
120 return;
121}
122
123
124#ifdef ACPI_DEBUG_OUTPUT
125/*******************************************************************************
126 *
127 * FUNCTION: acpi_ns_get_external_pathname
128 *
129 * PARAMETERS: Node - NS node whose pathname is needed
130 *
131 * RETURN: Pointer to storage containing the fully qualified name of
132 * the node, In external format (name segments separated by path
133 * separators.)
134 *
135 * DESCRIPTION: Used for debug printing in acpi_ns_search_table().
136 *
137 ******************************************************************************/
138
139char *
140acpi_ns_get_external_pathname (
141 struct acpi_namespace_node *node)
142{
143 char *name_buffer;
144 acpi_size size;
145
146
147 ACPI_FUNCTION_TRACE_PTR ("ns_get_external_pathname", node);
148
149
150 /* Calculate required buffer size based on depth below root */
151
152 size = acpi_ns_get_pathname_length (node);
153
154 /* Allocate a buffer to be returned to caller */
155
156 name_buffer = ACPI_MEM_CALLOCATE (size);
157 if (!name_buffer) {
158 ACPI_REPORT_ERROR (("ns_get_table_pathname: allocation failure\n"));
159 return_PTR (NULL);
160 }
161
162 /* Build the path in the allocated buffer */
163
164 acpi_ns_build_external_path (node, size, name_buffer);
165 return_PTR (name_buffer);
166}
167#endif
168
169
170/*******************************************************************************
171 *
172 * FUNCTION: acpi_ns_get_pathname_length
173 *
174 * PARAMETERS: Node - Namespace node
175 *
176 * RETURN: Length of path, including prefix
177 *
178 * DESCRIPTION: Get the length of the pathname string for this node
179 *
180 ******************************************************************************/
181
182acpi_size
183acpi_ns_get_pathname_length (
184 struct acpi_namespace_node *node)
185{
186 acpi_size size;
187 struct acpi_namespace_node *next_node;
188
189
190 ACPI_FUNCTION_ENTRY ();
191
192
193 /*
194 * Compute length of pathname as 5 * number of name segments.
195 * Go back up the parent tree to the root
196 */
197 size = 0;
198 next_node = node;
199
200 while (next_node && (next_node != acpi_gbl_root_node)) {
201 size += ACPI_PATH_SEGMENT_LENGTH;
202 next_node = acpi_ns_get_parent_node (next_node);
203 }
204
205 if (!size) {
206 size = 1; /* Root node case */
207 }
208
209 return (size + 1); /* +1 for null string terminator */
210}
211
212
213/*******************************************************************************
214 *
215 * FUNCTION: acpi_ns_handle_to_pathname
216 *
217 * PARAMETERS: target_handle - Handle of named object whose name is
218 * to be found
219 * Buffer - Where the pathname is returned
220 *
221 * RETURN: Status, Buffer is filled with pathname if status is AE_OK
222 *
223 * DESCRIPTION: Build and return a full namespace pathname
224 *
225 ******************************************************************************/
226
227acpi_status
228acpi_ns_handle_to_pathname (
229 acpi_handle target_handle,
230 struct acpi_buffer *buffer)
231{
232 acpi_status status;
233 struct acpi_namespace_node *node;
234 acpi_size required_size;
235
236
237 ACPI_FUNCTION_TRACE_PTR ("ns_handle_to_pathname", target_handle);
238
239
240 node = acpi_ns_map_handle_to_node (target_handle);
241 if (!node) {
242 return_ACPI_STATUS (AE_BAD_PARAMETER);
243 }
244
245 /* Determine size required for the caller buffer */
246
247 required_size = acpi_ns_get_pathname_length (node);
248
249 /* Validate/Allocate/Clear caller buffer */
250
251 status = acpi_ut_initialize_buffer (buffer, required_size);
252 if (ACPI_FAILURE (status)) {
253 return_ACPI_STATUS (status);
254 }
255
256 /* Build the path in the caller buffer */
257
258 acpi_ns_build_external_path (node, required_size, buffer->pointer);
259
260 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X] \n",
261 (char *) buffer->pointer, (u32) required_size));
262 return_ACPI_STATUS (AE_OK);
263}
264
265
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
new file mode 100644
index 000000000000..4e41e66db61f
--- /dev/null
+++ b/drivers/acpi/namespace/nsobject.c
@@ -0,0 +1,461 @@
1/*******************************************************************************
2 *
3 * Module Name: nsobject - Utilities for objects attached to namespace
4 * table entries
5 *
6 ******************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acnamesp.h>
48
49
50#define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsobject")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ns_attach_object
57 *
58 * PARAMETERS: Node - Parent Node
59 * Object - Object to be attached
60 * Type - Type of object, or ACPI_TYPE_ANY if not
61 * known
62 *
63 * DESCRIPTION: Record the given object as the value associated with the
64 * name whose acpi_handle is passed. If Object is NULL
65 * and Type is ACPI_TYPE_ANY, set the name as having no value.
66 * Note: Future may require that the Node->Flags field be passed
67 * as a parameter.
68 *
69 * MUTEX: Assumes namespace is locked
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_ns_attach_object (
75 struct acpi_namespace_node *node,
76 union acpi_operand_object *object,
77 acpi_object_type type)
78{
79 union acpi_operand_object *obj_desc;
80 union acpi_operand_object *last_obj_desc;
81 acpi_object_type object_type = ACPI_TYPE_ANY;
82
83
84 ACPI_FUNCTION_TRACE ("ns_attach_object");
85
86
87 /*
88 * Parameter validation
89 */
90 if (!node) {
91 /* Invalid handle */
92
93 ACPI_REPORT_ERROR (("ns_attach_object: Null named_obj handle\n"));
94 return_ACPI_STATUS (AE_BAD_PARAMETER);
95 }
96
97 if (!object && (ACPI_TYPE_ANY != type)) {
98 /* Null object */
99
100 ACPI_REPORT_ERROR (("ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n"));
101 return_ACPI_STATUS (AE_BAD_PARAMETER);
102 }
103
104 if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
105 /* Not a name handle */
106
107 ACPI_REPORT_ERROR (("ns_attach_object: Invalid handle %p [%s]\n",
108 node, acpi_ut_get_descriptor_name (node)));
109 return_ACPI_STATUS (AE_BAD_PARAMETER);
110 }
111
112 /* Check if this object is already attached */
113
114 if (node->object == object) {
115 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj %p already installed in name_obj %p\n",
116 object, node));
117
118 return_ACPI_STATUS (AE_OK);
119 }
120
121 /* If null object, we will just install it */
122
123 if (!object) {
124 obj_desc = NULL;
125 object_type = ACPI_TYPE_ANY;
126 }
127
128 /*
129 * If the source object is a namespace Node with an attached object,
130 * we will use that (attached) object
131 */
132 else if ((ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) &&
133 ((struct acpi_namespace_node *) object)->object) {
134 /*
135 * Value passed is a name handle and that name has a
136 * non-null value. Use that name's value and type.
137 */
138 obj_desc = ((struct acpi_namespace_node *) object)->object;
139 object_type = ((struct acpi_namespace_node *) object)->type;
140 }
141
142 /*
143 * Otherwise, we will use the parameter object, but we must type
144 * it first
145 */
146 else {
147 obj_desc = (union acpi_operand_object *) object;
148
149 /* Use the given type */
150
151 object_type = type;
152 }
153
154 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
155 obj_desc, node, acpi_ut_get_node_name (node)));
156
157 /* Detach an existing attached object if present */
158
159 if (node->object) {
160 acpi_ns_detach_object (node);
161 }
162
163 if (obj_desc) {
164 /*
165 * Must increment the new value's reference count
166 * (if it is an internal object)
167 */
168 acpi_ut_add_reference (obj_desc);
169
170 /*
171 * Handle objects with multiple descriptors - walk
172 * to the end of the descriptor list
173 */
174 last_obj_desc = obj_desc;
175 while (last_obj_desc->common.next_object) {
176 last_obj_desc = last_obj_desc->common.next_object;
177 }
178
179 /* Install the object at the front of the object list */
180
181 last_obj_desc->common.next_object = node->object;
182 }
183
184 node->type = (u8) object_type;
185 node->object = obj_desc;
186
187 return_ACPI_STATUS (AE_OK);
188}
189
190
191/*******************************************************************************
192 *
193 * FUNCTION: acpi_ns_detach_object
194 *
195 * PARAMETERS: Node - An node whose object will be detached
196 *
197 * RETURN: None.
198 *
199 * DESCRIPTION: Detach/delete an object associated with a namespace node.
200 * if the object is an allocated object, it is freed.
201 * Otherwise, the field is simply cleared.
202 *
203 ******************************************************************************/
204
205void
206acpi_ns_detach_object (
207 struct acpi_namespace_node *node)
208{
209 union acpi_operand_object *obj_desc;
210
211
212 ACPI_FUNCTION_TRACE ("ns_detach_object");
213
214
215 obj_desc = node->object;
216
217 if (!obj_desc ||
218 (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA)) {
219 return_VOID;
220 }
221
222 /* Clear the entry in all cases */
223
224 node->object = NULL;
225 if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) {
226 node->object = obj_desc->common.next_object;
227 if (node->object &&
228 (ACPI_GET_OBJECT_TYPE (node->object) != ACPI_TYPE_LOCAL_DATA)) {
229 node->object = node->object->common.next_object;
230 }
231 }
232
233 /* Reset the node type to untyped */
234
235 node->type = ACPI_TYPE_ANY;
236
237 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
238 node, acpi_ut_get_node_name (node), obj_desc));
239
240 /* Remove one reference on the object (and all subobjects) */
241
242 acpi_ut_remove_reference (obj_desc);
243 return_VOID;
244}
245
246
247/*******************************************************************************
248 *
249 * FUNCTION: acpi_ns_get_attached_object
250 *
251 * PARAMETERS: Node - Parent Node to be examined
252 *
253 * RETURN: Current value of the object field from the Node whose
254 * handle is passed
255 *
256 * DESCRIPTION: Obtain the object attached to a namespace node.
257 *
258 ******************************************************************************/
259
260union acpi_operand_object *
261acpi_ns_get_attached_object (
262 struct acpi_namespace_node *node)
263{
264 ACPI_FUNCTION_TRACE_PTR ("ns_get_attached_object", node);
265
266
267 if (!node) {
268 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Null Node ptr\n"));
269 return_PTR (NULL);
270 }
271
272 if (!node->object ||
273 ((ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_OPERAND) &&
274 (ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_NAMED)) ||
275 (ACPI_GET_OBJECT_TYPE (node->object) == ACPI_TYPE_LOCAL_DATA)) {
276 return_PTR (NULL);
277 }
278
279 return_PTR (node->object);
280}
281
282
283/*******************************************************************************
284 *
285 * FUNCTION: acpi_ns_get_secondary_object
286 *
287 * PARAMETERS: Node - Parent Node to be examined
288 *
289 * RETURN: Current value of the object field from the Node whose
290 * handle is passed.
291 *
292 * DESCRIPTION: Obtain a secondary object associated with a namespace node.
293 *
294 ******************************************************************************/
295
296union acpi_operand_object *
297acpi_ns_get_secondary_object (
298 union acpi_operand_object *obj_desc)
299{
300 ACPI_FUNCTION_TRACE_PTR ("ns_get_secondary_object", obj_desc);
301
302
303 if ((!obj_desc) ||
304 (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) ||
305 (!obj_desc->common.next_object) ||
306 (ACPI_GET_OBJECT_TYPE (obj_desc->common.next_object) == ACPI_TYPE_LOCAL_DATA)) {
307 return_PTR (NULL);
308 }
309
310 return_PTR (obj_desc->common.next_object);
311}
312
313
314/*******************************************************************************
315 *
316 * FUNCTION: acpi_ns_attach_data
317 *
318 * PARAMETERS: Node - Namespace node
319 * Handler - Handler to be associated with the data
320 * Data - Data to be attached
321 *
322 * RETURN: Status
323 *
324 * DESCRIPTION: Low-level attach data. Create and attach a Data object.
325 *
326 ******************************************************************************/
327
328acpi_status
329acpi_ns_attach_data (
330 struct acpi_namespace_node *node,
331 acpi_object_handler handler,
332 void *data)
333{
334 union acpi_operand_object *prev_obj_desc;
335 union acpi_operand_object *obj_desc;
336 union acpi_operand_object *data_desc;
337
338
339 /* We only allow one attachment per handler */
340
341 prev_obj_desc = NULL;
342 obj_desc = node->object;
343 while (obj_desc) {
344 if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
345 (obj_desc->data.handler == handler)) {
346 return (AE_ALREADY_EXISTS);
347 }
348
349 prev_obj_desc = obj_desc;
350 obj_desc = obj_desc->common.next_object;
351 }
352
353 /* Create an internal object for the data */
354
355 data_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_DATA);
356 if (!data_desc) {
357 return (AE_NO_MEMORY);
358 }
359
360 data_desc->data.handler = handler;
361 data_desc->data.pointer = data;
362
363 /* Install the data object */
364
365 if (prev_obj_desc) {
366 prev_obj_desc->common.next_object = data_desc;
367 }
368 else {
369 node->object = data_desc;
370 }
371
372 return (AE_OK);
373}
374
375
376/*******************************************************************************
377 *
378 * FUNCTION: acpi_ns_detach_data
379 *
380 * PARAMETERS: Node - Namespace node
381 * Handler - Handler associated with the data
382 *
383 * RETURN: Status
384 *
385 * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
386 * is responsible for the actual data.
387 *
388 ******************************************************************************/
389
390acpi_status
391acpi_ns_detach_data (
392 struct acpi_namespace_node *node,
393 acpi_object_handler handler)
394{
395 union acpi_operand_object *obj_desc;
396 union acpi_operand_object *prev_obj_desc;
397
398
399 prev_obj_desc = NULL;
400 obj_desc = node->object;
401 while (obj_desc) {
402 if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
403 (obj_desc->data.handler == handler)) {
404 if (prev_obj_desc) {
405 prev_obj_desc->common.next_object = obj_desc->common.next_object;
406 }
407 else {
408 node->object = obj_desc->common.next_object;
409 }
410
411 acpi_ut_remove_reference (obj_desc);
412 return (AE_OK);
413 }
414
415 prev_obj_desc = obj_desc;
416 obj_desc = obj_desc->common.next_object;
417 }
418
419 return (AE_NOT_FOUND);
420}
421
422
423/*******************************************************************************
424 *
425 * FUNCTION: acpi_ns_get_attached_data
426 *
427 * PARAMETERS: Node - Namespace node
428 * Handler - Handler associated with the data
429 * Data - Where the data is returned
430 *
431 * RETURN: Status
432 *
433 * DESCRIPTION: Low level interface to obtain data previously associated with
434 * a namespace node.
435 *
436 ******************************************************************************/
437
438acpi_status
439acpi_ns_get_attached_data (
440 struct acpi_namespace_node *node,
441 acpi_object_handler handler,
442 void **data)
443{
444 union acpi_operand_object *obj_desc;
445
446
447 obj_desc = node->object;
448 while (obj_desc) {
449 if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
450 (obj_desc->data.handler == handler)) {
451 *data = obj_desc->data.pointer;
452 return (AE_OK);
453 }
454
455 obj_desc = obj_desc->common.next_object;
456 }
457
458 return (AE_NOT_FOUND);
459}
460
461
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
new file mode 100644
index 000000000000..a0e13e8d3764
--- /dev/null
+++ b/drivers/acpi/namespace/nsparse.c
@@ -0,0 +1,171 @@
1/******************************************************************************
2 *
3 * Module Name: nsparse - namespace interface to AML parser
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acparser.h>
48#include <acpi/acdispat.h>
49
50
51#define _COMPONENT ACPI_NAMESPACE
52 ACPI_MODULE_NAME ("nsparse")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION: ns_one_complete_parse
58 *
59 * PARAMETERS: pass_number - 1 or 2
60 * table_desc - The table to be parsed.
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
65 *
66 ******************************************************************************/
67
68acpi_status
69acpi_ns_one_complete_parse (
70 u32 pass_number,
71 struct acpi_table_desc *table_desc)
72{
73 union acpi_parse_object *parse_root;
74 acpi_status status;
75 struct acpi_walk_state *walk_state;
76
77
78 ACPI_FUNCTION_TRACE ("ns_one_complete_parse");
79
80
81 /* Create and init a Root Node */
82
83 parse_root = acpi_ps_create_scope_op ();
84 if (!parse_root) {
85 return_ACPI_STATUS (AE_NO_MEMORY);
86 }
87
88 /* Create and initialize a new walk state */
89
90 walk_state = acpi_ds_create_walk_state (table_desc->table_id,
91 NULL, NULL, NULL);
92 if (!walk_state) {
93 acpi_ps_free_op (parse_root);
94 return_ACPI_STATUS (AE_NO_MEMORY);
95 }
96
97 status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL,
98 table_desc->aml_start, table_desc->aml_length,
99 NULL, pass_number);
100 if (ACPI_FAILURE (status)) {
101 acpi_ds_delete_walk_state (walk_state);
102 return_ACPI_STATUS (status);
103 }
104
105 /* Parse the AML */
106
107 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "*PARSE* pass %d parse\n", pass_number));
108 status = acpi_ps_parse_aml (walk_state);
109
110 acpi_ps_delete_parse_tree (parse_root);
111 return_ACPI_STATUS (status);
112}
113
114
115/*******************************************************************************
116 *
117 * FUNCTION: acpi_ns_parse_table
118 *
119 * PARAMETERS: table_desc - An ACPI table descriptor for table to parse
120 * start_node - Where to enter the table into the namespace
121 *
122 * RETURN: Status
123 *
124 * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
125 *
126 ******************************************************************************/
127
128acpi_status
129acpi_ns_parse_table (
130 struct acpi_table_desc *table_desc,
131 struct acpi_namespace_node *start_node)
132{
133 acpi_status status;
134
135
136 ACPI_FUNCTION_TRACE ("ns_parse_table");
137
138
139 /*
140 * AML Parse, pass 1
141 *
142 * In this pass, we load most of the namespace. Control methods
143 * are not parsed until later. A parse tree is not created. Instead,
144 * each Parser Op subtree is deleted when it is finished. This saves
145 * a great deal of memory, and allows a small cache of parse objects
146 * to service the entire parse. The second pass of the parse then
147 * performs another complete parse of the AML..
148 */
149 status = acpi_ns_one_complete_parse (1, table_desc);
150 if (ACPI_FAILURE (status)) {
151 return_ACPI_STATUS (status);
152 }
153
154 /*
155 * AML Parse, pass 2
156 *
157 * In this pass, we resolve forward references and other things
158 * that could not be completed during the first pass.
159 * Another complete parse of the AML is performed, but the
160 * overhead of this is compensated for by the fact that the
161 * parse objects are all cached.
162 */
163 status = acpi_ns_one_complete_parse (2, table_desc);
164 if (ACPI_FAILURE (status)) {
165 return_ACPI_STATUS (status);
166 }
167
168 return_ACPI_STATUS (status);
169}
170
171
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
new file mode 100644
index 000000000000..0e6dea23603b
--- /dev/null
+++ b/drivers/acpi/namespace/nssearch.c
@@ -0,0 +1,381 @@
1/*******************************************************************************
2 *
3 * Module Name: nssearch - Namespace search
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47
48
49#define _COMPONENT ACPI_NAMESPACE
50 ACPI_MODULE_NAME ("nssearch")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ns_search_node
56 *
57 * PARAMETERS: *target_name - Ascii ACPI name to search for
58 * *Node - Starting node where search will begin
59 * Type - Object type to match
60 * **return_node - Where the matched Named obj is returned
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Search a single level of the namespace. Performs a
65 * simple search of the specified level, and does not add
66 * entries or search parents.
67 *
68 *
69 * Named object lists are built (and subsequently dumped) in the
70 * order in which the names are encountered during the namespace load;
71 *
72 * All namespace searching is linear in this implementation, but
73 * could be easily modified to support any improved search
74 * algorithm. However, the linear search was chosen for simplicity
75 * and because the trees are small and the other interpreter
76 * execution overhead is relatively high.
77 *
78 ******************************************************************************/
79
80acpi_status
81acpi_ns_search_node (
82 u32 target_name,
83 struct acpi_namespace_node *node,
84 acpi_object_type type,
85 struct acpi_namespace_node **return_node)
86{
87 struct acpi_namespace_node *next_node;
88
89
90 ACPI_FUNCTION_TRACE ("ns_search_node");
91
92
93#ifdef ACPI_DEBUG_OUTPUT
94 if (ACPI_LV_NAMES & acpi_dbg_level) {
95 char *scope_name;
96
97 scope_name = acpi_ns_get_external_pathname (node);
98 if (scope_name) {
99 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
100 "Searching %s (%p) For [%4.4s] (%s)\n",
101 scope_name, node, (char *) &target_name,
102 acpi_ut_get_type_name (type)));
103
104 ACPI_MEM_FREE (scope_name);
105 }
106 }
107#endif
108
109 /*
110 * Search for name at this namespace level, which is to say that we
111 * must search for the name among the children of this object
112 */
113 next_node = node->child;
114 while (next_node) {
115 /* Check for match against the name */
116
117 if (next_node->name.integer == target_name) {
118 /* Resolve a control method alias if any */
119
120 if (acpi_ns_get_type (next_node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
121 next_node = ACPI_CAST_PTR (struct acpi_namespace_node, next_node->object);
122 }
123
124 /*
125 * Found matching entry.
126 */
127 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
128 "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n",
129 (char *) &target_name, acpi_ut_get_type_name (next_node->type),
130 next_node, acpi_ut_get_node_name (node), node));
131
132 *return_node = next_node;
133 return_ACPI_STATUS (AE_OK);
134 }
135
136 /*
137 * The last entry in the list points back to the parent,
138 * so a flag is used to indicate the end-of-list
139 */
140 if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
141 /* Searched entire list, we are done */
142
143 break;
144 }
145
146 /* Didn't match name, move on to the next peer object */
147
148 next_node = next_node->peer;
149 }
150
151 /* Searched entire namespace level, not found */
152
153 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
154 "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n",
155 (char *) &target_name, acpi_ut_get_type_name (type),
156 acpi_ut_get_node_name (node), node, node->child));
157
158 return_ACPI_STATUS (AE_NOT_FOUND);
159}
160
161
162/*******************************************************************************
163 *
164 * FUNCTION: acpi_ns_search_parent_tree
165 *
166 * PARAMETERS: *target_name - Ascii ACPI name to search for
167 * *Node - Starting node where search will begin
168 * Type - Object type to match
169 * **return_node - Where the matched Node is returned
170 *
171 * RETURN: Status
172 *
173 * DESCRIPTION: Called when a name has not been found in the current namespace
174 * level. Before adding it or giving up, ACPI scope rules require
175 * searching enclosing scopes in cases identified by acpi_ns_local().
176 *
177 * "A name is located by finding the matching name in the current
178 * name space, and then in the parent name space. If the parent
179 * name space does not contain the name, the search continues
180 * recursively until either the name is found or the name space
181 * does not have a parent (the root of the name space). This
182 * indicates that the name is not found" (From ACPI Specification,
183 * section 5.3)
184 *
185 ******************************************************************************/
186
187static acpi_status
188acpi_ns_search_parent_tree (
189 u32 target_name,
190 struct acpi_namespace_node *node,
191 acpi_object_type type,
192 struct acpi_namespace_node **return_node)
193{
194 acpi_status status;
195 struct acpi_namespace_node *parent_node;
196
197
198 ACPI_FUNCTION_TRACE ("ns_search_parent_tree");
199
200
201 parent_node = acpi_ns_get_parent_node (node);
202
203 /*
204 * If there is no parent (i.e., we are at the root) or type is "local",
205 * we won't be searching the parent tree.
206 */
207 if (!parent_node) {
208 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[%4.4s] has no parent\n",
209 (char *) &target_name));
210 return_ACPI_STATUS (AE_NOT_FOUND);
211 }
212
213 if (acpi_ns_local (type)) {
214 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
215 "[%4.4s] type [%s] must be local to this scope (no parent search)\n",
216 (char *) &target_name, acpi_ut_get_type_name (type)));
217 return_ACPI_STATUS (AE_NOT_FOUND);
218 }
219
220 /* Search the parent tree */
221
222 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
223 "Searching parent [%4.4s] for [%4.4s]\n",
224 acpi_ut_get_node_name (parent_node), (char *) &target_name));
225
226 /*
227 * Search parents until target is found or we have backed up to the root
228 */
229 while (parent_node) {
230 /*
231 * Search parent scope. Use TYPE_ANY because we don't care about the
232 * object type at this point, we only care about the existence of
233 * the actual name we are searching for. Typechecking comes later.
234 */
235 status = acpi_ns_search_node (target_name, parent_node,
236 ACPI_TYPE_ANY, return_node);
237 if (ACPI_SUCCESS (status)) {
238 return_ACPI_STATUS (status);
239 }
240
241 /*
242 * Not found here, go up another level
243 * (until we reach the root)
244 */
245 parent_node = acpi_ns_get_parent_node (parent_node);
246 }
247
248 /* Not found in parent tree */
249
250 return_ACPI_STATUS (AE_NOT_FOUND);
251}
252
253
254/*******************************************************************************
255 *
256 * FUNCTION: acpi_ns_search_and_enter
257 *
258 * PARAMETERS: target_name - Ascii ACPI name to search for (4 chars)
259 * walk_state - Current state of the walk
260 * *Node - Starting node where search will begin
261 * interpreter_mode - Add names only in ACPI_MODE_LOAD_PASS_x.
262 * Otherwise,search only.
263 * Type - Object type to match
264 * Flags - Flags describing the search restrictions
265 * **return_node - Where the Node is returned
266 *
267 * RETURN: Status
268 *
269 * DESCRIPTION: Search for a name segment in a single namespace level,
270 * optionally adding it if it is not found. If the passed
271 * Type is not Any and the type previously stored in the
272 * entry was Any (i.e. unknown), update the stored type.
273 *
274 * In ACPI_IMODE_EXECUTE, search only.
275 * In other modes, search and add if not found.
276 *
277 ******************************************************************************/
278
279acpi_status
280acpi_ns_search_and_enter (
281 u32 target_name,
282 struct acpi_walk_state *walk_state,
283 struct acpi_namespace_node *node,
284 acpi_interpreter_mode interpreter_mode,
285 acpi_object_type type,
286 u32 flags,
287 struct acpi_namespace_node **return_node)
288{
289 acpi_status status;
290 struct acpi_namespace_node *new_node;
291
292
293 ACPI_FUNCTION_TRACE ("ns_search_and_enter");
294
295
296 /* Parameter validation */
297
298 if (!node || !target_name || !return_node) {
299 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
300 "Null param: Node %p Name %X return_node %p\n",
301 node, target_name, return_node));
302
303 ACPI_REPORT_ERROR (("ns_search_and_enter: Null parameter\n"));
304 return_ACPI_STATUS (AE_BAD_PARAMETER);
305 }
306
307 /* Name must consist of printable characters */
308
309 if (!acpi_ut_valid_acpi_name (target_name)) {
310 ACPI_REPORT_ERROR (("ns_search_and_enter: Bad character in ACPI Name: %X\n",
311 target_name));
312 return_ACPI_STATUS (AE_BAD_CHARACTER);
313 }
314
315 /* Try to find the name in the namespace level specified by the caller */
316
317 *return_node = ACPI_ENTRY_NOT_FOUND;
318 status = acpi_ns_search_node (target_name, node, type, return_node);
319 if (status != AE_NOT_FOUND) {
320 /*
321 * If we found it AND the request specifies that a find is an error,
322 * return the error
323 */
324 if ((status == AE_OK) &&
325 (flags & ACPI_NS_ERROR_IF_FOUND)) {
326 status = AE_ALREADY_EXISTS;
327 }
328
329 /*
330 * Either found it or there was an error
331 * -- finished either way
332 */
333 return_ACPI_STATUS (status);
334 }
335
336 /*
337 * The name was not found. If we are NOT performing the first pass
338 * (name entry) of loading the namespace, search the parent tree (all the
339 * way to the root if necessary.) We don't want to perform the parent
340 * search when the namespace is actually being loaded. We want to perform
341 * the search when namespace references are being resolved (load pass 2)
342 * and during the execution phase.
343 */
344 if ((interpreter_mode != ACPI_IMODE_LOAD_PASS1) &&
345 (flags & ACPI_NS_SEARCH_PARENT)) {
346 /*
347 * Not found at this level - search parent tree according to the
348 * ACPI specification
349 */
350 status = acpi_ns_search_parent_tree (target_name, node, type, return_node);
351 if (ACPI_SUCCESS (status)) {
352 return_ACPI_STATUS (status);
353 }
354 }
355
356 /*
357 * In execute mode, just search, never add names. Exit now.
358 */
359 if (interpreter_mode == ACPI_IMODE_EXECUTE) {
360 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
361 "%4.4s Not found in %p [Not adding]\n",
362 (char *) &target_name, node));
363
364 return_ACPI_STATUS (AE_NOT_FOUND);
365 }
366
367 /* Create the new named object */
368
369 new_node = acpi_ns_create_node (target_name);
370 if (!new_node) {
371 return_ACPI_STATUS (AE_NO_MEMORY);
372 }
373
374 /* Install the new object into the parent's list of children */
375
376 acpi_ns_install_node (walk_state, node, new_node, type);
377 *return_node = new_node;
378
379 return_ACPI_STATUS (AE_OK);
380}
381
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
new file mode 100644
index 000000000000..75da76cc0b19
--- /dev/null
+++ b/drivers/acpi/namespace/nsutils.c
@@ -0,0 +1,1069 @@
1/******************************************************************************
2 *
3 * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
4 * parents and siblings and Scope manipulation
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acnamesp.h>
48#include <acpi/amlcode.h>
49#include <acpi/actables.h>
50
51#define _COMPONENT ACPI_NAMESPACE
52 ACPI_MODULE_NAME ("nsutils")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION: acpi_ns_report_error
58 *
59 * PARAMETERS: module_name - Caller's module name (for error output)
60 * line_number - Caller's line number (for error output)
61 * component_id - Caller's component ID (for error output)
62 * Message - Error message to use on failure
63 *
64 * RETURN: None
65 *
66 * DESCRIPTION: Print warning message with full pathname
67 *
68 ******************************************************************************/
69
70void
71acpi_ns_report_error (
72 char *module_name,
73 u32 line_number,
74 u32 component_id,
75 char *internal_name,
76 acpi_status lookup_status)
77{
78 acpi_status status;
79 char *name = NULL;
80
81
82 acpi_os_printf ("%8s-%04d: *** Error: Looking up ",
83 module_name, line_number);
84
85 if (lookup_status == AE_BAD_CHARACTER) {
86 /* There is a non-ascii character in the name */
87
88 acpi_os_printf ("[0x%4.4X] (NON-ASCII)\n",
89 *(ACPI_CAST_PTR (u32, internal_name)));
90 }
91 else {
92 /* Convert path to external format */
93
94 status = acpi_ns_externalize_name (ACPI_UINT32_MAX,
95 internal_name, NULL, &name);
96
97 /* Print target name */
98
99 if (ACPI_SUCCESS (status)) {
100 acpi_os_printf ("[%s]", name);
101 }
102 else {
103 acpi_os_printf ("[COULD NOT EXTERNALIZE NAME]");
104 }
105
106 if (name) {
107 ACPI_MEM_FREE (name);
108 }
109 }
110
111 acpi_os_printf (" in namespace, %s\n",
112 acpi_format_exception (lookup_status));
113}
114
115
116/*******************************************************************************
117 *
118 * FUNCTION: acpi_ns_report_method_error
119 *
120 * PARAMETERS: module_name - Caller's module name (for error output)
121 * line_number - Caller's line number (for error output)
122 * component_id - Caller's component ID (for error output)
123 * Message - Error message to use on failure
124 *
125 * RETURN: None
126 *
127 * DESCRIPTION: Print warning message with full pathname
128 *
129 ******************************************************************************/
130
131void
132acpi_ns_report_method_error (
133 char *module_name,
134 u32 line_number,
135 u32 component_id,
136 char *message,
137 struct acpi_namespace_node *prefix_node,
138 char *path,
139 acpi_status method_status)
140{
141 acpi_status status;
142 struct acpi_namespace_node *node = prefix_node;
143
144
145 if (path) {
146 status = acpi_ns_get_node_by_path (path, prefix_node,
147 ACPI_NS_NO_UPSEARCH, &node);
148 if (ACPI_FAILURE (status)) {
149 acpi_os_printf ("report_method_error: Could not get node\n");
150 return;
151 }
152 }
153
154 acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number);
155 acpi_ns_print_node_pathname (node, message);
156 acpi_os_printf (", %s\n", acpi_format_exception (method_status));
157}
158
159
160/*******************************************************************************
161 *
162 * FUNCTION: acpi_ns_print_node_pathname
163 *
164 * PARAMETERS: Node - Object
165 * Msg - Prefix message
166 *
167 * DESCRIPTION: Print an object's full namespace pathname
168 * Manages allocation/freeing of a pathname buffer
169 *
170 ******************************************************************************/
171
172void
173acpi_ns_print_node_pathname (
174 struct acpi_namespace_node *node,
175 char *msg)
176{
177 struct acpi_buffer buffer;
178 acpi_status status;
179
180
181 if (!node) {
182 acpi_os_printf ("[NULL NAME]");
183 return;
184 }
185
186 /* Convert handle to full pathname and print it (with supplied message) */
187
188 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
189
190 status = acpi_ns_handle_to_pathname (node, &buffer);
191 if (ACPI_SUCCESS (status)) {
192 if (msg) {
193 acpi_os_printf ("%s ", msg);
194 }
195
196 acpi_os_printf ("[%s] (Node %p)", (char *) buffer.pointer, node);
197 ACPI_MEM_FREE (buffer.pointer);
198 }
199}
200
201
202/*******************************************************************************
203 *
204 * FUNCTION: acpi_ns_valid_root_prefix
205 *
206 * PARAMETERS: Prefix - Character to be checked
207 *
208 * RETURN: TRUE if a valid prefix
209 *
210 * DESCRIPTION: Check if a character is a valid ACPI Root prefix
211 *
212 ******************************************************************************/
213
214u8
215acpi_ns_valid_root_prefix (
216 char prefix)
217{
218
219 return ((u8) (prefix == '\\'));
220}
221
222
223/*******************************************************************************
224 *
225 * FUNCTION: acpi_ns_valid_path_separator
226 *
227 * PARAMETERS: Sep - Character to be checked
228 *
229 * RETURN: TRUE if a valid path separator
230 *
231 * DESCRIPTION: Check if a character is a valid ACPI path separator
232 *
233 ******************************************************************************/
234
235u8
236acpi_ns_valid_path_separator (
237 char sep)
238{
239
240 return ((u8) (sep == '.'));
241}
242
243
244/*******************************************************************************
245 *
246 * FUNCTION: acpi_ns_get_type
247 *
248 * PARAMETERS: Handle - Parent Node to be examined
249 *
250 * RETURN: Type field from Node whose handle is passed
251 *
252 ******************************************************************************/
253
254acpi_object_type
255acpi_ns_get_type (
256 struct acpi_namespace_node *node)
257{
258 ACPI_FUNCTION_TRACE ("ns_get_type");
259
260
261 if (!node) {
262 ACPI_REPORT_WARNING (("ns_get_type: Null Node input pointer\n"));
263 return_VALUE (ACPI_TYPE_ANY);
264 }
265
266 return_VALUE ((acpi_object_type) node->type);
267}
268
269
270/*******************************************************************************
271 *
272 * FUNCTION: acpi_ns_local
273 *
274 * PARAMETERS: Type - A namespace object type
275 *
276 * RETURN: LOCAL if names must be found locally in objects of the
277 * passed type, 0 if enclosing scopes should be searched
278 *
279 ******************************************************************************/
280
281u32
282acpi_ns_local (
283 acpi_object_type type)
284{
285 ACPI_FUNCTION_TRACE ("ns_local");
286
287
288 if (!acpi_ut_valid_object_type (type)) {
289 /* Type code out of range */
290
291 ACPI_REPORT_WARNING (("ns_local: Invalid Object Type\n"));
292 return_VALUE (ACPI_NS_NORMAL);
293 }
294
295 return_VALUE ((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
296}
297
298
299/*******************************************************************************
300 *
301 * FUNCTION: acpi_ns_get_internal_name_length
302 *
303 * PARAMETERS: Info - Info struct initialized with the
304 * external name pointer.
305 *
306 * RETURN: Status
307 *
308 * DESCRIPTION: Calculate the length of the internal (AML) namestring
309 * corresponding to the external (ASL) namestring.
310 *
311 ******************************************************************************/
312
313void
314acpi_ns_get_internal_name_length (
315 struct acpi_namestring_info *info)
316{
317 char *next_external_char;
318 u32 i;
319
320
321 ACPI_FUNCTION_ENTRY ();
322
323
324 next_external_char = info->external_name;
325 info->num_carats = 0;
326 info->num_segments = 0;
327 info->fully_qualified = FALSE;
328
329 /*
330 * For the internal name, the required length is 4 bytes per segment, plus
331 * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null
332 * (which is not really needed, but no there's harm in putting it there)
333 *
334 * strlen() + 1 covers the first name_seg, which has no path separator
335 */
336 if (acpi_ns_valid_root_prefix (next_external_char[0])) {
337 info->fully_qualified = TRUE;
338 next_external_char++;
339 }
340 else {
341 /*
342 * Handle Carat prefixes
343 */
344 while (*next_external_char == '^') {
345 info->num_carats++;
346 next_external_char++;
347 }
348 }
349
350 /*
351 * Determine the number of ACPI name "segments" by counting the number of
352 * path separators within the string. Start with one segment since the
353 * segment count is [(# separators) + 1], and zero separators is ok.
354 */
355 if (*next_external_char) {
356 info->num_segments = 1;
357 for (i = 0; next_external_char[i]; i++) {
358 if (acpi_ns_valid_path_separator (next_external_char[i])) {
359 info->num_segments++;
360 }
361 }
362 }
363
364 info->length = (ACPI_NAME_SIZE * info->num_segments) +
365 4 + info->num_carats;
366
367 info->next_external_char = next_external_char;
368}
369
370
371/*******************************************************************************
372 *
373 * FUNCTION: acpi_ns_build_internal_name
374 *
375 * PARAMETERS: Info - Info struct fully initialized
376 *
377 * RETURN: Status
378 *
379 * DESCRIPTION: Construct the internal (AML) namestring
380 * corresponding to the external (ASL) namestring.
381 *
382 ******************************************************************************/
383
384acpi_status
385acpi_ns_build_internal_name (
386 struct acpi_namestring_info *info)
387{
388 u32 num_segments = info->num_segments;
389 char *internal_name = info->internal_name;
390 char *external_name = info->next_external_char;
391 char *result = NULL;
392 acpi_native_uint i;
393
394
395 ACPI_FUNCTION_TRACE ("ns_build_internal_name");
396
397
398 /* Setup the correct prefixes, counts, and pointers */
399
400 if (info->fully_qualified) {
401 internal_name[0] = '\\';
402
403 if (num_segments <= 1) {
404 result = &internal_name[1];
405 }
406 else if (num_segments == 2) {
407 internal_name[1] = AML_DUAL_NAME_PREFIX;
408 result = &internal_name[2];
409 }
410 else {
411 internal_name[1] = AML_MULTI_NAME_PREFIX_OP;
412 internal_name[2] = (char) num_segments;
413 result = &internal_name[3];
414 }
415 }
416 else {
417 /*
418 * Not fully qualified.
419 * Handle Carats first, then append the name segments
420 */
421 i = 0;
422 if (info->num_carats) {
423 for (i = 0; i < info->num_carats; i++) {
424 internal_name[i] = '^';
425 }
426 }
427
428 if (num_segments <= 1) {
429 result = &internal_name[i];
430 }
431 else if (num_segments == 2) {
432 internal_name[i] = AML_DUAL_NAME_PREFIX;
433 result = &internal_name[(acpi_native_uint) (i+1)];
434 }
435 else {
436 internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
437 internal_name[(acpi_native_uint) (i+1)] = (char) num_segments;
438 result = &internal_name[(acpi_native_uint) (i+2)];
439 }
440 }
441
442 /* Build the name (minus path separators) */
443
444 for (; num_segments; num_segments--) {
445 for (i = 0; i < ACPI_NAME_SIZE; i++) {
446 if (acpi_ns_valid_path_separator (*external_name) ||
447 (*external_name == 0)) {
448 /* Pad the segment with underscore(s) if segment is short */
449
450 result[i] = '_';
451 }
452 else {
453 /* Convert the character to uppercase and save it */
454
455 result[i] = (char) ACPI_TOUPPER ((int) *external_name);
456 external_name++;
457 }
458 }
459
460 /* Now we must have a path separator, or the pathname is bad */
461
462 if (!acpi_ns_valid_path_separator (*external_name) &&
463 (*external_name != 0)) {
464 return_ACPI_STATUS (AE_BAD_PARAMETER);
465 }
466
467 /* Move on the next segment */
468
469 external_name++;
470 result += ACPI_NAME_SIZE;
471 }
472
473 /* Terminate the string */
474
475 *result = 0;
476
477 if (info->fully_qualified) {
478 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
479 internal_name, internal_name));
480 }
481 else {
482 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
483 internal_name, internal_name));
484 }
485
486 return_ACPI_STATUS (AE_OK);
487}
488
489
490/*******************************************************************************
491 *
492 * FUNCTION: acpi_ns_internalize_name
493 *
494 * PARAMETERS: *external_name - External representation of name
495 * **Converted Name - Where to return the resulting
496 * internal represention of the name
497 *
498 * RETURN: Status
499 *
500 * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
501 * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
502 *
503 *******************************************************************************/
504
505acpi_status
506acpi_ns_internalize_name (
507 char *external_name,
508 char **converted_name)
509{
510 char *internal_name;
511 struct acpi_namestring_info info;
512 acpi_status status;
513
514
515 ACPI_FUNCTION_TRACE ("ns_internalize_name");
516
517
518 if ((!external_name) ||
519 (*external_name == 0) ||
520 (!converted_name)) {
521 return_ACPI_STATUS (AE_BAD_PARAMETER);
522 }
523
524 /* Get the length of the new internal name */
525
526 info.external_name = external_name;
527 acpi_ns_get_internal_name_length (&info);
528
529 /* We need a segment to store the internal name */
530
531 internal_name = ACPI_MEM_CALLOCATE (info.length);
532 if (!internal_name) {
533 return_ACPI_STATUS (AE_NO_MEMORY);
534 }
535
536 /* Build the name */
537
538 info.internal_name = internal_name;
539 status = acpi_ns_build_internal_name (&info);
540 if (ACPI_FAILURE (status)) {
541 ACPI_MEM_FREE (internal_name);
542 return_ACPI_STATUS (status);
543 }
544
545 *converted_name = internal_name;
546 return_ACPI_STATUS (AE_OK);
547}
548
549
550/*******************************************************************************
551 *
552 * FUNCTION: acpi_ns_externalize_name
553 *
554 * PARAMETERS: *internal_name - Internal representation of name
555 * **converted_name - Where to return the resulting
556 * external representation of name
557 *
558 * RETURN: Status
559 *
560 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
561 * to its external form (e.g. "\_PR_.CPU0")
562 *
563 ******************************************************************************/
564
565acpi_status
566acpi_ns_externalize_name (
567 u32 internal_name_length,
568 char *internal_name,
569 u32 *converted_name_length,
570 char **converted_name)
571{
572 acpi_native_uint names_index = 0;
573 acpi_native_uint num_segments = 0;
574 acpi_native_uint required_length;
575 acpi_native_uint prefix_length = 0;
576 acpi_native_uint i = 0;
577 acpi_native_uint j = 0;
578
579
580 ACPI_FUNCTION_TRACE ("ns_externalize_name");
581
582
583 if (!internal_name_length ||
584 !internal_name ||
585 !converted_name) {
586 return_ACPI_STATUS (AE_BAD_PARAMETER);
587 }
588
589 /*
590 * Check for a prefix (one '\' | one or more '^').
591 */
592 switch (internal_name[0]) {
593 case '\\':
594 prefix_length = 1;
595 break;
596
597 case '^':
598 for (i = 0; i < internal_name_length; i++) {
599 if (internal_name[i] == '^') {
600 prefix_length = i + 1;
601 }
602 else {
603 break;
604 }
605 }
606
607 if (i == internal_name_length) {
608 prefix_length = i;
609 }
610
611 break;
612
613 default:
614 break;
615 }
616
617 /*
618 * Check for object names. Note that there could be 0-255 of these
619 * 4-byte elements.
620 */
621 if (prefix_length < internal_name_length) {
622 switch (internal_name[prefix_length]) {
623 case AML_MULTI_NAME_PREFIX_OP:
624
625 /* <count> 4-byte names */
626
627 names_index = prefix_length + 2;
628 num_segments = (acpi_native_uint) (u8)
629 internal_name[(acpi_native_uint) (prefix_length + 1)];
630 break;
631
632 case AML_DUAL_NAME_PREFIX:
633
634 /* Two 4-byte names */
635
636 names_index = prefix_length + 1;
637 num_segments = 2;
638 break;
639
640 case 0:
641
642 /* null_name */
643
644 names_index = 0;
645 num_segments = 0;
646 break;
647
648 default:
649
650 /* one 4-byte name */
651
652 names_index = prefix_length;
653 num_segments = 1;
654 break;
655 }
656 }
657
658 /*
659 * Calculate the length of converted_name, which equals the length
660 * of the prefix, length of all object names, length of any required
661 * punctuation ('.') between object names, plus the NULL terminator.
662 */
663 required_length = prefix_length + (4 * num_segments) +
664 ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
665
666 /*
667 * Check to see if we're still in bounds. If not, there's a problem
668 * with internal_name (invalid format).
669 */
670 if (required_length > internal_name_length) {
671 ACPI_REPORT_ERROR (("ns_externalize_name: Invalid internal name\n"));
672 return_ACPI_STATUS (AE_BAD_PATHNAME);
673 }
674
675 /*
676 * Build converted_name
677 */
678 *converted_name = ACPI_MEM_CALLOCATE (required_length);
679 if (!(*converted_name)) {
680 return_ACPI_STATUS (AE_NO_MEMORY);
681 }
682
683 j = 0;
684
685 for (i = 0; i < prefix_length; i++) {
686 (*converted_name)[j++] = internal_name[i];
687 }
688
689 if (num_segments > 0) {
690 for (i = 0; i < num_segments; i++) {
691 if (i > 0) {
692 (*converted_name)[j++] = '.';
693 }
694
695 (*converted_name)[j++] = internal_name[names_index++];
696 (*converted_name)[j++] = internal_name[names_index++];
697 (*converted_name)[j++] = internal_name[names_index++];
698 (*converted_name)[j++] = internal_name[names_index++];
699 }
700 }
701
702 if (converted_name_length) {
703 *converted_name_length = (u32) required_length;
704 }
705
706 return_ACPI_STATUS (AE_OK);
707}
708
709
710/*******************************************************************************
711 *
712 * FUNCTION: acpi_ns_map_handle_to_node
713 *
714 * PARAMETERS: Handle - Handle to be converted to an Node
715 *
716 * RETURN: A Name table entry pointer
717 *
718 * DESCRIPTION: Convert a namespace handle to a real Node
719 *
720 * Note: Real integer handles allow for more verification
721 * and keep all pointers within this subsystem.
722 *
723 ******************************************************************************/
724
725struct acpi_namespace_node *
726acpi_ns_map_handle_to_node (
727 acpi_handle handle)
728{
729
730 ACPI_FUNCTION_ENTRY ();
731
732
733 /*
734 * Simple implementation.
735 */
736 if (!handle) {
737 return (NULL);
738 }
739
740 if (handle == ACPI_ROOT_OBJECT) {
741 return (acpi_gbl_root_node);
742 }
743
744 /* We can at least attempt to verify the handle */
745
746 if (ACPI_GET_DESCRIPTOR_TYPE (handle) != ACPI_DESC_TYPE_NAMED) {
747 return (NULL);
748 }
749
750 return ((struct acpi_namespace_node *) handle);
751}
752
753
754/*******************************************************************************
755 *
756 * FUNCTION: acpi_ns_convert_entry_to_handle
757 *
758 * PARAMETERS: Node - Node to be converted to a Handle
759 *
760 * RETURN: A user handle
761 *
762 * DESCRIPTION: Convert a real Node to a namespace handle
763 *
764 ******************************************************************************/
765
766acpi_handle
767acpi_ns_convert_entry_to_handle (
768 struct acpi_namespace_node *node)
769{
770
771
772 /*
773 * Simple implementation for now;
774 */
775 return ((acpi_handle) node);
776
777
778/* ---------------------------------------------------
779
780 if (!Node)
781 {
782 return (NULL);
783 }
784
785 if (Node == acpi_gbl_root_node)
786 {
787 return (ACPI_ROOT_OBJECT);
788 }
789
790
791 return ((acpi_handle) Node);
792------------------------------------------------------*/
793}
794
795
796/*******************************************************************************
797 *
798 * FUNCTION: acpi_ns_terminate
799 *
800 * PARAMETERS: none
801 *
802 * RETURN: none
803 *
804 * DESCRIPTION: free memory allocated for table storage.
805 *
806 ******************************************************************************/
807
808void
809acpi_ns_terminate (void)
810{
811 union acpi_operand_object *obj_desc;
812
813
814 ACPI_FUNCTION_TRACE ("ns_terminate");
815
816
817 /*
818 * 1) Free the entire namespace -- all nodes and objects
819 *
820 * Delete all object descriptors attached to namepsace nodes
821 */
822 acpi_ns_delete_namespace_subtree (acpi_gbl_root_node);
823
824 /* Detach any objects attached to the root */
825
826 obj_desc = acpi_ns_get_attached_object (acpi_gbl_root_node);
827 if (obj_desc) {
828 acpi_ns_detach_object (acpi_gbl_root_node);
829 }
830
831 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
832
833 /*
834 * 2) Now we can delete the ACPI tables
835 */
836 acpi_tb_delete_all_tables ();
837 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
838
839 return_VOID;
840}
841
842
843/*******************************************************************************
844 *
845 * FUNCTION: acpi_ns_opens_scope
846 *
847 * PARAMETERS: Type - A valid namespace type
848 *
849 * RETURN: NEWSCOPE if the passed type "opens a name scope" according
850 * to the ACPI specification, else 0
851 *
852 ******************************************************************************/
853
854u32
855acpi_ns_opens_scope (
856 acpi_object_type type)
857{
858 ACPI_FUNCTION_TRACE_STR ("ns_opens_scope", acpi_ut_get_type_name (type));
859
860
861 if (!acpi_ut_valid_object_type (type)) {
862 /* type code out of range */
863
864 ACPI_REPORT_WARNING (("ns_opens_scope: Invalid Object Type %X\n", type));
865 return_VALUE (ACPI_NS_NORMAL);
866 }
867
868 return_VALUE (((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
869}
870
871
872/*******************************************************************************
873 *
874 * FUNCTION: acpi_ns_get_node_by_path
875 *
876 * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The
877 * \ (backslash) and ^ (carat) prefixes, and the
878 * . (period) to separate segments are supported.
879 * start_node - Root of subtree to be searched, or NS_ALL for the
880 * root of the name space. If Name is fully
881 * qualified (first s8 is '\'), the passed value
882 * of Scope will not be accessed.
883 * Flags - Used to indicate whether to perform upsearch or
884 * not.
885 * return_node - Where the Node is returned
886 *
887 * DESCRIPTION: Look up a name relative to a given scope and return the
888 * corresponding Node. NOTE: Scope can be null.
889 *
890 * MUTEX: Locks namespace
891 *
892 ******************************************************************************/
893
894acpi_status
895acpi_ns_get_node_by_path (
896 char *pathname,
897 struct acpi_namespace_node *start_node,
898 u32 flags,
899 struct acpi_namespace_node **return_node)
900{
901 union acpi_generic_state scope_info;
902 acpi_status status;
903 char *internal_path = NULL;
904
905
906 ACPI_FUNCTION_TRACE_PTR ("ns_get_node_by_path", pathname);
907
908
909 if (pathname) {
910 /* Convert path to internal representation */
911
912 status = acpi_ns_internalize_name (pathname, &internal_path);
913 if (ACPI_FAILURE (status)) {
914 return_ACPI_STATUS (status);
915 }
916 }
917
918 /* Must lock namespace during lookup */
919
920 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
921 if (ACPI_FAILURE (status)) {
922 goto cleanup;
923 }
924
925 /* Setup lookup scope (search starting point) */
926
927 scope_info.scope.node = start_node;
928
929 /* Lookup the name in the namespace */
930
931 status = acpi_ns_lookup (&scope_info, internal_path,
932 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
933 (flags | ACPI_NS_DONT_OPEN_SCOPE),
934 NULL, return_node);
935 if (ACPI_FAILURE (status)) {
936 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s, %s\n",
937 internal_path, acpi_format_exception (status)));
938 }
939
940 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
941
942cleanup:
943 /* Cleanup */
944 if (internal_path) {
945 ACPI_MEM_FREE (internal_path);
946 }
947 return_ACPI_STATUS (status);
948}
949
950
951/*******************************************************************************
952 *
953 * FUNCTION: acpi_ns_find_parent_name
954 *
955 * PARAMETERS: *child_node - Named Obj whose name is to be found
956 *
957 * RETURN: The ACPI name
958 *
959 * DESCRIPTION: Search for the given obj in its parent scope and return the
960 * name segment, or "????" if the parent name can't be found
961 * (which "should not happen").
962 *
963 ******************************************************************************/
964#ifdef ACPI_FUTURE_USAGE
965acpi_name
966acpi_ns_find_parent_name (
967 struct acpi_namespace_node *child_node)
968{
969 struct acpi_namespace_node *parent_node;
970
971
972 ACPI_FUNCTION_TRACE ("ns_find_parent_name");
973
974
975 if (child_node) {
976 /* Valid entry. Get the parent Node */
977
978 parent_node = acpi_ns_get_parent_node (child_node);
979 if (parent_node) {
980 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
981 "Parent of %p [%4.4s] is %p [%4.4s]\n",
982 child_node, acpi_ut_get_node_name (child_node),
983 parent_node, acpi_ut_get_node_name (parent_node)));
984
985 if (parent_node->name.integer) {
986 return_VALUE ((acpi_name) parent_node->name.integer);
987 }
988 }
989
990 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
991 "Unable to find parent of %p (%4.4s)\n",
992 child_node, acpi_ut_get_node_name (child_node)));
993 }
994
995 return_VALUE (ACPI_UNKNOWN_NAME);
996}
997#endif
998
999
1000/*******************************************************************************
1001 *
1002 * FUNCTION: acpi_ns_get_parent_node
1003 *
1004 * PARAMETERS: Node - Current table entry
1005 *
1006 * RETURN: Parent entry of the given entry
1007 *
1008 * DESCRIPTION: Obtain the parent entry for a given entry in the namespace.
1009 *
1010 ******************************************************************************/
1011
1012
1013struct acpi_namespace_node *
1014acpi_ns_get_parent_node (
1015 struct acpi_namespace_node *node)
1016{
1017 ACPI_FUNCTION_ENTRY ();
1018
1019
1020 if (!node) {
1021 return (NULL);
1022 }
1023
1024 /*
1025 * Walk to the end of this peer list. The last entry is marked with a flag
1026 * and the peer pointer is really a pointer back to the parent. This saves
1027 * putting a parent back pointer in each and every named object!
1028 */
1029 while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) {
1030 node = node->peer;
1031 }
1032
1033
1034 return (node->peer);
1035}
1036
1037
1038/*******************************************************************************
1039 *
1040 * FUNCTION: acpi_ns_get_next_valid_node
1041 *
1042 * PARAMETERS: Node - Current table entry
1043 *
1044 * RETURN: Next valid Node in the linked node list. NULL if no more valid
1045 * nodes.
1046 *
1047 * DESCRIPTION: Find the next valid node within a name table.
1048 * Useful for implementing NULL-end-of-list loops.
1049 *
1050 ******************************************************************************/
1051
1052
1053struct acpi_namespace_node *
1054acpi_ns_get_next_valid_node (
1055 struct acpi_namespace_node *node)
1056{
1057
1058 /* If we are at the end of this peer list, return NULL */
1059
1060 if (node->flags & ANOBJ_END_OF_PEER_LIST) {
1061 return NULL;
1062 }
1063
1064 /* Otherwise just return the next peer */
1065
1066 return (node->peer);
1067}
1068
1069
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
new file mode 100644
index 000000000000..4de2444df300
--- /dev/null
+++ b/drivers/acpi/namespace/nswalk.c
@@ -0,0 +1,289 @@
1/******************************************************************************
2 *
3 * Module Name: nswalk - Functions for walking the ACPI namespace
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47
48
49#define _COMPONENT ACPI_NAMESPACE
50 ACPI_MODULE_NAME ("nswalk")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ns_get_next_node
56 *
57 * PARAMETERS: Type - Type of node to be searched for
58 * parent_node - Parent node whose children we are
59 * getting
60 * child_node - Previous child that was found.
61 * The NEXT child will be returned
62 *
63 * RETURN: struct acpi_namespace_node - Pointer to the NEXT child or NULL if
64 * none is found.
65 *
66 * DESCRIPTION: Return the next peer node within the namespace. If Handle
67 * is valid, Scope is ignored. Otherwise, the first node
68 * within Scope is returned.
69 *
70 ******************************************************************************/
71
72struct acpi_namespace_node *
73acpi_ns_get_next_node (
74 acpi_object_type type,
75 struct acpi_namespace_node *parent_node,
76 struct acpi_namespace_node *child_node)
77{
78 struct acpi_namespace_node *next_node = NULL;
79
80
81 ACPI_FUNCTION_ENTRY ();
82
83
84 if (!child_node) {
85 /* It's really the parent's _scope_ that we want */
86
87 if (parent_node->child) {
88 next_node = parent_node->child;
89 }
90 }
91
92 else {
93 /* Start search at the NEXT node */
94
95 next_node = acpi_ns_get_next_valid_node (child_node);
96 }
97
98 /* If any type is OK, we are done */
99
100 if (type == ACPI_TYPE_ANY) {
101 /* next_node is NULL if we are at the end-of-list */
102
103 return (next_node);
104 }
105
106 /* Must search for the node -- but within this scope only */
107
108 while (next_node) {
109 /* If type matches, we are done */
110
111 if (next_node->type == type) {
112 return (next_node);
113 }
114
115 /* Otherwise, move on to the next node */
116
117 next_node = acpi_ns_get_next_valid_node (next_node);
118 }
119
120 /* Not found */
121
122 return (NULL);
123}
124
125
126/*******************************************************************************
127 *
128 * FUNCTION: acpi_ns_walk_namespace
129 *
130 * PARAMETERS: Type - acpi_object_type to search for
131 * start_node - Handle in namespace where search begins
132 * max_depth - Depth to which search is to reach
133 * unlock_before_callback- Whether to unlock the NS before invoking
134 * the callback routine
135 * user_function - Called when an object of "Type" is found
136 * Context - Passed to user function
137 * return_value - from the user_function if terminated early.
138 * Otherwise, returns NULL.
139 * RETURNS: Status
140 *
141 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
142 * starting (and ending) at the node specified by start_handle.
143 * The user_function is called whenever a node that matches
144 * the type parameter is found. If the user function returns
145 * a non-zero value, the search is terminated immediately and this
146 * value is returned to the caller.
147 *
148 * The point of this procedure is to provide a generic namespace
149 * walk routine that can be called from multiple places to
150 * provide multiple services; the User Function can be tailored
151 * to each task, whether it is a print function, a compare
152 * function, etc.
153 *
154 ******************************************************************************/
155
156acpi_status
157acpi_ns_walk_namespace (
158 acpi_object_type type,
159 acpi_handle start_node,
160 u32 max_depth,
161 u8 unlock_before_callback,
162 acpi_walk_callback user_function,
163 void *context,
164 void **return_value)
165{
166 acpi_status status;
167 acpi_status mutex_status;
168 struct acpi_namespace_node *child_node;
169 struct acpi_namespace_node *parent_node;
170 acpi_object_type child_type;
171 u32 level;
172
173
174 ACPI_FUNCTION_TRACE ("ns_walk_namespace");
175
176
177 /* Special case for the namespace Root Node */
178
179 if (start_node == ACPI_ROOT_OBJECT) {
180 start_node = acpi_gbl_root_node;
181 }
182
183 /* Null child means "get first node" */
184
185 parent_node = start_node;
186 child_node = NULL;
187 child_type = ACPI_TYPE_ANY;
188 level = 1;
189
190 /*
191 * Traverse the tree of nodes until we bubble back up to where we
192 * started. When Level is zero, the loop is done because we have
193 * bubbled up to (and passed) the original parent handle (start_entry)
194 */
195 while (level > 0) {
196 /* Get the next node in this scope. Null if not found */
197
198 status = AE_OK;
199 child_node = acpi_ns_get_next_node (ACPI_TYPE_ANY, parent_node, child_node);
200 if (child_node) {
201 /*
202 * Found node, Get the type if we are not
203 * searching for ANY
204 */
205 if (type != ACPI_TYPE_ANY) {
206 child_type = child_node->type;
207 }
208
209 if (child_type == type) {
210 /*
211 * Found a matching node, invoke the user
212 * callback function
213 */
214 if (unlock_before_callback) {
215 mutex_status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
216 if (ACPI_FAILURE (mutex_status)) {
217 return_ACPI_STATUS (mutex_status);
218 }
219 }
220
221 status = user_function (child_node, level,
222 context, return_value);
223
224 if (unlock_before_callback) {
225 mutex_status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
226 if (ACPI_FAILURE (mutex_status)) {
227 return_ACPI_STATUS (mutex_status);
228 }
229 }
230
231 switch (status) {
232 case AE_OK:
233 case AE_CTRL_DEPTH:
234
235 /* Just keep going */
236 break;
237
238 case AE_CTRL_TERMINATE:
239
240 /* Exit now, with OK status */
241
242 return_ACPI_STATUS (AE_OK);
243
244 default:
245
246 /* All others are valid exceptions */
247
248 return_ACPI_STATUS (status);
249 }
250 }
251
252 /*
253 * Depth first search:
254 * Attempt to go down another level in the namespace
255 * if we are allowed to. Don't go any further if we
256 * have reached the caller specified maximum depth
257 * or if the user function has specified that the
258 * maximum depth has been reached.
259 */
260 if ((level < max_depth) && (status != AE_CTRL_DEPTH)) {
261 if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
262 /*
263 * There is at least one child of this
264 * node, visit the onde
265 */
266 level++;
267 parent_node = child_node;
268 child_node = NULL;
269 }
270 }
271 }
272 else {
273 /*
274 * No more children of this node (acpi_ns_get_next_node
275 * failed), go back upwards in the namespace tree to
276 * the node's parent.
277 */
278 level--;
279 child_node = parent_node;
280 parent_node = acpi_ns_get_parent_node (parent_node);
281 }
282 }
283
284 /* Complete walk, not terminated by user function */
285
286 return_ACPI_STATUS (AE_OK);
287}
288
289
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
new file mode 100644
index 000000000000..1dc995586cbe
--- /dev/null
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -0,0 +1,764 @@
1/*******************************************************************************
2 *
3 * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
4 * ACPI Object evaluation interfaces
5 *
6 ******************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <linux/module.h>
46
47#include <acpi/acpi.h>
48#include <acpi/acnamesp.h>
49#include <acpi/acinterp.h>
50
51
52#define _COMPONENT ACPI_NAMESPACE
53 ACPI_MODULE_NAME ("nsxfeval")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_evaluate_object_typed
59 *
60 * PARAMETERS: Handle - Object handle (optional)
61 * *Pathname - Object pathname (optional)
62 * **external_params - List of parameters to pass to method,
63 * terminated by NULL. May be NULL
64 * if no parameters are being passed.
65 * *return_buffer - Where to put method's return value (if
66 * any). If NULL, no value is returned.
67 * return_type - Expected type of return object
68 *
69 * RETURN: Status
70 *
71 * DESCRIPTION: Find and evaluate the given object, passing the given
72 * parameters if necessary. One of "Handle" or "Pathname" must
73 * be valid (non-null)
74 *
75 ******************************************************************************/
76#ifdef ACPI_FUTURE_USAGE
77acpi_status
78acpi_evaluate_object_typed (
79 acpi_handle handle,
80 acpi_string pathname,
81 struct acpi_object_list *external_params,
82 struct acpi_buffer *return_buffer,
83 acpi_object_type return_type)
84{
85 acpi_status status;
86 u8 must_free = FALSE;
87
88
89 ACPI_FUNCTION_TRACE ("acpi_evaluate_object_typed");
90
91
92 /* Return buffer must be valid */
93
94 if (!return_buffer) {
95 return_ACPI_STATUS (AE_BAD_PARAMETER);
96 }
97
98 if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
99 must_free = TRUE;
100 }
101
102 /* Evaluate the object */
103
104 status = acpi_evaluate_object (handle, pathname, external_params, return_buffer);
105 if (ACPI_FAILURE (status)) {
106 return_ACPI_STATUS (status);
107 }
108
109 /* Type ANY means "don't care" */
110
111 if (return_type == ACPI_TYPE_ANY) {
112 return_ACPI_STATUS (AE_OK);
113 }
114
115 if (return_buffer->length == 0) {
116 /* Error because caller specifically asked for a return value */
117
118 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
119 "No return value\n"));
120
121 return_ACPI_STATUS (AE_NULL_OBJECT);
122 }
123
124 /* Examine the object type returned from evaluate_object */
125
126 if (((union acpi_object *) return_buffer->pointer)->type == return_type) {
127 return_ACPI_STATUS (AE_OK);
128 }
129
130 /* Return object type does not match requested type */
131
132 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
133 "Incorrect return type [%s] requested [%s]\n",
134 acpi_ut_get_type_name (((union acpi_object *) return_buffer->pointer)->type),
135 acpi_ut_get_type_name (return_type)));
136
137 if (must_free) {
138 /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
139
140 acpi_os_free (return_buffer->pointer);
141 return_buffer->pointer = NULL;
142 }
143
144 return_buffer->length = 0;
145 return_ACPI_STATUS (AE_TYPE);
146}
147#endif /* ACPI_FUTURE_USAGE */
148
149
150/*******************************************************************************
151 *
152 * FUNCTION: acpi_evaluate_object
153 *
154 * PARAMETERS: Handle - Object handle (optional)
155 * Pathname - Object pathname (optional)
156 * external_params - List of parameters to pass to method,
157 * terminated by NULL. May be NULL
158 * if no parameters are being passed.
159 * return_buffer - Where to put method's return value (if
160 * any). If NULL, no value is returned.
161 *
162 * RETURN: Status
163 *
164 * DESCRIPTION: Find and evaluate the given object, passing the given
165 * parameters if necessary. One of "Handle" or "Pathname" must
166 * be valid (non-null)
167 *
168 ******************************************************************************/
169
170acpi_status
171acpi_evaluate_object (
172 acpi_handle handle,
173 acpi_string pathname,
174 struct acpi_object_list *external_params,
175 struct acpi_buffer *return_buffer)
176{
177 acpi_status status;
178 acpi_status status2;
179 struct acpi_parameter_info info;
180 acpi_size buffer_space_needed;
181 u32 i;
182
183
184 ACPI_FUNCTION_TRACE ("acpi_evaluate_object");
185
186
187 info.node = handle;
188 info.parameters = NULL;
189 info.return_object = NULL;
190 info.parameter_type = ACPI_PARAM_ARGS;
191
192 /*
193 * If there are parameters to be passed to the object
194 * (which must be a control method), the external objects
195 * must be converted to internal objects
196 */
197 if (external_params && external_params->count) {
198 /*
199 * Allocate a new parameter block for the internal objects
200 * Add 1 to count to allow for null terminated internal list
201 */
202 info.parameters = ACPI_MEM_CALLOCATE (
203 ((acpi_size) external_params->count + 1) *
204 sizeof (void *));
205 if (!info.parameters) {
206 return_ACPI_STATUS (AE_NO_MEMORY);
207 }
208
209 /*
210 * Convert each external object in the list to an
211 * internal object
212 */
213 for (i = 0; i < external_params->count; i++) {
214 status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
215 &info.parameters[i]);
216 if (ACPI_FAILURE (status)) {
217 acpi_ut_delete_internal_object_list (info.parameters);
218 return_ACPI_STATUS (status);
219 }
220 }
221 info.parameters[external_params->count] = NULL;
222 }
223
224
225 /*
226 * Three major cases:
227 * 1) Fully qualified pathname
228 * 2) No handle, not fully qualified pathname (error)
229 * 3) Valid handle
230 */
231 if ((pathname) &&
232 (acpi_ns_valid_root_prefix (pathname[0]))) {
233 /*
234 * The path is fully qualified, just evaluate by name
235 */
236 status = acpi_ns_evaluate_by_name (pathname, &info);
237 }
238 else if (!handle) {
239 /*
240 * A handle is optional iff a fully qualified pathname
241 * is specified. Since we've already handled fully
242 * qualified names above, this is an error
243 */
244 if (!pathname) {
245 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
246 "Both Handle and Pathname are NULL\n"));
247 }
248 else {
249 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
250 "Handle is NULL and Pathname is relative\n"));
251 }
252
253 status = AE_BAD_PARAMETER;
254 }
255 else {
256 /*
257 * We get here if we have a handle -- and if we have a
258 * pathname it is relative. The handle will be validated
259 * in the lower procedures
260 */
261 if (!pathname) {
262 /*
263 * The null pathname case means the handle is for
264 * the actual object to be evaluated
265 */
266 status = acpi_ns_evaluate_by_handle (&info);
267 }
268 else {
269 /*
270 * Both a Handle and a relative Pathname
271 */
272 status = acpi_ns_evaluate_relative (pathname, &info);
273 }
274 }
275
276
277 /*
278 * If we are expecting a return value, and all went well above,
279 * copy the return value to an external object.
280 */
281 if (return_buffer) {
282 if (!info.return_object) {
283 return_buffer->length = 0;
284 }
285 else {
286 if (ACPI_GET_DESCRIPTOR_TYPE (info.return_object) == ACPI_DESC_TYPE_NAMED) {
287 /*
288 * If we received a NS Node as a return object, this means that
289 * the object we are evaluating has nothing interesting to
290 * return (such as a mutex, etc.) We return an error because
291 * these types are essentially unsupported by this interface.
292 * We don't check up front because this makes it easier to add
293 * support for various types at a later date if necessary.
294 */
295 status = AE_TYPE;
296 info.return_object = NULL; /* No need to delete a NS Node */
297 return_buffer->length = 0;
298 }
299
300 if (ACPI_SUCCESS (status)) {
301 /*
302 * Find out how large a buffer is needed
303 * to contain the returned object
304 */
305 status = acpi_ut_get_object_size (info.return_object,
306 &buffer_space_needed);
307 if (ACPI_SUCCESS (status)) {
308 /* Validate/Allocate/Clear caller buffer */
309
310 status = acpi_ut_initialize_buffer (return_buffer, buffer_space_needed);
311 if (ACPI_FAILURE (status)) {
312 /*
313 * Caller's buffer is too small or a new one can't be allocated
314 */
315 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
316 "Needed buffer size %X, %s\n",
317 (u32) buffer_space_needed,
318 acpi_format_exception (status)));
319 }
320 else {
321 /*
322 * We have enough space for the object, build it
323 */
324 status = acpi_ut_copy_iobject_to_eobject (info.return_object,
325 return_buffer);
326 }
327 }
328 }
329 }
330 }
331
332 if (info.return_object) {
333 /*
334 * Delete the internal return object. NOTE: Interpreter
335 * must be locked to avoid race condition.
336 */
337 status2 = acpi_ex_enter_interpreter ();
338 if (ACPI_SUCCESS (status2)) {
339 /*
340 * Delete the internal return object. (Or at least
341 * decrement the reference count by one)
342 */
343 acpi_ut_remove_reference (info.return_object);
344 acpi_ex_exit_interpreter ();
345 }
346 }
347
348 /*
349 * Free the input parameter list (if we created one),
350 */
351 if (info.parameters) {
352 /* Free the allocated parameter block */
353
354 acpi_ut_delete_internal_object_list (info.parameters);
355 }
356
357 return_ACPI_STATUS (status);
358}
359EXPORT_SYMBOL(acpi_evaluate_object);
360
361
362/*******************************************************************************
363 *
364 * FUNCTION: acpi_walk_namespace
365 *
366 * PARAMETERS: Type - acpi_object_type to search for
367 * start_object - Handle in namespace where search begins
368 * max_depth - Depth to which search is to reach
369 * user_function - Called when an object of "Type" is found
370 * Context - Passed to user function
371 * return_value - Location where return value of
372 * user_function is put if terminated early
373 *
374 * RETURNS Return value from the user_function if terminated early.
375 * Otherwise, returns NULL.
376 *
377 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
378 * starting (and ending) at the object specified by start_handle.
379 * The user_function is called whenever an object that matches
380 * the type parameter is found. If the user function returns
381 * a non-zero value, the search is terminated immediately and this
382 * value is returned to the caller.
383 *
384 * The point of this procedure is to provide a generic namespace
385 * walk routine that can be called from multiple places to
386 * provide multiple services; the User Function can be tailored
387 * to each task, whether it is a print function, a compare
388 * function, etc.
389 *
390 ******************************************************************************/
391
392acpi_status
393acpi_walk_namespace (
394 acpi_object_type type,
395 acpi_handle start_object,
396 u32 max_depth,
397 acpi_walk_callback user_function,
398 void *context,
399 void **return_value)
400{
401 acpi_status status;
402
403
404 ACPI_FUNCTION_TRACE ("acpi_walk_namespace");
405
406
407 /* Parameter validation */
408
409 if ((type > ACPI_TYPE_EXTERNAL_MAX) ||
410 (!max_depth) ||
411 (!user_function)) {
412 return_ACPI_STATUS (AE_BAD_PARAMETER);
413 }
414
415 /*
416 * Lock the namespace around the walk.
417 * The namespace will be unlocked/locked around each call
418 * to the user function - since this function
419 * must be allowed to make Acpi calls itself.
420 */
421 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
422 if (ACPI_FAILURE (status)) {
423 return_ACPI_STATUS (status);
424 }
425
426 status = acpi_ns_walk_namespace (type, start_object, max_depth, ACPI_NS_WALK_UNLOCK,
427 user_function, context, return_value);
428
429 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
430 return_ACPI_STATUS (status);
431}
432EXPORT_SYMBOL(acpi_walk_namespace);
433
434
435/*******************************************************************************
436 *
437 * FUNCTION: acpi_ns_get_device_callback
438 *
439 * PARAMETERS: Callback from acpi_get_device
440 *
441 * RETURN: Status
442 *
443 * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non-
444 * present devices, or if they specified a HID, it filters based
445 * on that.
446 *
447 ******************************************************************************/
448
449static acpi_status
450acpi_ns_get_device_callback (
451 acpi_handle obj_handle,
452 u32 nesting_level,
453 void *context,
454 void **return_value)
455{
456 struct acpi_get_devices_info *info = context;
457 acpi_status status;
458 struct acpi_namespace_node *node;
459 u32 flags;
460 struct acpi_device_id hid;
461 struct acpi_compatible_id_list *cid;
462 acpi_native_uint i;
463
464
465 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
466 if (ACPI_FAILURE (status)) {
467 return (status);
468 }
469
470 node = acpi_ns_map_handle_to_node (obj_handle);
471 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
472 if (ACPI_FAILURE (status)) {
473 return (status);
474 }
475
476 if (!node) {
477 return (AE_BAD_PARAMETER);
478 }
479
480 /* Run _STA to determine if device is present */
481
482 status = acpi_ut_execute_STA (node, &flags);
483 if (ACPI_FAILURE (status)) {
484 return (AE_CTRL_DEPTH);
485 }
486
487 if (!(flags & 0x01)) {
488 /* Don't return at the device or children of the device if not there */
489
490 return (AE_CTRL_DEPTH);
491 }
492
493 /* Filter based on device HID & CID */
494
495 if (info->hid != NULL) {
496 status = acpi_ut_execute_HID (node, &hid);
497 if (status == AE_NOT_FOUND) {
498 return (AE_OK);
499 }
500 else if (ACPI_FAILURE (status)) {
501 return (AE_CTRL_DEPTH);
502 }
503
504 if (ACPI_STRNCMP (hid.value, info->hid, sizeof (hid.value)) != 0) {
505 /* Get the list of Compatible IDs */
506
507 status = acpi_ut_execute_CID (node, &cid);
508 if (status == AE_NOT_FOUND) {
509 return (AE_OK);
510 }
511 else if (ACPI_FAILURE (status)) {
512 return (AE_CTRL_DEPTH);
513 }
514
515 /* Walk the CID list */
516
517 for (i = 0; i < cid->count; i++) {
518 if (ACPI_STRNCMP (cid->id[i].value, info->hid,
519 sizeof (struct acpi_compatible_id)) != 0) {
520 ACPI_MEM_FREE (cid);
521 return (AE_OK);
522 }
523 }
524 ACPI_MEM_FREE (cid);
525 }
526 }
527
528 status = info->user_function (obj_handle, nesting_level, info->context, return_value);
529 return (status);
530}
531
532
533/*******************************************************************************
534 *
535 * FUNCTION: acpi_get_devices
536 *
537 * PARAMETERS: HID - HID to search for. Can be NULL.
538 * user_function - Called when a matching object is found
539 * Context - Passed to user function
540 * return_value - Location where return value of
541 * user_function is put if terminated early
542 *
543 * RETURNS Return value from the user_function if terminated early.
544 * Otherwise, returns NULL.
545 *
546 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
547 * starting (and ending) at the object specified by start_handle.
548 * The user_function is called whenever an object of type
549 * Device is found. If the user function returns
550 * a non-zero value, the search is terminated immediately and this
551 * value is returned to the caller.
552 *
553 * This is a wrapper for walk_namespace, but the callback performs
554 * additional filtering. Please see acpi_get_device_callback.
555 *
556 ******************************************************************************/
557
558acpi_status
559acpi_get_devices (
560 char *HID,
561 acpi_walk_callback user_function,
562 void *context,
563 void **return_value)
564{
565 acpi_status status;
566 struct acpi_get_devices_info info;
567
568
569 ACPI_FUNCTION_TRACE ("acpi_get_devices");
570
571
572 /* Parameter validation */
573
574 if (!user_function) {
575 return_ACPI_STATUS (AE_BAD_PARAMETER);
576 }
577
578 /*
579 * We're going to call their callback from OUR callback, so we need
580 * to know what it is, and their context parameter.
581 */
582 info.context = context;
583 info.user_function = user_function;
584 info.hid = HID;
585
586 /*
587 * Lock the namespace around the walk.
588 * The namespace will be unlocked/locked around each call
589 * to the user function - since this function
590 * must be allowed to make Acpi calls itself.
591 */
592 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
593 if (ACPI_FAILURE (status)) {
594 return_ACPI_STATUS (status);
595 }
596
597 status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE,
598 ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
599 ACPI_NS_WALK_UNLOCK,
600 acpi_ns_get_device_callback, &info,
601 return_value);
602
603 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
604 return_ACPI_STATUS (status);
605}
606EXPORT_SYMBOL(acpi_get_devices);
607
608
609/*******************************************************************************
610 *
611 * FUNCTION: acpi_attach_data
612 *
613 * PARAMETERS: obj_handle - Namespace node
614 * Handler - Handler for this attachment
615 * Data - Pointer to data to be attached
616 *
617 * RETURN: Status
618 *
619 * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
620 *
621 ******************************************************************************/
622
623acpi_status
624acpi_attach_data (
625 acpi_handle obj_handle,
626 acpi_object_handler handler,
627 void *data)
628{
629 struct acpi_namespace_node *node;
630 acpi_status status;
631
632
633 /* Parameter validation */
634
635 if (!obj_handle ||
636 !handler ||
637 !data) {
638 return (AE_BAD_PARAMETER);
639 }
640
641 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
642 if (ACPI_FAILURE (status)) {
643 return (status);
644 }
645
646 /* Convert and validate the handle */
647
648 node = acpi_ns_map_handle_to_node (obj_handle);
649 if (!node) {
650 status = AE_BAD_PARAMETER;
651 goto unlock_and_exit;
652 }
653
654 status = acpi_ns_attach_data (node, handler, data);
655
656unlock_and_exit:
657 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
658 return (status);
659}
660
661
662/*******************************************************************************
663 *
664 * FUNCTION: acpi_detach_data
665 *
666 * PARAMETERS: obj_handle - Namespace node handle
667 * Handler - Handler used in call to acpi_attach_data
668 *
669 * RETURN: Status
670 *
671 * DESCRIPTION: Remove data that was previously attached to a node.
672 *
673 ******************************************************************************/
674
675acpi_status
676acpi_detach_data (
677 acpi_handle obj_handle,
678 acpi_object_handler handler)
679{
680 struct acpi_namespace_node *node;
681 acpi_status status;
682
683
684 /* Parameter validation */
685
686 if (!obj_handle ||
687 !handler) {
688 return (AE_BAD_PARAMETER);
689 }
690
691 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
692 if (ACPI_FAILURE (status)) {
693 return (status);
694 }
695
696 /* Convert and validate the handle */
697
698 node = acpi_ns_map_handle_to_node (obj_handle);
699 if (!node) {
700 status = AE_BAD_PARAMETER;
701 goto unlock_and_exit;
702 }
703
704 status = acpi_ns_detach_data (node, handler);
705
706unlock_and_exit:
707 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
708 return (status);
709}
710
711
712/*******************************************************************************
713 *
714 * FUNCTION: acpi_get_data
715 *
716 * PARAMETERS: obj_handle - Namespace node
717 * Handler - Handler used in call to attach_data
718 * Data - Where the data is returned
719 *
720 * RETURN: Status
721 *
722 * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
723 *
724 ******************************************************************************/
725
726acpi_status
727acpi_get_data (
728 acpi_handle obj_handle,
729 acpi_object_handler handler,
730 void **data)
731{
732 struct acpi_namespace_node *node;
733 acpi_status status;
734
735
736 /* Parameter validation */
737
738 if (!obj_handle ||
739 !handler ||
740 !data) {
741 return (AE_BAD_PARAMETER);
742 }
743
744 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
745 if (ACPI_FAILURE (status)) {
746 return (status);
747 }
748
749 /* Convert and validate the handle */
750
751 node = acpi_ns_map_handle_to_node (obj_handle);
752 if (!node) {
753 status = AE_BAD_PARAMETER;
754 goto unlock_and_exit;
755 }
756
757 status = acpi_ns_get_attached_data (node, handler, data);
758
759unlock_and_exit:
760 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
761 return (status);
762}
763
764
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
new file mode 100644
index 000000000000..f2405efd1b9a
--- /dev/null
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -0,0 +1,369 @@
1/******************************************************************************
2 *
3 * Module Name: nsxfname - Public interfaces to the ACPI subsystem
4 * ACPI Namespace oriented interfaces
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <linux/module.h>
46
47#include <acpi/acpi.h>
48#include <acpi/acnamesp.h>
49
50
51#define _COMPONENT ACPI_NAMESPACE
52 ACPI_MODULE_NAME ("nsxfname")
53
54
55/******************************************************************************
56 *
57 * FUNCTION: acpi_get_handle
58 *
59 * PARAMETERS: Parent - Object to search under (search scope).
60 * path_name - Pointer to an asciiz string containing the
61 * name
62 * ret_handle - Where the return handle is placed
63 *
64 * RETURN: Status
65 *
66 * DESCRIPTION: This routine will search for a caller specified name in the
67 * name space. The caller can restrict the search region by
68 * specifying a non NULL parent. The parent value is itself a
69 * namespace handle.
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_get_handle (
75 acpi_handle parent,
76 acpi_string pathname,
77 acpi_handle *ret_handle)
78{
79 acpi_status status;
80 struct acpi_namespace_node *node = NULL;
81 struct acpi_namespace_node *prefix_node = NULL;
82
83
84 ACPI_FUNCTION_ENTRY ();
85
86
87 /* Parameter Validation */
88
89 if (!ret_handle || !pathname) {
90 return (AE_BAD_PARAMETER);
91 }
92
93 /* Convert a parent handle to a prefix node */
94
95 if (parent) {
96 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
97 if (ACPI_FAILURE (status)) {
98 return (status);
99 }
100
101 prefix_node = acpi_ns_map_handle_to_node (parent);
102 if (!prefix_node) {
103 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
104 return (AE_BAD_PARAMETER);
105 }
106
107 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
108 if (ACPI_FAILURE (status)) {
109 return (status);
110 }
111 }
112
113 /* Special case for root, since we can't search for it */
114
115 if (ACPI_STRCMP (pathname, ACPI_NS_ROOT_PATH) == 0) {
116 *ret_handle = acpi_ns_convert_entry_to_handle (acpi_gbl_root_node);
117 return (AE_OK);
118 }
119
120 /*
121 * Find the Node and convert to a handle
122 */
123 status = acpi_ns_get_node_by_path (pathname, prefix_node, ACPI_NS_NO_UPSEARCH,
124 &node);
125
126 *ret_handle = NULL;
127 if (ACPI_SUCCESS (status)) {
128 *ret_handle = acpi_ns_convert_entry_to_handle (node);
129 }
130
131 return (status);
132}
133EXPORT_SYMBOL(acpi_get_handle);
134
135
136/******************************************************************************
137 *
138 * FUNCTION: acpi_get_name
139 *
140 * PARAMETERS: Handle - Handle to be converted to a pathname
141 * name_type - Full pathname or single segment
142 * Buffer - Buffer for returned path
143 *
144 * RETURN: Pointer to a string containing the fully qualified Name.
145 *
146 * DESCRIPTION: This routine returns the fully qualified name associated with
147 * the Handle parameter. This and the acpi_pathname_to_handle are
148 * complementary functions.
149 *
150 ******************************************************************************/
151
152acpi_status
153acpi_get_name (
154 acpi_handle handle,
155 u32 name_type,
156 struct acpi_buffer *buffer)
157{
158 acpi_status status;
159 struct acpi_namespace_node *node;
160
161
162 /* Parameter validation */
163
164 if (name_type > ACPI_NAME_TYPE_MAX) {
165 return (AE_BAD_PARAMETER);
166 }
167
168 status = acpi_ut_validate_buffer (buffer);
169 if (ACPI_FAILURE (status)) {
170 return (status);
171 }
172
173 if (name_type == ACPI_FULL_PATHNAME) {
174 /* Get the full pathname (From the namespace root) */
175
176 status = acpi_ns_handle_to_pathname (handle, buffer);
177 return (status);
178 }
179
180 /*
181 * Wants the single segment ACPI name.
182 * Validate handle and convert to a namespace Node
183 */
184 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
185 if (ACPI_FAILURE (status)) {
186 return (status);
187 }
188
189 node = acpi_ns_map_handle_to_node (handle);
190 if (!node) {
191 status = AE_BAD_PARAMETER;
192 goto unlock_and_exit;
193 }
194
195 /* Validate/Allocate/Clear caller buffer */
196
197 status = acpi_ut_initialize_buffer (buffer, ACPI_PATH_SEGMENT_LENGTH);
198 if (ACPI_FAILURE (status)) {
199 goto unlock_and_exit;
200 }
201
202 /* Just copy the ACPI name from the Node and zero terminate it */
203
204 ACPI_STRNCPY (buffer->pointer, acpi_ut_get_node_name (node),
205 ACPI_NAME_SIZE);
206 ((char *) buffer->pointer) [ACPI_NAME_SIZE] = 0;
207 status = AE_OK;
208
209
210unlock_and_exit:
211
212 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
213 return (status);
214}
215EXPORT_SYMBOL(acpi_get_name);
216
217
218/******************************************************************************
219 *
220 * FUNCTION: acpi_get_object_info
221 *
222 * PARAMETERS: Handle - Object Handle
223 * Info - Where the info is returned
224 *
225 * RETURN: Status
226 *
227 * DESCRIPTION: Returns information about an object as gleaned from the
228 * namespace node and possibly by running several standard
229 * control methods (Such as in the case of a device.)
230 *
231 ******************************************************************************/
232
233acpi_status
234acpi_get_object_info (
235 acpi_handle handle,
236 struct acpi_buffer *buffer)
237{
238 acpi_status status;
239 struct acpi_namespace_node *node;
240 struct acpi_device_info *info;
241 struct acpi_device_info *return_info;
242 struct acpi_compatible_id_list *cid_list = NULL;
243 acpi_size size;
244
245
246 /* Parameter validation */
247
248 if (!handle || !buffer) {
249 return (AE_BAD_PARAMETER);
250 }
251
252 status = acpi_ut_validate_buffer (buffer);
253 if (ACPI_FAILURE (status)) {
254 return (status);
255 }
256
257 info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_device_info));
258 if (!info) {
259 return (AE_NO_MEMORY);
260 }
261
262 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
263 if (ACPI_FAILURE (status)) {
264 goto cleanup;
265 }
266
267 node = acpi_ns_map_handle_to_node (handle);
268 if (!node) {
269 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
270 goto cleanup;
271 }
272
273 /* Init return structure */
274
275 size = sizeof (struct acpi_device_info);
276
277 info->type = node->type;
278 info->name = node->name.integer;
279 info->valid = 0;
280
281 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
282 if (ACPI_FAILURE (status)) {
283 goto cleanup;
284 }
285
286 /* If not a device, we are all done */
287
288 if (info->type == ACPI_TYPE_DEVICE) {
289 /*
290 * Get extra info for ACPI Devices objects only:
291 * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods.
292 *
293 * Note: none of these methods are required, so they may or may
294 * not be present for this device. The Info->Valid bitfield is used
295 * to indicate which methods were found and ran successfully.
296 */
297
298 /* Execute the Device._HID method */
299
300 status = acpi_ut_execute_HID (node, &info->hardware_id);
301 if (ACPI_SUCCESS (status)) {
302 info->valid |= ACPI_VALID_HID;
303 }
304
305 /* Execute the Device._UID method */
306
307 status = acpi_ut_execute_UID (node, &info->unique_id);
308 if (ACPI_SUCCESS (status)) {
309 info->valid |= ACPI_VALID_UID;
310 }
311
312 /* Execute the Device._CID method */
313
314 status = acpi_ut_execute_CID (node, &cid_list);
315 if (ACPI_SUCCESS (status)) {
316 size += ((acpi_size) cid_list->count - 1) *
317 sizeof (struct acpi_compatible_id);
318 info->valid |= ACPI_VALID_CID;
319 }
320
321 /* Execute the Device._STA method */
322
323 status = acpi_ut_execute_STA (node, &info->current_status);
324 if (ACPI_SUCCESS (status)) {
325 info->valid |= ACPI_VALID_STA;
326 }
327
328 /* Execute the Device._ADR method */
329
330 status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node,
331 &info->address);
332 if (ACPI_SUCCESS (status)) {
333 info->valid |= ACPI_VALID_ADR;
334 }
335
336 /* Execute the Device._sx_d methods */
337
338 status = acpi_ut_execute_sxds (node, info->highest_dstates);
339 if (ACPI_SUCCESS (status)) {
340 info->valid |= ACPI_VALID_SXDS;
341 }
342 }
343
344 /* Validate/Allocate/Clear caller buffer */
345
346 status = acpi_ut_initialize_buffer (buffer, size);
347 if (ACPI_FAILURE (status)) {
348 goto cleanup;
349 }
350
351 /* Populate the return buffer */
352
353 return_info = buffer->pointer;
354 ACPI_MEMCPY (return_info, info, sizeof (struct acpi_device_info));
355
356 if (cid_list) {
357 ACPI_MEMCPY (&return_info->compatibility_id, cid_list, cid_list->size);
358 }
359
360
361cleanup:
362 ACPI_MEM_FREE (info);
363 if (cid_list) {
364 ACPI_MEM_FREE (cid_list);
365 }
366 return (status);
367}
368EXPORT_SYMBOL(acpi_get_object_info);
369
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
new file mode 100644
index 000000000000..19acf32674b9
--- /dev/null
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -0,0 +1,262 @@
1/*******************************************************************************
2 *
3 * Module Name: nsxfobj - Public interfaces to the ACPI subsystem
4 * ACPI Object oriented interfaces
5 *
6 ******************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <linux/module.h>
46
47#include <acpi/acpi.h>
48#include <acpi/acnamesp.h>
49
50
51#define _COMPONENT ACPI_NAMESPACE
52 ACPI_MODULE_NAME ("nsxfobj")
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_get_type
57 *
58 * PARAMETERS: Handle - Handle of object whose type is desired
59 * *ret_type - Where the type will be placed
60 *
61 * RETURN: Status
62 *
63 * DESCRIPTION: This routine returns the type associatd with a particular handle
64 *
65 ******************************************************************************/
66
67acpi_status
68acpi_get_type (
69 acpi_handle handle,
70 acpi_object_type *ret_type)
71{
72 struct acpi_namespace_node *node;
73 acpi_status status;
74
75
76 /* Parameter Validation */
77
78 if (!ret_type) {
79 return (AE_BAD_PARAMETER);
80 }
81
82 /*
83 * Special case for the predefined Root Node
84 * (return type ANY)
85 */
86 if (handle == ACPI_ROOT_OBJECT) {
87 *ret_type = ACPI_TYPE_ANY;
88 return (AE_OK);
89 }
90
91 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
92 if (ACPI_FAILURE (status)) {
93 return (status);
94 }
95
96 /* Convert and validate the handle */
97
98 node = acpi_ns_map_handle_to_node (handle);
99 if (!node) {
100 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
101 return (AE_BAD_PARAMETER);
102 }
103
104 *ret_type = node->type;
105
106
107 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
108 return (status);
109}
110EXPORT_SYMBOL(acpi_get_type);
111
112
113/*******************************************************************************
114 *
115 * FUNCTION: acpi_get_parent
116 *
117 * PARAMETERS: Handle - Handle of object whose parent is desired
118 * ret_handle - Where the parent handle will be placed
119 *
120 * RETURN: Status
121 *
122 * DESCRIPTION: Returns a handle to the parent of the object represented by
123 * Handle.
124 *
125 ******************************************************************************/
126
127acpi_status
128acpi_get_parent (
129 acpi_handle handle,
130 acpi_handle *ret_handle)
131{
132 struct acpi_namespace_node *node;
133 acpi_status status;
134
135
136 if (!ret_handle) {
137 return (AE_BAD_PARAMETER);
138 }
139
140 /* Special case for the predefined Root Node (no parent) */
141
142 if (handle == ACPI_ROOT_OBJECT) {
143 return (AE_NULL_ENTRY);
144 }
145
146 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
147 if (ACPI_FAILURE (status)) {
148 return (status);
149 }
150
151 /* Convert and validate the handle */
152
153 node = acpi_ns_map_handle_to_node (handle);
154 if (!node) {
155 status = AE_BAD_PARAMETER;
156 goto unlock_and_exit;
157 }
158
159 /* Get the parent entry */
160
161 *ret_handle =
162 acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_node (node));
163
164 /* Return exception if parent is null */
165
166 if (!acpi_ns_get_parent_node (node)) {
167 status = AE_NULL_ENTRY;
168 }
169
170
171unlock_and_exit:
172
173 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
174 return (status);
175}
176EXPORT_SYMBOL(acpi_get_parent);
177
178
179/*******************************************************************************
180 *
181 * FUNCTION: acpi_get_next_object
182 *
183 * PARAMETERS: Type - Type of object to be searched for
184 * Parent - Parent object whose children we are getting
185 * last_child - Previous child that was found.
186 * The NEXT child will be returned
187 * ret_handle - Where handle to the next object is placed
188 *
189 * RETURN: Status
190 *
191 * DESCRIPTION: Return the next peer object within the namespace. If Handle is
192 * valid, Scope is ignored. Otherwise, the first object within
193 * Scope is returned.
194 *
195 ******************************************************************************/
196
197acpi_status
198acpi_get_next_object (
199 acpi_object_type type,
200 acpi_handle parent,
201 acpi_handle child,
202 acpi_handle *ret_handle)
203{
204 acpi_status status;
205 struct acpi_namespace_node *node;
206 struct acpi_namespace_node *parent_node = NULL;
207 struct acpi_namespace_node *child_node = NULL;
208
209
210 /* Parameter validation */
211
212 if (type > ACPI_TYPE_EXTERNAL_MAX) {
213 return (AE_BAD_PARAMETER);
214 }
215
216 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
217 if (ACPI_FAILURE (status)) {
218 return (status);
219 }
220
221 /* If null handle, use the parent */
222
223 if (!child) {
224 /* Start search at the beginning of the specified scope */
225
226 parent_node = acpi_ns_map_handle_to_node (parent);
227 if (!parent_node) {
228 status = AE_BAD_PARAMETER;
229 goto unlock_and_exit;
230 }
231 }
232 else {
233 /* Non-null handle, ignore the parent */
234 /* Convert and validate the handle */
235
236 child_node = acpi_ns_map_handle_to_node (child);
237 if (!child_node) {
238 status = AE_BAD_PARAMETER;
239 goto unlock_and_exit;
240 }
241 }
242
243 /* Internal function does the real work */
244
245 node = acpi_ns_get_next_node (type, parent_node, child_node);
246 if (!node) {
247 status = AE_NOT_FOUND;
248 goto unlock_and_exit;
249 }
250
251 if (ret_handle) {
252 *ret_handle = acpi_ns_convert_entry_to_handle (node);
253 }
254
255
256unlock_and_exit:
257
258 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
259 return (status);
260}
261EXPORT_SYMBOL(acpi_get_next_object);
262
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
new file mode 100644
index 000000000000..a82834b32752
--- /dev/null
+++ b/drivers/acpi/numa.c
@@ -0,0 +1,213 @@
1/*
2 * acpi_numa.c - ACPI NUMA support
3 *
4 * Copyright (C) 2002 Takayoshi Kochi <t-kochi@bq.jp.nec.com>
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 *
24 */
25#include <linux/module.h>
26#include <linux/config.h>
27#include <linux/init.h>
28#include <linux/kernel.h>
29#include <linux/types.h>
30#include <linux/errno.h>
31#include <linux/acpi.h>
32#include <acpi/acpi_bus.h>
33#include <acpi/acmacros.h>
34
35#define ACPI_NUMA 0x80000000
36#define _COMPONENT ACPI_NUMA
37 ACPI_MODULE_NAME ("numa")
38
39extern int __init acpi_table_parse_madt_family (enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler, unsigned int max_entries);
40
41void __init
42acpi_table_print_srat_entry (
43 acpi_table_entry_header *header)
44{
45
46 ACPI_FUNCTION_NAME ("acpi_table_print_srat_entry");
47
48 if (!header)
49 return;
50
51 switch (header->type) {
52
53 case ACPI_SRAT_PROCESSOR_AFFINITY:
54#ifdef ACPI_DEBUG_OUTPUT
55 {
56 struct acpi_table_processor_affinity *p =
57 (struct acpi_table_processor_affinity*) header;
58 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
59 p->apic_id, p->lsapic_eid, p->proximity_domain,
60 p->flags.enabled?"enabled":"disabled"));
61 }
62#endif /* ACPI_DEBUG_OUTPUT */
63 break;
64
65 case ACPI_SRAT_MEMORY_AFFINITY:
66#ifdef ACPI_DEBUG_OUTPUT
67 {
68 struct acpi_table_memory_affinity *p =
69 (struct acpi_table_memory_affinity*) header;
70 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Memory (0x%08x%08x length 0x%08x%08x type 0x%x) in proximity domain %d %s%s\n",
71 p->base_addr_hi, p->base_addr_lo, p->length_hi, p->length_lo,
72 p->memory_type, p->proximity_domain,
73 p->flags.enabled ? "enabled" : "disabled",
74 p->flags.hot_pluggable ? " hot-pluggable" : ""));
75 }
76#endif /* ACPI_DEBUG_OUTPUT */
77 break;
78
79 default:
80 printk(KERN_WARNING PREFIX "Found unsupported SRAT entry (type = 0x%x)\n",
81 header->type);
82 break;
83 }
84}
85
86
87static int __init
88acpi_parse_slit (unsigned long phys_addr, unsigned long size)
89{
90 struct acpi_table_slit *slit;
91 u32 localities;
92
93 if (!phys_addr || !size)
94 return -EINVAL;
95
96 slit = (struct acpi_table_slit *) __va(phys_addr);
97
98 /* downcast just for %llu vs %lu for i386/ia64 */
99 localities = (u32) slit->localities;
100
101 acpi_numa_slit_init(slit);
102
103 return 0;
104}
105
106
107static int __init
108acpi_parse_processor_affinity (
109 acpi_table_entry_header *header,
110 const unsigned long end)
111{
112 struct acpi_table_processor_affinity *processor_affinity;
113
114 processor_affinity = (struct acpi_table_processor_affinity*) header;
115 if (!processor_affinity)
116 return -EINVAL;
117
118 acpi_table_print_srat_entry(header);
119
120 /* let architecture-dependent part to do it */
121 acpi_numa_processor_affinity_init(processor_affinity);
122
123 return 0;
124}
125
126
127static int __init
128acpi_parse_memory_affinity (
129 acpi_table_entry_header *header,
130 const unsigned long end)
131{
132 struct acpi_table_memory_affinity *memory_affinity;
133
134 memory_affinity = (struct acpi_table_memory_affinity*) header;
135 if (!memory_affinity)
136 return -EINVAL;
137
138 acpi_table_print_srat_entry(header);
139
140 /* let architecture-dependent part to do it */
141 acpi_numa_memory_affinity_init(memory_affinity);
142
143 return 0;
144}
145
146
147static int __init
148acpi_parse_srat (unsigned long phys_addr, unsigned long size)
149{
150 struct acpi_table_srat *srat;
151
152 if (!phys_addr || !size)
153 return -EINVAL;
154
155 srat = (struct acpi_table_srat *) __va(phys_addr);
156
157 return 0;
158}
159
160
161int __init
162acpi_table_parse_srat (
163 enum acpi_srat_entry_id id,
164 acpi_madt_entry_handler handler,
165 unsigned int max_entries)
166{
167 return acpi_table_parse_madt_family(ACPI_SRAT, sizeof(struct acpi_table_srat),
168 id, handler, max_entries);
169}
170
171
172int __init
173acpi_numa_init(void)
174{
175 int result;
176
177 /* SRAT: Static Resource Affinity Table */
178 result = acpi_table_parse(ACPI_SRAT, acpi_parse_srat);
179
180 if (result > 0) {
181 result = acpi_table_parse_srat(ACPI_SRAT_PROCESSOR_AFFINITY,
182 acpi_parse_processor_affinity,
183 NR_CPUS);
184 result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY,
185 acpi_parse_memory_affinity,
186 NR_NODE_MEMBLKS); // IA64 specific
187 }
188
189 /* SLIT: System Locality Information Table */
190 result = acpi_table_parse(ACPI_SLIT, acpi_parse_slit);
191
192 acpi_numa_arch_fixup();
193 return 0;
194}
195
196int
197acpi_get_pxm(acpi_handle h)
198{
199 unsigned long pxm;
200 acpi_status status;
201 acpi_handle handle;
202 acpi_handle phandle = h;
203
204 do {
205 handle = phandle;
206 status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm);
207 if (ACPI_SUCCESS(status))
208 return (int)pxm;
209 status = acpi_get_parent(handle, &phandle);
210 } while(ACPI_SUCCESS(status));
211 return -1;
212}
213EXPORT_SYMBOL(acpi_get_pxm);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
new file mode 100644
index 000000000000..5a9128de6226
--- /dev/null
+++ b/drivers/acpi/osl.c
@@ -0,0 +1,1162 @@
1/*
2 * acpi_osl.c - OS-dependent functions ($Revision: 83 $)
3 *
4 * Copyright (C) 2000 Andrew Henroid
5 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
6 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 */
27
28#include <linux/config.h>
29#include <linux/module.h>
30#include <linux/kernel.h>
31#include <linux/slab.h>
32#include <linux/mm.h>
33#include <linux/pci.h>
34#include <linux/smp_lock.h>
35#include <linux/interrupt.h>
36#include <linux/kmod.h>
37#include <linux/delay.h>
38#include <linux/workqueue.h>
39#include <linux/nmi.h>
40#include <acpi/acpi.h>
41#include <asm/io.h>
42#include <acpi/acpi_bus.h>
43#include <acpi/processor.h>
44#include <asm/uaccess.h>
45
46#include <linux/efi.h>
47
48
49#define _COMPONENT ACPI_OS_SERVICES
50ACPI_MODULE_NAME ("osl")
51
52#define PREFIX "ACPI: "
53
54struct acpi_os_dpc
55{
56 acpi_osd_exec_callback function;
57 void *context;
58};
59
60#ifdef CONFIG_ACPI_CUSTOM_DSDT
61#include CONFIG_ACPI_CUSTOM_DSDT_FILE
62#endif
63
64#ifdef ENABLE_DEBUGGER
65#include <linux/kdb.h>
66
67/* stuff for debugger support */
68int acpi_in_debugger;
69EXPORT_SYMBOL(acpi_in_debugger);
70
71extern char line_buf[80];
72#endif /*ENABLE_DEBUGGER*/
73
74static unsigned int acpi_irq_irq;
75static acpi_osd_handler acpi_irq_handler;
76static void *acpi_irq_context;
77static struct workqueue_struct *kacpid_wq;
78
79acpi_status
80acpi_os_initialize(void)
81{
82 return AE_OK;
83}
84
85acpi_status
86acpi_os_initialize1(void)
87{
88 /*
89 * Initialize PCI configuration space access, as we'll need to access
90 * it while walking the namespace (bus 0 and root bridges w/ _BBNs).
91 */
92#ifdef CONFIG_ACPI_PCI
93 if (!raw_pci_ops) {
94 printk(KERN_ERR PREFIX "Access to PCI configuration space unavailable\n");
95 return AE_NULL_ENTRY;
96 }
97#endif
98 kacpid_wq = create_singlethread_workqueue("kacpid");
99 BUG_ON(!kacpid_wq);
100
101 return AE_OK;
102}
103
104acpi_status
105acpi_os_terminate(void)
106{
107 if (acpi_irq_handler) {
108 acpi_os_remove_interrupt_handler(acpi_irq_irq,
109 acpi_irq_handler);
110 }
111
112 destroy_workqueue(kacpid_wq);
113
114 return AE_OK;
115}
116
117void
118acpi_os_printf(const char *fmt,...)
119{
120 va_list args;
121 va_start(args, fmt);
122 acpi_os_vprintf(fmt, args);
123 va_end(args);
124}
125EXPORT_SYMBOL(acpi_os_printf);
126
127void
128acpi_os_vprintf(const char *fmt, va_list args)
129{
130 static char buffer[512];
131
132 vsprintf(buffer, fmt, args);
133
134#ifdef ENABLE_DEBUGGER
135 if (acpi_in_debugger) {
136 kdb_printf("%s", buffer);
137 } else {
138 printk("%s", buffer);
139 }
140#else
141 printk("%s", buffer);
142#endif
143}
144
145void *
146acpi_os_allocate(acpi_size size)
147{
148 return kmalloc(size, GFP_KERNEL);
149}
150
151void
152acpi_os_free(void *ptr)
153{
154 kfree(ptr);
155}
156EXPORT_SYMBOL(acpi_os_free);
157
158acpi_status
159acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
160{
161 if (efi_enabled) {
162 addr->pointer_type = ACPI_PHYSICAL_POINTER;
163 if (efi.acpi20)
164 addr->pointer.physical =
165 (acpi_physical_address) virt_to_phys(efi.acpi20);
166 else if (efi.acpi)
167 addr->pointer.physical =
168 (acpi_physical_address) virt_to_phys(efi.acpi);
169 else {
170 printk(KERN_ERR PREFIX "System description tables not found\n");
171 return AE_NOT_FOUND;
172 }
173 } else {
174 if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) {
175 printk(KERN_ERR PREFIX "System description tables not found\n");
176 return AE_NOT_FOUND;
177 }
178 }
179
180 return AE_OK;
181}
182
183acpi_status
184acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **virt)
185{
186 if (efi_enabled) {
187 if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
188 *virt = (void __iomem *) phys_to_virt(phys);
189 } else {
190 *virt = ioremap(phys, size);
191 }
192 } else {
193 if (phys > ULONG_MAX) {
194 printk(KERN_ERR PREFIX "Cannot map memory that high\n");
195 return AE_BAD_PARAMETER;
196 }
197 /*
198 * ioremap checks to ensure this is in reserved space
199 */
200 *virt = ioremap((unsigned long) phys, size);
201 }
202
203 if (!*virt)
204 return AE_NO_MEMORY;
205
206 return AE_OK;
207}
208
209void
210acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
211{
212 iounmap(virt);
213}
214
215#ifdef ACPI_FUTURE_USAGE
216acpi_status
217acpi_os_get_physical_address(void *virt, acpi_physical_address *phys)
218{
219 if(!phys || !virt)
220 return AE_BAD_PARAMETER;
221
222 *phys = virt_to_phys(virt);
223
224 return AE_OK;
225}
226#endif
227
228#define ACPI_MAX_OVERRIDE_LEN 100
229
230static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN];
231
232acpi_status
233acpi_os_predefined_override (const struct acpi_predefined_names *init_val,
234 acpi_string *new_val)
235{
236 if (!init_val || !new_val)
237 return AE_BAD_PARAMETER;
238
239 *new_val = NULL;
240 if (!memcmp (init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
241 printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n",
242 acpi_os_name);
243 *new_val = acpi_os_name;
244 }
245
246 return AE_OK;
247}
248
249acpi_status
250acpi_os_table_override (struct acpi_table_header *existing_table,
251 struct acpi_table_header **new_table)
252{
253 if (!existing_table || !new_table)
254 return AE_BAD_PARAMETER;
255
256#ifdef CONFIG_ACPI_CUSTOM_DSDT
257 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
258 *new_table = (struct acpi_table_header*)AmlCode;
259 else
260 *new_table = NULL;
261#else
262 *new_table = NULL;
263#endif
264 return AE_OK;
265}
266
267static irqreturn_t
268acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
269{
270 return (*acpi_irq_handler)(acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
271}
272
273acpi_status
274acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, void *context)
275{
276 unsigned int irq;
277
278 /*
279 * Ignore the GSI from the core, and use the value in our copy of the
280 * FADT. It may not be the same if an interrupt source override exists
281 * for the SCI.
282 */
283 gsi = acpi_fadt.sci_int;
284 if (acpi_gsi_to_irq(gsi, &irq) < 0) {
285 printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n",
286 gsi);
287 return AE_OK;
288 }
289
290 acpi_irq_handler = handler;
291 acpi_irq_context = context;
292 if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", acpi_irq)) {
293 printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
294 return AE_NOT_ACQUIRED;
295 }
296 acpi_irq_irq = irq;
297
298 return AE_OK;
299}
300
301acpi_status
302acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
303{
304 if (irq) {
305 free_irq(irq, acpi_irq);
306 acpi_irq_handler = NULL;
307 acpi_irq_irq = 0;
308 }
309
310 return AE_OK;
311}
312
313/*
314 * Running in interpreter thread context, safe to sleep
315 */
316
317void
318acpi_os_sleep(acpi_integer ms)
319{
320 current->state = TASK_INTERRUPTIBLE;
321 schedule_timeout(((signed long) ms * HZ) / 1000);
322}
323EXPORT_SYMBOL(acpi_os_sleep);
324
325void
326acpi_os_stall(u32 us)
327{
328 while (us) {
329 u32 delay = 1000;
330
331 if (delay > us)
332 delay = us;
333 udelay(delay);
334 touch_nmi_watchdog();
335 us -= delay;
336 }
337}
338EXPORT_SYMBOL(acpi_os_stall);
339
340/*
341 * Support ACPI 3.0 AML Timer operand
342 * Returns 64-bit free-running, monotonically increasing timer
343 * with 100ns granularity
344 */
345u64
346acpi_os_get_timer (void)
347{
348 static u64 t;
349
350#ifdef CONFIG_HPET
351 /* TBD: use HPET if available */
352#endif
353
354#ifdef CONFIG_X86_PM_TIMER
355 /* TBD: default to PM timer if HPET was not available */
356#endif
357 if (!t)
358 printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n");
359
360 return ++t;
361}
362
363acpi_status
364acpi_os_read_port(
365 acpi_io_address port,
366 u32 *value,
367 u32 width)
368{
369 u32 dummy;
370
371 if (!value)
372 value = &dummy;
373
374 switch (width)
375 {
376 case 8:
377 *(u8*) value = inb(port);
378 break;
379 case 16:
380 *(u16*) value = inw(port);
381 break;
382 case 32:
383 *(u32*) value = inl(port);
384 break;
385 default:
386 BUG();
387 }
388
389 return AE_OK;
390}
391EXPORT_SYMBOL(acpi_os_read_port);
392
393acpi_status
394acpi_os_write_port(
395 acpi_io_address port,
396 u32 value,
397 u32 width)
398{
399 switch (width)
400 {
401 case 8:
402 outb(value, port);
403 break;
404 case 16:
405 outw(value, port);
406 break;
407 case 32:
408 outl(value, port);
409 break;
410 default:
411 BUG();
412 }
413
414 return AE_OK;
415}
416EXPORT_SYMBOL(acpi_os_write_port);
417
418acpi_status
419acpi_os_read_memory(
420 acpi_physical_address phys_addr,
421 u32 *value,
422 u32 width)
423{
424 u32 dummy;
425 void __iomem *virt_addr;
426 int iomem = 0;
427
428 if (efi_enabled) {
429 if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
430 /* HACK ALERT! We can use readb/w/l on real memory too.. */
431 virt_addr = (void __iomem *) phys_to_virt(phys_addr);
432 } else {
433 iomem = 1;
434 virt_addr = ioremap(phys_addr, width);
435 }
436 } else
437 virt_addr = (void __iomem *) phys_to_virt(phys_addr);
438 if (!value)
439 value = &dummy;
440
441 switch (width) {
442 case 8:
443 *(u8*) value = readb(virt_addr);
444 break;
445 case 16:
446 *(u16*) value = readw(virt_addr);
447 break;
448 case 32:
449 *(u32*) value = readl(virt_addr);
450 break;
451 default:
452 BUG();
453 }
454
455 if (efi_enabled) {
456 if (iomem)
457 iounmap(virt_addr);
458 }
459
460 return AE_OK;
461}
462
463acpi_status
464acpi_os_write_memory(
465 acpi_physical_address phys_addr,
466 u32 value,
467 u32 width)
468{
469 void __iomem *virt_addr;
470 int iomem = 0;
471
472 if (efi_enabled) {
473 if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
474 /* HACK ALERT! We can use writeb/w/l on real memory too */
475 virt_addr = (void __iomem *) phys_to_virt(phys_addr);
476 } else {
477 iomem = 1;
478 virt_addr = ioremap(phys_addr, width);
479 }
480 } else
481 virt_addr = (void __iomem *) phys_to_virt(phys_addr);
482
483 switch (width) {
484 case 8:
485 writeb(value, virt_addr);
486 break;
487 case 16:
488 writew(value, virt_addr);
489 break;
490 case 32:
491 writel(value, virt_addr);
492 break;
493 default:
494 BUG();
495 }
496
497 if (iomem)
498 iounmap(virt_addr);
499
500 return AE_OK;
501}
502
503#ifdef CONFIG_ACPI_PCI
504
505acpi_status
506acpi_os_read_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, void *value, u32 width)
507{
508 int result, size;
509
510 if (!value)
511 return AE_BAD_PARAMETER;
512
513 switch (width) {
514 case 8:
515 size = 1;
516 break;
517 case 16:
518 size = 2;
519 break;
520 case 32:
521 size = 4;
522 break;
523 default:
524 return AE_ERROR;
525 }
526
527 BUG_ON(!raw_pci_ops);
528
529 result = raw_pci_ops->read(pci_id->segment, pci_id->bus,
530 PCI_DEVFN(pci_id->device, pci_id->function),
531 reg, size, value);
532
533 return (result ? AE_ERROR : AE_OK);
534}
535EXPORT_SYMBOL(acpi_os_read_pci_configuration);
536
537acpi_status
538acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integer value, u32 width)
539{
540 int result, size;
541
542 switch (width) {
543 case 8:
544 size = 1;
545 break;
546 case 16:
547 size = 2;
548 break;
549 case 32:
550 size = 4;
551 break;
552 default:
553 return AE_ERROR;
554 }
555
556 BUG_ON(!raw_pci_ops);
557
558 result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
559 PCI_DEVFN(pci_id->device, pci_id->function),
560 reg, size, value);
561
562 return (result ? AE_ERROR : AE_OK);
563}
564
565/* TODO: Change code to take advantage of driver model more */
566static void
567acpi_os_derive_pci_id_2 (
568 acpi_handle rhandle, /* upper bound */
569 acpi_handle chandle, /* current node */
570 struct acpi_pci_id **id,
571 int *is_bridge,
572 u8 *bus_number)
573{
574 acpi_handle handle;
575 struct acpi_pci_id *pci_id = *id;
576 acpi_status status;
577 unsigned long temp;
578 acpi_object_type type;
579 u8 tu8;
580
581 acpi_get_parent(chandle, &handle);
582 if (handle != rhandle) {
583 acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge, bus_number);
584
585 status = acpi_get_type(handle, &type);
586 if ( (ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE) )
587 return;
588
589 status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &temp);
590 if (ACPI_SUCCESS(status)) {
591 pci_id->device = ACPI_HIWORD (ACPI_LODWORD (temp));
592 pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp));
593
594 if (*is_bridge)
595 pci_id->bus = *bus_number;
596
597 /* any nicer way to get bus number of bridge ? */
598 status = acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8, 8);
599 if (ACPI_SUCCESS(status) &&
600 ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) {
601 status = acpi_os_read_pci_configuration(pci_id, 0x18, &tu8, 8);
602 if (!ACPI_SUCCESS(status)) {
603 /* Certainly broken... FIX ME */
604 return;
605 }
606 *is_bridge = 1;
607 pci_id->bus = tu8;
608 status = acpi_os_read_pci_configuration(pci_id, 0x19, &tu8, 8);
609 if (ACPI_SUCCESS(status)) {
610 *bus_number = tu8;
611 }
612 } else
613 *is_bridge = 0;
614 }
615 }
616}
617
618void
619acpi_os_derive_pci_id (
620 acpi_handle rhandle, /* upper bound */
621 acpi_handle chandle, /* current node */
622 struct acpi_pci_id **id)
623{
624 int is_bridge = 1;
625 u8 bus_number = (*id)->bus;
626
627 acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
628}
629
630#else /*!CONFIG_ACPI_PCI*/
631
632acpi_status
633acpi_os_write_pci_configuration (
634 struct acpi_pci_id *pci_id,
635 u32 reg,
636 acpi_integer value,
637 u32 width)
638{
639 return AE_SUPPORT;
640}
641
642acpi_status
643acpi_os_read_pci_configuration (
644 struct acpi_pci_id *pci_id,
645 u32 reg,
646 void *value,
647 u32 width)
648{
649 return AE_SUPPORT;
650}
651
652void
653acpi_os_derive_pci_id (
654 acpi_handle rhandle, /* upper bound */
655 acpi_handle chandle, /* current node */
656 struct acpi_pci_id **id)
657{
658}
659
660#endif /*CONFIG_ACPI_PCI*/
661
662static void
663acpi_os_execute_deferred (
664 void *context)
665{
666 struct acpi_os_dpc *dpc = NULL;
667
668 ACPI_FUNCTION_TRACE ("os_execute_deferred");
669
670 dpc = (struct acpi_os_dpc *) context;
671 if (!dpc) {
672 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
673 return_VOID;
674 }
675
676 dpc->function(dpc->context);
677
678 kfree(dpc);
679
680 return_VOID;
681}
682
683acpi_status
684acpi_os_queue_for_execution(
685 u32 priority,
686 acpi_osd_exec_callback function,
687 void *context)
688{
689 acpi_status status = AE_OK;
690 struct acpi_os_dpc *dpc;
691 struct work_struct *task;
692
693 ACPI_FUNCTION_TRACE ("os_queue_for_execution");
694
695 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context));
696
697 if (!function)
698 return_ACPI_STATUS (AE_BAD_PARAMETER);
699
700 /*
701 * Allocate/initialize DPC structure. Note that this memory will be
702 * freed by the callee. The kernel handles the tq_struct list in a
703 * way that allows us to also free its memory inside the callee.
704 * Because we may want to schedule several tasks with different
705 * parameters we can't use the approach some kernel code uses of
706 * having a static tq_struct.
707 * We can save time and code by allocating the DPC and tq_structs
708 * from the same memory.
709 */
710
711 dpc = kmalloc(sizeof(struct acpi_os_dpc)+sizeof(struct work_struct), GFP_ATOMIC);
712 if (!dpc)
713 return_ACPI_STATUS (AE_NO_MEMORY);
714
715 dpc->function = function;
716 dpc->context = context;
717
718 task = (void *)(dpc+1);
719 INIT_WORK(task, acpi_os_execute_deferred, (void*)dpc);
720
721 if (!queue_work(kacpid_wq, task)) {
722 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to queue_work() failed.\n"));
723 kfree(dpc);
724 status = AE_ERROR;
725 }
726
727 return_ACPI_STATUS (status);
728}
729EXPORT_SYMBOL(acpi_os_queue_for_execution);
730
731void
732acpi_os_wait_events_complete(
733 void *context)
734{
735 flush_workqueue(kacpid_wq);
736}
737EXPORT_SYMBOL(acpi_os_wait_events_complete);
738
739/*
740 * Allocate the memory for a spinlock and initialize it.
741 */
742acpi_status
743acpi_os_create_lock (
744 acpi_handle *out_handle)
745{
746 spinlock_t *lock_ptr;
747
748 ACPI_FUNCTION_TRACE ("os_create_lock");
749
750 lock_ptr = acpi_os_allocate(sizeof(spinlock_t));
751
752 spin_lock_init(lock_ptr);
753
754 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating spinlock[%p].\n", lock_ptr));
755
756 *out_handle = lock_ptr;
757
758 return_ACPI_STATUS (AE_OK);
759}
760
761
762/*
763 * Deallocate the memory for a spinlock.
764 */
765void
766acpi_os_delete_lock (
767 acpi_handle handle)
768{
769 ACPI_FUNCTION_TRACE ("os_create_lock");
770
771 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting spinlock[%p].\n", handle));
772
773 acpi_os_free(handle);
774
775 return_VOID;
776}
777
778/*
779 * Acquire a spinlock.
780 *
781 * handle is a pointer to the spinlock_t.
782 * flags is *not* the result of save_flags - it is an ACPI-specific flag variable
783 * that indicates whether we are at interrupt level.
784 */
785void
786acpi_os_acquire_lock (
787 acpi_handle handle,
788 u32 flags)
789{
790 ACPI_FUNCTION_TRACE ("os_acquire_lock");
791
792 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquiring spinlock[%p] from %s level\n", handle,
793 ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt")));
794
795 if (flags & ACPI_NOT_ISR)
796 ACPI_DISABLE_IRQS();
797
798 spin_lock((spinlock_t *)handle);
799
800 return_VOID;
801}
802
803
804/*
805 * Release a spinlock. See above.
806 */
807void
808acpi_os_release_lock (
809 acpi_handle handle,
810 u32 flags)
811{
812 ACPI_FUNCTION_TRACE ("os_release_lock");
813
814 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Releasing spinlock[%p] from %s level\n", handle,
815 ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt")));
816
817 spin_unlock((spinlock_t *)handle);
818
819 if (flags & ACPI_NOT_ISR)
820 ACPI_ENABLE_IRQS();
821
822 return_VOID;
823}
824
825
826acpi_status
827acpi_os_create_semaphore(
828 u32 max_units,
829 u32 initial_units,
830 acpi_handle *handle)
831{
832 struct semaphore *sem = NULL;
833
834 ACPI_FUNCTION_TRACE ("os_create_semaphore");
835
836 sem = acpi_os_allocate(sizeof(struct semaphore));
837 if (!sem)
838 return_ACPI_STATUS (AE_NO_MEMORY);
839 memset(sem, 0, sizeof(struct semaphore));
840
841 sema_init(sem, initial_units);
842
843 *handle = (acpi_handle*)sem;
844
845 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n", *handle, initial_units));
846
847 return_ACPI_STATUS (AE_OK);
848}
849EXPORT_SYMBOL(acpi_os_create_semaphore);
850
851
852/*
853 * TODO: A better way to delete semaphores? Linux doesn't have a
854 * 'delete_semaphore()' function -- may result in an invalid
855 * pointer dereference for non-synchronized consumers. Should
856 * we at least check for blocked threads and signal/cancel them?
857 */
858
859acpi_status
860acpi_os_delete_semaphore(
861 acpi_handle handle)
862{
863 struct semaphore *sem = (struct semaphore*) handle;
864
865 ACPI_FUNCTION_TRACE ("os_delete_semaphore");
866
867 if (!sem)
868 return_ACPI_STATUS (AE_BAD_PARAMETER);
869
870 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
871
872 acpi_os_free(sem); sem = NULL;
873
874 return_ACPI_STATUS (AE_OK);
875}
876EXPORT_SYMBOL(acpi_os_delete_semaphore);
877
878
879/*
880 * TODO: The kernel doesn't have a 'down_timeout' function -- had to
881 * improvise. The process is to sleep for one scheduler quantum
882 * until the semaphore becomes available. Downside is that this
883 * may result in starvation for timeout-based waits when there's
884 * lots of semaphore activity.
885 *
886 * TODO: Support for units > 1?
887 */
888acpi_status
889acpi_os_wait_semaphore(
890 acpi_handle handle,
891 u32 units,
892 u16 timeout)
893{
894 acpi_status status = AE_OK;
895 struct semaphore *sem = (struct semaphore*)handle;
896 int ret = 0;
897
898 ACPI_FUNCTION_TRACE ("os_wait_semaphore");
899
900 if (!sem || (units < 1))
901 return_ACPI_STATUS (AE_BAD_PARAMETER);
902
903 if (units > 1)
904 return_ACPI_STATUS (AE_SUPPORT);
905
906 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout));
907
908 if (in_atomic())
909 timeout = 0;
910
911 switch (timeout)
912 {
913 /*
914 * No Wait:
915 * --------
916 * A zero timeout value indicates that we shouldn't wait - just
917 * acquire the semaphore if available otherwise return AE_TIME
918 * (a.k.a. 'would block').
919 */
920 case 0:
921 if(down_trylock(sem))
922 status = AE_TIME;
923 break;
924
925 /*
926 * Wait Indefinitely:
927 * ------------------
928 */
929 case ACPI_WAIT_FOREVER:
930 down(sem);
931 break;
932
933 /*
934 * Wait w/ Timeout:
935 * ----------------
936 */
937 default:
938 // TODO: A better timeout algorithm?
939 {
940 int i = 0;
941 static const int quantum_ms = 1000/HZ;
942
943 ret = down_trylock(sem);
944 for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) {
945 current->state = TASK_INTERRUPTIBLE;
946 schedule_timeout(1);
947 ret = down_trylock(sem);
948 }
949
950 if (ret != 0)
951 status = AE_TIME;
952 }
953 break;
954 }
955
956 if (ACPI_FAILURE(status)) {
957 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Failed to acquire semaphore[%p|%d|%d], %s\n",
958 handle, units, timeout, acpi_format_exception(status)));
959 }
960 else {
961 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout));
962 }
963
964 return_ACPI_STATUS (status);
965}
966EXPORT_SYMBOL(acpi_os_wait_semaphore);
967
968
969/*
970 * TODO: Support for units > 1?
971 */
972acpi_status
973acpi_os_signal_semaphore(
974 acpi_handle handle,
975 u32 units)
976{
977 struct semaphore *sem = (struct semaphore *) handle;
978
979 ACPI_FUNCTION_TRACE ("os_signal_semaphore");
980
981 if (!sem || (units < 1))
982 return_ACPI_STATUS (AE_BAD_PARAMETER);
983
984 if (units > 1)
985 return_ACPI_STATUS (AE_SUPPORT);
986
987 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle, units));
988
989 up(sem);
990
991 return_ACPI_STATUS (AE_OK);
992}
993EXPORT_SYMBOL(acpi_os_signal_semaphore);
994
995#ifdef ACPI_FUTURE_USAGE
996u32
997acpi_os_get_line(char *buffer)
998{
999
1000#ifdef ENABLE_DEBUGGER
1001 if (acpi_in_debugger) {
1002 u32 chars;
1003
1004 kdb_read(buffer, sizeof(line_buf));
1005
1006 /* remove the CR kdb includes */
1007 chars = strlen(buffer) - 1;
1008 buffer[chars] = '\0';
1009 }
1010#endif
1011
1012 return 0;
1013}
1014#endif /* ACPI_FUTURE_USAGE */
1015
1016/* Assumes no unreadable holes inbetween */
1017u8
1018acpi_os_readable(void *ptr, acpi_size len)
1019{
1020#if defined(__i386__) || defined(__x86_64__)
1021 char tmp;
1022 return !__get_user(tmp, (char __user *)ptr) && !__get_user(tmp, (char __user *)ptr + len - 1);
1023#endif
1024 return 1;
1025}
1026
1027#ifdef ACPI_FUTURE_USAGE
1028u8
1029acpi_os_writable(void *ptr, acpi_size len)
1030{
1031 /* could do dummy write (racy) or a kernel page table lookup.
1032 The later may be difficult at early boot when kmap doesn't work yet. */
1033 return 1;
1034}
1035#endif
1036
1037u32
1038acpi_os_get_thread_id (void)
1039{
1040 if (!in_atomic())
1041 return current->pid;
1042
1043 return 0;
1044}
1045
1046acpi_status
1047acpi_os_signal (
1048 u32 function,
1049 void *info)
1050{
1051 switch (function)
1052 {
1053 case ACPI_SIGNAL_FATAL:
1054 printk(KERN_ERR PREFIX "Fatal opcode executed\n");
1055 break;
1056 case ACPI_SIGNAL_BREAKPOINT:
1057 /*
1058 * AML Breakpoint
1059 * ACPI spec. says to treat it as a NOP unless
1060 * you are debugging. So if/when we integrate
1061 * AML debugger into the kernel debugger its
1062 * hook will go here. But until then it is
1063 * not useful to print anything on breakpoints.
1064 */
1065 break;
1066 default:
1067 break;
1068 }
1069
1070 return AE_OK;
1071}
1072EXPORT_SYMBOL(acpi_os_signal);
1073
1074static int __init
1075acpi_os_name_setup(char *str)
1076{
1077 char *p = acpi_os_name;
1078 int count = ACPI_MAX_OVERRIDE_LEN-1;
1079
1080 if (!str || !*str)
1081 return 0;
1082
1083 for (; count-- && str && *str; str++) {
1084 if (isalnum(*str) || *str == ' ' || *str == ':')
1085 *p++ = *str;
1086 else if (*str == '\'' || *str == '"')
1087 continue;
1088 else
1089 break;
1090 }
1091 *p = 0;
1092
1093 return 1;
1094
1095}
1096
1097__setup("acpi_os_name=", acpi_os_name_setup);
1098
1099/*
1100 * _OSI control
1101 * empty string disables _OSI
1102 * TBD additional string adds to _OSI
1103 */
1104static int __init
1105acpi_osi_setup(char *str)
1106{
1107 if (str == NULL || *str == '\0') {
1108 printk(KERN_INFO PREFIX "_OSI method disabled\n");
1109 acpi_gbl_create_osi_method = FALSE;
1110 } else
1111 {
1112 /* TBD */
1113 printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n", str);
1114 }
1115
1116 return 1;
1117}
1118
1119__setup("acpi_osi=", acpi_osi_setup);
1120
1121/* enable serialization to combat AE_ALREADY_EXISTS errors */
1122static int __init
1123acpi_serialize_setup(char *str)
1124{
1125 printk(KERN_INFO PREFIX "serialize enabled\n");
1126
1127 acpi_gbl_all_methods_serialized = TRUE;
1128
1129 return 1;
1130}
1131
1132__setup("acpi_serialize", acpi_serialize_setup);
1133
1134/*
1135 * Wake and Run-Time GPES are expected to be separate.
1136 * We disable wake-GPEs at run-time to prevent spurious
1137 * interrupts.
1138 *
1139 * However, if a system exists that shares Wake and
1140 * Run-time events on the same GPE this flag is available
1141 * to tell Linux to keep the wake-time GPEs enabled at run-time.
1142 */
1143static int __init
1144acpi_wake_gpes_always_on_setup(char *str)
1145{
1146 printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
1147
1148 acpi_gbl_leave_wake_gpes_disabled = FALSE;
1149
1150 return 1;
1151}
1152
1153__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
1154
1155/*
1156 * max_cstate is defined in the base kernel so modules can
1157 * change it w/o depending on the state of the processor module.
1158 */
1159unsigned int max_cstate = ACPI_PROCESSOR_MAX_POWER;
1160
1161
1162EXPORT_SYMBOL(max_cstate);
diff --git a/drivers/acpi/parser/Makefile b/drivers/acpi/parser/Makefile
new file mode 100644
index 000000000000..bbdd286c660d
--- /dev/null
+++ b/drivers/acpi/parser/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for all Linux ACPI interpreter subdirectories
3#
4
5obj-y := psargs.o psparse.o pstree.o pswalk.o \
6 psopcode.o psscope.o psutils.o psxface.o
7
8EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
new file mode 100644
index 000000000000..b5d98895f6a8
--- /dev/null
+++ b/drivers/acpi/parser/psargs.c
@@ -0,0 +1,746 @@
1/******************************************************************************
2 *
3 * Module Name: psargs - Parse AML opcode arguments
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/amlcode.h>
48#include <acpi/acnamesp.h>
49
50#define _COMPONENT ACPI_PARSER
51 ACPI_MODULE_NAME ("psargs")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ps_get_next_package_length
57 *
58 * PARAMETERS: parser_state - Current parser state object
59 *
60 * RETURN: Decoded package length. On completion, the AML pointer points
61 * past the length byte or bytes.
62 *
63 * DESCRIPTION: Decode and return a package length field
64 *
65 ******************************************************************************/
66
67u32
68acpi_ps_get_next_package_length (
69 struct acpi_parse_state *parser_state)
70{
71 u32 encoded_length;
72 u32 length = 0;
73
74
75 ACPI_FUNCTION_TRACE ("ps_get_next_package_length");
76
77
78 encoded_length = (u32) ACPI_GET8 (parser_state->aml);
79 parser_state->aml++;
80
81
82 switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ {
83 case 0: /* 1-byte encoding (bits 0-5) */
84
85 length = (encoded_length & 0x3F);
86 break;
87
88
89 case 1: /* 2-byte encoding (next byte + bits 0-3) */
90
91 length = ((ACPI_GET8 (parser_state->aml) << 04) |
92 (encoded_length & 0x0F));
93 parser_state->aml++;
94 break;
95
96
97 case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */
98
99 length = ((ACPI_GET8 (parser_state->aml + 1) << 12) |
100 (ACPI_GET8 (parser_state->aml) << 04) |
101 (encoded_length & 0x0F));
102 parser_state->aml += 2;
103 break;
104
105
106 case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */
107
108 length = ((ACPI_GET8 (parser_state->aml + 2) << 20) |
109 (ACPI_GET8 (parser_state->aml + 1) << 12) |
110 (ACPI_GET8 (parser_state->aml) << 04) |
111 (encoded_length & 0x0F));
112 parser_state->aml += 3;
113 break;
114
115 default:
116
117 /* Can't get here, only 2 bits / 4 cases */
118 break;
119 }
120
121 return_VALUE (length);
122}
123
124
125/*******************************************************************************
126 *
127 * FUNCTION: acpi_ps_get_next_package_end
128 *
129 * PARAMETERS: parser_state - Current parser state object
130 *
131 * RETURN: Pointer to end-of-package +1
132 *
133 * DESCRIPTION: Get next package length and return a pointer past the end of
134 * the package. Consumes the package length field
135 *
136 ******************************************************************************/
137
138u8 *
139acpi_ps_get_next_package_end (
140 struct acpi_parse_state *parser_state)
141{
142 u8 *start = parser_state->aml;
143 acpi_native_uint length;
144
145
146 ACPI_FUNCTION_TRACE ("ps_get_next_package_end");
147
148
149 /* Function below changes parser_state->Aml */
150
151 length = (acpi_native_uint) acpi_ps_get_next_package_length (parser_state);
152
153 return_PTR (start + length); /* end of package */
154}
155
156
157/*******************************************************************************
158 *
159 * FUNCTION: acpi_ps_get_next_namestring
160 *
161 * PARAMETERS: parser_state - Current parser state object
162 *
163 * RETURN: Pointer to the start of the name string (pointer points into
164 * the AML.
165 *
166 * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name
167 * prefix characters. Set parser state to point past the string.
168 * (Name is consumed from the AML.)
169 *
170 ******************************************************************************/
171
172char *
173acpi_ps_get_next_namestring (
174 struct acpi_parse_state *parser_state)
175{
176 u8 *start = parser_state->aml;
177 u8 *end = parser_state->aml;
178
179
180 ACPI_FUNCTION_TRACE ("ps_get_next_namestring");
181
182
183 /* Handle multiple prefix characters */
184
185 while (acpi_ps_is_prefix_char (ACPI_GET8 (end))) {
186 /* Include prefix '\\' or '^' */
187
188 end++;
189 }
190
191 /* Decode the path */
192
193 switch (ACPI_GET8 (end)) {
194 case 0:
195
196 /* null_name */
197
198 if (end == start) {
199 start = NULL;
200 }
201 end++;
202 break;
203
204 case AML_DUAL_NAME_PREFIX:
205
206 /* Two name segments */
207
208 end += 1 + (2 * ACPI_NAME_SIZE);
209 break;
210
211 case AML_MULTI_NAME_PREFIX_OP:
212
213 /* Multiple name segments, 4 chars each */
214
215 end += 2 + ((acpi_size) ACPI_GET8 (end + 1) * ACPI_NAME_SIZE);
216 break;
217
218 default:
219
220 /* Single name segment */
221
222 end += ACPI_NAME_SIZE;
223 break;
224 }
225
226 parser_state->aml = (u8*) end;
227 return_PTR ((char *) start);
228}
229
230
231/*******************************************************************************
232 *
233 * FUNCTION: acpi_ps_get_next_namepath
234 *
235 * PARAMETERS: parser_state - Current parser state object
236 * Arg - Where the namepath will be stored
237 * arg_count - If the namepath points to a control method
238 * the method's argument is returned here.
239 * method_call - Whether the namepath can possibly be the
240 * start of a method call
241 *
242 * RETURN: Status
243 *
244 * DESCRIPTION: Get next name (if method call, return # of required args).
245 * Names are looked up in the internal namespace to determine
246 * if the name represents a control method. If a method
247 * is found, the number of arguments to the method is returned.
248 * This information is critical for parsing to continue correctly.
249 *
250 ******************************************************************************/
251
252acpi_status
253acpi_ps_get_next_namepath (
254 struct acpi_walk_state *walk_state,
255 struct acpi_parse_state *parser_state,
256 union acpi_parse_object *arg,
257 u8 method_call)
258{
259 char *path;
260 union acpi_parse_object *name_op;
261 acpi_status status = AE_OK;
262 union acpi_operand_object *method_desc;
263 struct acpi_namespace_node *node;
264 union acpi_generic_state scope_info;
265
266
267 ACPI_FUNCTION_TRACE ("ps_get_next_namepath");
268
269
270 path = acpi_ps_get_next_namestring (parser_state);
271
272 /* Null path case is allowed */
273
274 if (path) {
275 /*
276 * Lookup the name in the internal namespace
277 */
278 scope_info.scope.node = NULL;
279 node = parser_state->start_node;
280 if (node) {
281 scope_info.scope.node = node;
282 }
283
284 /*
285 * Lookup object. We don't want to add anything new to the namespace
286 * here, however. So we use MODE_EXECUTE. Allow searching of the
287 * parent tree, but don't open a new scope -- we just want to lookup the
288 * object (MUST BE mode EXECUTE to perform upsearch)
289 */
290 status = acpi_ns_lookup (&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
291 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &node);
292 if (ACPI_SUCCESS (status) && method_call) {
293 if (node->type == ACPI_TYPE_METHOD) {
294 /*
295 * This name is actually a control method invocation
296 */
297 method_desc = acpi_ns_get_attached_object (node);
298 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
299 "Control Method - %p Desc %p Path=%p\n",
300 node, method_desc, path));
301
302 name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
303 if (!name_op) {
304 return_ACPI_STATUS (AE_NO_MEMORY);
305 }
306
307 /* Change arg into a METHOD CALL and attach name to it */
308
309 acpi_ps_init_op (arg, AML_INT_METHODCALL_OP);
310 name_op->common.value.name = path;
311
312 /* Point METHODCALL/NAME to the METHOD Node */
313
314 name_op->common.node = node;
315 acpi_ps_append_arg (arg, name_op);
316
317 if (!method_desc) {
318 ACPI_REPORT_ERROR ((
319 "ps_get_next_namepath: Control Method %p has no attached object\n",
320 node));
321 return_ACPI_STATUS (AE_AML_INTERNAL);
322 }
323
324 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
325 "Control Method - %p Args %X\n",
326 node, method_desc->method.param_count));
327
328 /* Get the number of arguments to expect */
329
330 walk_state->arg_count = method_desc->method.param_count;
331 return_ACPI_STATUS (AE_OK);
332 }
333
334 /*
335 * Else this is normal named object reference.
336 * Just init the NAMEPATH object with the pathname.
337 * (See code below)
338 */
339 }
340
341 if (ACPI_FAILURE (status)) {
342 /*
343 * 1) Any error other than NOT_FOUND is always severe
344 * 2) NOT_FOUND is only important if we are executing a method.
345 * 3) If executing a cond_ref_of opcode, NOT_FOUND is ok.
346 */
347 if ((((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) &&
348 (status == AE_NOT_FOUND) &&
349 (walk_state->op->common.aml_opcode != AML_COND_REF_OF_OP)) ||
350
351 (status != AE_NOT_FOUND)) {
352 ACPI_REPORT_NSERROR (path, status);
353
354 acpi_os_printf ("search_node %p start_node %p return_node %p\n",
355 scope_info.scope.node, parser_state->start_node, node);
356
357
358 }
359 else {
360 /*
361 * We got a NOT_FOUND during table load or we encountered
362 * a cond_ref_of(x) where the target does not exist.
363 * -- either case is ok
364 */
365 status = AE_OK;
366 }
367 }
368 }
369
370 /*
371 * Regardless of success/failure above,
372 * Just initialize the Op with the pathname.
373 */
374 acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
375 arg->common.value.name = path;
376
377 return_ACPI_STATUS (status);
378}
379
380
381/*******************************************************************************
382 *
383 * FUNCTION: acpi_ps_get_next_simple_arg
384 *
385 * PARAMETERS: parser_state - Current parser state object
386 * arg_type - The argument type (AML_*_ARG)
387 * Arg - Where the argument is returned
388 *
389 * RETURN: None
390 *
391 * DESCRIPTION: Get the next simple argument (constant, string, or namestring)
392 *
393 ******************************************************************************/
394
395void
396acpi_ps_get_next_simple_arg (
397 struct acpi_parse_state *parser_state,
398 u32 arg_type,
399 union acpi_parse_object *arg)
400{
401
402 ACPI_FUNCTION_TRACE_U32 ("ps_get_next_simple_arg", arg_type);
403
404
405 switch (arg_type) {
406 case ARGP_BYTEDATA:
407
408 acpi_ps_init_op (arg, AML_BYTE_OP);
409 arg->common.value.integer = (u32) ACPI_GET8 (parser_state->aml);
410 parser_state->aml++;
411 break;
412
413
414 case ARGP_WORDDATA:
415
416 acpi_ps_init_op (arg, AML_WORD_OP);
417
418 /* Get 2 bytes from the AML stream */
419
420 ACPI_MOVE_16_TO_32 (&arg->common.value.integer, parser_state->aml);
421 parser_state->aml += 2;
422 break;
423
424
425 case ARGP_DWORDDATA:
426
427 acpi_ps_init_op (arg, AML_DWORD_OP);
428
429 /* Get 4 bytes from the AML stream */
430
431 ACPI_MOVE_32_TO_32 (&arg->common.value.integer, parser_state->aml);
432 parser_state->aml += 4;
433 break;
434
435
436 case ARGP_QWORDDATA:
437
438 acpi_ps_init_op (arg, AML_QWORD_OP);
439
440 /* Get 8 bytes from the AML stream */
441
442 ACPI_MOVE_64_TO_64 (&arg->common.value.integer, parser_state->aml);
443 parser_state->aml += 8;
444 break;
445
446
447 case ARGP_CHARLIST:
448
449 acpi_ps_init_op (arg, AML_STRING_OP);
450 arg->common.value.string = (char *) parser_state->aml;
451
452 while (ACPI_GET8 (parser_state->aml) != '\0') {
453 parser_state->aml++;
454 }
455 parser_state->aml++;
456 break;
457
458
459 case ARGP_NAME:
460 case ARGP_NAMESTRING:
461
462 acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
463 arg->common.value.name = acpi_ps_get_next_namestring (parser_state);
464 break;
465
466
467 default:
468
469 ACPI_REPORT_ERROR (("Invalid arg_type %X\n", arg_type));
470 break;
471 }
472
473 return_VOID;
474}
475
476
477/*******************************************************************************
478 *
479 * FUNCTION: acpi_ps_get_next_field
480 *
481 * PARAMETERS: parser_state - Current parser state object
482 *
483 * RETURN: A newly allocated FIELD op
484 *
485 * DESCRIPTION: Get next field (named_field, reserved_field, or access_field)
486 *
487 ******************************************************************************/
488
489union acpi_parse_object *
490acpi_ps_get_next_field (
491 struct acpi_parse_state *parser_state)
492{
493 u32 aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml,
494 parser_state->aml_start);
495 union acpi_parse_object *field;
496 u16 opcode;
497 u32 name;
498
499
500 ACPI_FUNCTION_TRACE ("ps_get_next_field");
501
502
503 /* determine field type */
504
505 switch (ACPI_GET8 (parser_state->aml)) {
506 default:
507
508 opcode = AML_INT_NAMEDFIELD_OP;
509 break;
510
511 case 0x00:
512
513 opcode = AML_INT_RESERVEDFIELD_OP;
514 parser_state->aml++;
515 break;
516
517 case 0x01:
518
519 opcode = AML_INT_ACCESSFIELD_OP;
520 parser_state->aml++;
521 break;
522 }
523
524
525 /* Allocate a new field op */
526
527 field = acpi_ps_alloc_op (opcode);
528 if (!field) {
529 return_PTR (NULL);
530 }
531
532 field->common.aml_offset = aml_offset;
533
534 /* Decode the field type */
535
536 switch (opcode) {
537 case AML_INT_NAMEDFIELD_OP:
538
539 /* Get the 4-character name */
540
541 ACPI_MOVE_32_TO_32 (&name, parser_state->aml);
542 acpi_ps_set_name (field, name);
543 parser_state->aml += ACPI_NAME_SIZE;
544
545 /* Get the length which is encoded as a package length */
546
547 field->common.value.size = acpi_ps_get_next_package_length (parser_state);
548 break;
549
550
551 case AML_INT_RESERVEDFIELD_OP:
552
553 /* Get the length which is encoded as a package length */
554
555 field->common.value.size = acpi_ps_get_next_package_length (parser_state);
556 break;
557
558
559 case AML_INT_ACCESSFIELD_OP:
560
561 /*
562 * Get access_type and access_attrib and merge into the field Op
563 * access_type is first operand, access_attribute is second
564 */
565 field->common.value.integer = (ACPI_GET8 (parser_state->aml) << 8);
566 parser_state->aml++;
567 field->common.value.integer |= ACPI_GET8 (parser_state->aml);
568 parser_state->aml++;
569 break;
570
571 default:
572
573 /* Opcode was set in previous switch */
574 break;
575 }
576
577 return_PTR (field);
578}
579
580
581/*******************************************************************************
582 *
583 * FUNCTION: acpi_ps_get_next_arg
584 *
585 * PARAMETERS: parser_state - Current parser state object
586 * arg_type - The argument type (AML_*_ARG)
587 * arg_count - If the argument points to a control method
588 * the method's argument is returned here.
589 *
590 * RETURN: Status, and an op object containing the next argument.
591 *
592 * DESCRIPTION: Get next argument (including complex list arguments that require
593 * pushing the parser stack)
594 *
595 ******************************************************************************/
596
597acpi_status
598acpi_ps_get_next_arg (
599 struct acpi_walk_state *walk_state,
600 struct acpi_parse_state *parser_state,
601 u32 arg_type,
602 union acpi_parse_object **return_arg)
603{
604 union acpi_parse_object *arg = NULL;
605 union acpi_parse_object *prev = NULL;
606 union acpi_parse_object *field;
607 u32 subop;
608 acpi_status status = AE_OK;
609
610
611 ACPI_FUNCTION_TRACE_PTR ("ps_get_next_arg", parser_state);
612
613
614 switch (arg_type) {
615 case ARGP_BYTEDATA:
616 case ARGP_WORDDATA:
617 case ARGP_DWORDDATA:
618 case ARGP_CHARLIST:
619 case ARGP_NAME:
620 case ARGP_NAMESTRING:
621
622 /* constants, strings, and namestrings are all the same size */
623
624 arg = acpi_ps_alloc_op (AML_BYTE_OP);
625 if (!arg) {
626 return_ACPI_STATUS (AE_NO_MEMORY);
627 }
628 acpi_ps_get_next_simple_arg (parser_state, arg_type, arg);
629 break;
630
631
632 case ARGP_PKGLENGTH:
633
634 /* Package length, nothing returned */
635
636 parser_state->pkg_end = acpi_ps_get_next_package_end (parser_state);
637 break;
638
639
640 case ARGP_FIELDLIST:
641
642 if (parser_state->aml < parser_state->pkg_end) {
643 /* Non-empty list */
644
645 while (parser_state->aml < parser_state->pkg_end) {
646 field = acpi_ps_get_next_field (parser_state);
647 if (!field) {
648 return_ACPI_STATUS (AE_NO_MEMORY);
649 }
650
651 if (prev) {
652 prev->common.next = field;
653 }
654 else {
655 arg = field;
656 }
657
658 prev = field;
659 }
660
661 /* Skip to End of byte data */
662
663 parser_state->aml = parser_state->pkg_end;
664 }
665 break;
666
667
668 case ARGP_BYTELIST:
669
670 if (parser_state->aml < parser_state->pkg_end) {
671 /* Non-empty list */
672
673 arg = acpi_ps_alloc_op (AML_INT_BYTELIST_OP);
674 if (!arg) {
675 return_ACPI_STATUS (AE_NO_MEMORY);
676 }
677
678 /* Fill in bytelist data */
679
680 arg->common.value.size = (u32) ACPI_PTR_DIFF (parser_state->pkg_end,
681 parser_state->aml);
682 arg->named.data = parser_state->aml;
683
684 /* Skip to End of byte data */
685
686 parser_state->aml = parser_state->pkg_end;
687 }
688 break;
689
690
691 case ARGP_TARGET:
692 case ARGP_SUPERNAME:
693 case ARGP_SIMPLENAME:
694
695 subop = acpi_ps_peek_opcode (parser_state);
696 if (subop == 0 ||
697 acpi_ps_is_leading_char (subop) ||
698 acpi_ps_is_prefix_char (subop)) {
699 /* null_name or name_string */
700
701 arg = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
702 if (!arg) {
703 return_ACPI_STATUS (AE_NO_MEMORY);
704 }
705
706 status = acpi_ps_get_next_namepath (walk_state, parser_state, arg, 0);
707 }
708 else {
709 /* single complex argument, nothing returned */
710
711 walk_state->arg_count = 1;
712 }
713 break;
714
715
716 case ARGP_DATAOBJ:
717 case ARGP_TERMARG:
718
719 /* single complex argument, nothing returned */
720
721 walk_state->arg_count = 1;
722 break;
723
724
725 case ARGP_DATAOBJLIST:
726 case ARGP_TERMLIST:
727 case ARGP_OBJLIST:
728
729 if (parser_state->aml < parser_state->pkg_end) {
730 /* non-empty list of variable arguments, nothing returned */
731
732 walk_state->arg_count = ACPI_VAR_ARGS;
733 }
734 break;
735
736
737 default:
738
739 ACPI_REPORT_ERROR (("Invalid arg_type: %X\n", arg_type));
740 status = AE_AML_OPERAND_TYPE;
741 break;
742 }
743
744 *return_arg = arg;
745 return_ACPI_STATUS (status);
746}
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
new file mode 100644
index 000000000000..03e33fedc11a
--- /dev/null
+++ b/drivers/acpi/parser/psopcode.c
@@ -0,0 +1,778 @@
1/******************************************************************************
2 *
3 * Module Name: psopcode - Parser/Interpreter opcode information table
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/amlcode.h>
48
49
50#define _COMPONENT ACPI_PARSER
51 ACPI_MODULE_NAME ("psopcode")
52
53
54#define _UNK 0x6B
55/*
56 * Reserved ASCII characters. Do not use any of these for
57 * internal opcodes, since they are used to differentiate
58 * name strings from AML opcodes
59 */
60#define _ASC 0x6C
61#define _NAM 0x6C
62#define _PFX 0x6D
63#define _UNKNOWN_OPCODE 0x02 /* An example unknown opcode */
64
65#define MAX_EXTENDED_OPCODE 0x88
66#define NUM_EXTENDED_OPCODE (MAX_EXTENDED_OPCODE + 1)
67#define MAX_INTERNAL_OPCODE
68#define NUM_INTERNAL_OPCODE (MAX_INTERNAL_OPCODE + 1)
69
70
71/*******************************************************************************
72 *
73 * NAME: acpi_gbl_aml_op_info
74 *
75 * DESCRIPTION: Opcode table. Each entry contains <opcode, type, name, operands>
76 * The name is a simple ascii string, the operand specifier is an
77 * ascii string with one letter per operand. The letter specifies
78 * the operand type.
79 *
80 ******************************************************************************/
81
82
83/*
84 * All AML opcodes and the parse-time arguments for each. Used by the AML parser Each list is compressed
85 * into a 32-bit number and stored in the master opcode table at the end of this file.
86 */
87
88
89#define ARGP_ACCESSFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
90#define ARGP_ACQUIRE_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_WORDDATA)
91#define ARGP_ADD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
92#define ARGP_ALIAS_OP ARGP_LIST2 (ARGP_NAMESTRING, ARGP_NAME)
93#define ARGP_ARG0 ARG_NONE
94#define ARGP_ARG1 ARG_NONE
95#define ARGP_ARG2 ARG_NONE
96#define ARGP_ARG3 ARG_NONE
97#define ARGP_ARG4 ARG_NONE
98#define ARGP_ARG5 ARG_NONE
99#define ARGP_ARG6 ARG_NONE
100#define ARGP_BANK_FIELD_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_TERMARG, ARGP_BYTEDATA, ARGP_FIELDLIST)
101#define ARGP_BIT_AND_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
102#define ARGP_BIT_NAND_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
103#define ARGP_BIT_NOR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
104#define ARGP_BIT_NOT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
105#define ARGP_BIT_OR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
106#define ARGP_BIT_XOR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
107#define ARGP_BREAK_OP ARG_NONE
108#define ARGP_BREAK_POINT_OP ARG_NONE
109#define ARGP_BUFFER_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_BYTELIST)
110#define ARGP_BYTE_OP ARGP_LIST1 (ARGP_BYTEDATA)
111#define ARGP_BYTELIST_OP ARGP_LIST1 (ARGP_NAMESTRING)
112#define ARGP_CONCAT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
113#define ARGP_CONCAT_RES_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
114#define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME)
115#define ARGP_CONTINUE_OP ARG_NONE
116#define ARGP_COPY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SIMPLENAME)
117#define ARGP_CREATE_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
118#define ARGP_CREATE_BYTE_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
119#define ARGP_CREATE_DWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
120#define ARGP_CREATE_FIELD_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
121#define ARGP_CREATE_QWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
122#define ARGP_CREATE_WORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
123#define ARGP_DATA_REGION_OP ARGP_LIST4 (ARGP_NAME, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG)
124#define ARGP_DEBUG_OP ARG_NONE
125#define ARGP_DECREMENT_OP ARGP_LIST1 (ARGP_SUPERNAME)
126#define ARGP_DEREF_OF_OP ARGP_LIST1 (ARGP_TERMARG)
127#define ARGP_DEVICE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST)
128#define ARGP_DIVIDE_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET, ARGP_TARGET)
129#define ARGP_DWORD_OP ARGP_LIST1 (ARGP_DWORDDATA)
130#define ARGP_ELSE_OP ARGP_LIST2 (ARGP_PKGLENGTH, ARGP_TERMLIST)
131#define ARGP_EVENT_OP ARGP_LIST1 (ARGP_NAME)
132#define ARGP_FATAL_OP ARGP_LIST3 (ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_TERMARG)
133#define ARGP_FIELD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_BYTEDATA, ARGP_FIELDLIST)
134#define ARGP_FIND_SET_LEFT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
135#define ARGP_FIND_SET_RIGHT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
136#define ARGP_FROM_BCD_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
137#define ARGP_IF_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST)
138#define ARGP_INCREMENT_OP ARGP_LIST1 (ARGP_SUPERNAME)
139#define ARGP_INDEX_FIELD_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_BYTEDATA, ARGP_FIELDLIST)
140#define ARGP_INDEX_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
141#define ARGP_LAND_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
142#define ARGP_LEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
143#define ARGP_LGREATER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
144#define ARGP_LGREATEREQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
145#define ARGP_LLESS_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
146#define ARGP_LLESSEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
147#define ARGP_LNOT_OP ARGP_LIST1 (ARGP_TERMARG)
148#define ARGP_LNOTEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
149#define ARGP_LOAD_OP ARGP_LIST2 (ARGP_NAMESTRING, ARGP_SUPERNAME)
150#define ARGP_LOAD_TABLE_OP ARGP_LIST6 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG)
151#define ARGP_LOCAL0 ARG_NONE
152#define ARGP_LOCAL1 ARG_NONE
153#define ARGP_LOCAL2 ARG_NONE
154#define ARGP_LOCAL3 ARG_NONE
155#define ARGP_LOCAL4 ARG_NONE
156#define ARGP_LOCAL5 ARG_NONE
157#define ARGP_LOCAL6 ARG_NONE
158#define ARGP_LOCAL7 ARG_NONE
159#define ARGP_LOR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
160#define ARGP_MATCH_OP ARGP_LIST6 (ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG)
161#define ARGP_METHOD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMLIST)
162#define ARGP_METHODCALL_OP ARGP_LIST1 (ARGP_NAMESTRING)
163#define ARGP_MID_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
164#define ARGP_MOD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
165#define ARGP_MULTIPLY_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
166#define ARGP_MUTEX_OP ARGP_LIST2 (ARGP_NAME, ARGP_BYTEDATA)
167#define ARGP_NAME_OP ARGP_LIST2 (ARGP_NAME, ARGP_DATAOBJ)
168#define ARGP_NAMEDFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
169#define ARGP_NAMEPATH_OP ARGP_LIST1 (ARGP_NAMESTRING)
170#define ARGP_NOOP_OP ARG_NONE
171#define ARGP_NOTIFY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG)
172#define ARGP_ONE_OP ARG_NONE
173#define ARGP_ONES_OP ARG_NONE
174#define ARGP_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_BYTEDATA, ARGP_DATAOBJLIST)
175#define ARGP_POWER_RES_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_WORDDATA, ARGP_OBJLIST)
176#define ARGP_PROCESSOR_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_BYTEDATA, ARGP_OBJLIST)
177#define ARGP_QWORD_OP ARGP_LIST1 (ARGP_QWORDDATA)
178#define ARGP_REF_OF_OP ARGP_LIST1 (ARGP_SUPERNAME)
179#define ARGP_REGION_OP ARGP_LIST4 (ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG)
180#define ARGP_RELEASE_OP ARGP_LIST1 (ARGP_SUPERNAME)
181#define ARGP_RESERVEDFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
182#define ARGP_RESET_OP ARGP_LIST1 (ARGP_SUPERNAME)
183#define ARGP_RETURN_OP ARGP_LIST1 (ARGP_TERMARG)
184#define ARGP_REVISION_OP ARG_NONE
185#define ARGP_SCOPE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_TERMLIST)
186#define ARGP_SHIFT_LEFT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
187#define ARGP_SHIFT_RIGHT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
188#define ARGP_SIGNAL_OP ARGP_LIST1 (ARGP_SUPERNAME)
189#define ARGP_SIZE_OF_OP ARGP_LIST1 (ARGP_SUPERNAME)
190#define ARGP_SLEEP_OP ARGP_LIST1 (ARGP_TERMARG)
191#define ARGP_STALL_OP ARGP_LIST1 (ARGP_TERMARG)
192#define ARGP_STATICSTRING_OP ARGP_LIST1 (ARGP_NAMESTRING)
193#define ARGP_STORE_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SUPERNAME)
194#define ARGP_STRING_OP ARGP_LIST1 (ARGP_CHARLIST)
195#define ARGP_SUBTRACT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
196#define ARGP_THERMAL_ZONE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST)
197#define ARGP_TIMER_OP ARG_NONE
198#define ARGP_TO_BCD_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
199#define ARGP_TO_BUFFER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
200#define ARGP_TO_DEC_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
201#define ARGP_TO_HEX_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
202#define ARGP_TO_INTEGER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
203#define ARGP_TO_STRING_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
204#define ARGP_TYPE_OP ARGP_LIST1 (ARGP_SUPERNAME)
205#define ARGP_UNLOAD_OP ARGP_LIST1 (ARGP_SUPERNAME)
206#define ARGP_VAR_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_DATAOBJLIST)
207#define ARGP_WAIT_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG)
208#define ARGP_WHILE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST)
209#define ARGP_WORD_OP ARGP_LIST1 (ARGP_WORDDATA)
210#define ARGP_ZERO_OP ARG_NONE
211
212
213/*
214 * All AML opcodes and the runtime arguments for each. Used by the AML interpreter Each list is compressed
215 * into a 32-bit number and stored in the master opcode table at the end of this file.
216 *
217 * (Used by prep_operands procedure and the ASL Compiler)
218 */
219
220
221#define ARGI_ACCESSFIELD_OP ARGI_INVALID_OPCODE
222#define ARGI_ACQUIRE_OP ARGI_LIST2 (ARGI_MUTEX, ARGI_INTEGER)
223#define ARGI_ADD_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
224#define ARGI_ALIAS_OP ARGI_INVALID_OPCODE
225#define ARGI_ARG0 ARG_NONE
226#define ARGI_ARG1 ARG_NONE
227#define ARGI_ARG2 ARG_NONE
228#define ARGI_ARG3 ARG_NONE
229#define ARGI_ARG4 ARG_NONE
230#define ARGI_ARG5 ARG_NONE
231#define ARGI_ARG6 ARG_NONE
232#define ARGI_BANK_FIELD_OP ARGI_INVALID_OPCODE
233#define ARGI_BIT_AND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
234#define ARGI_BIT_NAND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
235#define ARGI_BIT_NOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
236#define ARGI_BIT_NOT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
237#define ARGI_BIT_OR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
238#define ARGI_BIT_XOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
239#define ARGI_BREAK_OP ARG_NONE
240#define ARGI_BREAK_POINT_OP ARG_NONE
241#define ARGI_BUFFER_OP ARGI_LIST1 (ARGI_INTEGER)
242#define ARGI_BYTE_OP ARGI_INVALID_OPCODE
243#define ARGI_BYTELIST_OP ARGI_INVALID_OPCODE
244#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA, ARGI_TARGETREF)
245#define ARGI_CONCAT_RES_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_BUFFER, ARGI_TARGETREF)
246#define ARGI_COND_REF_OF_OP ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF)
247#define ARGI_CONTINUE_OP ARGI_INVALID_OPCODE
248#define ARGI_COPY_OP ARGI_LIST2 (ARGI_ANYTYPE, ARGI_SIMPLE_TARGET)
249#define ARGI_CREATE_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
250#define ARGI_CREATE_BYTE_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
251#define ARGI_CREATE_DWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
252#define ARGI_CREATE_FIELD_OP ARGI_LIST4 (ARGI_BUFFER, ARGI_INTEGER, ARGI_INTEGER, ARGI_REFERENCE)
253#define ARGI_CREATE_QWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
254#define ARGI_CREATE_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
255#define ARGI_DATA_REGION_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_STRING)
256#define ARGI_DEBUG_OP ARG_NONE
257#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF)
258#define ARGI_DEREF_OF_OP ARGI_LIST1 (ARGI_REF_OR_STRING)
259#define ARGI_DEVICE_OP ARGI_INVALID_OPCODE
260#define ARGI_DIVIDE_OP ARGI_LIST4 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF, ARGI_TARGETREF)
261#define ARGI_DWORD_OP ARGI_INVALID_OPCODE
262#define ARGI_ELSE_OP ARGI_INVALID_OPCODE
263#define ARGI_EVENT_OP ARGI_INVALID_OPCODE
264#define ARGI_FATAL_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER)
265#define ARGI_FIELD_OP ARGI_INVALID_OPCODE
266#define ARGI_FIND_SET_LEFT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
267#define ARGI_FIND_SET_RIGHT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
268#define ARGI_FROM_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
269#define ARGI_IF_OP ARGI_INVALID_OPCODE
270#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF)
271#define ARGI_INDEX_FIELD_OP ARGI_INVALID_OPCODE
272#define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER, ARGI_TARGETREF)
273#define ARGI_LAND_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
274#define ARGI_LEQUAL_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
275#define ARGI_LGREATER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
276#define ARGI_LGREATEREQUAL_OP ARGI_INVALID_OPCODE
277#define ARGI_LLESS_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
278#define ARGI_LLESSEQUAL_OP ARGI_INVALID_OPCODE
279#define ARGI_LNOT_OP ARGI_LIST1 (ARGI_INTEGER)
280#define ARGI_LNOTEQUAL_OP ARGI_INVALID_OPCODE
281#define ARGI_LOAD_OP ARGI_LIST2 (ARGI_REGION_OR_FIELD,ARGI_TARGETREF)
282#define ARGI_LOAD_TABLE_OP ARGI_LIST6 (ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_ANYTYPE)
283#define ARGI_LOCAL0 ARG_NONE
284#define ARGI_LOCAL1 ARG_NONE
285#define ARGI_LOCAL2 ARG_NONE
286#define ARGI_LOCAL3 ARG_NONE
287#define ARGI_LOCAL4 ARG_NONE
288#define ARGI_LOCAL5 ARG_NONE
289#define ARGI_LOCAL6 ARG_NONE
290#define ARGI_LOCAL7 ARG_NONE
291#define ARGI_LOR_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
292#define ARGI_MATCH_OP ARGI_LIST6 (ARGI_PACKAGE, ARGI_INTEGER, ARGI_COMPUTEDATA, ARGI_INTEGER,ARGI_COMPUTEDATA,ARGI_INTEGER)
293#define ARGI_METHOD_OP ARGI_INVALID_OPCODE
294#define ARGI_METHODCALL_OP ARGI_INVALID_OPCODE
295#define ARGI_MID_OP ARGI_LIST4 (ARGI_BUFFER_OR_STRING,ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
296#define ARGI_MOD_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
297#define ARGI_MULTIPLY_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
298#define ARGI_MUTEX_OP ARGI_INVALID_OPCODE
299#define ARGI_NAME_OP ARGI_INVALID_OPCODE
300#define ARGI_NAMEDFIELD_OP ARGI_INVALID_OPCODE
301#define ARGI_NAMEPATH_OP ARGI_INVALID_OPCODE
302#define ARGI_NOOP_OP ARG_NONE
303#define ARGI_NOTIFY_OP ARGI_LIST2 (ARGI_DEVICE_REF, ARGI_INTEGER)
304#define ARGI_ONE_OP ARG_NONE
305#define ARGI_ONES_OP ARG_NONE
306#define ARGI_PACKAGE_OP ARGI_LIST1 (ARGI_INTEGER)
307#define ARGI_POWER_RES_OP ARGI_INVALID_OPCODE
308#define ARGI_PROCESSOR_OP ARGI_INVALID_OPCODE
309#define ARGI_QWORD_OP ARGI_INVALID_OPCODE
310#define ARGI_REF_OF_OP ARGI_LIST1 (ARGI_OBJECT_REF)
311#define ARGI_REGION_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
312#define ARGI_RELEASE_OP ARGI_LIST1 (ARGI_MUTEX)
313#define ARGI_RESERVEDFIELD_OP ARGI_INVALID_OPCODE
314#define ARGI_RESET_OP ARGI_LIST1 (ARGI_EVENT)
315#define ARGI_RETURN_OP ARGI_INVALID_OPCODE
316#define ARGI_REVISION_OP ARG_NONE
317#define ARGI_SCOPE_OP ARGI_INVALID_OPCODE
318#define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
319#define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
320#define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT)
321#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_DATAOBJECT)
322#define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_INTEGER)
323#define ARGI_STALL_OP ARGI_LIST1 (ARGI_INTEGER)
324#define ARGI_STATICSTRING_OP ARGI_INVALID_OPCODE
325#define ARGI_STORE_OP ARGI_LIST2 (ARGI_DATAREFOBJ, ARGI_TARGETREF)
326#define ARGI_STRING_OP ARGI_INVALID_OPCODE
327#define ARGI_SUBTRACT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
328#define ARGI_THERMAL_ZONE_OP ARGI_INVALID_OPCODE
329#define ARGI_TIMER_OP ARG_NONE
330#define ARGI_TO_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET)
331#define ARGI_TO_BUFFER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
332#define ARGI_TO_DEC_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
333#define ARGI_TO_HEX_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
334#define ARGI_TO_INTEGER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
335#define ARGI_TO_STRING_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_FIXED_TARGET)
336#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE)
337#define ARGI_UNLOAD_OP ARGI_LIST1 (ARGI_DDBHANDLE)
338#define ARGI_VAR_PACKAGE_OP ARGI_LIST1 (ARGI_INTEGER)
339#define ARGI_WAIT_OP ARGI_LIST2 (ARGI_EVENT, ARGI_INTEGER)
340#define ARGI_WHILE_OP ARGI_INVALID_OPCODE
341#define ARGI_WORD_OP ARGI_INVALID_OPCODE
342#define ARGI_ZERO_OP ARG_NONE
343
344
345/*
346 * Summary of opcode types/flags
347 */
348
349/******************************************************************************
350
351 Opcodes that have associated namespace objects (AML_NSOBJECT flag)
352
353 AML_SCOPE_OP
354 AML_DEVICE_OP
355 AML_THERMAL_ZONE_OP
356 AML_METHOD_OP
357 AML_POWER_RES_OP
358 AML_PROCESSOR_OP
359 AML_FIELD_OP
360 AML_INDEX_FIELD_OP
361 AML_BANK_FIELD_OP
362 AML_NAME_OP
363 AML_ALIAS_OP
364 AML_MUTEX_OP
365 AML_EVENT_OP
366 AML_REGION_OP
367 AML_CREATE_FIELD_OP
368 AML_CREATE_BIT_FIELD_OP
369 AML_CREATE_BYTE_FIELD_OP
370 AML_CREATE_WORD_FIELD_OP
371 AML_CREATE_DWORD_FIELD_OP
372 AML_CREATE_QWORD_FIELD_OP
373 AML_INT_NAMEDFIELD_OP
374 AML_INT_METHODCALL_OP
375 AML_INT_NAMEPATH_OP
376
377 Opcodes that are "namespace" opcodes (AML_NSOPCODE flag)
378
379 AML_SCOPE_OP
380 AML_DEVICE_OP
381 AML_THERMAL_ZONE_OP
382 AML_METHOD_OP
383 AML_POWER_RES_OP
384 AML_PROCESSOR_OP
385 AML_FIELD_OP
386 AML_INDEX_FIELD_OP
387 AML_BANK_FIELD_OP
388 AML_NAME_OP
389 AML_ALIAS_OP
390 AML_MUTEX_OP
391 AML_EVENT_OP
392 AML_REGION_OP
393 AML_INT_NAMEDFIELD_OP
394
395 Opcodes that have an associated namespace node (AML_NSNODE flag)
396
397 AML_SCOPE_OP
398 AML_DEVICE_OP
399 AML_THERMAL_ZONE_OP
400 AML_METHOD_OP
401 AML_POWER_RES_OP
402 AML_PROCESSOR_OP
403 AML_NAME_OP
404 AML_ALIAS_OP
405 AML_MUTEX_OP
406 AML_EVENT_OP
407 AML_REGION_OP
408 AML_CREATE_FIELD_OP
409 AML_CREATE_BIT_FIELD_OP
410 AML_CREATE_BYTE_FIELD_OP
411 AML_CREATE_WORD_FIELD_OP
412 AML_CREATE_DWORD_FIELD_OP
413 AML_CREATE_QWORD_FIELD_OP
414 AML_INT_NAMEDFIELD_OP
415 AML_INT_METHODCALL_OP
416 AML_INT_NAMEPATH_OP
417
418 Opcodes that define named ACPI objects (AML_NAMED flag)
419
420 AML_SCOPE_OP
421 AML_DEVICE_OP
422 AML_THERMAL_ZONE_OP
423 AML_METHOD_OP
424 AML_POWER_RES_OP
425 AML_PROCESSOR_OP
426 AML_NAME_OP
427 AML_ALIAS_OP
428 AML_MUTEX_OP
429 AML_EVENT_OP
430 AML_REGION_OP
431 AML_INT_NAMEDFIELD_OP
432
433 Opcodes that contain executable AML as part of the definition that
434 must be deferred until needed
435
436 AML_METHOD_OP
437 AML_VAR_PACKAGE_OP
438 AML_CREATE_FIELD_OP
439 AML_CREATE_BIT_FIELD_OP
440 AML_CREATE_BYTE_FIELD_OP
441 AML_CREATE_WORD_FIELD_OP
442 AML_CREATE_DWORD_FIELD_OP
443 AML_CREATE_QWORD_FIELD_OP
444 AML_REGION_OP
445 AML_BUFFER_OP
446
447 Field opcodes
448
449 AML_CREATE_FIELD_OP
450 AML_FIELD_OP
451 AML_INDEX_FIELD_OP
452 AML_BANK_FIELD_OP
453
454 Field "Create" opcodes
455
456 AML_CREATE_FIELD_OP
457 AML_CREATE_BIT_FIELD_OP
458 AML_CREATE_BYTE_FIELD_OP
459 AML_CREATE_WORD_FIELD_OP
460 AML_CREATE_DWORD_FIELD_OP
461 AML_CREATE_QWORD_FIELD_OP
462
463******************************************************************************/
464
465
466/*
467 * Master Opcode information table. A summary of everything we know about each opcode, all in one place.
468 */
469
470
471const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] =
472{
473/*! [Begin] no source code translation */
474/* Index Name Parser Args Interpreter Args ObjectType Class Type Flags */
475
476/* 00 */ ACPI_OP ("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
477/* 01 */ ACPI_OP ("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
478/* 02 */ ACPI_OP ("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP, ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
479/* 03 */ ACPI_OP ("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
480/* 04 */ ACPI_OP ("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
481/* 05 */ ACPI_OP ("WordConst", ARGP_WORD_OP, ARGI_WORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
482/* 06 */ ACPI_OP ("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
483/* 07 */ ACPI_OP ("String", ARGP_STRING_OP, ARGI_STRING_OP, ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
484/* 08 */ ACPI_OP ("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
485/* 09 */ ACPI_OP ("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP, ACPI_TYPE_BUFFER, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
486/* 0A */ ACPI_OP ("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
487/* 0B */ ACPI_OP ("Method", ARGP_METHOD_OP, ARGI_METHOD_OP, ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED | AML_DEFER),
488/* 0C */ ACPI_OP ("Local0", ARGP_LOCAL0, ARGI_LOCAL0, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
489/* 0D */ ACPI_OP ("Local1", ARGP_LOCAL1, ARGI_LOCAL1, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
490/* 0E */ ACPI_OP ("Local2", ARGP_LOCAL2, ARGI_LOCAL2, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
491/* 0F */ ACPI_OP ("Local3", ARGP_LOCAL3, ARGI_LOCAL3, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
492/* 10 */ ACPI_OP ("Local4", ARGP_LOCAL4, ARGI_LOCAL4, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
493/* 11 */ ACPI_OP ("Local5", ARGP_LOCAL5, ARGI_LOCAL5, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
494/* 12 */ ACPI_OP ("Local6", ARGP_LOCAL6, ARGI_LOCAL6, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
495/* 13 */ ACPI_OP ("Local7", ARGP_LOCAL7, ARGI_LOCAL7, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
496/* 14 */ ACPI_OP ("Arg0", ARGP_ARG0, ARGI_ARG0, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
497/* 15 */ ACPI_OP ("Arg1", ARGP_ARG1, ARGI_ARG1, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
498/* 16 */ ACPI_OP ("Arg2", ARGP_ARG2, ARGI_ARG2, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
499/* 17 */ ACPI_OP ("Arg3", ARGP_ARG3, ARGI_ARG3, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
500/* 18 */ ACPI_OP ("Arg4", ARGP_ARG4, ARGI_ARG4, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
501/* 19 */ ACPI_OP ("Arg5", ARGP_ARG5, ARGI_ARG5, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
502/* 1A */ ACPI_OP ("Arg6", ARGP_ARG6, ARGI_ARG6, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
503/* 1B */ ACPI_OP ("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
504/* 1C */ ACPI_OP ("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
505/* 1D */ ACPI_OP ("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
506/* 1E */ ACPI_OP ("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
507/* 1F */ ACPI_OP ("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
508/* 20 */ ACPI_OP ("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
509/* 21 */ ACPI_OP ("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
510/* 22 */ ACPI_OP ("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
511/* 23 */ ACPI_OP ("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_2T_1R, AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT),
512/* 24 */ ACPI_OP ("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
513/* 25 */ ACPI_OP ("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
514/* 26 */ ACPI_OP ("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
515/* 27 */ ACPI_OP ("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
516/* 28 */ ACPI_OP ("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
517/* 29 */ ACPI_OP ("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
518/* 2A */ ACPI_OP ("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
519/* 2B */ ACPI_OP ("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
520/* 2C */ ACPI_OP ("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP, ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
521/* 2D */ ACPI_OP ("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
522/* 2E */ ACPI_OP ("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
523/* 2F */ ACPI_OP ("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
524/* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
525/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R),
526/* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
527/* 33 */ ACPI_OP ("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
528/* 34 */ ACPI_OP ("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
529/* 35 */ ACPI_OP ("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP, ARGI_CREATE_BYTE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
530/* 36 */ ACPI_OP ("CreateBitField", ARGP_CREATE_BIT_FIELD_OP, ARGI_CREATE_BIT_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
531/* 37 */ ACPI_OP ("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
532/* 38 */ ACPI_OP ("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
533/* 39 */ ACPI_OP ("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
534/* 3A */ ACPI_OP ("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
535/* 3B */ ACPI_OP ("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
536/* 3C */ ACPI_OP ("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
537/* 3D */ ACPI_OP ("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
538/* 3E */ ACPI_OP ("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
539/* 3F */ ACPI_OP ("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
540/* 40 */ ACPI_OP ("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
541/* 41 */ ACPI_OP ("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
542/* 42 */ ACPI_OP ("Return", ARGP_RETURN_OP, ARGI_RETURN_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
543/* 43 */ ACPI_OP ("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
544/* 44 */ ACPI_OP ("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
545/* 45 */ ACPI_OP ("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
546
547/* Prefixed opcodes (Two-byte opcodes with a prefix op) */
548
549/* 46 */ ACPI_OP ("Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP, ACPI_TYPE_MUTEX, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
550/* 47 */ ACPI_OP ("Event", ARGP_EVENT_OP, ARGI_EVENT_OP, ACPI_TYPE_EVENT, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED ),
551/* 48 */ ACPI_OP ("CondRefOf", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
552/* 49 */ ACPI_OP ("CreateField", ARGP_CREATE_FIELD_OP, ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_FIELD | AML_CREATE),
553/* 4A */ ACPI_OP ("Load", ARGP_LOAD_OP, ARGI_LOAD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R, AML_FLAGS_EXEC_1A_1T_0R),
554/* 4B */ ACPI_OP ("Stall", ARGP_STALL_OP, ARGI_STALL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
555/* 4C */ ACPI_OP ("Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
556/* 4D */ ACPI_OP ("Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
557/* 4E */ ACPI_OP ("Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
558/* 4F */ ACPI_OP ("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
559/* 50 */ ACPI_OP ("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
560/* 51 */ ACPI_OP ("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
561/* 52 */ ACPI_OP ("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
562/* 53 */ ACPI_OP ("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
563/* 54 */ ACPI_OP ("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
564/* 55 */ ACPI_OP ("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0),
565/* 56 */ ACPI_OP ("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0),
566/* 57 */ ACPI_OP ("Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R, AML_FLAGS_EXEC_3A_0T_0R),
567/* 58 */ ACPI_OP ("OperationRegion", ARGP_REGION_OP, ARGI_REGION_OP, ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED | AML_DEFER),
568/* 59 */ ACPI_OP ("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
569/* 5A */ ACPI_OP ("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP, ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
570/* 5B */ ACPI_OP ("Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP, ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
571/* 5C */ ACPI_OP ("PowerResource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP, ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
572/* 5D */ ACPI_OP ("ThermalZone", ARGP_THERMAL_ZONE_OP, ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
573/* 5E */ ACPI_OP ("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
574/* 5F */ ACPI_OP ("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
575
576/* Internal opcodes that map to invalid AML opcodes */
577
578/* 60 */ ACPI_OP ("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
579/* 61 */ ACPI_OP ("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
580/* 62 */ ACPI_OP ("LGreaterEqual", ARGP_LGREATEREQUAL_OP, ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
581/* 63 */ ACPI_OP ("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE ),
582/* 64 */ ACPI_OP ("-MethodCall-", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP, ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL, AML_TYPE_METHOD_CALL, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE),
583/* 65 */ ACPI_OP ("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP, ACPI_TYPE_ANY, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, 0),
584/* 66 */ ACPI_OP ("-ReservedField-", ARGP_RESERVEDFIELD_OP, ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
585/* 67 */ ACPI_OP ("-NamedField-", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED ),
586/* 68 */ ACPI_OP ("-AccessField-", ARGP_ACCESSFIELD_OP, ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
587/* 69 */ ACPI_OP ("-StaticString", ARGP_STATICSTRING_OP, ARGI_STATICSTRING_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
588/* 6A */ ACPI_OP ("-Return Value-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN, AML_HAS_ARGS | AML_HAS_RETVAL),
589/* 6B */ ACPI_OP ("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID, AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS),
590/* 6C */ ACPI_OP ("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS),
591/* 6D */ ACPI_OP ("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS),
592
593/* ACPI 2.0 opcodes */
594
595/* 6E */ ACPI_OP ("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
596/* 6F */ ACPI_OP ("Package /*Var*/", ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER),
597/* 70 */ ACPI_OP ("ConcatenateResTemplate", ARGP_CONCAT_RES_OP, ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
598/* 71 */ ACPI_OP ("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
599/* 72 */ ACPI_OP ("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP,ARGI_CREATE_QWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
600/* 73 */ ACPI_OP ("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
601/* 74 */ ACPI_OP ("ToDecimalString", ARGP_TO_DEC_STR_OP, ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
602/* 75 */ ACPI_OP ("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
603/* 76 */ ACPI_OP ("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
604/* 77 */ ACPI_OP ("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
605/* 78 */ ACPI_OP ("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
606/* 79 */ ACPI_OP ("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R, AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT),
607/* 7A */ ACPI_OP ("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
608/* 7B */ ACPI_OP ("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
609/* 7C */ ACPI_OP ("DataTableRegion", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
610/* 7D */ ACPI_OP ("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE),
611
612/* ACPI 3.0 opcodes */
613
614/* 7E */ ACPI_OP ("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, AML_FLAGS_EXEC_0A_0T_1R)
615
616/*! [End] no source code translation !*/
617};
618
619/*
620 * This table is directly indexed by the opcodes, and returns an
621 * index into the table above
622 */
623static const u8 acpi_gbl_short_op_index[256] =
624{
625/* 0 1 2 3 4 5 6 7 */
626/* 8 9 A B C D E F */
627/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK,
628/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK,
629/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK,
630/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
631/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
632/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
633/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
634/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
635/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
636/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
637/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
638/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC,
639/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
640/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK,
641/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
642/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
643/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30,
644/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72,
645/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
646/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
647/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
648/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
649/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
650/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
651/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
652/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK,
653/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
654/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
655/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
656/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
657/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
658/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45,
659};
660
661/*
662 * This table is indexed by the second opcode of the extended opcode
663 * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info)
664 */
665static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] =
666{
667/* 0 1 2 3 4 5 6 7 */
668/* 8 9 A B C D E F */
669/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK,
670/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
671/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK,
672/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B,
673/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
674/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK,
675/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK,
676/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
677/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
678/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
679/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
680/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
681/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
682/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
683/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
684/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
685/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
686/* 0x88 */ 0x7C,
687};
688
689
690/*******************************************************************************
691 *
692 * FUNCTION: acpi_ps_get_opcode_info
693 *
694 * PARAMETERS: Opcode - The AML opcode
695 *
696 * RETURN: A pointer to the info about the opcode. NULL if the opcode was
697 * not found in the table.
698 *
699 * DESCRIPTION: Find AML opcode description based on the opcode.
700 * NOTE: This procedure must ALWAYS return a valid pointer!
701 *
702 ******************************************************************************/
703
704const struct acpi_opcode_info *
705acpi_ps_get_opcode_info (
706 u16 opcode)
707{
708 ACPI_FUNCTION_NAME ("ps_get_opcode_info");
709
710
711 /*
712 * Detect normal 8-bit opcode or extended 16-bit opcode
713 */
714 switch ((u8) (opcode >> 8)) {
715 case 0:
716
717 /* Simple (8-bit) opcode: 0-255, can't index beyond table */
718
719 return (&acpi_gbl_aml_op_info [acpi_gbl_short_op_index [(u8) opcode]]);
720
721 case AML_EXTOP:
722
723 /* Extended (16-bit, prefix+opcode) opcode */
724
725 if (((u8) opcode) <= MAX_EXTENDED_OPCODE) {
726 return (&acpi_gbl_aml_op_info [acpi_gbl_long_op_index [(u8) opcode]]);
727 }
728
729 /* Else fall through to error case below */
730 /*lint -fallthrough */
731
732 default:
733
734 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown AML opcode [%4.4X]\n", opcode));
735 break;
736 }
737
738
739 /* Default is "unknown opcode" */
740
741 return (&acpi_gbl_aml_op_info [_UNK]);
742}
743
744
745/*******************************************************************************
746 *
747 * FUNCTION: acpi_ps_get_opcode_name
748 *
749 * PARAMETERS: Opcode - The AML opcode
750 *
751 * RETURN: A pointer to the name of the opcode (ASCII String)
752 * Note: Never returns NULL.
753 *
754 * DESCRIPTION: Translate an opcode into a human-readable string
755 *
756 ******************************************************************************/
757
758char *
759acpi_ps_get_opcode_name (
760 u16 opcode)
761{
762#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
763
764 const struct acpi_opcode_info *op;
765
766
767 op = acpi_ps_get_opcode_info (opcode);
768
769 /* Always guaranteed to return a valid pointer */
770
771 return (op->name);
772
773#else
774 return ("AE_NOT_CONFIGURED");
775
776#endif
777}
778
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
new file mode 100644
index 000000000000..e79edb53cb3b
--- /dev/null
+++ b/drivers/acpi/parser/psparse.c
@@ -0,0 +1,1266 @@
1/******************************************************************************
2 *
3 * Module Name: psparse - Parser top level AML parse routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45/*
46 * Parse the AML and build an operation tree as most interpreters,
47 * like Perl, do. Parsing is done by hand rather than with a YACC
48 * generated parser to tightly constrain stack and dynamic memory
49 * usage. At the same time, parsing is kept flexible and the code
50 * fairly compact by parsing based on a list of AML opcode
51 * templates in aml_op_info[]
52 */
53
54#include <acpi/acpi.h>
55#include <acpi/acparser.h>
56#include <acpi/acdispat.h>
57#include <acpi/amlcode.h>
58#include <acpi/acnamesp.h>
59#include <acpi/acinterp.h>
60
61#define _COMPONENT ACPI_PARSER
62 ACPI_MODULE_NAME ("psparse")
63
64
65static u32 acpi_gbl_depth = 0;
66
67
68/*******************************************************************************
69 *
70 * FUNCTION: acpi_ps_get_opcode_size
71 *
72 * PARAMETERS: Opcode - An AML opcode
73 *
74 * RETURN: Size of the opcode, in bytes (1 or 2)
75 *
76 * DESCRIPTION: Get the size of the current opcode.
77 *
78 ******************************************************************************/
79
80u32
81acpi_ps_get_opcode_size (
82 u32 opcode)
83{
84
85 /* Extended (2-byte) opcode if > 255 */
86
87 if (opcode > 0x00FF) {
88 return (2);
89 }
90
91 /* Otherwise, just a single byte opcode */
92
93 return (1);
94}
95
96
97/*******************************************************************************
98 *
99 * FUNCTION: acpi_ps_peek_opcode
100 *
101 * PARAMETERS: parser_state - A parser state object
102 *
103 * RETURN: Status
104 *
105 * DESCRIPTION: Get next AML opcode (without incrementing AML pointer)
106 *
107 ******************************************************************************/
108
109u16
110acpi_ps_peek_opcode (
111 struct acpi_parse_state *parser_state)
112{
113 u8 *aml;
114 u16 opcode;
115
116
117 aml = parser_state->aml;
118 opcode = (u16) ACPI_GET8 (aml);
119
120
121 if (opcode == AML_EXTOP) {
122 /* Extended opcode */
123
124 aml++;
125 opcode = (u16) ((opcode << 8) | ACPI_GET8 (aml));
126 }
127
128 return (opcode);
129}
130
131
132/*******************************************************************************
133 *
134 * FUNCTION: acpi_ps_complete_this_op
135 *
136 * PARAMETERS: walk_state - Current State
137 * Op - Op to complete
138 *
139 * RETURN: None.
140 *
141 * DESCRIPTION: Perform any cleanup at the completion of an Op.
142 *
143 ******************************************************************************/
144
145void
146acpi_ps_complete_this_op (
147 struct acpi_walk_state *walk_state,
148 union acpi_parse_object *op)
149{
150 union acpi_parse_object *prev;
151 union acpi_parse_object *next;
152 const struct acpi_opcode_info *parent_info;
153 union acpi_parse_object *replacement_op = NULL;
154
155
156 ACPI_FUNCTION_TRACE_PTR ("ps_complete_this_op", op);
157
158
159 /* Check for null Op, can happen if AML code is corrupt */
160
161 if (!op) {
162 return_VOID;
163 }
164
165 /* Delete this op and the subtree below it if asked to */
166
167 if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||
168 (walk_state->op_info->class == AML_CLASS_ARGUMENT)) {
169 return_VOID;
170 }
171
172 /* Make sure that we only delete this subtree */
173
174 if (op->common.parent) {
175 /*
176 * Check if we need to replace the operator and its subtree
177 * with a return value op (placeholder op)
178 */
179 parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
180
181 switch (parent_info->class) {
182 case AML_CLASS_CONTROL:
183 break;
184
185 case AML_CLASS_CREATE:
186
187 /*
188 * These opcodes contain term_arg operands. The current
189 * op must be replaced by a placeholder return op
190 */
191 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
192 if (!replacement_op) {
193 goto cleanup;
194 }
195 break;
196
197 case AML_CLASS_NAMED_OBJECT:
198
199 /*
200 * These opcodes contain term_arg operands. The current
201 * op must be replaced by a placeholder return op
202 */
203 if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
204 (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) ||
205 (op->common.parent->common.aml_opcode == AML_BUFFER_OP) ||
206 (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
207 (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
208 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
209 if (!replacement_op) {
210 goto cleanup;
211 }
212 }
213
214 if ((op->common.parent->common.aml_opcode == AML_NAME_OP) &&
215 (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
216 if ((op->common.aml_opcode == AML_BUFFER_OP) ||
217 (op->common.aml_opcode == AML_PACKAGE_OP) ||
218 (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
219 replacement_op = acpi_ps_alloc_op (op->common.aml_opcode);
220 if (!replacement_op) {
221 goto cleanup;
222 }
223
224 replacement_op->named.data = op->named.data;
225 replacement_op->named.length = op->named.length;
226 }
227 }
228 break;
229
230 default:
231 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
232 if (!replacement_op) {
233 goto cleanup;
234 }
235 }
236
237 /* We must unlink this op from the parent tree */
238
239 prev = op->common.parent->common.value.arg;
240 if (prev == op) {
241 /* This op is the first in the list */
242
243 if (replacement_op) {
244 replacement_op->common.parent = op->common.parent;
245 replacement_op->common.value.arg = NULL;
246 replacement_op->common.node = op->common.node;
247 op->common.parent->common.value.arg = replacement_op;
248 replacement_op->common.next = op->common.next;
249 }
250 else {
251 op->common.parent->common.value.arg = op->common.next;
252 }
253 }
254
255 /* Search the parent list */
256
257 else while (prev) {
258 /* Traverse all siblings in the parent's argument list */
259
260 next = prev->common.next;
261 if (next == op) {
262 if (replacement_op) {
263 replacement_op->common.parent = op->common.parent;
264 replacement_op->common.value.arg = NULL;
265 replacement_op->common.node = op->common.node;
266 prev->common.next = replacement_op;
267 replacement_op->common.next = op->common.next;
268 next = NULL;
269 }
270 else {
271 prev->common.next = op->common.next;
272 next = NULL;
273 }
274 }
275
276 prev = next;
277 }
278 }
279
280
281cleanup:
282
283 /* Now we can actually delete the subtree rooted at op */
284
285 acpi_ps_delete_parse_tree (op);
286 return_VOID;
287}
288
289
290/*******************************************************************************
291 *
292 * FUNCTION: acpi_ps_next_parse_state
293 *
294 * PARAMETERS: parser_state - Current parser state object
295 *
296 * RETURN: Status
297 *
298 * DESCRIPTION: Update the parser state based upon the return exception from
299 * the parser callback.
300 *
301 ******************************************************************************/
302
303acpi_status
304acpi_ps_next_parse_state (
305 struct acpi_walk_state *walk_state,
306 union acpi_parse_object *op,
307 acpi_status callback_status)
308{
309 struct acpi_parse_state *parser_state = &walk_state->parser_state;
310 acpi_status status = AE_CTRL_PENDING;
311
312
313 ACPI_FUNCTION_TRACE_PTR ("ps_next_parse_state", op);
314
315
316 switch (callback_status) {
317 case AE_CTRL_TERMINATE:
318
319 /*
320 * A control method was terminated via a RETURN statement.
321 * The walk of this method is complete.
322 */
323 parser_state->aml = parser_state->aml_end;
324 status = AE_CTRL_TERMINATE;
325 break;
326
327
328 case AE_CTRL_BREAK:
329
330 parser_state->aml = walk_state->aml_last_while;
331 walk_state->control_state->common.value = FALSE;
332 status = AE_CTRL_BREAK;
333 break;
334
335 case AE_CTRL_CONTINUE:
336
337
338 parser_state->aml = walk_state->aml_last_while;
339 status = AE_CTRL_CONTINUE;
340 break;
341
342 case AE_CTRL_PENDING:
343
344 parser_state->aml = walk_state->aml_last_while;
345 break;
346
347#if 0
348 case AE_CTRL_SKIP:
349
350 parser_state->aml = parser_state->scope->parse_scope.pkg_end;
351 status = AE_OK;
352 break;
353#endif
354
355 case AE_CTRL_TRUE:
356
357 /*
358 * Predicate of an IF was true, and we are at the matching ELSE.
359 * Just close out this package
360 */
361 parser_state->aml = acpi_ps_get_next_package_end (parser_state);
362 break;
363
364
365 case AE_CTRL_FALSE:
366
367 /*
368 * Either an IF/WHILE Predicate was false or we encountered a BREAK
369 * opcode. In both cases, we do not execute the rest of the
370 * package; We simply close out the parent (finishing the walk of
371 * this branch of the tree) and continue execution at the parent
372 * level.
373 */
374 parser_state->aml = parser_state->scope->parse_scope.pkg_end;
375
376 /* In the case of a BREAK, just force a predicate (if any) to FALSE */
377
378 walk_state->control_state->common.value = FALSE;
379 status = AE_CTRL_END;
380 break;
381
382
383 case AE_CTRL_TRANSFER:
384
385 /*
386 * A method call (invocation) -- transfer control
387 */
388 status = AE_CTRL_TRANSFER;
389 walk_state->prev_op = op;
390 walk_state->method_call_op = op;
391 walk_state->method_call_node = (op->common.value.arg)->common.node;
392
393 /* Will return value (if any) be used by the caller? */
394
395 walk_state->return_used = acpi_ds_is_result_used (op, walk_state);
396 break;
397
398
399 default:
400 status = callback_status;
401 if ((callback_status & AE_CODE_MASK) == AE_CODE_CONTROL) {
402 status = AE_OK;
403 }
404 break;
405 }
406
407 return_ACPI_STATUS (status);
408}
409
410
411/*******************************************************************************
412 *
413 * FUNCTION: acpi_ps_parse_loop
414 *
415 * PARAMETERS: parser_state - Current parser state object
416 *
417 * RETURN: Status
418 *
419 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
420 * a tree of ops.
421 *
422 ******************************************************************************/
423
424acpi_status
425acpi_ps_parse_loop (
426 struct acpi_walk_state *walk_state)
427{
428 acpi_status status = AE_OK;
429 union acpi_parse_object *op = NULL; /* current op */
430 union acpi_parse_object *arg = NULL;
431 union acpi_parse_object *pre_op = NULL;
432 struct acpi_parse_state *parser_state;
433 u8 *aml_op_start = NULL;
434
435
436 ACPI_FUNCTION_TRACE_PTR ("ps_parse_loop", walk_state);
437
438 if (walk_state->descending_callback == NULL) {
439 return_ACPI_STATUS (AE_BAD_PARAMETER);
440 }
441
442 parser_state = &walk_state->parser_state;
443 walk_state->arg_types = 0;
444
445#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
446 if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
447 /* We are restarting a preempted control method */
448
449 if (acpi_ps_has_completed_scope (parser_state)) {
450 /*
451 * We must check if a predicate to an IF or WHILE statement
452 * was just completed
453 */
454 if ((parser_state->scope->parse_scope.op) &&
455 ((parser_state->scope->parse_scope.op->common.aml_opcode == AML_IF_OP) ||
456 (parser_state->scope->parse_scope.op->common.aml_opcode == AML_WHILE_OP)) &&
457 (walk_state->control_state) &&
458 (walk_state->control_state->common.state ==
459 ACPI_CONTROL_PREDICATE_EXECUTING)) {
460 /*
461 * A predicate was just completed, get the value of the
462 * predicate and branch based on that value
463 */
464 walk_state->op = NULL;
465 status = acpi_ds_get_predicate_value (walk_state, ACPI_TO_POINTER (TRUE));
466 if (ACPI_FAILURE (status) &&
467 ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) {
468 if (status == AE_AML_NO_RETURN_VALUE) {
469 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
470 "Invoked method did not return a value, %s\n",
471 acpi_format_exception (status)));
472
473 }
474 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "get_predicate Failed, %s\n",
475 acpi_format_exception (status)));
476 return_ACPI_STATUS (status);
477 }
478
479 status = acpi_ps_next_parse_state (walk_state, op, status);
480 }
481
482 acpi_ps_pop_scope (parser_state, &op,
483 &walk_state->arg_types, &walk_state->arg_count);
484 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op));
485 }
486 else if (walk_state->prev_op) {
487 /* We were in the middle of an op */
488
489 op = walk_state->prev_op;
490 walk_state->arg_types = walk_state->prev_arg_types;
491 }
492 }
493#endif
494
495 /*
496 * Iterative parsing loop, while there is more aml to process:
497 */
498 while ((parser_state->aml < parser_state->aml_end) || (op)) {
499 aml_op_start = parser_state->aml;
500 if (!op) {
501 /* Get the next opcode from the AML stream */
502
503 walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml,
504 parser_state->aml_start);
505 walk_state->opcode = acpi_ps_peek_opcode (parser_state);
506
507 /*
508 * First cut to determine what we have found:
509 * 1) A valid AML opcode
510 * 2) A name string
511 * 3) An unknown/invalid opcode
512 */
513 walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode);
514 switch (walk_state->op_info->class) {
515 case AML_CLASS_ASCII:
516 case AML_CLASS_PREFIX:
517 /*
518 * Starts with a valid prefix or ASCII char, this is a name
519 * string. Convert the bare name string to a namepath.
520 */
521 walk_state->opcode = AML_INT_NAMEPATH_OP;
522 walk_state->arg_types = ARGP_NAMESTRING;
523 break;
524
525 case AML_CLASS_UNKNOWN:
526
527 /* The opcode is unrecognized. Just skip unknown opcodes */
528
529 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
530 "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
531 walk_state->opcode, parser_state->aml, walk_state->aml_offset));
532
533 ACPI_DUMP_BUFFER (parser_state->aml, 128);
534
535 /* Assume one-byte bad opcode */
536
537 parser_state->aml++;
538 continue;
539
540 default:
541
542 /* Found opcode info, this is a normal opcode */
543
544 parser_state->aml += acpi_ps_get_opcode_size (walk_state->opcode);
545 walk_state->arg_types = walk_state->op_info->parse_args;
546 break;
547 }
548
549 /* Create Op structure and append to parent's argument list */
550
551 if (walk_state->op_info->flags & AML_NAMED) {
552 /* Allocate a new pre_op if necessary */
553
554 if (!pre_op) {
555 pre_op = acpi_ps_alloc_op (walk_state->opcode);
556 if (!pre_op) {
557 status = AE_NO_MEMORY;
558 goto close_this_op;
559 }
560 }
561
562 pre_op->common.value.arg = NULL;
563 pre_op->common.aml_opcode = walk_state->opcode;
564
565 /*
566 * Get and append arguments until we find the node that contains
567 * the name (the type ARGP_NAME).
568 */
569 while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) &&
570 (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME)) {
571 status = acpi_ps_get_next_arg (walk_state, parser_state,
572 GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg);
573 if (ACPI_FAILURE (status)) {
574 goto close_this_op;
575 }
576
577 acpi_ps_append_arg (pre_op, arg);
578 INCREMENT_ARG_LIST (walk_state->arg_types);
579 }
580
581 /* Make sure that we found a NAME and didn't run out of arguments */
582
583 if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) {
584 status = AE_AML_NO_OPERAND;
585 goto close_this_op;
586 }
587
588 /* We know that this arg is a name, move to next arg */
589
590 INCREMENT_ARG_LIST (walk_state->arg_types);
591
592 /*
593 * Find the object. This will either insert the object into
594 * the namespace or simply look it up
595 */
596 walk_state->op = NULL;
597
598 status = walk_state->descending_callback (walk_state, &op);
599 if (ACPI_FAILURE (status)) {
600 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "During name lookup/catalog, %s\n",
601 acpi_format_exception (status)));
602 goto close_this_op;
603 }
604
605 if (op == NULL) {
606 continue;
607 }
608
609 status = acpi_ps_next_parse_state (walk_state, op, status);
610 if (status == AE_CTRL_PENDING) {
611 status = AE_OK;
612 goto close_this_op;
613 }
614
615 if (ACPI_FAILURE (status)) {
616 goto close_this_op;
617 }
618
619 acpi_ps_append_arg (op, pre_op->common.value.arg);
620 acpi_gbl_depth++;
621
622 if (op->common.aml_opcode == AML_REGION_OP) {
623 /*
624 * Defer final parsing of an operation_region body,
625 * because we don't have enough info in the first pass
626 * to parse it correctly (i.e., there may be method
627 * calls within the term_arg elements of the body.)
628 *
629 * However, we must continue parsing because
630 * the opregion is not a standalone package --
631 * we don't know where the end is at this point.
632 *
633 * (Length is unknown until parse of the body complete)
634 */
635 op->named.data = aml_op_start;
636 op->named.length = 0;
637 }
638 }
639 else {
640 /* Not a named opcode, just allocate Op and append to parent */
641
642 walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode);
643 op = acpi_ps_alloc_op (walk_state->opcode);
644 if (!op) {
645 status = AE_NO_MEMORY;
646 goto close_this_op;
647 }
648
649 if (walk_state->op_info->flags & AML_CREATE) {
650 /*
651 * Backup to beginning of create_xXXfield declaration
652 * body_length is unknown until we parse the body
653 */
654 op->named.data = aml_op_start;
655 op->named.length = 0;
656 }
657
658 acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op);
659
660 if ((walk_state->descending_callback != NULL)) {
661 /*
662 * Find the object. This will either insert the object into
663 * the namespace or simply look it up
664 */
665 walk_state->op = op;
666
667 status = walk_state->descending_callback (walk_state, &op);
668 status = acpi_ps_next_parse_state (walk_state, op, status);
669 if (status == AE_CTRL_PENDING) {
670 status = AE_OK;
671 goto close_this_op;
672 }
673
674 if (ACPI_FAILURE (status)) {
675 goto close_this_op;
676 }
677 }
678 }
679
680 op->common.aml_offset = walk_state->aml_offset;
681
682 if (walk_state->op_info) {
683 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
684 "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n",
685 (u32) op->common.aml_opcode, walk_state->op_info->name,
686 op, parser_state->aml, op->common.aml_offset));
687 }
688 }
689
690
691 /* Start arg_count at zero because we don't know if there are any args yet */
692
693 walk_state->arg_count = 0;
694
695 if (walk_state->arg_types) /* Are there any arguments that must be processed? */ {
696 /* Get arguments */
697
698 switch (op->common.aml_opcode) {
699 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
700 case AML_WORD_OP: /* AML_WORDDATA_ARG */
701 case AML_DWORD_OP: /* AML_DWORDATA_ARG */
702 case AML_QWORD_OP: /* AML_QWORDATA_ARG */
703 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
704
705 /* Fill in constant or string argument directly */
706
707 acpi_ps_get_next_simple_arg (parser_state,
708 GET_CURRENT_ARG_TYPE (walk_state->arg_types), op);
709 break;
710
711 case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
712
713 status = acpi_ps_get_next_namepath (walk_state, parser_state, op, 1);
714 if (ACPI_FAILURE (status)) {
715 goto close_this_op;
716 }
717
718 walk_state->arg_types = 0;
719 break;
720
721 default:
722
723 /* Op is not a constant or string, append each argument to the Op */
724
725 while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) &&
726 !walk_state->arg_count) {
727 walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml,
728 parser_state->aml_start);
729 status = acpi_ps_get_next_arg (walk_state, parser_state,
730 GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg);
731 if (ACPI_FAILURE (status)) {
732 goto close_this_op;
733 }
734
735 if (arg) {
736 arg->common.aml_offset = walk_state->aml_offset;
737 acpi_ps_append_arg (op, arg);
738 }
739 INCREMENT_ARG_LIST (walk_state->arg_types);
740 }
741
742 /* Special processing for certain opcodes */
743
744 switch (op->common.aml_opcode) {
745 case AML_METHOD_OP:
746
747 /*
748 * Skip parsing of control method
749 * because we don't have enough info in the first pass
750 * to parse it correctly.
751 *
752 * Save the length and address of the body
753 */
754 op->named.data = parser_state->aml;
755 op->named.length = (u32) (parser_state->pkg_end - parser_state->aml);
756
757 /* Skip body of method */
758
759 parser_state->aml = parser_state->pkg_end;
760 walk_state->arg_count = 0;
761 break;
762
763 case AML_BUFFER_OP:
764 case AML_PACKAGE_OP:
765 case AML_VAR_PACKAGE_OP:
766
767 if ((op->common.parent) &&
768 (op->common.parent->common.aml_opcode == AML_NAME_OP) &&
769 (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
770 /*
771 * Skip parsing of Buffers and Packages
772 * because we don't have enough info in the first pass
773 * to parse them correctly.
774 */
775 op->named.data = aml_op_start;
776 op->named.length = (u32) (parser_state->pkg_end - aml_op_start);
777
778 /* Skip body */
779
780 parser_state->aml = parser_state->pkg_end;
781 walk_state->arg_count = 0;
782 }
783 break;
784
785 case AML_WHILE_OP:
786
787 if (walk_state->control_state) {
788 walk_state->control_state->control.package_end = parser_state->pkg_end;
789 }
790 break;
791
792 default:
793
794 /* No action for all other opcodes */
795 break;
796 }
797 break;
798 }
799 }
800
801 /* Check for arguments that need to be processed */
802
803 if (walk_state->arg_count) {
804 /* There are arguments (complex ones), push Op and prepare for argument */
805
806 status = acpi_ps_push_scope (parser_state, op,
807 walk_state->arg_types, walk_state->arg_count);
808 if (ACPI_FAILURE (status)) {
809 goto close_this_op;
810 }
811 op = NULL;
812 continue;
813 }
814
815 /* All arguments have been processed -- Op is complete, prepare for next */
816
817 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
818 if (walk_state->op_info->flags & AML_NAMED) {
819 if (acpi_gbl_depth) {
820 acpi_gbl_depth--;
821 }
822
823 if (op->common.aml_opcode == AML_REGION_OP) {
824 /*
825 * Skip parsing of control method or opregion body,
826 * because we don't have enough info in the first pass
827 * to parse them correctly.
828 *
829 * Completed parsing an op_region declaration, we now
830 * know the length.
831 */
832 op->named.length = (u32) (parser_state->aml - op->named.data);
833 }
834 }
835
836 if (walk_state->op_info->flags & AML_CREATE) {
837 /*
838 * Backup to beginning of create_xXXfield declaration (1 for
839 * Opcode)
840 *
841 * body_length is unknown until we parse the body
842 */
843 op->named.length = (u32) (parser_state->aml - op->named.data);
844 }
845
846 /* This op complete, notify the dispatcher */
847
848 if (walk_state->ascending_callback != NULL) {
849 walk_state->op = op;
850 walk_state->opcode = op->common.aml_opcode;
851
852 status = walk_state->ascending_callback (walk_state);
853 status = acpi_ps_next_parse_state (walk_state, op, status);
854 if (status == AE_CTRL_PENDING) {
855 status = AE_OK;
856 goto close_this_op;
857 }
858 }
859
860
861close_this_op:
862 /*
863 * Finished one argument of the containing scope
864 */
865 parser_state->scope->parse_scope.arg_count--;
866
867 /* Close this Op (will result in parse subtree deletion) */
868
869 acpi_ps_complete_this_op (walk_state, op);
870 op = NULL;
871 if (pre_op) {
872 acpi_ps_free_op (pre_op);
873 pre_op = NULL;
874 }
875
876 switch (status) {
877 case AE_OK:
878 break;
879
880
881 case AE_CTRL_TRANSFER:
882
883 /*
884 * We are about to transfer to a called method.
885 */
886 walk_state->prev_op = op;
887 walk_state->prev_arg_types = walk_state->arg_types;
888 return_ACPI_STATUS (status);
889
890
891 case AE_CTRL_END:
892
893 acpi_ps_pop_scope (parser_state, &op,
894 &walk_state->arg_types, &walk_state->arg_count);
895
896 if (op) {
897 walk_state->op = op;
898 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
899 walk_state->opcode = op->common.aml_opcode;
900
901 status = walk_state->ascending_callback (walk_state);
902 status = acpi_ps_next_parse_state (walk_state, op, status);
903
904 acpi_ps_complete_this_op (walk_state, op);
905 op = NULL;
906 }
907 status = AE_OK;
908 break;
909
910
911 case AE_CTRL_BREAK:
912 case AE_CTRL_CONTINUE:
913
914 /* Pop off scopes until we find the While */
915
916 while (!op || (op->common.aml_opcode != AML_WHILE_OP)) {
917 acpi_ps_pop_scope (parser_state, &op,
918 &walk_state->arg_types, &walk_state->arg_count);
919 }
920
921 /* Close this iteration of the While loop */
922
923 walk_state->op = op;
924 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
925 walk_state->opcode = op->common.aml_opcode;
926
927 status = walk_state->ascending_callback (walk_state);
928 status = acpi_ps_next_parse_state (walk_state, op, status);
929
930 acpi_ps_complete_this_op (walk_state, op);
931 op = NULL;
932
933 status = AE_OK;
934 break;
935
936
937 case AE_CTRL_TERMINATE:
938
939 status = AE_OK;
940
941 /* Clean up */
942 do {
943 if (op) {
944 acpi_ps_complete_this_op (walk_state, op);
945 }
946 acpi_ps_pop_scope (parser_state, &op,
947 &walk_state->arg_types, &walk_state->arg_count);
948
949 } while (op);
950
951 return_ACPI_STATUS (status);
952
953
954 default: /* All other non-AE_OK status */
955
956 do {
957 if (op) {
958 acpi_ps_complete_this_op (walk_state, op);
959 }
960 acpi_ps_pop_scope (parser_state, &op,
961 &walk_state->arg_types, &walk_state->arg_count);
962
963 } while (op);
964
965
966 /*
967 * TBD: Cleanup parse ops on error
968 */
969#if 0
970 if (op == NULL) {
971 acpi_ps_pop_scope (parser_state, &op,
972 &walk_state->arg_types, &walk_state->arg_count);
973 }
974#endif
975 walk_state->prev_op = op;
976 walk_state->prev_arg_types = walk_state->arg_types;
977 return_ACPI_STATUS (status);
978 }
979
980 /* This scope complete? */
981
982 if (acpi_ps_has_completed_scope (parser_state)) {
983 acpi_ps_pop_scope (parser_state, &op,
984 &walk_state->arg_types, &walk_state->arg_count);
985 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op));
986 }
987 else {
988 op = NULL;
989 }
990
991 } /* while parser_state->Aml */
992
993
994 /*
995 * Complete the last Op (if not completed), and clear the scope stack.
996 * It is easily possible to end an AML "package" with an unbounded number
997 * of open scopes (such as when several ASL blocks are closed with
998 * sequential closing braces). We want to terminate each one cleanly.
999 */
1000 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", op));
1001 do {
1002 if (op) {
1003 if (walk_state->ascending_callback != NULL) {
1004 walk_state->op = op;
1005 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
1006 walk_state->opcode = op->common.aml_opcode;
1007
1008 status = walk_state->ascending_callback (walk_state);
1009 status = acpi_ps_next_parse_state (walk_state, op, status);
1010 if (status == AE_CTRL_PENDING) {
1011 status = AE_OK;
1012 goto close_this_op;
1013 }
1014
1015 if (status == AE_CTRL_TERMINATE) {
1016 status = AE_OK;
1017
1018 /* Clean up */
1019 do {
1020 if (op) {
1021 acpi_ps_complete_this_op (walk_state, op);
1022 }
1023
1024 acpi_ps_pop_scope (parser_state, &op,
1025 &walk_state->arg_types, &walk_state->arg_count);
1026
1027 } while (op);
1028
1029 return_ACPI_STATUS (status);
1030 }
1031
1032 else if (ACPI_FAILURE (status)) {
1033 acpi_ps_complete_this_op (walk_state, op);
1034 return_ACPI_STATUS (status);
1035 }
1036 }
1037
1038 acpi_ps_complete_this_op (walk_state, op);
1039 }
1040
1041 acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types,
1042 &walk_state->arg_count);
1043
1044 } while (op);
1045
1046 return_ACPI_STATUS (status);
1047}
1048
1049
1050/*******************************************************************************
1051 *
1052 * FUNCTION: acpi_ps_parse_aml
1053 *
1054 * PARAMETERS: start_scope - The starting point of the parse. Becomes the
1055 * root of the parsed op tree.
1056 * Aml - Pointer to the raw AML code to parse
1057 * aml_size - Length of the AML to parse
1058 *
1059 *
1060 * RETURN: Status
1061 *
1062 * DESCRIPTION: Parse raw AML and return a tree of ops
1063 *
1064 ******************************************************************************/
1065
1066acpi_status
1067acpi_ps_parse_aml (
1068 struct acpi_walk_state *walk_state)
1069{
1070 acpi_status status;
1071 acpi_status terminate_status;
1072 struct acpi_thread_state *thread;
1073 struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list;
1074 struct acpi_walk_state *previous_walk_state;
1075
1076
1077 ACPI_FUNCTION_TRACE ("ps_parse_aml");
1078
1079 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Entered with walk_state=%p Aml=%p size=%X\n",
1080 walk_state, walk_state->parser_state.aml, walk_state->parser_state.aml_size));
1081
1082
1083 /* Create and initialize a new thread state */
1084
1085 thread = acpi_ut_create_thread_state ();
1086 if (!thread) {
1087 return_ACPI_STATUS (AE_NO_MEMORY);
1088 }
1089
1090 walk_state->thread = thread;
1091 acpi_ds_push_walk_state (walk_state, thread);
1092
1093 /*
1094 * This global allows the AML debugger to get a handle to the currently
1095 * executing control method.
1096 */
1097 acpi_gbl_current_walk_list = thread;
1098
1099 /*
1100 * Execute the walk loop as long as there is a valid Walk State. This
1101 * handles nested control method invocations without recursion.
1102 */
1103 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", walk_state));
1104
1105 status = AE_OK;
1106 while (walk_state) {
1107 if (ACPI_SUCCESS (status)) {
1108 /*
1109 * The parse_loop executes AML until the method terminates
1110 * or calls another method.
1111 */
1112 status = acpi_ps_parse_loop (walk_state);
1113 }
1114
1115 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
1116 "Completed one call to walk loop, %s State=%p\n",
1117 acpi_format_exception (status), walk_state));
1118
1119 if (status == AE_CTRL_TRANSFER) {
1120 /*
1121 * A method call was detected.
1122 * Transfer control to the called control method
1123 */
1124 status = acpi_ds_call_control_method (thread, walk_state, NULL);
1125
1126 /*
1127 * If the transfer to the new method method call worked, a new walk
1128 * state was created -- get it
1129 */
1130 walk_state = acpi_ds_get_current_walk_state (thread);
1131 continue;
1132 }
1133 else if (status == AE_CTRL_TERMINATE) {
1134 status = AE_OK;
1135 }
1136 else if ((status != AE_OK) && (walk_state->method_desc)) {
1137 ACPI_REPORT_METHOD_ERROR ("Method execution failed",
1138 walk_state->method_node, NULL, status);
1139
1140 /* Check for possible multi-thread reentrancy problem */
1141
1142 if ((status == AE_ALREADY_EXISTS) &&
1143 (!walk_state->method_desc->method.semaphore)) {
1144 /*
1145 * This method is marked not_serialized, but it tried to create a named
1146 * object, causing the second thread entrance to fail. We will workaround
1147 * this by marking the method permanently as Serialized.
1148 */
1149 walk_state->method_desc->method.method_flags |= AML_METHOD_SERIALIZED;
1150 walk_state->method_desc->method.concurrency = 1;
1151 }
1152 }
1153
1154 if (walk_state->method_desc) {
1155 /* Decrement the thread count on the method parse tree */
1156
1157 if (walk_state->method_desc->method.thread_count) {
1158 walk_state->method_desc->method.thread_count--;
1159 }
1160 }
1161
1162 /* We are done with this walk, move on to the parent if any */
1163
1164 walk_state = acpi_ds_pop_walk_state (thread);
1165
1166 /* Reset the current scope to the beginning of scope stack */
1167
1168 acpi_ds_scope_stack_clear (walk_state);
1169
1170 /*
1171 * If we just returned from the execution of a control method,
1172 * there's lots of cleanup to do
1173 */
1174 if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) {
1175 terminate_status = acpi_ds_terminate_control_method (walk_state);
1176 if (ACPI_FAILURE (terminate_status)) {
1177 ACPI_REPORT_ERROR ((
1178 "Could not terminate control method properly\n"));
1179
1180 /* Ignore error and continue */
1181 }
1182 }
1183
1184 /* Delete this walk state and all linked control states */
1185
1186 acpi_ps_cleanup_scope (&walk_state->parser_state);
1187
1188 previous_walk_state = walk_state;
1189
1190 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p, implicit_value=%p State=%p\n",
1191 walk_state->return_desc, walk_state->implicit_return_obj, walk_state));
1192
1193 /* Check if we have restarted a preempted walk */
1194
1195 walk_state = acpi_ds_get_current_walk_state (thread);
1196 if (walk_state) {
1197 if (ACPI_SUCCESS (status)) {
1198 /*
1199 * There is another walk state, restart it.
1200 * If the method return value is not used by the parent,
1201 * The object is deleted
1202 */
1203 if (!previous_walk_state->return_desc) {
1204 status = acpi_ds_restart_control_method (walk_state,
1205 previous_walk_state->implicit_return_obj);
1206 }
1207 else {
1208 /*
1209 * We have a valid return value, delete any implicit
1210 * return value.
1211 */
1212 acpi_ds_clear_implicit_return (previous_walk_state);
1213
1214 status = acpi_ds_restart_control_method (walk_state,
1215 previous_walk_state->return_desc);
1216 }
1217 if (ACPI_SUCCESS (status)) {
1218 walk_state->walk_type |= ACPI_WALK_METHOD_RESTART;
1219 }
1220 }
1221 else {
1222 /* On error, delete any return object */
1223
1224 acpi_ut_remove_reference (previous_walk_state->return_desc);
1225 }
1226 }
1227
1228 /*
1229 * Just completed a 1st-level method, save the final internal return
1230 * value (if any)
1231 */
1232 else if (previous_walk_state->caller_return_desc) {
1233 if (previous_walk_state->implicit_return_obj) {
1234 *(previous_walk_state->caller_return_desc) = previous_walk_state->implicit_return_obj;
1235 }
1236 else {
1237 /* NULL if no return value */
1238
1239 *(previous_walk_state->caller_return_desc) = previous_walk_state->return_desc;
1240 }
1241 }
1242 else {
1243 if (previous_walk_state->return_desc) {
1244 /* Caller doesn't want it, must delete it */
1245
1246 acpi_ut_remove_reference (previous_walk_state->return_desc);
1247 }
1248 if (previous_walk_state->implicit_return_obj) {
1249 /* Caller doesn't want it, must delete it */
1250
1251 acpi_ut_remove_reference (previous_walk_state->implicit_return_obj);
1252 }
1253 }
1254
1255 acpi_ds_delete_walk_state (previous_walk_state);
1256 }
1257
1258 /* Normal exit */
1259
1260 acpi_ex_release_all_mutexes (thread);
1261 acpi_ut_delete_generic_state (ACPI_CAST_PTR (union acpi_generic_state, thread));
1262 acpi_gbl_current_walk_list = prev_walk_list;
1263 return_ACPI_STATUS (status);
1264}
1265
1266
diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c
new file mode 100644
index 000000000000..dcbed49608b0
--- /dev/null
+++ b/drivers/acpi/parser/psscope.c
@@ -0,0 +1,290 @@
1/******************************************************************************
2 *
3 * Module Name: psscope - Parser scope stack management routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47
48#define _COMPONENT ACPI_PARSER
49 ACPI_MODULE_NAME ("psscope")
50
51
52/*******************************************************************************
53 *
54 * FUNCTION: acpi_ps_get_parent_scope
55 *
56 * PARAMETERS: parser_state - Current parser state object
57 *
58 * RETURN: Pointer to an Op object
59 *
60 * DESCRIPTION: Get parent of current op being parsed
61 *
62 ******************************************************************************/
63
64union acpi_parse_object *
65acpi_ps_get_parent_scope (
66 struct acpi_parse_state *parser_state)
67{
68 return (parser_state->scope->parse_scope.op);
69}
70
71
72/*******************************************************************************
73 *
74 * FUNCTION: acpi_ps_has_completed_scope
75 *
76 * PARAMETERS: parser_state - Current parser state object
77 *
78 * RETURN: Boolean, TRUE = scope completed.
79 *
80 * DESCRIPTION: Is parsing of current argument complete? Determined by
81 * 1) AML pointer is at or beyond the end of the scope
82 * 2) The scope argument count has reached zero.
83 *
84 ******************************************************************************/
85
86u8
87acpi_ps_has_completed_scope (
88 struct acpi_parse_state *parser_state)
89{
90 return ((u8) ((parser_state->aml >= parser_state->scope->parse_scope.arg_end ||
91 !parser_state->scope->parse_scope.arg_count)));
92}
93
94
95/*******************************************************************************
96 *
97 * FUNCTION: acpi_ps_init_scope
98 *
99 * PARAMETERS: parser_state - Current parser state object
100 * Root - the Root Node of this new scope
101 *
102 * RETURN: Status
103 *
104 * DESCRIPTION: Allocate and init a new scope object
105 *
106 ******************************************************************************/
107
108acpi_status
109acpi_ps_init_scope (
110 struct acpi_parse_state *parser_state,
111 union acpi_parse_object *root_op)
112{
113 union acpi_generic_state *scope;
114
115
116 ACPI_FUNCTION_TRACE_PTR ("ps_init_scope", root_op);
117
118
119 scope = acpi_ut_create_generic_state ();
120 if (!scope) {
121 return_ACPI_STATUS (AE_NO_MEMORY);
122 }
123
124 scope->common.data_type = ACPI_DESC_TYPE_STATE_RPSCOPE;
125 scope->parse_scope.op = root_op;
126 scope->parse_scope.arg_count = ACPI_VAR_ARGS;
127 scope->parse_scope.arg_end = parser_state->aml_end;
128 scope->parse_scope.pkg_end = parser_state->aml_end;
129
130 parser_state->scope = scope;
131 parser_state->start_op = root_op;
132
133 return_ACPI_STATUS (AE_OK);
134}
135
136
137/*******************************************************************************
138 *
139 * FUNCTION: acpi_ps_push_scope
140 *
141 * PARAMETERS: parser_state - Current parser state object
142 * Op - Current op to be pushed
143 * remaining_args - List of args remaining
144 * arg_count - Fixed or variable number of args
145 *
146 * RETURN: Status
147 *
148 * DESCRIPTION: Push current op to begin parsing its argument
149 *
150 ******************************************************************************/
151
152acpi_status
153acpi_ps_push_scope (
154 struct acpi_parse_state *parser_state,
155 union acpi_parse_object *op,
156 u32 remaining_args,
157 u32 arg_count)
158{
159 union acpi_generic_state *scope;
160
161
162 ACPI_FUNCTION_TRACE_PTR ("ps_push_scope", op);
163
164
165 scope = acpi_ut_create_generic_state ();
166 if (!scope) {
167 return_ACPI_STATUS (AE_NO_MEMORY);
168 }
169
170 scope->common.data_type = ACPI_DESC_TYPE_STATE_PSCOPE;
171 scope->parse_scope.op = op;
172 scope->parse_scope.arg_list = remaining_args;
173 scope->parse_scope.arg_count = arg_count;
174 scope->parse_scope.pkg_end = parser_state->pkg_end;
175
176 /* Push onto scope stack */
177
178 acpi_ut_push_generic_state (&parser_state->scope, scope);
179
180 if (arg_count == ACPI_VAR_ARGS) {
181 /* multiple arguments */
182
183 scope->parse_scope.arg_end = parser_state->pkg_end;
184 }
185 else {
186 /* single argument */
187
188 scope->parse_scope.arg_end = ACPI_TO_POINTER (ACPI_MAX_PTR);
189 }
190
191 return_ACPI_STATUS (AE_OK);
192}
193
194
195/*******************************************************************************
196 *
197 * FUNCTION: acpi_ps_pop_scope
198 *
199 * PARAMETERS: parser_state - Current parser state object
200 * Op - Where the popped op is returned
201 * arg_list - Where the popped "next argument" is
202 * returned
203 * arg_count - Count of objects in arg_list
204 *
205 * RETURN: Status
206 *
207 * DESCRIPTION: Return to parsing a previous op
208 *
209 ******************************************************************************/
210
211void
212acpi_ps_pop_scope (
213 struct acpi_parse_state *parser_state,
214 union acpi_parse_object **op,
215 u32 *arg_list,
216 u32 *arg_count)
217{
218 union acpi_generic_state *scope = parser_state->scope;
219
220
221 ACPI_FUNCTION_TRACE ("ps_pop_scope");
222
223
224 /*
225 * Only pop the scope if there is in fact a next scope
226 */
227 if (scope->common.next) {
228 scope = acpi_ut_pop_generic_state (&parser_state->scope);
229
230 /* return to parsing previous op */
231
232 *op = scope->parse_scope.op;
233 *arg_list = scope->parse_scope.arg_list;
234 *arg_count = scope->parse_scope.arg_count;
235 parser_state->pkg_end = scope->parse_scope.pkg_end;
236
237 /* All done with this scope state structure */
238
239 acpi_ut_delete_generic_state (scope);
240 }
241 else {
242 /* empty parse stack, prepare to fetch next opcode */
243
244 *op = NULL;
245 *arg_list = 0;
246 *arg_count = 0;
247 }
248
249 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped Op %p Args %X\n", *op, *arg_count));
250 return_VOID;
251}
252
253
254/*******************************************************************************
255 *
256 * FUNCTION: acpi_ps_cleanup_scope
257 *
258 * PARAMETERS: parser_state - Current parser state object
259 *
260 * RETURN: Status
261 *
262 * DESCRIPTION: Destroy available list, remaining stack levels, and return
263 * root scope
264 *
265 ******************************************************************************/
266
267void
268acpi_ps_cleanup_scope (
269 struct acpi_parse_state *parser_state)
270{
271 union acpi_generic_state *scope;
272
273
274 ACPI_FUNCTION_TRACE_PTR ("ps_cleanup_scope", parser_state);
275
276
277 if (!parser_state) {
278 return_VOID;
279 }
280
281 /* Delete anything on the scope stack */
282
283 while (parser_state->scope) {
284 scope = acpi_ut_pop_generic_state (&parser_state->scope);
285 acpi_ut_delete_generic_state (scope);
286 }
287
288 return_VOID;
289}
290
diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c
new file mode 100644
index 000000000000..2140bd1ac10b
--- /dev/null
+++ b/drivers/acpi/parser/pstree.c
@@ -0,0 +1,327 @@
1/******************************************************************************
2 *
3 * Module Name: pstree - Parser op tree manipulation/traversal/search
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/amlcode.h>
48
49#define _COMPONENT ACPI_PARSER
50 ACPI_MODULE_NAME ("pstree")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ps_get_arg
56 *
57 * PARAMETERS: Op - Get an argument for this op
58 * Argn - Nth argument to get
59 *
60 * RETURN: The argument (as an Op object). NULL if argument does not exist
61 *
62 * DESCRIPTION: Get the specified op's argument.
63 *
64 ******************************************************************************/
65
66union acpi_parse_object *
67acpi_ps_get_arg (
68 union acpi_parse_object *op,
69 u32 argn)
70{
71 union acpi_parse_object *arg = NULL;
72 const struct acpi_opcode_info *op_info;
73
74
75 ACPI_FUNCTION_ENTRY ();
76
77
78 /* Get the info structure for this opcode */
79
80 op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
81 if (op_info->class == AML_CLASS_UNKNOWN) {
82 /* Invalid opcode or ASCII character */
83
84 return (NULL);
85 }
86
87 /* Check if this opcode requires argument sub-objects */
88
89 if (!(op_info->flags & AML_HAS_ARGS)) {
90 /* Has no linked argument objects */
91
92 return (NULL);
93 }
94
95 /* Get the requested argument object */
96
97 arg = op->common.value.arg;
98 while (arg && argn) {
99 argn--;
100 arg = arg->common.next;
101 }
102
103 return (arg);
104}
105
106
107/*******************************************************************************
108 *
109 * FUNCTION: acpi_ps_append_arg
110 *
111 * PARAMETERS: Op - Append an argument to this Op.
112 * Arg - Argument Op to append
113 *
114 * RETURN: None.
115 *
116 * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK)
117 *
118 ******************************************************************************/
119
120void
121acpi_ps_append_arg (
122 union acpi_parse_object *op,
123 union acpi_parse_object *arg)
124{
125 union acpi_parse_object *prev_arg;
126 const struct acpi_opcode_info *op_info;
127
128
129 ACPI_FUNCTION_ENTRY ();
130
131
132 if (!op) {
133 return;
134 }
135
136 /* Get the info structure for this opcode */
137
138 op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
139 if (op_info->class == AML_CLASS_UNKNOWN) {
140 /* Invalid opcode */
141
142 ACPI_REPORT_ERROR (("ps_append_arg: Invalid AML Opcode: 0x%2.2X\n",
143 op->common.aml_opcode));
144 return;
145 }
146
147 /* Check if this opcode requires argument sub-objects */
148
149 if (!(op_info->flags & AML_HAS_ARGS)) {
150 /* Has no linked argument objects */
151
152 return;
153 }
154
155
156 /* Append the argument to the linked argument list */
157
158 if (op->common.value.arg) {
159 /* Append to existing argument list */
160
161 prev_arg = op->common.value.arg;
162 while (prev_arg->common.next) {
163 prev_arg = prev_arg->common.next;
164 }
165 prev_arg->common.next = arg;
166 }
167
168 else {
169 /* No argument list, this will be the first argument */
170
171 op->common.value.arg = arg;
172 }
173
174
175 /* Set the parent in this arg and any args linked after it */
176
177 while (arg) {
178 arg->common.parent = op;
179 arg = arg->common.next;
180 }
181}
182
183
184#ifdef ACPI_FUTURE_USAGE
185
186/*******************************************************************************
187 *
188 * FUNCTION: acpi_ps_get_child
189 *
190 * PARAMETERS: Op - Get the child of this Op
191 *
192 * RETURN: Child Op, Null if none is found.
193 *
194 * DESCRIPTION: Get op's children or NULL if none
195 *
196 ******************************************************************************/
197union acpi_parse_object *
198acpi_ps_get_child (
199 union acpi_parse_object *op)
200{
201 union acpi_parse_object *child = NULL;
202
203
204 ACPI_FUNCTION_ENTRY ();
205
206
207 switch (op->common.aml_opcode) {
208 case AML_SCOPE_OP:
209 case AML_ELSE_OP:
210 case AML_DEVICE_OP:
211 case AML_THERMAL_ZONE_OP:
212 case AML_INT_METHODCALL_OP:
213
214 child = acpi_ps_get_arg (op, 0);
215 break;
216
217
218 case AML_BUFFER_OP:
219 case AML_PACKAGE_OP:
220 case AML_METHOD_OP:
221 case AML_IF_OP:
222 case AML_WHILE_OP:
223 case AML_FIELD_OP:
224
225 child = acpi_ps_get_arg (op, 1);
226 break;
227
228
229 case AML_POWER_RES_OP:
230 case AML_INDEX_FIELD_OP:
231
232 child = acpi_ps_get_arg (op, 2);
233 break;
234
235
236 case AML_PROCESSOR_OP:
237 case AML_BANK_FIELD_OP:
238
239 child = acpi_ps_get_arg (op, 3);
240 break;
241
242
243 default:
244 /* All others have no children */
245 break;
246 }
247
248 return (child);
249}
250
251
252/*******************************************************************************
253 *
254 * FUNCTION: acpi_ps_get_depth_next
255 *
256 * PARAMETERS: Origin - Root of subtree to search
257 * Op - Last (previous) Op that was found
258 *
259 * RETURN: Next Op found in the search.
260 *
261 * DESCRIPTION: Get next op in tree (walking the tree in depth-first order)
262 * Return NULL when reaching "origin" or when walking up from root
263 *
264 ******************************************************************************/
265
266union acpi_parse_object *
267acpi_ps_get_depth_next (
268 union acpi_parse_object *origin,
269 union acpi_parse_object *op)
270{
271 union acpi_parse_object *next = NULL;
272 union acpi_parse_object *parent;
273 union acpi_parse_object *arg;
274
275
276 ACPI_FUNCTION_ENTRY ();
277
278
279 if (!op) {
280 return (NULL);
281 }
282
283 /* look for an argument or child */
284
285 next = acpi_ps_get_arg (op, 0);
286 if (next) {
287 return (next);
288 }
289
290 /* look for a sibling */
291
292 next = op->common.next;
293 if (next) {
294 return (next);
295 }
296
297 /* look for a sibling of parent */
298
299 parent = op->common.parent;
300
301 while (parent) {
302 arg = acpi_ps_get_arg (parent, 0);
303 while (arg && (arg != origin) && (arg != op)) {
304 arg = arg->common.next;
305 }
306
307 if (arg == origin) {
308 /* reached parent of origin, end search */
309
310 return (NULL);
311 }
312
313 if (parent->common.next) {
314 /* found sibling of parent */
315
316 return (parent->common.next);
317 }
318
319 op = parent;
320 parent = parent->common.parent;
321 }
322
323 return (next);
324}
325
326#endif /* ACPI_FUTURE_USAGE */
327
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
new file mode 100644
index 000000000000..b3597cb19f88
--- /dev/null
+++ b/drivers/acpi/parser/psutils.c
@@ -0,0 +1,309 @@
1/******************************************************************************
2 *
3 * Module Name: psutils - Parser miscellaneous utilities (Parser only)
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/amlcode.h>
48#include <acpi/acnamesp.h>
49
50#define _COMPONENT ACPI_PARSER
51 ACPI_MODULE_NAME ("psutils")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ps_create_scope_op
57 *
58 * PARAMETERS: None
59 *
60 * RETURN: scope_op
61 *
62 * DESCRIPTION: Create a Scope and associated namepath op with the root name
63 *
64 ******************************************************************************/
65
66union acpi_parse_object *
67acpi_ps_create_scope_op (
68 void)
69{
70 union acpi_parse_object *scope_op;
71
72
73 scope_op = acpi_ps_alloc_op (AML_SCOPE_OP);
74 if (!scope_op) {
75 return (NULL);
76 }
77
78
79 scope_op->named.name = ACPI_ROOT_NAME;
80 return (scope_op);
81}
82
83
84/*******************************************************************************
85 *
86 * FUNCTION: acpi_ps_init_op
87 *
88 * PARAMETERS: Op - A newly allocated Op object
89 * Opcode - Opcode to store in the Op
90 *
91 * RETURN: Status
92 *
93 * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on
94 * opcode
95 *
96 ******************************************************************************/
97
98void
99acpi_ps_init_op (
100 union acpi_parse_object *op,
101 u16 opcode)
102{
103 ACPI_FUNCTION_ENTRY ();
104
105
106 op->common.data_type = ACPI_DESC_TYPE_PARSER;
107 op->common.aml_opcode = opcode;
108
109 ACPI_DISASM_ONLY_MEMBERS (ACPI_STRNCPY (op->common.aml_op_name,
110 (acpi_ps_get_opcode_info (opcode))->name, sizeof (op->common.aml_op_name)));
111}
112
113
114/*******************************************************************************
115 *
116 * FUNCTION: acpi_ps_alloc_op
117 *
118 * PARAMETERS: Opcode - Opcode that will be stored in the new Op
119 *
120 * RETURN: Pointer to the new Op.
121 *
122 * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on
123 * opcode. A cache of opcodes is available for the pure
124 * GENERIC_OP, since this is by far the most commonly used.
125 *
126 ******************************************************************************/
127
128union acpi_parse_object*
129acpi_ps_alloc_op (
130 u16 opcode)
131{
132 union acpi_parse_object *op;
133 const struct acpi_opcode_info *op_info;
134 u8 flags = ACPI_PARSEOP_GENERIC;
135
136
137 ACPI_FUNCTION_ENTRY ();
138
139
140 op_info = acpi_ps_get_opcode_info (opcode);
141
142 /* Determine type of parse_op required */
143
144 if (op_info->flags & AML_DEFER) {
145 flags = ACPI_PARSEOP_DEFERRED;
146 }
147 else if (op_info->flags & AML_NAMED) {
148 flags = ACPI_PARSEOP_NAMED;
149 }
150 else if (opcode == AML_INT_BYTELIST_OP) {
151 flags = ACPI_PARSEOP_BYTELIST;
152 }
153
154 /* Allocate the minimum required size object */
155
156 if (flags == ACPI_PARSEOP_GENERIC) {
157 /* The generic op (default) is by far the most common (16 to 1) */
158
159 op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE);
160 }
161 else {
162 /* Extended parseop */
163
164 op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE_EXT);
165 }
166
167 /* Initialize the Op */
168
169 if (op) {
170 acpi_ps_init_op (op, opcode);
171 op->common.flags = flags;
172 }
173
174 return (op);
175}
176
177
178/*******************************************************************************
179 *
180 * FUNCTION: acpi_ps_free_op
181 *
182 * PARAMETERS: Op - Op to be freed
183 *
184 * RETURN: None.
185 *
186 * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list
187 * or actually free it.
188 *
189 ******************************************************************************/
190
191void
192acpi_ps_free_op (
193 union acpi_parse_object *op)
194{
195 ACPI_FUNCTION_NAME ("ps_free_op");
196
197
198 if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
199 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n", op));
200 }
201
202 if (op->common.flags & ACPI_PARSEOP_GENERIC) {
203 acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE, op);
204 }
205 else {
206 acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE_EXT, op);
207 }
208}
209
210
211#ifdef ACPI_ENABLE_OBJECT_CACHE
212/*******************************************************************************
213 *
214 * FUNCTION: acpi_ps_delete_parse_cache
215 *
216 * PARAMETERS: None
217 *
218 * RETURN: None
219 *
220 * DESCRIPTION: Free all objects that are on the parse cache list.
221 *
222 ******************************************************************************/
223
224void
225acpi_ps_delete_parse_cache (
226 void)
227{
228 ACPI_FUNCTION_TRACE ("ps_delete_parse_cache");
229
230
231 acpi_ut_delete_generic_cache (ACPI_MEM_LIST_PSNODE);
232 acpi_ut_delete_generic_cache (ACPI_MEM_LIST_PSNODE_EXT);
233 return_VOID;
234}
235#endif
236
237
238/*******************************************************************************
239 *
240 * FUNCTION: Utility functions
241 *
242 * DESCRIPTION: Low level character and object functions
243 *
244 ******************************************************************************/
245
246
247/*
248 * Is "c" a namestring lead character?
249 */
250u8
251acpi_ps_is_leading_char (
252 u32 c)
253{
254 return ((u8) (c == '_' || (c >= 'A' && c <= 'Z')));
255}
256
257
258/*
259 * Is "c" a namestring prefix character?
260 */
261u8
262acpi_ps_is_prefix_char (
263 u32 c)
264{
265 return ((u8) (c == '\\' || c == '^'));
266}
267
268
269/*
270 * Get op's name (4-byte name segment) or 0 if unnamed
271 */
272#ifdef ACPI_FUTURE_USAGE
273u32
274acpi_ps_get_name (
275 union acpi_parse_object *op)
276{
277
278
279 /* The "generic" object has no name associated with it */
280
281 if (op->common.flags & ACPI_PARSEOP_GENERIC) {
282 return (0);
283 }
284
285 /* Only the "Extended" parse objects have a name */
286
287 return (op->named.name);
288}
289#endif /* ACPI_FUTURE_USAGE */
290
291
292/*
293 * Set op's name
294 */
295void
296acpi_ps_set_name (
297 union acpi_parse_object *op,
298 u32 name)
299{
300
301 /* The "generic" object has no name associated with it */
302
303 if (op->common.flags & ACPI_PARSEOP_GENERIC) {
304 return;
305 }
306
307 op->named.name = name;
308}
309
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
new file mode 100644
index 000000000000..110d2ce917b6
--- /dev/null
+++ b/drivers/acpi/parser/pswalk.c
@@ -0,0 +1,115 @@
1/******************************************************************************
2 *
3 * Module Name: pswalk - Parser routines to walk parsed op tree(s)
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47
48#define _COMPONENT ACPI_PARSER
49 ACPI_MODULE_NAME ("pswalk")
50
51
52/*******************************************************************************
53 *
54 * FUNCTION: acpi_ps_delete_parse_tree
55 *
56 * PARAMETERS: subtree_root - Root of tree (or subtree) to delete
57 *
58 * RETURN: None
59 *
60 * DESCRIPTION: Delete a portion of or an entire parse tree.
61 *
62 ******************************************************************************/
63
64void
65acpi_ps_delete_parse_tree (
66 union acpi_parse_object *subtree_root)
67{
68 union acpi_parse_object *op = subtree_root;
69 union acpi_parse_object *next = NULL;
70 union acpi_parse_object *parent = NULL;
71
72
73 ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root);
74
75
76 /* Visit all nodes in the subtree */
77
78 while (op) {
79 /* Check if we are not ascending */
80
81 if (op != parent) {
82 /* Look for an argument or child of the current op */
83
84 next = acpi_ps_get_arg (op, 0);
85 if (next) {
86 /* Still going downward in tree (Op is not completed yet) */
87
88 op = next;
89 continue;
90 }
91 }
92
93 /*
94 * No more children, this Op is complete.
95 */
96 next = op->common.next;
97 parent = op->common.parent;
98
99 acpi_ps_free_op (op);
100
101 /*
102 * If we are back to the starting point, the walk is complete.
103 */
104 if (op == subtree_root) {
105 return_VOID;
106 }
107 if (next) {
108 op = next;
109 }
110 else {
111 op = parent;
112 }
113 }
114 return_VOID;
115}
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
new file mode 100644
index 000000000000..b318ad24726d
--- /dev/null
+++ b/drivers/acpi/parser/psxface.c
@@ -0,0 +1,243 @@
1/******************************************************************************
2 *
3 * Module Name: psxface - Parser external interfaces
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/acdispat.h>
48#include <acpi/acinterp.h>
49#include <acpi/acnamesp.h>
50
51
52#define _COMPONENT ACPI_PARSER
53 ACPI_MODULE_NAME ("psxface")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_psx_execute
59 *
60 * PARAMETERS: Info->Node - A method object containing both the AML
61 * address and length.
62 * **Params - List of parameters to pass to method,
63 * terminated by NULL. Params itself may be
64 * NULL if no parameters are being passed.
65 * **return_obj_desc - Return object from execution of the
66 * method.
67 *
68 * RETURN: Status
69 *
70 * DESCRIPTION: Execute a control method
71 *
72 ******************************************************************************/
73
74acpi_status
75acpi_psx_execute (
76 struct acpi_parameter_info *info)
77{
78 acpi_status status;
79 union acpi_operand_object *obj_desc;
80 u32 i;
81 union acpi_parse_object *op;
82 struct acpi_walk_state *walk_state;
83
84
85 ACPI_FUNCTION_TRACE ("psx_execute");
86
87
88 /* Validate the Node and get the attached object */
89
90 if (!info || !info->node) {
91 return_ACPI_STATUS (AE_NULL_ENTRY);
92 }
93
94 obj_desc = acpi_ns_get_attached_object (info->node);
95 if (!obj_desc) {
96 return_ACPI_STATUS (AE_NULL_OBJECT);
97 }
98
99 /* Init for new method, wait on concurrency semaphore */
100
101 status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL);
102 if (ACPI_FAILURE (status)) {
103 return_ACPI_STATUS (status);
104 }
105
106 if ((info->parameter_type == ACPI_PARAM_ARGS) &&
107 (info->parameters)) {
108 /*
109 * The caller "owns" the parameters, so give each one an extra
110 * reference
111 */
112 for (i = 0; info->parameters[i]; i++) {
113 acpi_ut_add_reference (info->parameters[i]);
114 }
115 }
116
117 /*
118 * 1) Perform the first pass parse of the method to enter any
119 * named objects that it creates into the namespace
120 */
121 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
122 "**** Begin Method Parse **** Entry=%p obj=%p\n",
123 info->node, obj_desc));
124
125 /* Create and init a Root Node */
126
127 op = acpi_ps_create_scope_op ();
128 if (!op) {
129 status = AE_NO_MEMORY;
130 goto cleanup1;
131 }
132
133 /*
134 * Get a new owner_id for objects created by this method. Namespace
135 * objects (such as Operation Regions) can be created during the
136 * first pass parse.
137 */
138 obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
139
140 /* Create and initialize a new walk state */
141
142 walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
143 NULL, NULL, NULL);
144 if (!walk_state) {
145 status = AE_NO_MEMORY;
146 goto cleanup2;
147 }
148
149 status = acpi_ds_init_aml_walk (walk_state, op, info->node,
150 obj_desc->method.aml_start,
151 obj_desc->method.aml_length, NULL, 1);
152 if (ACPI_FAILURE (status)) {
153 goto cleanup3;
154 }
155
156 /* Parse the AML */
157
158 status = acpi_ps_parse_aml (walk_state);
159 acpi_ps_delete_parse_tree (op);
160 if (ACPI_FAILURE (status)) {
161 goto cleanup1; /* Walk state is already deleted */
162 }
163
164 /*
165 * 2) Execute the method. Performs second pass parse simultaneously
166 */
167 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
168 "**** Begin Method Execution **** Entry=%p obj=%p\n",
169 info->node, obj_desc));
170
171 /* Create and init a Root Node */
172
173 op = acpi_ps_create_scope_op ();
174 if (!op) {
175 status = AE_NO_MEMORY;
176 goto cleanup1;
177 }
178
179 /* Init new op with the method name and pointer back to the NS node */
180
181 acpi_ps_set_name (op, info->node->name.integer);
182 op->common.node = info->node;
183
184 /* Create and initialize a new walk state */
185
186 walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
187 if (!walk_state) {
188 status = AE_NO_MEMORY;
189 goto cleanup2;
190 }
191
192 status = acpi_ds_init_aml_walk (walk_state, op, info->node,
193 obj_desc->method.aml_start,
194 obj_desc->method.aml_length, info, 3);
195 if (ACPI_FAILURE (status)) {
196 goto cleanup3;
197 }
198
199 /*
200 * The walk of the parse tree is where we actually execute the method
201 */
202 status = acpi_ps_parse_aml (walk_state);
203 goto cleanup2; /* Walk state already deleted */
204
205
206cleanup3:
207 acpi_ds_delete_walk_state (walk_state);
208
209cleanup2:
210 acpi_ps_delete_parse_tree (op);
211
212cleanup1:
213 if ((info->parameter_type == ACPI_PARAM_ARGS) &&
214 (info->parameters)) {
215 /* Take away the extra reference that we gave the parameters above */
216
217 for (i = 0; info->parameters[i]; i++) {
218 /* Ignore errors, just do them all */
219
220 (void) acpi_ut_update_object_reference (info->parameters[i], REF_DECREMENT);
221 }
222 }
223
224 if (ACPI_FAILURE (status)) {
225 return_ACPI_STATUS (status);
226 }
227
228 /*
229 * If the method has returned an object, signal this to the caller with
230 * a control exception code
231 */
232 if (info->return_object) {
233 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n",
234 info->return_object));
235 ACPI_DUMP_STACK_ENTRY (info->return_object);
236
237 status = AE_CTRL_RETURN_VALUE;
238 }
239
240 return_ACPI_STATUS (status);
241}
242
243
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
new file mode 100644
index 000000000000..5d19b39e9e2b
--- /dev/null
+++ b/drivers/acpi/pci_bind.c
@@ -0,0 +1,384 @@
1/*
2 * pci_bind.c - ACPI PCI Device Binding ($Revision: 2 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/types.h>
30#include <linux/proc_fs.h>
31#include <linux/spinlock.h>
32#include <linux/pm.h>
33#include <linux/pci.h>
34#include <linux/acpi.h>
35#include <acpi/acpi_bus.h>
36#include <acpi/acpi_drivers.h>
37
38
39#define _COMPONENT ACPI_PCI_COMPONENT
40ACPI_MODULE_NAME ("pci_bind")
41
42struct acpi_pci_data {
43 struct acpi_pci_id id;
44 struct pci_bus *bus;
45 struct pci_dev *dev;
46};
47
48
49void
50acpi_pci_data_handler (
51 acpi_handle handle,
52 u32 function,
53 void *context)
54{
55 ACPI_FUNCTION_TRACE("acpi_pci_data_handler");
56
57 /* TBD: Anything we need to do here? */
58
59 return_VOID;
60}
61
62
63/**
64 * acpi_os_get_pci_id
65 * ------------------
66 * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem)
67 * to resolve PCI information for ACPI-PCI devices defined in the namespace.
68 * This typically occurs when resolving PCI operation region information.
69 */
70#ifdef ACPI_FUTURE_USAGE
71acpi_status
72acpi_os_get_pci_id (
73 acpi_handle handle,
74 struct acpi_pci_id *id)
75{
76 int result = 0;
77 acpi_status status = AE_OK;
78 struct acpi_device *device = NULL;
79 struct acpi_pci_data *data = NULL;
80
81 ACPI_FUNCTION_TRACE("acpi_os_get_pci_id");
82
83 if (!id)
84 return_ACPI_STATUS(AE_BAD_PARAMETER);
85
86 result = acpi_bus_get_device(handle, &device);
87 if (result) {
88 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
89 "Invalid ACPI Bus context for device %s\n",
90 acpi_device_bid(device)));
91 return_ACPI_STATUS(AE_NOT_EXIST);
92 }
93
94 status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data);
95 if (ACPI_FAILURE(status) || !data || !data->dev) {
96 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
97 "Invalid ACPI-PCI context for device %s\n",
98 acpi_device_bid(device)));
99 return_ACPI_STATUS(status);
100 }
101
102 *id = data->id;
103
104 /*
105 id->segment = data->id.segment;
106 id->bus = data->id.bus;
107 id->device = data->id.device;
108 id->function = data->id.function;
109 */
110
111 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
112 "Device %s has PCI address %02x:%02x:%02x.%02x\n",
113 acpi_device_bid(device), id->segment, id->bus,
114 id->device, id->function));
115
116 return_ACPI_STATUS(AE_OK);
117}
118#endif /* ACPI_FUTURE_USAGE */
119
120
121int
122acpi_pci_bind (
123 struct acpi_device *device)
124{
125 int result = 0;
126 acpi_status status = AE_OK;
127 struct acpi_pci_data *data = NULL;
128 struct acpi_pci_data *pdata = NULL;
129 char *pathname = NULL;
130 struct acpi_buffer buffer = {0, NULL};
131 acpi_handle handle = NULL;
132
133 ACPI_FUNCTION_TRACE("acpi_pci_bind");
134
135 if (!device || !device->parent)
136 return_VALUE(-EINVAL);
137
138 pathname = kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
139 if(!pathname)
140 return_VALUE(-ENOMEM);
141 memset(pathname, 0, ACPI_PATHNAME_MAX);
142 buffer.length = ACPI_PATHNAME_MAX;
143 buffer.pointer = pathname;
144
145 data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
146 if (!data){
147 kfree (pathname);
148 return_VALUE(-ENOMEM);
149 }
150 memset(data, 0, sizeof(struct acpi_pci_data));
151
152 acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
153 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
154 pathname));
155
156 /*
157 * Segment & Bus
158 * -------------
159 * These are obtained via the parent device's ACPI-PCI context.
160 */
161 status = acpi_get_data(device->parent->handle, acpi_pci_data_handler,
162 (void**) &pdata);
163 if (ACPI_FAILURE(status) || !pdata || !pdata->bus) {
164 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
165 "Invalid ACPI-PCI context for parent device %s\n",
166 acpi_device_bid(device->parent)));
167 result = -ENODEV;
168 goto end;
169 }
170 data->id.segment = pdata->id.segment;
171 data->id.bus = pdata->bus->number;
172
173 /*
174 * Device & Function
175 * -----------------
176 * These are simply obtained from the device's _ADR method. Note
177 * that a value of zero is valid.
178 */
179 data->id.device = device->pnp.bus_address >> 16;
180 data->id.function = device->pnp.bus_address & 0xFFFF;
181
182 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %02x:%02x:%02x.%02x\n",
183 data->id.segment, data->id.bus, data->id.device,
184 data->id.function));
185
186 /*
187 * TBD: Support slot devices (e.g. function=0xFFFF).
188 */
189
190 /*
191 * Locate PCI Device
192 * -----------------
193 * Locate matching device in PCI namespace. If it doesn't exist
194 * this typically means that the device isn't currently inserted
195 * (e.g. docking station, port replicator, etc.).
196 */
197 data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function));
198 if (!data->dev) {
199 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
200 "Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
201 data->id.segment, data->id.bus,
202 data->id.device, data->id.function));
203 result = -ENODEV;
204 goto end;
205 }
206 if (!data->dev->bus) {
207 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
208 "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n",
209 data->id.segment, data->id.bus,
210 data->id.device, data->id.function));
211 result = -ENODEV;
212 goto end;
213 }
214
215 /*
216 * PCI Bridge?
217 * -----------
218 * If so, set the 'bus' field and install the 'bind' function to
219 * facilitate callbacks for all of its children.
220 */
221 if (data->dev->subordinate) {
222 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
223 "Device %02x:%02x:%02x.%02x is a PCI bridge\n",
224 data->id.segment, data->id.bus,
225 data->id.device, data->id.function));
226 data->bus = data->dev->subordinate;
227 device->ops.bind = acpi_pci_bind;
228 device->ops.unbind = acpi_pci_unbind;
229 }
230
231 /*
232 * Attach ACPI-PCI Context
233 * -----------------------
234 * Thus binding the ACPI and PCI devices.
235 */
236 status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
237 if (ACPI_FAILURE(status)) {
238 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
239 "Unable to attach ACPI-PCI context to device %s\n",
240 acpi_device_bid(device)));
241 result = -ENODEV;
242 goto end;
243 }
244
245 /*
246 * PCI Routing Table
247 * -----------------
248 * Evaluate and parse _PRT, if exists. This code is independent of
249 * PCI bridges (above) to allow parsing of _PRT objects within the
250 * scope of non-bridge devices. Note that _PRTs within the scope of
251 * a PCI bridge assume the bridge's subordinate bus number.
252 *
253 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
254 */
255 status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
256 if (ACPI_SUCCESS(status)) {
257 if (data->bus) /* PCI-PCI bridge */
258 acpi_pci_irq_add_prt(device->handle, data->id.segment,
259 data->bus->number);
260 else /* non-bridge PCI device */
261 acpi_pci_irq_add_prt(device->handle, data->id.segment,
262 data->id.bus);
263 }
264
265end:
266 kfree(pathname);
267 if (result)
268 kfree(data);
269
270 return_VALUE(result);
271}
272
273int acpi_pci_unbind(
274 struct acpi_device *device)
275{
276 int result = 0;
277 acpi_status status = AE_OK;
278 struct acpi_pci_data *data = NULL;
279 char *pathname = NULL;
280 struct acpi_buffer buffer = {0, NULL};
281
282 ACPI_FUNCTION_TRACE("acpi_pci_unbind");
283
284 if (!device || !device->parent)
285 return_VALUE(-EINVAL);
286
287 pathname = (char *) kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
288 if(!pathname)
289 return_VALUE(-ENOMEM);
290 memset(pathname, 0, ACPI_PATHNAME_MAX);
291
292 buffer.length = ACPI_PATHNAME_MAX;
293 buffer.pointer = pathname;
294 acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
295 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n",
296 pathname));
297 kfree(pathname);
298
299 status = acpi_get_data(device->handle, acpi_pci_data_handler, (void**)&data);
300 if (ACPI_FAILURE(status)) {
301 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
302 "Unable to get data from device %s\n",
303 acpi_device_bid(device)));
304 result = -ENODEV;
305 goto end;
306 }
307
308 status = acpi_detach_data(device->handle, acpi_pci_data_handler);
309 if (ACPI_FAILURE(status)) {
310 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
311 "Unable to detach data from device %s\n",
312 acpi_device_bid(device)));
313 result = -ENODEV;
314 goto end;
315 }
316 if (data->dev->subordinate) {
317 acpi_pci_irq_del_prt(data->id.segment, data->bus->number);
318 }
319 kfree(data);
320
321end:
322 return_VALUE(result);
323}
324
325int
326acpi_pci_bind_root (
327 struct acpi_device *device,
328 struct acpi_pci_id *id,
329 struct pci_bus *bus)
330{
331 int result = 0;
332 acpi_status status = AE_OK;
333 struct acpi_pci_data *data = NULL;
334 char *pathname = NULL;
335 struct acpi_buffer buffer = {0, NULL};
336
337 ACPI_FUNCTION_TRACE("acpi_pci_bind_root");
338
339 pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
340 if(!pathname)
341 return_VALUE(-ENOMEM);
342 memset(pathname, 0, ACPI_PATHNAME_MAX);
343
344 buffer.length = ACPI_PATHNAME_MAX;
345 buffer.pointer = pathname;
346
347 if (!device || !id || !bus){
348 kfree(pathname);
349 return_VALUE(-EINVAL);
350 }
351
352 data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
353 if (!data){
354 kfree(pathname);
355 return_VALUE(-ENOMEM);
356 }
357 memset(data, 0, sizeof(struct acpi_pci_data));
358
359 data->id = *id;
360 data->bus = bus;
361 device->ops.bind = acpi_pci_bind;
362 device->ops.unbind = acpi_pci_unbind;
363
364 acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
365
366 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to "
367 "%02x:%02x\n", pathname, id->segment, id->bus));
368
369 status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
370 if (ACPI_FAILURE(status)) {
371 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
372 "Unable to attach ACPI-PCI context to device %s\n",
373 pathname));
374 result = -ENODEV;
375 goto end;
376 }
377
378end:
379 kfree(pathname);
380 if (result != 0)
381 kfree(data);
382
383 return_VALUE(result);
384}
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
new file mode 100644
index 000000000000..12b0eea63407
--- /dev/null
+++ b/drivers/acpi/pci_irq.c
@@ -0,0 +1,518 @@
1/*
2 * pci_irq.c - ACPI PCI Interrupt Routing ($Revision: 11 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de>
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 */
26
27#include <linux/config.h>
28
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/types.h>
33#include <linux/proc_fs.h>
34#include <linux/spinlock.h>
35#include <linux/pm.h>
36#include <linux/pci.h>
37#include <linux/acpi.h>
38#include <acpi/acpi_bus.h>
39#include <acpi/acpi_drivers.h>
40
41
42#define _COMPONENT ACPI_PCI_COMPONENT
43ACPI_MODULE_NAME ("pci_irq")
44
45static struct acpi_prt_list acpi_prt;
46static DEFINE_SPINLOCK(acpi_prt_lock);
47
48/* --------------------------------------------------------------------------
49 PCI IRQ Routing Table (PRT) Support
50 -------------------------------------------------------------------------- */
51
52static struct acpi_prt_entry *
53acpi_pci_irq_find_prt_entry (
54 int segment,
55 int bus,
56 int device,
57 int pin)
58{
59 struct list_head *node = NULL;
60 struct acpi_prt_entry *entry = NULL;
61
62 ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry");
63
64 if (!acpi_prt.count)
65 return_PTR(NULL);
66
67 /*
68 * Parse through all PRT entries looking for a match on the specified
69 * PCI device's segment, bus, device, and pin (don't care about func).
70 *
71 */
72 spin_lock(&acpi_prt_lock);
73 list_for_each(node, &acpi_prt.entries) {
74 entry = list_entry(node, struct acpi_prt_entry, node);
75 if ((segment == entry->id.segment)
76 && (bus == entry->id.bus)
77 && (device == entry->id.device)
78 && (pin == entry->pin)) {
79 spin_unlock(&acpi_prt_lock);
80 return_PTR(entry);
81 }
82 }
83
84 spin_unlock(&acpi_prt_lock);
85 return_PTR(NULL);
86}
87
88
89static int
90acpi_pci_irq_add_entry (
91 acpi_handle handle,
92 int segment,
93 int bus,
94 struct acpi_pci_routing_table *prt)
95{
96 struct acpi_prt_entry *entry = NULL;
97
98 ACPI_FUNCTION_TRACE("acpi_pci_irq_add_entry");
99
100 if (!prt)
101 return_VALUE(-EINVAL);
102
103 entry = kmalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
104 if (!entry)
105 return_VALUE(-ENOMEM);
106 memset(entry, 0, sizeof(struct acpi_prt_entry));
107
108 entry->id.segment = segment;
109 entry->id.bus = bus;
110 entry->id.device = (prt->address >> 16) & 0xFFFF;
111 entry->id.function = prt->address & 0xFFFF;
112 entry->pin = prt->pin;
113
114 /*
115 * Type 1: Dynamic
116 * ---------------
117 * The 'source' field specifies the PCI interrupt link device used to
118 * configure the IRQ assigned to this slot|dev|pin. The 'source_index'
119 * indicates which resource descriptor in the resource template (of
120 * the link device) this interrupt is allocated from.
121 *
122 * NOTE: Don't query the Link Device for IRQ information at this time
123 * because Link Device enumeration may not have occurred yet
124 * (e.g. exists somewhere 'below' this _PRT entry in the ACPI
125 * namespace).
126 */
127 if (prt->source[0]) {
128 acpi_get_handle(handle, prt->source, &entry->link.handle);
129 entry->link.index = prt->source_index;
130 }
131 /*
132 * Type 2: Static
133 * --------------
134 * The 'source' field is NULL, and the 'source_index' field specifies
135 * the IRQ value, which is hardwired to specific interrupt inputs on
136 * the interrupt controller.
137 */
138 else
139 entry->link.index = prt->source_index;
140
141 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
142 " %02X:%02X:%02X[%c] -> %s[%d]\n",
143 entry->id.segment, entry->id.bus, entry->id.device,
144 ('A' + entry->pin), prt->source, entry->link.index));
145
146 spin_lock(&acpi_prt_lock);
147 list_add_tail(&entry->node, &acpi_prt.entries);
148 acpi_prt.count++;
149 spin_unlock(&acpi_prt_lock);
150
151 return_VALUE(0);
152}
153
154
155static void
156acpi_pci_irq_del_entry (
157 int segment,
158 int bus,
159 struct acpi_prt_entry *entry)
160{
161 if (segment == entry->id.segment && bus == entry->id.bus){
162 acpi_prt.count--;
163 list_del(&entry->node);
164 kfree(entry);
165 }
166}
167
168
169int
170acpi_pci_irq_add_prt (
171 acpi_handle handle,
172 int segment,
173 int bus)
174{
175 acpi_status status = AE_OK;
176 char *pathname = NULL;
177 struct acpi_buffer buffer = {0, NULL};
178 struct acpi_pci_routing_table *prt = NULL;
179 struct acpi_pci_routing_table *entry = NULL;
180 static int first_time = 1;
181
182 ACPI_FUNCTION_TRACE("acpi_pci_irq_add_prt");
183
184 pathname = (char *) kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
185 if(!pathname)
186 return_VALUE(-ENOMEM);
187 memset(pathname, 0, ACPI_PATHNAME_MAX);
188
189 if (first_time) {
190 acpi_prt.count = 0;
191 INIT_LIST_HEAD(&acpi_prt.entries);
192 first_time = 0;
193 }
194
195 /*
196 * NOTE: We're given a 'handle' to the _PRT object's parent device
197 * (either a PCI root bridge or PCI-PCI bridge).
198 */
199
200 buffer.length = ACPI_PATHNAME_MAX;
201 buffer.pointer = pathname;
202 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
203
204 printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
205 pathname);
206
207 /*
208 * Evaluate this _PRT and add its entries to our global list (acpi_prt).
209 */
210
211 buffer.length = 0;
212 buffer.pointer = NULL;
213 kfree(pathname);
214 status = acpi_get_irq_routing_table(handle, &buffer);
215 if (status != AE_BUFFER_OVERFLOW) {
216 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
217 acpi_format_exception(status)));
218 return_VALUE(-ENODEV);
219 }
220
221 prt = kmalloc(buffer.length, GFP_KERNEL);
222 if (!prt){
223 return_VALUE(-ENOMEM);
224 }
225 memset(prt, 0, buffer.length);
226 buffer.pointer = prt;
227
228 status = acpi_get_irq_routing_table(handle, &buffer);
229 if (ACPI_FAILURE(status)) {
230 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
231 acpi_format_exception(status)));
232 kfree(buffer.pointer);
233 return_VALUE(-ENODEV);
234 }
235
236 entry = prt;
237
238 while (entry && (entry->length > 0)) {
239 acpi_pci_irq_add_entry(handle, segment, bus, entry);
240 entry = (struct acpi_pci_routing_table *)
241 ((unsigned long) entry + entry->length);
242 }
243
244 kfree(prt);
245
246 return_VALUE(0);
247}
248
249void
250acpi_pci_irq_del_prt (int segment, int bus)
251{
252 struct list_head *node = NULL, *n = NULL;
253 struct acpi_prt_entry *entry = NULL;
254
255 if (!acpi_prt.count) {
256 return;
257 }
258
259 printk(KERN_DEBUG "ACPI: Delete PCI Interrupt Routing Table for %x:%x\n",
260 segment, bus);
261 spin_lock(&acpi_prt_lock);
262 list_for_each_safe(node, n, &acpi_prt.entries) {
263 entry = list_entry(node, struct acpi_prt_entry, node);
264
265 acpi_pci_irq_del_entry(segment, bus, entry);
266 }
267 spin_unlock(&acpi_prt_lock);
268}
269/* --------------------------------------------------------------------------
270 PCI Interrupt Routing Support
271 -------------------------------------------------------------------------- */
272
273/*
274 * acpi_pci_irq_lookup
275 * success: return IRQ >= 0
276 * failure: return -1
277 */
278static int
279acpi_pci_irq_lookup (
280 struct pci_bus *bus,
281 int device,
282 int pin,
283 int *edge_level,
284 int *active_high_low,
285 char **link)
286{
287 struct acpi_prt_entry *entry = NULL;
288 int segment = pci_domain_nr(bus);
289 int bus_nr = bus->number;
290 int irq;
291
292 ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup");
293
294 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
295 "Searching for PRT entry for %02x:%02x:%02x[%c]\n",
296 segment, bus_nr, device, ('A' + pin)));
297
298 entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin);
299 if (!entry) {
300 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n"));
301 return_VALUE(-1);
302 }
303
304 if (entry->link.handle) {
305 irq = acpi_pci_link_get_irq(entry->link.handle,
306 entry->link.index, edge_level, active_high_low, link);
307 if (irq < 0) {
308 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
309 return_VALUE(-1);
310 }
311 } else {
312 irq = entry->link.index;
313 *edge_level = ACPI_LEVEL_SENSITIVE;
314 *active_high_low = ACPI_ACTIVE_LOW;
315 }
316
317 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq));
318
319 return_VALUE(irq);
320}
321
322/*
323 * acpi_pci_irq_derive
324 * success: return IRQ >= 0
325 * failure: return < 0
326 */
327static int
328acpi_pci_irq_derive (
329 struct pci_dev *dev,
330 int pin,
331 int *edge_level,
332 int *active_high_low,
333 char **link)
334{
335 struct pci_dev *bridge = dev;
336 int irq = -1;
337 u8 bridge_pin = 0;
338
339 ACPI_FUNCTION_TRACE("acpi_pci_irq_derive");
340
341 if (!dev)
342 return_VALUE(-EINVAL);
343
344 /*
345 * Attempt to derive an IRQ for this device from a parent bridge's
346 * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
347 */
348 while (irq < 0 && bridge->bus->self) {
349 pin = (pin + PCI_SLOT(bridge->devfn)) % 4;
350 bridge = bridge->bus->self;
351
352 if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
353 /* PC card has the same IRQ as its cardbridge */
354 pci_read_config_byte(bridge, PCI_INTERRUPT_PIN, &bridge_pin);
355 if (!bridge_pin) {
356 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
357 "No interrupt pin configured for device %s\n", pci_name(bridge)));
358 return_VALUE(-1);
359 }
360 /* Pin is from 0 to 3 */
361 bridge_pin --;
362 pin = bridge_pin;
363 }
364
365 irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
366 pin, edge_level, active_high_low, link);
367 }
368
369 if (irq < 0) {
370 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to derive IRQ for device %s\n", pci_name(dev)));
371 return_VALUE(-1);
372 }
373
374 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n",
375 irq, pci_name(dev), pci_name(bridge)));
376
377 return_VALUE(irq);
378}
379
380/*
381 * acpi_pci_irq_enable
382 * success: return 0
383 * failure: return < 0
384 */
385
386int
387acpi_pci_irq_enable (
388 struct pci_dev *dev)
389{
390 int irq = 0;
391 u8 pin = 0;
392 int edge_level = ACPI_LEVEL_SENSITIVE;
393 int active_high_low = ACPI_ACTIVE_LOW;
394 extern int via_interrupt_line_quirk;
395 char *link = NULL;
396
397 ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
398
399 if (!dev)
400 return_VALUE(-EINVAL);
401
402 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
403 if (!pin) {
404 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No interrupt pin configured for device %s\n", pci_name(dev)));
405 return_VALUE(0);
406 }
407 pin--;
408
409 if (!dev->bus) {
410 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) 'bus' field\n"));
411 return_VALUE(-ENODEV);
412 }
413
414 /*
415 * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT
416 * values override any BIOS-assigned IRQs set during boot.
417 */
418 irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
419 &edge_level, &active_high_low, &link);
420
421 /*
422 * If no PRT entry was found, we'll try to derive an IRQ from the
423 * device's parent bridge.
424 */
425 if (irq < 0)
426 irq = acpi_pci_irq_derive(dev, pin, &edge_level,
427 &active_high_low, &link);
428
429 /*
430 * No IRQ known to the ACPI subsystem - maybe the BIOS /
431 * driver reported one, then use it. Exit in any case.
432 */
433 if (irq < 0) {
434 printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI",
435 pci_name(dev), ('A' + pin));
436 /* Interrupt Line values above 0xF are forbidden */
437 if (dev->irq >= 0 && (dev->irq <= 0xF)) {
438 printk(" - using IRQ %d\n", dev->irq);
439 return_VALUE(0);
440 }
441 else {
442 printk("\n");
443 return_VALUE(0);
444 }
445 }
446
447 if (via_interrupt_line_quirk)
448 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq & 15);
449
450 dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
451
452 printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
453 pci_name(dev), 'A' + pin);
454
455 if (link)
456 printk("Link [%s] -> ", link);
457
458 printk("GSI %u (%s, %s) -> IRQ %d\n", irq,
459 (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
460 (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high",
461 dev->irq);
462
463 return_VALUE(0);
464}
465EXPORT_SYMBOL(acpi_pci_irq_enable);
466
467
468#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
469void
470acpi_pci_irq_disable (
471 struct pci_dev *dev)
472{
473 int gsi = 0;
474 u8 pin = 0;
475 int edge_level = ACPI_LEVEL_SENSITIVE;
476 int active_high_low = ACPI_ACTIVE_LOW;
477
478 ACPI_FUNCTION_TRACE("acpi_pci_irq_disable");
479
480 if (!dev)
481 return_VOID;
482
483 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
484 if (!pin)
485 return_VOID;
486 pin--;
487
488 if (!dev->bus)
489 return_VOID;
490
491 /*
492 * First we check the PCI IRQ routing table (PRT) for an IRQ.
493 */
494 gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
495 &edge_level, &active_high_low, NULL);
496 /*
497 * If no PRT entry was found, we'll try to derive an IRQ from the
498 * device's parent bridge.
499 */
500 if (gsi < 0)
501 gsi = acpi_pci_irq_derive(dev, pin,
502 &edge_level, &active_high_low, NULL);
503 if (gsi < 0)
504 return_VOID;
505
506 /*
507 * TBD: It might be worth clearing dev->irq by magic constant
508 * (e.g. PCI_UNDEFINED_IRQ).
509 */
510
511 printk(KERN_INFO PREFIX "PCI interrupt for device %s disabled\n",
512 pci_name(dev));
513
514 acpi_unregister_gsi(gsi);
515
516 return_VOID;
517}
518#endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
new file mode 100644
index 000000000000..520b28ad0740
--- /dev/null
+++ b/drivers/acpi/pci_link.c
@@ -0,0 +1,904 @@
1/*
2 * pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 34 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de>
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 * TBD:
27 * 1. Support more than one IRQ resource entry per link device (index).
28 * 2. Implement start/stop mechanism and use ACPI Bus Driver facilities
29 * for IRQ management (e.g. start()->_SRS).
30 */
31
32#include <linux/sysdev.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/types.h>
37#include <linux/proc_fs.h>
38#include <linux/spinlock.h>
39#include <linux/pm.h>
40#include <linux/pci.h>
41
42#include <acpi/acpi_bus.h>
43#include <acpi/acpi_drivers.h>
44
45
46#define _COMPONENT ACPI_PCI_COMPONENT
47ACPI_MODULE_NAME ("pci_link")
48
49#define ACPI_PCI_LINK_CLASS "pci_irq_routing"
50#define ACPI_PCI_LINK_HID "PNP0C0F"
51#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver"
52#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link"
53#define ACPI_PCI_LINK_FILE_INFO "info"
54#define ACPI_PCI_LINK_FILE_STATUS "state"
55
56#define ACPI_PCI_LINK_MAX_POSSIBLE 16
57
58static int acpi_pci_link_add (struct acpi_device *device);
59static int acpi_pci_link_remove (struct acpi_device *device, int type);
60
61static struct acpi_driver acpi_pci_link_driver = {
62 .name = ACPI_PCI_LINK_DRIVER_NAME,
63 .class = ACPI_PCI_LINK_CLASS,
64 .ids = ACPI_PCI_LINK_HID,
65 .ops = {
66 .add = acpi_pci_link_add,
67 .remove = acpi_pci_link_remove,
68 },
69};
70
71struct acpi_pci_link_irq {
72 u8 active; /* Current IRQ */
73 u8 edge_level; /* All IRQs */
74 u8 active_high_low; /* All IRQs */
75 u8 initialized;
76 u8 resource_type;
77 u8 possible_count;
78 u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
79};
80
81struct acpi_pci_link {
82 struct list_head node;
83 struct acpi_device *device;
84 acpi_handle handle;
85 struct acpi_pci_link_irq irq;
86};
87
88static struct {
89 int count;
90 struct list_head entries;
91} acpi_link;
92
93
94/* --------------------------------------------------------------------------
95 PCI Link Device Management
96 -------------------------------------------------------------------------- */
97
98/*
99 * set context (link) possible list from resource list
100 */
101static acpi_status
102acpi_pci_link_check_possible (
103 struct acpi_resource *resource,
104 void *context)
105{
106 struct acpi_pci_link *link = (struct acpi_pci_link *) context;
107 u32 i = 0;
108
109 ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible");
110
111 switch (resource->id) {
112 case ACPI_RSTYPE_START_DPF:
113 return_ACPI_STATUS(AE_OK);
114 case ACPI_RSTYPE_IRQ:
115 {
116 struct acpi_resource_irq *p = &resource->data.irq;
117 if (!p || !p->number_of_interrupts) {
118 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank IRQ resource\n"));
119 return_ACPI_STATUS(AE_OK);
120 }
121 for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
122 if (!p->interrupts[i]) {
123 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
124 continue;
125 }
126 link->irq.possible[i] = p->interrupts[i];
127 link->irq.possible_count++;
128 }
129 link->irq.edge_level = p->edge_level;
130 link->irq.active_high_low = p->active_high_low;
131 link->irq.resource_type = ACPI_RSTYPE_IRQ;
132 break;
133 }
134 case ACPI_RSTYPE_EXT_IRQ:
135 {
136 struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
137 if (!p || !p->number_of_interrupts) {
138 ACPI_DEBUG_PRINT((ACPI_DB_WARN,
139 "Blank EXT IRQ resource\n"));
140 return_ACPI_STATUS(AE_OK);
141 }
142 for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
143 if (!p->interrupts[i]) {
144 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
145 continue;
146 }
147 link->irq.possible[i] = p->interrupts[i];
148 link->irq.possible_count++;
149 }
150 link->irq.edge_level = p->edge_level;
151 link->irq.active_high_low = p->active_high_low;
152 link->irq.resource_type = ACPI_RSTYPE_EXT_IRQ;
153 break;
154 }
155 default:
156 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
157 "Resource is not an IRQ entry\n"));
158 return_ACPI_STATUS(AE_OK);
159 }
160
161 return_ACPI_STATUS(AE_CTRL_TERMINATE);
162}
163
164
165static int
166acpi_pci_link_get_possible (
167 struct acpi_pci_link *link)
168{
169 acpi_status status;
170
171 ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible");
172
173 if (!link)
174 return_VALUE(-EINVAL);
175
176 status = acpi_walk_resources(link->handle, METHOD_NAME__PRS,
177 acpi_pci_link_check_possible, link);
178 if (ACPI_FAILURE(status)) {
179 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n"));
180 return_VALUE(-ENODEV);
181 }
182
183 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
184 "Found %d possible IRQs\n", link->irq.possible_count));
185
186 return_VALUE(0);
187}
188
189
190static acpi_status
191acpi_pci_link_check_current (
192 struct acpi_resource *resource,
193 void *context)
194{
195 int *irq = (int *) context;
196
197 ACPI_FUNCTION_TRACE("acpi_pci_link_check_current");
198
199 switch (resource->id) {
200 case ACPI_RSTYPE_IRQ:
201 {
202 struct acpi_resource_irq *p = &resource->data.irq;
203 if (!p || !p->number_of_interrupts) {
204 /*
205 * IRQ descriptors may have no IRQ# bits set,
206 * particularly those those w/ _STA disabled
207 */
208 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
209 "Blank IRQ resource\n"));
210 return_ACPI_STATUS(AE_OK);
211 }
212 *irq = p->interrupts[0];
213 break;
214 }
215 case ACPI_RSTYPE_EXT_IRQ:
216 {
217 struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
218 if (!p || !p->number_of_interrupts) {
219 /*
220 * extended IRQ descriptors must
221 * return at least 1 IRQ
222 */
223 ACPI_DEBUG_PRINT((ACPI_DB_WARN,
224 "Blank EXT IRQ resource\n"));
225 return_ACPI_STATUS(AE_OK);
226 }
227 *irq = p->interrupts[0];
228 break;
229 }
230 default:
231 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
232 "Resource isn't an IRQ\n"));
233 return_ACPI_STATUS(AE_OK);
234 }
235 return_ACPI_STATUS(AE_CTRL_TERMINATE);
236}
237
238/*
239 * Run _CRS and set link->irq.active
240 *
241 * return value:
242 * 0 - success
243 * !0 - failure
244 */
245static int
246acpi_pci_link_get_current (
247 struct acpi_pci_link *link)
248{
249 int result = 0;
250 acpi_status status = AE_OK;
251 int irq = 0;
252
253 ACPI_FUNCTION_TRACE("acpi_pci_link_get_current");
254
255 if (!link || !link->handle)
256 return_VALUE(-EINVAL);
257
258 link->irq.active = 0;
259
260 /* in practice, status disabled is meaningless, ignore it */
261 if (acpi_strict) {
262 /* Query _STA, set link->device->status */
263 result = acpi_bus_get_status(link->device);
264 if (result) {
265 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
266 goto end;
267 }
268
269 if (!link->device->status.enabled) {
270 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link disabled\n"));
271 return_VALUE(0);
272 }
273 }
274
275 /*
276 * Query and parse _CRS to get the current IRQ assignment.
277 */
278
279 status = acpi_walk_resources(link->handle, METHOD_NAME__CRS,
280 acpi_pci_link_check_current, &irq);
281 if (ACPI_FAILURE(status)) {
282 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
283 result = -ENODEV;
284 goto end;
285 }
286
287 if (acpi_strict && !irq) {
288 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "_CRS returned 0\n"));
289 result = -ENODEV;
290 }
291
292 link->irq.active = irq;
293
294 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
295
296end:
297 return_VALUE(result);
298}
299
300static int
301acpi_pci_link_set (
302 struct acpi_pci_link *link,
303 int irq)
304{
305 int result = 0;
306 acpi_status status = AE_OK;
307 struct {
308 struct acpi_resource res;
309 struct acpi_resource end;
310 } *resource;
311 struct acpi_buffer buffer = {0, NULL};
312
313 ACPI_FUNCTION_TRACE("acpi_pci_link_set");
314
315 if (!link || !irq)
316 return_VALUE(-EINVAL);
317
318 resource = kmalloc( sizeof(*resource)+1, GFP_KERNEL);
319 if(!resource)
320 return_VALUE(-ENOMEM);
321
322 memset(resource, 0, sizeof(*resource)+1);
323 buffer.length = sizeof(*resource) +1;
324 buffer.pointer = resource;
325
326 switch(link->irq.resource_type) {
327 case ACPI_RSTYPE_IRQ:
328 resource->res.id = ACPI_RSTYPE_IRQ;
329 resource->res.length = sizeof(struct acpi_resource);
330 resource->res.data.irq.edge_level = link->irq.edge_level;
331 resource->res.data.irq.active_high_low = link->irq.active_high_low;
332 if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
333 resource->res.data.irq.shared_exclusive = ACPI_EXCLUSIVE;
334 else
335 resource->res.data.irq.shared_exclusive = ACPI_SHARED;
336 resource->res.data.irq.number_of_interrupts = 1;
337 resource->res.data.irq.interrupts[0] = irq;
338 break;
339
340 case ACPI_RSTYPE_EXT_IRQ:
341 resource->res.id = ACPI_RSTYPE_EXT_IRQ;
342 resource->res.length = sizeof(struct acpi_resource);
343 resource->res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
344 resource->res.data.extended_irq.edge_level = link->irq.edge_level;
345 resource->res.data.extended_irq.active_high_low = link->irq.active_high_low;
346 if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
347 resource->res.data.irq.shared_exclusive = ACPI_EXCLUSIVE;
348 else
349 resource->res.data.irq.shared_exclusive = ACPI_SHARED;
350 resource->res.data.extended_irq.number_of_interrupts = 1;
351 resource->res.data.extended_irq.interrupts[0] = irq;
352 /* ignore resource_source, it's optional */
353 break;
354 default:
355 printk("ACPI BUG: resource_type %d\n", link->irq.resource_type);
356 result = -EINVAL;
357 goto end;
358
359 }
360 resource->end.id = ACPI_RSTYPE_END_TAG;
361
362 /* Attempt to set the resource */
363 status = acpi_set_current_resources(link->handle, &buffer);
364
365 /* check for total failure */
366 if (ACPI_FAILURE(status)) {
367 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
368 result = -ENODEV;
369 goto end;
370 }
371
372 /* Query _STA, set device->status */
373 result = acpi_bus_get_status(link->device);
374 if (result) {
375 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
376 goto end;
377 }
378 if (!link->device->status.enabled) {
379 printk(KERN_WARNING PREFIX
380 "%s [%s] disabled and referenced, BIOS bug.\n",
381 acpi_device_name(link->device),
382 acpi_device_bid(link->device));
383 }
384
385 /* Query _CRS, set link->irq.active */
386 result = acpi_pci_link_get_current(link);
387 if (result) {
388 goto end;
389 }
390
391 /*
392 * Is current setting not what we set?
393 * set link->irq.active
394 */
395 if (link->irq.active != irq) {
396 /*
397 * policy: when _CRS doesn't return what we just _SRS
398 * assume _SRS worked and override _CRS value.
399 */
400 printk(KERN_WARNING PREFIX
401 "%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
402 acpi_device_name(link->device),
403 acpi_device_bid(link->device),
404 link->irq.active, irq);
405 link->irq.active = irq;
406 }
407
408 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active));
409
410end:
411 kfree(resource);
412 return_VALUE(result);
413}
414
415
416/* --------------------------------------------------------------------------
417 PCI Link IRQ Management
418 -------------------------------------------------------------------------- */
419
420/*
421 * "acpi_irq_balance" (default in APIC mode) enables ACPI to use PIC Interrupt
422 * Link Devices to move the PIRQs around to minimize sharing.
423 *
424 * "acpi_irq_nobalance" (default in PIC mode) tells ACPI not to move any PIC IRQs
425 * that the BIOS has already set to active. This is necessary because
426 * ACPI has no automatic means of knowing what ISA IRQs are used. Note that
427 * if the BIOS doesn't set a Link Device active, ACPI needs to program it
428 * even if acpi_irq_nobalance is set.
429 *
430 * A tables of penalties avoids directing PCI interrupts to well known
431 * ISA IRQs. Boot params are available to over-ride the default table:
432 *
433 * List interrupts that are free for PCI use.
434 * acpi_irq_pci=n[,m]
435 *
436 * List interrupts that should not be used for PCI:
437 * acpi_irq_isa=n[,m]
438 *
439 * Note that PCI IRQ routers have a list of possible IRQs,
440 * which may not include the IRQs this table says are available.
441 *
442 * Since this heuristic can't tell the difference between a link
443 * that no device will attach to, vs. a link which may be shared
444 * by multiple active devices -- it is not optimal.
445 *
446 * If interrupt performance is that important, get an IO-APIC system
447 * with a pin dedicated to each device. Or for that matter, an MSI
448 * enabled system.
449 */
450
451#define ACPI_MAX_IRQS 256
452#define ACPI_MAX_ISA_IRQ 16
453
454#define PIRQ_PENALTY_PCI_AVAILABLE (0)
455#define PIRQ_PENALTY_PCI_POSSIBLE (16*16)
456#define PIRQ_PENALTY_PCI_USING (16*16*16)
457#define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16)
458#define PIRQ_PENALTY_ISA_USED (16*16*16*16*16)
459#define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16)
460
461static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
462 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */
463 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */
464 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */
465 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ3 serial */
466 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ4 serial */
467 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ5 sometimes SoundBlaster */
468 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */
469 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */
470 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */
471 PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */
472 PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */
473 PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */
474 PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */
475 PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */
476 PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */
477 PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */
478 /* >IRQ15 */
479};
480
481int __init
482acpi_irq_penalty_init(void)
483{
484 struct list_head *node = NULL;
485 struct acpi_pci_link *link = NULL;
486 int i = 0;
487
488 ACPI_FUNCTION_TRACE("acpi_irq_penalty_init");
489
490 /*
491 * Update penalties to facilitate IRQ balancing.
492 */
493 list_for_each(node, &acpi_link.entries) {
494
495 link = list_entry(node, struct acpi_pci_link, node);
496 if (!link) {
497 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
498 continue;
499 }
500
501 /*
502 * reflect the possible and active irqs in the penalty table --
503 * useful for breaking ties.
504 */
505 if (link->irq.possible_count) {
506 int penalty = PIRQ_PENALTY_PCI_POSSIBLE / link->irq.possible_count;
507
508 for (i = 0; i < link->irq.possible_count; i++) {
509 if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
510 acpi_irq_penalty[link->irq.possible[i]] += penalty;
511 }
512
513 } else if (link->irq.active) {
514 acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_POSSIBLE;
515 }
516 }
517 /* Add a penalty for the SCI */
518 acpi_irq_penalty[acpi_fadt.sci_int] += PIRQ_PENALTY_PCI_USING;
519
520 return_VALUE(0);
521}
522
523static int acpi_irq_balance; /* 0: static, 1: balance */
524
525static int acpi_pci_link_allocate(
526 struct acpi_pci_link *link)
527{
528 int irq;
529 int i;
530
531 ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
532
533 if (link->irq.initialized)
534 return_VALUE(0);
535
536 /*
537 * search for active IRQ in list of possible IRQs.
538 */
539 for (i = 0; i < link->irq.possible_count; ++i) {
540 if (link->irq.active == link->irq.possible[i])
541 break;
542 }
543 /*
544 * forget active IRQ that is not in possible list
545 */
546 if (i == link->irq.possible_count) {
547 if (acpi_strict)
548 printk(KERN_WARNING PREFIX "_CRS %d not found"
549 " in _PRS\n", link->irq.active);
550 link->irq.active = 0;
551 }
552
553 /*
554 * if active found, use it; else pick entry from end of possible list.
555 */
556 if (link->irq.active) {
557 irq = link->irq.active;
558 } else {
559 irq = link->irq.possible[link->irq.possible_count - 1];
560 }
561
562 if (acpi_irq_balance || !link->irq.active) {
563 /*
564 * Select the best IRQ. This is done in reverse to promote
565 * the use of IRQs 9, 10, 11, and >15.
566 */
567 for (i = (link->irq.possible_count - 1); i >= 0; i--) {
568 if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
569 irq = link->irq.possible[i];
570 }
571 }
572
573 /* Attempt to enable the link device at this IRQ. */
574 if (acpi_pci_link_set(link, irq)) {
575 printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS).\n"
576 "Try pci=noacpi or acpi=off\n",
577 acpi_device_name(link->device),
578 acpi_device_bid(link->device));
579 return_VALUE(-ENODEV);
580 } else {
581 acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
582 printk(PREFIX "%s [%s] enabled at IRQ %d\n",
583 acpi_device_name(link->device),
584 acpi_device_bid(link->device), link->irq.active);
585 }
586
587 link->irq.initialized = 1;
588
589 return_VALUE(0);
590}
591
592/*
593 * acpi_pci_link_get_irq
594 * success: return IRQ >= 0
595 * failure: return -1
596 */
597
598int
599acpi_pci_link_get_irq (
600 acpi_handle handle,
601 int index,
602 int *edge_level,
603 int *active_high_low,
604 char **name)
605{
606 int result = 0;
607 struct acpi_device *device = NULL;
608 struct acpi_pci_link *link = NULL;
609
610 ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq");
611
612 result = acpi_bus_get_device(handle, &device);
613 if (result) {
614 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n"));
615 return_VALUE(-1);
616 }
617
618 link = (struct acpi_pci_link *) acpi_driver_data(device);
619 if (!link) {
620 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
621 return_VALUE(-1);
622 }
623
624 /* TBD: Support multiple index (IRQ) entries per Link Device */
625 if (index) {
626 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid index %d\n", index));
627 return_VALUE(-1);
628 }
629
630 if (acpi_pci_link_allocate(link))
631 return_VALUE(-1);
632
633 if (!link->irq.active) {
634 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n"));
635 return_VALUE(-1);
636 }
637
638 if (edge_level) *edge_level = link->irq.edge_level;
639 if (active_high_low) *active_high_low = link->irq.active_high_low;
640 if (name) *name = acpi_device_bid(link->device);
641 return_VALUE(link->irq.active);
642}
643
644
645/* --------------------------------------------------------------------------
646 Driver Interface
647 -------------------------------------------------------------------------- */
648
649static int
650acpi_pci_link_add (
651 struct acpi_device *device)
652{
653 int result = 0;
654 struct acpi_pci_link *link = NULL;
655 int i = 0;
656 int found = 0;
657
658 ACPI_FUNCTION_TRACE("acpi_pci_link_add");
659
660 if (!device)
661 return_VALUE(-EINVAL);
662
663 link = kmalloc(sizeof(struct acpi_pci_link), GFP_KERNEL);
664 if (!link)
665 return_VALUE(-ENOMEM);
666 memset(link, 0, sizeof(struct acpi_pci_link));
667
668 link->device = device;
669 link->handle = device->handle;
670 strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
671 strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
672 acpi_driver_data(device) = link;
673
674 result = acpi_pci_link_get_possible(link);
675 if (result)
676 goto end;
677
678 /* query and set link->irq.active */
679 acpi_pci_link_get_current(link);
680
681 printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device),
682 acpi_device_bid(device));
683 for (i = 0; i < link->irq.possible_count; i++) {
684 if (link->irq.active == link->irq.possible[i]) {
685 printk(" *%d", link->irq.possible[i]);
686 found = 1;
687 }
688 else
689 printk(" %d", link->irq.possible[i]);
690 }
691
692 printk(")");
693
694 if (!found)
695 printk(" *%d", link->irq.active);
696
697 if(!link->device->status.enabled)
698 printk(", disabled.");
699
700 printk("\n");
701
702 /* TBD: Acquire/release lock */
703 list_add_tail(&link->node, &acpi_link.entries);
704 acpi_link.count++;
705
706end:
707 /* disable all links -- to be activated on use */
708 acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
709
710 if (result)
711 kfree(link);
712
713 return_VALUE(result);
714}
715
716
717static int
718acpi_pci_link_resume (
719 struct acpi_pci_link *link)
720{
721 ACPI_FUNCTION_TRACE("acpi_pci_link_resume");
722
723 if (link->irq.active && link->irq.initialized)
724 return_VALUE(acpi_pci_link_set(link, link->irq.active));
725 else
726 return_VALUE(0);
727}
728
729
730static int
731irqrouter_resume(
732 struct sys_device *dev)
733{
734 struct list_head *node = NULL;
735 struct acpi_pci_link *link = NULL;
736
737 ACPI_FUNCTION_TRACE("irqrouter_resume");
738
739 list_for_each(node, &acpi_link.entries) {
740
741 link = list_entry(node, struct acpi_pci_link, node);
742 if (!link) {
743 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
744 continue;
745 }
746
747 acpi_pci_link_resume(link);
748 }
749 return_VALUE(0);
750}
751
752
753static int
754acpi_pci_link_remove (
755 struct acpi_device *device,
756 int type)
757{
758 struct acpi_pci_link *link = NULL;
759
760 ACPI_FUNCTION_TRACE("acpi_pci_link_remove");
761
762 if (!device || !acpi_driver_data(device))
763 return_VALUE(-EINVAL);
764
765 link = (struct acpi_pci_link *) acpi_driver_data(device);
766
767 /* TBD: Acquire/release lock */
768 list_del(&link->node);
769
770 kfree(link);
771
772 return_VALUE(0);
773}
774
775/*
776 * modify acpi_irq_penalty[] from cmdline
777 */
778static int __init acpi_irq_penalty_update(char *str, int used)
779{
780 int i;
781
782 for (i = 0; i < 16; i++) {
783 int retval;
784 int irq;
785
786 retval = get_option(&str,&irq);
787
788 if (!retval)
789 break; /* no number found */
790
791 if (irq < 0)
792 continue;
793
794 if (irq >= ACPI_MAX_IRQS)
795 continue;
796
797 if (used)
798 acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
799 else
800 acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
801
802 if (retval != 2) /* no next number */
803 break;
804 }
805 return 1;
806}
807
808/*
809 * We'd like PNP to call this routine for the
810 * single ISA_USED value for each legacy device.
811 * But instead it calls us with each POSSIBLE setting.
812 * There is no ISA_POSSIBLE weight, so we simply use
813 * the (small) PCI_USING penalty.
814 */
815void acpi_penalize_isa_irq(int irq)
816{
817 acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
818}
819
820/*
821 * Over-ride default table to reserve additional IRQs for use by ISA
822 * e.g. acpi_irq_isa=5
823 * Useful for telling ACPI how not to interfere with your ISA sound card.
824 */
825static int __init acpi_irq_isa(char *str)
826{
827 return acpi_irq_penalty_update(str, 1);
828}
829__setup("acpi_irq_isa=", acpi_irq_isa);
830
831/*
832 * Over-ride default table to free additional IRQs for use by PCI
833 * e.g. acpi_irq_pci=7,15
834 * Used for acpi_irq_balance to free up IRQs to reduce PCI IRQ sharing.
835 */
836static int __init acpi_irq_pci(char *str)
837{
838 return acpi_irq_penalty_update(str, 0);
839}
840__setup("acpi_irq_pci=", acpi_irq_pci);
841
842static int __init acpi_irq_nobalance_set(char *str)
843{
844 acpi_irq_balance = 0;
845 return 1;
846}
847__setup("acpi_irq_nobalance", acpi_irq_nobalance_set);
848
849int __init acpi_irq_balance_set(char *str)
850{
851 acpi_irq_balance = 1;
852 return 1;
853}
854__setup("acpi_irq_balance", acpi_irq_balance_set);
855
856
857static struct sysdev_class irqrouter_sysdev_class = {
858 set_kset_name("irqrouter"),
859 .resume = irqrouter_resume,
860};
861
862
863static struct sys_device device_irqrouter = {
864 .id = 0,
865 .cls = &irqrouter_sysdev_class,
866};
867
868
869static int __init irqrouter_init_sysfs(void)
870{
871 int error;
872
873 ACPI_FUNCTION_TRACE("irqrouter_init_sysfs");
874
875 if (acpi_disabled || acpi_noirq)
876 return_VALUE(0);
877
878 error = sysdev_class_register(&irqrouter_sysdev_class);
879 if (!error)
880 error = sysdev_register(&device_irqrouter);
881
882 return_VALUE(error);
883}
884
885device_initcall(irqrouter_init_sysfs);
886
887
888static int __init acpi_pci_link_init (void)
889{
890 ACPI_FUNCTION_TRACE("acpi_pci_link_init");
891
892 if (acpi_noirq)
893 return_VALUE(0);
894
895 acpi_link.count = 0;
896 INIT_LIST_HEAD(&acpi_link.entries);
897
898 if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0)
899 return_VALUE(-ENODEV);
900
901 return_VALUE(0);
902}
903
904subsys_initcall(acpi_pci_link_init);
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
new file mode 100644
index 000000000000..7e6b8e3b2ed4
--- /dev/null
+++ b/drivers/acpi/pci_root.c
@@ -0,0 +1,347 @@
1/*
2 * pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 40 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/types.h>
30#include <linux/proc_fs.h>
31#include <linux/spinlock.h>
32#include <linux/pm.h>
33#include <linux/pci.h>
34#include <linux/acpi.h>
35#include <acpi/acpi_bus.h>
36#include <acpi/acpi_drivers.h>
37
38
39#define _COMPONENT ACPI_PCI_COMPONENT
40ACPI_MODULE_NAME ("pci_root")
41
42#define ACPI_PCI_ROOT_CLASS "pci_bridge"
43#define ACPI_PCI_ROOT_HID "PNP0A03"
44#define ACPI_PCI_ROOT_DRIVER_NAME "ACPI PCI Root Bridge Driver"
45#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge"
46
47static int acpi_pci_root_add (struct acpi_device *device);
48static int acpi_pci_root_remove (struct acpi_device *device, int type);
49
50static struct acpi_driver acpi_pci_root_driver = {
51 .name = ACPI_PCI_ROOT_DRIVER_NAME,
52 .class = ACPI_PCI_ROOT_CLASS,
53 .ids = ACPI_PCI_ROOT_HID,
54 .ops = {
55 .add = acpi_pci_root_add,
56 .remove = acpi_pci_root_remove,
57 },
58};
59
60struct acpi_pci_root {
61 struct list_head node;
62 acpi_handle handle;
63 struct acpi_pci_id id;
64 struct pci_bus *bus;
65};
66
67static LIST_HEAD(acpi_pci_roots);
68
69static struct acpi_pci_driver *sub_driver;
70
71int acpi_pci_register_driver(struct acpi_pci_driver *driver)
72{
73 int n = 0;
74 struct list_head *entry;
75
76 struct acpi_pci_driver **pptr = &sub_driver;
77 while (*pptr)
78 pptr = &(*pptr)->next;
79 *pptr = driver;
80
81 if (!driver->add)
82 return 0;
83
84 list_for_each(entry, &acpi_pci_roots) {
85 struct acpi_pci_root *root;
86 root = list_entry(entry, struct acpi_pci_root, node);
87 driver->add(root->handle);
88 n++;
89 }
90
91 return n;
92}
93EXPORT_SYMBOL(acpi_pci_register_driver);
94
95void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
96{
97 struct list_head *entry;
98
99 struct acpi_pci_driver **pptr = &sub_driver;
100 while (*pptr) {
101 if (*pptr != driver)
102 continue;
103 *pptr = (*pptr)->next;
104 break;
105 }
106
107 if (!driver->remove)
108 return;
109
110 list_for_each(entry, &acpi_pci_roots) {
111 struct acpi_pci_root *root;
112 root = list_entry(entry, struct acpi_pci_root, node);
113 driver->remove(root->handle);
114 }
115}
116EXPORT_SYMBOL(acpi_pci_unregister_driver);
117
118static acpi_status
119get_root_bridge_busnr_callback (struct acpi_resource *resource, void *data)
120{
121 int *busnr = (int *)data;
122 struct acpi_resource_address64 address;
123
124 if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
125 resource->id != ACPI_RSTYPE_ADDRESS32 &&
126 resource->id != ACPI_RSTYPE_ADDRESS64)
127 return AE_OK;
128
129 acpi_resource_to_address64(resource, &address);
130 if ((address.address_length > 0) &&
131 (address.resource_type == ACPI_BUS_NUMBER_RANGE))
132 *busnr = address.min_address_range;
133
134 return AE_OK;
135}
136
137static acpi_status
138try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
139{
140 acpi_status status;
141
142 *busnum = -1;
143 status = acpi_walk_resources(handle, METHOD_NAME__CRS, get_root_bridge_busnr_callback, busnum);
144 if (ACPI_FAILURE(status))
145 return status;
146 /* Check if we really get a bus number from _CRS */
147 if (*busnum == -1)
148 return AE_ERROR;
149 return AE_OK;
150}
151
152static int
153acpi_pci_root_add (
154 struct acpi_device *device)
155{
156 int result = 0;
157 struct acpi_pci_root *root = NULL;
158 struct acpi_pci_root *tmp;
159 acpi_status status = AE_OK;
160 unsigned long value = 0;
161 acpi_handle handle = NULL;
162
163 ACPI_FUNCTION_TRACE("acpi_pci_root_add");
164
165 if (!device)
166 return_VALUE(-EINVAL);
167
168 root = kmalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
169 if (!root)
170 return_VALUE(-ENOMEM);
171 memset(root, 0, sizeof(struct acpi_pci_root));
172
173 root->handle = device->handle;
174 strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
175 strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
176 acpi_driver_data(device) = root;
177
178 /*
179 * TBD: Doesn't the bus driver automatically set this?
180 */
181 device->ops.bind = acpi_pci_bind;
182
183 /*
184 * Segment
185 * -------
186 * Obtained via _SEG, if exists, otherwise assumed to be zero (0).
187 */
188 status = acpi_evaluate_integer(root->handle, METHOD_NAME__SEG, NULL,
189 &value);
190 switch (status) {
191 case AE_OK:
192 root->id.segment = (u16) value;
193 break;
194 case AE_NOT_FOUND:
195 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
196 "Assuming segment 0 (no _SEG)\n"));
197 root->id.segment = 0;
198 break;
199 default:
200 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SEG\n"));
201 result = -ENODEV;
202 goto end;
203 }
204
205 /*
206 * Bus
207 * ---
208 * Obtained via _BBN, if exists, otherwise assumed to be zero (0).
209 */
210 status = acpi_evaluate_integer(root->handle, METHOD_NAME__BBN, NULL,
211 &value);
212 switch (status) {
213 case AE_OK:
214 root->id.bus = (u16) value;
215 break;
216 case AE_NOT_FOUND:
217 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming bus 0 (no _BBN)\n"));
218 root->id.bus = 0;
219 break;
220 default:
221 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BBN\n"));
222 result = -ENODEV;
223 goto end;
224 }
225
226 /* Some systems have wrong _BBN */
227 list_for_each_entry(tmp, &acpi_pci_roots, node) {
228 if ((tmp->id.segment == root->id.segment)
229 && (tmp->id.bus == root->id.bus)) {
230 int bus = 0;
231 acpi_status status;
232
233 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
234 "Wrong _BBN value, please reboot and using option 'pci=noacpi'\n"));
235
236 status = try_get_root_bridge_busnr(root->handle, &bus);
237 if (ACPI_FAILURE(status))
238 break;
239 if (bus != root->id.bus) {
240 printk(KERN_INFO PREFIX "PCI _CRS %d overrides _BBN 0\n", bus);
241 root->id.bus = bus;
242 }
243 break;
244 }
245 }
246 /*
247 * Device & Function
248 * -----------------
249 * Obtained from _ADR (which has already been evaluated for us).
250 */
251 root->id.device = device->pnp.bus_address >> 16;
252 root->id.function = device->pnp.bus_address & 0xFFFF;
253
254 /*
255 * TBD: Need PCI interface for enumeration/configuration of roots.
256 */
257
258 /* TBD: Locking */
259 list_add_tail(&root->node, &acpi_pci_roots);
260
261 printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n",
262 acpi_device_name(device), acpi_device_bid(device),
263 root->id.segment, root->id.bus);
264
265 /*
266 * Scan the Root Bridge
267 * --------------------
268 * Must do this prior to any attempt to bind the root device, as the
269 * PCI namespace does not get created until this call is made (and
270 * thus the root bridge's pci_dev does not exist).
271 */
272 root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus);
273 if (!root->bus) {
274 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
275 "Bus %04x:%02x not present in PCI namespace\n",
276 root->id.segment, root->id.bus));
277 result = -ENODEV;
278 goto end;
279 }
280
281 /*
282 * Attach ACPI-PCI Context
283 * -----------------------
284 * Thus binding the ACPI and PCI devices.
285 */
286 result = acpi_pci_bind_root(device, &root->id, root->bus);
287 if (result)
288 goto end;
289
290 /*
291 * PCI Routing Table
292 * -----------------
293 * Evaluate and parse _PRT, if exists.
294 */
295 status = acpi_get_handle(root->handle, METHOD_NAME__PRT, &handle);
296 if (ACPI_SUCCESS(status))
297 result = acpi_pci_irq_add_prt(root->handle, root->id.segment,
298 root->id.bus);
299
300end:
301 if (result)
302 kfree(root);
303
304 return_VALUE(result);
305}
306
307
308static int
309acpi_pci_root_remove (
310 struct acpi_device *device,
311 int type)
312{
313 struct acpi_pci_root *root = NULL;
314
315 ACPI_FUNCTION_TRACE("acpi_pci_root_remove");
316
317 if (!device || !acpi_driver_data(device))
318 return_VALUE(-EINVAL);
319
320 root = (struct acpi_pci_root *) acpi_driver_data(device);
321
322 kfree(root);
323
324 return_VALUE(0);
325}
326
327
328static int __init acpi_pci_root_init (void)
329{
330 ACPI_FUNCTION_TRACE("acpi_pci_root_init");
331
332 if (acpi_pci_disabled)
333 return_VALUE(0);
334
335 /* DEBUG:
336 acpi_dbg_layer = ACPI_PCI_COMPONENT;
337 acpi_dbg_level = 0xFFFFFFFF;
338 */
339
340 if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
341 return_VALUE(-ENODEV);
342
343 return_VALUE(0);
344}
345
346subsys_initcall(acpi_pci_root_init);
347
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
new file mode 100644
index 000000000000..373a3a95bb4e
--- /dev/null
+++ b/drivers/acpi/power.c
@@ -0,0 +1,692 @@
1/*
2 * acpi_power.c - ACPI Bus Power Management ($Revision: 39 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
25
26/*
27 * ACPI power-managed devices may be controlled in two ways:
28 * 1. via "Device Specific (D-State) Control"
29 * 2. via "Power Resource Control".
30 * This module is used to manage devices relying on Power Resource Control.
31 *
32 * An ACPI "power resource object" describes a software controllable power
33 * plane, clock plane, or other resource used by a power managed device.
34 * A device may rely on multiple power resources, and a power resource
35 * may be shared by multiple devices.
36 */
37
38#include <linux/kernel.h>
39#include <linux/module.h>
40#include <linux/init.h>
41#include <linux/types.h>
42#include <linux/proc_fs.h>
43#include <linux/seq_file.h>
44#include <acpi/acpi_bus.h>
45#include <acpi/acpi_drivers.h>
46
47
48#define _COMPONENT ACPI_POWER_COMPONENT
49ACPI_MODULE_NAME ("acpi_power")
50
51#define ACPI_POWER_COMPONENT 0x00800000
52#define ACPI_POWER_CLASS "power_resource"
53#define ACPI_POWER_DRIVER_NAME "ACPI Power Resource Driver"
54#define ACPI_POWER_DEVICE_NAME "Power Resource"
55#define ACPI_POWER_FILE_INFO "info"
56#define ACPI_POWER_FILE_STATUS "state"
57#define ACPI_POWER_RESOURCE_STATE_OFF 0x00
58#define ACPI_POWER_RESOURCE_STATE_ON 0x01
59#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
60
61static int acpi_power_add (struct acpi_device *device);
62static int acpi_power_remove (struct acpi_device *device, int type);
63static int acpi_power_open_fs(struct inode *inode, struct file *file);
64
65static struct acpi_driver acpi_power_driver = {
66 .name = ACPI_POWER_DRIVER_NAME,
67 .class = ACPI_POWER_CLASS,
68 .ids = ACPI_POWER_HID,
69 .ops = {
70 .add = acpi_power_add,
71 .remove = acpi_power_remove,
72 },
73};
74
75struct acpi_power_resource
76{
77 acpi_handle handle;
78 acpi_bus_id name;
79 u32 system_level;
80 u32 order;
81 int state;
82 int references;
83};
84
85static struct list_head acpi_power_resource_list;
86
87static struct file_operations acpi_power_fops = {
88 .open = acpi_power_open_fs,
89 .read = seq_read,
90 .llseek = seq_lseek,
91 .release = single_release,
92};
93
94/* --------------------------------------------------------------------------
95 Power Resource Management
96 -------------------------------------------------------------------------- */
97
98static int
99acpi_power_get_context (
100 acpi_handle handle,
101 struct acpi_power_resource **resource)
102{
103 int result = 0;
104 struct acpi_device *device = NULL;
105
106 ACPI_FUNCTION_TRACE("acpi_power_get_context");
107
108 if (!resource)
109 return_VALUE(-ENODEV);
110
111 result = acpi_bus_get_device(handle, &device);
112 if (result) {
113 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error getting context [%p]\n",
114 handle));
115 return_VALUE(result);
116 }
117
118 *resource = (struct acpi_power_resource *) acpi_driver_data(device);
119 if (!resource)
120 return_VALUE(-ENODEV);
121
122 return_VALUE(0);
123}
124
125
126static int
127acpi_power_get_state (
128 struct acpi_power_resource *resource)
129{
130 acpi_status status = AE_OK;
131 unsigned long sta = 0;
132
133 ACPI_FUNCTION_TRACE("acpi_power_get_state");
134
135 if (!resource)
136 return_VALUE(-EINVAL);
137
138 status = acpi_evaluate_integer(resource->handle, "_STA", NULL, &sta);
139 if (ACPI_FAILURE(status))
140 return_VALUE(-ENODEV);
141
142 if (sta & 0x01)
143 resource->state = ACPI_POWER_RESOURCE_STATE_ON;
144 else
145 resource->state = ACPI_POWER_RESOURCE_STATE_OFF;
146
147 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
148 resource->name, resource->state?"on":"off"));
149
150 return_VALUE(0);
151}
152
153
154static int
155acpi_power_get_list_state (
156 struct acpi_handle_list *list,
157 int *state)
158{
159 int result = 0;
160 struct acpi_power_resource *resource = NULL;
161 u32 i = 0;
162
163 ACPI_FUNCTION_TRACE("acpi_power_get_list_state");
164
165 if (!list || !state)
166 return_VALUE(-EINVAL);
167
168 /* The state of the list is 'on' IFF all resources are 'on'. */
169
170 for (i=0; i<list->count; i++) {
171 result = acpi_power_get_context(list->handles[i], &resource);
172 if (result)
173 return_VALUE(result);
174 result = acpi_power_get_state(resource);
175 if (result)
176 return_VALUE(result);
177
178 *state = resource->state;
179
180 if (*state != ACPI_POWER_RESOURCE_STATE_ON)
181 break;
182 }
183
184 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
185 *state?"on":"off"));
186
187 return_VALUE(result);
188}
189
190
191static int
192acpi_power_on (
193 acpi_handle handle)
194{
195 int result = 0;
196 acpi_status status = AE_OK;
197 struct acpi_device *device = NULL;
198 struct acpi_power_resource *resource = NULL;
199
200 ACPI_FUNCTION_TRACE("acpi_power_on");
201
202 result = acpi_power_get_context(handle, &resource);
203 if (result)
204 return_VALUE(result);
205
206 resource->references++;
207
208 if ((resource->references > 1)
209 || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) {
210 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n",
211 resource->name));
212 return_VALUE(0);
213 }
214
215 status = acpi_evaluate_object(resource->handle, "_ON", NULL, NULL);
216 if (ACPI_FAILURE(status))
217 return_VALUE(-ENODEV);
218
219 result = acpi_power_get_state(resource);
220 if (result)
221 return_VALUE(result);
222 if (resource->state != ACPI_POWER_RESOURCE_STATE_ON)
223 return_VALUE(-ENOEXEC);
224
225 /* Update the power resource's _device_ power state */
226 result = acpi_bus_get_device(resource->handle, &device);
227 if (result)
228 return_VALUE(result);
229 device->power.state = ACPI_STATE_D0;
230
231 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n",
232 resource->name));
233
234 return_VALUE(0);
235}
236
237
238static int
239acpi_power_off_device (
240 acpi_handle handle)
241{
242 int result = 0;
243 acpi_status status = AE_OK;
244 struct acpi_device *device = NULL;
245 struct acpi_power_resource *resource = NULL;
246
247 ACPI_FUNCTION_TRACE("acpi_power_off_device");
248
249 result = acpi_power_get_context(handle, &resource);
250 if (result)
251 return_VALUE(result);
252
253 if (resource->references)
254 resource->references--;
255
256 if (resource->references) {
257 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
258 "Resource [%s] is still in use, dereferencing\n",
259 device->pnp.bus_id));
260 return_VALUE(0);
261 }
262
263 if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
264 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
265 device->pnp.bus_id));
266 return_VALUE(0);
267 }
268
269 status = acpi_evaluate_object(resource->handle, "_OFF", NULL, NULL);
270 if (ACPI_FAILURE(status))
271 return_VALUE(-ENODEV);
272
273 result = acpi_power_get_state(resource);
274 if (result)
275 return_VALUE(result);
276 if (resource->state != ACPI_POWER_RESOURCE_STATE_OFF)
277 return_VALUE(-ENOEXEC);
278
279 /* Update the power resource's _device_ power state */
280 result = acpi_bus_get_device(resource->handle, &device);
281 if (result)
282 return_VALUE(result);
283 device->power.state = ACPI_STATE_D3;
284
285 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n",
286 resource->name));
287
288 return_VALUE(0);
289}
290
291/*
292 * Prepare a wakeup device, two steps (Ref ACPI 2.0:P229):
293 * 1. Power on the power resources required for the wakeup device
294 * 2. Enable _PSW (power state wake) for the device if present
295 */
296int acpi_enable_wakeup_device_power (struct acpi_device *dev)
297{
298 union acpi_object arg = {ACPI_TYPE_INTEGER};
299 struct acpi_object_list arg_list = {1, &arg};
300 acpi_status status = AE_OK;
301 int i;
302 int ret = 0;
303
304 ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_power");
305 if (!dev || !dev->wakeup.flags.valid)
306 return_VALUE(-1);
307
308 arg.integer.value = 1;
309 /* Open power resource */
310 for (i = 0; i < dev->wakeup.resources.count; i++) {
311 ret = acpi_power_on(dev->wakeup.resources.handles[i]);
312 if (ret) {
313 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
314 "Error transition power state\n"));
315 dev->wakeup.flags.valid = 0;
316 return_VALUE(-1);
317 }
318 }
319
320 /* Execute PSW */
321 status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
322 if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
323 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluate _PSW\n"));
324 dev->wakeup.flags.valid = 0;
325 ret = -1;
326 }
327
328 return_VALUE(ret);
329}
330
331/*
332 * Shutdown a wakeup device, counterpart of above method
333 * 1. Disable _PSW (power state wake)
334 * 2. Shutdown down the power resources
335 */
336int acpi_disable_wakeup_device_power (struct acpi_device *dev)
337{
338 union acpi_object arg = {ACPI_TYPE_INTEGER};
339 struct acpi_object_list arg_list = {1, &arg};
340 acpi_status status = AE_OK;
341 int i;
342 int ret = 0;
343
344 ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device_power");
345
346 if (!dev || !dev->wakeup.flags.valid)
347 return_VALUE(-1);
348
349 arg.integer.value = 0;
350 /* Execute PSW */
351 status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
352 if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
353 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluate _PSW\n"));
354 dev->wakeup.flags.valid = 0;
355 return_VALUE(-1);
356 }
357
358 /* Close power resource */
359 for (i = 0; i < dev->wakeup.resources.count; i++) {
360 ret = acpi_power_off_device(dev->wakeup.resources.handles[i]);
361 if (ret) {
362 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
363 "Error transition power state\n"));
364 dev->wakeup.flags.valid = 0;
365 return_VALUE(-1);
366 }
367 }
368
369 return_VALUE(ret);
370}
371
372/* --------------------------------------------------------------------------
373 Device Power Management
374 -------------------------------------------------------------------------- */
375
376int
377acpi_power_get_inferred_state (
378 struct acpi_device *device)
379{
380 int result = 0;
381 struct acpi_handle_list *list = NULL;
382 int list_state = 0;
383 int i = 0;
384
385 ACPI_FUNCTION_TRACE("acpi_power_get_inferred_state");
386
387 if (!device)
388 return_VALUE(-EINVAL);
389
390 device->power.state = ACPI_STATE_UNKNOWN;
391
392 /*
393 * We know a device's inferred power state when all the resources
394 * required for a given D-state are 'on'.
395 */
396 for (i=ACPI_STATE_D0; i<ACPI_STATE_D3; i++) {
397 list = &device->power.states[i].resources;
398 if (list->count < 1)
399 continue;
400
401 result = acpi_power_get_list_state(list, &list_state);
402 if (result)
403 return_VALUE(result);
404
405 if (list_state == ACPI_POWER_RESOURCE_STATE_ON) {
406 device->power.state = i;
407 return_VALUE(0);
408 }
409 }
410
411 device->power.state = ACPI_STATE_D3;
412
413 return_VALUE(0);
414}
415
416
417int
418acpi_power_transition (
419 struct acpi_device *device,
420 int state)
421{
422 int result = 0;
423 struct acpi_handle_list *cl = NULL; /* Current Resources */
424 struct acpi_handle_list *tl = NULL; /* Target Resources */
425 int i = 0;
426
427 ACPI_FUNCTION_TRACE("acpi_power_transition");
428
429 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
430 return_VALUE(-EINVAL);
431
432 if ((device->power.state < ACPI_STATE_D0) || (device->power.state > ACPI_STATE_D3))
433 return_VALUE(-ENODEV);
434
435 cl = &device->power.states[device->power.state].resources;
436 tl = &device->power.states[state].resources;
437
438 device->power.state = ACPI_STATE_UNKNOWN;
439
440 if (!cl->count && !tl->count) {
441 result = -ENODEV;
442 goto end;
443 }
444
445 /* TBD: Resources must be ordered. */
446
447 /*
448 * First we reference all power resources required in the target list
449 * (e.g. so the device doesn't lose power while transitioning).
450 */
451 for (i=0; i<tl->count; i++) {
452 result = acpi_power_on(tl->handles[i]);
453 if (result)
454 goto end;
455 }
456
457 /*
458 * Then we dereference all power resources used in the current list.
459 */
460 for (i=0; i<cl->count; i++) {
461 result = acpi_power_off_device(cl->handles[i]);
462 if (result)
463 goto end;
464 }
465
466 /* We shouldn't change the state till all above operations succeed */
467 device->power.state = state;
468end:
469 if (result)
470 ACPI_DEBUG_PRINT((ACPI_DB_WARN,
471 "Error transitioning device [%s] to D%d\n",
472 device->pnp.bus_id, state));
473
474 return_VALUE(result);
475}
476
477
478/* --------------------------------------------------------------------------
479 FS Interface (/proc)
480 -------------------------------------------------------------------------- */
481
482static struct proc_dir_entry *acpi_power_dir;
483
484static int acpi_power_seq_show(struct seq_file *seq, void *offset)
485{
486 struct acpi_power_resource *resource = NULL;
487
488 ACPI_FUNCTION_TRACE("acpi_power_seq_show");
489
490 resource = (struct acpi_power_resource *)seq->private;
491
492 if (!resource)
493 goto end;
494
495 seq_puts(seq, "state: ");
496 switch (resource->state) {
497 case ACPI_POWER_RESOURCE_STATE_ON:
498 seq_puts(seq, "on\n");
499 break;
500 case ACPI_POWER_RESOURCE_STATE_OFF:
501 seq_puts(seq, "off\n");
502 break;
503 default:
504 seq_puts(seq, "unknown\n");
505 break;
506 }
507
508 seq_printf(seq, "system level: S%d\n"
509 "order: %d\n"
510 "reference count: %d\n",
511 resource->system_level,
512 resource->order,
513 resource->references);
514
515end:
516 return_VALUE(0);
517}
518
519static int acpi_power_open_fs(struct inode *inode, struct file *file)
520{
521 return single_open(file, acpi_power_seq_show, PDE(inode)->data);
522}
523
524static int
525acpi_power_add_fs (
526 struct acpi_device *device)
527{
528 struct proc_dir_entry *entry = NULL;
529
530 ACPI_FUNCTION_TRACE("acpi_power_add_fs");
531
532 if (!device)
533 return_VALUE(-EINVAL);
534
535 if (!acpi_device_dir(device)) {
536 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
537 acpi_power_dir);
538 if (!acpi_device_dir(device))
539 return_VALUE(-ENODEV);
540 }
541
542 /* 'status' [R] */
543 entry = create_proc_entry(ACPI_POWER_FILE_STATUS,
544 S_IRUGO, acpi_device_dir(device));
545 if (!entry)
546 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
547 "Unable to create '%s' fs entry\n",
548 ACPI_POWER_FILE_STATUS));
549 else {
550 entry->proc_fops = &acpi_power_fops;
551 entry->data = acpi_driver_data(device);
552 }
553
554 return_VALUE(0);
555}
556
557
558static int
559acpi_power_remove_fs (
560 struct acpi_device *device)
561{
562 ACPI_FUNCTION_TRACE("acpi_power_remove_fs");
563
564 if (acpi_device_dir(device)) {
565 remove_proc_entry(ACPI_POWER_FILE_STATUS,
566 acpi_device_dir(device));
567 remove_proc_entry(acpi_device_bid(device), acpi_power_dir);
568 acpi_device_dir(device) = NULL;
569 }
570
571 return_VALUE(0);
572}
573
574
575/* --------------------------------------------------------------------------
576 Driver Interface
577 -------------------------------------------------------------------------- */
578
579static int
580acpi_power_add (
581 struct acpi_device *device)
582{
583 int result = 0;
584 acpi_status status = AE_OK;
585 struct acpi_power_resource *resource = NULL;
586 union acpi_object acpi_object;
587 struct acpi_buffer buffer = {sizeof(acpi_object), &acpi_object};
588
589 ACPI_FUNCTION_TRACE("acpi_power_add");
590
591 if (!device)
592 return_VALUE(-EINVAL);
593
594 resource = kmalloc(sizeof(struct acpi_power_resource), GFP_KERNEL);
595 if (!resource)
596 return_VALUE(-ENOMEM);
597 memset(resource, 0, sizeof(struct acpi_power_resource));
598
599 resource->handle = device->handle;
600 strcpy(resource->name, device->pnp.bus_id);
601 strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
602 strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
603 acpi_driver_data(device) = resource;
604
605 /* Evalute the object to get the system level and resource order. */
606 status = acpi_evaluate_object(resource->handle, NULL, NULL, &buffer);
607 if (ACPI_FAILURE(status)) {
608 result = -ENODEV;
609 goto end;
610 }
611 resource->system_level = acpi_object.power_resource.system_level;
612 resource->order = acpi_object.power_resource.resource_order;
613
614 result = acpi_power_get_state(resource);
615 if (result)
616 goto end;
617
618 switch (resource->state) {
619 case ACPI_POWER_RESOURCE_STATE_ON:
620 device->power.state = ACPI_STATE_D0;
621 break;
622 case ACPI_POWER_RESOURCE_STATE_OFF:
623 device->power.state = ACPI_STATE_D3;
624 break;
625 default:
626 device->power.state = ACPI_STATE_UNKNOWN;
627 break;
628 }
629
630 result = acpi_power_add_fs(device);
631 if (result)
632 goto end;
633
634 printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device),
635 acpi_device_bid(device), resource->state?"on":"off");
636
637end:
638 if (result)
639 kfree(resource);
640
641 return_VALUE(result);
642}
643
644
645static int
646acpi_power_remove (
647 struct acpi_device *device,
648 int type)
649{
650 struct acpi_power_resource *resource = NULL;
651
652 ACPI_FUNCTION_TRACE("acpi_power_remove");
653
654 if (!device || !acpi_driver_data(device))
655 return_VALUE(-EINVAL);
656
657 resource = (struct acpi_power_resource *) acpi_driver_data(device);
658
659 acpi_power_remove_fs(device);
660
661 kfree(resource);
662
663 return_VALUE(0);
664}
665
666
667static int __init acpi_power_init (void)
668{
669 int result = 0;
670
671 ACPI_FUNCTION_TRACE("acpi_power_init");
672
673 if (acpi_disabled)
674 return_VALUE(0);
675
676 INIT_LIST_HEAD(&acpi_power_resource_list);
677
678 acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir);
679 if (!acpi_power_dir)
680 return_VALUE(-ENODEV);
681
682 result = acpi_bus_register_driver(&acpi_power_driver);
683 if (result < 0) {
684 remove_proc_entry(ACPI_POWER_CLASS, acpi_root_dir);
685 return_VALUE(-ENODEV);
686 }
687
688 return_VALUE(0);
689}
690
691subsys_initcall(acpi_power_init);
692
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
new file mode 100644
index 000000000000..f4778747e889
--- /dev/null
+++ b/drivers/acpi/processor_core.c
@@ -0,0 +1,989 @@
1/*
2 * acpi_processor.c - ACPI Processor Driver ($Revision: 71 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de>
7 * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
8 * - Added processor hotplug support
9 *
10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or (at
15 * your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 *
26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 * TBD:
28 * 1. Make # power states dynamic.
29 * 2. Support duty_cycle values that span bit 4.
30 * 3. Optimize by having scheduler determine business instead of
31 * having us try to calculate it here.
32 * 4. Need C1 timing -- must modify kernel (IRQ handler) to get this.
33 */
34
35#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/init.h>
38#include <linux/types.h>
39#include <linux/pci.h>
40#include <linux/pm.h>
41#include <linux/cpufreq.h>
42#include <linux/cpu.h>
43#include <linux/proc_fs.h>
44#include <linux/seq_file.h>
45#include <linux/dmi.h>
46#include <linux/moduleparam.h>
47
48#include <asm/io.h>
49#include <asm/system.h>
50#include <asm/cpu.h>
51#include <asm/delay.h>
52#include <asm/uaccess.h>
53#include <asm/processor.h>
54#include <asm/smp.h>
55#include <asm/acpi.h>
56
57#include <acpi/acpi_bus.h>
58#include <acpi/acpi_drivers.h>
59#include <acpi/processor.h>
60
61
62#define ACPI_PROCESSOR_COMPONENT 0x01000000
63#define ACPI_PROCESSOR_CLASS "processor"
64#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
65#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
66#define ACPI_PROCESSOR_FILE_INFO "info"
67#define ACPI_PROCESSOR_FILE_THROTTLING "throttling"
68#define ACPI_PROCESSOR_FILE_LIMIT "limit"
69#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
70#define ACPI_PROCESSOR_NOTIFY_POWER 0x81
71
72#define ACPI_PROCESSOR_LIMIT_USER 0
73#define ACPI_PROCESSOR_LIMIT_THERMAL 1
74
75#define ACPI_STA_PRESENT 0x00000001
76
77#define _COMPONENT ACPI_PROCESSOR_COMPONENT
78ACPI_MODULE_NAME ("acpi_processor")
79
80MODULE_AUTHOR("Paul Diefenbaugh");
81MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
82MODULE_LICENSE("GPL");
83
84
85static int acpi_processor_add (struct acpi_device *device);
86static int acpi_processor_start (struct acpi_device *device);
87static int acpi_processor_remove (struct acpi_device *device, int type);
88static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
89static void acpi_processor_notify ( acpi_handle handle, u32 event, void *data);
90static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
91static int acpi_processor_handle_eject(struct acpi_processor *pr);
92
93static struct acpi_driver acpi_processor_driver = {
94 .name = ACPI_PROCESSOR_DRIVER_NAME,
95 .class = ACPI_PROCESSOR_CLASS,
96 .ids = ACPI_PROCESSOR_HID,
97 .ops = {
98 .add = acpi_processor_add,
99 .remove = acpi_processor_remove,
100 .start = acpi_processor_start,
101 },
102};
103
104#define INSTALL_NOTIFY_HANDLER 1
105#define UNINSTALL_NOTIFY_HANDLER 2
106
107
108static struct file_operations acpi_processor_info_fops = {
109 .open = acpi_processor_info_open_fs,
110 .read = seq_read,
111 .llseek = seq_lseek,
112 .release = single_release,
113};
114
115
116struct acpi_processor *processors[NR_CPUS];
117struct acpi_processor_errata errata;
118
119
120/* --------------------------------------------------------------------------
121 Errata Handling
122 -------------------------------------------------------------------------- */
123
124static int
125acpi_processor_errata_piix4 (
126 struct pci_dev *dev)
127{
128 u8 rev = 0;
129 u8 value1 = 0;
130 u8 value2 = 0;
131
132 ACPI_FUNCTION_TRACE("acpi_processor_errata_piix4");
133
134 if (!dev)
135 return_VALUE(-EINVAL);
136
137 /*
138 * Note that 'dev' references the PIIX4 ACPI Controller.
139 */
140
141 pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
142
143 switch (rev) {
144 case 0:
145 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
146 break;
147 case 1:
148 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n"));
149 break;
150 case 2:
151 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n"));
152 break;
153 case 3:
154 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n"));
155 break;
156 default:
157 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n"));
158 break;
159 }
160
161 switch (rev) {
162
163 case 0: /* PIIX4 A-step */
164 case 1: /* PIIX4 B-step */
165 /*
166 * See specification changes #13 ("Manual Throttle Duty Cycle")
167 * and #14 ("Enabling and Disabling Manual Throttle"), plus
168 * erratum #5 ("STPCLK# Deassertion Time") from the January
169 * 2002 PIIX4 specification update. Applies to only older
170 * PIIX4 models.
171 */
172 errata.piix4.throttle = 1;
173
174 case 2: /* PIIX4E */
175 case 3: /* PIIX4M */
176 /*
177 * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA
178 * Livelock") from the January 2002 PIIX4 specification update.
179 * Applies to all PIIX4 models.
180 */
181
182 /*
183 * BM-IDE
184 * ------
185 * Find the PIIX4 IDE Controller and get the Bus Master IDE
186 * Status register address. We'll use this later to read
187 * each IDE controller's DMA status to make sure we catch all
188 * DMA activity.
189 */
190 dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
191 PCI_DEVICE_ID_INTEL_82371AB,
192 PCI_ANY_ID, PCI_ANY_ID, NULL);
193 if (dev) {
194 errata.piix4.bmisx = pci_resource_start(dev, 4);
195 pci_dev_put(dev);
196 }
197
198 /*
199 * Type-F DMA
200 * ----------
201 * Find the PIIX4 ISA Controller and read the Motherboard
202 * DMA controller's status to see if Type-F (Fast) DMA mode
203 * is enabled (bit 7) on either channel. Note that we'll
204 * disable C3 support if this is enabled, as some legacy
205 * devices won't operate well if fast DMA is disabled.
206 */
207 dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
208 PCI_DEVICE_ID_INTEL_82371AB_0,
209 PCI_ANY_ID, PCI_ANY_ID, NULL);
210 if (dev) {
211 pci_read_config_byte(dev, 0x76, &value1);
212 pci_read_config_byte(dev, 0x77, &value2);
213 if ((value1 & 0x80) || (value2 & 0x80))
214 errata.piix4.fdma = 1;
215 pci_dev_put(dev);
216 }
217
218 break;
219 }
220
221 if (errata.piix4.bmisx)
222 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
223 "Bus master activity detection (BM-IDE) erratum enabled\n"));
224 if (errata.piix4.fdma)
225 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
226 "Type-F DMA livelock erratum (C3 disabled)\n"));
227
228 return_VALUE(0);
229}
230
231
232int
233acpi_processor_errata (
234 struct acpi_processor *pr)
235{
236 int result = 0;
237 struct pci_dev *dev = NULL;
238
239 ACPI_FUNCTION_TRACE("acpi_processor_errata");
240
241 if (!pr)
242 return_VALUE(-EINVAL);
243
244 /*
245 * PIIX4
246 */
247 dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
248 PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL);
249 if (dev) {
250 result = acpi_processor_errata_piix4(dev);
251 pci_dev_put(dev);
252 }
253
254 return_VALUE(result);
255}
256
257
258/* --------------------------------------------------------------------------
259 FS Interface (/proc)
260 -------------------------------------------------------------------------- */
261
262static struct proc_dir_entry *acpi_processor_dir = NULL;
263
264static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
265{
266 struct acpi_processor *pr = (struct acpi_processor *)seq->private;
267
268 ACPI_FUNCTION_TRACE("acpi_processor_info_seq_show");
269
270 if (!pr)
271 goto end;
272
273 seq_printf(seq, "processor id: %d\n"
274 "acpi id: %d\n"
275 "bus mastering control: %s\n"
276 "power management: %s\n"
277 "throttling control: %s\n"
278 "limit interface: %s\n",
279 pr->id,
280 pr->acpi_id,
281 pr->flags.bm_control ? "yes" : "no",
282 pr->flags.power ? "yes" : "no",
283 pr->flags.throttling ? "yes" : "no",
284 pr->flags.limit ? "yes" : "no");
285
286end:
287 return_VALUE(0);
288}
289
290static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
291{
292 return single_open(file, acpi_processor_info_seq_show,
293 PDE(inode)->data);
294}
295
296
297static int
298acpi_processor_add_fs (
299 struct acpi_device *device)
300{
301 struct proc_dir_entry *entry = NULL;
302
303 ACPI_FUNCTION_TRACE("acpi_processor_add_fs");
304
305 if (!acpi_device_dir(device)) {
306 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
307 acpi_processor_dir);
308 if (!acpi_device_dir(device))
309 return_VALUE(-ENODEV);
310 }
311 acpi_device_dir(device)->owner = THIS_MODULE;
312
313 /* 'info' [R] */
314 entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO,
315 S_IRUGO, acpi_device_dir(device));
316 if (!entry)
317 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
318 "Unable to create '%s' fs entry\n",
319 ACPI_PROCESSOR_FILE_INFO));
320 else {
321 entry->proc_fops = &acpi_processor_info_fops;
322 entry->data = acpi_driver_data(device);
323 entry->owner = THIS_MODULE;
324 }
325
326 /* 'throttling' [R/W] */
327 entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
328 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
329 if (!entry)
330 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
331 "Unable to create '%s' fs entry\n",
332 ACPI_PROCESSOR_FILE_THROTTLING));
333 else {
334 entry->proc_fops = &acpi_processor_throttling_fops;
335 entry->proc_fops->write = acpi_processor_write_throttling;
336 entry->data = acpi_driver_data(device);
337 entry->owner = THIS_MODULE;
338 }
339
340 /* 'limit' [R/W] */
341 entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
342 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
343 if (!entry)
344 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
345 "Unable to create '%s' fs entry\n",
346 ACPI_PROCESSOR_FILE_LIMIT));
347 else {
348 entry->proc_fops = &acpi_processor_limit_fops;
349 entry->proc_fops->write = acpi_processor_write_limit;
350 entry->data = acpi_driver_data(device);
351 entry->owner = THIS_MODULE;
352 }
353
354 return_VALUE(0);
355}
356
357
358static int
359acpi_processor_remove_fs (
360 struct acpi_device *device)
361{
362 ACPI_FUNCTION_TRACE("acpi_processor_remove_fs");
363
364 if (acpi_device_dir(device)) {
365 remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,acpi_device_dir(device));
366 remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
367 acpi_device_dir(device));
368 remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,acpi_device_dir(device));
369 remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
370 acpi_device_dir(device) = NULL;
371 }
372
373 return_VALUE(0);
374}
375
376/* Use the acpiid in MADT to map cpus in case of SMP */
377#ifndef CONFIG_SMP
378#define convert_acpiid_to_cpu(acpi_id) (0xff)
379#else
380
381#ifdef CONFIG_IA64
382#define arch_acpiid_to_apicid ia64_acpiid_to_sapicid
383#define arch_cpu_to_apicid ia64_cpu_to_sapicid
384#define ARCH_BAD_APICID (0xffff)
385#else
386#define arch_acpiid_to_apicid x86_acpiid_to_apicid
387#define arch_cpu_to_apicid x86_cpu_to_apicid
388#define ARCH_BAD_APICID (0xff)
389#endif
390
391static u8 convert_acpiid_to_cpu(u8 acpi_id)
392{
393 u16 apic_id;
394 int i;
395
396 apic_id = arch_acpiid_to_apicid[acpi_id];
397 if (apic_id == ARCH_BAD_APICID)
398 return -1;
399
400 for (i = 0; i < NR_CPUS; i++) {
401 if (arch_cpu_to_apicid[i] == apic_id)
402 return i;
403 }
404 return -1;
405}
406#endif
407
408/* --------------------------------------------------------------------------
409 Driver Interface
410 -------------------------------------------------------------------------- */
411
412static int
413acpi_processor_get_info (
414 struct acpi_processor *pr)
415{
416 acpi_status status = 0;
417 union acpi_object object = {0};
418 struct acpi_buffer buffer = {sizeof(union acpi_object), &object};
419 u8 cpu_index;
420 static int cpu0_initialized;
421
422 ACPI_FUNCTION_TRACE("acpi_processor_get_info");
423
424 if (!pr)
425 return_VALUE(-EINVAL);
426
427 if (num_online_cpus() > 1)
428 errata.smp = TRUE;
429
430 acpi_processor_errata(pr);
431
432 /*
433 * Check to see if we have bus mastering arbitration control. This
434 * is required for proper C3 usage (to maintain cache coherency).
435 */
436 if (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len) {
437 pr->flags.bm_control = 1;
438 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
439 "Bus mastering arbitration control present\n"));
440 }
441 else
442 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
443 "No bus mastering arbitration control\n"));
444
445 /*
446 * Evalute the processor object. Note that it is common on SMP to
447 * have the first (boot) processor with a valid PBLK address while
448 * all others have a NULL address.
449 */
450 status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
451 if (ACPI_FAILURE(status)) {
452 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
453 "Error evaluating processor object\n"));
454 return_VALUE(-ENODEV);
455 }
456
457 /*
458 * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
459 * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
460 */
461 pr->acpi_id = object.processor.proc_id;
462
463 cpu_index = convert_acpiid_to_cpu(pr->acpi_id);
464
465 /* Handle UP system running SMP kernel, with no LAPIC in MADT */
466 if ( !cpu0_initialized && (cpu_index == 0xff) &&
467 (num_online_cpus() == 1)) {
468 cpu_index = 0;
469 }
470
471 cpu0_initialized = 1;
472
473 pr->id = cpu_index;
474
475 /*
476 * Extra Processor objects may be enumerated on MP systems with
477 * less than the max # of CPUs. They should be ignored _iff
478 * they are physically not present.
479 */
480 if (cpu_index >= NR_CPUS) {
481 if (ACPI_FAILURE(acpi_processor_hotadd_init(pr->handle, &pr->id))) {
482 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
483 "Error getting cpuindex for acpiid 0x%x\n",
484 pr->acpi_id));
485 return_VALUE(-ENODEV);
486 }
487 }
488
489 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
490 pr->acpi_id));
491
492 if (!object.processor.pblk_address)
493 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
494 else if (object.processor.pblk_length != 6)
495 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid PBLK length [%d]\n",
496 object.processor.pblk_length));
497 else {
498 pr->throttling.address = object.processor.pblk_address;
499 pr->throttling.duty_offset = acpi_fadt.duty_offset;
500 pr->throttling.duty_width = acpi_fadt.duty_width;
501
502 pr->pblk = object.processor.pblk_address;
503
504 /*
505 * We don't care about error returns - we just try to mark
506 * these reserved so that nobody else is confused into thinking
507 * that this region might be unused..
508 *
509 * (In particular, allocating the IO range for Cardbus)
510 */
511 request_region(pr->throttling.address, 6, "ACPI CPU throttle");
512 }
513
514#ifdef CONFIG_CPU_FREQ
515 acpi_processor_ppc_has_changed(pr);
516#endif
517 acpi_processor_get_throttling_info(pr);
518 acpi_processor_get_limit_info(pr);
519
520 return_VALUE(0);
521}
522
523static int
524acpi_processor_start(
525 struct acpi_device *device)
526{
527 int result = 0;
528 acpi_status status = AE_OK;
529 struct acpi_processor *pr;
530
531 ACPI_FUNCTION_TRACE("acpi_processor_start");
532
533 pr = acpi_driver_data(device);
534
535 result = acpi_processor_get_info(pr);
536 if (result) {
537 /* Processor is physically not present */
538 return_VALUE(0);
539 }
540
541 BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0));
542
543 processors[pr->id] = pr;
544
545 result = acpi_processor_add_fs(device);
546 if (result)
547 goto end;
548
549 status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
550 acpi_processor_notify, pr);
551 if (ACPI_FAILURE(status)) {
552 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
553 "Error installing device notify handler\n"));
554 }
555
556 acpi_processor_power_init(pr, device);
557
558 if (pr->flags.throttling) {
559 printk(KERN_INFO PREFIX "%s [%s] (supports",
560 acpi_device_name(device), acpi_device_bid(device));
561 printk(" %d throttling states", pr->throttling.state_count);
562 printk(")\n");
563 }
564
565end:
566
567 return_VALUE(result);
568}
569
570
571
572static void
573acpi_processor_notify (
574 acpi_handle handle,
575 u32 event,
576 void *data)
577{
578 struct acpi_processor *pr = (struct acpi_processor *) data;
579 struct acpi_device *device = NULL;
580
581 ACPI_FUNCTION_TRACE("acpi_processor_notify");
582
583 if (!pr)
584 return_VOID;
585
586 if (acpi_bus_get_device(pr->handle, &device))
587 return_VOID;
588
589 switch (event) {
590 case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
591 acpi_processor_ppc_has_changed(pr);
592 acpi_bus_generate_event(device, event,
593 pr->performance_platform_limit);
594 break;
595 case ACPI_PROCESSOR_NOTIFY_POWER:
596 acpi_processor_cst_has_changed(pr);
597 acpi_bus_generate_event(device, event, 0);
598 break;
599 default:
600 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
601 "Unsupported event [0x%x]\n", event));
602 break;
603 }
604
605 return_VOID;
606}
607
608
609static int
610acpi_processor_add (
611 struct acpi_device *device)
612{
613 struct acpi_processor *pr = NULL;
614
615 ACPI_FUNCTION_TRACE("acpi_processor_add");
616
617 if (!device)
618 return_VALUE(-EINVAL);
619
620 pr = kmalloc(sizeof(struct acpi_processor), GFP_KERNEL);
621 if (!pr)
622 return_VALUE(-ENOMEM);
623 memset(pr, 0, sizeof(struct acpi_processor));
624
625 pr->handle = device->handle;
626 strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
627 strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
628 acpi_driver_data(device) = pr;
629
630 return_VALUE(0);
631}
632
633
634static int
635acpi_processor_remove (
636 struct acpi_device *device,
637 int type)
638{
639 acpi_status status = AE_OK;
640 struct acpi_processor *pr = NULL;
641
642 ACPI_FUNCTION_TRACE("acpi_processor_remove");
643
644 if (!device || !acpi_driver_data(device))
645 return_VALUE(-EINVAL);
646
647 pr = (struct acpi_processor *) acpi_driver_data(device);
648
649 if (pr->id >= NR_CPUS) {
650 kfree(pr);
651 return_VALUE(0);
652 }
653
654 if (type == ACPI_BUS_REMOVAL_EJECT) {
655 if (acpi_processor_handle_eject(pr))
656 return_VALUE(-EINVAL);
657 }
658
659 acpi_processor_power_exit(pr, device);
660
661 status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
662 acpi_processor_notify);
663 if (ACPI_FAILURE(status)) {
664 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
665 "Error removing notify handler\n"));
666 }
667
668 acpi_processor_remove_fs(device);
669
670 processors[pr->id] = NULL;
671
672 kfree(pr);
673
674 return_VALUE(0);
675}
676
677#ifdef CONFIG_ACPI_HOTPLUG_CPU
678/****************************************************************************
679 * Acpi processor hotplug support *
680 ****************************************************************************/
681
682static int is_processor_present(acpi_handle handle);
683
684static int
685is_processor_present(
686 acpi_handle handle)
687{
688 acpi_status status;
689 unsigned long sta = 0;
690
691 ACPI_FUNCTION_TRACE("is_processor_present");
692
693 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
694 if (ACPI_FAILURE(status) || !(sta & ACPI_STA_PRESENT)) {
695 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
696 "Processor Device is not present\n"));
697 return_VALUE(0);
698 }
699 return_VALUE(1);
700}
701
702
703static
704int acpi_processor_device_add(
705 acpi_handle handle,
706 struct acpi_device **device)
707{
708 acpi_handle phandle;
709 struct acpi_device *pdev;
710 struct acpi_processor *pr;
711
712 ACPI_FUNCTION_TRACE("acpi_processor_device_add");
713
714 if (acpi_get_parent(handle, &phandle)) {
715 return_VALUE(-ENODEV);
716 }
717
718 if (acpi_bus_get_device(phandle, &pdev)) {
719 return_VALUE(-ENODEV);
720 }
721
722 if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
723 return_VALUE(-ENODEV);
724 }
725
726 acpi_bus_scan(*device);
727
728 pr = acpi_driver_data(*device);
729 if (!pr)
730 return_VALUE(-ENODEV);
731
732 if ((pr->id >=0) && (pr->id < NR_CPUS)) {
733 kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE);
734 }
735 return_VALUE(0);
736}
737
738
739static void
740acpi_processor_hotplug_notify (
741 acpi_handle handle,
742 u32 event,
743 void *data)
744{
745 struct acpi_processor *pr;
746 struct acpi_device *device = NULL;
747 int result;
748
749 ACPI_FUNCTION_TRACE("acpi_processor_hotplug_notify");
750
751 switch (event) {
752 case ACPI_NOTIFY_BUS_CHECK:
753 case ACPI_NOTIFY_DEVICE_CHECK:
754 printk("Processor driver received %s event\n",
755 (event==ACPI_NOTIFY_BUS_CHECK)?
756 "ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK");
757
758 if (!is_processor_present(handle))
759 break;
760
761 if (acpi_bus_get_device(handle, &device)) {
762 result = acpi_processor_device_add(handle, &device);
763 if (result)
764 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
765 "Unable to add the device\n"));
766 break;
767 }
768
769 pr = acpi_driver_data(device);
770 if (!pr) {
771 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
772 "Driver data is NULL\n"));
773 break;
774 }
775
776 if (pr->id >= 0 && (pr->id < NR_CPUS)) {
777 kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
778 break;
779 }
780
781 result = acpi_processor_start(device);
782 if ((!result) && ((pr->id >=0) && (pr->id < NR_CPUS))) {
783 kobject_hotplug(&device->kobj, KOBJ_ONLINE);
784 } else {
785 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
786 "Device [%s] failed to start\n",
787 acpi_device_bid(device)));
788 }
789 break;
790 case ACPI_NOTIFY_EJECT_REQUEST:
791 ACPI_DEBUG_PRINT((ACPI_DB_INFO,"received ACPI_NOTIFY_EJECT_REQUEST\n"));
792
793 if (acpi_bus_get_device(handle, &device)) {
794 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Device don't exist, dropping EJECT\n"));
795 break;
796 }
797 pr = acpi_driver_data(device);
798 if (!pr) {
799 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Driver data is NULL, dropping EJECT\n"));
800 return_VOID;
801 }
802
803 if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
804 kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
805 break;
806 default:
807 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
808 "Unsupported event [0x%x]\n", event));
809 break;
810 }
811
812 return_VOID;
813}
814
815static acpi_status
816processor_walk_namespace_cb(acpi_handle handle,
817 u32 lvl,
818 void *context,
819 void **rv)
820{
821 acpi_status status;
822 int *action = context;
823 acpi_object_type type = 0;
824
825 status = acpi_get_type(handle, &type);
826 if (ACPI_FAILURE(status))
827 return(AE_OK);
828
829 if (type != ACPI_TYPE_PROCESSOR)
830 return(AE_OK);
831
832 switch(*action) {
833 case INSTALL_NOTIFY_HANDLER:
834 acpi_install_notify_handler(handle,
835 ACPI_SYSTEM_NOTIFY,
836 acpi_processor_hotplug_notify,
837 NULL);
838 break;
839 case UNINSTALL_NOTIFY_HANDLER:
840 acpi_remove_notify_handler(handle,
841 ACPI_SYSTEM_NOTIFY,
842 acpi_processor_hotplug_notify);
843 break;
844 default:
845 break;
846 }
847
848 return(AE_OK);
849}
850
851
852static acpi_status
853acpi_processor_hotadd_init(
854 acpi_handle handle,
855 int *p_cpu)
856{
857 ACPI_FUNCTION_TRACE("acpi_processor_hotadd_init");
858
859 if (!is_processor_present(handle)) {
860 return_VALUE(AE_ERROR);
861 }
862
863 if (acpi_map_lsapic(handle, p_cpu))
864 return_VALUE(AE_ERROR);
865
866 if (arch_register_cpu(*p_cpu)) {
867 acpi_unmap_lsapic(*p_cpu);
868 return_VALUE(AE_ERROR);
869 }
870
871 return_VALUE(AE_OK);
872}
873
874
875static int
876acpi_processor_handle_eject(struct acpi_processor *pr)
877{
878 if (cpu_online(pr->id)) {
879 return(-EINVAL);
880 }
881 arch_unregister_cpu(pr->id);
882 acpi_unmap_lsapic(pr->id);
883 return(0);
884}
885#else
886static acpi_status
887acpi_processor_hotadd_init(
888 acpi_handle handle,
889 int *p_cpu)
890{
891 return AE_ERROR;
892}
893static int
894acpi_processor_handle_eject(struct acpi_processor *pr)
895{
896 return(-EINVAL);
897}
898#endif
899
900
901static
902void acpi_processor_install_hotplug_notify(void)
903{
904#ifdef CONFIG_ACPI_HOTPLUG_CPU
905 int action = INSTALL_NOTIFY_HANDLER;
906 acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
907 ACPI_ROOT_OBJECT,
908 ACPI_UINT32_MAX,
909 processor_walk_namespace_cb,
910 &action, NULL);
911#endif
912}
913
914
915static
916void acpi_processor_uninstall_hotplug_notify(void)
917{
918#ifdef CONFIG_ACPI_HOTPLUG_CPU
919 int action = UNINSTALL_NOTIFY_HANDLER;
920 acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
921 ACPI_ROOT_OBJECT,
922 ACPI_UINT32_MAX,
923 processor_walk_namespace_cb,
924 &action, NULL);
925#endif
926}
927
928/*
929 * We keep the driver loaded even when ACPI is not running.
930 * This is needed for the powernow-k8 driver, that works even without
931 * ACPI, but needs symbols from this driver
932 */
933
934static int __init
935acpi_processor_init (void)
936{
937 int result = 0;
938
939 ACPI_FUNCTION_TRACE("acpi_processor_init");
940
941 memset(&processors, 0, sizeof(processors));
942 memset(&errata, 0, sizeof(errata));
943
944 acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
945 if (!acpi_processor_dir)
946 return_VALUE(0);
947 acpi_processor_dir->owner = THIS_MODULE;
948
949 result = acpi_bus_register_driver(&acpi_processor_driver);
950 if (result < 0) {
951 remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
952 return_VALUE(0);
953 }
954
955 acpi_processor_install_hotplug_notify();
956
957 acpi_thermal_cpufreq_init();
958
959 acpi_processor_ppc_init();
960
961 return_VALUE(0);
962}
963
964
965static void __exit
966acpi_processor_exit (void)
967{
968 ACPI_FUNCTION_TRACE("acpi_processor_exit");
969
970 acpi_processor_ppc_exit();
971
972 acpi_thermal_cpufreq_exit();
973
974 acpi_processor_uninstall_hotplug_notify();
975
976 acpi_bus_unregister_driver(&acpi_processor_driver);
977
978 remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
979
980 return_VOID;
981}
982
983
984module_init(acpi_processor_init);
985module_exit(acpi_processor_exit);
986
987EXPORT_SYMBOL(acpi_processor_set_thermal_limit);
988
989MODULE_ALIAS("processor");
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
new file mode 100644
index 000000000000..05a17812d521
--- /dev/null
+++ b/drivers/acpi/processor_idle.c
@@ -0,0 +1,1017 @@
1/*
2 * processor_idle - idle state submodule to the ACPI processor driver
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de>
7 * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
8 * - Added processor hotplug support
9 *
10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or (at
15 * your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 *
26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 */
28
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/cpufreq.h>
33#include <linux/proc_fs.h>
34#include <linux/seq_file.h>
35#include <linux/acpi.h>
36#include <linux/dmi.h>
37#include <linux/moduleparam.h>
38
39#include <asm/io.h>
40#include <asm/uaccess.h>
41
42#include <acpi/acpi_bus.h>
43#include <acpi/processor.h>
44
45#define ACPI_PROCESSOR_COMPONENT 0x01000000
46#define ACPI_PROCESSOR_CLASS "processor"
47#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
48#define _COMPONENT ACPI_PROCESSOR_COMPONENT
49ACPI_MODULE_NAME ("acpi_processor")
50
51#define ACPI_PROCESSOR_FILE_POWER "power"
52
53#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
54#define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */
55#define C3_OVERHEAD 4 /* 1us (3.579 ticks per us) */
56
57static void (*pm_idle_save)(void);
58module_param(max_cstate, uint, 0644);
59
60static unsigned int nocst = 0;
61module_param(nocst, uint, 0000);
62
63/*
64 * bm_history -- bit-mask with a bit per jiffy of bus-master activity
65 * 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
66 * 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms
67 * 100 HZ: 0x0000000F: 4 jiffies = 40ms
68 * reduce history for more aggressive entry into C3
69 */
70static unsigned int bm_history = (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
71module_param(bm_history, uint, 0644);
72/* --------------------------------------------------------------------------
73 Power Management
74 -------------------------------------------------------------------------- */
75
76/*
77 * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
78 * For now disable this. Probably a bug somewhere else.
79 *
80 * To skip this limit, boot/load with a large max_cstate limit.
81 */
82static int no_c2c3(struct dmi_system_id *id)
83{
84 if (max_cstate > ACPI_PROCESSOR_MAX_POWER)
85 return 0;
86
87 printk(KERN_NOTICE PREFIX "%s detected - C2,C3 disabled."
88 " Override with \"processor.max_cstate=%d\"\n", id->ident,
89 ACPI_PROCESSOR_MAX_POWER + 1);
90
91 max_cstate = 1;
92
93 return 0;
94}
95
96
97
98
99static struct dmi_system_id __initdata processor_power_dmi_table[] = {
100 { no_c2c3, "IBM ThinkPad R40e", {
101 DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
102 DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }},
103 { no_c2c3, "Medion 41700", {
104 DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
105 DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }},
106 {},
107};
108
109
110static inline u32
111ticks_elapsed (
112 u32 t1,
113 u32 t2)
114{
115 if (t2 >= t1)
116 return (t2 - t1);
117 else if (!acpi_fadt.tmr_val_ext)
118 return (((0x00FFFFFF - t1) + t2) & 0x00FFFFFF);
119 else
120 return ((0xFFFFFFFF - t1) + t2);
121}
122
123
124static void
125acpi_processor_power_activate (
126 struct acpi_processor *pr,
127 struct acpi_processor_cx *new)
128{
129 struct acpi_processor_cx *old;
130
131 if (!pr || !new)
132 return;
133
134 old = pr->power.state;
135
136 if (old)
137 old->promotion.count = 0;
138 new->demotion.count = 0;
139
140 /* Cleanup from old state. */
141 if (old) {
142 switch (old->type) {
143 case ACPI_STATE_C3:
144 /* Disable bus master reload */
145 if (new->type != ACPI_STATE_C3)
146 acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK);
147 break;
148 }
149 }
150
151 /* Prepare to use new state. */
152 switch (new->type) {
153 case ACPI_STATE_C3:
154 /* Enable bus master reload */
155 if (old->type != ACPI_STATE_C3)
156 acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1, ACPI_MTX_DO_NOT_LOCK);
157 break;
158 }
159
160 pr->power.state = new;
161
162 return;
163}
164
165
166static void acpi_processor_idle (void)
167{
168 struct acpi_processor *pr = NULL;
169 struct acpi_processor_cx *cx = NULL;
170 struct acpi_processor_cx *next_state = NULL;
171 int sleep_ticks = 0;
172 u32 t1, t2 = 0;
173
174 pr = processors[_smp_processor_id()];
175 if (!pr)
176 return;
177
178 /*
179 * Interrupts must be disabled during bus mastering calculations and
180 * for C2/C3 transitions.
181 */
182 local_irq_disable();
183
184 /*
185 * Check whether we truly need to go idle, or should
186 * reschedule:
187 */
188 if (unlikely(need_resched())) {
189 local_irq_enable();
190 return;
191 }
192
193 cx = pr->power.state;
194 if (!cx)
195 goto easy_out;
196
197 /*
198 * Check BM Activity
199 * -----------------
200 * Check for bus mastering activity (if required), record, and check
201 * for demotion.
202 */
203 if (pr->flags.bm_check) {
204 u32 bm_status = 0;
205 unsigned long diff = jiffies - pr->power.bm_check_timestamp;
206
207 if (diff > 32)
208 diff = 32;
209
210 while (diff) {
211 /* if we didn't get called, assume there was busmaster activity */
212 diff--;
213 if (diff)
214 pr->power.bm_activity |= 0x1;
215 pr->power.bm_activity <<= 1;
216 }
217
218 acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS,
219 &bm_status, ACPI_MTX_DO_NOT_LOCK);
220 if (bm_status) {
221 pr->power.bm_activity++;
222 acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS,
223 1, ACPI_MTX_DO_NOT_LOCK);
224 }
225 /*
226 * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
227 * the true state of bus mastering activity; forcing us to
228 * manually check the BMIDEA bit of each IDE channel.
229 */
230 else if (errata.piix4.bmisx) {
231 if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
232 || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
233 pr->power.bm_activity++;
234 }
235
236 pr->power.bm_check_timestamp = jiffies;
237
238 /*
239 * Apply bus mastering demotion policy. Automatically demote
240 * to avoid a faulty transition. Note that the processor
241 * won't enter a low-power state during this call (to this
242 * funciton) but should upon the next.
243 *
244 * TBD: A better policy might be to fallback to the demotion
245 * state (use it for this quantum only) istead of
246 * demoting -- and rely on duration as our sole demotion
247 * qualification. This may, however, introduce DMA
248 * issues (e.g. floppy DMA transfer overrun/underrun).
249 */
250 if (pr->power.bm_activity & cx->demotion.threshold.bm) {
251 local_irq_enable();
252 next_state = cx->demotion.state;
253 goto end;
254 }
255 }
256
257 cx->usage++;
258
259 /*
260 * Sleep:
261 * ------
262 * Invoke the current Cx state to put the processor to sleep.
263 */
264 switch (cx->type) {
265
266 case ACPI_STATE_C1:
267 /*
268 * Invoke C1.
269 * Use the appropriate idle routine, the one that would
270 * be used without acpi C-states.
271 */
272 if (pm_idle_save)
273 pm_idle_save();
274 else
275 safe_halt();
276 /*
277 * TBD: Can't get time duration while in C1, as resumes
278 * go to an ISR rather than here. Need to instrument
279 * base interrupt handler.
280 */
281 sleep_ticks = 0xFFFFFFFF;
282 break;
283
284 case ACPI_STATE_C2:
285 /* Get start time (ticks) */
286 t1 = inl(acpi_fadt.xpm_tmr_blk.address);
287 /* Invoke C2 */
288 inb(cx->address);
289 /* Dummy op - must do something useless after P_LVL2 read */
290 t2 = inl(acpi_fadt.xpm_tmr_blk.address);
291 /* Get end time (ticks) */
292 t2 = inl(acpi_fadt.xpm_tmr_blk.address);
293 /* Re-enable interrupts */
294 local_irq_enable();
295 /* Compute time (ticks) that we were actually asleep */
296 sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
297 break;
298
299 case ACPI_STATE_C3:
300 /* Disable bus master arbitration */
301 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
302 /* Get start time (ticks) */
303 t1 = inl(acpi_fadt.xpm_tmr_blk.address);
304 /* Invoke C3 */
305 inb(cx->address);
306 /* Dummy op - must do something useless after P_LVL3 read */
307 t2 = inl(acpi_fadt.xpm_tmr_blk.address);
308 /* Get end time (ticks) */
309 t2 = inl(acpi_fadt.xpm_tmr_blk.address);
310 /* Enable bus master arbitration */
311 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK);
312 /* Re-enable interrupts */
313 local_irq_enable();
314 /* Compute time (ticks) that we were actually asleep */
315 sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
316 break;
317
318 default:
319 local_irq_enable();
320 return;
321 }
322
323 next_state = pr->power.state;
324
325 /*
326 * Promotion?
327 * ----------
328 * Track the number of longs (time asleep is greater than threshold)
329 * and promote when the count threshold is reached. Note that bus
330 * mastering activity may prevent promotions.
331 * Do not promote above max_cstate.
332 */
333 if (cx->promotion.state &&
334 ((cx->promotion.state - pr->power.states) <= max_cstate)) {
335 if (sleep_ticks > cx->promotion.threshold.ticks) {
336 cx->promotion.count++;
337 cx->demotion.count = 0;
338 if (cx->promotion.count >= cx->promotion.threshold.count) {
339 if (pr->flags.bm_check) {
340 if (!(pr->power.bm_activity & cx->promotion.threshold.bm)) {
341 next_state = cx->promotion.state;
342 goto end;
343 }
344 }
345 else {
346 next_state = cx->promotion.state;
347 goto end;
348 }
349 }
350 }
351 }
352
353 /*
354 * Demotion?
355 * ---------
356 * Track the number of shorts (time asleep is less than time threshold)
357 * and demote when the usage threshold is reached.
358 */
359 if (cx->demotion.state) {
360 if (sleep_ticks < cx->demotion.threshold.ticks) {
361 cx->demotion.count++;
362 cx->promotion.count = 0;
363 if (cx->demotion.count >= cx->demotion.threshold.count) {
364 next_state = cx->demotion.state;
365 goto end;
366 }
367 }
368 }
369
370end:
371 /*
372 * Demote if current state exceeds max_cstate
373 */
374 if ((pr->power.state - pr->power.states) > max_cstate) {
375 if (cx->demotion.state)
376 next_state = cx->demotion.state;
377 }
378
379 /*
380 * New Cx State?
381 * -------------
382 * If we're going to start using a new Cx state we must clean up
383 * from the previous and prepare to use the new.
384 */
385 if (next_state != pr->power.state)
386 acpi_processor_power_activate(pr, next_state);
387
388 return;
389
390 easy_out:
391 /* do C1 instead of busy loop */
392 if (pm_idle_save)
393 pm_idle_save();
394 else
395 safe_halt();
396 return;
397}
398
399
400static int
401acpi_processor_set_power_policy (
402 struct acpi_processor *pr)
403{
404 unsigned int i;
405 unsigned int state_is_set = 0;
406 struct acpi_processor_cx *lower = NULL;
407 struct acpi_processor_cx *higher = NULL;
408 struct acpi_processor_cx *cx;
409
410 ACPI_FUNCTION_TRACE("acpi_processor_set_power_policy");
411
412 if (!pr)
413 return_VALUE(-EINVAL);
414
415 /*
416 * This function sets the default Cx state policy (OS idle handler).
417 * Our scheme is to promote quickly to C2 but more conservatively
418 * to C3. We're favoring C2 for its characteristics of low latency
419 * (quick response), good power savings, and ability to allow bus
420 * mastering activity. Note that the Cx state policy is completely
421 * customizable and can be altered dynamically.
422 */
423
424 /* startup state */
425 for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
426 cx = &pr->power.states[i];
427 if (!cx->valid)
428 continue;
429
430 if (!state_is_set)
431 pr->power.state = cx;
432 state_is_set++;
433 break;
434 }
435
436 if (!state_is_set)
437 return_VALUE(-ENODEV);
438
439 /* demotion */
440 for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
441 cx = &pr->power.states[i];
442 if (!cx->valid)
443 continue;
444
445 if (lower) {
446 cx->demotion.state = lower;
447 cx->demotion.threshold.ticks = cx->latency_ticks;
448 cx->demotion.threshold.count = 1;
449 if (cx->type == ACPI_STATE_C3)
450 cx->demotion.threshold.bm = bm_history;
451 }
452
453 lower = cx;
454 }
455
456 /* promotion */
457 for (i = (ACPI_PROCESSOR_MAX_POWER - 1); i > 0; i--) {
458 cx = &pr->power.states[i];
459 if (!cx->valid)
460 continue;
461
462 if (higher) {
463 cx->promotion.state = higher;
464 cx->promotion.threshold.ticks = cx->latency_ticks;
465 if (cx->type >= ACPI_STATE_C2)
466 cx->promotion.threshold.count = 4;
467 else
468 cx->promotion.threshold.count = 10;
469 if (higher->type == ACPI_STATE_C3)
470 cx->promotion.threshold.bm = bm_history;
471 }
472
473 higher = cx;
474 }
475
476 return_VALUE(0);
477}
478
479
480static int acpi_processor_get_power_info_fadt (struct acpi_processor *pr)
481{
482 int i;
483
484 ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_fadt");
485
486 if (!pr)
487 return_VALUE(-EINVAL);
488
489 if (!pr->pblk)
490 return_VALUE(-ENODEV);
491
492 for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
493 memset(pr->power.states, 0, sizeof(struct acpi_processor_cx));
494
495 /* if info is obtained from pblk/fadt, type equals state */
496 pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
497 pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2;
498 pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3;
499
500 /* the C0 state only exists as a filler in our array,
501 * and all processors need to support C1 */
502 pr->power.states[ACPI_STATE_C0].valid = 1;
503 pr->power.states[ACPI_STATE_C1].valid = 1;
504
505 /* determine C2 and C3 address from pblk */
506 pr->power.states[ACPI_STATE_C2].address = pr->pblk + 4;
507 pr->power.states[ACPI_STATE_C3].address = pr->pblk + 5;
508
509 /* determine latencies from FADT */
510 pr->power.states[ACPI_STATE_C2].latency = acpi_fadt.plvl2_lat;
511 pr->power.states[ACPI_STATE_C3].latency = acpi_fadt.plvl3_lat;
512
513 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
514 "lvl2[0x%08x] lvl3[0x%08x]\n",
515 pr->power.states[ACPI_STATE_C2].address,
516 pr->power.states[ACPI_STATE_C3].address));
517
518 return_VALUE(0);
519}
520
521
522static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
523{
524 acpi_status status = 0;
525 acpi_integer count;
526 int i;
527 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
528 union acpi_object *cst;
529
530 ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_cst");
531
532 if (errata.smp)
533 return_VALUE(-ENODEV);
534
535 if (nocst)
536 return_VALUE(-ENODEV);
537
538 pr->power.count = 0;
539 for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
540 memset(pr->power.states, 0, sizeof(struct acpi_processor_cx));
541
542 status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
543 if (ACPI_FAILURE(status)) {
544 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No _CST, giving up\n"));
545 return_VALUE(-ENODEV);
546 }
547
548 cst = (union acpi_object *) buffer.pointer;
549
550 /* There must be at least 2 elements */
551 if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) {
552 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "not enough elements in _CST\n"));
553 status = -EFAULT;
554 goto end;
555 }
556
557 count = cst->package.elements[0].integer.value;
558
559 /* Validate number of power states. */
560 if (count < 1 || count != cst->package.count - 1) {
561 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "count given by _CST is not valid\n"));
562 status = -EFAULT;
563 goto end;
564 }
565
566 /* We support up to ACPI_PROCESSOR_MAX_POWER. */
567 if (count > ACPI_PROCESSOR_MAX_POWER) {
568 printk(KERN_WARNING "Limiting number of power states to max (%d)\n", ACPI_PROCESSOR_MAX_POWER);
569 printk(KERN_WARNING "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
570 count = ACPI_PROCESSOR_MAX_POWER;
571 }
572
573 /* Tell driver that at least _CST is supported. */
574 pr->flags.has_cst = 1;
575
576 for (i = 1; i <= count; i++) {
577 union acpi_object *element;
578 union acpi_object *obj;
579 struct acpi_power_register *reg;
580 struct acpi_processor_cx cx;
581
582 memset(&cx, 0, sizeof(cx));
583
584 element = (union acpi_object *) &(cst->package.elements[i]);
585 if (element->type != ACPI_TYPE_PACKAGE)
586 continue;
587
588 if (element->package.count != 4)
589 continue;
590
591 obj = (union acpi_object *) &(element->package.elements[0]);
592
593 if (obj->type != ACPI_TYPE_BUFFER)
594 continue;
595
596 reg = (struct acpi_power_register *) obj->buffer.pointer;
597
598 if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO &&
599 (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
600 continue;
601
602 cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ?
603 0 : reg->address;
604
605 /* There should be an easy way to extract an integer... */
606 obj = (union acpi_object *) &(element->package.elements[1]);
607 if (obj->type != ACPI_TYPE_INTEGER)
608 continue;
609
610 cx.type = obj->integer.value;
611
612 if ((cx.type != ACPI_STATE_C1) &&
613 (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
614 continue;
615
616 if ((cx.type < ACPI_STATE_C1) ||
617 (cx.type > ACPI_STATE_C3))
618 continue;
619
620 obj = (union acpi_object *) &(element->package.elements[2]);
621 if (obj->type != ACPI_TYPE_INTEGER)
622 continue;
623
624 cx.latency = obj->integer.value;
625
626 obj = (union acpi_object *) &(element->package.elements[3]);
627 if (obj->type != ACPI_TYPE_INTEGER)
628 continue;
629
630 cx.power = obj->integer.value;
631
632 (pr->power.count)++;
633 memcpy(&(pr->power.states[pr->power.count]), &cx, sizeof(cx));
634 }
635
636 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n", pr->power.count));
637
638 /* Validate number of power states discovered */
639 if (pr->power.count < 2)
640 status = -ENODEV;
641
642end:
643 acpi_os_free(buffer.pointer);
644
645 return_VALUE(status);
646}
647
648
649static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
650{
651 ACPI_FUNCTION_TRACE("acpi_processor_get_power_verify_c2");
652
653 if (!cx->address)
654 return_VOID;
655
656 /*
657 * C2 latency must be less than or equal to 100
658 * microseconds.
659 */
660 else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) {
661 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
662 "latency too large [%d]\n",
663 cx->latency));
664 return_VOID;
665 }
666
667 /* We're (currently) only supporting C2 on UP */
668 else if (errata.smp) {
669 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
670 "C2 not supported in SMP mode\n"));
671 return_VOID;
672 }
673
674 /*
675 * Otherwise we've met all of our C2 requirements.
676 * Normalize the C2 latency to expidite policy
677 */
678 cx->valid = 1;
679 cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
680
681 return_VOID;
682}
683
684
685static void acpi_processor_power_verify_c3(
686 struct acpi_processor *pr,
687 struct acpi_processor_cx *cx)
688{
689 ACPI_FUNCTION_TRACE("acpi_processor_get_power_verify_c3");
690
691 if (!cx->address)
692 return_VOID;
693
694 /*
695 * C3 latency must be less than or equal to 1000
696 * microseconds.
697 */
698 else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) {
699 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
700 "latency too large [%d]\n",
701 cx->latency));
702 return_VOID;
703 }
704
705 /* bus mastering control is necessary */
706 else if (!pr->flags.bm_control) {
707 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
708 "C3 support requires bus mastering control\n"));
709 return_VOID;
710 }
711
712 /* We're (currently) only supporting C2 on UP */
713 else if (errata.smp) {
714 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
715 "C3 not supported in SMP mode\n"));
716 return_VOID;
717 }
718
719 /*
720 * PIIX4 Erratum #18: We don't support C3 when Type-F (fast)
721 * DMA transfers are used by any ISA device to avoid livelock.
722 * Note that we could disable Type-F DMA (as recommended by
723 * the erratum), but this is known to disrupt certain ISA
724 * devices thus we take the conservative approach.
725 */
726 else if (errata.piix4.fdma) {
727 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
728 "C3 not supported on PIIX4 with Type-F DMA\n"));
729 return_VOID;
730 }
731
732 /*
733 * Otherwise we've met all of our C3 requirements.
734 * Normalize the C3 latency to expidite policy. Enable
735 * checking of bus mastering status (bm_check) so we can
736 * use this in our C3 policy
737 */
738 cx->valid = 1;
739 cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
740 pr->flags.bm_check = 1;
741
742 return_VOID;
743}
744
745
746static int acpi_processor_power_verify(struct acpi_processor *pr)
747{
748 unsigned int i;
749 unsigned int working = 0;
750
751 for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
752 struct acpi_processor_cx *cx = &pr->power.states[i];
753
754 switch (cx->type) {
755 case ACPI_STATE_C1:
756 cx->valid = 1;
757 break;
758
759 case ACPI_STATE_C2:
760 acpi_processor_power_verify_c2(cx);
761 break;
762
763 case ACPI_STATE_C3:
764 acpi_processor_power_verify_c3(pr, cx);
765 break;
766 }
767
768 if (cx->valid)
769 working++;
770 }
771
772 return (working);
773}
774
775static int acpi_processor_get_power_info (
776 struct acpi_processor *pr)
777{
778 unsigned int i;
779 int result;
780
781 ACPI_FUNCTION_TRACE("acpi_processor_get_power_info");
782
783 /* NOTE: the idle thread may not be running while calling
784 * this function */
785
786 result = acpi_processor_get_power_info_cst(pr);
787 if ((result) || (acpi_processor_power_verify(pr) < 2)) {
788 result = acpi_processor_get_power_info_fadt(pr);
789 if (result)
790 return_VALUE(result);
791
792 if (acpi_processor_power_verify(pr) < 2)
793 return_VALUE(-ENODEV);
794 }
795
796 /*
797 * Set Default Policy
798 * ------------------
799 * Now that we know which states are supported, set the default
800 * policy. Note that this policy can be changed dynamically
801 * (e.g. encourage deeper sleeps to conserve battery life when
802 * not on AC).
803 */
804 result = acpi_processor_set_power_policy(pr);
805 if (result)
806 return_VALUE(result);
807
808 /*
809 * if one state of type C2 or C3 is available, mark this
810 * CPU as being "idle manageable"
811 */
812 for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
813 if (pr->power.states[i].valid)
814 pr->power.count = i;
815 if ((pr->power.states[i].valid) &&
816 (pr->power.states[i].type >= ACPI_STATE_C2))
817 pr->flags.power = 1;
818 }
819
820 return_VALUE(0);
821}
822
823int acpi_processor_cst_has_changed (struct acpi_processor *pr)
824{
825 int result = 0;
826
827 ACPI_FUNCTION_TRACE("acpi_processor_cst_has_changed");
828
829 if (!pr)
830 return_VALUE(-EINVAL);
831
832 if (errata.smp || nocst) {
833 return_VALUE(-ENODEV);
834 }
835
836 if (!pr->flags.power_setup_done)
837 return_VALUE(-ENODEV);
838
839 /* Fall back to the default idle loop */
840 pm_idle = pm_idle_save;
841 synchronize_kernel();
842
843 pr->flags.power = 0;
844 result = acpi_processor_get_power_info(pr);
845 if ((pr->flags.power == 1) && (pr->flags.power_setup_done))
846 pm_idle = acpi_processor_idle;
847
848 return_VALUE(result);
849}
850
851/* proc interface */
852
853static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
854{
855 struct acpi_processor *pr = (struct acpi_processor *)seq->private;
856 unsigned int i;
857
858 ACPI_FUNCTION_TRACE("acpi_processor_power_seq_show");
859
860 if (!pr)
861 goto end;
862
863 seq_printf(seq, "active state: C%zd\n"
864 "max_cstate: C%d\n"
865 "bus master activity: %08x\n",
866 pr->power.state ? pr->power.state - pr->power.states : 0,
867 max_cstate,
868 (unsigned)pr->power.bm_activity);
869
870 seq_puts(seq, "states:\n");
871
872 for (i = 1; i <= pr->power.count; i++) {
873 seq_printf(seq, " %cC%d: ",
874 (&pr->power.states[i] == pr->power.state?'*':' '), i);
875
876 if (!pr->power.states[i].valid) {
877 seq_puts(seq, "<not supported>\n");
878 continue;
879 }
880
881 switch (pr->power.states[i].type) {
882 case ACPI_STATE_C1:
883 seq_printf(seq, "type[C1] ");
884 break;
885 case ACPI_STATE_C2:
886 seq_printf(seq, "type[C2] ");
887 break;
888 case ACPI_STATE_C3:
889 seq_printf(seq, "type[C3] ");
890 break;
891 default:
892 seq_printf(seq, "type[--] ");
893 break;
894 }
895
896 if (pr->power.states[i].promotion.state)
897 seq_printf(seq, "promotion[C%zd] ",
898 (pr->power.states[i].promotion.state -
899 pr->power.states));
900 else
901 seq_puts(seq, "promotion[--] ");
902
903 if (pr->power.states[i].demotion.state)
904 seq_printf(seq, "demotion[C%zd] ",
905 (pr->power.states[i].demotion.state -
906 pr->power.states));
907 else
908 seq_puts(seq, "demotion[--] ");
909
910 seq_printf(seq, "latency[%03d] usage[%08d]\n",
911 pr->power.states[i].latency,
912 pr->power.states[i].usage);
913 }
914
915end:
916 return_VALUE(0);
917}
918
919static int acpi_processor_power_open_fs(struct inode *inode, struct file *file)
920{
921 return single_open(file, acpi_processor_power_seq_show,
922 PDE(inode)->data);
923}
924
925static struct file_operations acpi_processor_power_fops = {
926 .open = acpi_processor_power_open_fs,
927 .read = seq_read,
928 .llseek = seq_lseek,
929 .release = single_release,
930};
931
932
933int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device)
934{
935 acpi_status status = 0;
936 static int first_run = 0;
937 struct proc_dir_entry *entry = NULL;
938 unsigned int i;
939
940 ACPI_FUNCTION_TRACE("acpi_processor_power_init");
941
942 if (!first_run) {
943 dmi_check_system(processor_power_dmi_table);
944 if (max_cstate < ACPI_C_STATES_MAX)
945 printk(KERN_NOTICE "ACPI: processor limited to max C-state %d\n", max_cstate);
946 first_run++;
947 }
948
949 if (!errata.smp && (pr->id == 0) && acpi_fadt.cst_cnt && !nocst) {
950 status = acpi_os_write_port(acpi_fadt.smi_cmd, acpi_fadt.cst_cnt, 8);
951 if (ACPI_FAILURE(status)) {
952 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
953 "Notifying BIOS of _CST ability failed\n"));
954 }
955 }
956
957 acpi_processor_get_power_info(pr);
958
959 /*
960 * Install the idle handler if processor power management is supported.
961 * Note that we use previously set idle handler will be used on
962 * platforms that only support C1.
963 */
964 if ((pr->flags.power) && (!boot_option_idle_override)) {
965 printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id);
966 for (i = 1; i <= pr->power.count; i++)
967 if (pr->power.states[i].valid)
968 printk(" C%d[C%d]", i, pr->power.states[i].type);
969 printk(")\n");
970
971 if (pr->id == 0) {
972 pm_idle_save = pm_idle;
973 pm_idle = acpi_processor_idle;
974 }
975 }
976
977 /* 'power' [R] */
978 entry = create_proc_entry(ACPI_PROCESSOR_FILE_POWER,
979 S_IRUGO, acpi_device_dir(device));
980 if (!entry)
981 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
982 "Unable to create '%s' fs entry\n",
983 ACPI_PROCESSOR_FILE_POWER));
984 else {
985 entry->proc_fops = &acpi_processor_power_fops;
986 entry->data = acpi_driver_data(device);
987 entry->owner = THIS_MODULE;
988 }
989
990 pr->flags.power_setup_done = 1;
991
992 return_VALUE(0);
993}
994
995int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *device)
996{
997 ACPI_FUNCTION_TRACE("acpi_processor_power_exit");
998
999 pr->flags.power_setup_done = 0;
1000
1001 if (acpi_device_dir(device))
1002 remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,acpi_device_dir(device));
1003
1004 /* Unregister the idle handler when processor #0 is removed. */
1005 if (pr->id == 0) {
1006 pm_idle = pm_idle_save;
1007
1008 /*
1009 * We are about to unload the current idle thread pm callback
1010 * (pm_idle), Wait for all processors to update cached/local
1011 * copies of pm_idle before proceeding.
1012 */
1013 cpu_idle_wait();
1014 }
1015
1016 return_VALUE(0);
1017}
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
new file mode 100644
index 000000000000..a9a1a8fe3199
--- /dev/null
+++ b/drivers/acpi/processor_perflib.c
@@ -0,0 +1,666 @@
1/*
2 * processor_perflib.c - ACPI Processor P-States Library ($Revision: 71 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de>
7 * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
8 * - Added processor hotplug support
9 *
10 *
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 (at
16 * your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 *
27 */
28
29
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/cpufreq.h>
34
35#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
36#include <linux/proc_fs.h>
37#include <linux/seq_file.h>
38
39#include <asm/uaccess.h>
40#endif
41
42#include <acpi/acpi_bus.h>
43#include <acpi/processor.h>
44
45
46#define ACPI_PROCESSOR_COMPONENT 0x01000000
47#define ACPI_PROCESSOR_CLASS "processor"
48#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
49#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
50#define _COMPONENT ACPI_PROCESSOR_COMPONENT
51ACPI_MODULE_NAME ("acpi_processor")
52
53
54static DECLARE_MUTEX(performance_sem);
55
56/*
57 * _PPC support is implemented as a CPUfreq policy notifier:
58 * This means each time a CPUfreq driver registered also with
59 * the ACPI core is asked to change the speed policy, the maximum
60 * value is adjusted so that it is within the platform limit.
61 *
62 * Also, when a new platform limit value is detected, the CPUfreq
63 * policy is adjusted accordingly.
64 */
65
66#define PPC_REGISTERED 1
67#define PPC_IN_USE 2
68
69static int acpi_processor_ppc_status = 0;
70
71static int acpi_processor_ppc_notifier(struct notifier_block *nb,
72 unsigned long event,
73 void *data)
74{
75 struct cpufreq_policy *policy = data;
76 struct acpi_processor *pr;
77 unsigned int ppc = 0;
78
79 down(&performance_sem);
80
81 if (event != CPUFREQ_INCOMPATIBLE)
82 goto out;
83
84 pr = processors[policy->cpu];
85 if (!pr || !pr->performance)
86 goto out;
87
88 ppc = (unsigned int) pr->performance_platform_limit;
89 if (!ppc)
90 goto out;
91
92 if (ppc > pr->performance->state_count)
93 goto out;
94
95 cpufreq_verify_within_limits(policy, 0,
96 pr->performance->states[ppc].core_frequency * 1000);
97
98 out:
99 up(&performance_sem);
100
101 return 0;
102}
103
104
105static struct notifier_block acpi_ppc_notifier_block = {
106 .notifier_call = acpi_processor_ppc_notifier,
107};
108
109
110static int
111acpi_processor_get_platform_limit (
112 struct acpi_processor* pr)
113{
114 acpi_status status = 0;
115 unsigned long ppc = 0;
116
117 ACPI_FUNCTION_TRACE("acpi_processor_get_platform_limit");
118
119 if (!pr)
120 return_VALUE(-EINVAL);
121
122 /*
123 * _PPC indicates the maximum state currently supported by the platform
124 * (e.g. 0 = states 0..n; 1 = states 1..n; etc.
125 */
126 status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
127
128 if (status != AE_NOT_FOUND)
129 acpi_processor_ppc_status |= PPC_IN_USE;
130
131 if(ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
132 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n"));
133 return_VALUE(-ENODEV);
134 }
135
136 pr->performance_platform_limit = (int) ppc;
137
138 return_VALUE(0);
139}
140
141
142int acpi_processor_ppc_has_changed(
143 struct acpi_processor *pr)
144{
145 int ret = acpi_processor_get_platform_limit(pr);
146 if (ret < 0)
147 return (ret);
148 else
149 return cpufreq_update_policy(pr->id);
150}
151
152
153void acpi_processor_ppc_init(void) {
154 if (!cpufreq_register_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
155 acpi_processor_ppc_status |= PPC_REGISTERED;
156 else
157 printk(KERN_DEBUG "Warning: Processor Platform Limit not supported.\n");
158}
159
160
161void acpi_processor_ppc_exit(void) {
162 if (acpi_processor_ppc_status & PPC_REGISTERED)
163 cpufreq_unregister_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER);
164
165 acpi_processor_ppc_status &= ~PPC_REGISTERED;
166}
167
168/*
169 * when registering a cpufreq driver with this ACPI processor driver, the
170 * _PCT and _PSS structures are read out and written into struct
171 * acpi_processor_performance.
172 */
173static int acpi_processor_set_pdc (struct acpi_processor *pr)
174{
175 acpi_status status = AE_OK;
176 u32 arg0_buf[3];
177 union acpi_object arg0 = {ACPI_TYPE_BUFFER};
178 struct acpi_object_list no_object = {1, &arg0};
179 struct acpi_object_list *pdc;
180
181 ACPI_FUNCTION_TRACE("acpi_processor_set_pdc");
182
183 arg0.buffer.length = 12;
184 arg0.buffer.pointer = (u8 *) arg0_buf;
185 arg0_buf[0] = ACPI_PDC_REVISION_ID;
186 arg0_buf[1] = 0;
187 arg0_buf[2] = 0;
188
189 pdc = (pr->performance->pdc) ? pr->performance->pdc : &no_object;
190
191 status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL);
192
193 if ((ACPI_FAILURE(status)) && (pr->performance->pdc))
194 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PDC, using legacy perf. control...\n"));
195
196 return_VALUE(status);
197}
198
199
200static int
201acpi_processor_get_performance_control (
202 struct acpi_processor *pr)
203{
204 int result = 0;
205 acpi_status status = 0;
206 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
207 union acpi_object *pct = NULL;
208 union acpi_object obj = {0};
209
210 ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control");
211
212 status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
213 if(ACPI_FAILURE(status)) {
214 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n"));
215 return_VALUE(-ENODEV);
216 }
217
218 pct = (union acpi_object *) buffer.pointer;
219 if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
220 || (pct->package.count != 2)) {
221 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n"));
222 result = -EFAULT;
223 goto end;
224 }
225
226 /*
227 * control_register
228 */
229
230 obj = pct->package.elements[0];
231
232 if ((obj.type != ACPI_TYPE_BUFFER)
233 || (obj.buffer.length < sizeof(struct acpi_pct_register))
234 || (obj.buffer.pointer == NULL)) {
235 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
236 "Invalid _PCT data (control_register)\n"));
237 result = -EFAULT;
238 goto end;
239 }
240 memcpy(&pr->performance->control_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
241
242
243 /*
244 * status_register
245 */
246
247 obj = pct->package.elements[1];
248
249 if ((obj.type != ACPI_TYPE_BUFFER)
250 || (obj.buffer.length < sizeof(struct acpi_pct_register))
251 || (obj.buffer.pointer == NULL)) {
252 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
253 "Invalid _PCT data (status_register)\n"));
254 result = -EFAULT;
255 goto end;
256 }
257
258 memcpy(&pr->performance->status_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
259
260end:
261 acpi_os_free(buffer.pointer);
262
263 return_VALUE(result);
264}
265
266
267static int
268acpi_processor_get_performance_states (
269 struct acpi_processor *pr)
270{
271 int result = 0;
272 acpi_status status = AE_OK;
273 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
274 struct acpi_buffer format = {sizeof("NNNNNN"), "NNNNNN"};
275 struct acpi_buffer state = {0, NULL};
276 union acpi_object *pss = NULL;
277 int i;
278
279 ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states");
280
281 status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
282 if(ACPI_FAILURE(status)) {
283 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n"));
284 return_VALUE(-ENODEV);
285 }
286
287 pss = (union acpi_object *) buffer.pointer;
288 if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
289 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
290 result = -EFAULT;
291 goto end;
292 }
293
294 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
295 pss->package.count));
296
297 pr->performance->state_count = pss->package.count;
298 pr->performance->states = kmalloc(sizeof(struct acpi_processor_px) * pss->package.count, GFP_KERNEL);
299 if (!pr->performance->states) {
300 result = -ENOMEM;
301 goto end;
302 }
303
304 for (i = 0; i < pr->performance->state_count; i++) {
305
306 struct acpi_processor_px *px = &(pr->performance->states[i]);
307
308 state.length = sizeof(struct acpi_processor_px);
309 state.pointer = px;
310
311 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
312
313 status = acpi_extract_package(&(pss->package.elements[i]),
314 &format, &state);
315 if (ACPI_FAILURE(status)) {
316 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
317 result = -EFAULT;
318 kfree(pr->performance->states);
319 goto end;
320 }
321
322 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
323 "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
324 i,
325 (u32) px->core_frequency,
326 (u32) px->power,
327 (u32) px->transition_latency,
328 (u32) px->bus_master_latency,
329 (u32) px->control,
330 (u32) px->status));
331
332 if (!px->core_frequency) {
333 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data: freq is zero\n"));
334 result = -EFAULT;
335 kfree(pr->performance->states);
336 goto end;
337 }
338 }
339
340end:
341 acpi_os_free(buffer.pointer);
342
343 return_VALUE(result);
344}
345
346
347static int
348acpi_processor_get_performance_info (
349 struct acpi_processor *pr)
350{
351 int result = 0;
352 acpi_status status = AE_OK;
353 acpi_handle handle = NULL;
354
355 ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info");
356
357 if (!pr || !pr->performance || !pr->handle)
358 return_VALUE(-EINVAL);
359
360 acpi_processor_set_pdc(pr);
361
362 status = acpi_get_handle(pr->handle, "_PCT", &handle);
363 if (ACPI_FAILURE(status)) {
364 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
365 "ACPI-based processor performance control unavailable\n"));
366 return_VALUE(-ENODEV);
367 }
368
369 result = acpi_processor_get_performance_control(pr);
370 if (result)
371 return_VALUE(result);
372
373 result = acpi_processor_get_performance_states(pr);
374 if (result)
375 return_VALUE(result);
376
377 result = acpi_processor_get_platform_limit(pr);
378 if (result)
379 return_VALUE(result);
380
381 return_VALUE(0);
382}
383
384
385int acpi_processor_notify_smm(struct module *calling_module) {
386 acpi_status status;
387 static int is_done = 0;
388
389 ACPI_FUNCTION_TRACE("acpi_processor_notify_smm");
390
391 if (!(acpi_processor_ppc_status & PPC_REGISTERED))
392 return_VALUE(-EBUSY);
393
394 if (!try_module_get(calling_module))
395 return_VALUE(-EINVAL);
396
397 /* is_done is set to negative if an error occured,
398 * and to postitive if _no_ error occured, but SMM
399 * was already notified. This avoids double notification
400 * which might lead to unexpected results...
401 */
402 if (is_done > 0) {
403 module_put(calling_module);
404 return_VALUE(0);
405 }
406 else if (is_done < 0) {
407 module_put(calling_module);
408 return_VALUE(is_done);
409 }
410
411 is_done = -EIO;
412
413 /* Can't write pstate_cnt to smi_cmd if either value is zero */
414 if ((!acpi_fadt.smi_cmd) ||
415 (!acpi_fadt.pstate_cnt)) {
416 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
417 "No SMI port or pstate_cnt\n"));
418 module_put(calling_module);
419 return_VALUE(0);
420 }
421
422 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
423
424 /* FADT v1 doesn't support pstate_cnt, many BIOS vendors use
425 * it anyway, so we need to support it... */
426 if (acpi_fadt_is_v1) {
427 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using v1.0 FADT reserved value for pstate_cnt\n"));
428 }
429
430 status = acpi_os_write_port (acpi_fadt.smi_cmd,
431 (u32) acpi_fadt.pstate_cnt, 8);
432 if (ACPI_FAILURE (status)) {
433 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
434 "Failed to write pstate_cnt [0x%x] to "
435 "smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
436 module_put(calling_module);
437 return_VALUE(status);
438 }
439
440 /* Success. If there's no _PPC, we need to fear nothing, so
441 * we can allow the cpufreq driver to be rmmod'ed. */
442 is_done = 1;
443
444 if (!(acpi_processor_ppc_status & PPC_IN_USE))
445 module_put(calling_module);
446
447 return_VALUE(0);
448}
449EXPORT_SYMBOL(acpi_processor_notify_smm);
450
451
452#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
453/* /proc/acpi/processor/../performance interface (DEPRECATED) */
454
455static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
456static struct file_operations acpi_processor_perf_fops = {
457 .open = acpi_processor_perf_open_fs,
458 .read = seq_read,
459 .llseek = seq_lseek,
460 .release = single_release,
461};
462
463static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
464{
465 struct acpi_processor *pr = (struct acpi_processor *)seq->private;
466 int i;
467
468 ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show");
469
470 if (!pr)
471 goto end;
472
473 if (!pr->performance) {
474 seq_puts(seq, "<not supported>\n");
475 goto end;
476 }
477
478 seq_printf(seq, "state count: %d\n"
479 "active state: P%d\n",
480 pr->performance->state_count,
481 pr->performance->state);
482
483 seq_puts(seq, "states:\n");
484 for (i = 0; i < pr->performance->state_count; i++)
485 seq_printf(seq, " %cP%d: %d MHz, %d mW, %d uS\n",
486 (i == pr->performance->state?'*':' '), i,
487 (u32) pr->performance->states[i].core_frequency,
488 (u32) pr->performance->states[i].power,
489 (u32) pr->performance->states[i].transition_latency);
490
491end:
492 return_VALUE(0);
493}
494
495static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
496{
497 return single_open(file, acpi_processor_perf_seq_show,
498 PDE(inode)->data);
499}
500
501static ssize_t
502acpi_processor_write_performance (
503 struct file *file,
504 const char __user *buffer,
505 size_t count,
506 loff_t *data)
507{
508 int result = 0;
509 struct seq_file *m = (struct seq_file *) file->private_data;
510 struct acpi_processor *pr = (struct acpi_processor *) m->private;
511 struct acpi_processor_performance *perf;
512 char state_string[12] = {'\0'};
513 unsigned int new_state = 0;
514 struct cpufreq_policy policy;
515
516 ACPI_FUNCTION_TRACE("acpi_processor_write_performance");
517
518 if (!pr || (count > sizeof(state_string) - 1))
519 return_VALUE(-EINVAL);
520
521 perf = pr->performance;
522 if (!perf)
523 return_VALUE(-EINVAL);
524
525 if (copy_from_user(state_string, buffer, count))
526 return_VALUE(-EFAULT);
527
528 state_string[count] = '\0';
529 new_state = simple_strtoul(state_string, NULL, 0);
530
531 if (new_state >= perf->state_count)
532 return_VALUE(-EINVAL);
533
534 cpufreq_get_policy(&policy, pr->id);
535
536 policy.cpu = pr->id;
537 policy.min = perf->states[new_state].core_frequency * 1000;
538 policy.max = perf->states[new_state].core_frequency * 1000;
539
540 result = cpufreq_set_policy(&policy);
541 if (result)
542 return_VALUE(result);
543
544 return_VALUE(count);
545}
546
547static void
548acpi_cpufreq_add_file (
549 struct acpi_processor *pr)
550{
551 struct proc_dir_entry *entry = NULL;
552 struct acpi_device *device = NULL;
553
554 ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
555
556 if (acpi_bus_get_device(pr->handle, &device))
557 return_VOID;
558
559 /* add file 'performance' [R/W] */
560 entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
561 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
562 if (!entry)
563 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
564 "Unable to create '%s' fs entry\n",
565 ACPI_PROCESSOR_FILE_PERFORMANCE));
566 else {
567 entry->proc_fops = &acpi_processor_perf_fops;
568 entry->proc_fops->write = acpi_processor_write_performance;
569 entry->data = acpi_driver_data(device);
570 entry->owner = THIS_MODULE;
571 }
572 return_VOID;
573}
574
575static void
576acpi_cpufreq_remove_file (
577 struct acpi_processor *pr)
578{
579 struct acpi_device *device = NULL;
580
581 ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
582
583 if (acpi_bus_get_device(pr->handle, &device))
584 return_VOID;
585
586 /* remove file 'performance' */
587 remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
588 acpi_device_dir(device));
589
590 return_VOID;
591}
592
593#else
594static void acpi_cpufreq_add_file (struct acpi_processor *pr) { return; }
595static void acpi_cpufreq_remove_file (struct acpi_processor *pr) { return; }
596#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
597
598
599int
600acpi_processor_register_performance (
601 struct acpi_processor_performance * performance,
602 unsigned int cpu)
603{
604 struct acpi_processor *pr;
605
606 ACPI_FUNCTION_TRACE("acpi_processor_register_performance");
607
608 if (!(acpi_processor_ppc_status & PPC_REGISTERED))
609 return_VALUE(-EINVAL);
610
611 down(&performance_sem);
612
613 pr = processors[cpu];
614 if (!pr) {
615 up(&performance_sem);
616 return_VALUE(-ENODEV);
617 }
618
619 if (pr->performance) {
620 up(&performance_sem);
621 return_VALUE(-EBUSY);
622 }
623
624 pr->performance = performance;
625
626 if (acpi_processor_get_performance_info(pr)) {
627 pr->performance = NULL;
628 up(&performance_sem);
629 return_VALUE(-EIO);
630 }
631
632 acpi_cpufreq_add_file(pr);
633
634 up(&performance_sem);
635 return_VALUE(0);
636}
637EXPORT_SYMBOL(acpi_processor_register_performance);
638
639
640void
641acpi_processor_unregister_performance (
642 struct acpi_processor_performance * performance,
643 unsigned int cpu)
644{
645 struct acpi_processor *pr;
646
647 ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance");
648
649 down(&performance_sem);
650
651 pr = processors[cpu];
652 if (!pr) {
653 up(&performance_sem);
654 return_VOID;
655 }
656
657 kfree(pr->performance->states);
658 pr->performance = NULL;
659
660 acpi_cpufreq_remove_file(pr);
661
662 up(&performance_sem);
663
664 return_VOID;
665}
666EXPORT_SYMBOL(acpi_processor_unregister_performance);
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
new file mode 100644
index 000000000000..12bd980a12e9
--- /dev/null
+++ b/drivers/acpi/processor_thermal.c
@@ -0,0 +1,406 @@
1/*
2 * processor_thermal.c - Passive cooling submodule of the ACPI processor driver
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de>
7 * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
8 * - Added processor hotplug support
9 *
10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or (at
15 * your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 *
26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 */
28
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/cpufreq.h>
33#include <linux/proc_fs.h>
34#include <linux/seq_file.h>
35
36#include <asm/uaccess.h>
37
38#include <acpi/acpi_bus.h>
39#include <acpi/processor.h>
40#include <acpi/acpi_drivers.h>
41
42#define ACPI_PROCESSOR_COMPONENT 0x01000000
43#define ACPI_PROCESSOR_CLASS "processor"
44#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
45#define _COMPONENT ACPI_PROCESSOR_COMPONENT
46ACPI_MODULE_NAME ("acpi_processor")
47
48
49/* --------------------------------------------------------------------------
50 Limit Interface
51 -------------------------------------------------------------------------- */
52
53static int
54acpi_processor_apply_limit (
55 struct acpi_processor* pr)
56{
57 int result = 0;
58 u16 px = 0;
59 u16 tx = 0;
60
61 ACPI_FUNCTION_TRACE("acpi_processor_apply_limit");
62
63 if (!pr)
64 return_VALUE(-EINVAL);
65
66 if (!pr->flags.limit)
67 return_VALUE(-ENODEV);
68
69 if (pr->flags.throttling) {
70 if (pr->limit.user.tx > tx)
71 tx = pr->limit.user.tx;
72 if (pr->limit.thermal.tx > tx)
73 tx = pr->limit.thermal.tx;
74
75 result = acpi_processor_set_throttling(pr, tx);
76 if (result)
77 goto end;
78 }
79
80 pr->limit.state.px = px;
81 pr->limit.state.tx = tx;
82
83 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d] limit set to (P%d:T%d)\n",
84 pr->id,
85 pr->limit.state.px,
86 pr->limit.state.tx));
87
88end:
89 if (result)
90 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set limit\n"));
91
92 return_VALUE(result);
93}
94
95
96#ifdef CONFIG_CPU_FREQ
97
98/* If a passive cooling situation is detected, primarily CPUfreq is used, as it
99 * offers (in most cases) voltage scaling in addition to frequency scaling, and
100 * thus a cubic (instead of linear) reduction of energy. Also, we allow for
101 * _any_ cpufreq driver and not only the acpi-cpufreq driver.
102 */
103
104static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS];
105static unsigned int acpi_thermal_cpufreq_is_init = 0;
106
107
108static int cpu_has_cpufreq(unsigned int cpu)
109{
110 struct cpufreq_policy policy;
111 if (!acpi_thermal_cpufreq_is_init)
112 return -ENODEV;
113 if (!cpufreq_get_policy(&policy, cpu))
114 return -ENODEV;
115 return 0;
116}
117
118
119static int acpi_thermal_cpufreq_increase(unsigned int cpu)
120{
121 if (!cpu_has_cpufreq(cpu))
122 return -ENODEV;
123
124 if (cpufreq_thermal_reduction_pctg[cpu] < 60) {
125 cpufreq_thermal_reduction_pctg[cpu] += 20;
126 cpufreq_update_policy(cpu);
127 return 0;
128 }
129
130 return -ERANGE;
131}
132
133
134static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
135{
136 if (!cpu_has_cpufreq(cpu))
137 return -ENODEV;
138
139 if (cpufreq_thermal_reduction_pctg[cpu] >= 20) {
140 cpufreq_thermal_reduction_pctg[cpu] -= 20;
141 cpufreq_update_policy(cpu);
142 return 0;
143 }
144
145 return -ERANGE;
146}
147
148
149static int acpi_thermal_cpufreq_notifier(
150 struct notifier_block *nb,
151 unsigned long event,
152 void *data)
153{
154 struct cpufreq_policy *policy = data;
155 unsigned long max_freq = 0;
156
157 if (event != CPUFREQ_ADJUST)
158 goto out;
159
160 max_freq = (policy->cpuinfo.max_freq * (100 - cpufreq_thermal_reduction_pctg[policy->cpu])) / 100;
161
162 cpufreq_verify_within_limits(policy, 0, max_freq);
163
164 out:
165 return 0;
166}
167
168
169static struct notifier_block acpi_thermal_cpufreq_notifier_block = {
170 .notifier_call = acpi_thermal_cpufreq_notifier,
171};
172
173
174void acpi_thermal_cpufreq_init(void) {
175 int i;
176
177 for (i=0; i<NR_CPUS; i++)
178 cpufreq_thermal_reduction_pctg[i] = 0;
179
180 i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, CPUFREQ_POLICY_NOTIFIER);
181 if (!i)
182 acpi_thermal_cpufreq_is_init = 1;
183}
184
185void acpi_thermal_cpufreq_exit(void) {
186 if (acpi_thermal_cpufreq_is_init)
187 cpufreq_unregister_notifier(&acpi_thermal_cpufreq_notifier_block, CPUFREQ_POLICY_NOTIFIER);
188
189 acpi_thermal_cpufreq_is_init = 0;
190}
191
192#else /* ! CONFIG_CPU_FREQ */
193
194static int acpi_thermal_cpufreq_increase(unsigned int cpu) { return -ENODEV; }
195static int acpi_thermal_cpufreq_decrease(unsigned int cpu) { return -ENODEV; }
196
197
198#endif
199
200
201int
202acpi_processor_set_thermal_limit (
203 acpi_handle handle,
204 int type)
205{
206 int result = 0;
207 struct acpi_processor *pr = NULL;
208 struct acpi_device *device = NULL;
209 int tx = 0;
210
211 ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit");
212
213 if ((type < ACPI_PROCESSOR_LIMIT_NONE)
214 || (type > ACPI_PROCESSOR_LIMIT_DECREMENT))
215 return_VALUE(-EINVAL);
216
217 result = acpi_bus_get_device(handle, &device);
218 if (result)
219 return_VALUE(result);
220
221 pr = (struct acpi_processor *) acpi_driver_data(device);
222 if (!pr)
223 return_VALUE(-ENODEV);
224
225 /* Thermal limits are always relative to the current Px/Tx state. */
226 if (pr->flags.throttling)
227 pr->limit.thermal.tx = pr->throttling.state;
228
229 /*
230 * Our default policy is to only use throttling at the lowest
231 * performance state.
232 */
233
234 tx = pr->limit.thermal.tx;
235
236 switch (type) {
237
238 case ACPI_PROCESSOR_LIMIT_NONE:
239 do {
240 result = acpi_thermal_cpufreq_decrease(pr->id);
241 } while (!result);
242 tx = 0;
243 break;
244
245 case ACPI_PROCESSOR_LIMIT_INCREMENT:
246 /* if going up: P-states first, T-states later */
247
248 result = acpi_thermal_cpufreq_increase(pr->id);
249 if (!result)
250 goto end;
251 else if (result == -ERANGE)
252 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
253 "At maximum performance state\n"));
254
255 if (pr->flags.throttling) {
256 if (tx == (pr->throttling.state_count - 1))
257 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
258 "At maximum throttling state\n"));
259 else
260 tx++;
261 }
262 break;
263
264 case ACPI_PROCESSOR_LIMIT_DECREMENT:
265 /* if going down: T-states first, P-states later */
266
267 if (pr->flags.throttling) {
268 if (tx == 0)
269 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
270 "At minimum throttling state\n"));
271 else {
272 tx--;
273 goto end;
274 }
275 }
276
277 result = acpi_thermal_cpufreq_decrease(pr->id);
278 if (result == -ERANGE)
279 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
280 "At minimum performance state\n"));
281
282 break;
283 }
284
285end:
286 if (pr->flags.throttling) {
287 pr->limit.thermal.px = 0;
288 pr->limit.thermal.tx = tx;
289
290 result = acpi_processor_apply_limit(pr);
291 if (result)
292 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
293 "Unable to set thermal limit\n"));
294
295 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n",
296 pr->limit.thermal.px,
297 pr->limit.thermal.tx));
298 } else
299 result = 0;
300
301 return_VALUE(result);
302}
303
304
305int
306acpi_processor_get_limit_info (
307 struct acpi_processor *pr)
308{
309 ACPI_FUNCTION_TRACE("acpi_processor_get_limit_info");
310
311 if (!pr)
312 return_VALUE(-EINVAL);
313
314 if (pr->flags.throttling)
315 pr->flags.limit = 1;
316
317 return_VALUE(0);
318}
319
320
321/* /proc interface */
322
323static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
324{
325 struct acpi_processor *pr = (struct acpi_processor *)seq->private;
326
327 ACPI_FUNCTION_TRACE("acpi_processor_limit_seq_show");
328
329 if (!pr)
330 goto end;
331
332 if (!pr->flags.limit) {
333 seq_puts(seq, "<not supported>\n");
334 goto end;
335 }
336
337 seq_printf(seq, "active limit: P%d:T%d\n"
338 "user limit: P%d:T%d\n"
339 "thermal limit: P%d:T%d\n",
340 pr->limit.state.px, pr->limit.state.tx,
341 pr->limit.user.px, pr->limit.user.tx,
342 pr->limit.thermal.px, pr->limit.thermal.tx);
343
344end:
345 return_VALUE(0);
346}
347
348static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
349{
350 return single_open(file, acpi_processor_limit_seq_show,
351 PDE(inode)->data);
352}
353
354ssize_t acpi_processor_write_limit (
355 struct file *file,
356 const char __user *buffer,
357 size_t count,
358 loff_t *data)
359{
360 int result = 0;
361 struct seq_file *m = (struct seq_file *)file->private_data;
362 struct acpi_processor *pr = (struct acpi_processor *)m->private;
363 char limit_string[25] = {'\0'};
364 int px = 0;
365 int tx = 0;
366
367 ACPI_FUNCTION_TRACE("acpi_processor_write_limit");
368
369 if (!pr || (count > sizeof(limit_string) - 1)) {
370 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n"));
371 return_VALUE(-EINVAL);
372 }
373
374 if (copy_from_user(limit_string, buffer, count)) {
375 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
376 return_VALUE(-EFAULT);
377 }
378
379 limit_string[count] = '\0';
380
381 if (sscanf(limit_string, "%d:%d", &px, &tx) != 2) {
382 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
383 return_VALUE(-EINVAL);
384 }
385
386 if (pr->flags.throttling) {
387 if ((tx < 0) || (tx > (pr->throttling.state_count - 1))) {
388 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid tx\n"));
389 return_VALUE(-EINVAL);
390 }
391 pr->limit.user.tx = tx;
392 }
393
394 result = acpi_processor_apply_limit(pr);
395
396 return_VALUE(count);
397}
398
399
400struct file_operations acpi_processor_limit_fops = {
401 .open = acpi_processor_limit_open_fs,
402 .read = seq_read,
403 .llseek = seq_lseek,
404 .release = single_release,
405};
406
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
new file mode 100644
index 000000000000..be9f569d39d3
--- /dev/null
+++ b/drivers/acpi/processor_throttling.c
@@ -0,0 +1,351 @@
1/*
2 * processor_throttling.c - Throttling submodule of the ACPI processor driver
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de>
7 * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
8 * - Added processor hotplug support
9 *
10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or (at
15 * your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 *
26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 */
28
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/cpufreq.h>
33#include <linux/proc_fs.h>
34#include <linux/seq_file.h>
35
36#include <asm/io.h>
37#include <asm/uaccess.h>
38
39#include <acpi/acpi_bus.h>
40#include <acpi/processor.h>
41
42#define ACPI_PROCESSOR_COMPONENT 0x01000000
43#define ACPI_PROCESSOR_CLASS "processor"
44#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
45#define _COMPONENT ACPI_PROCESSOR_COMPONENT
46ACPI_MODULE_NAME ("acpi_processor")
47
48
49/* --------------------------------------------------------------------------
50 Throttling Control
51 -------------------------------------------------------------------------- */
52
53static int
54acpi_processor_get_throttling (
55 struct acpi_processor *pr)
56{
57 int state = 0;
58 u32 value = 0;
59 u32 duty_mask = 0;
60 u32 duty_value = 0;
61
62 ACPI_FUNCTION_TRACE("acpi_processor_get_throttling");
63
64 if (!pr)
65 return_VALUE(-EINVAL);
66
67 if (!pr->flags.throttling)
68 return_VALUE(-ENODEV);
69
70 pr->throttling.state = 0;
71
72 duty_mask = pr->throttling.state_count - 1;
73
74 duty_mask <<= pr->throttling.duty_offset;
75
76 local_irq_disable();
77
78 value = inl(pr->throttling.address);
79
80 /*
81 * Compute the current throttling state when throttling is enabled
82 * (bit 4 is on).
83 */
84 if (value & 0x10) {
85 duty_value = value & duty_mask;
86 duty_value >>= pr->throttling.duty_offset;
87
88 if (duty_value)
89 state = pr->throttling.state_count-duty_value;
90 }
91
92 pr->throttling.state = state;
93
94 local_irq_enable();
95
96 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
97 "Throttling state is T%d (%d%% throttling applied)\n",
98 state, pr->throttling.states[state].performance));
99
100 return_VALUE(0);
101}
102
103
104int acpi_processor_set_throttling (
105 struct acpi_processor *pr,
106 int state)
107{
108 u32 value = 0;
109 u32 duty_mask = 0;
110 u32 duty_value = 0;
111
112 ACPI_FUNCTION_TRACE("acpi_processor_set_throttling");
113
114 if (!pr)
115 return_VALUE(-EINVAL);
116
117 if ((state < 0) || (state > (pr->throttling.state_count - 1)))
118 return_VALUE(-EINVAL);
119
120 if (!pr->flags.throttling)
121 return_VALUE(-ENODEV);
122
123 if (state == pr->throttling.state)
124 return_VALUE(0);
125
126 /*
127 * Calculate the duty_value and duty_mask.
128 */
129 if (state) {
130 duty_value = pr->throttling.state_count - state;
131
132 duty_value <<= pr->throttling.duty_offset;
133
134 /* Used to clear all duty_value bits */
135 duty_mask = pr->throttling.state_count - 1;
136
137 duty_mask <<= acpi_fadt.duty_offset;
138 duty_mask = ~duty_mask;
139 }
140
141 local_irq_disable();
142
143 /*
144 * Disable throttling by writing a 0 to bit 4. Note that we must
145 * turn it off before you can change the duty_value.
146 */
147 value = inl(pr->throttling.address);
148 if (value & 0x10) {
149 value &= 0xFFFFFFEF;
150 outl(value, pr->throttling.address);
151 }
152
153 /*
154 * Write the new duty_value and then enable throttling. Note
155 * that a state value of 0 leaves throttling disabled.
156 */
157 if (state) {
158 value &= duty_mask;
159 value |= duty_value;
160 outl(value, pr->throttling.address);
161
162 value |= 0x00000010;
163 outl(value, pr->throttling.address);
164 }
165
166 pr->throttling.state = state;
167
168 local_irq_enable();
169
170 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
171 "Throttling state set to T%d (%d%%)\n", state,
172 (pr->throttling.states[state].performance?pr->throttling.states[state].performance/10:0)));
173
174 return_VALUE(0);
175}
176
177
178int
179acpi_processor_get_throttling_info (
180 struct acpi_processor *pr)
181{
182 int result = 0;
183 int step = 0;
184 int i = 0;
185
186 ACPI_FUNCTION_TRACE("acpi_processor_get_throttling_info");
187
188 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
189 "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
190 pr->throttling.address,
191 pr->throttling.duty_offset,
192 pr->throttling.duty_width));
193
194 if (!pr)
195 return_VALUE(-EINVAL);
196
197 /* TBD: Support ACPI 2.0 objects */
198
199 if (!pr->throttling.address) {
200 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n"));
201 return_VALUE(0);
202 }
203 else if (!pr->throttling.duty_width) {
204 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n"));
205 return_VALUE(0);
206 }
207 /* TBD: Support duty_cycle values that span bit 4. */
208 else if ((pr->throttling.duty_offset
209 + pr->throttling.duty_width) > 4) {
210 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "duty_cycle spans bit 4\n"));
211 return_VALUE(0);
212 }
213
214 /*
215 * PIIX4 Errata: We don't support throttling on the original PIIX4.
216 * This shouldn't be an issue as few (if any) mobile systems ever
217 * used this part.
218 */
219 if (errata.piix4.throttle) {
220 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
221 "Throttling not supported on PIIX4 A- or B-step\n"));
222 return_VALUE(0);
223 }
224
225 pr->throttling.state_count = 1 << acpi_fadt.duty_width;
226
227 /*
228 * Compute state values. Note that throttling displays a linear power/
229 * performance relationship (at 50% performance the CPU will consume
230 * 50% power). Values are in 1/10th of a percent to preserve accuracy.
231 */
232
233 step = (1000 / pr->throttling.state_count);
234
235 for (i=0; i<pr->throttling.state_count; i++) {
236 pr->throttling.states[i].performance = step * i;
237 pr->throttling.states[i].power = step * i;
238 }
239
240 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n",
241 pr->throttling.state_count));
242
243 pr->flags.throttling = 1;
244
245 /*
246 * Disable throttling (if enabled). We'll let subsequent policy (e.g.
247 * thermal) decide to lower performance if it so chooses, but for now
248 * we'll crank up the speed.
249 */
250
251 result = acpi_processor_get_throttling(pr);
252 if (result)
253 goto end;
254
255 if (pr->throttling.state) {
256 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabling throttling (was T%d)\n",
257 pr->throttling.state));
258 result = acpi_processor_set_throttling(pr, 0);
259 if (result)
260 goto end;
261 }
262
263end:
264 if (result)
265 pr->flags.throttling = 0;
266
267 return_VALUE(result);
268}
269
270
271/* proc interface */
272
273static int acpi_processor_throttling_seq_show(struct seq_file *seq, void *offset)
274{
275 struct acpi_processor *pr = (struct acpi_processor *)seq->private;
276 int i = 0;
277 int result = 0;
278
279 ACPI_FUNCTION_TRACE("acpi_processor_throttling_seq_show");
280
281 if (!pr)
282 goto end;
283
284 if (!(pr->throttling.state_count > 0)) {
285 seq_puts(seq, "<not supported>\n");
286 goto end;
287 }
288
289 result = acpi_processor_get_throttling(pr);
290
291 if (result) {
292 seq_puts(seq, "Could not determine current throttling state.\n");
293 goto end;
294 }
295
296 seq_printf(seq, "state count: %d\n"
297 "active state: T%d\n",
298 pr->throttling.state_count,
299 pr->throttling.state);
300
301 seq_puts(seq, "states:\n");
302 for (i = 0; i < pr->throttling.state_count; i++)
303 seq_printf(seq, " %cT%d: %02d%%\n",
304 (i == pr->throttling.state?'*':' '), i,
305 (pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0));
306
307end:
308 return_VALUE(0);
309}
310
311static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file)
312{
313 return single_open(file, acpi_processor_throttling_seq_show,
314 PDE(inode)->data);
315}
316
317ssize_t acpi_processor_write_throttling (
318 struct file *file,
319 const char __user *buffer,
320 size_t count,
321 loff_t *data)
322{
323 int result = 0;
324 struct seq_file *m = (struct seq_file *)file->private_data;
325 struct acpi_processor *pr = (struct acpi_processor *)m->private;
326 char state_string[12] = {'\0'};
327
328 ACPI_FUNCTION_TRACE("acpi_processor_write_throttling");
329
330 if (!pr || (count > sizeof(state_string) - 1))
331 return_VALUE(-EINVAL);
332
333 if (copy_from_user(state_string, buffer, count))
334 return_VALUE(-EFAULT);
335
336 state_string[count] = '\0';
337
338 result = acpi_processor_set_throttling(pr,
339 simple_strtoul(state_string, NULL, 0));
340 if (result)
341 return_VALUE(result);
342
343 return_VALUE(count);
344}
345
346struct file_operations acpi_processor_throttling_fops = {
347 .open = acpi_processor_throttling_open_fs,
348 .read = seq_read,
349 .llseek = seq_lseek,
350 .release = single_release,
351};
diff --git a/drivers/acpi/resources/Makefile b/drivers/acpi/resources/Makefile
new file mode 100644
index 000000000000..2130b74170c3
--- /dev/null
+++ b/drivers/acpi/resources/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for all Linux ACPI interpreter subdirectories
3#
4
5obj-y := rsaddr.o rscreate.o rsio.o rslist.o rsmisc.o rsxface.o \
6 rscalc.o rsirq.o rsmemory.o rsutils.o
7
8obj-$(ACPI_FUTURE_USAGE) += rsdump.o
9
10EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c
new file mode 100644
index 000000000000..4788c079735d
--- /dev/null
+++ b/drivers/acpi/resources/rsaddr.c
@@ -0,0 +1,1225 @@
1/*******************************************************************************
2 *
3 * Module Name: rsaddr - Address resource descriptors (16/32/64)
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acresrc.h>
47
48#define _COMPONENT ACPI_RESOURCES
49 ACPI_MODULE_NAME ("rsaddr")
50
51
52/*******************************************************************************
53 *
54 * FUNCTION: acpi_rs_address16_resource
55 *
56 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
57 * stream
58 * bytes_consumed - Pointer to where the number of bytes
59 * consumed the byte_stream_buffer is
60 * returned
61 * output_buffer - Pointer to the return data buffer
62 * structure_size - Pointer to where the number of bytes
63 * in the return data struct is returned
64 *
65 * RETURN: Status
66 *
67 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
68 * structure pointed to by the output_buffer. Return the
69 * number of bytes consumed from the byte stream.
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_rs_address16_resource (
75 u8 *byte_stream_buffer,
76 acpi_size *bytes_consumed,
77 u8 **output_buffer,
78 acpi_size *structure_size)
79{
80 u8 *buffer = byte_stream_buffer;
81 struct acpi_resource *output_struct = (void *) *output_buffer;
82 u8 *temp_ptr;
83 acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16);
84 u32 index;
85 u16 temp16;
86 u8 temp8;
87
88
89 ACPI_FUNCTION_TRACE ("rs_address16_resource");
90
91
92 /*
93 * Point past the Descriptor to get the number of bytes consumed
94 */
95 buffer += 1;
96 ACPI_MOVE_16_TO_16 (&temp16, buffer);
97
98 /* Validate minimum descriptor length */
99
100 if (temp16 < 13) {
101 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
102 }
103
104 *bytes_consumed = temp16 + 3;
105 output_struct->id = ACPI_RSTYPE_ADDRESS16;
106
107 /*
108 * Get the Resource Type (Byte3)
109 */
110 buffer += 2;
111 temp8 = *buffer;
112
113 /* Values 0-2 and 0xC0-0xFF are valid */
114
115 if ((temp8 > 2) && (temp8 < 0xC0)) {
116 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
117 }
118
119 output_struct->data.address16.resource_type = temp8;
120
121 /*
122 * Get the General Flags (Byte4)
123 */
124 buffer += 1;
125 temp8 = *buffer;
126
127 /* Producer / Consumer */
128
129 output_struct->data.address16.producer_consumer = temp8 & 0x01;
130
131 /* Decode */
132
133 output_struct->data.address16.decode = (temp8 >> 1) & 0x01;
134
135 /* Min Address Fixed */
136
137 output_struct->data.address16.min_address_fixed = (temp8 >> 2) & 0x01;
138
139 /* Max Address Fixed */
140
141 output_struct->data.address16.max_address_fixed = (temp8 >> 3) & 0x01;
142
143 /*
144 * Get the Type Specific Flags (Byte5)
145 */
146 buffer += 1;
147 temp8 = *buffer;
148
149 if (ACPI_MEMORY_RANGE == output_struct->data.address16.resource_type) {
150 output_struct->data.address16.attribute.memory.read_write_attribute =
151 (u16) (temp8 & 0x01);
152 output_struct->data.address16.attribute.memory.cache_attribute =
153 (u16) ((temp8 >> 1) & 0x03);
154 }
155 else {
156 if (ACPI_IO_RANGE == output_struct->data.address16.resource_type) {
157 output_struct->data.address16.attribute.io.range_attribute =
158 (u16) (temp8 & 0x03);
159 output_struct->data.address16.attribute.io.translation_attribute =
160 (u16) ((temp8 >> 4) & 0x03);
161 }
162 else {
163 /* BUS_NUMBER_RANGE == Address16.Data->resource_type */
164 /* Nothing needs to be filled in */
165 }
166 }
167
168 /*
169 * Get Granularity (Bytes 6-7)
170 */
171 buffer += 1;
172 ACPI_MOVE_16_TO_32 (&output_struct->data.address16.granularity, buffer);
173
174 /*
175 * Get min_address_range (Bytes 8-9)
176 */
177 buffer += 2;
178 ACPI_MOVE_16_TO_32 (&output_struct->data.address16.min_address_range, buffer);
179
180 /*
181 * Get max_address_range (Bytes 10-11)
182 */
183 buffer += 2;
184 ACPI_MOVE_16_TO_32 (&output_struct->data.address16.max_address_range, buffer);
185
186 /*
187 * Get address_translation_offset (Bytes 12-13)
188 */
189 buffer += 2;
190 ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_translation_offset, buffer);
191
192 /*
193 * Get address_length (Bytes 14-15)
194 */
195 buffer += 2;
196 ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_length, buffer);
197
198 /*
199 * Resource Source Index (if present)
200 */
201 buffer += 2;
202
203 /*
204 * This will leave us pointing to the Resource Source Index
205 * If it is present, then save it off and calculate the
206 * pointer to where the null terminated string goes:
207 * Each Interrupt takes 32-bits + the 5 bytes of the
208 * stream that are default.
209 *
210 * Note: Some resource descriptors will have an additional null, so
211 * we add 1 to the length.
212 */
213 if (*bytes_consumed > (16 + 1)) {
214 /* Dereference the Index */
215
216 temp8 = *buffer;
217 output_struct->data.address16.resource_source.index = (u32) temp8;
218
219 /* Point to the String */
220
221 buffer += 1;
222
223 /* Point the String pointer to the end of this structure */
224
225 output_struct->data.address16.resource_source.string_ptr =
226 (char *)((u8 * )output_struct + struct_size);
227
228 temp_ptr = (u8 *) output_struct->data.address16.resource_source.string_ptr;
229
230 /* Copy the string into the buffer */
231
232 index = 0;
233
234 while (0x00 != *buffer) {
235 *temp_ptr = *buffer;
236
237 temp_ptr += 1;
238 buffer += 1;
239 index += 1;
240 }
241
242 /*
243 * Add the terminating null
244 */
245 *temp_ptr = 0x00;
246
247 output_struct->data.address16.resource_source.string_length = index + 1;
248
249 /*
250 * In order for the struct_size to fall on a 32-bit boundary,
251 * calculate the length of the string and expand the
252 * struct_size to the next 32-bit boundary.
253 */
254 temp8 = (u8) (index + 1);
255 struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
256 }
257 else {
258 output_struct->data.address16.resource_source.index = 0x00;
259 output_struct->data.address16.resource_source.string_length = 0;
260 output_struct->data.address16.resource_source.string_ptr = NULL;
261 }
262
263 /*
264 * Set the Length parameter
265 */
266 output_struct->length = (u32) struct_size;
267
268 /*
269 * Return the final size of the structure
270 */
271 *structure_size = struct_size;
272 return_ACPI_STATUS (AE_OK);
273}
274
275
276/*******************************************************************************
277 *
278 * FUNCTION: acpi_rs_address16_stream
279 *
280 * PARAMETERS: linked_list - Pointer to the resource linked list
281 * output_buffer - Pointer to the user's return buffer
282 * bytes_consumed - Pointer to where the number of bytes
283 * used in the output_buffer is returned
284 *
285 * RETURN: Status
286 *
287 * DESCRIPTION: Take the linked list resource structure and fills in the
288 * the appropriate bytes in a byte stream
289 *
290 ******************************************************************************/
291
292acpi_status
293acpi_rs_address16_stream (
294 struct acpi_resource *linked_list,
295 u8 **output_buffer,
296 acpi_size *bytes_consumed)
297{
298 u8 *buffer = *output_buffer;
299 u8 *length_field;
300 u8 temp8;
301 char *temp_pointer = NULL;
302 acpi_size actual_bytes;
303
304
305 ACPI_FUNCTION_TRACE ("rs_address16_stream");
306
307
308 /*
309 * The descriptor field is static
310 */
311 *buffer = 0x88;
312 buffer += 1;
313
314 /*
315 * Save a pointer to the Length field - to be filled in later
316 */
317 length_field = buffer;
318 buffer += 2;
319
320 /*
321 * Set the Resource Type (Memory, Io, bus_number)
322 */
323 temp8 = (u8) (linked_list->data.address16.resource_type & 0x03);
324 *buffer = temp8;
325 buffer += 1;
326
327 /*
328 * Set the general flags
329 */
330 temp8 = (u8) (linked_list->data.address16.producer_consumer & 0x01);
331
332 temp8 |= (linked_list->data.address16.decode & 0x01) << 1;
333 temp8 |= (linked_list->data.address16.min_address_fixed & 0x01) << 2;
334 temp8 |= (linked_list->data.address16.max_address_fixed & 0x01) << 3;
335
336 *buffer = temp8;
337 buffer += 1;
338
339 /*
340 * Set the type specific flags
341 */
342 temp8 = 0;
343
344 if (ACPI_MEMORY_RANGE == linked_list->data.address16.resource_type) {
345 temp8 = (u8)
346 (linked_list->data.address16.attribute.memory.read_write_attribute &
347 0x01);
348
349 temp8 |=
350 (linked_list->data.address16.attribute.memory.cache_attribute &
351 0x03) << 1;
352 }
353 else if (ACPI_IO_RANGE == linked_list->data.address16.resource_type) {
354 temp8 = (u8)
355 (linked_list->data.address16.attribute.io.range_attribute &
356 0x03);
357 temp8 |=
358 (linked_list->data.address16.attribute.io.translation_attribute &
359 0x03) << 4;
360 }
361
362 *buffer = temp8;
363 buffer += 1;
364
365 /*
366 * Set the address space granularity
367 */
368 ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.granularity);
369 buffer += 2;
370
371 /*
372 * Set the address range minimum
373 */
374 ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.min_address_range);
375 buffer += 2;
376
377 /*
378 * Set the address range maximum
379 */
380 ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.max_address_range);
381 buffer += 2;
382
383 /*
384 * Set the address translation offset
385 */
386 ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.address_translation_offset);
387 buffer += 2;
388
389 /*
390 * Set the address length
391 */
392 ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.address_length);
393 buffer += 2;
394
395 /*
396 * Resource Source Index and Resource Source are optional
397 */
398 if (0 != linked_list->data.address16.resource_source.string_length) {
399 temp8 = (u8) linked_list->data.address16.resource_source.index;
400
401 *buffer = temp8;
402 buffer += 1;
403
404 temp_pointer = (char *) buffer;
405
406 /*
407 * Copy the string
408 */
409 ACPI_STRCPY (temp_pointer,
410 linked_list->data.address16.resource_source.string_ptr);
411
412 /*
413 * Buffer needs to be set to the length of the sting + one for the
414 * terminating null
415 */
416 buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address16.resource_source.string_ptr) + 1);
417 }
418
419 /*
420 * Return the number of bytes consumed in this operation
421 */
422 actual_bytes = ACPI_PTR_DIFF (buffer, *output_buffer);
423 *bytes_consumed = actual_bytes;
424
425 /*
426 * Set the length field to the number of bytes consumed
427 * minus the header size (3 bytes)
428 */
429 actual_bytes -= 3;
430 ACPI_MOVE_SIZE_TO_16 (length_field, &actual_bytes);
431 return_ACPI_STATUS (AE_OK);
432}
433
434
435/*******************************************************************************
436 *
437 * FUNCTION: acpi_rs_address32_resource
438 *
439 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
440 * stream
441 * bytes_consumed - Pointer to where the number of bytes
442 * consumed the byte_stream_buffer is
443 * returned
444 * output_buffer - Pointer to the return data buffer
445 * structure_size - Pointer to where the number of bytes
446 * in the return data struct is returned
447 *
448 * RETURN: Status
449 *
450 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
451 * structure pointed to by the output_buffer. Return the
452 * number of bytes consumed from the byte stream.
453 *
454 ******************************************************************************/
455
456acpi_status
457acpi_rs_address32_resource (
458 u8 *byte_stream_buffer,
459 acpi_size *bytes_consumed,
460 u8 **output_buffer,
461 acpi_size *structure_size)
462{
463 u8 *buffer;
464 struct acpi_resource *output_struct= (void *) *output_buffer;
465 u16 temp16;
466 u8 temp8;
467 u8 *temp_ptr;
468 acpi_size struct_size;
469 u32 index;
470
471
472 ACPI_FUNCTION_TRACE ("rs_address32_resource");
473
474
475 buffer = byte_stream_buffer;
476 struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32);
477
478 /*
479 * Point past the Descriptor to get the number of bytes consumed
480 */
481 buffer += 1;
482 ACPI_MOVE_16_TO_16 (&temp16, buffer);
483
484 /* Validate minimum descriptor length */
485
486 if (temp16 < 23) {
487 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
488 }
489
490 *bytes_consumed = temp16 + 3;
491 output_struct->id = ACPI_RSTYPE_ADDRESS32;
492
493 /*
494 * Get the Resource Type (Byte3)
495 */
496 buffer += 2;
497 temp8 = *buffer;
498
499 /* Values 0-2 and 0xC0-0xFF are valid */
500
501 if ((temp8 > 2) && (temp8 < 0xC0)) {
502 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
503 }
504
505 output_struct->data.address32.resource_type = temp8;
506
507 /*
508 * Get the General Flags (Byte4)
509 */
510 buffer += 1;
511 temp8 = *buffer;
512
513 /*
514 * Producer / Consumer
515 */
516 output_struct->data.address32.producer_consumer = temp8 & 0x01;
517
518 /*
519 * Decode
520 */
521 output_struct->data.address32.decode = (temp8 >> 1) & 0x01;
522
523 /*
524 * Min Address Fixed
525 */
526 output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01;
527
528 /*
529 * Max Address Fixed
530 */
531 output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01;
532
533 /*
534 * Get the Type Specific Flags (Byte5)
535 */
536 buffer += 1;
537 temp8 = *buffer;
538
539 if (ACPI_MEMORY_RANGE == output_struct->data.address32.resource_type) {
540 output_struct->data.address32.attribute.memory.read_write_attribute =
541 (u16) (temp8 & 0x01);
542
543 output_struct->data.address32.attribute.memory.cache_attribute =
544 (u16) ((temp8 >> 1) & 0x03);
545 }
546 else {
547 if (ACPI_IO_RANGE == output_struct->data.address32.resource_type) {
548 output_struct->data.address32.attribute.io.range_attribute =
549 (u16) (temp8 & 0x03);
550 output_struct->data.address32.attribute.io.translation_attribute =
551 (u16) ((temp8 >> 4) & 0x03);
552 }
553 else {
554 /* BUS_NUMBER_RANGE == output_struct->Data.Address32.resource_type */
555 /* Nothing needs to be filled in */
556 }
557 }
558
559 /*
560 * Get Granularity (Bytes 6-9)
561 */
562 buffer += 1;
563 ACPI_MOVE_32_TO_32 (&output_struct->data.address32.granularity, buffer);
564
565 /*
566 * Get min_address_range (Bytes 10-13)
567 */
568 buffer += 4;
569 ACPI_MOVE_32_TO_32 (&output_struct->data.address32.min_address_range, buffer);
570
571 /*
572 * Get max_address_range (Bytes 14-17)
573 */
574 buffer += 4;
575 ACPI_MOVE_32_TO_32 (&output_struct->data.address32.max_address_range, buffer);
576
577 /*
578 * Get address_translation_offset (Bytes 18-21)
579 */
580 buffer += 4;
581 ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_translation_offset, buffer);
582
583 /*
584 * Get address_length (Bytes 22-25)
585 */
586 buffer += 4;
587 ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_length, buffer);
588
589 /*
590 * Resource Source Index (if present)
591 */
592 buffer += 4;
593
594 /*
595 * This will leave us pointing to the Resource Source Index
596 * If it is present, then save it off and calculate the
597 * pointer to where the null terminated string goes:
598 *
599 * Note: Some resource descriptors will have an additional null, so
600 * we add 1 to the length.
601 */
602 if (*bytes_consumed > (26 + 1)) {
603 /* Dereference the Index */
604
605 temp8 = *buffer;
606 output_struct->data.address32.resource_source.index =
607 (u32) temp8;
608
609 /* Point to the String */
610
611 buffer += 1;
612
613 /* Point the String pointer to the end of this structure */
614
615 output_struct->data.address32.resource_source.string_ptr =
616 (char *)((u8 *)output_struct + struct_size);
617
618 temp_ptr = (u8 *) output_struct->data.address32.resource_source.string_ptr;
619
620 /* Copy the string into the buffer */
621
622 index = 0;
623 while (0x00 != *buffer) {
624 *temp_ptr = *buffer;
625
626 temp_ptr += 1;
627 buffer += 1;
628 index += 1;
629 }
630
631 /*
632 * Add the terminating null
633 */
634 *temp_ptr = 0x00;
635 output_struct->data.address32.resource_source.string_length = index + 1;
636
637 /*
638 * In order for the struct_size to fall on a 32-bit boundary,
639 * calculate the length of the string and expand the
640 * struct_size to the next 32-bit boundary.
641 */
642 temp8 = (u8) (index + 1);
643 struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
644 }
645 else {
646 output_struct->data.address32.resource_source.index = 0x00;
647 output_struct->data.address32.resource_source.string_length = 0;
648 output_struct->data.address32.resource_source.string_ptr = NULL;
649 }
650
651 /*
652 * Set the Length parameter
653 */
654 output_struct->length = (u32) struct_size;
655
656 /*
657 * Return the final size of the structure
658 */
659 *structure_size = struct_size;
660 return_ACPI_STATUS (AE_OK);
661}
662
663
664/*******************************************************************************
665 *
666 * FUNCTION: acpi_rs_address32_stream
667 *
668 * PARAMETERS: linked_list - Pointer to the resource linked list
669 * output_buffer - Pointer to the user's return buffer
670 * bytes_consumed - Pointer to where the number of bytes
671 * used in the output_buffer is returned
672 *
673 * RETURN: Status
674 *
675 * DESCRIPTION: Take the linked list resource structure and fills in the
676 * the appropriate bytes in a byte stream
677 *
678 ******************************************************************************/
679
680acpi_status
681acpi_rs_address32_stream (
682 struct acpi_resource *linked_list,
683 u8 **output_buffer,
684 acpi_size *bytes_consumed)
685{
686 u8 *buffer;
687 u16 *length_field;
688 u8 temp8;
689 char *temp_pointer;
690
691
692 ACPI_FUNCTION_TRACE ("rs_address32_stream");
693
694
695 buffer = *output_buffer;
696
697 /*
698 * The descriptor field is static
699 */
700 *buffer = 0x87;
701 buffer += 1;
702
703 /*
704 * Set a pointer to the Length field - to be filled in later
705 */
706 length_field = ACPI_CAST_PTR (u16, buffer);
707 buffer += 2;
708
709 /*
710 * Set the Resource Type (Memory, Io, bus_number)
711 */
712 temp8 = (u8) (linked_list->data.address32.resource_type & 0x03);
713
714 *buffer = temp8;
715 buffer += 1;
716
717 /*
718 * Set the general flags
719 */
720 temp8 = (u8) (linked_list->data.address32.producer_consumer & 0x01);
721 temp8 |= (linked_list->data.address32.decode & 0x01) << 1;
722 temp8 |= (linked_list->data.address32.min_address_fixed & 0x01) << 2;
723 temp8 |= (linked_list->data.address32.max_address_fixed & 0x01) << 3;
724
725 *buffer = temp8;
726 buffer += 1;
727
728 /*
729 * Set the type specific flags
730 */
731 temp8 = 0;
732
733 if (ACPI_MEMORY_RANGE == linked_list->data.address32.resource_type) {
734 temp8 = (u8)
735 (linked_list->data.address32.attribute.memory.read_write_attribute &
736 0x01);
737
738 temp8 |=
739 (linked_list->data.address32.attribute.memory.cache_attribute &
740 0x03) << 1;
741 }
742 else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) {
743 temp8 = (u8)
744 (linked_list->data.address32.attribute.io.range_attribute &
745 0x03);
746 temp8 |=
747 (linked_list->data.address32.attribute.io.translation_attribute &
748 0x03) << 4;
749 }
750
751 *buffer = temp8;
752 buffer += 1;
753
754 /*
755 * Set the address space granularity
756 */
757 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.granularity);
758 buffer += 4;
759
760 /*
761 * Set the address range minimum
762 */
763 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.min_address_range);
764 buffer += 4;
765
766 /*
767 * Set the address range maximum
768 */
769 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.max_address_range);
770 buffer += 4;
771
772 /*
773 * Set the address translation offset
774 */
775 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_translation_offset);
776 buffer += 4;
777
778 /*
779 * Set the address length
780 */
781 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_length);
782 buffer += 4;
783
784 /*
785 * Resource Source Index and Resource Source are optional
786 */
787 if (0 != linked_list->data.address32.resource_source.string_length) {
788 temp8 = (u8) linked_list->data.address32.resource_source.index;
789
790 *buffer = temp8;
791 buffer += 1;
792
793 temp_pointer = (char *) buffer;
794
795 /*
796 * Copy the string
797 */
798 ACPI_STRCPY (temp_pointer,
799 linked_list->data.address32.resource_source.string_ptr);
800
801 /*
802 * Buffer needs to be set to the length of the sting + one for the
803 * terminating null
804 */
805 buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address32.resource_source.string_ptr) + 1);
806 }
807
808 /*
809 * Return the number of bytes consumed in this operation
810 */
811 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
812
813 /*
814 * Set the length field to the number of bytes consumed
815 * minus the header size (3 bytes)
816 */
817 *length_field = (u16) (*bytes_consumed - 3);
818 return_ACPI_STATUS (AE_OK);
819}
820
821
822/*******************************************************************************
823 *
824 * FUNCTION: acpi_rs_address64_resource
825 *
826 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
827 * stream
828 * bytes_consumed - Pointer to where the number of bytes
829 * consumed the byte_stream_buffer is
830 * returned
831 * output_buffer - Pointer to the return data buffer
832 * structure_size - Pointer to where the number of bytes
833 * in the return data struct is returned
834 *
835 * RETURN: Status
836 *
837 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
838 * structure pointed to by the output_buffer. Return the
839 * number of bytes consumed from the byte stream.
840 *
841 ******************************************************************************/
842
843acpi_status
844acpi_rs_address64_resource (
845 u8 *byte_stream_buffer,
846 acpi_size *bytes_consumed,
847 u8 **output_buffer,
848 acpi_size *structure_size)
849{
850 u8 *buffer;
851 struct acpi_resource *output_struct = (void *) *output_buffer;
852 u16 temp16;
853 u8 temp8;
854 u8 resource_type;
855 u8 *temp_ptr;
856 acpi_size struct_size;
857 u32 index;
858
859
860 ACPI_FUNCTION_TRACE ("rs_address64_resource");
861
862
863 buffer = byte_stream_buffer;
864 struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
865 resource_type = *buffer;
866
867 /*
868 * Point past the Descriptor to get the number of bytes consumed
869 */
870 buffer += 1;
871 ACPI_MOVE_16_TO_16 (&temp16, buffer);
872
873 /* Validate minimum descriptor length */
874
875 if (temp16 < 43) {
876 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
877 }
878
879 *bytes_consumed = temp16 + 3;
880 output_struct->id = ACPI_RSTYPE_ADDRESS64;
881
882 /*
883 * Get the Resource Type (Byte3)
884 */
885 buffer += 2;
886 temp8 = *buffer;
887
888 /* Values 0-2 and 0xC0-0xFF are valid */
889
890 if ((temp8 > 2) && (temp8 < 0xC0)) {
891 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
892 }
893
894 output_struct->data.address64.resource_type = temp8;
895
896 /*
897 * Get the General Flags (Byte4)
898 */
899 buffer += 1;
900 temp8 = *buffer;
901
902 /*
903 * Producer / Consumer
904 */
905 output_struct->data.address64.producer_consumer = temp8 & 0x01;
906
907 /*
908 * Decode
909 */
910 output_struct->data.address64.decode = (temp8 >> 1) & 0x01;
911
912 /*
913 * Min Address Fixed
914 */
915 output_struct->data.address64.min_address_fixed = (temp8 >> 2) & 0x01;
916
917 /*
918 * Max Address Fixed
919 */
920 output_struct->data.address64.max_address_fixed = (temp8 >> 3) & 0x01;
921
922 /*
923 * Get the Type Specific Flags (Byte5)
924 */
925 buffer += 1;
926 temp8 = *buffer;
927
928 if (ACPI_MEMORY_RANGE == output_struct->data.address64.resource_type) {
929 output_struct->data.address64.attribute.memory.read_write_attribute =
930 (u16) (temp8 & 0x01);
931
932 output_struct->data.address64.attribute.memory.cache_attribute =
933 (u16) ((temp8 >> 1) & 0x03);
934 }
935 else {
936 if (ACPI_IO_RANGE == output_struct->data.address64.resource_type) {
937 output_struct->data.address64.attribute.io.range_attribute =
938 (u16) (temp8 & 0x03);
939 output_struct->data.address64.attribute.io.translation_attribute =
940 (u16) ((temp8 >> 4) & 0x03);
941 }
942 else {
943 /* BUS_NUMBER_RANGE == output_struct->Data.Address64.resource_type */
944 /* Nothing needs to be filled in */
945 }
946 }
947
948 if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
949 /* Move past revision_id and Reserved byte */
950
951 buffer += 2;
952 }
953
954 /*
955 * Get Granularity (Bytes 6-13) or (Bytes 8-15)
956 */
957 buffer += 1;
958 ACPI_MOVE_64_TO_64 (&output_struct->data.address64.granularity, buffer);
959
960 /*
961 * Get min_address_range (Bytes 14-21) or (Bytes 16-23)
962 */
963 buffer += 8;
964 ACPI_MOVE_64_TO_64 (&output_struct->data.address64.min_address_range, buffer);
965
966 /*
967 * Get max_address_range (Bytes 22-29) or (Bytes 24-31)
968 */
969 buffer += 8;
970 ACPI_MOVE_64_TO_64 (&output_struct->data.address64.max_address_range, buffer);
971
972 /*
973 * Get address_translation_offset (Bytes 30-37) or (Bytes 32-39)
974 */
975 buffer += 8;
976 ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_translation_offset, buffer);
977
978 /*
979 * Get address_length (Bytes 38-45) or (Bytes 40-47)
980 */
981 buffer += 8;
982 ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_length, buffer);
983
984 output_struct->data.address64.resource_source.index = 0x00;
985 output_struct->data.address64.resource_source.string_length = 0;
986 output_struct->data.address64.resource_source.string_ptr = NULL;
987
988 if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
989 /* Get type_specific_attribute (Bytes 48-55) */
990
991 buffer += 8;
992 ACPI_MOVE_64_TO_64 (&output_struct->data.address64.type_specific_attributes, buffer);
993 }
994 else {
995 output_struct->data.address64.type_specific_attributes = 0;
996
997 /*
998 * Resource Source Index (if present)
999 */
1000 buffer += 8;
1001
1002 /*
1003 * This will leave us pointing to the Resource Source Index
1004 * If it is present, then save it off and calculate the
1005 * pointer to where the null terminated string goes:
1006 * Each Interrupt takes 32-bits + the 5 bytes of the
1007 * stream that are default.
1008 *
1009 * Note: Some resource descriptors will have an additional null, so
1010 * we add 1 to the length.
1011 */
1012 if (*bytes_consumed > (46 + 1)) {
1013 /* Dereference the Index */
1014
1015 temp8 = *buffer;
1016 output_struct->data.address64.resource_source.index =
1017 (u32) temp8;
1018
1019 /* Point to the String */
1020
1021 buffer += 1;
1022
1023 /* Point the String pointer to the end of this structure */
1024
1025 output_struct->data.address64.resource_source.string_ptr =
1026 (char *)((u8 *)output_struct + struct_size);
1027
1028 temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr;
1029
1030 /* Copy the string into the buffer */
1031
1032 index = 0;
1033 while (0x00 != *buffer) {
1034 *temp_ptr = *buffer;
1035
1036 temp_ptr += 1;
1037 buffer += 1;
1038 index += 1;
1039 }
1040
1041 /*
1042 * Add the terminating null
1043 */
1044 *temp_ptr = 0x00;
1045 output_struct->data.address64.resource_source.string_length = index + 1;
1046
1047 /*
1048 * In order for the struct_size to fall on a 32-bit boundary,
1049 * calculate the length of the string and expand the
1050 * struct_size to the next 32-bit boundary.
1051 */
1052 temp8 = (u8) (index + 1);
1053 struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
1054 }
1055 }
1056
1057 /*
1058 * Set the Length parameter
1059 */
1060 output_struct->length = (u32) struct_size;
1061
1062 /*
1063 * Return the final size of the structure
1064 */
1065 *structure_size = struct_size;
1066 return_ACPI_STATUS (AE_OK);
1067}
1068
1069
1070/*******************************************************************************
1071 *
1072 * FUNCTION: acpi_rs_address64_stream
1073 *
1074 * PARAMETERS: linked_list - Pointer to the resource linked list
1075 * output_buffer - Pointer to the user's return buffer
1076 * bytes_consumed - Pointer to where the number of bytes
1077 * used in the output_buffer is returned
1078 *
1079 * RETURN: Status
1080 *
1081 * DESCRIPTION: Take the linked list resource structure and fills in the
1082 * the appropriate bytes in a byte stream
1083 *
1084 ******************************************************************************/
1085
1086acpi_status
1087acpi_rs_address64_stream (
1088 struct acpi_resource *linked_list,
1089 u8 **output_buffer,
1090 acpi_size *bytes_consumed)
1091{
1092 u8 *buffer;
1093 u16 *length_field;
1094 u8 temp8;
1095 char *temp_pointer;
1096
1097
1098 ACPI_FUNCTION_TRACE ("rs_address64_stream");
1099
1100
1101 buffer = *output_buffer;
1102
1103 /*
1104 * The descriptor field is static
1105 */
1106 *buffer = 0x8A;
1107 buffer += 1;
1108
1109 /*
1110 * Set a pointer to the Length field - to be filled in later
1111 */
1112 length_field = ACPI_CAST_PTR (u16, buffer);
1113 buffer += 2;
1114
1115 /*
1116 * Set the Resource Type (Memory, Io, bus_number)
1117 */
1118 temp8 = (u8) (linked_list->data.address64.resource_type & 0x03);
1119
1120 *buffer = temp8;
1121 buffer += 1;
1122
1123 /*
1124 * Set the general flags
1125 */
1126 temp8 = (u8) (linked_list->data.address64.producer_consumer & 0x01);
1127 temp8 |= (linked_list->data.address64.decode & 0x01) << 1;
1128 temp8 |= (linked_list->data.address64.min_address_fixed & 0x01) << 2;
1129 temp8 |= (linked_list->data.address64.max_address_fixed & 0x01) << 3;
1130
1131 *buffer = temp8;
1132 buffer += 1;
1133
1134 /*
1135 * Set the type specific flags
1136 */
1137 temp8 = 0;
1138
1139 if (ACPI_MEMORY_RANGE == linked_list->data.address64.resource_type) {
1140 temp8 = (u8)
1141 (linked_list->data.address64.attribute.memory.read_write_attribute &
1142 0x01);
1143
1144 temp8 |=
1145 (linked_list->data.address64.attribute.memory.cache_attribute &
1146 0x03) << 1;
1147 }
1148 else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) {
1149 temp8 = (u8)
1150 (linked_list->data.address64.attribute.io.range_attribute &
1151 0x03);
1152 temp8 |=
1153 (linked_list->data.address64.attribute.io.range_attribute &
1154 0x03) << 4;
1155 }
1156
1157 *buffer = temp8;
1158 buffer += 1;
1159
1160 /*
1161 * Set the address space granularity
1162 */
1163 ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.granularity);
1164 buffer += 8;
1165
1166 /*
1167 * Set the address range minimum
1168 */
1169 ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.min_address_range);
1170 buffer += 8;
1171
1172 /*
1173 * Set the address range maximum
1174 */
1175 ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.max_address_range);
1176 buffer += 8;
1177
1178 /*
1179 * Set the address translation offset
1180 */
1181 ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_translation_offset);
1182 buffer += 8;
1183
1184 /*
1185 * Set the address length
1186 */
1187 ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_length);
1188 buffer += 8;
1189
1190 /*
1191 * Resource Source Index and Resource Source are optional
1192 */
1193 if (0 != linked_list->data.address64.resource_source.string_length) {
1194 temp8 = (u8) linked_list->data.address64.resource_source.index;
1195
1196 *buffer = temp8;
1197 buffer += 1;
1198
1199 temp_pointer = (char *) buffer;
1200
1201 /*
1202 * Copy the string
1203 */
1204 ACPI_STRCPY (temp_pointer, linked_list->data.address64.resource_source.string_ptr);
1205
1206 /*
1207 * Buffer needs to be set to the length of the sting + one for the
1208 * terminating null
1209 */
1210 buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address64.resource_source.string_ptr) + 1);
1211 }
1212
1213 /*
1214 * Return the number of bytes consumed in this operation
1215 */
1216 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
1217
1218 /*
1219 * Set the length field to the number of bytes consumed
1220 * minus the header size (3 bytes)
1221 */
1222 *length_field = (u16) (*bytes_consumed - 3);
1223 return_ACPI_STATUS (AE_OK);
1224}
1225
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
new file mode 100644
index 000000000000..8a5f0a52371d
--- /dev/null
+++ b/drivers/acpi/resources/rscalc.c
@@ -0,0 +1,841 @@
1/*******************************************************************************
2 *
3 * Module Name: rscalc - Calculate stream and list lengths
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acresrc.h>
47#include <acpi/amlcode.h>
48#include <acpi/acnamesp.h>
49
50#define _COMPONENT ACPI_RESOURCES
51 ACPI_MODULE_NAME ("rscalc")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_rs_get_byte_stream_length
57 *
58 * PARAMETERS: linked_list - Pointer to the resource linked list
59 * size_needed - u32 pointer of the size buffer needed
60 * to properly return the parsed data
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Takes the resource byte stream and parses it once, calculating
65 * the size buffer needed to hold the linked list that conveys
66 * the resource data.
67 *
68 ******************************************************************************/
69
70acpi_status
71acpi_rs_get_byte_stream_length (
72 struct acpi_resource *linked_list,
73 acpi_size *size_needed)
74{
75 acpi_size byte_stream_size_needed = 0;
76 acpi_size segment_size;
77 u8 done = FALSE;
78
79
80 ACPI_FUNCTION_TRACE ("rs_get_byte_stream_length");
81
82
83 while (!done) {
84 /*
85 * Init the variable that will hold the size to add to the total.
86 */
87 segment_size = 0;
88
89 switch (linked_list->id) {
90 case ACPI_RSTYPE_IRQ:
91 /*
92 * IRQ Resource
93 * For an IRQ Resource, Byte 3, although optional, will always be
94 * created - it holds IRQ information.
95 */
96 segment_size = 4;
97 break;
98
99 case ACPI_RSTYPE_DMA:
100 /*
101 * DMA Resource
102 * For this resource the size is static
103 */
104 segment_size = 3;
105 break;
106
107 case ACPI_RSTYPE_START_DPF:
108 /*
109 * Start Dependent Functions Resource
110 * For a start_dependent_functions Resource, Byte 1, although
111 * optional, will always be created.
112 */
113 segment_size = 2;
114 break;
115
116 case ACPI_RSTYPE_END_DPF:
117 /*
118 * End Dependent Functions Resource
119 * For this resource the size is static
120 */
121 segment_size = 1;
122 break;
123
124 case ACPI_RSTYPE_IO:
125 /*
126 * IO Port Resource
127 * For this resource the size is static
128 */
129 segment_size = 8;
130 break;
131
132 case ACPI_RSTYPE_FIXED_IO:
133 /*
134 * Fixed IO Port Resource
135 * For this resource the size is static
136 */
137 segment_size = 4;
138 break;
139
140 case ACPI_RSTYPE_VENDOR:
141 /*
142 * Vendor Defined Resource
143 * For a Vendor Specific resource, if the Length is between 1 and 7
144 * it will be created as a Small Resource data type, otherwise it
145 * is a Large Resource data type.
146 */
147 if (linked_list->data.vendor_specific.length > 7) {
148 segment_size = 3;
149 }
150 else {
151 segment_size = 1;
152 }
153 segment_size += linked_list->data.vendor_specific.length;
154 break;
155
156 case ACPI_RSTYPE_END_TAG:
157 /*
158 * End Tag
159 * For this resource the size is static
160 */
161 segment_size = 2;
162 done = TRUE;
163 break;
164
165 case ACPI_RSTYPE_MEM24:
166 /*
167 * 24-Bit Memory Resource
168 * For this resource the size is static
169 */
170 segment_size = 12;
171 break;
172
173 case ACPI_RSTYPE_MEM32:
174 /*
175 * 32-Bit Memory Range Resource
176 * For this resource the size is static
177 */
178 segment_size = 20;
179 break;
180
181 case ACPI_RSTYPE_FIXED_MEM32:
182 /*
183 * 32-Bit Fixed Memory Resource
184 * For this resource the size is static
185 */
186 segment_size = 12;
187 break;
188
189 case ACPI_RSTYPE_ADDRESS16:
190 /*
191 * 16-Bit Address Resource
192 * The base size of this byte stream is 16. If a Resource Source
193 * string is not NULL, add 1 for the Index + the length of the null
194 * terminated string Resource Source + 1 for the null.
195 */
196 segment_size = 16;
197
198 if (linked_list->data.address16.resource_source.string_ptr) {
199 segment_size += linked_list->data.address16.resource_source.string_length;
200 segment_size++;
201 }
202 break;
203
204 case ACPI_RSTYPE_ADDRESS32:
205 /*
206 * 32-Bit Address Resource
207 * The base size of this byte stream is 26. If a Resource
208 * Source string is not NULL, add 1 for the Index + the
209 * length of the null terminated string Resource Source +
210 * 1 for the null.
211 */
212 segment_size = 26;
213
214 if (linked_list->data.address32.resource_source.string_ptr) {
215 segment_size += linked_list->data.address32.resource_source.string_length;
216 segment_size++;
217 }
218 break;
219
220 case ACPI_RSTYPE_ADDRESS64:
221 /*
222 * 64-Bit Address Resource
223 * The base size of this byte stream is 46. If a resource_source
224 * string is not NULL, add 1 for the Index + the length of the null
225 * terminated string Resource Source + 1 for the null.
226 */
227 segment_size = 46;
228
229 if (linked_list->data.address64.resource_source.string_ptr) {
230 segment_size += linked_list->data.address64.resource_source.string_length;
231 segment_size++;
232 }
233 break;
234
235 case ACPI_RSTYPE_EXT_IRQ:
236 /*
237 * Extended IRQ Resource
238 * The base size of this byte stream is 9. This is for an Interrupt
239 * table length of 1. For each additional interrupt, add 4.
240 * If a Resource Source string is not NULL, add 1 for the
241 * Index + the length of the null terminated string
242 * Resource Source + 1 for the null.
243 */
244 segment_size = 9 +
245 (((acpi_size) linked_list->data.extended_irq.number_of_interrupts - 1) * 4);
246
247 if (linked_list->data.extended_irq.resource_source.string_ptr) {
248 segment_size += linked_list->data.extended_irq.resource_source.string_length;
249 segment_size++;
250 }
251 break;
252
253 default:
254 /*
255 * If we get here, everything is out of sync, exit with error
256 */
257 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
258
259 } /* switch (linked_list->Id) */
260
261 /*
262 * Update the total
263 */
264 byte_stream_size_needed += segment_size;
265
266 /*
267 * Point to the next object
268 */
269 linked_list = ACPI_PTR_ADD (struct acpi_resource,
270 linked_list, linked_list->length);
271 }
272
273 /*
274 * This is the data the caller needs
275 */
276 *size_needed = byte_stream_size_needed;
277 return_ACPI_STATUS (AE_OK);
278}
279
280
281/*******************************************************************************
282 *
283 * FUNCTION: acpi_rs_get_list_length
284 *
285 * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream
286 * byte_stream_buffer_length - Size of byte_stream_buffer
287 * size_needed - u32 pointer of the size buffer
288 * needed to properly return the
289 * parsed data
290 *
291 * RETURN: Status
292 *
293 * DESCRIPTION: Takes the resource byte stream and parses it once, calculating
294 * the size buffer needed to hold the linked list that conveys
295 * the resource data.
296 *
297 ******************************************************************************/
298
299acpi_status
300acpi_rs_get_list_length (
301 u8 *byte_stream_buffer,
302 u32 byte_stream_buffer_length,
303 acpi_size *size_needed)
304{
305 u32 buffer_size = 0;
306 u32 bytes_parsed = 0;
307 u8 number_of_interrupts = 0;
308 u8 number_of_channels = 0;
309 u8 resource_type;
310 u32 structure_size;
311 u32 bytes_consumed;
312 u8 *buffer;
313 u8 temp8;
314 u16 temp16;
315 u8 index;
316 u8 additional_bytes;
317
318
319 ACPI_FUNCTION_TRACE ("rs_get_list_length");
320
321
322 while (bytes_parsed < byte_stream_buffer_length) {
323 /*
324 * The next byte in the stream is the resource type
325 */
326 resource_type = acpi_rs_get_resource_type (*byte_stream_buffer);
327
328 switch (resource_type) {
329 case ACPI_RDESC_TYPE_MEMORY_24:
330 /*
331 * 24-Bit Memory Resource
332 */
333 bytes_consumed = 12;
334
335 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem24);
336 break;
337
338
339 case ACPI_RDESC_TYPE_LARGE_VENDOR:
340 /*
341 * Vendor Defined Resource
342 */
343 buffer = byte_stream_buffer;
344 ++buffer;
345
346 ACPI_MOVE_16_TO_16 (&temp16, buffer);
347 bytes_consumed = temp16 + 3;
348
349 /*
350 * Ensure a 32-bit boundary for the structure
351 */
352 temp16 = (u16) ACPI_ROUND_UP_to_32_bITS (temp16);
353
354 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
355 (temp16 * sizeof (u8));
356 break;
357
358
359 case ACPI_RDESC_TYPE_MEMORY_32:
360 /*
361 * 32-Bit Memory Range Resource
362 */
363 bytes_consumed = 20;
364
365 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32);
366 break;
367
368
369 case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
370 /*
371 * 32-Bit Fixed Memory Resource
372 */
373 bytes_consumed = 12;
374
375 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_mem32);
376 break;
377
378
379 case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
380 /*
381 * 64-Bit Address Resource
382 */
383 buffer = byte_stream_buffer;
384
385 ++buffer;
386 ACPI_MOVE_16_TO_16 (&temp16, buffer);
387
388 bytes_consumed = temp16 + 3;
389 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
390 break;
391
392
393 case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
394 /*
395 * 64-Bit Address Resource
396 */
397 buffer = byte_stream_buffer;
398
399 ++buffer;
400 ACPI_MOVE_16_TO_16 (&temp16, buffer);
401
402 bytes_consumed = temp16 + 3;
403
404 /*
405 * Resource Source Index and Resource Source are optional elements.
406 * Check the length of the Bytestream. If it is greater than 43,
407 * that means that an Index exists and is followed by a null
408 * terminated string. Therefore, set the temp variable to the
409 * length minus the minimum byte stream length plus the byte for
410 * the Index to determine the size of the NULL terminated string.
411 */
412 if (43 < temp16) {
413 temp8 = (u8) (temp16 - 44);
414 }
415 else {
416 temp8 = 0;
417 }
418
419 /*
420 * Ensure a 64-bit boundary for the structure
421 */
422 temp8 = (u8) ACPI_ROUND_UP_to_64_bITS (temp8);
423
424 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64) +
425 (temp8 * sizeof (u8));
426 break;
427
428
429 case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
430 /*
431 * 32-Bit Address Resource
432 */
433 buffer = byte_stream_buffer;
434
435 ++buffer;
436 ACPI_MOVE_16_TO_16 (&temp16, buffer);
437
438 bytes_consumed = temp16 + 3;
439
440 /*
441 * Resource Source Index and Resource Source are optional elements.
442 * Check the length of the Bytestream. If it is greater than 23,
443 * that means that an Index exists and is followed by a null
444 * terminated string. Therefore, set the temp variable to the
445 * length minus the minimum byte stream length plus the byte for
446 * the Index to determine the size of the NULL terminated string.
447 */
448 if (23 < temp16) {
449 temp8 = (u8) (temp16 - 24);
450 }
451 else {
452 temp8 = 0;
453 }
454
455 /*
456 * Ensure a 32-bit boundary for the structure
457 */
458 temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
459
460 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32) +
461 (temp8 * sizeof (u8));
462 break;
463
464
465 case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
466 /*
467 * 16-Bit Address Resource
468 */
469 buffer = byte_stream_buffer;
470
471 ++buffer;
472 ACPI_MOVE_16_TO_16 (&temp16, buffer);
473
474 bytes_consumed = temp16 + 3;
475
476 /*
477 * Resource Source Index and Resource Source are optional elements.
478 * Check the length of the Bytestream. If it is greater than 13,
479 * that means that an Index exists and is followed by a null
480 * terminated string. Therefore, set the temp variable to the
481 * length minus the minimum byte stream length plus the byte for
482 * the Index to determine the size of the NULL terminated string.
483 */
484 if (13 < temp16) {
485 temp8 = (u8) (temp16 - 14);
486 }
487 else {
488 temp8 = 0;
489 }
490
491 /*
492 * Ensure a 32-bit boundary for the structure
493 */
494 temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
495
496 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16) +
497 (temp8 * sizeof (u8));
498 break;
499
500
501 case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
502 /*
503 * Extended IRQ
504 */
505 buffer = byte_stream_buffer;
506
507 ++buffer;
508 ACPI_MOVE_16_TO_16 (&temp16, buffer);
509
510 bytes_consumed = temp16 + 3;
511
512 /*
513 * Point past the length field and the Interrupt vector flags to
514 * save off the Interrupt table length to the Temp8 variable.
515 */
516 buffer += 3;
517 temp8 = *buffer;
518
519 /*
520 * To compensate for multiple interrupt numbers, add 4 bytes for
521 * each additional interrupts greater than 1
522 */
523 additional_bytes = (u8) ((temp8 - 1) * 4);
524
525 /*
526 * Resource Source Index and Resource Source are optional elements.
527 * Check the length of the Bytestream. If it is greater than 9,
528 * that means that an Index exists and is followed by a null
529 * terminated string. Therefore, set the temp variable to the
530 * length minus the minimum byte stream length plus the byte for
531 * the Index to determine the size of the NULL terminated string.
532 */
533 if (9 + additional_bytes < temp16) {
534 temp8 = (u8) (temp16 - (9 + additional_bytes));
535 }
536 else {
537 temp8 = 0;
538 }
539
540 /*
541 * Ensure a 32-bit boundary for the structure
542 */
543 temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
544
545 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_ext_irq) +
546 (additional_bytes * sizeof (u8)) +
547 (temp8 * sizeof (u8));
548 break;
549
550
551 case ACPI_RDESC_TYPE_IRQ_FORMAT:
552 /*
553 * IRQ Resource.
554 * Determine if it there are two or three trailing bytes
555 */
556 buffer = byte_stream_buffer;
557 temp8 = *buffer;
558
559 if(temp8 & 0x01) {
560 bytes_consumed = 4;
561 }
562 else {
563 bytes_consumed = 3;
564 }
565
566 /* Point past the descriptor */
567
568 ++buffer;
569
570 /*
571 * Look at the number of bits set
572 */
573 ACPI_MOVE_16_TO_16 (&temp16, buffer);
574
575 for (index = 0; index < 16; index++) {
576 if (temp16 & 0x1) {
577 ++number_of_interrupts;
578 }
579
580 temp16 >>= 1;
581 }
582
583 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io) +
584 (number_of_interrupts * sizeof (u32));
585 break;
586
587
588 case ACPI_RDESC_TYPE_DMA_FORMAT:
589 /*
590 * DMA Resource
591 */
592 buffer = byte_stream_buffer;
593 bytes_consumed = 3;
594
595 /* Point past the descriptor */
596
597 ++buffer;
598
599 /*
600 * Look at the number of bits set
601 */
602 temp8 = *buffer;
603
604 for(index = 0; index < 8; index++) {
605 if(temp8 & 0x1) {
606 ++number_of_channels;
607 }
608
609 temp8 >>= 1;
610 }
611
612 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_dma) +
613 (number_of_channels * sizeof (u32));
614 break;
615
616
617 case ACPI_RDESC_TYPE_START_DEPENDENT:
618 /*
619 * Start Dependent Functions Resource
620 * Determine if it there are two or three trailing bytes
621 */
622 buffer = byte_stream_buffer;
623 temp8 = *buffer;
624
625 if(temp8 & 0x01) {
626 bytes_consumed = 2;
627 }
628 else {
629 bytes_consumed = 1;
630 }
631
632 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_start_dpf);
633 break;
634
635
636 case ACPI_RDESC_TYPE_END_DEPENDENT:
637 /*
638 * End Dependent Functions Resource
639 */
640 bytes_consumed = 1;
641 structure_size = ACPI_RESOURCE_LENGTH;
642 break;
643
644
645 case ACPI_RDESC_TYPE_IO_PORT:
646 /*
647 * IO Port Resource
648 */
649 bytes_consumed = 8;
650 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io);
651 break;
652
653
654 case ACPI_RDESC_TYPE_FIXED_IO_PORT:
655 /*
656 * Fixed IO Port Resource
657 */
658 bytes_consumed = 4;
659 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_io);
660 break;
661
662
663 case ACPI_RDESC_TYPE_SMALL_VENDOR:
664 /*
665 * Vendor Specific Resource
666 */
667 buffer = byte_stream_buffer;
668
669 temp8 = *buffer;
670 temp8 = (u8) (temp8 & 0x7);
671 bytes_consumed = temp8 + 1;
672
673 /*
674 * Ensure a 32-bit boundary for the structure
675 */
676 temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
677 structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
678 (temp8 * sizeof (u8));
679 break;
680
681
682 case ACPI_RDESC_TYPE_END_TAG:
683 /*
684 * End Tag
685 */
686 bytes_consumed = 2;
687 structure_size = ACPI_RESOURCE_LENGTH;
688 byte_stream_buffer_length = bytes_parsed;
689 break;
690
691
692 default:
693 /*
694 * If we get here, everything is out of sync,
695 * exit with an error
696 */
697 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
698 }
699
700 /*
701 * Update the return value and counter
702 */
703 buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE (structure_size);
704 bytes_parsed += bytes_consumed;
705
706 /*
707 * Set the byte stream to point to the next resource
708 */
709 byte_stream_buffer += bytes_consumed;
710 }
711
712 /*
713 * This is the data the caller needs
714 */
715 *size_needed = buffer_size;
716 return_ACPI_STATUS (AE_OK);
717}
718
719
720/*******************************************************************************
721 *
722 * FUNCTION: acpi_rs_get_pci_routing_table_length
723 *
724 * PARAMETERS: package_object - Pointer to the package object
725 * buffer_size_needed - u32 pointer of the size buffer
726 * needed to properly return the
727 * parsed data
728 *
729 * RETURN: Status
730 *
731 * DESCRIPTION: Given a package representing a PCI routing table, this
732 * calculates the size of the corresponding linked list of
733 * descriptions.
734 *
735 ******************************************************************************/
736
737acpi_status
738acpi_rs_get_pci_routing_table_length (
739 union acpi_operand_object *package_object,
740 acpi_size *buffer_size_needed)
741{
742 u32 number_of_elements;
743 acpi_size temp_size_needed = 0;
744 union acpi_operand_object **top_object_list;
745 u32 index;
746 union acpi_operand_object *package_element;
747 union acpi_operand_object **sub_object_list;
748 u8 name_found;
749 u32 table_index;
750
751
752 ACPI_FUNCTION_TRACE ("rs_get_pci_routing_table_length");
753
754
755 number_of_elements = package_object->package.count;
756
757 /*
758 * Calculate the size of the return buffer.
759 * The base size is the number of elements * the sizes of the
760 * structures. Additional space for the strings is added below.
761 * The minus one is to subtract the size of the u8 Source[1]
762 * member because it is added below.
763 *
764 * But each PRT_ENTRY structure has a pointer to a string and
765 * the size of that string must be found.
766 */
767 top_object_list = package_object->package.elements;
768
769 for (index = 0; index < number_of_elements; index++) {
770 /*
771 * Dereference the sub-package
772 */
773 package_element = *top_object_list;
774
775 /*
776 * The sub_object_list will now point to an array of the
777 * four IRQ elements: Address, Pin, Source and source_index
778 */
779 sub_object_list = package_element->package.elements;
780
781 /*
782 * Scan the irq_table_elements for the Source Name String
783 */
784 name_found = FALSE;
785
786 for (table_index = 0; table_index < 4 && !name_found; table_index++) {
787 if ((ACPI_TYPE_STRING == ACPI_GET_OBJECT_TYPE (*sub_object_list)) ||
788 ((ACPI_TYPE_LOCAL_REFERENCE == ACPI_GET_OBJECT_TYPE (*sub_object_list)) &&
789 ((*sub_object_list)->reference.opcode == AML_INT_NAMEPATH_OP))) {
790 name_found = TRUE;
791 }
792 else {
793 /*
794 * Look at the next element
795 */
796 sub_object_list++;
797 }
798 }
799
800 temp_size_needed += (sizeof (struct acpi_pci_routing_table) - 4);
801
802 /*
803 * Was a String type found?
804 */
805 if (name_found) {
806 if (ACPI_GET_OBJECT_TYPE (*sub_object_list) == ACPI_TYPE_STRING) {
807 /*
808 * The length String.Length field does not include the
809 * terminating NULL, add 1
810 */
811 temp_size_needed += ((acpi_size) (*sub_object_list)->string.length + 1);
812 }
813 else {
814 temp_size_needed += acpi_ns_get_pathname_length (
815 (*sub_object_list)->reference.node);
816 }
817 }
818 else {
819 /*
820 * If no name was found, then this is a NULL, which is
821 * translated as a u32 zero.
822 */
823 temp_size_needed += sizeof (u32);
824 }
825
826 /* Round up the size since each element must be aligned */
827
828 temp_size_needed = ACPI_ROUND_UP_to_64_bITS (temp_size_needed);
829
830 /*
831 * Point to the next union acpi_operand_object
832 */
833 top_object_list++;
834 }
835
836 /*
837 * Adding an extra element to the end of the list, essentially a NULL terminator
838 */
839 *buffer_size_needed = temp_size_needed + sizeof (struct acpi_pci_routing_table);
840 return_ACPI_STATUS (AE_OK);
841}
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
new file mode 100644
index 000000000000..a3a0cbfda68d
--- /dev/null
+++ b/drivers/acpi/resources/rscreate.c
@@ -0,0 +1,428 @@
1/*******************************************************************************
2 *
3 * Module Name: rscreate - Create resource lists/tables
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acresrc.h>
47#include <acpi/amlcode.h>
48#include <acpi/acnamesp.h>
49
50#define _COMPONENT ACPI_RESOURCES
51 ACPI_MODULE_NAME ("rscreate")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_rs_create_resource_list
57 *
58 * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream
59 * output_buffer - Pointer to the user's buffer
60 *
61 * RETURN: Status - AE_OK if okay, else a valid acpi_status code
62 * If output_buffer is not large enough, output_buffer_length
63 * indicates how large output_buffer should be, else it
64 * indicates how may u8 elements of output_buffer are valid.
65 *
66 * DESCRIPTION: Takes the byte stream returned from a _CRS, _PRS control method
67 * execution and parses the stream to create a linked list
68 * of device resources.
69 *
70 ******************************************************************************/
71
72acpi_status
73acpi_rs_create_resource_list (
74 union acpi_operand_object *byte_stream_buffer,
75 struct acpi_buffer *output_buffer)
76{
77
78 acpi_status status;
79 u8 *byte_stream_start;
80 acpi_size list_size_needed = 0;
81 u32 byte_stream_buffer_length;
82
83
84 ACPI_FUNCTION_TRACE ("rs_create_resource_list");
85
86
87 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "byte_stream_buffer = %p\n",
88 byte_stream_buffer));
89
90 /*
91 * Params already validated, so we don't re-validate here
92 */
93 byte_stream_buffer_length = byte_stream_buffer->buffer.length;
94 byte_stream_start = byte_stream_buffer->buffer.pointer;
95
96 /*
97 * Pass the byte_stream_buffer into a module that can calculate
98 * the buffer size needed for the linked list
99 */
100 status = acpi_rs_get_list_length (byte_stream_start, byte_stream_buffer_length,
101 &list_size_needed);
102
103 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n",
104 status, (u32) list_size_needed));
105 if (ACPI_FAILURE (status)) {
106 return_ACPI_STATUS (status);
107 }
108
109 /* Validate/Allocate/Clear caller buffer */
110
111 status = acpi_ut_initialize_buffer (output_buffer, list_size_needed);
112 if (ACPI_FAILURE (status)) {
113 return_ACPI_STATUS (status);
114 }
115
116 /* Do the conversion */
117
118 status = acpi_rs_byte_stream_to_list (byte_stream_start, byte_stream_buffer_length,
119 output_buffer->pointer);
120 if (ACPI_FAILURE (status)) {
121 return_ACPI_STATUS (status);
122 }
123
124 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n",
125 output_buffer->pointer, (u32) output_buffer->length));
126 return_ACPI_STATUS (AE_OK);
127}
128
129
130/*******************************************************************************
131 *
132 * FUNCTION: acpi_rs_create_pci_routing_table
133 *
134 * PARAMETERS: package_object - Pointer to an union acpi_operand_object
135 * package
136 * output_buffer - Pointer to the user's buffer
137 *
138 * RETURN: Status AE_OK if okay, else a valid acpi_status code.
139 * If the output_buffer is too small, the error will be
140 * AE_BUFFER_OVERFLOW and output_buffer->Length will point
141 * to the size buffer needed.
142 *
143 * DESCRIPTION: Takes the union acpi_operand_object package and creates a
144 * linked list of PCI interrupt descriptions
145 *
146 * NOTE: It is the caller's responsibility to ensure that the start of the
147 * output buffer is aligned properly (if necessary).
148 *
149 ******************************************************************************/
150
151acpi_status
152acpi_rs_create_pci_routing_table (
153 union acpi_operand_object *package_object,
154 struct acpi_buffer *output_buffer)
155{
156 u8 *buffer;
157 union acpi_operand_object **top_object_list;
158 union acpi_operand_object **sub_object_list;
159 union acpi_operand_object *obj_desc;
160 acpi_size buffer_size_needed = 0;
161 u32 number_of_elements;
162 u32 index;
163 struct acpi_pci_routing_table *user_prt;
164 struct acpi_namespace_node *node;
165 acpi_status status;
166 struct acpi_buffer path_buffer;
167
168
169 ACPI_FUNCTION_TRACE ("rs_create_pci_routing_table");
170
171
172 /* Params already validated, so we don't re-validate here */
173
174 /*
175 * Get the required buffer length
176 */
177 status = acpi_rs_get_pci_routing_table_length (package_object,
178 &buffer_size_needed);
179 if (ACPI_FAILURE (status)) {
180 return_ACPI_STATUS (status);
181 }
182
183 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "buffer_size_needed = %X\n",
184 (u32) buffer_size_needed));
185
186 /* Validate/Allocate/Clear caller buffer */
187
188 status = acpi_ut_initialize_buffer (output_buffer, buffer_size_needed);
189 if (ACPI_FAILURE (status)) {
190 return_ACPI_STATUS (status);
191 }
192
193 /*
194 * Loop through the ACPI_INTERNAL_OBJECTS - Each object
195 * should be a package that in turn contains an
196 * acpi_integer Address, a u8 Pin, a Name and a u8 source_index.
197 */
198 top_object_list = package_object->package.elements;
199 number_of_elements = package_object->package.count;
200 buffer = output_buffer->pointer;
201 user_prt = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
202
203 for (index = 0; index < number_of_elements; index++) {
204 /*
205 * Point user_prt past this current structure
206 *
207 * NOTE: On the first iteration, user_prt->Length will
208 * be zero because we cleared the return buffer earlier
209 */
210 buffer += user_prt->length;
211 user_prt = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
212
213 /*
214 * Fill in the Length field with the information we have at this point.
215 * The minus four is to subtract the size of the u8 Source[4] member
216 * because it is added below.
217 */
218 user_prt->length = (sizeof (struct acpi_pci_routing_table) - 4);
219
220 /*
221 * Each element of the top-level package must also be a package
222 */
223 if (ACPI_GET_OBJECT_TYPE (*top_object_list) != ACPI_TYPE_PACKAGE) {
224 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
225 "(PRT[%X]) Need sub-package, found %s\n",
226 index, acpi_ut_get_object_type_name (*top_object_list)));
227 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
228 }
229
230 /* Each sub-package must be of length 4 */
231
232 if ((*top_object_list)->package.count != 4) {
233 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
234 "(PRT[%X]) Need package of length 4, found length %d\n",
235 index, (*top_object_list)->package.count));
236 return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT);
237 }
238
239 /*
240 * Dereference the sub-package.
241 * The sub_object_list will now point to an array of the four IRQ
242 * elements: [Address, Pin, Source, source_index]
243 */
244 sub_object_list = (*top_object_list)->package.elements;
245
246 /*
247 * 1) First subobject: Dereference the PRT.Address
248 */
249 obj_desc = sub_object_list[0];
250 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
251 user_prt->address = obj_desc->integer.value;
252 }
253 else {
254 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
255 "(PRT[%X].Address) Need Integer, found %s\n",
256 index, acpi_ut_get_object_type_name (obj_desc)));
257 return_ACPI_STATUS (AE_BAD_DATA);
258 }
259
260 /*
261 * 2) Second subobject: Dereference the PRT.Pin
262 */
263 obj_desc = sub_object_list[1];
264 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
265 user_prt->pin = (u32) obj_desc->integer.value;
266 }
267 else {
268 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
269 "(PRT[%X].Pin) Need Integer, found %s\n",
270 index, acpi_ut_get_object_type_name (obj_desc)));
271 return_ACPI_STATUS (AE_BAD_DATA);
272 }
273
274 /*
275 * 3) Third subobject: Dereference the PRT.source_name
276 */
277 obj_desc = sub_object_list[2];
278 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
279 case ACPI_TYPE_LOCAL_REFERENCE:
280
281 if (obj_desc->reference.opcode != AML_INT_NAMEPATH_OP) {
282 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
283 "(PRT[%X].Source) Need name, found reference op %X\n",
284 index, obj_desc->reference.opcode));
285 return_ACPI_STATUS (AE_BAD_DATA);
286 }
287
288 node = obj_desc->reference.node;
289
290 /* Use *remaining* length of the buffer as max for pathname */
291
292 path_buffer.length = output_buffer->length -
293 (u32) ((u8 *) user_prt->source -
294 (u8 *) output_buffer->pointer);
295 path_buffer.pointer = user_prt->source;
296
297 status = acpi_ns_handle_to_pathname ((acpi_handle) node, &path_buffer);
298
299 user_prt->length += (u32) ACPI_STRLEN (user_prt->source) + 1; /* include null terminator */
300 break;
301
302
303 case ACPI_TYPE_STRING:
304
305 ACPI_STRCPY (user_prt->source, obj_desc->string.pointer);
306
307 /* Add to the Length field the length of the string (add 1 for terminator) */
308
309 user_prt->length += obj_desc->string.length + 1;
310 break;
311
312
313 case ACPI_TYPE_INTEGER:
314 /*
315 * If this is a number, then the Source Name is NULL, since the
316 * entire buffer was zeroed out, we can leave this alone.
317 *
318 * Add to the Length field the length of the u32 NULL
319 */
320 user_prt->length += sizeof (u32);
321 break;
322
323
324 default:
325
326 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
327 "(PRT[%X].Source) Need Ref/String/Integer, found %s\n",
328 index, acpi_ut_get_object_type_name (obj_desc)));
329 return_ACPI_STATUS (AE_BAD_DATA);
330 }
331
332 /* Now align the current length */
333
334 user_prt->length = (u32) ACPI_ROUND_UP_to_64_bITS (user_prt->length);
335
336 /*
337 * 4) Fourth subobject: Dereference the PRT.source_index
338 */
339 obj_desc = sub_object_list[3];
340 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
341 user_prt->source_index = (u32) obj_desc->integer.value;
342 }
343 else {
344 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
345 "(PRT[%X].source_index) Need Integer, found %s\n",
346 index, acpi_ut_get_object_type_name (obj_desc)));
347 return_ACPI_STATUS (AE_BAD_DATA);
348 }
349
350 /* Point to the next union acpi_operand_object in the top level package */
351
352 top_object_list++;
353 }
354
355 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n",
356 output_buffer->pointer, (u32) output_buffer->length));
357 return_ACPI_STATUS (AE_OK);
358}
359
360
361/*******************************************************************************
362 *
363 * FUNCTION: acpi_rs_create_byte_stream
364 *
365 * PARAMETERS: linked_list_buffer - Pointer to the resource linked list
366 * output_buffer - Pointer to the user's buffer
367 *
368 * RETURN: Status AE_OK if okay, else a valid acpi_status code.
369 * If the output_buffer is too small, the error will be
370 * AE_BUFFER_OVERFLOW and output_buffer->Length will point
371 * to the size buffer needed.
372 *
373 * DESCRIPTION: Takes the linked list of device resources and
374 * creates a bytestream to be used as input for the
375 * _SRS control method.
376 *
377 ******************************************************************************/
378
379acpi_status
380acpi_rs_create_byte_stream (
381 struct acpi_resource *linked_list_buffer,
382 struct acpi_buffer *output_buffer)
383{
384 acpi_status status;
385 acpi_size byte_stream_size_needed = 0;
386
387
388 ACPI_FUNCTION_TRACE ("rs_create_byte_stream");
389
390
391 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "linked_list_buffer = %p\n",
392 linked_list_buffer));
393
394 /*
395 * Params already validated, so we don't re-validate here
396 *
397 * Pass the linked_list_buffer into a module that calculates
398 * the buffer size needed for the byte stream.
399 */
400 status = acpi_rs_get_byte_stream_length (linked_list_buffer,
401 &byte_stream_size_needed);
402
403 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "byte_stream_size_needed=%X, %s\n",
404 (u32) byte_stream_size_needed, acpi_format_exception (status)));
405 if (ACPI_FAILURE (status)) {
406 return_ACPI_STATUS (status);
407 }
408
409 /* Validate/Allocate/Clear caller buffer */
410
411 status = acpi_ut_initialize_buffer (output_buffer, byte_stream_size_needed);
412 if (ACPI_FAILURE (status)) {
413 return_ACPI_STATUS (status);
414 }
415
416 /* Do the conversion */
417
418 status = acpi_rs_list_to_byte_stream (linked_list_buffer, byte_stream_size_needed,
419 output_buffer->pointer);
420 if (ACPI_FAILURE (status)) {
421 return_ACPI_STATUS (status);
422 }
423
424 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n",
425 output_buffer->pointer, (u32) output_buffer->length));
426 return_ACPI_STATUS (AE_OK);
427}
428
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c
new file mode 100644
index 000000000000..eef1b1f2c685
--- /dev/null
+++ b/drivers/acpi/resources/rsdump.c
@@ -0,0 +1,1150 @@
1/*******************************************************************************
2 *
3 * Module Name: rsdump - Functions to display the resource structures.
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acresrc.h>
47
48#define _COMPONENT ACPI_RESOURCES
49 ACPI_MODULE_NAME ("rsdump")
50
51
52#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_rs_dump_irq
57 *
58 * PARAMETERS: Data - pointer to the resource structure to dump.
59 *
60 * RETURN: None
61 *
62 * DESCRIPTION: Prints out the various members of the Data structure type.
63 *
64 ******************************************************************************/
65
66void
67acpi_rs_dump_irq (
68 union acpi_resource_data *data)
69{
70 struct acpi_resource_irq *irq_data = (struct acpi_resource_irq *) data;
71 u8 index = 0;
72
73
74 ACPI_FUNCTION_ENTRY ();
75
76
77 acpi_os_printf ("IRQ Resource\n");
78
79 acpi_os_printf (" %s Triggered\n",
80 ACPI_LEVEL_SENSITIVE == irq_data->edge_level ? "Level" : "Edge");
81
82 acpi_os_printf (" Active %s\n",
83 ACPI_ACTIVE_LOW == irq_data->active_high_low ? "Low" : "High");
84
85 acpi_os_printf (" %s\n",
86 ACPI_SHARED == irq_data->shared_exclusive ? "Shared" : "Exclusive");
87
88 acpi_os_printf (" %X Interrupts ( ", irq_data->number_of_interrupts);
89
90 for (index = 0; index < irq_data->number_of_interrupts; index++) {
91 acpi_os_printf ("%X ", irq_data->interrupts[index]);
92 }
93
94 acpi_os_printf (")\n");
95 return;
96}
97
98
99/*******************************************************************************
100 *
101 * FUNCTION: acpi_rs_dump_dma
102 *
103 * PARAMETERS: Data - pointer to the resource structure to dump.
104 *
105 * RETURN: None
106 *
107 * DESCRIPTION: Prints out the various members of the Data structure type.
108 *
109 ******************************************************************************/
110
111void
112acpi_rs_dump_dma (
113 union acpi_resource_data *data)
114{
115 struct acpi_resource_dma *dma_data = (struct acpi_resource_dma *) data;
116 u8 index = 0;
117
118
119 ACPI_FUNCTION_ENTRY ();
120
121
122 acpi_os_printf ("DMA Resource\n");
123
124 switch (dma_data->type) {
125 case ACPI_COMPATIBILITY:
126 acpi_os_printf (" Compatibility mode\n");
127 break;
128
129 case ACPI_TYPE_A:
130 acpi_os_printf (" Type A\n");
131 break;
132
133 case ACPI_TYPE_B:
134 acpi_os_printf (" Type B\n");
135 break;
136
137 case ACPI_TYPE_F:
138 acpi_os_printf (" Type F\n");
139 break;
140
141 default:
142 acpi_os_printf (" Invalid DMA type\n");
143 break;
144 }
145
146 acpi_os_printf (" %sBus Master\n",
147 ACPI_BUS_MASTER == dma_data->bus_master ? "" : "Not a ");
148
149
150 switch (dma_data->transfer) {
151 case ACPI_TRANSFER_8:
152 acpi_os_printf (" 8-bit only transfer\n");
153 break;
154
155 case ACPI_TRANSFER_8_16:
156 acpi_os_printf (" 8 and 16-bit transfer\n");
157 break;
158
159 case ACPI_TRANSFER_16:
160 acpi_os_printf (" 16 bit only transfer\n");
161 break;
162
163 default:
164 acpi_os_printf (" Invalid transfer preference\n");
165 break;
166 }
167
168 acpi_os_printf (" Number of Channels: %X ( ", dma_data->number_of_channels);
169
170 for (index = 0; index < dma_data->number_of_channels; index++) {
171 acpi_os_printf ("%X ", dma_data->channels[index]);
172 }
173
174 acpi_os_printf (")\n");
175 return;
176}
177
178
179/*******************************************************************************
180 *
181 * FUNCTION: acpi_rs_dump_start_depend_fns
182 *
183 * PARAMETERS: Data - pointer to the resource structure to dump.
184 *
185 * RETURN: None
186 *
187 * DESCRIPTION: Prints out the various members of the Data structure type.
188 *
189 ******************************************************************************/
190
191void
192acpi_rs_dump_start_depend_fns (
193 union acpi_resource_data *data)
194{
195 struct acpi_resource_start_dpf *sdf_data = (struct acpi_resource_start_dpf *) data;
196
197
198 ACPI_FUNCTION_ENTRY ();
199
200
201 acpi_os_printf ("Start Dependent Functions Resource\n");
202
203 switch (sdf_data->compatibility_priority) {
204 case ACPI_GOOD_CONFIGURATION:
205 acpi_os_printf (" Good configuration\n");
206 break;
207
208 case ACPI_ACCEPTABLE_CONFIGURATION:
209 acpi_os_printf (" Acceptable configuration\n");
210 break;
211
212 case ACPI_SUB_OPTIMAL_CONFIGURATION:
213 acpi_os_printf (" Sub-optimal configuration\n");
214 break;
215
216 default:
217 acpi_os_printf (" Invalid compatibility priority\n");
218 break;
219 }
220
221 switch(sdf_data->performance_robustness) {
222 case ACPI_GOOD_CONFIGURATION:
223 acpi_os_printf (" Good configuration\n");
224 break;
225
226 case ACPI_ACCEPTABLE_CONFIGURATION:
227 acpi_os_printf (" Acceptable configuration\n");
228 break;
229
230 case ACPI_SUB_OPTIMAL_CONFIGURATION:
231 acpi_os_printf (" Sub-optimal configuration\n");
232 break;
233
234 default:
235 acpi_os_printf (" Invalid performance "
236 "robustness preference\n");
237 break;
238 }
239
240 return;
241}
242
243
244/*******************************************************************************
245 *
246 * FUNCTION: acpi_rs_dump_io
247 *
248 * PARAMETERS: Data - pointer to the resource structure to dump.
249 *
250 * RETURN: None
251 *
252 * DESCRIPTION: Prints out the various members of the Data structure type.
253 *
254 ******************************************************************************/
255
256void
257acpi_rs_dump_io (
258 union acpi_resource_data *data)
259{
260 struct acpi_resource_io *io_data = (struct acpi_resource_io *) data;
261
262
263 ACPI_FUNCTION_ENTRY ();
264
265
266 acpi_os_printf ("Io Resource\n");
267
268 acpi_os_printf (" %d bit decode\n",
269 ACPI_DECODE_16 == io_data->io_decode ? 16 : 10);
270
271 acpi_os_printf (" Range minimum base: %08X\n",
272 io_data->min_base_address);
273
274 acpi_os_printf (" Range maximum base: %08X\n",
275 io_data->max_base_address);
276
277 acpi_os_printf (" Alignment: %08X\n",
278 io_data->alignment);
279
280 acpi_os_printf (" Range Length: %08X\n",
281 io_data->range_length);
282
283 return;
284}
285
286
287/*******************************************************************************
288 *
289 * FUNCTION: acpi_rs_dump_fixed_io
290 *
291 * PARAMETERS: Data - pointer to the resource structure to dump.
292 *
293 * RETURN: None
294 *
295 * DESCRIPTION: Prints out the various members of the Data structure type.
296 *
297 ******************************************************************************/
298
299void
300acpi_rs_dump_fixed_io (
301 union acpi_resource_data *data)
302{
303 struct acpi_resource_fixed_io *fixed_io_data = (struct acpi_resource_fixed_io *) data;
304
305
306 ACPI_FUNCTION_ENTRY ();
307
308
309 acpi_os_printf ("Fixed Io Resource\n");
310 acpi_os_printf (" Range base address: %08X",
311 fixed_io_data->base_address);
312
313 acpi_os_printf (" Range length: %08X",
314 fixed_io_data->range_length);
315
316 return;
317}
318
319
320/*******************************************************************************
321 *
322 * FUNCTION: acpi_rs_dump_vendor_specific
323 *
324 * PARAMETERS: Data - pointer to the resource structure to dump.
325 *
326 * RETURN: None
327 *
328 * DESCRIPTION: Prints out the various members of the Data structure type.
329 *
330 ******************************************************************************/
331
332void
333acpi_rs_dump_vendor_specific (
334 union acpi_resource_data *data)
335{
336 struct acpi_resource_vendor *vendor_data = (struct acpi_resource_vendor *) data;
337 u16 index = 0;
338
339
340 ACPI_FUNCTION_ENTRY ();
341
342
343 acpi_os_printf ("Vendor Specific Resource\n");
344
345 acpi_os_printf (" Length: %08X\n", vendor_data->length);
346
347 for (index = 0; index < vendor_data->length; index++) {
348 acpi_os_printf (" Byte %X: %08X\n",
349 index, vendor_data->reserved[index]);
350 }
351
352 return;
353}
354
355
356/*******************************************************************************
357 *
358 * FUNCTION: acpi_rs_dump_memory24
359 *
360 * PARAMETERS: Data - pointer to the resource structure to dump.
361 *
362 * RETURN: None
363 *
364 * DESCRIPTION: Prints out the various members of the Data structure type.
365 *
366 ******************************************************************************/
367
368void
369acpi_rs_dump_memory24 (
370 union acpi_resource_data *data)
371{
372 struct acpi_resource_mem24 *memory24_data = (struct acpi_resource_mem24 *) data;
373
374
375 ACPI_FUNCTION_ENTRY ();
376
377
378 acpi_os_printf ("24-Bit Memory Range Resource\n");
379
380 acpi_os_printf (" Read%s\n",
381 ACPI_READ_WRITE_MEMORY ==
382 memory24_data->read_write_attribute ?
383 "/Write" : " only");
384
385 acpi_os_printf (" Range minimum base: %08X\n",
386 memory24_data->min_base_address);
387
388 acpi_os_printf (" Range maximum base: %08X\n",
389 memory24_data->max_base_address);
390
391 acpi_os_printf (" Alignment: %08X\n",
392 memory24_data->alignment);
393
394 acpi_os_printf (" Range length: %08X\n",
395 memory24_data->range_length);
396
397 return;
398}
399
400
401/*******************************************************************************
402 *
403 * FUNCTION: acpi_rs_dump_memory32
404 *
405 * PARAMETERS: Data - pointer to the resource structure to dump.
406 *
407 * RETURN: None
408 *
409 * DESCRIPTION: Prints out the various members of the Data structure type.
410 *
411 ******************************************************************************/
412
413void
414acpi_rs_dump_memory32 (
415 union acpi_resource_data *data)
416{
417 struct acpi_resource_mem32 *memory32_data = (struct acpi_resource_mem32 *) data;
418
419
420 ACPI_FUNCTION_ENTRY ();
421
422
423 acpi_os_printf ("32-Bit Memory Range Resource\n");
424
425 acpi_os_printf (" Read%s\n",
426 ACPI_READ_WRITE_MEMORY ==
427 memory32_data->read_write_attribute ?
428 "/Write" : " only");
429
430 acpi_os_printf (" Range minimum base: %08X\n",
431 memory32_data->min_base_address);
432
433 acpi_os_printf (" Range maximum base: %08X\n",
434 memory32_data->max_base_address);
435
436 acpi_os_printf (" Alignment: %08X\n",
437 memory32_data->alignment);
438
439 acpi_os_printf (" Range length: %08X\n",
440 memory32_data->range_length);
441
442 return;
443}
444
445
446/*******************************************************************************
447 *
448 * FUNCTION: acpi_rs_dump_fixed_memory32
449 *
450 * PARAMETERS: Data - pointer to the resource structure to dump.
451 *
452 * RETURN:
453 *
454 * DESCRIPTION: Prints out the various members of the Data structure type.
455 *
456 ******************************************************************************/
457
458void
459acpi_rs_dump_fixed_memory32 (
460 union acpi_resource_data *data)
461{
462 struct acpi_resource_fixed_mem32 *fixed_memory32_data = (struct acpi_resource_fixed_mem32 *) data;
463
464
465 ACPI_FUNCTION_ENTRY ();
466
467
468 acpi_os_printf ("32-Bit Fixed Location Memory Range Resource\n");
469
470 acpi_os_printf (" Read%s\n",
471 ACPI_READ_WRITE_MEMORY ==
472 fixed_memory32_data->read_write_attribute ?
473 "/Write" : " Only");
474
475 acpi_os_printf (" Range base address: %08X\n",
476 fixed_memory32_data->range_base_address);
477
478 acpi_os_printf (" Range length: %08X\n",
479 fixed_memory32_data->range_length);
480
481 return;
482}
483
484
485/*******************************************************************************
486 *
487 * FUNCTION: acpi_rs_dump_address16
488 *
489 * PARAMETERS: Data - pointer to the resource structure to dump.
490 *
491 * RETURN: None
492 *
493 * DESCRIPTION: Prints out the various members of the Data structure type.
494 *
495 ******************************************************************************/
496
497void
498acpi_rs_dump_address16 (
499 union acpi_resource_data *data)
500{
501 struct acpi_resource_address16 *address16_data = (struct acpi_resource_address16 *) data;
502
503
504 ACPI_FUNCTION_ENTRY ();
505
506
507 acpi_os_printf ("16-Bit Address Space Resource\n");
508 acpi_os_printf (" Resource Type: ");
509
510 switch (address16_data->resource_type) {
511 case ACPI_MEMORY_RANGE:
512
513 acpi_os_printf ("Memory Range\n");
514
515 switch (address16_data->attribute.memory.cache_attribute) {
516 case ACPI_NON_CACHEABLE_MEMORY:
517 acpi_os_printf (" Type Specific: "
518 "Noncacheable memory\n");
519 break;
520
521 case ACPI_CACHABLE_MEMORY:
522 acpi_os_printf (" Type Specific: "
523 "Cacheable memory\n");
524 break;
525
526 case ACPI_WRITE_COMBINING_MEMORY:
527 acpi_os_printf (" Type Specific: "
528 "Write-combining memory\n");
529 break;
530
531 case ACPI_PREFETCHABLE_MEMORY:
532 acpi_os_printf (" Type Specific: "
533 "Prefetchable memory\n");
534 break;
535
536 default:
537 acpi_os_printf (" Type Specific: "
538 "Invalid cache attribute\n");
539 break;
540 }
541
542 acpi_os_printf (" Type Specific: Read%s\n",
543 ACPI_READ_WRITE_MEMORY ==
544 address16_data->attribute.memory.read_write_attribute ?
545 "/Write" : " Only");
546 break;
547
548 case ACPI_IO_RANGE:
549
550 acpi_os_printf ("I/O Range\n");
551
552 switch (address16_data->attribute.io.range_attribute) {
553 case ACPI_NON_ISA_ONLY_RANGES:
554 acpi_os_printf (" Type Specific: "
555 "Non-ISA Io Addresses\n");
556 break;
557
558 case ACPI_ISA_ONLY_RANGES:
559 acpi_os_printf (" Type Specific: "
560 "ISA Io Addresses\n");
561 break;
562
563 case ACPI_ENTIRE_RANGE:
564 acpi_os_printf (" Type Specific: "
565 "ISA and non-ISA Io Addresses\n");
566 break;
567
568 default:
569 acpi_os_printf (" Type Specific: "
570 "Invalid range attribute\n");
571 break;
572 }
573
574 acpi_os_printf (" Type Specific: %s Translation\n",
575 ACPI_SPARSE_TRANSLATION ==
576 address16_data->attribute.io.translation_attribute ?
577 "Sparse" : "Dense");
578 break;
579
580 case ACPI_BUS_NUMBER_RANGE:
581
582 acpi_os_printf ("Bus Number Range\n");
583 break;
584
585 default:
586
587 acpi_os_printf ("0x%2.2X\n", address16_data->resource_type);
588 break;
589 }
590
591 acpi_os_printf (" Resource %s\n",
592 ACPI_CONSUMER == address16_data->producer_consumer ?
593 "Consumer" : "Producer");
594
595 acpi_os_printf (" %s decode\n",
596 ACPI_SUB_DECODE == address16_data->decode ?
597 "Subtractive" : "Positive");
598
599 acpi_os_printf (" Min address is %s fixed\n",
600 ACPI_ADDRESS_FIXED == address16_data->min_address_fixed ?
601 "" : "not");
602
603 acpi_os_printf (" Max address is %s fixed\n",
604 ACPI_ADDRESS_FIXED == address16_data->max_address_fixed ?
605 "" : "not");
606
607 acpi_os_printf (" Granularity: %08X\n",
608 address16_data->granularity);
609
610 acpi_os_printf (" Address range min: %08X\n",
611 address16_data->min_address_range);
612
613 acpi_os_printf (" Address range max: %08X\n",
614 address16_data->max_address_range);
615
616 acpi_os_printf (" Address translation offset: %08X\n",
617 address16_data->address_translation_offset);
618
619 acpi_os_printf (" Address Length: %08X\n",
620 address16_data->address_length);
621
622 if (0xFF != address16_data->resource_source.index) {
623 acpi_os_printf (" Resource Source Index: %X\n",
624 address16_data->resource_source.index);
625 acpi_os_printf (" Resource Source: %s\n",
626 address16_data->resource_source.string_ptr);
627 }
628
629 return;
630}
631
632
633/*******************************************************************************
634 *
635 * FUNCTION: acpi_rs_dump_address32
636 *
637 * PARAMETERS: Data - pointer to the resource structure to dump.
638 *
639 * RETURN: None
640 *
641 * DESCRIPTION: Prints out the various members of the Data structure type.
642 *
643 ******************************************************************************/
644
645void
646acpi_rs_dump_address32 (
647 union acpi_resource_data *data)
648{
649 struct acpi_resource_address32 *address32_data = (struct acpi_resource_address32 *) data;
650
651
652 ACPI_FUNCTION_ENTRY ();
653
654
655 acpi_os_printf ("32-Bit Address Space Resource\n");
656
657 switch (address32_data->resource_type) {
658 case ACPI_MEMORY_RANGE:
659
660 acpi_os_printf (" Resource Type: Memory Range\n");
661
662 switch (address32_data->attribute.memory.cache_attribute) {
663 case ACPI_NON_CACHEABLE_MEMORY:
664 acpi_os_printf (" Type Specific: "
665 "Noncacheable memory\n");
666 break;
667
668 case ACPI_CACHABLE_MEMORY:
669 acpi_os_printf (" Type Specific: "
670 "Cacheable memory\n");
671 break;
672
673 case ACPI_WRITE_COMBINING_MEMORY:
674 acpi_os_printf (" Type Specific: "
675 "Write-combining memory\n");
676 break;
677
678 case ACPI_PREFETCHABLE_MEMORY:
679 acpi_os_printf (" Type Specific: "
680 "Prefetchable memory\n");
681 break;
682
683 default:
684 acpi_os_printf (" Type Specific: "
685 "Invalid cache attribute\n");
686 break;
687 }
688
689 acpi_os_printf (" Type Specific: Read%s\n",
690 ACPI_READ_WRITE_MEMORY ==
691 address32_data->attribute.memory.read_write_attribute ?
692 "/Write" : " Only");
693 break;
694
695 case ACPI_IO_RANGE:
696
697 acpi_os_printf (" Resource Type: Io Range\n");
698
699 switch (address32_data->attribute.io.range_attribute) {
700 case ACPI_NON_ISA_ONLY_RANGES:
701 acpi_os_printf (" Type Specific: "
702 "Non-ISA Io Addresses\n");
703 break;
704
705 case ACPI_ISA_ONLY_RANGES:
706 acpi_os_printf (" Type Specific: "
707 "ISA Io Addresses\n");
708 break;
709
710 case ACPI_ENTIRE_RANGE:
711 acpi_os_printf (" Type Specific: "
712 "ISA and non-ISA Io Addresses\n");
713 break;
714
715 default:
716 acpi_os_printf (" Type Specific: "
717 "Invalid Range attribute");
718 break;
719 }
720
721 acpi_os_printf (" Type Specific: %s Translation\n",
722 ACPI_SPARSE_TRANSLATION ==
723 address32_data->attribute.io.translation_attribute ?
724 "Sparse" : "Dense");
725 break;
726
727 case ACPI_BUS_NUMBER_RANGE:
728
729 acpi_os_printf (" Resource Type: Bus Number Range\n");
730 break;
731
732 default:
733
734 acpi_os_printf (" Resource Type: 0x%2.2X\n", address32_data->resource_type);
735 break;
736 }
737
738 acpi_os_printf (" Resource %s\n",
739 ACPI_CONSUMER == address32_data->producer_consumer ?
740 "Consumer" : "Producer");
741
742 acpi_os_printf (" %s decode\n",
743 ACPI_SUB_DECODE == address32_data->decode ?
744 "Subtractive" : "Positive");
745
746 acpi_os_printf (" Min address is %s fixed\n",
747 ACPI_ADDRESS_FIXED == address32_data->min_address_fixed ?
748 "" : "not ");
749
750 acpi_os_printf (" Max address is %s fixed\n",
751 ACPI_ADDRESS_FIXED == address32_data->max_address_fixed ?
752 "" : "not ");
753
754 acpi_os_printf (" Granularity: %08X\n",
755 address32_data->granularity);
756
757 acpi_os_printf (" Address range min: %08X\n",
758 address32_data->min_address_range);
759
760 acpi_os_printf (" Address range max: %08X\n",
761 address32_data->max_address_range);
762
763 acpi_os_printf (" Address translation offset: %08X\n",
764 address32_data->address_translation_offset);
765
766 acpi_os_printf (" Address Length: %08X\n",
767 address32_data->address_length);
768
769 if(0xFF != address32_data->resource_source.index) {
770 acpi_os_printf (" Resource Source Index: %X\n",
771 address32_data->resource_source.index);
772 acpi_os_printf (" Resource Source: %s\n",
773 address32_data->resource_source.string_ptr);
774 }
775
776 return;
777}
778
779
780/*******************************************************************************
781 *
782 * FUNCTION: acpi_rs_dump_address64
783 *
784 * PARAMETERS: Data - pointer to the resource structure to dump.
785 *
786 * RETURN: None
787 *
788 * DESCRIPTION: Prints out the various members of the Data structure type.
789 *
790 ******************************************************************************/
791
792void
793acpi_rs_dump_address64 (
794 union acpi_resource_data *data)
795{
796 struct acpi_resource_address64 *address64_data = (struct acpi_resource_address64 *) data;
797
798
799 ACPI_FUNCTION_ENTRY ();
800
801
802 acpi_os_printf ("64-Bit Address Space Resource\n");
803
804 switch (address64_data->resource_type) {
805 case ACPI_MEMORY_RANGE:
806
807 acpi_os_printf (" Resource Type: Memory Range\n");
808
809 switch (address64_data->attribute.memory.cache_attribute) {
810 case ACPI_NON_CACHEABLE_MEMORY:
811 acpi_os_printf (" Type Specific: "
812 "Noncacheable memory\n");
813 break;
814
815 case ACPI_CACHABLE_MEMORY:
816 acpi_os_printf (" Type Specific: "
817 "Cacheable memory\n");
818 break;
819
820 case ACPI_WRITE_COMBINING_MEMORY:
821 acpi_os_printf (" Type Specific: "
822 "Write-combining memory\n");
823 break;
824
825 case ACPI_PREFETCHABLE_MEMORY:
826 acpi_os_printf (" Type Specific: "
827 "Prefetchable memory\n");
828 break;
829
830 default:
831 acpi_os_printf (" Type Specific: "
832 "Invalid cache attribute\n");
833 break;
834 }
835
836 acpi_os_printf (" Type Specific: Read%s\n",
837 ACPI_READ_WRITE_MEMORY ==
838 address64_data->attribute.memory.read_write_attribute ?
839 "/Write" : " Only");
840 break;
841
842 case ACPI_IO_RANGE:
843
844 acpi_os_printf (" Resource Type: Io Range\n");
845
846 switch (address64_data->attribute.io.range_attribute) {
847 case ACPI_NON_ISA_ONLY_RANGES:
848 acpi_os_printf (" Type Specific: "
849 "Non-ISA Io Addresses\n");
850 break;
851
852 case ACPI_ISA_ONLY_RANGES:
853 acpi_os_printf (" Type Specific: "
854 "ISA Io Addresses\n");
855 break;
856
857 case ACPI_ENTIRE_RANGE:
858 acpi_os_printf (" Type Specific: "
859 "ISA and non-ISA Io Addresses\n");
860 break;
861
862 default:
863 acpi_os_printf (" Type Specific: "
864 "Invalid Range attribute");
865 break;
866 }
867
868 acpi_os_printf (" Type Specific: %s Translation\n",
869 ACPI_SPARSE_TRANSLATION ==
870 address64_data->attribute.io.translation_attribute ?
871 "Sparse" : "Dense");
872 break;
873
874 case ACPI_BUS_NUMBER_RANGE:
875
876 acpi_os_printf (" Resource Type: Bus Number Range\n");
877 break;
878
879 default:
880
881 acpi_os_printf (" Resource Type: 0x%2.2X\n", address64_data->resource_type);
882 break;
883 }
884
885 acpi_os_printf (" Resource %s\n",
886 ACPI_CONSUMER == address64_data->producer_consumer ?
887 "Consumer" : "Producer");
888
889 acpi_os_printf (" %s decode\n",
890 ACPI_SUB_DECODE == address64_data->decode ?
891 "Subtractive" : "Positive");
892
893 acpi_os_printf (" Min address is %s fixed\n",
894 ACPI_ADDRESS_FIXED == address64_data->min_address_fixed ?
895 "" : "not ");
896
897 acpi_os_printf (" Max address is %s fixed\n",
898 ACPI_ADDRESS_FIXED == address64_data->max_address_fixed ?
899 "" : "not ");
900
901 acpi_os_printf (" Granularity: %8.8X%8.8X\n",
902 ACPI_FORMAT_UINT64 (address64_data->granularity));
903
904 acpi_os_printf (" Address range min: %8.8X%8.8X\n",
905 ACPI_FORMAT_UINT64 (address64_data->min_address_range));
906
907 acpi_os_printf (" Address range max: %8.8X%8.8X\n",
908 ACPI_FORMAT_UINT64 (address64_data->max_address_range));
909
910 acpi_os_printf (" Address translation offset: %8.8X%8.8X\n",
911 ACPI_FORMAT_UINT64 (address64_data->address_translation_offset));
912
913 acpi_os_printf (" Address Length: %8.8X%8.8X\n",
914 ACPI_FORMAT_UINT64 (address64_data->address_length));
915
916 acpi_os_printf (" Type Specific Attributes: %8.8X%8.8X\n",
917 ACPI_FORMAT_UINT64 (address64_data->type_specific_attributes));
918
919 if (0xFF != address64_data->resource_source.index) {
920 acpi_os_printf (" Resource Source Index: %X\n",
921 address64_data->resource_source.index);
922 acpi_os_printf (" Resource Source: %s\n",
923 address64_data->resource_source.string_ptr);
924 }
925
926 return;
927}
928
929
930/*******************************************************************************
931 *
932 * FUNCTION: acpi_rs_dump_extended_irq
933 *
934 * PARAMETERS: Data - pointer to the resource structure to dump.
935 *
936 * RETURN: None
937 *
938 * DESCRIPTION: Prints out the various members of the Data structure type.
939 *
940 ******************************************************************************/
941
942void
943acpi_rs_dump_extended_irq (
944 union acpi_resource_data *data)
945{
946 struct acpi_resource_ext_irq *ext_irq_data = (struct acpi_resource_ext_irq *) data;
947 u8 index = 0;
948
949
950 ACPI_FUNCTION_ENTRY ();
951
952
953 acpi_os_printf ("Extended IRQ Resource\n");
954
955 acpi_os_printf (" Resource %s\n",
956 ACPI_CONSUMER == ext_irq_data->producer_consumer ?
957 "Consumer" : "Producer");
958
959 acpi_os_printf (" %s\n",
960 ACPI_LEVEL_SENSITIVE == ext_irq_data->edge_level ?
961 "Level" : "Edge");
962
963 acpi_os_printf (" Active %s\n",
964 ACPI_ACTIVE_LOW == ext_irq_data->active_high_low ?
965 "low" : "high");
966
967 acpi_os_printf (" %s\n",
968 ACPI_SHARED == ext_irq_data->shared_exclusive ?
969 "Shared" : "Exclusive");
970
971 acpi_os_printf (" Interrupts : %X ( ",
972 ext_irq_data->number_of_interrupts);
973
974 for (index = 0; index < ext_irq_data->number_of_interrupts; index++) {
975 acpi_os_printf ("%X ", ext_irq_data->interrupts[index]);
976 }
977
978 acpi_os_printf (")\n");
979
980 if(0xFF != ext_irq_data->resource_source.index) {
981 acpi_os_printf (" Resource Source Index: %X",
982 ext_irq_data->resource_source.index);
983 acpi_os_printf (" Resource Source: %s",
984 ext_irq_data->resource_source.string_ptr);
985 }
986
987 return;
988}
989
990
991/*******************************************************************************
992 *
993 * FUNCTION: acpi_rs_dump_resource_list
994 *
995 * PARAMETERS: Data - pointer to the resource structure to dump.
996 *
997 * RETURN: None
998 *
999 * DESCRIPTION: Dispatches the structure to the correct dump routine.
1000 *
1001 ******************************************************************************/
1002
1003void
1004acpi_rs_dump_resource_list (
1005 struct acpi_resource *resource)
1006{
1007 u8 count = 0;
1008 u8 done = FALSE;
1009
1010
1011 ACPI_FUNCTION_ENTRY ();
1012
1013
1014 if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) {
1015 while (!done) {
1016 acpi_os_printf ("Resource structure %X.\n", count++);
1017
1018 switch (resource->id) {
1019 case ACPI_RSTYPE_IRQ:
1020 acpi_rs_dump_irq (&resource->data);
1021 break;
1022
1023 case ACPI_RSTYPE_DMA:
1024 acpi_rs_dump_dma (&resource->data);
1025 break;
1026
1027 case ACPI_RSTYPE_START_DPF:
1028 acpi_rs_dump_start_depend_fns (&resource->data);
1029 break;
1030
1031 case ACPI_RSTYPE_END_DPF:
1032 acpi_os_printf ("end_dependent_functions Resource\n");
1033 /* acpi_rs_dump_end_dependent_functions (Resource->Data);*/
1034 break;
1035
1036 case ACPI_RSTYPE_IO:
1037 acpi_rs_dump_io (&resource->data);
1038 break;
1039
1040 case ACPI_RSTYPE_FIXED_IO:
1041 acpi_rs_dump_fixed_io (&resource->data);
1042 break;
1043
1044 case ACPI_RSTYPE_VENDOR:
1045 acpi_rs_dump_vendor_specific (&resource->data);
1046 break;
1047
1048 case ACPI_RSTYPE_END_TAG:
1049 /*rs_dump_end_tag (Resource->Data);*/
1050 acpi_os_printf ("end_tag Resource\n");
1051 done = TRUE;
1052 break;
1053
1054 case ACPI_RSTYPE_MEM24:
1055 acpi_rs_dump_memory24 (&resource->data);
1056 break;
1057
1058 case ACPI_RSTYPE_MEM32:
1059 acpi_rs_dump_memory32 (&resource->data);
1060 break;
1061
1062 case ACPI_RSTYPE_FIXED_MEM32:
1063 acpi_rs_dump_fixed_memory32 (&resource->data);
1064 break;
1065
1066 case ACPI_RSTYPE_ADDRESS16:
1067 acpi_rs_dump_address16 (&resource->data);
1068 break;
1069
1070 case ACPI_RSTYPE_ADDRESS32:
1071 acpi_rs_dump_address32 (&resource->data);
1072 break;
1073
1074 case ACPI_RSTYPE_ADDRESS64:
1075 acpi_rs_dump_address64 (&resource->data);
1076 break;
1077
1078 case ACPI_RSTYPE_EXT_IRQ:
1079 acpi_rs_dump_extended_irq (&resource->data);
1080 break;
1081
1082 default:
1083 acpi_os_printf ("Invalid resource type\n");
1084 break;
1085
1086 }
1087
1088 resource = ACPI_PTR_ADD (struct acpi_resource, resource, resource->length);
1089 }
1090 }
1091
1092 return;
1093}
1094
1095/*******************************************************************************
1096 *
1097 * FUNCTION: acpi_rs_dump_irq_list
1098 *
1099 * PARAMETERS: Data - pointer to the routing table to dump.
1100 *
1101 * RETURN: None
1102 *
1103 * DESCRIPTION: Dispatches the structures to the correct dump routine.
1104 *
1105 ******************************************************************************/
1106
1107void
1108acpi_rs_dump_irq_list (
1109 u8 *route_table)
1110{
1111 u8 *buffer = route_table;
1112 u8 count = 0;
1113 u8 done = FALSE;
1114 struct acpi_pci_routing_table *prt_element;
1115
1116
1117 ACPI_FUNCTION_ENTRY ();
1118
1119
1120 if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) {
1121 prt_element = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
1122
1123 while (!done) {
1124 acpi_os_printf ("PCI IRQ Routing Table structure %X.\n", count++);
1125
1126 acpi_os_printf (" Address: %8.8X%8.8X\n",
1127 ACPI_FORMAT_UINT64 (prt_element->address));
1128
1129 acpi_os_printf (" Pin: %X\n", prt_element->pin);
1130
1131 acpi_os_printf (" Source: %s\n", prt_element->source);
1132
1133 acpi_os_printf (" source_index: %X\n",
1134 prt_element->source_index);
1135
1136 buffer += prt_element->length;
1137
1138 prt_element = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
1139
1140 if(0 == prt_element->length) {
1141 done = TRUE;
1142 }
1143 }
1144 }
1145
1146 return;
1147}
1148
1149#endif
1150
diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c
new file mode 100644
index 000000000000..972c746d37e4
--- /dev/null
+++ b/drivers/acpi/resources/rsio.c
@@ -0,0 +1,545 @@
1/*******************************************************************************
2 *
3 * Module Name: rsio - IO and DMA resource descriptors
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acresrc.h>
47
48#define _COMPONENT ACPI_RESOURCES
49 ACPI_MODULE_NAME ("rsio")
50
51
52/*******************************************************************************
53 *
54 * FUNCTION: acpi_rs_io_resource
55 *
56 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
57 * stream
58 * bytes_consumed - Pointer to where the number of bytes
59 * consumed the byte_stream_buffer is
60 * returned
61 * output_buffer - Pointer to the return data buffer
62 * structure_size - Pointer to where the number of bytes
63 * in the return data struct is returned
64 *
65 * RETURN: Status
66 *
67 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
68 * structure pointed to by the output_buffer. Return the
69 * number of bytes consumed from the byte stream.
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_rs_io_resource (
75 u8 *byte_stream_buffer,
76 acpi_size *bytes_consumed,
77 u8 **output_buffer,
78 acpi_size *structure_size)
79{
80 u8 *buffer = byte_stream_buffer;
81 struct acpi_resource *output_struct = (void *) *output_buffer;
82 u16 temp16 = 0;
83 u8 temp8 = 0;
84 acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io);
85
86
87 ACPI_FUNCTION_TRACE ("rs_io_resource");
88
89
90 /*
91 * The number of bytes consumed are Constant
92 */
93 *bytes_consumed = 8;
94
95 output_struct->id = ACPI_RSTYPE_IO;
96
97 /*
98 * Check Decode
99 */
100 buffer += 1;
101 temp8 = *buffer;
102
103 output_struct->data.io.io_decode = temp8 & 0x01;
104
105 /*
106 * Check min_base Address
107 */
108 buffer += 1;
109 ACPI_MOVE_16_TO_16 (&temp16, buffer);
110
111 output_struct->data.io.min_base_address = temp16;
112
113 /*
114 * Check max_base Address
115 */
116 buffer += 2;
117 ACPI_MOVE_16_TO_16 (&temp16, buffer);
118
119 output_struct->data.io.max_base_address = temp16;
120
121 /*
122 * Check Base alignment
123 */
124 buffer += 2;
125 temp8 = *buffer;
126
127 output_struct->data.io.alignment = temp8;
128
129 /*
130 * Check range_length
131 */
132 buffer += 1;
133 temp8 = *buffer;
134
135 output_struct->data.io.range_length = temp8;
136
137 /*
138 * Set the Length parameter
139 */
140 output_struct->length = (u32) struct_size;
141
142 /*
143 * Return the final size of the structure
144 */
145 *structure_size = struct_size;
146 return_ACPI_STATUS (AE_OK);
147}
148
149
150/*******************************************************************************
151 *
152 * FUNCTION: acpi_rs_fixed_io_resource
153 *
154 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
155 * stream
156 * bytes_consumed - Pointer to where the number of bytes
157 * consumed the byte_stream_buffer is
158 * returned
159 * output_buffer - Pointer to the return data buffer
160 * structure_size - Pointer to where the number of bytes
161 * in the return data struct is returned
162 *
163 * RETURN: Status
164 *
165 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
166 * structure pointed to by the output_buffer. Return the
167 * number of bytes consumed from the byte stream.
168 *
169 ******************************************************************************/
170
171acpi_status
172acpi_rs_fixed_io_resource (
173 u8 *byte_stream_buffer,
174 acpi_size *bytes_consumed,
175 u8 **output_buffer,
176 acpi_size *structure_size)
177{
178 u8 *buffer = byte_stream_buffer;
179 struct acpi_resource *output_struct = (void *) *output_buffer;
180 u16 temp16 = 0;
181 u8 temp8 = 0;
182 acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_io);
183
184
185 ACPI_FUNCTION_TRACE ("rs_fixed_io_resource");
186
187
188 /*
189 * The number of bytes consumed are Constant
190 */
191 *bytes_consumed = 4;
192
193 output_struct->id = ACPI_RSTYPE_FIXED_IO;
194
195 /*
196 * Check Range Base Address
197 */
198 buffer += 1;
199 ACPI_MOVE_16_TO_16 (&temp16, buffer);
200
201 output_struct->data.fixed_io.base_address = temp16;
202
203 /*
204 * Check range_length
205 */
206 buffer += 2;
207 temp8 = *buffer;
208
209 output_struct->data.fixed_io.range_length = temp8;
210
211 /*
212 * Set the Length parameter
213 */
214 output_struct->length = (u32) struct_size;
215
216 /*
217 * Return the final size of the structure
218 */
219 *structure_size = struct_size;
220 return_ACPI_STATUS (AE_OK);
221}
222
223
224/*******************************************************************************
225 *
226 * FUNCTION: acpi_rs_io_stream
227 *
228 * PARAMETERS: linked_list - Pointer to the resource linked list
229 * output_buffer - Pointer to the user's return buffer
230 * bytes_consumed - Pointer to where the number of bytes
231 * used in the output_buffer is returned
232 *
233 * RETURN: Status
234 *
235 * DESCRIPTION: Take the linked list resource structure and fills in the
236 * the appropriate bytes in a byte stream
237 *
238 ******************************************************************************/
239
240acpi_status
241acpi_rs_io_stream (
242 struct acpi_resource *linked_list,
243 u8 **output_buffer,
244 acpi_size *bytes_consumed)
245{
246 u8 *buffer = *output_buffer;
247 u16 temp16 = 0;
248 u8 temp8 = 0;
249
250
251 ACPI_FUNCTION_TRACE ("rs_io_stream");
252
253
254 /*
255 * The descriptor field is static
256 */
257 *buffer = 0x47;
258 buffer += 1;
259
260 /*
261 * Io Information Byte
262 */
263 temp8 = (u8) (linked_list->data.io.io_decode & 0x01);
264
265 *buffer = temp8;
266 buffer += 1;
267
268 /*
269 * Set the Range minimum base address
270 */
271 temp16 = (u16) linked_list->data.io.min_base_address;
272
273 ACPI_MOVE_16_TO_16 (buffer, &temp16);
274 buffer += 2;
275
276 /*
277 * Set the Range maximum base address
278 */
279 temp16 = (u16) linked_list->data.io.max_base_address;
280
281 ACPI_MOVE_16_TO_16 (buffer, &temp16);
282 buffer += 2;
283
284 /*
285 * Set the base alignment
286 */
287 temp8 = (u8) linked_list->data.io.alignment;
288
289 *buffer = temp8;
290 buffer += 1;
291
292 /*
293 * Set the range length
294 */
295 temp8 = (u8) linked_list->data.io.range_length;
296
297 *buffer = temp8;
298 buffer += 1;
299
300 /*
301 * Return the number of bytes consumed in this operation
302 */
303 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
304 return_ACPI_STATUS (AE_OK);
305}
306
307
308/*******************************************************************************
309 *
310 * FUNCTION: acpi_rs_fixed_io_stream
311 *
312 * PARAMETERS: linked_list - Pointer to the resource linked list
313 * output_buffer - Pointer to the user's return buffer
314 * bytes_consumed - Pointer to where the number of bytes
315 * used in the output_buffer is returned
316 *
317 * RETURN: Status
318 *
319 * DESCRIPTION: Take the linked list resource structure and fills in the
320 * the appropriate bytes in a byte stream
321 *
322 ******************************************************************************/
323
324acpi_status
325acpi_rs_fixed_io_stream (
326 struct acpi_resource *linked_list,
327 u8 **output_buffer,
328 acpi_size *bytes_consumed)
329{
330 u8 *buffer = *output_buffer;
331 u16 temp16 = 0;
332 u8 temp8 = 0;
333
334
335 ACPI_FUNCTION_TRACE ("rs_fixed_io_stream");
336
337
338 /*
339 * The descriptor field is static
340 */
341 *buffer = 0x4B;
342
343 buffer += 1;
344
345 /*
346 * Set the Range base address
347 */
348 temp16 = (u16) linked_list->data.fixed_io.base_address;
349
350 ACPI_MOVE_16_TO_16 (buffer, &temp16);
351 buffer += 2;
352
353 /*
354 * Set the range length
355 */
356 temp8 = (u8) linked_list->data.fixed_io.range_length;
357
358 *buffer = temp8;
359 buffer += 1;
360
361 /*
362 * Return the number of bytes consumed in this operation
363 */
364 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
365 return_ACPI_STATUS (AE_OK);
366}
367
368
369/*******************************************************************************
370 *
371 * FUNCTION: acpi_rs_dma_resource
372 *
373 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
374 * stream
375 * bytes_consumed - Pointer to where the number of bytes
376 * consumed the byte_stream_buffer is
377 * returned
378 * output_buffer - Pointer to the return data buffer
379 * structure_size - Pointer to where the number of bytes
380 * in the return data struct is returned
381 *
382 * RETURN: Status
383 *
384 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
385 * structure pointed to by the output_buffer. Return the
386 * number of bytes consumed from the byte stream.
387 *
388 ******************************************************************************/
389
390acpi_status
391acpi_rs_dma_resource (
392 u8 *byte_stream_buffer,
393 acpi_size *bytes_consumed,
394 u8 **output_buffer,
395 acpi_size *structure_size)
396{
397 u8 *buffer = byte_stream_buffer;
398 struct acpi_resource *output_struct = (void *) *output_buffer;
399 u8 temp8 = 0;
400 u8 index;
401 u8 i;
402 acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_dma);
403
404
405 ACPI_FUNCTION_TRACE ("rs_dma_resource");
406
407
408 /*
409 * The number of bytes consumed are Constant
410 */
411 *bytes_consumed = 3;
412 output_struct->id = ACPI_RSTYPE_DMA;
413
414 /*
415 * Point to the 8-bits of Byte 1
416 */
417 buffer += 1;
418 temp8 = *buffer;
419
420 /* Decode the DMA channel bits */
421
422 for (i = 0, index = 0; index < 8; index++) {
423 if ((temp8 >> index) & 0x01) {
424 output_struct->data.dma.channels[i] = index;
425 i++;
426 }
427 }
428
429 /* Zero DMA channels is valid */
430
431 output_struct->data.dma.number_of_channels = i;
432 if (i > 0) {
433 /*
434 * Calculate the structure size based upon the number of interrupts
435 */
436 struct_size += ((acpi_size) i - 1) * 4;
437 }
438
439 /*
440 * Point to Byte 2
441 */
442 buffer += 1;
443 temp8 = *buffer;
444
445 /*
446 * Check for transfer preference (Bits[1:0])
447 */
448 output_struct->data.dma.transfer = temp8 & 0x03;
449
450 if (0x03 == output_struct->data.dma.transfer) {
451 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid DMA.Transfer preference (3)\n"));
452 return_ACPI_STATUS (AE_BAD_DATA);
453 }
454
455 /*
456 * Get bus master preference (Bit[2])
457 */
458 output_struct->data.dma.bus_master = (temp8 >> 2) & 0x01;
459
460 /*
461 * Get channel speed support (Bits[6:5])
462 */
463 output_struct->data.dma.type = (temp8 >> 5) & 0x03;
464
465 /*
466 * Set the Length parameter
467 */
468 output_struct->length = (u32) struct_size;
469
470 /*
471 * Return the final size of the structure
472 */
473 *structure_size = struct_size;
474 return_ACPI_STATUS (AE_OK);
475}
476
477
478/*******************************************************************************
479 *
480 * FUNCTION: acpi_rs_dma_stream
481 *
482 * PARAMETERS: linked_list - Pointer to the resource linked list
483 * output_buffer - Pointer to the user's return buffer
484 * bytes_consumed - Pointer to where the number of bytes
485 * used in the output_buffer is returned
486 *
487 * RETURN: Status
488 *
489 * DESCRIPTION: Take the linked list resource structure and fills in the
490 * the appropriate bytes in a byte stream
491 *
492 ******************************************************************************/
493
494acpi_status
495acpi_rs_dma_stream (
496 struct acpi_resource *linked_list,
497 u8 **output_buffer,
498 acpi_size *bytes_consumed)
499{
500 u8 *buffer = *output_buffer;
501 u16 temp16 = 0;
502 u8 temp8 = 0;
503 u8 index;
504
505
506 ACPI_FUNCTION_TRACE ("rs_dma_stream");
507
508
509 /*
510 * The descriptor field is static
511 */
512 *buffer = 0x2A;
513 buffer += 1;
514 temp8 = 0;
515
516 /*
517 * Loop through all of the Channels and set the mask bits
518 */
519 for (index = 0;
520 index < linked_list->data.dma.number_of_channels;
521 index++) {
522 temp16 = (u16) linked_list->data.dma.channels[index];
523 temp8 |= 0x1 << temp16;
524 }
525
526 *buffer = temp8;
527 buffer += 1;
528
529 /*
530 * Set the DMA Info
531 */
532 temp8 = (u8) ((linked_list->data.dma.type & 0x03) << 5);
533 temp8 |= ((linked_list->data.dma.bus_master & 0x01) << 2);
534 temp8 |= (linked_list->data.dma.transfer & 0x03);
535
536 *buffer = temp8;
537 buffer += 1;
538
539 /*
540 * Return the number of bytes consumed in this operation
541 */
542 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
543 return_ACPI_STATUS (AE_OK);
544}
545
diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c
new file mode 100644
index 000000000000..fd07a8702fbe
--- /dev/null
+++ b/drivers/acpi/resources/rsirq.c
@@ -0,0 +1,592 @@
1/*******************************************************************************
2 *
3 * Module Name: rsirq - IRQ resource descriptors
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acresrc.h>
47
48#define _COMPONENT ACPI_RESOURCES
49 ACPI_MODULE_NAME ("rsirq")
50
51
52/*******************************************************************************
53 *
54 * FUNCTION: acpi_rs_irq_resource
55 *
56 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
57 * stream
58 * bytes_consumed - Pointer to where the number of bytes
59 * consumed the byte_stream_buffer is
60 * returned
61 * output_buffer - Pointer to the return data buffer
62 * structure_size - Pointer to where the number of bytes
63 * in the return data struct is returned
64 *
65 * RETURN: Status
66 *
67 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
68 * structure pointed to by the output_buffer. Return the
69 * number of bytes consumed from the byte stream.
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_rs_irq_resource (
75 u8 *byte_stream_buffer,
76 acpi_size *bytes_consumed,
77 u8 **output_buffer,
78 acpi_size *structure_size)
79{
80 u8 *buffer = byte_stream_buffer;
81 struct acpi_resource *output_struct = (void *) *output_buffer;
82 u16 temp16 = 0;
83 u8 temp8 = 0;
84 u8 index;
85 u8 i;
86 acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_irq);
87
88
89 ACPI_FUNCTION_TRACE ("rs_irq_resource");
90
91
92 /*
93 * The number of bytes consumed are contained in the descriptor
94 * (Bits:0-1)
95 */
96 temp8 = *buffer;
97 *bytes_consumed = (temp8 & 0x03) + 1;
98 output_struct->id = ACPI_RSTYPE_IRQ;
99
100 /*
101 * Point to the 16-bits of Bytes 1 and 2
102 */
103 buffer += 1;
104 ACPI_MOVE_16_TO_16 (&temp16, buffer);
105
106 output_struct->data.irq.number_of_interrupts = 0;
107
108 /* Decode the IRQ bits */
109
110 for (i = 0, index = 0; index < 16; index++) {
111 if ((temp16 >> index) & 0x01) {
112 output_struct->data.irq.interrupts[i] = index;
113 i++;
114 }
115 }
116
117 /* Zero interrupts is valid */
118
119 output_struct->data.irq.number_of_interrupts = i;
120 if (i > 0) {
121 /*
122 * Calculate the structure size based upon the number of interrupts
123 */
124 struct_size += ((acpi_size) i - 1) * 4;
125 }
126
127 /*
128 * Point to Byte 3 if it is used
129 */
130 if (4 == *bytes_consumed) {
131 buffer += 2;
132 temp8 = *buffer;
133
134 /*
135 * Check for HE, LL interrupts
136 */
137 switch (temp8 & 0x09) {
138 case 0x01: /* HE */
139 output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE;
140 output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH;
141 break;
142
143 case 0x08: /* LL */
144 output_struct->data.irq.edge_level = ACPI_LEVEL_SENSITIVE;
145 output_struct->data.irq.active_high_low = ACPI_ACTIVE_LOW;
146 break;
147
148 default:
149 /*
150 * Only _LL and _HE polarity/trigger interrupts
151 * are allowed (ACPI spec, section "IRQ Format")
152 * so 0x00 and 0x09 are illegal.
153 */
154 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
155 "Invalid interrupt polarity/trigger in resource list, %X\n", temp8));
156 return_ACPI_STATUS (AE_BAD_DATA);
157 }
158
159 /*
160 * Check for sharable
161 */
162 output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01;
163 }
164 else {
165 /*
166 * Assume Edge Sensitive, Active High, Non-Sharable
167 * per ACPI Specification
168 */
169 output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE;
170 output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH;
171 output_struct->data.irq.shared_exclusive = ACPI_EXCLUSIVE;
172 }
173
174 /*
175 * Set the Length parameter
176 */
177 output_struct->length = (u32) struct_size;
178
179 /*
180 * Return the final size of the structure
181 */
182 *structure_size = struct_size;
183 return_ACPI_STATUS (AE_OK);
184}
185
186
187/*******************************************************************************
188 *
189 * FUNCTION: acpi_rs_irq_stream
190 *
191 * PARAMETERS: linked_list - Pointer to the resource linked list
192 * output_buffer - Pointer to the user's return buffer
193 * bytes_consumed - Pointer to where the number of bytes
194 * used in the output_buffer is returned
195 *
196 * RETURN: Status
197 *
198 * DESCRIPTION: Take the linked list resource structure and fills in the
199 * the appropriate bytes in a byte stream
200 *
201 ******************************************************************************/
202
203acpi_status
204acpi_rs_irq_stream (
205 struct acpi_resource *linked_list,
206 u8 **output_buffer,
207 acpi_size *bytes_consumed)
208{
209 u8 *buffer = *output_buffer;
210 u16 temp16 = 0;
211 u8 temp8 = 0;
212 u8 index;
213 u8 IRqinfo_byte_needed;
214
215
216 ACPI_FUNCTION_TRACE ("rs_irq_stream");
217
218
219 /*
220 * The descriptor field is set based upon whether a third byte is
221 * needed to contain the IRQ Information.
222 */
223 if (ACPI_EDGE_SENSITIVE == linked_list->data.irq.edge_level &&
224 ACPI_ACTIVE_HIGH == linked_list->data.irq.active_high_low &&
225 ACPI_EXCLUSIVE == linked_list->data.irq.shared_exclusive) {
226 *buffer = 0x22;
227 IRqinfo_byte_needed = FALSE;
228 }
229 else {
230 *buffer = 0x23;
231 IRqinfo_byte_needed = TRUE;
232 }
233
234 buffer += 1;
235 temp16 = 0;
236
237 /*
238 * Loop through all of the interrupts and set the mask bits
239 */
240 for(index = 0;
241 index < linked_list->data.irq.number_of_interrupts;
242 index++) {
243 temp8 = (u8) linked_list->data.irq.interrupts[index];
244 temp16 |= 0x1 << temp8;
245 }
246
247 ACPI_MOVE_16_TO_16 (buffer, &temp16);
248 buffer += 2;
249
250 /*
251 * Set the IRQ Info byte if needed.
252 */
253 if (IRqinfo_byte_needed) {
254 temp8 = 0;
255 temp8 = (u8) ((linked_list->data.irq.shared_exclusive &
256 0x01) << 4);
257
258 if (ACPI_LEVEL_SENSITIVE == linked_list->data.irq.edge_level &&
259 ACPI_ACTIVE_LOW == linked_list->data.irq.active_high_low) {
260 temp8 |= 0x08;
261 }
262 else {
263 temp8 |= 0x01;
264 }
265
266 *buffer = temp8;
267 buffer += 1;
268 }
269
270 /*
271 * Return the number of bytes consumed in this operation
272 */
273 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
274 return_ACPI_STATUS (AE_OK);
275}
276
277
278/*******************************************************************************
279 *
280 * FUNCTION: acpi_rs_extended_irq_resource
281 *
282 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
283 * stream
284 * bytes_consumed - Pointer to where the number of bytes
285 * consumed the byte_stream_buffer is
286 * returned
287 * output_buffer - Pointer to the return data buffer
288 * structure_size - Pointer to where the number of bytes
289 * in the return data struct is returned
290 *
291 * RETURN: Status
292 *
293 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
294 * structure pointed to by the output_buffer. Return the
295 * number of bytes consumed from the byte stream.
296 *
297 ******************************************************************************/
298
299acpi_status
300acpi_rs_extended_irq_resource (
301 u8 *byte_stream_buffer,
302 acpi_size *bytes_consumed,
303 u8 **output_buffer,
304 acpi_size *structure_size)
305{
306 u8 *buffer = byte_stream_buffer;
307 struct acpi_resource *output_struct = (void *) *output_buffer;
308 u16 temp16 = 0;
309 u8 temp8 = 0;
310 u8 *temp_ptr;
311 u8 index;
312 acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_ext_irq);
313
314
315 ACPI_FUNCTION_TRACE ("rs_extended_irq_resource");
316
317
318 /*
319 * Point past the Descriptor to get the number of bytes consumed
320 */
321 buffer += 1;
322 ACPI_MOVE_16_TO_16 (&temp16, buffer);
323
324 /* Validate minimum descriptor length */
325
326 if (temp16 < 6) {
327 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
328 }
329
330 *bytes_consumed = temp16 + 3;
331 output_struct->id = ACPI_RSTYPE_EXT_IRQ;
332
333 /*
334 * Point to the Byte3
335 */
336 buffer += 2;
337 temp8 = *buffer;
338
339 output_struct->data.extended_irq.producer_consumer = temp8 & 0x01;
340
341 /*
342 * Check for Interrupt Mode
343 *
344 * The definition of an Extended IRQ changed between ACPI spec v1.0b
345 * and ACPI spec 2.0 (section 6.4.3.6 in both).
346 *
347 * - Edge/Level are defined opposite in the table vs the headers
348 */
349 output_struct->data.extended_irq.edge_level =
350 (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
351
352 /*
353 * Check Interrupt Polarity
354 */
355 output_struct->data.extended_irq.active_high_low = (temp8 >> 2) & 0x1;
356
357 /*
358 * Check for sharable
359 */
360 output_struct->data.extended_irq.shared_exclusive = (temp8 >> 3) & 0x01;
361
362 /*
363 * Point to Byte4 (IRQ Table length)
364 */
365 buffer += 1;
366 temp8 = *buffer;
367
368 /* Must have at least one IRQ */
369
370 if (temp8 < 1) {
371 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
372 }
373
374 output_struct->data.extended_irq.number_of_interrupts = temp8;
375
376 /*
377 * Add any additional structure size to properly calculate
378 * the next pointer at the end of this function
379 */
380 struct_size += (temp8 - 1) * 4;
381
382 /*
383 * Point to Byte5 (First IRQ Number)
384 */
385 buffer += 1;
386
387 /*
388 * Cycle through every IRQ in the table
389 */
390 for (index = 0; index < temp8; index++) {
391 ACPI_MOVE_32_TO_32 (
392 &output_struct->data.extended_irq.interrupts[index], buffer);
393
394 /* Point to the next IRQ */
395
396 buffer += 4;
397 }
398
399 /*
400 * This will leave us pointing to the Resource Source Index
401 * If it is present, then save it off and calculate the
402 * pointer to where the null terminated string goes:
403 * Each Interrupt takes 32-bits + the 5 bytes of the
404 * stream that are default.
405 *
406 * Note: Some resource descriptors will have an additional null, so
407 * we add 1 to the length.
408 */
409 if (*bytes_consumed >
410 ((acpi_size) output_struct->data.extended_irq.number_of_interrupts * 4) + (5 + 1)) {
411 /* Dereference the Index */
412
413 temp8 = *buffer;
414 output_struct->data.extended_irq.resource_source.index = (u32) temp8;
415
416 /* Point to the String */
417
418 buffer += 1;
419
420 /*
421 * Point the String pointer to the end of this structure.
422 */
423 output_struct->data.extended_irq.resource_source.string_ptr =
424 (char *)((char *) output_struct + struct_size);
425
426 temp_ptr = (u8 *) output_struct->data.extended_irq.resource_source.string_ptr;
427
428 /* Copy the string into the buffer */
429
430 index = 0;
431 while (0x00 != *buffer) {
432 *temp_ptr = *buffer;
433
434 temp_ptr += 1;
435 buffer += 1;
436 index += 1;
437 }
438
439 /*
440 * Add the terminating null
441 */
442 *temp_ptr = 0x00;
443 output_struct->data.extended_irq.resource_source.string_length = index + 1;
444
445 /*
446 * In order for the struct_size to fall on a 32-bit boundary,
447 * calculate the length of the string and expand the
448 * struct_size to the next 32-bit boundary.
449 */
450 temp8 = (u8) (index + 1);
451 struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
452 }
453 else {
454 output_struct->data.extended_irq.resource_source.index = 0x00;
455 output_struct->data.extended_irq.resource_source.string_length = 0;
456 output_struct->data.extended_irq.resource_source.string_ptr = NULL;
457 }
458
459 /*
460 * Set the Length parameter
461 */
462 output_struct->length = (u32) struct_size;
463
464 /*
465 * Return the final size of the structure
466 */
467 *structure_size = struct_size;
468 return_ACPI_STATUS (AE_OK);
469}
470
471
472/*******************************************************************************
473 *
474 * FUNCTION: acpi_rs_extended_irq_stream
475 *
476 * PARAMETERS: linked_list - Pointer to the resource linked list
477 * output_buffer - Pointer to the user's return buffer
478 * bytes_consumed - Pointer to where the number of bytes
479 * used in the output_buffer is returned
480 *
481 * RETURN: Status
482 *
483 * DESCRIPTION: Take the linked list resource structure and fills in the
484 * the appropriate bytes in a byte stream
485 *
486 ******************************************************************************/
487
488acpi_status
489acpi_rs_extended_irq_stream (
490 struct acpi_resource *linked_list,
491 u8 **output_buffer,
492 acpi_size *bytes_consumed)
493{
494 u8 *buffer = *output_buffer;
495 u16 *length_field;
496 u8 temp8 = 0;
497 u8 index;
498 char *temp_pointer = NULL;
499
500
501 ACPI_FUNCTION_TRACE ("rs_extended_irq_stream");
502
503
504 /*
505 * The descriptor field is static
506 */
507 *buffer = 0x89;
508 buffer += 1;
509
510 /*
511 * Set a pointer to the Length field - to be filled in later
512 */
513 length_field = ACPI_CAST_PTR (u16, buffer);
514 buffer += 2;
515
516 /*
517 * Set the Interrupt vector flags
518 */
519 temp8 = (u8)(linked_list->data.extended_irq.producer_consumer & 0x01);
520 temp8 |= ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3);
521
522 /*
523 * Set the Interrupt Mode
524 *
525 * The definition of an Extended IRQ changed between ACPI spec v1.0b
526 * and ACPI spec 2.0 (section 6.4.3.6 in both). This code does not
527 * implement the more restrictive definition of 1.0b
528 *
529 * - Edge/Level are defined opposite in the table vs the headers
530 */
531 if (ACPI_EDGE_SENSITIVE == linked_list->data.extended_irq.edge_level) {
532 temp8 |= 0x2;
533 }
534
535 /*
536 * Set the Interrupt Polarity
537 */
538 temp8 |= ((linked_list->data.extended_irq.active_high_low & 0x1) << 2);
539
540 *buffer = temp8;
541 buffer += 1;
542
543 /*
544 * Set the Interrupt table length
545 */
546 temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts;
547
548 *buffer = temp8;
549 buffer += 1;
550
551 for (index = 0; index < linked_list->data.extended_irq.number_of_interrupts;
552 index++) {
553 ACPI_MOVE_32_TO_32 (buffer,
554 &linked_list->data.extended_irq.interrupts[index]);
555 buffer += 4;
556 }
557
558 /*
559 * Resource Source Index and Resource Source are optional
560 */
561 if (0 != linked_list->data.extended_irq.resource_source.string_length) {
562 *buffer = (u8) linked_list->data.extended_irq.resource_source.index;
563 buffer += 1;
564
565 temp_pointer = (char *) buffer;
566
567 /*
568 * Copy the string
569 */
570 ACPI_STRCPY (temp_pointer,
571 linked_list->data.extended_irq.resource_source.string_ptr);
572
573 /*
574 * Buffer needs to be set to the length of the sting + one for the
575 * terminating null
576 */
577 buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.extended_irq.resource_source.string_ptr) + 1);
578 }
579
580 /*
581 * Return the number of bytes consumed in this operation
582 */
583 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
584
585 /*
586 * Set the length field to the number of bytes consumed
587 * minus the header size (3 bytes)
588 */
589 *length_field = (u16) (*bytes_consumed - 3);
590 return_ACPI_STATUS (AE_OK);
591}
592
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
new file mode 100644
index 000000000000..e49c1e030f99
--- /dev/null
+++ b/drivers/acpi/resources/rslist.c
@@ -0,0 +1,518 @@
1/*******************************************************************************
2 *
3 * Module Name: rslist - Linked list utilities
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acresrc.h>
47
48#define _COMPONENT ACPI_RESOURCES
49 ACPI_MODULE_NAME ("rslist")
50
51
52/*******************************************************************************
53 *
54 * FUNCTION: acpi_rs_get_resource_type
55 *
56 * PARAMETERS: resource_start_byte - Byte 0 of a resource descriptor
57 *
58 * RETURN: The Resource Type (Name) with no extraneous bits
59 *
60 * DESCRIPTION: Extract the Resource Type/Name from the first byte of
61 * a resource descriptor.
62 *
63 ******************************************************************************/
64
65u8
66acpi_rs_get_resource_type (
67 u8 resource_start_byte)
68{
69
70 ACPI_FUNCTION_ENTRY ();
71
72
73 /*
74 * Determine if this is a small or large resource
75 */
76 switch (resource_start_byte & ACPI_RDESC_TYPE_MASK) {
77 case ACPI_RDESC_TYPE_SMALL:
78
79 /*
80 * Small Resource Type -- Only bits 6:3 are valid
81 */
82 return ((u8) (resource_start_byte & ACPI_RDESC_SMALL_MASK));
83
84
85 case ACPI_RDESC_TYPE_LARGE:
86
87 /*
88 * Large Resource Type -- All bits are valid
89 */
90 return (resource_start_byte);
91
92
93 default:
94 /* No other types of resource descriptor */
95 break;
96 }
97
98 return (0xFF);
99}
100
101
102/*******************************************************************************
103 *
104 * FUNCTION: acpi_rs_byte_stream_to_list
105 *
106 * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream
107 * byte_stream_buffer_length - Length of byte_stream_buffer
108 * output_buffer - Pointer to the buffer that will
109 * contain the output structures
110 *
111 * RETURN: Status
112 *
113 * DESCRIPTION: Takes the resource byte stream and parses it, creating a
114 * linked list of resources in the caller's output buffer
115 *
116 ******************************************************************************/
117
118acpi_status
119acpi_rs_byte_stream_to_list (
120 u8 *byte_stream_buffer,
121 u32 byte_stream_buffer_length,
122 u8 *output_buffer)
123{
124 acpi_status status;
125 acpi_size bytes_parsed = 0;
126 u8 resource_type = 0;
127 acpi_size bytes_consumed = 0;
128 u8 *buffer = output_buffer;
129 acpi_size structure_size = 0;
130 u8 end_tag_processed = FALSE;
131 struct acpi_resource *resource;
132
133 ACPI_FUNCTION_TRACE ("rs_byte_stream_to_list");
134
135
136 while (bytes_parsed < byte_stream_buffer_length &&
137 !end_tag_processed) {
138 /*
139 * The next byte in the stream is the resource type
140 */
141 resource_type = acpi_rs_get_resource_type (*byte_stream_buffer);
142
143 switch (resource_type) {
144 case ACPI_RDESC_TYPE_MEMORY_24:
145 /*
146 * 24-Bit Memory Resource
147 */
148 status = acpi_rs_memory24_resource (byte_stream_buffer,
149 &bytes_consumed, &buffer, &structure_size);
150 break;
151
152
153 case ACPI_RDESC_TYPE_LARGE_VENDOR:
154 /*
155 * Vendor Defined Resource
156 */
157 status = acpi_rs_vendor_resource (byte_stream_buffer,
158 &bytes_consumed, &buffer, &structure_size);
159 break;
160
161
162 case ACPI_RDESC_TYPE_MEMORY_32:
163 /*
164 * 32-Bit Memory Range Resource
165 */
166 status = acpi_rs_memory32_range_resource (byte_stream_buffer,
167 &bytes_consumed, &buffer, &structure_size);
168 break;
169
170
171 case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
172 /*
173 * 32-Bit Fixed Memory Resource
174 */
175 status = acpi_rs_fixed_memory32_resource (byte_stream_buffer,
176 &bytes_consumed, &buffer, &structure_size);
177 break;
178
179
180 case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
181 case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
182 /*
183 * 64-Bit Address Resource
184 */
185 status = acpi_rs_address64_resource (byte_stream_buffer,
186 &bytes_consumed, &buffer, &structure_size);
187 break;
188
189
190 case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
191 /*
192 * 32-Bit Address Resource
193 */
194 status = acpi_rs_address32_resource (byte_stream_buffer,
195 &bytes_consumed, &buffer, &structure_size);
196 break;
197
198
199 case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
200 /*
201 * 16-Bit Address Resource
202 */
203 status = acpi_rs_address16_resource (byte_stream_buffer,
204 &bytes_consumed, &buffer, &structure_size);
205 break;
206
207
208 case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
209 /*
210 * Extended IRQ
211 */
212 status = acpi_rs_extended_irq_resource (byte_stream_buffer,
213 &bytes_consumed, &buffer, &structure_size);
214 break;
215
216
217 case ACPI_RDESC_TYPE_IRQ_FORMAT:
218 /*
219 * IRQ Resource
220 */
221 status = acpi_rs_irq_resource (byte_stream_buffer,
222 &bytes_consumed, &buffer, &structure_size);
223 break;
224
225
226 case ACPI_RDESC_TYPE_DMA_FORMAT:
227 /*
228 * DMA Resource
229 */
230 status = acpi_rs_dma_resource (byte_stream_buffer,
231 &bytes_consumed, &buffer, &structure_size);
232 break;
233
234
235 case ACPI_RDESC_TYPE_START_DEPENDENT:
236 /*
237 * Start Dependent Functions Resource
238 */
239 status = acpi_rs_start_depend_fns_resource (byte_stream_buffer,
240 &bytes_consumed, &buffer, &structure_size);
241 break;
242
243
244 case ACPI_RDESC_TYPE_END_DEPENDENT:
245 /*
246 * End Dependent Functions Resource
247 */
248 status = acpi_rs_end_depend_fns_resource (byte_stream_buffer,
249 &bytes_consumed, &buffer, &structure_size);
250 break;
251
252
253 case ACPI_RDESC_TYPE_IO_PORT:
254 /*
255 * IO Port Resource
256 */
257 status = acpi_rs_io_resource (byte_stream_buffer,
258 &bytes_consumed, &buffer, &structure_size);
259 break;
260
261
262 case ACPI_RDESC_TYPE_FIXED_IO_PORT:
263 /*
264 * Fixed IO Port Resource
265 */
266 status = acpi_rs_fixed_io_resource (byte_stream_buffer,
267 &bytes_consumed, &buffer, &structure_size);
268 break;
269
270
271 case ACPI_RDESC_TYPE_SMALL_VENDOR:
272 /*
273 * Vendor Specific Resource
274 */
275 status = acpi_rs_vendor_resource (byte_stream_buffer,
276 &bytes_consumed, &buffer, &structure_size);
277 break;
278
279
280 case ACPI_RDESC_TYPE_END_TAG:
281 /*
282 * End Tag
283 */
284 end_tag_processed = TRUE;
285 status = acpi_rs_end_tag_resource (byte_stream_buffer,
286 &bytes_consumed, &buffer, &structure_size);
287 break;
288
289
290 default:
291 /*
292 * Invalid/Unknown resource type
293 */
294 status = AE_AML_INVALID_RESOURCE_TYPE;
295 break;
296 }
297
298 if (ACPI_FAILURE (status)) {
299 return_ACPI_STATUS (status);
300 }
301
302 /*
303 * Update the return value and counter
304 */
305 bytes_parsed += bytes_consumed;
306
307 /*
308 * Set the byte stream to point to the next resource
309 */
310 byte_stream_buffer += bytes_consumed;
311
312 /*
313 * Set the Buffer to the next structure
314 */
315 resource = ACPI_CAST_PTR (struct acpi_resource, buffer);
316 resource->length = (u32) ACPI_ALIGN_RESOURCE_SIZE (resource->length);
317 buffer += ACPI_ALIGN_RESOURCE_SIZE (structure_size);
318
319 } /* end while */
320
321 /*
322 * Check the reason for exiting the while loop
323 */
324 if (!end_tag_processed) {
325 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
326 }
327
328 return_ACPI_STATUS (AE_OK);
329}
330
331
332/*******************************************************************************
333 *
334 * FUNCTION: acpi_rs_list_to_byte_stream
335 *
336 * PARAMETERS: linked_list - Pointer to the resource linked list
337 * byte_steam_size_needed - Calculated size of the byte stream
338 * needed from calling
339 * acpi_rs_get_byte_stream_length()
340 * The size of the output_buffer is
341 * guaranteed to be >=
342 * byte_stream_size_needed
343 * output_buffer - Pointer to the buffer that will
344 * contain the byte stream
345 *
346 * RETURN: Status
347 *
348 * DESCRIPTION: Takes the resource linked list and parses it, creating a
349 * byte stream of resources in the caller's output buffer
350 *
351 ******************************************************************************/
352
353acpi_status
354acpi_rs_list_to_byte_stream (
355 struct acpi_resource *linked_list,
356 acpi_size byte_stream_size_needed,
357 u8 *output_buffer)
358{
359 acpi_status status;
360 u8 *buffer = output_buffer;
361 acpi_size bytes_consumed = 0;
362 u8 done = FALSE;
363
364
365 ACPI_FUNCTION_TRACE ("rs_list_to_byte_stream");
366
367
368 while (!done) {
369 switch (linked_list->id) {
370 case ACPI_RSTYPE_IRQ:
371 /*
372 * IRQ Resource
373 */
374 status = acpi_rs_irq_stream (linked_list, &buffer, &bytes_consumed);
375 break;
376
377 case ACPI_RSTYPE_DMA:
378 /*
379 * DMA Resource
380 */
381 status = acpi_rs_dma_stream (linked_list, &buffer, &bytes_consumed);
382 break;
383
384 case ACPI_RSTYPE_START_DPF:
385 /*
386 * Start Dependent Functions Resource
387 */
388 status = acpi_rs_start_depend_fns_stream (linked_list,
389 &buffer, &bytes_consumed);
390 break;
391
392 case ACPI_RSTYPE_END_DPF:
393 /*
394 * End Dependent Functions Resource
395 */
396 status = acpi_rs_end_depend_fns_stream (linked_list,
397 &buffer, &bytes_consumed);
398 break;
399
400 case ACPI_RSTYPE_IO:
401 /*
402 * IO Port Resource
403 */
404 status = acpi_rs_io_stream (linked_list, &buffer, &bytes_consumed);
405 break;
406
407 case ACPI_RSTYPE_FIXED_IO:
408 /*
409 * Fixed IO Port Resource
410 */
411 status = acpi_rs_fixed_io_stream (linked_list, &buffer, &bytes_consumed);
412 break;
413
414 case ACPI_RSTYPE_VENDOR:
415 /*
416 * Vendor Defined Resource
417 */
418 status = acpi_rs_vendor_stream (linked_list, &buffer, &bytes_consumed);
419 break;
420
421 case ACPI_RSTYPE_END_TAG:
422 /*
423 * End Tag
424 */
425 status = acpi_rs_end_tag_stream (linked_list, &buffer, &bytes_consumed);
426
427 /*
428 * An End Tag indicates the end of the Resource Template
429 */
430 done = TRUE;
431 break;
432
433 case ACPI_RSTYPE_MEM24:
434 /*
435 * 24-Bit Memory Resource
436 */
437 status = acpi_rs_memory24_stream (linked_list, &buffer, &bytes_consumed);
438 break;
439
440 case ACPI_RSTYPE_MEM32:
441 /*
442 * 32-Bit Memory Range Resource
443 */
444 status = acpi_rs_memory32_range_stream (linked_list, &buffer,
445 &bytes_consumed);
446 break;
447
448 case ACPI_RSTYPE_FIXED_MEM32:
449 /*
450 * 32-Bit Fixed Memory Resource
451 */
452 status = acpi_rs_fixed_memory32_stream (linked_list, &buffer,
453 &bytes_consumed);
454 break;
455
456 case ACPI_RSTYPE_ADDRESS16:
457 /*
458 * 16-Bit Address Descriptor Resource
459 */
460 status = acpi_rs_address16_stream (linked_list, &buffer,
461 &bytes_consumed);
462 break;
463
464 case ACPI_RSTYPE_ADDRESS32:
465 /*
466 * 32-Bit Address Descriptor Resource
467 */
468 status = acpi_rs_address32_stream (linked_list, &buffer,
469 &bytes_consumed);
470 break;
471
472 case ACPI_RSTYPE_ADDRESS64:
473 /*
474 * 64-Bit Address Descriptor Resource
475 */
476 status = acpi_rs_address64_stream (linked_list, &buffer,
477 &bytes_consumed);
478 break;
479
480 case ACPI_RSTYPE_EXT_IRQ:
481 /*
482 * Extended IRQ Resource
483 */
484 status = acpi_rs_extended_irq_stream (linked_list, &buffer,
485 &bytes_consumed);
486 break;
487
488 default:
489 /*
490 * If we get here, everything is out of sync,
491 * so exit with an error
492 */
493 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid descriptor type (%X) in resource list\n",
494 linked_list->id));
495 status = AE_BAD_DATA;
496 break;
497
498 } /* switch (linked_list->Id) */
499
500 if (ACPI_FAILURE (status)) {
501 return_ACPI_STATUS (status);
502 }
503
504 /*
505 * Set the Buffer to point to the open byte
506 */
507 buffer += bytes_consumed;
508
509 /*
510 * Point to the next object
511 */
512 linked_list = ACPI_PTR_ADD (struct acpi_resource,
513 linked_list, linked_list->length);
514 }
515
516 return_ACPI_STATUS (AE_OK);
517}
518
diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c
new file mode 100644
index 000000000000..7c935aecf075
--- /dev/null
+++ b/drivers/acpi/resources/rsmemory.c
@@ -0,0 +1,566 @@
1/*******************************************************************************
2 *
3 * Module Name: rsmem24 - Memory resource descriptors
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acresrc.h>
47
48#define _COMPONENT ACPI_RESOURCES
49 ACPI_MODULE_NAME ("rsmemory")
50
51
52/*******************************************************************************
53 *
54 * FUNCTION: acpi_rs_memory24_resource
55 *
56 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
57 * stream
58 * bytes_consumed - Pointer to where the number of bytes
59 * consumed the byte_stream_buffer is
60 * returned
61 * output_buffer - Pointer to the return data buffer
62 * structure_size - Pointer to where the number of bytes
63 * in the return data struct is returned
64 *
65 * RETURN: Status
66 *
67 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
68 * structure pointed to by the output_buffer. Return the
69 * number of bytes consumed from the byte stream.
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_rs_memory24_resource (
75 u8 *byte_stream_buffer,
76 acpi_size *bytes_consumed,
77 u8 **output_buffer,
78 acpi_size *structure_size)
79{
80 u8 *buffer = byte_stream_buffer;
81 struct acpi_resource *output_struct = (void *) *output_buffer;
82 u16 temp16 = 0;
83 u8 temp8 = 0;
84 acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem24);
85
86
87 ACPI_FUNCTION_TRACE ("rs_memory24_resource");
88
89
90 /*
91 * Point past the Descriptor to get the number of bytes consumed
92 */
93 buffer += 1;
94
95 ACPI_MOVE_16_TO_16 (&temp16, buffer);
96 buffer += 2;
97 *bytes_consumed = (acpi_size) temp16 + 3;
98 output_struct->id = ACPI_RSTYPE_MEM24;
99
100 /*
101 * Check Byte 3 the Read/Write bit
102 */
103 temp8 = *buffer;
104 buffer += 1;
105 output_struct->data.memory24.read_write_attribute = temp8 & 0x01;
106
107 /*
108 * Get min_base_address (Bytes 4-5)
109 */
110 ACPI_MOVE_16_TO_16 (&temp16, buffer);
111 buffer += 2;
112 output_struct->data.memory24.min_base_address = temp16;
113
114 /*
115 * Get max_base_address (Bytes 6-7)
116 */
117 ACPI_MOVE_16_TO_16 (&temp16, buffer);
118 buffer += 2;
119 output_struct->data.memory24.max_base_address = temp16;
120
121 /*
122 * Get Alignment (Bytes 8-9)
123 */
124 ACPI_MOVE_16_TO_16 (&temp16, buffer);
125 buffer += 2;
126 output_struct->data.memory24.alignment = temp16;
127
128 /*
129 * Get range_length (Bytes 10-11)
130 */
131 ACPI_MOVE_16_TO_16 (&temp16, buffer);
132 output_struct->data.memory24.range_length = temp16;
133
134 /*
135 * Set the Length parameter
136 */
137 output_struct->length = (u32) struct_size;
138
139 /*
140 * Return the final size of the structure
141 */
142 *structure_size = struct_size;
143 return_ACPI_STATUS (AE_OK);
144}
145
146
147/*******************************************************************************
148 *
149 * FUNCTION: acpi_rs_memory24_stream
150 *
151 * PARAMETERS: linked_list - Pointer to the resource linked list
152 * output_buffer - Pointer to the user's return buffer
153 * bytes_consumed - Pointer to where the number of bytes
154 * used in the output_buffer is returned
155 *
156 * RETURN: Status
157 *
158 * DESCRIPTION: Take the linked list resource structure and fills in the
159 * the appropriate bytes in a byte stream
160 *
161 ******************************************************************************/
162
163acpi_status
164acpi_rs_memory24_stream (
165 struct acpi_resource *linked_list,
166 u8 **output_buffer,
167 acpi_size *bytes_consumed)
168{
169 u8 *buffer = *output_buffer;
170 u16 temp16 = 0;
171 u8 temp8 = 0;
172
173
174 ACPI_FUNCTION_TRACE ("rs_memory24_stream");
175
176
177 /*
178 * The descriptor field is static
179 */
180 *buffer = 0x81;
181 buffer += 1;
182
183 /*
184 * The length field is static
185 */
186 temp16 = 0x09;
187 ACPI_MOVE_16_TO_16 (buffer, &temp16);
188 buffer += 2;
189
190 /*
191 * Set the Information Byte
192 */
193 temp8 = (u8) (linked_list->data.memory24.read_write_attribute & 0x01);
194 *buffer = temp8;
195 buffer += 1;
196
197 /*
198 * Set the Range minimum base address
199 */
200 ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.min_base_address);
201 buffer += 2;
202
203 /*
204 * Set the Range maximum base address
205 */
206 ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.max_base_address);
207 buffer += 2;
208
209 /*
210 * Set the base alignment
211 */
212 ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.alignment);
213 buffer += 2;
214
215 /*
216 * Set the range length
217 */
218 ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.range_length);
219 buffer += 2;
220
221 /*
222 * Return the number of bytes consumed in this operation
223 */
224 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
225 return_ACPI_STATUS (AE_OK);
226}
227
228
229/*******************************************************************************
230 *
231 * FUNCTION: acpi_rs_memory32_range_resource
232 *
233 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
234 * stream
235 * bytes_consumed - Pointer to where the number of bytes
236 * consumed the byte_stream_buffer is
237 * returned
238 * output_buffer - Pointer to the return data buffer
239 * structure_size - Pointer to where the number of bytes
240 * in the return data struct is returned
241 *
242 * RETURN: Status
243 *
244 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
245 * structure pointed to by the output_buffer. Return the
246 * number of bytes consumed from the byte stream.
247 *
248 ******************************************************************************/
249
250acpi_status
251acpi_rs_memory32_range_resource (
252 u8 *byte_stream_buffer,
253 acpi_size *bytes_consumed,
254 u8 **output_buffer,
255 acpi_size *structure_size)
256{
257 u8 *buffer = byte_stream_buffer;
258 struct acpi_resource *output_struct = (void *) *output_buffer;
259 u16 temp16 = 0;
260 u8 temp8 = 0;
261 acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32);
262
263
264 ACPI_FUNCTION_TRACE ("rs_memory32_range_resource");
265
266
267 /*
268 * Point past the Descriptor to get the number of bytes consumed
269 */
270 buffer += 1;
271
272 ACPI_MOVE_16_TO_16 (&temp16, buffer);
273 buffer += 2;
274 *bytes_consumed = (acpi_size) temp16 + 3;
275
276 output_struct->id = ACPI_RSTYPE_MEM32;
277
278 /*
279 * Point to the place in the output buffer where the data portion will
280 * begin.
281 * 1. Set the RESOURCE_DATA * Data to point to its own address, then
282 * 2. Set the pointer to the next address.
283 *
284 * NOTE: output_struct->Data is cast to u8, otherwise, this addition adds
285 * 4 * sizeof(RESOURCE_DATA) instead of 4 * sizeof(u8)
286 */
287
288 /*
289 * Check Byte 3 the Read/Write bit
290 */
291 temp8 = *buffer;
292 buffer += 1;
293
294 output_struct->data.memory32.read_write_attribute = temp8 & 0x01;
295
296 /*
297 * Get min_base_address (Bytes 4-7)
298 */
299 ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.min_base_address, buffer);
300 buffer += 4;
301
302 /*
303 * Get max_base_address (Bytes 8-11)
304 */
305 ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.max_base_address, buffer);
306 buffer += 4;
307
308 /*
309 * Get Alignment (Bytes 12-15)
310 */
311 ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.alignment, buffer);
312 buffer += 4;
313
314 /*
315 * Get range_length (Bytes 16-19)
316 */
317 ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.range_length, buffer);
318
319 /*
320 * Set the Length parameter
321 */
322 output_struct->length = (u32) struct_size;
323
324 /*
325 * Return the final size of the structure
326 */
327 *structure_size = struct_size;
328 return_ACPI_STATUS (AE_OK);
329}
330
331
332/*******************************************************************************
333 *
334 * FUNCTION: acpi_rs_fixed_memory32_resource
335 *
336 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
337 * stream
338 * bytes_consumed - Pointer to where the number of bytes
339 * consumed the byte_stream_buffer is
340 * returned
341 * output_buffer - Pointer to the return data buffer
342 * structure_size - Pointer to where the number of bytes
343 * in the return data struct is returned
344 *
345 * RETURN: Status
346 *
347 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
348 * structure pointed to by the output_buffer. Return the
349 * number of bytes consumed from the byte stream.
350 *
351 ******************************************************************************/
352
353acpi_status
354acpi_rs_fixed_memory32_resource (
355 u8 *byte_stream_buffer,
356 acpi_size *bytes_consumed,
357 u8 **output_buffer,
358 acpi_size *structure_size)
359{
360 u8 *buffer = byte_stream_buffer;
361 struct acpi_resource *output_struct = (void *) *output_buffer;
362 u16 temp16 = 0;
363 u8 temp8 = 0;
364 acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_mem32);
365
366
367 ACPI_FUNCTION_TRACE ("rs_fixed_memory32_resource");
368
369
370 /*
371 * Point past the Descriptor to get the number of bytes consumed
372 */
373 buffer += 1;
374 ACPI_MOVE_16_TO_16 (&temp16, buffer);
375
376 buffer += 2;
377 *bytes_consumed = (acpi_size) temp16 + 3;
378
379 output_struct->id = ACPI_RSTYPE_FIXED_MEM32;
380
381 /*
382 * Check Byte 3 the Read/Write bit
383 */
384 temp8 = *buffer;
385 buffer += 1;
386 output_struct->data.fixed_memory32.read_write_attribute = temp8 & 0x01;
387
388 /*
389 * Get range_base_address (Bytes 4-7)
390 */
391 ACPI_MOVE_32_TO_32 (&output_struct->data.fixed_memory32.range_base_address, buffer);
392 buffer += 4;
393
394 /*
395 * Get range_length (Bytes 8-11)
396 */
397 ACPI_MOVE_32_TO_32 (&output_struct->data.fixed_memory32.range_length, buffer);
398
399 /*
400 * Set the Length parameter
401 */
402 output_struct->length = (u32) struct_size;
403
404 /*
405 * Return the final size of the structure
406 */
407 *structure_size = struct_size;
408 return_ACPI_STATUS (AE_OK);
409}
410
411
412/*******************************************************************************
413 *
414 * FUNCTION: acpi_rs_memory32_range_stream
415 *
416 * PARAMETERS: linked_list - Pointer to the resource linked list
417 * output_buffer - Pointer to the user's return buffer
418 * bytes_consumed - Pointer to where the number of bytes
419 * used in the output_buffer is returned
420 *
421 * RETURN: Status
422 *
423 * DESCRIPTION: Take the linked list resource structure and fills in the
424 * the appropriate bytes in a byte stream
425 *
426 ******************************************************************************/
427
428acpi_status
429acpi_rs_memory32_range_stream (
430 struct acpi_resource *linked_list,
431 u8 **output_buffer,
432 acpi_size *bytes_consumed)
433{
434 u8 *buffer = *output_buffer;
435 u16 temp16 = 0;
436 u8 temp8 = 0;
437
438
439 ACPI_FUNCTION_TRACE ("rs_memory32_range_stream");
440
441
442 /*
443 * The descriptor field is static
444 */
445 *buffer = 0x85;
446 buffer += 1;
447
448 /*
449 * The length field is static
450 */
451 temp16 = 0x11;
452
453 ACPI_MOVE_16_TO_16 (buffer, &temp16);
454 buffer += 2;
455
456 /*
457 * Set the Information Byte
458 */
459 temp8 = (u8) (linked_list->data.memory32.read_write_attribute & 0x01);
460 *buffer = temp8;
461 buffer += 1;
462
463 /*
464 * Set the Range minimum base address
465 */
466 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.min_base_address);
467 buffer += 4;
468
469 /*
470 * Set the Range maximum base address
471 */
472 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.max_base_address);
473 buffer += 4;
474
475 /*
476 * Set the base alignment
477 */
478 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.alignment);
479 buffer += 4;
480
481 /*
482 * Set the range length
483 */
484 ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.range_length);
485 buffer += 4;
486
487 /*
488 * Return the number of bytes consumed in this operation
489 */
490 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
491 return_ACPI_STATUS (AE_OK);
492}
493
494
495/*******************************************************************************
496 *
497 * FUNCTION: acpi_rs_fixed_memory32_stream
498 *
499 * PARAMETERS: linked_list - Pointer to the resource linked list
500 * output_buffer - Pointer to the user's return buffer
501 * bytes_consumed - Pointer to where the number of bytes
502 * used in the output_buffer is returned
503 *
504 * RETURN: Status
505 *
506 * DESCRIPTION: Take the linked list resource structure and fills in the
507 * the appropriate bytes in a byte stream
508 *
509 ******************************************************************************/
510
511acpi_status
512acpi_rs_fixed_memory32_stream (
513 struct acpi_resource *linked_list,
514 u8 **output_buffer,
515 acpi_size *bytes_consumed)
516{
517 u8 *buffer = *output_buffer;
518 u16 temp16 = 0;
519 u8 temp8 = 0;
520
521
522 ACPI_FUNCTION_TRACE ("rs_fixed_memory32_stream");
523
524
525 /*
526 * The descriptor field is static
527 */
528 *buffer = 0x86;
529 buffer += 1;
530
531 /*
532 * The length field is static
533 */
534 temp16 = 0x09;
535
536 ACPI_MOVE_16_TO_16 (buffer, &temp16);
537 buffer += 2;
538
539 /*
540 * Set the Information Byte
541 */
542 temp8 = (u8) (linked_list->data.fixed_memory32.read_write_attribute & 0x01);
543 *buffer = temp8;
544 buffer += 1;
545
546 /*
547 * Set the Range base address
548 */
549 ACPI_MOVE_32_TO_32 (buffer,
550 &linked_list->data.fixed_memory32.range_base_address);
551 buffer += 4;
552
553 /*
554 * Set the range length
555 */
556 ACPI_MOVE_32_TO_32 (buffer,
557 &linked_list->data.fixed_memory32.range_length);
558 buffer += 4;
559
560 /*
561 * Return the number of bytes consumed in this operation
562 */
563 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
564 return_ACPI_STATUS (AE_OK);
565}
566
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c
new file mode 100644
index 000000000000..d16be44b5df7
--- /dev/null
+++ b/drivers/acpi/resources/rsmisc.c
@@ -0,0 +1,597 @@
1/*******************************************************************************
2 *
3 * Module Name: rsmisc - Miscellaneous resource descriptors
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acresrc.h>
47
48#define _COMPONENT ACPI_RESOURCES
49 ACPI_MODULE_NAME ("rsmisc")
50
51
52/*******************************************************************************
53 *
54 * FUNCTION: acpi_rs_end_tag_resource
55 *
56 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
57 * stream
58 * bytes_consumed - Pointer to where the number of bytes
59 * consumed the byte_stream_buffer is
60 * returned
61 * output_buffer - Pointer to the return data buffer
62 * structure_size - Pointer to where the number of bytes
63 * in the return data struct is returned
64 *
65 * RETURN: Status
66 *
67 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
68 * structure pointed to by the output_buffer. Return the
69 * number of bytes consumed from the byte stream.
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_rs_end_tag_resource (
75 u8 *byte_stream_buffer,
76 acpi_size *bytes_consumed,
77 u8 **output_buffer,
78 acpi_size *structure_size)
79{
80 struct acpi_resource *output_struct = (void *) *output_buffer;
81 acpi_size struct_size = ACPI_RESOURCE_LENGTH;
82
83
84 ACPI_FUNCTION_TRACE ("rs_end_tag_resource");
85
86
87 /*
88 * The number of bytes consumed is static
89 */
90 *bytes_consumed = 2;
91
92 /*
93 * Fill out the structure
94 */
95 output_struct->id = ACPI_RSTYPE_END_TAG;
96
97 /*
98 * Set the Length parameter
99 */
100 output_struct->length = 0;
101
102 /*
103 * Return the final size of the structure
104 */
105 *structure_size = struct_size;
106 return_ACPI_STATUS (AE_OK);
107}
108
109
110/*******************************************************************************
111 *
112 * FUNCTION: acpi_rs_end_tag_stream
113 *
114 * PARAMETERS: linked_list - Pointer to the resource linked list
115 * output_buffer - Pointer to the user's return buffer
116 * bytes_consumed - Pointer to where the number of bytes
117 * used in the output_buffer is returned
118 *
119 * RETURN: Status
120 *
121 * DESCRIPTION: Take the linked list resource structure and fills in the
122 * the appropriate bytes in a byte stream
123 *
124 ******************************************************************************/
125
126acpi_status
127acpi_rs_end_tag_stream (
128 struct acpi_resource *linked_list,
129 u8 **output_buffer,
130 acpi_size *bytes_consumed)
131{
132 u8 *buffer = *output_buffer;
133 u8 temp8 = 0;
134
135
136 ACPI_FUNCTION_TRACE ("rs_end_tag_stream");
137
138
139 /*
140 * The descriptor field is static
141 */
142 *buffer = 0x79;
143 buffer += 1;
144
145 /*
146 * Set the Checksum - zero means that the resource data is treated as if
147 * the checksum operation succeeded (ACPI Spec 1.0b Section 6.4.2.8)
148 */
149 temp8 = 0;
150
151 *buffer = temp8;
152 buffer += 1;
153
154 /*
155 * Return the number of bytes consumed in this operation
156 */
157 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
158 return_ACPI_STATUS (AE_OK);
159}
160
161
162/*******************************************************************************
163 *
164 * FUNCTION: acpi_rs_vendor_resource
165 *
166 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
167 * stream
168 * bytes_consumed - Pointer to where the number of bytes
169 * consumed the byte_stream_buffer is
170 * returned
171 * output_buffer - Pointer to the return data buffer
172 * structure_size - Pointer to where the number of bytes
173 * in the return data struct is returned
174 *
175 * RETURN: Status
176 *
177 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
178 * structure pointed to by the output_buffer. Return the
179 * number of bytes consumed from the byte stream.
180 *
181 ******************************************************************************/
182
183acpi_status
184acpi_rs_vendor_resource (
185 u8 *byte_stream_buffer,
186 acpi_size *bytes_consumed,
187 u8 **output_buffer,
188 acpi_size *structure_size)
189{
190 u8 *buffer = byte_stream_buffer;
191 struct acpi_resource *output_struct = (void *) *output_buffer;
192 u16 temp16 = 0;
193 u8 temp8 = 0;
194 u8 index;
195 acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor);
196
197
198 ACPI_FUNCTION_TRACE ("rs_vendor_resource");
199
200
201 /*
202 * Dereference the Descriptor to find if this is a large or small item.
203 */
204 temp8 = *buffer;
205
206 if (temp8 & 0x80) {
207 /*
208 * Large Item, point to the length field
209 */
210 buffer += 1;
211
212 /* Dereference */
213
214 ACPI_MOVE_16_TO_16 (&temp16, buffer);
215
216 /* Calculate bytes consumed */
217
218 *bytes_consumed = (acpi_size) temp16 + 3;
219
220 /* Point to the first vendor byte */
221
222 buffer += 2;
223 }
224 else {
225 /*
226 * Small Item, dereference the size
227 */
228 temp16 = (u8)(*buffer & 0x07);
229
230 /* Calculate bytes consumed */
231
232 *bytes_consumed = (acpi_size) temp16 + 1;
233
234 /* Point to the first vendor byte */
235
236 buffer += 1;
237 }
238
239 output_struct->id = ACPI_RSTYPE_VENDOR;
240 output_struct->data.vendor_specific.length = temp16;
241
242 for (index = 0; index < temp16; index++) {
243 output_struct->data.vendor_specific.reserved[index] = *buffer;
244 buffer += 1;
245 }
246
247 /*
248 * In order for the struct_size to fall on a 32-bit boundary,
249 * calculate the length of the vendor string and expand the
250 * struct_size to the next 32-bit boundary.
251 */
252 struct_size += ACPI_ROUND_UP_to_32_bITS (temp16);
253
254 /*
255 * Set the Length parameter
256 */
257 output_struct->length = (u32) struct_size;
258
259 /*
260 * Return the final size of the structure
261 */
262 *structure_size = struct_size;
263 return_ACPI_STATUS (AE_OK);
264}
265
266
267/*******************************************************************************
268 *
269 * FUNCTION: acpi_rs_vendor_stream
270 *
271 * PARAMETERS: linked_list - Pointer to the resource linked list
272 * output_buffer - Pointer to the user's return buffer
273 * bytes_consumed - Pointer to where the number of bytes
274 * used in the output_buffer is returned
275 *
276 * RETURN: Status
277 *
278 * DESCRIPTION: Take the linked list resource structure and fills in the
279 * the appropriate bytes in a byte stream
280 *
281 ******************************************************************************/
282
283acpi_status
284acpi_rs_vendor_stream (
285 struct acpi_resource *linked_list,
286 u8 **output_buffer,
287 acpi_size *bytes_consumed)
288{
289 u8 *buffer = *output_buffer;
290 u16 temp16 = 0;
291 u8 temp8 = 0;
292 u8 index;
293
294
295 ACPI_FUNCTION_TRACE ("rs_vendor_stream");
296
297
298 /*
299 * Dereference the length to find if this is a large or small item.
300 */
301 if(linked_list->data.vendor_specific.length > 7) {
302 /*
303 * Large Item, Set the descriptor field and length bytes
304 */
305 *buffer = 0x84;
306 buffer += 1;
307
308 temp16 = (u16) linked_list->data.vendor_specific.length;
309
310 ACPI_MOVE_16_TO_16 (buffer, &temp16);
311 buffer += 2;
312 }
313 else {
314 /*
315 * Small Item, Set the descriptor field
316 */
317 temp8 = 0x70;
318 temp8 |= (u8) linked_list->data.vendor_specific.length;
319
320 *buffer = temp8;
321 buffer += 1;
322 }
323
324 /*
325 * Loop through all of the Vendor Specific fields
326 */
327 for (index = 0; index < linked_list->data.vendor_specific.length; index++) {
328 temp8 = linked_list->data.vendor_specific.reserved[index];
329
330 *buffer = temp8;
331 buffer += 1;
332 }
333
334 /*
335 * Return the number of bytes consumed in this operation
336 */
337 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
338 return_ACPI_STATUS (AE_OK);
339}
340
341
342/*******************************************************************************
343 *
344 * FUNCTION: acpi_rs_start_depend_fns_resource
345 *
346 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
347 * stream
348 * bytes_consumed - Pointer to where the number of bytes
349 * consumed the byte_stream_buffer is
350 * returned
351 * output_buffer - Pointer to the return data buffer
352 * structure_size - Pointer to where the number of bytes
353 * in the return data struct is returned
354 *
355 * RETURN: Status
356 *
357 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
358 * structure pointed to by the output_buffer. Return the
359 * number of bytes consumed from the byte stream.
360 *
361 ******************************************************************************/
362
363acpi_status
364acpi_rs_start_depend_fns_resource (
365 u8 *byte_stream_buffer,
366 acpi_size *bytes_consumed,
367 u8 **output_buffer,
368 acpi_size *structure_size)
369{
370 u8 *buffer = byte_stream_buffer;
371 struct acpi_resource *output_struct = (void *) *output_buffer;
372 u8 temp8 = 0;
373 acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_start_dpf);
374
375
376 ACPI_FUNCTION_TRACE ("rs_start_depend_fns_resource");
377
378
379 /*
380 * The number of bytes consumed are contained in the descriptor (Bits:0-1)
381 */
382 temp8 = *buffer;
383
384 *bytes_consumed = (temp8 & 0x01) + 1;
385
386 output_struct->id = ACPI_RSTYPE_START_DPF;
387
388 /*
389 * Point to Byte 1 if it is used
390 */
391 if (2 == *bytes_consumed) {
392 buffer += 1;
393 temp8 = *buffer;
394
395 /*
396 * Check Compatibility priority
397 */
398 output_struct->data.start_dpf.compatibility_priority = temp8 & 0x03;
399
400 if (3 == output_struct->data.start_dpf.compatibility_priority) {
401 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE);
402 }
403
404 /*
405 * Check Performance/Robustness preference
406 */
407 output_struct->data.start_dpf.performance_robustness = (temp8 >> 2) & 0x03;
408
409 if (3 == output_struct->data.start_dpf.performance_robustness) {
410 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE);
411 }
412 }
413 else {
414 output_struct->data.start_dpf.compatibility_priority =
415 ACPI_ACCEPTABLE_CONFIGURATION;
416
417 output_struct->data.start_dpf.performance_robustness =
418 ACPI_ACCEPTABLE_CONFIGURATION;
419 }
420
421 /*
422 * Set the Length parameter
423 */
424 output_struct->length = (u32) struct_size;
425
426 /*
427 * Return the final size of the structure
428 */
429 *structure_size = struct_size;
430 return_ACPI_STATUS (AE_OK);
431}
432
433
434/*******************************************************************************
435 *
436 * FUNCTION: acpi_rs_end_depend_fns_resource
437 *
438 * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
439 * stream
440 * bytes_consumed - Pointer to where the number of bytes
441 * consumed the byte_stream_buffer is
442 * returned
443 * output_buffer - Pointer to the return data buffer
444 * structure_size - Pointer to where the number of bytes
445 * in the return data struct is returned
446 *
447 * RETURN: Status
448 *
449 * DESCRIPTION: Take the resource byte stream and fill out the appropriate
450 * structure pointed to by the output_buffer. Return the
451 * number of bytes consumed from the byte stream.
452 *
453 ******************************************************************************/
454
455acpi_status
456acpi_rs_end_depend_fns_resource (
457 u8 *byte_stream_buffer,
458 acpi_size *bytes_consumed,
459 u8 **output_buffer,
460 acpi_size *structure_size)
461{
462 struct acpi_resource *output_struct = (void *) *output_buffer;
463 acpi_size struct_size = ACPI_RESOURCE_LENGTH;
464
465
466 ACPI_FUNCTION_TRACE ("rs_end_depend_fns_resource");
467
468
469 /*
470 * The number of bytes consumed is static
471 */
472 *bytes_consumed = 1;
473
474 /*
475 * Fill out the structure
476 */
477 output_struct->id = ACPI_RSTYPE_END_DPF;
478
479 /*
480 * Set the Length parameter
481 */
482 output_struct->length = (u32) struct_size;
483
484 /*
485 * Return the final size of the structure
486 */
487 *structure_size = struct_size;
488 return_ACPI_STATUS (AE_OK);
489}
490
491
492/*******************************************************************************
493 *
494 * FUNCTION: acpi_rs_start_depend_fns_stream
495 *
496 * PARAMETERS: linked_list - Pointer to the resource linked list
497 * output_buffer - Pointer to the user's return buffer
498 * bytes_consumed - u32 pointer that is filled with
499 * the number of bytes of the
500 * output_buffer used
501 *
502 * RETURN: Status
503 *
504 * DESCRIPTION: Take the linked list resource structure and fills in the
505 * the appropriate bytes in a byte stream
506 *
507 ******************************************************************************/
508
509acpi_status
510acpi_rs_start_depend_fns_stream (
511 struct acpi_resource *linked_list,
512 u8 **output_buffer,
513 acpi_size *bytes_consumed)
514{
515 u8 *buffer = *output_buffer;
516 u8 temp8 = 0;
517
518
519 ACPI_FUNCTION_TRACE ("rs_start_depend_fns_stream");
520
521
522 /*
523 * The descriptor field is set based upon whether a byte is needed
524 * to contain Priority data.
525 */
526 if (ACPI_ACCEPTABLE_CONFIGURATION ==
527 linked_list->data.start_dpf.compatibility_priority &&
528 ACPI_ACCEPTABLE_CONFIGURATION ==
529 linked_list->data.start_dpf.performance_robustness) {
530 *buffer = 0x30;
531 }
532 else {
533 *buffer = 0x31;
534 buffer += 1;
535
536 /*
537 * Set the Priority Byte Definition
538 */
539 temp8 = 0;
540 temp8 = (u8) ((linked_list->data.start_dpf.performance_robustness &
541 0x03) << 2);
542 temp8 |= (linked_list->data.start_dpf.compatibility_priority &
543 0x03);
544 *buffer = temp8;
545 }
546
547 buffer += 1;
548
549 /*
550 * Return the number of bytes consumed in this operation
551 */
552 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
553 return_ACPI_STATUS (AE_OK);
554}
555
556
557/*******************************************************************************
558 *
559 * FUNCTION: acpi_rs_end_depend_fns_stream
560 *
561 * PARAMETERS: linked_list - Pointer to the resource linked list
562 * output_buffer - Pointer to the user's return buffer
563 * bytes_consumed - Pointer to where the number of bytes
564 * used in the output_buffer is returned
565 *
566 * RETURN: Status
567 *
568 * DESCRIPTION: Take the linked list resource structure and fills in the
569 * the appropriate bytes in a byte stream
570 *
571 ******************************************************************************/
572
573acpi_status
574acpi_rs_end_depend_fns_stream (
575 struct acpi_resource *linked_list,
576 u8 **output_buffer,
577 acpi_size *bytes_consumed)
578{
579 u8 *buffer = *output_buffer;
580
581
582 ACPI_FUNCTION_TRACE ("rs_end_depend_fns_stream");
583
584
585 /*
586 * The descriptor field is static
587 */
588 *buffer = 0x38;
589 buffer += 1;
590
591 /*
592 * Return the number of bytes consumed in this operation
593 */
594 *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
595 return_ACPI_STATUS (AE_OK);
596}
597
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
new file mode 100644
index 000000000000..ee9ce13c053d
--- /dev/null
+++ b/drivers/acpi/resources/rsutils.c
@@ -0,0 +1,356 @@
1/*******************************************************************************
2 *
3 * Module Name: rsutils - Utilities for the resource manager
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acresrc.h>
48
49
50#define _COMPONENT ACPI_RESOURCES
51 ACPI_MODULE_NAME ("rsutils")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_rs_get_prt_method_data
57 *
58 * PARAMETERS: Handle - a handle to the containing object
59 * ret_buffer - a pointer to a buffer structure for the
60 * results
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: This function is called to get the _PRT value of an object
65 * contained in an object specified by the handle passed in
66 *
67 * If the function fails an appropriate status will be returned
68 * and the contents of the callers buffer is undefined.
69 *
70 ******************************************************************************/
71
72acpi_status
73acpi_rs_get_prt_method_data (
74 acpi_handle handle,
75 struct acpi_buffer *ret_buffer)
76{
77 union acpi_operand_object *obj_desc;
78 acpi_status status;
79
80
81 ACPI_FUNCTION_TRACE ("rs_get_prt_method_data");
82
83
84 /* Parameters guaranteed valid by caller */
85
86 /*
87 * Execute the method, no parameters
88 */
89 status = acpi_ut_evaluate_object (handle, "_PRT", ACPI_BTYPE_PACKAGE, &obj_desc);
90 if (ACPI_FAILURE (status)) {
91 return_ACPI_STATUS (status);
92 }
93
94 /*
95 * Create a resource linked list from the byte stream buffer that comes
96 * back from the _CRS method execution.
97 */
98 status = acpi_rs_create_pci_routing_table (obj_desc, ret_buffer);
99
100 /* On exit, we must delete the object returned by evaluate_object */
101
102 acpi_ut_remove_reference (obj_desc);
103 return_ACPI_STATUS (status);
104}
105
106
107/*******************************************************************************
108 *
109 * FUNCTION: acpi_rs_get_crs_method_data
110 *
111 * PARAMETERS: Handle - a handle to the containing object
112 * ret_buffer - a pointer to a buffer structure for the
113 * results
114 *
115 * RETURN: Status
116 *
117 * DESCRIPTION: This function is called to get the _CRS value of an object
118 * contained in an object specified by the handle passed in
119 *
120 * If the function fails an appropriate status will be returned
121 * and the contents of the callers buffer is undefined.
122 *
123 ******************************************************************************/
124
125acpi_status
126acpi_rs_get_crs_method_data (
127 acpi_handle handle,
128 struct acpi_buffer *ret_buffer)
129{
130 union acpi_operand_object *obj_desc;
131 acpi_status status;
132
133
134 ACPI_FUNCTION_TRACE ("rs_get_crs_method_data");
135
136
137 /* Parameters guaranteed valid by caller */
138
139 /*
140 * Execute the method, no parameters
141 */
142 status = acpi_ut_evaluate_object (handle, "_CRS", ACPI_BTYPE_BUFFER, &obj_desc);
143 if (ACPI_FAILURE (status)) {
144 return_ACPI_STATUS (status);
145 }
146
147 /*
148 * Make the call to create a resource linked list from the
149 * byte stream buffer that comes back from the _CRS method
150 * execution.
151 */
152 status = acpi_rs_create_resource_list (obj_desc, ret_buffer);
153
154 /* on exit, we must delete the object returned by evaluate_object */
155
156 acpi_ut_remove_reference (obj_desc);
157 return_ACPI_STATUS (status);
158}
159
160
161/*******************************************************************************
162 *
163 * FUNCTION: acpi_rs_get_prs_method_data
164 *
165 * PARAMETERS: Handle - a handle to the containing object
166 * ret_buffer - a pointer to a buffer structure for the
167 * results
168 *
169 * RETURN: Status
170 *
171 * DESCRIPTION: This function is called to get the _PRS value of an object
172 * contained in an object specified by the handle passed in
173 *
174 * If the function fails an appropriate status will be returned
175 * and the contents of the callers buffer is undefined.
176 *
177 ******************************************************************************/
178#ifdef ACPI_FUTURE_USAGE
179acpi_status
180acpi_rs_get_prs_method_data (
181 acpi_handle handle,
182 struct acpi_buffer *ret_buffer)
183{
184 union acpi_operand_object *obj_desc;
185 acpi_status status;
186
187
188 ACPI_FUNCTION_TRACE ("rs_get_prs_method_data");
189
190
191 /* Parameters guaranteed valid by caller */
192
193 /*
194 * Execute the method, no parameters
195 */
196 status = acpi_ut_evaluate_object (handle, "_PRS", ACPI_BTYPE_BUFFER, &obj_desc);
197 if (ACPI_FAILURE (status)) {
198 return_ACPI_STATUS (status);
199 }
200
201 /*
202 * Make the call to create a resource linked list from the
203 * byte stream buffer that comes back from the _CRS method
204 * execution.
205 */
206 status = acpi_rs_create_resource_list (obj_desc, ret_buffer);
207
208 /* on exit, we must delete the object returned by evaluate_object */
209
210 acpi_ut_remove_reference (obj_desc);
211 return_ACPI_STATUS (status);
212}
213#endif /* ACPI_FUTURE_USAGE */
214
215
216/*******************************************************************************
217 *
218 * FUNCTION: acpi_rs_get_method_data
219 *
220 * PARAMETERS: Handle - a handle to the containing object
221 * ret_buffer - a pointer to a buffer structure for the
222 * results
223 *
224 * RETURN: Status
225 *
226 * DESCRIPTION: This function is called to get the _CRS or _PRS value of an
227 * object contained in an object specified by the handle passed in
228 *
229 * If the function fails an appropriate status will be returned
230 * and the contents of the callers buffer is undefined.
231 *
232 ******************************************************************************/
233
234acpi_status
235acpi_rs_get_method_data (
236 acpi_handle handle,
237 char *path,
238 struct acpi_buffer *ret_buffer)
239{
240 union acpi_operand_object *obj_desc;
241 acpi_status status;
242
243
244 ACPI_FUNCTION_TRACE ("rs_get_method_data");
245
246
247 /* Parameters guaranteed valid by caller */
248
249 /*
250 * Execute the method, no parameters
251 */
252 status = acpi_ut_evaluate_object (handle, path, ACPI_BTYPE_BUFFER, &obj_desc);
253 if (ACPI_FAILURE (status)) {
254 return_ACPI_STATUS (status);
255 }
256
257 /*
258 * Make the call to create a resource linked list from the
259 * byte stream buffer that comes back from the method
260 * execution.
261 */
262 status = acpi_rs_create_resource_list (obj_desc, ret_buffer);
263
264 /* On exit, we must delete the object returned by evaluate_object */
265
266 acpi_ut_remove_reference (obj_desc);
267 return_ACPI_STATUS (status);
268}
269
270/*******************************************************************************
271 *
272 * FUNCTION: acpi_rs_set_srs_method_data
273 *
274 * PARAMETERS: Handle - a handle to the containing object
275 * in_buffer - a pointer to a buffer structure of the
276 * parameter
277 *
278 * RETURN: Status
279 *
280 * DESCRIPTION: This function is called to set the _SRS of an object contained
281 * in an object specified by the handle passed in
282 *
283 * If the function fails an appropriate status will be returned
284 * and the contents of the callers buffer is undefined.
285 *
286 ******************************************************************************/
287
288acpi_status
289acpi_rs_set_srs_method_data (
290 acpi_handle handle,
291 struct acpi_buffer *in_buffer)
292{
293 struct acpi_parameter_info info;
294 union acpi_operand_object *params[2];
295 acpi_status status;
296 struct acpi_buffer buffer;
297
298
299 ACPI_FUNCTION_TRACE ("rs_set_srs_method_data");
300
301
302 /* Parameters guaranteed valid by caller */
303
304 /*
305 * The in_buffer parameter will point to a linked list of
306 * resource parameters. It needs to be formatted into a
307 * byte stream to be sent in as an input parameter to _SRS
308 *
309 * Convert the linked list into a byte stream
310 */
311 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
312 status = acpi_rs_create_byte_stream (in_buffer->pointer, &buffer);
313 if (ACPI_FAILURE (status)) {
314 return_ACPI_STATUS (status);
315 }
316
317 /*
318 * Init the param object
319 */
320 params[0] = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
321 if (!params[0]) {
322 acpi_os_free (buffer.pointer);
323 return_ACPI_STATUS (AE_NO_MEMORY);
324 }
325
326 /*
327 * Set up the parameter object
328 */
329 params[0]->buffer.length = (u32) buffer.length;
330 params[0]->buffer.pointer = buffer.pointer;
331 params[0]->common.flags = AOPOBJ_DATA_VALID;
332 params[1] = NULL;
333
334 info.node = handle;
335 info.parameters = params;
336 info.parameter_type = ACPI_PARAM_ARGS;
337
338 /*
339 * Execute the method, no return value
340 */
341 status = acpi_ns_evaluate_relative ("_SRS", &info);
342 if (ACPI_SUCCESS (status)) {
343 /* Delete any return object (especially if implicit_return is enabled) */
344
345 if (info.return_object) {
346 acpi_ut_remove_reference (info.return_object);
347 }
348 }
349
350 /*
351 * Clean up and return the status from acpi_ns_evaluate_relative
352 */
353 acpi_ut_remove_reference (params[0]);
354 return_ACPI_STATUS (status);
355}
356
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
new file mode 100644
index 000000000000..a9cdcbeb3432
--- /dev/null
+++ b/drivers/acpi/resources/rsxface.c
@@ -0,0 +1,437 @@
1/*******************************************************************************
2 *
3 * Module Name: rsxface - Public interfaces to the resource manager
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <linux/module.h>
45
46#include <acpi/acpi.h>
47#include <acpi/acresrc.h>
48
49#define _COMPONENT ACPI_RESOURCES
50 ACPI_MODULE_NAME ("rsxface")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_get_irq_routing_table
56 *
57 * PARAMETERS: device_handle - a handle to the Bus device we are querying
58 * ret_buffer - a pointer to a buffer to receive the
59 * current resources for the device
60 *
61 * RETURN: Status
62 *
63 * DESCRIPTION: This function is called to get the IRQ routing table for a
64 * specific bus. The caller must first acquire a handle for the
65 * desired bus. The routine table is placed in the buffer pointed
66 * to by the ret_buffer variable parameter.
67 *
68 * If the function fails an appropriate status will be returned
69 * and the value of ret_buffer is undefined.
70 *
71 * This function attempts to execute the _PRT method contained in
72 * the object indicated by the passed device_handle.
73 *
74 ******************************************************************************/
75
76acpi_status
77acpi_get_irq_routing_table (
78 acpi_handle device_handle,
79 struct acpi_buffer *ret_buffer)
80{
81 acpi_status status;
82
83
84 ACPI_FUNCTION_TRACE ("acpi_get_irq_routing_table ");
85
86
87 /*
88 * Must have a valid handle and buffer, So we have to have a handle
89 * and a return buffer structure, and if there is a non-zero buffer length
90 * we also need a valid pointer in the buffer. If it's a zero buffer length,
91 * we'll be returning the needed buffer size, so keep going.
92 */
93 if (!device_handle) {
94 return_ACPI_STATUS (AE_BAD_PARAMETER);
95 }
96
97 status = acpi_ut_validate_buffer (ret_buffer);
98 if (ACPI_FAILURE (status)) {
99 return_ACPI_STATUS (status);
100 }
101
102 status = acpi_rs_get_prt_method_data (device_handle, ret_buffer);
103 return_ACPI_STATUS (status);
104}
105
106
107/*******************************************************************************
108 *
109 * FUNCTION: acpi_get_current_resources
110 *
111 * PARAMETERS: device_handle - a handle to the device object for the
112 * device we are querying
113 * ret_buffer - a pointer to a buffer to receive the
114 * current resources for the device
115 *
116 * RETURN: Status
117 *
118 * DESCRIPTION: This function is called to get the current resources for a
119 * specific device. The caller must first acquire a handle for
120 * the desired device. The resource data is placed in the buffer
121 * pointed to by the ret_buffer variable parameter.
122 *
123 * If the function fails an appropriate status will be returned
124 * and the value of ret_buffer is undefined.
125 *
126 * This function attempts to execute the _CRS method contained in
127 * the object indicated by the passed device_handle.
128 *
129 ******************************************************************************/
130
131acpi_status
132acpi_get_current_resources (
133 acpi_handle device_handle,
134 struct acpi_buffer *ret_buffer)
135{
136 acpi_status status;
137
138
139 ACPI_FUNCTION_TRACE ("acpi_get_current_resources");
140
141
142 /*
143 * Must have a valid handle and buffer, So we have to have a handle
144 * and a return buffer structure, and if there is a non-zero buffer length
145 * we also need a valid pointer in the buffer. If it's a zero buffer length,
146 * we'll be returning the needed buffer size, so keep going.
147 */
148 if (!device_handle) {
149 return_ACPI_STATUS (AE_BAD_PARAMETER);
150 }
151
152 status = acpi_ut_validate_buffer (ret_buffer);
153 if (ACPI_FAILURE (status)) {
154 return_ACPI_STATUS (status);
155 }
156
157 status = acpi_rs_get_crs_method_data (device_handle, ret_buffer);
158 return_ACPI_STATUS (status);
159}
160EXPORT_SYMBOL(acpi_get_current_resources);
161
162
163/*******************************************************************************
164 *
165 * FUNCTION: acpi_get_possible_resources
166 *
167 * PARAMETERS: device_handle - a handle to the device object for the
168 * device we are querying
169 * ret_buffer - a pointer to a buffer to receive the
170 * resources for the device
171 *
172 * RETURN: Status
173 *
174 * DESCRIPTION: This function is called to get a list of the possible resources
175 * for a specific device. The caller must first acquire a handle
176 * for the desired device. The resource data is placed in the
177 * buffer pointed to by the ret_buffer variable.
178 *
179 * If the function fails an appropriate status will be returned
180 * and the value of ret_buffer is undefined.
181 *
182 ******************************************************************************/
183#ifdef ACPI_FUTURE_USAGE
184acpi_status
185acpi_get_possible_resources (
186 acpi_handle device_handle,
187 struct acpi_buffer *ret_buffer)
188{
189 acpi_status status;
190
191
192 ACPI_FUNCTION_TRACE ("acpi_get_possible_resources");
193
194
195 /*
196 * Must have a valid handle and buffer, So we have to have a handle
197 * and a return buffer structure, and if there is a non-zero buffer length
198 * we also need a valid pointer in the buffer. If it's a zero buffer length,
199 * we'll be returning the needed buffer size, so keep going.
200 */
201 if (!device_handle) {
202 return_ACPI_STATUS (AE_BAD_PARAMETER);
203 }
204
205 status = acpi_ut_validate_buffer (ret_buffer);
206 if (ACPI_FAILURE (status)) {
207 return_ACPI_STATUS (status);
208 }
209
210 status = acpi_rs_get_prs_method_data (device_handle, ret_buffer);
211 return_ACPI_STATUS (status);
212}
213EXPORT_SYMBOL(acpi_get_possible_resources);
214#endif /* ACPI_FUTURE_USAGE */
215
216
217/*******************************************************************************
218 *
219 * FUNCTION: acpi_walk_resources
220 *
221 * PARAMETERS: device_handle - a handle to the device object for the
222 * device we are querying
223 * Path - method name of the resources we want
224 * (METHOD_NAME__CRS or METHOD_NAME__PRS)
225 * user_function - called for each resource
226 * Context - passed to user_function
227 *
228 * RETURN: Status
229 *
230 * DESCRIPTION: Retrieves the current or possible resource list for the
231 * specified device. The user_function is called once for
232 * each resource in the list.
233 *
234 ******************************************************************************/
235
236acpi_status
237acpi_walk_resources (
238 acpi_handle device_handle,
239 char *path,
240 ACPI_WALK_RESOURCE_CALLBACK user_function,
241 void *context)
242{
243 acpi_status status;
244 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
245 struct acpi_resource *resource;
246 struct acpi_resource *buffer_end;
247
248
249 ACPI_FUNCTION_TRACE ("acpi_walk_resources");
250
251
252 if (!device_handle ||
253 (ACPI_STRNCMP (path, METHOD_NAME__CRS, sizeof (METHOD_NAME__CRS)) &&
254 ACPI_STRNCMP (path, METHOD_NAME__PRS, sizeof (METHOD_NAME__PRS)))) {
255 return_ACPI_STATUS (AE_BAD_PARAMETER);
256 }
257
258 status = acpi_rs_get_method_data (device_handle, path, &buffer);
259 if (ACPI_FAILURE (status)) {
260 return_ACPI_STATUS (status);
261 }
262
263 /* Setup pointers */
264
265 resource = (struct acpi_resource *) buffer.pointer;
266 buffer_end = ACPI_CAST_PTR (struct acpi_resource,
267 ((u8 *) buffer.pointer + buffer.length));
268
269 /* Walk the resource list */
270
271 for (;;) {
272 if (!resource || resource->id == ACPI_RSTYPE_END_TAG) {
273 break;
274 }
275
276 status = user_function (resource, context);
277
278 switch (status) {
279 case AE_OK:
280 case AE_CTRL_DEPTH:
281
282 /* Just keep going */
283
284 status = AE_OK;
285 break;
286
287 case AE_CTRL_TERMINATE:
288
289 /* Exit now, with OK stats */
290
291 status = AE_OK;
292 goto cleanup;
293
294 default:
295
296 /* All others are valid exceptions */
297
298 goto cleanup;
299 }
300
301 /* Get the next resource descriptor */
302
303 resource = ACPI_NEXT_RESOURCE (resource);
304
305 /* Check for end-of-buffer */
306
307 if (resource >= buffer_end) {
308 goto cleanup;
309 }
310 }
311
312cleanup:
313
314 acpi_os_free (buffer.pointer);
315 return_ACPI_STATUS (status);
316}
317EXPORT_SYMBOL(acpi_walk_resources);
318
319
320/*******************************************************************************
321 *
322 * FUNCTION: acpi_set_current_resources
323 *
324 * PARAMETERS: device_handle - a handle to the device object for the
325 * device we are changing the resources of
326 * in_buffer - a pointer to a buffer containing the
327 * resources to be set for the device
328 *
329 * RETURN: Status
330 *
331 * DESCRIPTION: This function is called to set the current resources for a
332 * specific device. The caller must first acquire a handle for
333 * the desired device. The resource data is passed to the routine
334 * the buffer pointed to by the in_buffer variable.
335 *
336 ******************************************************************************/
337
338acpi_status
339acpi_set_current_resources (
340 acpi_handle device_handle,
341 struct acpi_buffer *in_buffer)
342{
343 acpi_status status;
344
345
346 ACPI_FUNCTION_TRACE ("acpi_set_current_resources");
347
348
349 /*
350 * Must have a valid handle and buffer
351 */
352 if ((!device_handle) ||
353 (!in_buffer) ||
354 (!in_buffer->pointer) ||
355 (!in_buffer->length)) {
356 return_ACPI_STATUS (AE_BAD_PARAMETER);
357 }
358
359 status = acpi_rs_set_srs_method_data (device_handle, in_buffer);
360 return_ACPI_STATUS (status);
361}
362EXPORT_SYMBOL(acpi_set_current_resources);
363
364
365#define ACPI_COPY_FIELD(out, in, field) ((out)->field = (in)->field)
366#define ACPI_COPY_ADDRESS(out, in) \
367 ACPI_COPY_FIELD(out, in, resource_type); \
368 ACPI_COPY_FIELD(out, in, producer_consumer); \
369 ACPI_COPY_FIELD(out, in, decode); \
370 ACPI_COPY_FIELD(out, in, min_address_fixed); \
371 ACPI_COPY_FIELD(out, in, max_address_fixed); \
372 ACPI_COPY_FIELD(out, in, attribute); \
373 ACPI_COPY_FIELD(out, in, granularity); \
374 ACPI_COPY_FIELD(out, in, min_address_range); \
375 ACPI_COPY_FIELD(out, in, max_address_range); \
376 ACPI_COPY_FIELD(out, in, address_translation_offset); \
377 ACPI_COPY_FIELD(out, in, address_length); \
378 ACPI_COPY_FIELD(out, in, resource_source);
379
380/******************************************************************************
381 *
382 * FUNCTION: acpi_resource_to_address64
383 *
384 * PARAMETERS: resource - Pointer to a resource
385 * out - Pointer to the users's return
386 * buffer (a struct
387 * struct acpi_resource_address64)
388 *
389 * RETURN: Status
390 *
391 * DESCRIPTION: If the resource is an address16, address32, or address64,
392 * copy it to the address64 return buffer. This saves the
393 * caller from having to duplicate code for different-sized
394 * addresses.
395 *
396 ******************************************************************************/
397
398acpi_status
399acpi_resource_to_address64 (
400 struct acpi_resource *resource,
401 struct acpi_resource_address64 *out)
402{
403 struct acpi_resource_address16 *address16;
404 struct acpi_resource_address32 *address32;
405
406
407 switch (resource->id) {
408 case ACPI_RSTYPE_ADDRESS16:
409
410 address16 = (struct acpi_resource_address16 *) &resource->data;
411 ACPI_COPY_ADDRESS(out, address16);
412 break;
413
414
415 case ACPI_RSTYPE_ADDRESS32:
416
417 address32 = (struct acpi_resource_address32 *) &resource->data;
418 ACPI_COPY_ADDRESS(out, address32);
419 break;
420
421
422 case ACPI_RSTYPE_ADDRESS64:
423
424 /* Simple copy for 64 bit source */
425
426 ACPI_MEMCPY (out, &resource->data, sizeof (struct acpi_resource_address64));
427 break;
428
429
430 default:
431 return (AE_BAD_PARAMETER);
432 }
433
434 return (AE_OK);
435}
436EXPORT_SYMBOL(acpi_resource_to_address64);
437
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
new file mode 100644
index 000000000000..e7ca06626566
--- /dev/null
+++ b/drivers/acpi/scan.c
@@ -0,0 +1,1379 @@
1/*
2 * scan.c - support for transforming the ACPI namespace into individual objects
3 */
4
5#include <linux/module.h>
6#include <linux/init.h>
7#include <linux/acpi.h>
8
9#include <acpi/acpi_drivers.h>
10#include <acpi/acinterp.h> /* for acpi_ex_eisa_id_to_string() */
11
12
13#define _COMPONENT ACPI_BUS_COMPONENT
14ACPI_MODULE_NAME ("scan")
15
16#define STRUCT_TO_INT(s) (*((int*)&s))
17
18extern struct acpi_device *acpi_root;
19
20
21#define ACPI_BUS_CLASS "system_bus"
22#define ACPI_BUS_HID "ACPI_BUS"
23#define ACPI_BUS_DRIVER_NAME "ACPI Bus Driver"
24#define ACPI_BUS_DEVICE_NAME "System Bus"
25
26static LIST_HEAD(acpi_device_list);
27DEFINE_SPINLOCK(acpi_device_lock);
28LIST_HEAD(acpi_wakeup_device_list);
29
30static int
31acpi_bus_trim(struct acpi_device *start,
32 int rmdevice);
33
34static void acpi_device_release(struct kobject * kobj)
35{
36 struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
37 if (dev->pnp.cid_list)
38 kfree(dev->pnp.cid_list);
39 kfree(dev);
40}
41
42struct acpi_device_attribute {
43 struct attribute attr;
44 ssize_t (*show)(struct acpi_device *, char *);
45 ssize_t (*store)(struct acpi_device *, const char *, size_t);
46};
47
48typedef void acpi_device_sysfs_files(struct kobject *,
49 const struct attribute *);
50
51static void setup_sys_fs_device_files(struct acpi_device *dev,
52 acpi_device_sysfs_files *func);
53
54#define create_sysfs_device_files(dev) \
55 setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_create_file)
56#define remove_sysfs_device_files(dev) \
57 setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_remove_file)
58
59
60#define to_acpi_device(n) container_of(n, struct acpi_device, kobj)
61#define to_handle_attr(n) container_of(n, struct acpi_device_attribute, attr);
62
63static ssize_t acpi_device_attr_show(struct kobject *kobj,
64 struct attribute *attr, char *buf)
65{
66 struct acpi_device *device = to_acpi_device(kobj);
67 struct acpi_device_attribute *attribute = to_handle_attr(attr);
68 return attribute->show ? attribute->show(device, buf) : 0;
69}
70static ssize_t acpi_device_attr_store(struct kobject *kobj,
71 struct attribute *attr, const char *buf, size_t len)
72{
73 struct acpi_device *device = to_acpi_device(kobj);
74 struct acpi_device_attribute *attribute = to_handle_attr(attr);
75 return attribute->store ? attribute->store(device, buf, len) : len;
76}
77
78static struct sysfs_ops acpi_device_sysfs_ops = {
79 .show = acpi_device_attr_show,
80 .store = acpi_device_attr_store,
81};
82
83static struct kobj_type ktype_acpi_ns = {
84 .sysfs_ops = &acpi_device_sysfs_ops,
85 .release = acpi_device_release,
86};
87
88static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
89 char **envp, int num_envp, char *buffer,
90 int buffer_size)
91{
92 struct acpi_device *dev = to_acpi_device(kobj);
93 int i = 0;
94 int len = 0;
95
96 if (!dev->driver)
97 return 0;
98
99 if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
100 "PHYSDEVDRIVER=%s", dev->driver->name))
101 return -ENOMEM;
102
103 envp[i] = NULL;
104
105 return 0;
106}
107
108static struct kset_hotplug_ops namespace_hotplug_ops = {
109 .hotplug = &namespace_hotplug,
110};
111
112static struct kset acpi_namespace_kset = {
113 .kobj = {
114 .name = "namespace",
115 },
116 .subsys = &acpi_subsys,
117 .ktype = &ktype_acpi_ns,
118 .hotplug_ops = &namespace_hotplug_ops,
119};
120
121
122static void acpi_device_register(struct acpi_device * device, struct acpi_device * parent)
123{
124 /*
125 * Linkage
126 * -------
127 * Link this device to its parent and siblings.
128 */
129 INIT_LIST_HEAD(&device->children);
130 INIT_LIST_HEAD(&device->node);
131 INIT_LIST_HEAD(&device->g_list);
132 INIT_LIST_HEAD(&device->wakeup_list);
133
134 spin_lock(&acpi_device_lock);
135 if (device->parent) {
136 list_add_tail(&device->node, &device->parent->children);
137 list_add_tail(&device->g_list,&device->parent->g_list);
138 } else
139 list_add_tail(&device->g_list,&acpi_device_list);
140 if (device->wakeup.flags.valid)
141 list_add_tail(&device->wakeup_list,&acpi_wakeup_device_list);
142 spin_unlock(&acpi_device_lock);
143
144 strlcpy(device->kobj.name,device->pnp.bus_id,KOBJ_NAME_LEN);
145 if (parent)
146 device->kobj.parent = &parent->kobj;
147 device->kobj.ktype = &ktype_acpi_ns;
148 device->kobj.kset = &acpi_namespace_kset;
149 kobject_register(&device->kobj);
150 create_sysfs_device_files(device);
151}
152
153static int
154acpi_device_unregister (
155 struct acpi_device *device,
156 int type)
157{
158 spin_lock(&acpi_device_lock);
159 if (device->parent) {
160 list_del(&device->node);
161 list_del(&device->g_list);
162 } else
163 list_del(&device->g_list);
164
165 list_del(&device->wakeup_list);
166
167 spin_unlock(&acpi_device_lock);
168
169 acpi_detach_data(device->handle, acpi_bus_data_handler);
170 remove_sysfs_device_files(device);
171 kobject_unregister(&device->kobj);
172 return 0;
173}
174
175void
176acpi_bus_data_handler (
177 acpi_handle handle,
178 u32 function,
179 void *context)
180{
181 ACPI_FUNCTION_TRACE("acpi_bus_data_handler");
182
183 /* TBD */
184
185 return_VOID;
186}
187
188static int
189acpi_bus_get_power_flags (
190 struct acpi_device *device)
191{
192 acpi_status status = 0;
193 acpi_handle handle = NULL;
194 u32 i = 0;
195
196 ACPI_FUNCTION_TRACE("acpi_bus_get_power_flags");
197
198 /*
199 * Power Management Flags
200 */
201 status = acpi_get_handle(device->handle, "_PSC", &handle);
202 if (ACPI_SUCCESS(status))
203 device->power.flags.explicit_get = 1;
204 status = acpi_get_handle(device->handle, "_IRC", &handle);
205 if (ACPI_SUCCESS(status))
206 device->power.flags.inrush_current = 1;
207
208 /*
209 * Enumerate supported power management states
210 */
211 for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) {
212 struct acpi_device_power_state *ps = &device->power.states[i];
213 char object_name[5] = {'_','P','R','0'+i,'\0'};
214
215 /* Evaluate "_PRx" to se if power resources are referenced */
216 acpi_evaluate_reference(device->handle, object_name, NULL,
217 &ps->resources);
218 if (ps->resources.count) {
219 device->power.flags.power_resources = 1;
220 ps->flags.valid = 1;
221 }
222
223 /* Evaluate "_PSx" to see if we can do explicit sets */
224 object_name[2] = 'S';
225 status = acpi_get_handle(device->handle, object_name, &handle);
226 if (ACPI_SUCCESS(status)) {
227 ps->flags.explicit_set = 1;
228 ps->flags.valid = 1;
229 }
230
231 /* State is valid if we have some power control */
232 if (ps->resources.count || ps->flags.explicit_set)
233 ps->flags.valid = 1;
234
235 ps->power = -1; /* Unknown - driver assigned */
236 ps->latency = -1; /* Unknown - driver assigned */
237 }
238
239 /* Set defaults for D0 and D3 states (always valid) */
240 device->power.states[ACPI_STATE_D0].flags.valid = 1;
241 device->power.states[ACPI_STATE_D0].power = 100;
242 device->power.states[ACPI_STATE_D3].flags.valid = 1;
243 device->power.states[ACPI_STATE_D3].power = 0;
244
245 /* TBD: System wake support and resource requirements. */
246
247 device->power.state = ACPI_STATE_UNKNOWN;
248
249 return_VALUE(0);
250}
251
252int
253acpi_match_ids (
254 struct acpi_device *device,
255 char *ids)
256{
257 int error = 0;
258 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
259
260 if (device->flags.hardware_id)
261 if (strstr(ids, device->pnp.hardware_id))
262 goto Done;
263
264 if (device->flags.compatible_ids) {
265 struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
266 int i;
267
268 /* compare multiple _CID entries against driver ids */
269 for (i = 0; i < cid_list->count; i++)
270 {
271 if (strstr(ids, cid_list->id[i].value))
272 goto Done;
273 }
274 }
275 error = -ENOENT;
276
277 Done:
278 if (buffer.pointer)
279 acpi_os_free(buffer.pointer);
280 return error;
281}
282
283static acpi_status
284acpi_bus_extract_wakeup_device_power_package (
285 struct acpi_device *device,
286 union acpi_object *package)
287{
288 int i = 0;
289 union acpi_object *element = NULL;
290
291 if (!device || !package || (package->package.count < 2))
292 return AE_BAD_PARAMETER;
293
294 element = &(package->package.elements[0]);
295 if (!element)
296 return AE_BAD_PARAMETER;
297 if (element->type == ACPI_TYPE_PACKAGE) {
298 if ((element->package.count < 2) ||
299 (element->package.elements[0].type != ACPI_TYPE_LOCAL_REFERENCE) ||
300 (element->package.elements[1].type != ACPI_TYPE_INTEGER))
301 return AE_BAD_DATA;
302 device->wakeup.gpe_device = element->package.elements[0].reference.handle;
303 device->wakeup.gpe_number = (u32)element->package.elements[1].integer.value;
304 }else if (element->type == ACPI_TYPE_INTEGER) {
305 device->wakeup.gpe_number = element->integer.value;
306 }else
307 return AE_BAD_DATA;
308
309 element = &(package->package.elements[1]);
310 if (element->type != ACPI_TYPE_INTEGER) {
311 return AE_BAD_DATA;
312 }
313 device->wakeup.sleep_state = element->integer.value;
314
315 if ((package->package.count - 2) > ACPI_MAX_HANDLES) {
316 return AE_NO_MEMORY;
317 }
318 device->wakeup.resources.count = package->package.count - 2;
319 for (i=0; i < device->wakeup.resources.count; i++) {
320 element = &(package->package.elements[i + 2]);
321 if (element->type != ACPI_TYPE_ANY ) {
322 return AE_BAD_DATA;
323 }
324
325 device->wakeup.resources.handles[i] = element->reference.handle;
326 }
327
328 return AE_OK;
329}
330
331static int
332acpi_bus_get_wakeup_device_flags (
333 struct acpi_device *device)
334{
335 acpi_status status = 0;
336 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
337 union acpi_object *package = NULL;
338
339 ACPI_FUNCTION_TRACE("acpi_bus_get_wakeup_flags");
340
341 /* _PRW */
342 status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
343 if (ACPI_FAILURE(status)) {
344 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRW\n"));
345 goto end;
346 }
347
348 package = (union acpi_object *) buffer.pointer;
349 status = acpi_bus_extract_wakeup_device_power_package(device, package);
350 if (ACPI_FAILURE(status)) {
351 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _PRW package\n"));
352 goto end;
353 }
354
355 acpi_os_free(buffer.pointer);
356
357 device->wakeup.flags.valid = 1;
358 /* Power button, Lid switch always enable wakeup*/
359 if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E"))
360 device->wakeup.flags.run_wake = 1;
361
362end:
363 if (ACPI_FAILURE(status))
364 device->flags.wake_capable = 0;
365 return_VALUE(0);
366}
367
368/* --------------------------------------------------------------------------
369 ACPI hotplug sysfs device file support
370 -------------------------------------------------------------------------- */
371static ssize_t acpi_eject_store(struct acpi_device *device,
372 const char *buf, size_t count);
373
374#define ACPI_DEVICE_ATTR(_name,_mode,_show,_store) \
375static struct acpi_device_attribute acpi_device_attr_##_name = \
376 __ATTR(_name, _mode, _show, _store)
377
378ACPI_DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
379
380/**
381 * setup_sys_fs_device_files - sets up the device files under device namespace
382 * @@dev: acpi_device object
383 * @@func: function pointer to create or destroy the device file
384 */
385static void
386setup_sys_fs_device_files (
387 struct acpi_device *dev,
388 acpi_device_sysfs_files *func)
389{
390 acpi_status status;
391 acpi_handle temp = NULL;
392
393 /*
394 * If device has _EJ0, 'eject' file is created that is used to trigger
395 * hot-removal function from userland.
396 */
397 status = acpi_get_handle(dev->handle, "_EJ0", &temp);
398 if (ACPI_SUCCESS(status))
399 (*(func))(&dev->kobj,&acpi_device_attr_eject.attr);
400}
401
402static int
403acpi_eject_operation(acpi_handle handle, int lockable)
404{
405 struct acpi_object_list arg_list;
406 union acpi_object arg;
407 acpi_status status = AE_OK;
408
409 /*
410 * TBD: evaluate _PS3?
411 */
412
413 if (lockable) {
414 arg_list.count = 1;
415 arg_list.pointer = &arg;
416 arg.type = ACPI_TYPE_INTEGER;
417 arg.integer.value = 0;
418 acpi_evaluate_object(handle, "_LCK", &arg_list, NULL);
419 }
420
421 arg_list.count = 1;
422 arg_list.pointer = &arg;
423 arg.type = ACPI_TYPE_INTEGER;
424 arg.integer.value = 1;
425
426 /*
427 * TBD: _EJD support.
428 */
429
430 status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
431 if (ACPI_FAILURE(status)) {
432 return(-ENODEV);
433 }
434
435 return(0);
436}
437
438
439static ssize_t
440acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
441{
442 int result;
443 int ret = count;
444 int islockable;
445 acpi_status status;
446 acpi_handle handle;
447 acpi_object_type type = 0;
448
449 if ((!count) || (buf[0] != '1')) {
450 return -EINVAL;
451 }
452
453#ifndef FORCE_EJECT
454 if (device->driver == NULL) {
455 ret = -ENODEV;
456 goto err;
457 }
458#endif
459 status = acpi_get_type(device->handle, &type);
460 if (ACPI_FAILURE(status) || (!device->flags.ejectable) ) {
461 ret = -ENODEV;
462 goto err;
463 }
464
465 islockable = device->flags.lockable;
466 handle = device->handle;
467
468 if (type == ACPI_TYPE_PROCESSOR)
469 result = acpi_bus_trim(device, 0);
470 else
471 result = acpi_bus_trim(device, 1);
472
473 if (!result)
474 result = acpi_eject_operation(handle, islockable);
475
476 if (result) {
477 ret = -EBUSY;
478 }
479err:
480 return ret;
481}
482
483
484/* --------------------------------------------------------------------------
485 Performance Management
486 -------------------------------------------------------------------------- */
487
488static int
489acpi_bus_get_perf_flags (
490 struct acpi_device *device)
491{
492 device->performance.state = ACPI_STATE_UNKNOWN;
493 return 0;
494}
495
496/* --------------------------------------------------------------------------
497 Driver Management
498 -------------------------------------------------------------------------- */
499
500static LIST_HEAD(acpi_bus_drivers);
501static DECLARE_MUTEX(acpi_bus_drivers_lock);
502
503
504/**
505 * acpi_bus_match
506 * --------------
507 * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it
508 * matches the specified driver's criteria.
509 */
510static int
511acpi_bus_match (
512 struct acpi_device *device,
513 struct acpi_driver *driver)
514{
515 if (driver && driver->ops.match)
516 return driver->ops.match(device, driver);
517 return acpi_match_ids(device, driver->ids);
518}
519
520
521/**
522 * acpi_bus_driver_init
523 * --------------------
524 * Used to initialize a device via its device driver. Called whenever a
525 * driver is bound to a device. Invokes the driver's add() and start() ops.
526 */
527static int
528acpi_bus_driver_init (
529 struct acpi_device *device,
530 struct acpi_driver *driver)
531{
532 int result = 0;
533
534 ACPI_FUNCTION_TRACE("acpi_bus_driver_init");
535
536 if (!device || !driver)
537 return_VALUE(-EINVAL);
538
539 if (!driver->ops.add)
540 return_VALUE(-ENOSYS);
541
542 result = driver->ops.add(device);
543 if (result) {
544 device->driver = NULL;
545 acpi_driver_data(device) = NULL;
546 return_VALUE(result);
547 }
548
549 device->driver = driver;
550
551 /*
552 * TBD - Configuration Management: Assign resources to device based
553 * upon possible configuration and currently allocated resources.
554 */
555
556 if (driver->ops.start) {
557 result = driver->ops.start(device);
558 if (result && driver->ops.remove)
559 driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
560 return_VALUE(result);
561 }
562
563 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
564
565 if (driver->ops.scan) {
566 driver->ops.scan(device);
567 }
568
569 return_VALUE(0);
570}
571
572static int acpi_driver_attach(struct acpi_driver * drv)
573{
574 struct list_head * node, * next;
575 int count = 0;
576
577 ACPI_FUNCTION_TRACE("acpi_driver_attach");
578
579 spin_lock(&acpi_device_lock);
580 list_for_each_safe(node, next, &acpi_device_list) {
581 struct acpi_device * dev = container_of(node, struct acpi_device, g_list);
582
583 if (dev->driver || !dev->status.present)
584 continue;
585 spin_unlock(&acpi_device_lock);
586
587 if (!acpi_bus_match(dev, drv)) {
588 if (!acpi_bus_driver_init(dev, drv)) {
589 atomic_inc(&drv->references);
590 count++;
591 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
592 drv->name, dev->pnp.bus_id));
593 }
594 }
595 spin_lock(&acpi_device_lock);
596 }
597 spin_unlock(&acpi_device_lock);
598 return_VALUE(count);
599}
600
601static int acpi_driver_detach(struct acpi_driver * drv)
602{
603 struct list_head * node, * next;
604
605 ACPI_FUNCTION_TRACE("acpi_driver_detach");
606
607 spin_lock(&acpi_device_lock);
608 list_for_each_safe(node,next,&acpi_device_list) {
609 struct acpi_device * dev = container_of(node,struct acpi_device,g_list);
610
611 if (dev->driver == drv) {
612 spin_unlock(&acpi_device_lock);
613 if (drv->ops.remove)
614 drv->ops.remove(dev,ACPI_BUS_REMOVAL_NORMAL);
615 spin_lock(&acpi_device_lock);
616 dev->driver = NULL;
617 dev->driver_data = NULL;
618 atomic_dec(&drv->references);
619 }
620 }
621 spin_unlock(&acpi_device_lock);
622 return_VALUE(0);
623}
624
625/**
626 * acpi_bus_register_driver
627 * ------------------------
628 * Registers a driver with the ACPI bus. Searches the namespace for all
629 * devices that match the driver's criteria and binds. Returns the
630 * number of devices that were claimed by the driver, or a negative
631 * error status for failure.
632 */
633int
634acpi_bus_register_driver (
635 struct acpi_driver *driver)
636{
637 int count;
638
639 ACPI_FUNCTION_TRACE("acpi_bus_register_driver");
640
641 if (acpi_disabled)
642 return_VALUE(-ENODEV);
643
644 if (!driver)
645 return_VALUE(-EINVAL);
646
647 spin_lock(&acpi_device_lock);
648 list_add_tail(&driver->node, &acpi_bus_drivers);
649 spin_unlock(&acpi_device_lock);
650 count = acpi_driver_attach(driver);
651
652 return_VALUE(count);
653}
654EXPORT_SYMBOL(acpi_bus_register_driver);
655
656
657/**
658 * acpi_bus_unregister_driver
659 * --------------------------
660 * Unregisters a driver with the ACPI bus. Searches the namespace for all
661 * devices that match the driver's criteria and unbinds.
662 */
663int
664acpi_bus_unregister_driver (
665 struct acpi_driver *driver)
666{
667 int error = 0;
668
669 ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver");
670
671 if (driver) {
672 acpi_driver_detach(driver);
673
674 if (!atomic_read(&driver->references)) {
675 spin_lock(&acpi_device_lock);
676 list_del_init(&driver->node);
677 spin_unlock(&acpi_device_lock);
678 }
679 } else
680 error = -EINVAL;
681 return_VALUE(error);
682}
683EXPORT_SYMBOL(acpi_bus_unregister_driver);
684
685/**
686 * acpi_bus_find_driver
687 * --------------------
688 * Parses the list of registered drivers looking for a driver applicable for
689 * the specified device.
690 */
691static int
692acpi_bus_find_driver (
693 struct acpi_device *device)
694{
695 int result = 0;
696 struct list_head * node, *next;
697
698 ACPI_FUNCTION_TRACE("acpi_bus_find_driver");
699
700 spin_lock(&acpi_device_lock);
701 list_for_each_safe(node,next,&acpi_bus_drivers) {
702 struct acpi_driver * driver = container_of(node,struct acpi_driver,node);
703
704 atomic_inc(&driver->references);
705 spin_unlock(&acpi_device_lock);
706 if (!acpi_bus_match(device, driver)) {
707 result = acpi_bus_driver_init(device, driver);
708 if (!result)
709 goto Done;
710 }
711 atomic_dec(&driver->references);
712 spin_lock(&acpi_device_lock);
713 }
714 spin_unlock(&acpi_device_lock);
715
716 Done:
717 return_VALUE(result);
718}
719
720
721/* --------------------------------------------------------------------------
722 Device Enumeration
723 -------------------------------------------------------------------------- */
724
725static int
726acpi_bus_get_flags (
727 struct acpi_device *device)
728{
729 acpi_status status = AE_OK;
730 acpi_handle temp = NULL;
731
732 ACPI_FUNCTION_TRACE("acpi_bus_get_flags");
733
734 /* Presence of _STA indicates 'dynamic_status' */
735 status = acpi_get_handle(device->handle, "_STA", &temp);
736 if (ACPI_SUCCESS(status))
737 device->flags.dynamic_status = 1;
738
739 /* Presence of _CID indicates 'compatible_ids' */
740 status = acpi_get_handle(device->handle, "_CID", &temp);
741 if (ACPI_SUCCESS(status))
742 device->flags.compatible_ids = 1;
743
744 /* Presence of _RMV indicates 'removable' */
745 status = acpi_get_handle(device->handle, "_RMV", &temp);
746 if (ACPI_SUCCESS(status))
747 device->flags.removable = 1;
748
749 /* Presence of _EJD|_EJ0 indicates 'ejectable' */
750 status = acpi_get_handle(device->handle, "_EJD", &temp);
751 if (ACPI_SUCCESS(status))
752 device->flags.ejectable = 1;
753 else {
754 status = acpi_get_handle(device->handle, "_EJ0", &temp);
755 if (ACPI_SUCCESS(status))
756 device->flags.ejectable = 1;
757 }
758
759 /* Presence of _LCK indicates 'lockable' */
760 status = acpi_get_handle(device->handle, "_LCK", &temp);
761 if (ACPI_SUCCESS(status))
762 device->flags.lockable = 1;
763
764 /* Presence of _PS0|_PR0 indicates 'power manageable' */
765 status = acpi_get_handle(device->handle, "_PS0", &temp);
766 if (ACPI_FAILURE(status))
767 status = acpi_get_handle(device->handle, "_PR0", &temp);
768 if (ACPI_SUCCESS(status))
769 device->flags.power_manageable = 1;
770
771 /* Presence of _PRW indicates wake capable */
772 status = acpi_get_handle(device->handle, "_PRW", &temp);
773 if (ACPI_SUCCESS(status))
774 device->flags.wake_capable = 1;
775
776 /* TBD: Peformance management */
777
778 return_VALUE(0);
779}
780
781static void acpi_device_get_busid(struct acpi_device * device, acpi_handle handle, int type)
782{
783 char bus_id[5] = {'?',0};
784 struct acpi_buffer buffer = {sizeof(bus_id), bus_id};
785 int i = 0;
786
787 /*
788 * Bus ID
789 * ------
790 * The device's Bus ID is simply the object name.
791 * TBD: Shouldn't this value be unique (within the ACPI namespace)?
792 */
793 switch (type) {
794 case ACPI_BUS_TYPE_SYSTEM:
795 strcpy(device->pnp.bus_id, "ACPI");
796 break;
797 case ACPI_BUS_TYPE_POWER_BUTTON:
798 strcpy(device->pnp.bus_id, "PWRF");
799 break;
800 case ACPI_BUS_TYPE_SLEEP_BUTTON:
801 strcpy(device->pnp.bus_id, "SLPF");
802 break;
803 default:
804 acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
805 /* Clean up trailing underscores (if any) */
806 for (i = 3; i > 1; i--) {
807 if (bus_id[i] == '_')
808 bus_id[i] = '\0';
809 else
810 break;
811 }
812 strcpy(device->pnp.bus_id, bus_id);
813 break;
814 }
815}
816
817static void acpi_device_set_id(struct acpi_device * device, struct acpi_device * parent,
818 acpi_handle handle, int type)
819{
820 struct acpi_device_info *info;
821 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
822 char *hid = NULL;
823 char *uid = NULL;
824 struct acpi_compatible_id_list *cid_list = NULL;
825 acpi_status status;
826
827 switch (type) {
828 case ACPI_BUS_TYPE_DEVICE:
829 status = acpi_get_object_info(handle, &buffer);
830 if (ACPI_FAILURE(status)) {
831 printk("%s: Error reading device info\n",__FUNCTION__);
832 return;
833 }
834
835 info = buffer.pointer;
836 if (info->valid & ACPI_VALID_HID)
837 hid = info->hardware_id.value;
838 if (info->valid & ACPI_VALID_UID)
839 uid = info->unique_id.value;
840 if (info->valid & ACPI_VALID_CID)
841 cid_list = &info->compatibility_id;
842 if (info->valid & ACPI_VALID_ADR) {
843 device->pnp.bus_address = info->address;
844 device->flags.bus_address = 1;
845 }
846 break;
847 case ACPI_BUS_TYPE_POWER:
848 hid = ACPI_POWER_HID;
849 break;
850 case ACPI_BUS_TYPE_PROCESSOR:
851 hid = ACPI_PROCESSOR_HID;
852 break;
853 case ACPI_BUS_TYPE_SYSTEM:
854 hid = ACPI_SYSTEM_HID;
855 break;
856 case ACPI_BUS_TYPE_THERMAL:
857 hid = ACPI_THERMAL_HID;
858 break;
859 case ACPI_BUS_TYPE_POWER_BUTTON:
860 hid = ACPI_BUTTON_HID_POWERF;
861 break;
862 case ACPI_BUS_TYPE_SLEEP_BUTTON:
863 hid = ACPI_BUTTON_HID_SLEEPF;
864 break;
865 }
866
867 /*
868 * \_SB
869 * ----
870 * Fix for the system root bus device -- the only root-level device.
871 */
872 if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
873 hid = ACPI_BUS_HID;
874 strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
875 strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
876 }
877
878 if (hid) {
879 strcpy(device->pnp.hardware_id, hid);
880 device->flags.hardware_id = 1;
881 }
882 if (uid) {
883 strcpy(device->pnp.unique_id, uid);
884 device->flags.unique_id = 1;
885 }
886 if (cid_list) {
887 device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL);
888 if (device->pnp.cid_list)
889 memcpy(device->pnp.cid_list, cid_list, cid_list->size);
890 else
891 printk(KERN_ERR "Memory allocation error\n");
892 }
893
894 acpi_os_free(buffer.pointer);
895}
896
897static int acpi_device_set_context(struct acpi_device * device, int type)
898{
899 acpi_status status = AE_OK;
900 int result = 0;
901 /*
902 * Context
903 * -------
904 * Attach this 'struct acpi_device' to the ACPI object. This makes
905 * resolutions from handle->device very efficient. Note that we need
906 * to be careful with fixed-feature devices as they all attach to the
907 * root object.
908 */
909 if (type != ACPI_BUS_TYPE_POWER_BUTTON &&
910 type != ACPI_BUS_TYPE_SLEEP_BUTTON) {
911 status = acpi_attach_data(device->handle,
912 acpi_bus_data_handler, device);
913
914 if (ACPI_FAILURE(status)) {
915 printk("Error attaching device data\n");
916 result = -ENODEV;
917 }
918 }
919 return result;
920}
921
922static void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type)
923{
924#ifdef CONFIG_ACPI_DEBUG_OUTPUT
925 char *type_string = NULL;
926 char name[80] = {'?','\0'};
927 struct acpi_buffer buffer = {sizeof(name), name};
928
929 switch (type) {
930 case ACPI_BUS_TYPE_DEVICE:
931 type_string = "Device";
932 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
933 break;
934 case ACPI_BUS_TYPE_POWER:
935 type_string = "Power Resource";
936 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
937 break;
938 case ACPI_BUS_TYPE_PROCESSOR:
939 type_string = "Processor";
940 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
941 break;
942 case ACPI_BUS_TYPE_SYSTEM:
943 type_string = "System";
944 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
945 break;
946 case ACPI_BUS_TYPE_THERMAL:
947 type_string = "Thermal Zone";
948 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
949 break;
950 case ACPI_BUS_TYPE_POWER_BUTTON:
951 type_string = "Power Button";
952 sprintf(name, "PWRB");
953 break;
954 case ACPI_BUS_TYPE_SLEEP_BUTTON:
955 type_string = "Sleep Button";
956 sprintf(name, "SLPB");
957 break;
958 }
959
960 printk(KERN_DEBUG "Found %s %s [%p]\n", type_string, name, handle);
961#endif /*CONFIG_ACPI_DEBUG_OUTPUT*/
962}
963
964
965static int
966acpi_bus_remove (
967 struct acpi_device *dev,
968 int rmdevice)
969{
970 int result = 0;
971 struct acpi_driver *driver;
972
973 ACPI_FUNCTION_TRACE("acpi_bus_remove");
974
975 if (!dev)
976 return_VALUE(-EINVAL);
977
978 driver = dev->driver;
979
980 if ((driver) && (driver->ops.remove)) {
981
982 if (driver->ops.stop) {
983 result = driver->ops.stop(dev, ACPI_BUS_REMOVAL_EJECT);
984 if (result)
985 return_VALUE(result);
986 }
987
988 result = dev->driver->ops.remove(dev, ACPI_BUS_REMOVAL_EJECT);
989 if (result) {
990 return_VALUE(result);
991 }
992
993 atomic_dec(&dev->driver->references);
994 dev->driver = NULL;
995 acpi_driver_data(dev) = NULL;
996 }
997
998 if (!rmdevice)
999 return_VALUE(0);
1000
1001 if (dev->flags.bus_address) {
1002 if ((dev->parent) && (dev->parent->ops.unbind))
1003 dev->parent->ops.unbind(dev);
1004 }
1005
1006 acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT);
1007
1008 return_VALUE(0);
1009}
1010
1011
1012int
1013acpi_bus_add (
1014 struct acpi_device **child,
1015 struct acpi_device *parent,
1016 acpi_handle handle,
1017 int type)
1018{
1019 int result = 0;
1020 struct acpi_device *device = NULL;
1021
1022 ACPI_FUNCTION_TRACE("acpi_bus_add");
1023
1024 if (!child)
1025 return_VALUE(-EINVAL);
1026
1027 device = kmalloc(sizeof(struct acpi_device), GFP_KERNEL);
1028 if (!device) {
1029 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Memory allocation error\n"));
1030 return_VALUE(-ENOMEM);
1031 }
1032 memset(device, 0, sizeof(struct acpi_device));
1033
1034 device->handle = handle;
1035 device->parent = parent;
1036
1037 acpi_device_get_busid(device,handle,type);
1038
1039 /*
1040 * Flags
1041 * -----
1042 * Get prior to calling acpi_bus_get_status() so we know whether
1043 * or not _STA is present. Note that we only look for object
1044 * handles -- cannot evaluate objects until we know the device is
1045 * present and properly initialized.
1046 */
1047 result = acpi_bus_get_flags(device);
1048 if (result)
1049 goto end;
1050
1051 /*
1052 * Status
1053 * ------
1054 * See if the device is present. We always assume that non-Device()
1055 * objects (e.g. thermal zones, power resources, processors, etc.) are
1056 * present, functioning, etc. (at least when parent object is present).
1057 * Note that _STA has a different meaning for some objects (e.g.
1058 * power resources) so we need to be careful how we use it.
1059 */
1060 switch (type) {
1061 case ACPI_BUS_TYPE_DEVICE:
1062 result = acpi_bus_get_status(device);
1063 if (ACPI_FAILURE(result) || !device->status.present) {
1064 result = -ENOENT;
1065 goto end;
1066 }
1067 break;
1068 default:
1069 STRUCT_TO_INT(device->status) = 0x0F;
1070 break;
1071 }
1072
1073 /*
1074 * Initialize Device
1075 * -----------------
1076 * TBD: Synch with Core's enumeration/initialization process.
1077 */
1078
1079 /*
1080 * Hardware ID, Unique ID, & Bus Address
1081 * -------------------------------------
1082 */
1083 acpi_device_set_id(device,parent,handle,type);
1084
1085 /*
1086 * Power Management
1087 * ----------------
1088 */
1089 if (device->flags.power_manageable) {
1090 result = acpi_bus_get_power_flags(device);
1091 if (result)
1092 goto end;
1093 }
1094
1095 /*
1096 * Wakeup device management
1097 *-----------------------
1098 */
1099 if (device->flags.wake_capable) {
1100 result = acpi_bus_get_wakeup_device_flags(device);
1101 if (result)
1102 goto end;
1103 }
1104
1105 /*
1106 * Performance Management
1107 * ----------------------
1108 */
1109 if (device->flags.performance_manageable) {
1110 result = acpi_bus_get_perf_flags(device);
1111 if (result)
1112 goto end;
1113 }
1114
1115 if ((result = acpi_device_set_context(device,type)))
1116 goto end;
1117
1118 acpi_device_get_debug_info(device,handle,type);
1119
1120 acpi_device_register(device,parent);
1121
1122 /*
1123 * Bind _ADR-Based Devices
1124 * -----------------------
1125 * If there's a a bus address (_ADR) then we utilize the parent's
1126 * 'bind' function (if exists) to bind the ACPI- and natively-
1127 * enumerated device representations.
1128 */
1129 if (device->flags.bus_address) {
1130 if (device->parent && device->parent->ops.bind)
1131 device->parent->ops.bind(device);
1132 }
1133
1134 /*
1135 * Locate & Attach Driver
1136 * ----------------------
1137 * If there's a hardware id (_HID) or compatible ids (_CID) we check
1138 * to see if there's a driver installed for this kind of device. Note
1139 * that drivers can install before or after a device is enumerated.
1140 *
1141 * TBD: Assumes LDM provides driver hot-plug capability.
1142 */
1143 acpi_bus_find_driver(device);
1144
1145end:
1146 if (!result)
1147 *child = device;
1148 else {
1149 if (device->pnp.cid_list)
1150 kfree(device->pnp.cid_list);
1151 kfree(device);
1152 }
1153
1154 return_VALUE(result);
1155}
1156EXPORT_SYMBOL(acpi_bus_add);
1157
1158
1159int acpi_bus_scan (struct acpi_device *start)
1160{
1161 acpi_status status = AE_OK;
1162 struct acpi_device *parent = NULL;
1163 struct acpi_device *child = NULL;
1164 acpi_handle phandle = NULL;
1165 acpi_handle chandle = NULL;
1166 acpi_object_type type = 0;
1167 u32 level = 1;
1168
1169 ACPI_FUNCTION_TRACE("acpi_bus_scan");
1170
1171 if (!start)
1172 return_VALUE(-EINVAL);
1173
1174 parent = start;
1175 phandle = start->handle;
1176
1177 /*
1178 * Parse through the ACPI namespace, identify all 'devices', and
1179 * create a new 'struct acpi_device' for each.
1180 */
1181 while ((level > 0) && parent) {
1182
1183 status = acpi_get_next_object(ACPI_TYPE_ANY, phandle,
1184 chandle, &chandle);
1185
1186 /*
1187 * If this scope is exhausted then move our way back up.
1188 */
1189 if (ACPI_FAILURE(status)) {
1190 level--;
1191 chandle = phandle;
1192 acpi_get_parent(phandle, &phandle);
1193 if (parent->parent)
1194 parent = parent->parent;
1195 continue;
1196 }
1197
1198 status = acpi_get_type(chandle, &type);
1199 if (ACPI_FAILURE(status))
1200 continue;
1201
1202 /*
1203 * If this is a scope object then parse it (depth-first).
1204 */
1205 if (type == ACPI_TYPE_LOCAL_SCOPE) {
1206 level++;
1207 phandle = chandle;
1208 chandle = NULL;
1209 continue;
1210 }
1211
1212 /*
1213 * We're only interested in objects that we consider 'devices'.
1214 */
1215 switch (type) {
1216 case ACPI_TYPE_DEVICE:
1217 type = ACPI_BUS_TYPE_DEVICE;
1218 break;
1219 case ACPI_TYPE_PROCESSOR:
1220 type = ACPI_BUS_TYPE_PROCESSOR;
1221 break;
1222 case ACPI_TYPE_THERMAL:
1223 type = ACPI_BUS_TYPE_THERMAL;
1224 break;
1225 case ACPI_TYPE_POWER:
1226 type = ACPI_BUS_TYPE_POWER;
1227 break;
1228 default:
1229 continue;
1230 }
1231
1232 status = acpi_bus_add(&child, parent, chandle, type);
1233 if (ACPI_FAILURE(status))
1234 continue;
1235
1236 /*
1237 * If the device is present, enabled, and functioning then
1238 * parse its scope (depth-first). Note that we need to
1239 * represent absent devices to facilitate PnP notifications
1240 * -- but only the subtree head (not all of its children,
1241 * which will be enumerated when the parent is inserted).
1242 *
1243 * TBD: Need notifications and other detection mechanisms
1244 * in place before we can fully implement this.
1245 */
1246 if (child->status.present) {
1247 status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,
1248 NULL, NULL);
1249 if (ACPI_SUCCESS(status)) {
1250 level++;
1251 phandle = chandle;
1252 chandle = NULL;
1253 parent = child;
1254 }
1255 }
1256 }
1257
1258 return_VALUE(0);
1259}
1260EXPORT_SYMBOL(acpi_bus_scan);
1261
1262
1263static int
1264acpi_bus_trim(struct acpi_device *start,
1265 int rmdevice)
1266{
1267 acpi_status status;
1268 struct acpi_device *parent, *child;
1269 acpi_handle phandle, chandle;
1270 acpi_object_type type;
1271 u32 level = 1;
1272 int err = 0;
1273
1274 parent = start;
1275 phandle = start->handle;
1276 child = chandle = NULL;
1277
1278 while ((level > 0) && parent && (!err)) {
1279 status = acpi_get_next_object(ACPI_TYPE_ANY, phandle,
1280 chandle, &chandle);
1281
1282 /*
1283 * If this scope is exhausted then move our way back up.
1284 */
1285 if (ACPI_FAILURE(status)) {
1286 level--;
1287 chandle = phandle;
1288 acpi_get_parent(phandle, &phandle);
1289 child = parent;
1290 parent = parent->parent;
1291
1292 if (level == 0)
1293 err = acpi_bus_remove(child, rmdevice);
1294 else
1295 err = acpi_bus_remove(child, 1);
1296
1297 continue;
1298 }
1299
1300 status = acpi_get_type(chandle, &type);
1301 if (ACPI_FAILURE(status)) {
1302 continue;
1303 }
1304 /*
1305 * If there is a device corresponding to chandle then
1306 * parse it (depth-first).
1307 */
1308 if (acpi_bus_get_device(chandle, &child) == 0) {
1309 level++;
1310 phandle = chandle;
1311 chandle = NULL;
1312 parent = child;
1313 }
1314 continue;
1315 }
1316 return err;
1317}
1318
1319static int
1320acpi_bus_scan_fixed (
1321 struct acpi_device *root)
1322{
1323 int result = 0;
1324 struct acpi_device *device = NULL;
1325
1326 ACPI_FUNCTION_TRACE("acpi_bus_scan_fixed");
1327
1328 if (!root)
1329 return_VALUE(-ENODEV);
1330
1331 /*
1332 * Enumerate all fixed-feature devices.
1333 */
1334 if (acpi_fadt.pwr_button == 0)
1335 result = acpi_bus_add(&device, acpi_root,
1336 NULL, ACPI_BUS_TYPE_POWER_BUTTON);
1337
1338 if (acpi_fadt.sleep_button == 0)
1339 result = acpi_bus_add(&device, acpi_root,
1340 NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
1341
1342 return_VALUE(result);
1343}
1344
1345
1346static int __init acpi_scan_init(void)
1347{
1348 int result;
1349
1350 ACPI_FUNCTION_TRACE("acpi_scan_init");
1351
1352 if (acpi_disabled)
1353 return_VALUE(0);
1354
1355 kset_register(&acpi_namespace_kset);
1356
1357 /*
1358 * Create the root device in the bus's device tree
1359 */
1360 result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT,
1361 ACPI_BUS_TYPE_SYSTEM);
1362 if (result)
1363 goto Done;
1364
1365 /*
1366 * Enumerate devices in the ACPI namespace.
1367 */
1368 result = acpi_bus_scan_fixed(acpi_root);
1369 if (!result)
1370 result = acpi_bus_scan(acpi_root);
1371
1372 if (result)
1373 acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
1374
1375 Done:
1376 return_VALUE(result);
1377}
1378
1379subsys_initcall(acpi_scan_init);
diff --git a/drivers/acpi/sleep/Makefile b/drivers/acpi/sleep/Makefile
new file mode 100644
index 000000000000..d6c017709c85
--- /dev/null
+++ b/drivers/acpi/sleep/Makefile
@@ -0,0 +1,5 @@
1obj-y := poweroff.o wakeup.o
2obj-$(CONFIG_ACPI_SLEEP) += main.o
3obj-$(CONFIG_ACPI_SLEEP_PROC_FS) += proc.o
4
5EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
new file mode 100644
index 000000000000..0a5d2a94131e
--- /dev/null
+++ b/drivers/acpi/sleep/main.c
@@ -0,0 +1,234 @@
1/*
2 * sleep.c - ACPI sleep support.
3 *
4 * Copyright (c) 2004 David Shaohua Li <shaohua.li@intel.com>
5 * Copyright (c) 2000-2003 Patrick Mochel
6 * Copyright (c) 2003 Open Source Development Lab
7 *
8 * This file is released under the GPLv2.
9 *
10 */
11
12#include <linux/delay.h>
13#include <linux/irq.h>
14#include <linux/dmi.h>
15#include <linux/device.h>
16#include <linux/suspend.h>
17#include <asm/io.h>
18#include <acpi/acpi_bus.h>
19#include <acpi/acpi_drivers.h>
20#include "sleep.h"
21
22u8 sleep_states[ACPI_S_STATE_COUNT];
23
24static struct pm_ops acpi_pm_ops;
25
26extern void do_suspend_lowlevel_s4bios(void);
27extern void do_suspend_lowlevel(void);
28
29static u32 acpi_suspend_states[] = {
30 [PM_SUSPEND_ON] = ACPI_STATE_S0,
31 [PM_SUSPEND_STANDBY] = ACPI_STATE_S1,
32 [PM_SUSPEND_MEM] = ACPI_STATE_S3,
33 [PM_SUSPEND_DISK] = ACPI_STATE_S4,
34};
35
36static int init_8259A_after_S1;
37
38/**
39 * acpi_pm_prepare - Do preliminary suspend work.
40 * @pm_state: suspend state we're entering.
41 *
42 * Make sure we support the state. If we do, and we need it, set the
43 * firmware waking vector and do arch-specific nastiness to get the
44 * wakeup code to the waking vector.
45 */
46
47static int acpi_pm_prepare(suspend_state_t pm_state)
48{
49 u32 acpi_state = acpi_suspend_states[pm_state];
50
51 if (!sleep_states[acpi_state])
52 return -EPERM;
53
54 /* do we have a wakeup address for S2 and S3? */
55 /* Here, we support only S4BIOS, those we set the wakeup address */
56 /* S4OS is only supported for now via swsusp.. */
57 if (pm_state == PM_SUSPEND_MEM || pm_state == PM_SUSPEND_DISK) {
58 if (!acpi_wakeup_address)
59 return -EFAULT;
60 acpi_set_firmware_waking_vector(
61 (acpi_physical_address) virt_to_phys(
62 (void *)acpi_wakeup_address));
63 }
64 ACPI_FLUSH_CPU_CACHE();
65 acpi_enable_wakeup_device_prep(acpi_state);
66 acpi_enter_sleep_state_prep(acpi_state);
67 return 0;
68}
69
70
71/**
72 * acpi_pm_enter - Actually enter a sleep state.
73 * @pm_state: State we're entering.
74 *
75 * Flush caches and go to sleep. For STR or STD, we have to call
76 * arch-specific assembly, which in turn call acpi_enter_sleep_state().
77 * It's unfortunate, but it works. Please fix if you're feeling frisky.
78 */
79
80static int acpi_pm_enter(suspend_state_t pm_state)
81{
82 acpi_status status = AE_OK;
83 unsigned long flags = 0;
84 u32 acpi_state = acpi_suspend_states[pm_state];
85
86 ACPI_FLUSH_CPU_CACHE();
87
88 /* Do arch specific saving of state. */
89 if (pm_state > PM_SUSPEND_STANDBY) {
90 int error = acpi_save_state_mem();
91 if (error)
92 return error;
93 }
94
95
96 local_irq_save(flags);
97 acpi_enable_wakeup_device(acpi_state);
98 switch (pm_state)
99 {
100 case PM_SUSPEND_STANDBY:
101 barrier();
102 status = acpi_enter_sleep_state(acpi_state);
103 break;
104
105 case PM_SUSPEND_MEM:
106 do_suspend_lowlevel();
107 break;
108
109 case PM_SUSPEND_DISK:
110 if (acpi_pm_ops.pm_disk_mode == PM_DISK_PLATFORM)
111 status = acpi_enter_sleep_state(acpi_state);
112 else
113 do_suspend_lowlevel_s4bios();
114 break;
115 default:
116 return -EINVAL;
117 }
118 local_irq_restore(flags);
119 printk(KERN_DEBUG "Back to C!\n");
120
121 /* restore processor state
122 * We should only be here if we're coming back from STR or STD.
123 * And, in the case of the latter, the memory image should have already
124 * been loaded from disk.
125 */
126 if (pm_state > PM_SUSPEND_STANDBY)
127 acpi_restore_state_mem();
128
129
130 return ACPI_SUCCESS(status) ? 0 : -EFAULT;
131}
132
133
134/**
135 * acpi_pm_finish - Finish up suspend sequence.
136 * @pm_state: State we're coming out of.
137 *
138 * This is called after we wake back up (or if entering the sleep state
139 * failed).
140 */
141
142static int acpi_pm_finish(suspend_state_t pm_state)
143{
144 u32 acpi_state = acpi_suspend_states[pm_state];
145
146 acpi_leave_sleep_state(acpi_state);
147 acpi_disable_wakeup_device(acpi_state);
148
149 /* reset firmware waking vector */
150 acpi_set_firmware_waking_vector((acpi_physical_address) 0);
151
152 if (init_8259A_after_S1) {
153 printk("Broken toshiba laptop -> kicking interrupts\n");
154 init_8259A(0);
155 }
156 return 0;
157}
158
159
160int acpi_suspend(u32 acpi_state)
161{
162 suspend_state_t states[] = {
163 [1] = PM_SUSPEND_STANDBY,
164 [3] = PM_SUSPEND_MEM,
165 [4] = PM_SUSPEND_DISK,
166 };
167
168 if (acpi_state <= 4 && states[acpi_state])
169 return pm_suspend(states[acpi_state]);
170 return -EINVAL;
171}
172
173static struct pm_ops acpi_pm_ops = {
174 .prepare = acpi_pm_prepare,
175 .enter = acpi_pm_enter,
176 .finish = acpi_pm_finish,
177};
178
179
180/*
181 * Toshiba fails to preserve interrupts over S1, reinitialization
182 * of 8259 is needed after S1 resume.
183 */
184static int __init init_ints_after_s1(struct dmi_system_id *d)
185{
186 printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident);
187 init_8259A_after_S1 = 1;
188 return 0;
189}
190
191static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
192 {
193 .callback = init_ints_after_s1,
194 .ident = "Toshiba Satellite 4030cdt",
195 .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), },
196 },
197 { },
198};
199
200static int __init acpi_sleep_init(void)
201{
202 int i = 0;
203
204 dmi_check_system(acpisleep_dmi_table);
205
206 if (acpi_disabled)
207 return 0;
208
209 printk(KERN_INFO PREFIX "(supports");
210 for (i=0; i < ACPI_S_STATE_COUNT; i++) {
211 acpi_status status;
212 u8 type_a, type_b;
213 status = acpi_get_sleep_type_data(i, &type_a, &type_b);
214 if (ACPI_SUCCESS(status)) {
215 sleep_states[i] = 1;
216 printk(" S%d", i);
217 }
218 if (i == ACPI_STATE_S4) {
219 if (acpi_gbl_FACS->S4bios_f) {
220 sleep_states[i] = 1;
221 printk(" S4bios");
222 acpi_pm_ops.pm_disk_mode = PM_DISK_FIRMWARE;
223 }
224 if (sleep_states[i])
225 acpi_pm_ops.pm_disk_mode = PM_DISK_PLATFORM;
226 }
227 }
228 printk(")\n");
229
230 pm_set_ops(&acpi_pm_ops);
231 return 0;
232}
233
234late_initcall(acpi_sleep_init);
diff --git a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c
new file mode 100644
index 000000000000..da237754ded9
--- /dev/null
+++ b/drivers/acpi/sleep/poweroff.c
@@ -0,0 +1,39 @@
1/*
2 * poweroff.c - ACPI handler for powering off the system.
3 *
4 * AKA S5, but it is independent of whether or not the kernel supports
5 * any other sleep support in the system.
6 */
7
8#include <linux/pm.h>
9#include <linux/init.h>
10#include <acpi/acpi_bus.h>
11#include <linux/sched.h>
12#include "sleep.h"
13
14static void
15acpi_power_off (void)
16{
17 printk("%s called\n",__FUNCTION__);
18 /* Some SMP machines only can poweroff in boot CPU */
19 set_cpus_allowed(current, cpumask_of_cpu(0));
20 acpi_wakeup_gpe_poweroff_prepare();
21 acpi_enter_sleep_state_prep(ACPI_STATE_S5);
22 ACPI_DISABLE_IRQS();
23 acpi_enter_sleep_state(ACPI_STATE_S5);
24}
25
26static int acpi_poweroff_init(void)
27{
28 if (!acpi_disabled) {
29 u8 type_a, type_b;
30 acpi_status status;
31
32 status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
33 if (ACPI_SUCCESS(status))
34 pm_power_off = acpi_power_off;
35 }
36 return 0;
37}
38
39late_initcall(acpi_poweroff_init);
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
new file mode 100644
index 000000000000..fd7c5a0649af
--- /dev/null
+++ b/drivers/acpi/sleep/proc.c
@@ -0,0 +1,509 @@
1#include <linux/proc_fs.h>
2#include <linux/seq_file.h>
3#include <linux/suspend.h>
4#include <linux/bcd.h>
5#include <asm/uaccess.h>
6
7#include <acpi/acpi_bus.h>
8#include <acpi/acpi_drivers.h>
9
10#ifdef CONFIG_X86
11#include <linux/mc146818rtc.h>
12#endif
13
14#include "sleep.h"
15
16#define ACPI_SYSTEM_FILE_SLEEP "sleep"
17#define ACPI_SYSTEM_FILE_ALARM "alarm"
18#define ACPI_SYSTEM_FILE_WAKEUP_DEVICE "wakeup"
19
20#define _COMPONENT ACPI_SYSTEM_COMPONENT
21ACPI_MODULE_NAME ("sleep")
22
23
24static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset)
25{
26 int i;
27
28 ACPI_FUNCTION_TRACE("acpi_system_sleep_seq_show");
29
30 for (i = 0; i <= ACPI_STATE_S5; i++) {
31 if (sleep_states[i]) {
32 seq_printf(seq,"S%d ", i);
33 if (i == ACPI_STATE_S4 && acpi_gbl_FACS->S4bios_f)
34 seq_printf(seq, "S4bios ");
35 }
36 }
37
38 seq_puts(seq, "\n");
39
40 return 0;
41}
42
43static int acpi_system_sleep_open_fs(struct inode *inode, struct file *file)
44{
45 return single_open(file, acpi_system_sleep_seq_show, PDE(inode)->data);
46}
47
48static ssize_t
49acpi_system_write_sleep (
50 struct file *file,
51 const char __user *buffer,
52 size_t count,
53 loff_t *ppos)
54{
55 char str[12];
56 u32 state = 0;
57 int error = 0;
58
59 if (count > sizeof(str) - 1)
60 goto Done;
61 memset(str,0,sizeof(str));
62 if (copy_from_user(str, buffer, count))
63 return -EFAULT;
64
65 /* Check for S4 bios request */
66 if (!strcmp(str,"4b")) {
67 error = acpi_suspend(4);
68 goto Done;
69 }
70 state = simple_strtoul(str, NULL, 0);
71#ifdef CONFIG_SOFTWARE_SUSPEND
72 if (state == 4) {
73 error = software_suspend();
74 goto Done;
75 }
76#endif
77 error = acpi_suspend(state);
78 Done:
79 return error ? error : count;
80}
81
82static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
83{
84 u32 sec, min, hr;
85 u32 day, mo, yr;
86 unsigned char rtc_control = 0;
87 unsigned long flags;
88
89 ACPI_FUNCTION_TRACE("acpi_system_alarm_seq_show");
90
91 spin_lock_irqsave(&rtc_lock, flags);
92
93 sec = CMOS_READ(RTC_SECONDS_ALARM);
94 min = CMOS_READ(RTC_MINUTES_ALARM);
95 hr = CMOS_READ(RTC_HOURS_ALARM);
96 rtc_control = CMOS_READ(RTC_CONTROL);
97
98 /* If we ever get an FACP with proper values... */
99 if (acpi_gbl_FADT->day_alrm)
100 /* ACPI spec: only low 6 its should be cared */
101 day = CMOS_READ(acpi_gbl_FADT->day_alrm) & 0x3F;
102 else
103 day = CMOS_READ(RTC_DAY_OF_MONTH);
104 if (acpi_gbl_FADT->mon_alrm)
105 mo = CMOS_READ(acpi_gbl_FADT->mon_alrm);
106 else
107 mo = CMOS_READ(RTC_MONTH);
108 if (acpi_gbl_FADT->century)
109 yr = CMOS_READ(acpi_gbl_FADT->century) * 100 + CMOS_READ(RTC_YEAR);
110 else
111 yr = CMOS_READ(RTC_YEAR);
112
113 spin_unlock_irqrestore(&rtc_lock, flags);
114
115 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
116 BCD_TO_BIN(sec);
117 BCD_TO_BIN(min);
118 BCD_TO_BIN(hr);
119 BCD_TO_BIN(day);
120 BCD_TO_BIN(mo);
121 BCD_TO_BIN(yr);
122 }
123
124 /* we're trusting the FADT (see above)*/
125 if (!acpi_gbl_FADT->century)
126 /* If we're not trusting the FADT, we should at least make it
127 * right for _this_ century... ehm, what is _this_ century?
128 *
129 * TBD:
130 * ASAP: find piece of code in the kernel, e.g. star tracker driver,
131 * which we can trust to determine the century correctly. Atom
132 * watch driver would be nice, too...
133 *
134 * if that has not happened, change for first release in 2050:
135 * if (yr<50)
136 * yr += 2100;
137 * else
138 * yr += 2000; // current line of code
139 *
140 * if that has not happened either, please do on 2099/12/31:23:59:59
141 * s/2000/2100
142 *
143 */
144 yr += 2000;
145
146 seq_printf(seq,"%4.4u-", yr);
147 (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo);
148 (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day);
149 (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr);
150 (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min);
151 (sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec);
152
153 return 0;
154}
155
156static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file)
157{
158 return single_open(file, acpi_system_alarm_seq_show, PDE(inode)->data);
159}
160
161
162static int
163get_date_field (
164 char **p,
165 u32 *value)
166{
167 char *next = NULL;
168 char *string_end = NULL;
169 int result = -EINVAL;
170
171 /*
172 * Try to find delimeter, only to insert null. The end of the
173 * string won't have one, but is still valid.
174 */
175 next = strpbrk(*p, "- :");
176 if (next)
177 *next++ = '\0';
178
179 *value = simple_strtoul(*p, &string_end, 10);
180
181 /* Signal success if we got a good digit */
182 if (string_end != *p)
183 result = 0;
184
185 if (next)
186 *p = next;
187
188 return result;
189}
190
191
192static ssize_t
193acpi_system_write_alarm (
194 struct file *file,
195 const char __user *buffer,
196 size_t count,
197 loff_t *ppos)
198{
199 int result = 0;
200 char alarm_string[30] = {'\0'};
201 char *p = alarm_string;
202 u32 sec, min, hr, day, mo, yr;
203 int adjust = 0;
204 unsigned char rtc_control = 0;
205
206 ACPI_FUNCTION_TRACE("acpi_system_write_alarm");
207
208 if (count > sizeof(alarm_string) - 1)
209 return_VALUE(-EINVAL);
210
211 if (copy_from_user(alarm_string, buffer, count))
212 return_VALUE(-EFAULT);
213
214 alarm_string[count] = '\0';
215
216 /* check for time adjustment */
217 if (alarm_string[0] == '+') {
218 p++;
219 adjust = 1;
220 }
221
222 if ((result = get_date_field(&p, &yr)))
223 goto end;
224 if ((result = get_date_field(&p, &mo)))
225 goto end;
226 if ((result = get_date_field(&p, &day)))
227 goto end;
228 if ((result = get_date_field(&p, &hr)))
229 goto end;
230 if ((result = get_date_field(&p, &min)))
231 goto end;
232 if ((result = get_date_field(&p, &sec)))
233 goto end;
234
235 if (sec > 59) {
236 min += 1;
237 sec -= 60;
238 }
239 if (min > 59) {
240 hr += 1;
241 min -= 60;
242 }
243 if (hr > 23) {
244 day += 1;
245 hr -= 24;
246 }
247 if (day > 31) {
248 mo += 1;
249 day -= 31;
250 }
251 if (mo > 12) {
252 yr += 1;
253 mo -= 12;
254 }
255
256 spin_lock_irq(&rtc_lock);
257
258 rtc_control = CMOS_READ(RTC_CONTROL);
259 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
260 BIN_TO_BCD(yr);
261 BIN_TO_BCD(mo);
262 BIN_TO_BCD(day);
263 BIN_TO_BCD(hr);
264 BIN_TO_BCD(min);
265 BIN_TO_BCD(sec);
266 }
267
268 if (adjust) {
269 yr += CMOS_READ(RTC_YEAR);
270 mo += CMOS_READ(RTC_MONTH);
271 day += CMOS_READ(RTC_DAY_OF_MONTH);
272 hr += CMOS_READ(RTC_HOURS);
273 min += CMOS_READ(RTC_MINUTES);
274 sec += CMOS_READ(RTC_SECONDS);
275 }
276
277 spin_unlock_irq(&rtc_lock);
278
279 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
280 BCD_TO_BIN(yr);
281 BCD_TO_BIN(mo);
282 BCD_TO_BIN(day);
283 BCD_TO_BIN(hr);
284 BCD_TO_BIN(min);
285 BCD_TO_BIN(sec);
286 }
287
288 if (sec > 59) {
289 min++;
290 sec -= 60;
291 }
292 if (min > 59) {
293 hr++;
294 min -= 60;
295 }
296 if (hr > 23) {
297 day++;
298 hr -= 24;
299 }
300 if (day > 31) {
301 mo++;
302 day -= 31;
303 }
304 if (mo > 12) {
305 yr++;
306 mo -= 12;
307 }
308 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
309 BIN_TO_BCD(yr);
310 BIN_TO_BCD(mo);
311 BIN_TO_BCD(day);
312 BIN_TO_BCD(hr);
313 BIN_TO_BCD(min);
314 BIN_TO_BCD(sec);
315 }
316
317 spin_lock_irq(&rtc_lock);
318 /*
319 * Disable alarm interrupt before setting alarm timer or else
320 * when ACPI_EVENT_RTC is enabled, a spurious ACPI interrupt occurs
321 */
322 rtc_control &= ~RTC_AIE;
323 CMOS_WRITE(rtc_control, RTC_CONTROL);
324 CMOS_READ(RTC_INTR_FLAGS);
325
326 /* write the fields the rtc knows about */
327 CMOS_WRITE(hr, RTC_HOURS_ALARM);
328 CMOS_WRITE(min, RTC_MINUTES_ALARM);
329 CMOS_WRITE(sec, RTC_SECONDS_ALARM);
330
331 /*
332 * If the system supports an enhanced alarm it will have non-zero
333 * offsets into the CMOS RAM here -- which for some reason are pointing
334 * to the RTC area of memory.
335 */
336 if (acpi_gbl_FADT->day_alrm)
337 CMOS_WRITE(day, acpi_gbl_FADT->day_alrm);
338 if (acpi_gbl_FADT->mon_alrm)
339 CMOS_WRITE(mo, acpi_gbl_FADT->mon_alrm);
340 if (acpi_gbl_FADT->century)
341 CMOS_WRITE(yr/100, acpi_gbl_FADT->century);
342 /* enable the rtc alarm interrupt */
343 rtc_control |= RTC_AIE;
344 CMOS_WRITE(rtc_control, RTC_CONTROL);
345 CMOS_READ(RTC_INTR_FLAGS);
346
347 spin_unlock_irq(&rtc_lock);
348
349 acpi_clear_event(ACPI_EVENT_RTC);
350 acpi_enable_event(ACPI_EVENT_RTC, 0);
351
352 *ppos += count;
353
354 result = 0;
355end:
356 return_VALUE(result ? result : count);
357}
358
359extern struct list_head acpi_wakeup_device_list;
360extern spinlock_t acpi_device_lock;
361
362static int
363acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
364{
365 struct list_head * node, * next;
366
367 seq_printf(seq, "Device Sleep state Status\n");
368
369 spin_lock(&acpi_device_lock);
370 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
371 struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
372
373 if (!dev->wakeup.flags.valid)
374 continue;
375 spin_unlock(&acpi_device_lock);
376 if (dev->wakeup.flags.run_wake)
377 seq_printf(seq, "%4s %4d %8s\n",
378 dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
379 dev->wakeup.state.enabled ? "*enabled" : "*disabled");
380 else
381 seq_printf(seq, "%4s %4d %8s\n",
382 dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
383 dev->wakeup.state.enabled ? "enabled" : "disabled");
384 spin_lock(&acpi_device_lock);
385 }
386 spin_unlock(&acpi_device_lock);
387 return 0;
388}
389
390static ssize_t
391acpi_system_write_wakeup_device (
392 struct file *file,
393 const char __user *buffer,
394 size_t count,
395 loff_t *ppos)
396{
397 struct list_head * node, * next;
398 char strbuf[5];
399 char str[5] = "";
400 int len = count;
401 struct acpi_device *found_dev = NULL;
402
403 if (len > 4) len = 4;
404
405 if (copy_from_user(strbuf, buffer, len))
406 return -EFAULT;
407 strbuf[len] = '\0';
408 sscanf(strbuf, "%s", str);
409
410 spin_lock(&acpi_device_lock);
411 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
412 struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
413 if (!dev->wakeup.flags.valid)
414 continue;
415
416 if (!strncmp(dev->pnp.bus_id, str, 4)) {
417 dev->wakeup.state.enabled = dev->wakeup.state.enabled ? 0:1;
418 found_dev = dev;
419 break;
420 }
421 }
422 if (found_dev) {
423 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
424 struct acpi_device * dev = container_of(node,
425 struct acpi_device, wakeup_list);
426
427 if ((dev != found_dev) &&
428 (dev->wakeup.gpe_number == found_dev->wakeup.gpe_number) &&
429 (dev->wakeup.gpe_device == found_dev->wakeup.gpe_device)) {
430 printk(KERN_WARNING "ACPI: '%s' and '%s' have the same GPE, "
431 "can't disable/enable one seperately\n",
432 dev->pnp.bus_id, found_dev->pnp.bus_id);
433 dev->wakeup.state.enabled = found_dev->wakeup.state.enabled;
434 }
435 }
436 }
437 spin_unlock(&acpi_device_lock);
438 return count;
439}
440
441static int
442acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
443{
444 return single_open(file, acpi_system_wakeup_device_seq_show, PDE(inode)->data);
445}
446
447static struct file_operations acpi_system_wakeup_device_fops = {
448 .open = acpi_system_wakeup_device_open_fs,
449 .read = seq_read,
450 .write = acpi_system_write_wakeup_device,
451 .llseek = seq_lseek,
452 .release = single_release,
453};
454
455static struct file_operations acpi_system_sleep_fops = {
456 .open = acpi_system_sleep_open_fs,
457 .read = seq_read,
458 .write = acpi_system_write_sleep,
459 .llseek = seq_lseek,
460 .release = single_release,
461};
462
463static struct file_operations acpi_system_alarm_fops = {
464 .open = acpi_system_alarm_open_fs,
465 .read = seq_read,
466 .write = acpi_system_write_alarm,
467 .llseek = seq_lseek,
468 .release = single_release,
469};
470
471
472static u32 rtc_handler(void * context)
473{
474 acpi_clear_event(ACPI_EVENT_RTC);
475 acpi_disable_event(ACPI_EVENT_RTC, 0);
476
477 return ACPI_INTERRUPT_HANDLED;
478}
479
480static int acpi_sleep_proc_init(void)
481{
482 struct proc_dir_entry *entry = NULL;
483
484 if (acpi_disabled)
485 return 0;
486
487 /* 'sleep' [R/W]*/
488 entry = create_proc_entry(ACPI_SYSTEM_FILE_SLEEP,
489 S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
490 if (entry)
491 entry->proc_fops = &acpi_system_sleep_fops;
492
493 /* 'alarm' [R/W] */
494 entry = create_proc_entry(ACPI_SYSTEM_FILE_ALARM,
495 S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
496 if (entry)
497 entry->proc_fops = &acpi_system_alarm_fops;
498
499 /* 'wakeup device' [R/W]*/
500 entry = create_proc_entry(ACPI_SYSTEM_FILE_WAKEUP_DEVICE,
501 S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
502 if (entry)
503 entry->proc_fops = &acpi_system_wakeup_device_fops;
504
505 acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
506 return 0;
507}
508
509late_initcall(acpi_sleep_proc_init);
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
new file mode 100644
index 000000000000..efd0001c6f05
--- /dev/null
+++ b/drivers/acpi/sleep/sleep.h
@@ -0,0 +1,8 @@
1
2extern u8 sleep_states[];
3extern int acpi_suspend (u32 state);
4
5extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
6extern void acpi_enable_wakeup_device(u8 sleep_state);
7extern void acpi_disable_wakeup_device(u8 sleep_state);
8extern void acpi_wakeup_gpe_poweroff_prepare(void);
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
new file mode 100644
index 000000000000..d9b199969d5d
--- /dev/null
+++ b/drivers/acpi/sleep/wakeup.c
@@ -0,0 +1,209 @@
1/*
2 * wakeup.c - support wakeup devices
3 * Copyright (C) 2004 Li Shaohua <shaohua.li@intel.com>
4 */
5
6#include <linux/init.h>
7#include <linux/acpi.h>
8#include <acpi/acpi_drivers.h>
9#include <linux/kernel.h>
10#include <linux/types.h>
11#include <acpi/acevents.h>
12#include "sleep.h"
13
14#define _COMPONENT ACPI_SYSTEM_COMPONENT
15ACPI_MODULE_NAME ("wakeup_devices")
16
17extern struct list_head acpi_wakeup_device_list;
18extern spinlock_t acpi_device_lock;
19
20#ifdef CONFIG_ACPI_SLEEP
21/**
22 * acpi_enable_wakeup_device_prep - prepare wakeup devices
23 * @sleep_state: ACPI state
24 * Enable all wakup devices power if the devices' wakeup level
25 * is higher than requested sleep level
26 */
27
28void
29acpi_enable_wakeup_device_prep(
30 u8 sleep_state)
31{
32 struct list_head * node, * next;
33
34 ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_prep");
35
36 spin_lock(&acpi_device_lock);
37 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
38 struct acpi_device * dev = container_of(node,
39 struct acpi_device, wakeup_list);
40
41 if (!dev->wakeup.flags.valid ||
42 !dev->wakeup.state.enabled ||
43 (sleep_state > (u32) dev->wakeup.sleep_state))
44 continue;
45
46 spin_unlock(&acpi_device_lock);
47 acpi_enable_wakeup_device_power(dev);
48 spin_lock(&acpi_device_lock);
49 }
50 spin_unlock(&acpi_device_lock);
51}
52
53/**
54 * acpi_enable_wakeup_device - enable wakeup devices
55 * @sleep_state: ACPI state
56 * Enable all wakup devices's GPE
57 */
58void
59acpi_enable_wakeup_device(
60 u8 sleep_state)
61{
62 struct list_head * node, * next;
63
64 /*
65 * Caution: this routine must be invoked when interrupt is disabled
66 * Refer ACPI2.0: P212
67 */
68 ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
69 spin_lock(&acpi_device_lock);
70 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
71 struct acpi_device * dev = container_of(node,
72 struct acpi_device, wakeup_list);
73
74 /* If users want to disable run-wake GPE,
75 * we only disable it for wake and leave it for runtime
76 */
77 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
78 spin_unlock(&acpi_device_lock);
79 acpi_set_gpe_type(dev->wakeup.gpe_device,
80 dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
81 /* Re-enable it, since set_gpe_type will disable it */
82 acpi_enable_gpe(dev->wakeup.gpe_device,
83 dev->wakeup.gpe_number, ACPI_ISR);
84 spin_lock(&acpi_device_lock);
85 continue;
86 }
87
88 if (!dev->wakeup.flags.valid ||
89 !dev->wakeup.state.enabled ||
90 (sleep_state > (u32) dev->wakeup.sleep_state))
91 continue;
92
93 spin_unlock(&acpi_device_lock);
94 /* run-wake GPE has been enabled */
95 if (!dev->wakeup.flags.run_wake)
96 acpi_enable_gpe(dev->wakeup.gpe_device,
97 dev->wakeup.gpe_number, ACPI_ISR);
98 dev->wakeup.state.active = 1;
99 spin_lock(&acpi_device_lock);
100 }
101 spin_unlock(&acpi_device_lock);
102}
103
104/**
105 * acpi_disable_wakeup_device - disable devices' wakeup capability
106 * @sleep_state: ACPI state
107 * Disable all wakup devices's GPE and wakeup capability
108 */
109void
110acpi_disable_wakeup_device (
111 u8 sleep_state)
112{
113 struct list_head * node, * next;
114
115 ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device");
116
117 spin_lock(&acpi_device_lock);
118 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
119 struct acpi_device * dev = container_of(node,
120 struct acpi_device, wakeup_list);
121
122 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
123 spin_unlock(&acpi_device_lock);
124 acpi_set_gpe_type(dev->wakeup.gpe_device,
125 dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
126 /* Re-enable it, since set_gpe_type will disable it */
127 acpi_enable_gpe(dev->wakeup.gpe_device,
128 dev->wakeup.gpe_number, ACPI_NOT_ISR);
129 spin_lock(&acpi_device_lock);
130 continue;
131 }
132
133 if (!dev->wakeup.flags.valid ||
134 !dev->wakeup.state.active ||
135 (sleep_state > (u32) dev->wakeup.sleep_state))
136 continue;
137
138 spin_unlock(&acpi_device_lock);
139 acpi_disable_wakeup_device_power(dev);
140 /* Never disable run-wake GPE */
141 if (!dev->wakeup.flags.run_wake) {
142 acpi_disable_gpe(dev->wakeup.gpe_device,
143 dev->wakeup.gpe_number, ACPI_NOT_ISR);
144 acpi_clear_gpe(dev->wakeup.gpe_device,
145 dev->wakeup.gpe_number, ACPI_NOT_ISR);
146 }
147 dev->wakeup.state.active = 0;
148 spin_lock(&acpi_device_lock);
149 }
150 spin_unlock(&acpi_device_lock);
151}
152
153static int __init acpi_wakeup_device_init(void)
154{
155 struct list_head * node, * next;
156
157 if (acpi_disabled)
158 return 0;
159 printk("ACPI wakeup devices: \n");
160
161 spin_lock(&acpi_device_lock);
162 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
163 struct acpi_device * dev = container_of(node,
164 struct acpi_device, wakeup_list);
165
166 /* In case user doesn't load button driver */
167 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
168 spin_unlock(&acpi_device_lock);
169 acpi_set_gpe_type(dev->wakeup.gpe_device,
170 dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
171 acpi_enable_gpe(dev->wakeup.gpe_device,
172 dev->wakeup.gpe_number, ACPI_NOT_ISR);
173 dev->wakeup.state.enabled = 1;
174 spin_lock(&acpi_device_lock);
175 }
176 printk("%4s ", dev->pnp.bus_id);
177 }
178 spin_unlock(&acpi_device_lock);
179 printk("\n");
180
181 return 0;
182}
183
184late_initcall(acpi_wakeup_device_init);
185#endif
186
187/*
188 * Disable all wakeup GPEs before power off.
189 *
190 * Since acpi_enter_sleep_state() will disable all
191 * RUNTIME GPEs, we simply mark all GPES that
192 * are not enabled for wakeup from S5 as RUNTIME.
193 */
194void acpi_wakeup_gpe_poweroff_prepare(void)
195{
196 struct list_head * node, * next;
197
198 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
199 struct acpi_device * dev = container_of(node,
200 struct acpi_device, wakeup_list);
201
202 /* The GPE can wakeup system from S5, don't touch it */
203 if ((u32)dev->wakeup.sleep_state == ACPI_STATE_S5)
204 continue;
205 /* acpi_set_gpe_type will automatically disable GPE */
206 acpi_set_gpe_type(dev->wakeup.gpe_device,
207 dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
208 }
209}
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
new file mode 100644
index 000000000000..8925a6ca5f87
--- /dev/null
+++ b/drivers/acpi/system.c
@@ -0,0 +1,187 @@
1/*
2 * acpi_system.c - ACPI System Driver ($Revision: 63 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
25
26#include <linux/proc_fs.h>
27#include <linux/seq_file.h>
28#include <linux/init.h>
29#include <asm/uaccess.h>
30
31#include <acpi/acpi_drivers.h>
32
33
34#define _COMPONENT ACPI_SYSTEM_COMPONENT
35ACPI_MODULE_NAME ("acpi_system")
36
37#define ACPI_SYSTEM_CLASS "system"
38#define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver"
39#define ACPI_SYSTEM_DEVICE_NAME "System"
40#define ACPI_SYSTEM_FILE_INFO "info"
41#define ACPI_SYSTEM_FILE_EVENT "event"
42#define ACPI_SYSTEM_FILE_DSDT "dsdt"
43#define ACPI_SYSTEM_FILE_FADT "fadt"
44
45extern FADT_DESCRIPTOR acpi_fadt;
46
47/* --------------------------------------------------------------------------
48 FS Interface (/proc)
49 -------------------------------------------------------------------------- */
50
51static int
52acpi_system_read_info (struct seq_file *seq, void *offset)
53{
54 ACPI_FUNCTION_TRACE("acpi_system_read_info");
55
56 seq_printf(seq, "version: %x\n", ACPI_CA_VERSION);
57 return_VALUE(0);
58}
59
60static int acpi_system_info_open_fs(struct inode *inode, struct file *file)
61{
62 return single_open(file, acpi_system_read_info, PDE(inode)->data);
63}
64
65static struct file_operations acpi_system_info_ops = {
66 .open = acpi_system_info_open_fs,
67 .read = seq_read,
68 .llseek = seq_lseek,
69 .release = single_release,
70};
71
72static ssize_t acpi_system_read_dsdt (struct file*, char __user *, size_t, loff_t*);
73
74static struct file_operations acpi_system_dsdt_ops = {
75 .read = acpi_system_read_dsdt,
76};
77
78static ssize_t
79acpi_system_read_dsdt (
80 struct file *file,
81 char __user *buffer,
82 size_t count,
83 loff_t *ppos)
84{
85 acpi_status status = AE_OK;
86 struct acpi_buffer dsdt = {ACPI_ALLOCATE_BUFFER, NULL};
87 ssize_t res;
88
89 ACPI_FUNCTION_TRACE("acpi_system_read_dsdt");
90
91 status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt);
92 if (ACPI_FAILURE(status))
93 return_VALUE(-ENODEV);
94
95 res = simple_read_from_buffer(buffer, count, ppos,
96 dsdt.pointer, dsdt.length);
97 acpi_os_free(dsdt.pointer);
98
99 return_VALUE(res);
100}
101
102
103static ssize_t acpi_system_read_fadt (struct file*, char __user *, size_t, loff_t*);
104
105static struct file_operations acpi_system_fadt_ops = {
106 .read = acpi_system_read_fadt,
107};
108
109static ssize_t
110acpi_system_read_fadt (
111 struct file *file,
112 char __user *buffer,
113 size_t count,
114 loff_t *ppos)
115{
116 acpi_status status = AE_OK;
117 struct acpi_buffer fadt = {ACPI_ALLOCATE_BUFFER, NULL};
118 ssize_t res;
119
120 ACPI_FUNCTION_TRACE("acpi_system_read_fadt");
121
122 status = acpi_get_table(ACPI_TABLE_FADT, 1, &fadt);
123 if (ACPI_FAILURE(status))
124 return_VALUE(-ENODEV);
125
126 res = simple_read_from_buffer(buffer, count, ppos,
127 fadt.pointer, fadt.length);
128 acpi_os_free(fadt.pointer);
129
130 return_VALUE(res);
131}
132
133
134static int __init acpi_system_init (void)
135{
136 struct proc_dir_entry *entry;
137 int error = 0;
138 char * name;
139
140 ACPI_FUNCTION_TRACE("acpi_system_init");
141
142 if (acpi_disabled)
143 return_VALUE(0);
144
145 /* 'info' [R] */
146 name = ACPI_SYSTEM_FILE_INFO;
147 entry = create_proc_entry(name,
148 S_IRUGO, acpi_root_dir);
149 if (!entry)
150 goto Error;
151 else {
152 entry->proc_fops = &acpi_system_info_ops;
153 }
154
155 /* 'dsdt' [R] */
156 name = ACPI_SYSTEM_FILE_DSDT;
157 entry = create_proc_entry(name, S_IRUSR, acpi_root_dir);
158 if (entry)
159 entry->proc_fops = &acpi_system_dsdt_ops;
160 else
161 goto Error;
162
163 /* 'fadt' [R] */
164 name = ACPI_SYSTEM_FILE_FADT;
165 entry = create_proc_entry(name, S_IRUSR, acpi_root_dir);
166 if (entry)
167 entry->proc_fops = &acpi_system_fadt_ops;
168 else
169 goto Error;
170
171 Done:
172 return_VALUE(error);
173
174 Error:
175 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
176 "Unable to create '%s' proc fs entry\n", name));
177
178 remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir);
179 remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir);
180 remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir);
181
182 error = -EFAULT;
183 goto Done;
184}
185
186
187subsys_initcall(acpi_system_init);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
new file mode 100644
index 000000000000..fb64bd5d2e18
--- /dev/null
+++ b/drivers/acpi/tables.c
@@ -0,0 +1,609 @@
1/*
2 * acpi_tables.c - ACPI Boot-Time Table Parsing
3 *
4 * Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 *
24 */
25
26#include <linux/config.h>
27#include <linux/init.h>
28#include <linux/kernel.h>
29#include <linux/sched.h>
30#include <linux/smp.h>
31#include <linux/string.h>
32#include <linux/types.h>
33#include <linux/irq.h>
34#include <linux/errno.h>
35#include <linux/acpi.h>
36#include <linux/bootmem.h>
37
38#define PREFIX "ACPI: "
39
40#define ACPI_MAX_TABLES 256
41
42static char *acpi_table_signatures[ACPI_TABLE_COUNT] = {
43 [ACPI_TABLE_UNKNOWN] = "????",
44 [ACPI_APIC] = "APIC",
45 [ACPI_BOOT] = "BOOT",
46 [ACPI_DBGP] = "DBGP",
47 [ACPI_DSDT] = "DSDT",
48 [ACPI_ECDT] = "ECDT",
49 [ACPI_ETDT] = "ETDT",
50 [ACPI_FADT] = "FACP",
51 [ACPI_FACS] = "FACS",
52 [ACPI_OEMX] = "OEM",
53 [ACPI_PSDT] = "PSDT",
54 [ACPI_SBST] = "SBST",
55 [ACPI_SLIT] = "SLIT",
56 [ACPI_SPCR] = "SPCR",
57 [ACPI_SRAT] = "SRAT",
58 [ACPI_SSDT] = "SSDT",
59 [ACPI_SPMI] = "SPMI",
60 [ACPI_HPET] = "HPET",
61 [ACPI_MCFG] = "MCFG",
62};
63
64static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
65static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" };
66
67/* System Description Table (RSDT/XSDT) */
68struct acpi_table_sdt {
69 unsigned long pa;
70 enum acpi_table_id id;
71 unsigned long size;
72} __attribute__ ((packed));
73
74static unsigned long sdt_pa; /* Physical Address */
75static unsigned long sdt_count; /* Table count */
76
77static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES];
78
79void
80acpi_table_print (
81 struct acpi_table_header *header,
82 unsigned long phys_addr)
83{
84 char *name = NULL;
85
86 if (!header)
87 return;
88
89 /* Some table signatures aren't good table names */
90
91 if (!strncmp((char *) &header->signature,
92 acpi_table_signatures[ACPI_APIC],
93 sizeof(header->signature))) {
94 name = "MADT";
95 }
96 else if (!strncmp((char *) &header->signature,
97 acpi_table_signatures[ACPI_FADT],
98 sizeof(header->signature))) {
99 name = "FADT";
100 }
101 else
102 name = header->signature;
103
104 printk(KERN_DEBUG PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n",
105 name, header->revision, header->oem_id,
106 header->oem_table_id, header->oem_revision,
107 header->asl_compiler_id, header->asl_compiler_revision,
108 (void *) phys_addr);
109}
110
111
112void
113acpi_table_print_madt_entry (
114 acpi_table_entry_header *header)
115{
116 if (!header)
117 return;
118
119 switch (header->type) {
120
121 case ACPI_MADT_LAPIC:
122 {
123 struct acpi_table_lapic *p =
124 (struct acpi_table_lapic*) header;
125 printk(KERN_INFO PREFIX "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
126 p->acpi_id, p->id, p->flags.enabled?"enabled":"disabled");
127 }
128 break;
129
130 case ACPI_MADT_IOAPIC:
131 {
132 struct acpi_table_ioapic *p =
133 (struct acpi_table_ioapic*) header;
134 printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
135 p->id, p->address, p->global_irq_base);
136 }
137 break;
138
139 case ACPI_MADT_INT_SRC_OVR:
140 {
141 struct acpi_table_int_src_ovr *p =
142 (struct acpi_table_int_src_ovr*) header;
143 printk(KERN_INFO PREFIX "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n",
144 p->bus, p->bus_irq, p->global_irq,
145 mps_inti_flags_polarity[p->flags.polarity],
146 mps_inti_flags_trigger[p->flags.trigger]);
147 if(p->flags.reserved)
148 printk(KERN_INFO PREFIX "INT_SRC_OVR unexpected reserved flags: 0x%x\n",
149 p->flags.reserved);
150
151 }
152 break;
153
154 case ACPI_MADT_NMI_SRC:
155 {
156 struct acpi_table_nmi_src *p =
157 (struct acpi_table_nmi_src*) header;
158 printk(KERN_INFO PREFIX "NMI_SRC (%s %s global_irq %d)\n",
159 mps_inti_flags_polarity[p->flags.polarity],
160 mps_inti_flags_trigger[p->flags.trigger], p->global_irq);
161 }
162 break;
163
164 case ACPI_MADT_LAPIC_NMI:
165 {
166 struct acpi_table_lapic_nmi *p =
167 (struct acpi_table_lapic_nmi*) header;
168 printk(KERN_INFO PREFIX "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n",
169 p->acpi_id,
170 mps_inti_flags_polarity[p->flags.polarity],
171 mps_inti_flags_trigger[p->flags.trigger], p->lint);
172 }
173 break;
174
175 case ACPI_MADT_LAPIC_ADDR_OVR:
176 {
177 struct acpi_table_lapic_addr_ovr *p =
178 (struct acpi_table_lapic_addr_ovr*) header;
179 printk(KERN_INFO PREFIX "LAPIC_ADDR_OVR (address[%p])\n",
180 (void *) (unsigned long) p->address);
181 }
182 break;
183
184 case ACPI_MADT_IOSAPIC:
185 {
186 struct acpi_table_iosapic *p =
187 (struct acpi_table_iosapic*) header;
188 printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
189 p->id, (void *) (unsigned long) p->address, p->global_irq_base);
190 }
191 break;
192
193 case ACPI_MADT_LSAPIC:
194 {
195 struct acpi_table_lsapic *p =
196 (struct acpi_table_lsapic*) header;
197 printk(KERN_INFO PREFIX "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
198 p->acpi_id, p->id, p->eid, p->flags.enabled?"enabled":"disabled");
199 }
200 break;
201
202 case ACPI_MADT_PLAT_INT_SRC:
203 {
204 struct acpi_table_plat_int_src *p =
205 (struct acpi_table_plat_int_src*) header;
206 printk(KERN_INFO PREFIX "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",
207 mps_inti_flags_polarity[p->flags.polarity],
208 mps_inti_flags_trigger[p->flags.trigger],
209 p->type, p->id, p->eid, p->iosapic_vector, p->global_irq);
210 }
211 break;
212
213 default:
214 printk(KERN_WARNING PREFIX "Found unsupported MADT entry (type = 0x%x)\n",
215 header->type);
216 break;
217 }
218}
219
220
221static int
222acpi_table_compute_checksum (
223 void *table_pointer,
224 unsigned long length)
225{
226 u8 *p = (u8 *) table_pointer;
227 unsigned long remains = length;
228 unsigned long sum = 0;
229
230 if (!p || !length)
231 return -EINVAL;
232
233 while (remains--)
234 sum += *p++;
235
236 return (sum & 0xFF);
237}
238
239/*
240 * acpi_get_table_header_early()
241 * for acpi_blacklisted(), acpi_table_get_sdt()
242 */
243int __init
244acpi_get_table_header_early (
245 enum acpi_table_id id,
246 struct acpi_table_header **header)
247{
248 unsigned int i;
249 enum acpi_table_id temp_id;
250
251 /* DSDT is different from the rest */
252 if (id == ACPI_DSDT)
253 temp_id = ACPI_FADT;
254 else
255 temp_id = id;
256
257 /* Locate the table. */
258
259 for (i = 0; i < sdt_count; i++) {
260 if (sdt_entry[i].id != temp_id)
261 continue;
262 *header = (void *)
263 __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
264 if (!*header) {
265 printk(KERN_WARNING PREFIX "Unable to map %s\n",
266 acpi_table_signatures[temp_id]);
267 return -ENODEV;
268 }
269 break;
270 }
271
272 if (!*header) {
273 printk(KERN_WARNING PREFIX "%s not present\n",
274 acpi_table_signatures[id]);
275 return -ENODEV;
276 }
277
278 /* Map the DSDT header via the pointer in the FADT */
279 if (id == ACPI_DSDT) {
280 struct fadt_descriptor_rev2 *fadt = (struct fadt_descriptor_rev2 *) *header;
281
282 if (fadt->revision == 3 && fadt->Xdsdt) {
283 *header = (void *) __acpi_map_table(fadt->Xdsdt,
284 sizeof(struct acpi_table_header));
285 } else if (fadt->V1_dsdt) {
286 *header = (void *) __acpi_map_table(fadt->V1_dsdt,
287 sizeof(struct acpi_table_header));
288 } else
289 *header = NULL;
290
291 if (!*header) {
292 printk(KERN_WARNING PREFIX "Unable to map DSDT\n");
293 return -ENODEV;
294 }
295 }
296
297 return 0;
298}
299
300
301int __init
302acpi_table_parse_madt_family (
303 enum acpi_table_id id,
304 unsigned long madt_size,
305 int entry_id,
306 acpi_madt_entry_handler handler,
307 unsigned int max_entries)
308{
309 void *madt = NULL;
310 acpi_table_entry_header *entry;
311 unsigned int count = 0;
312 unsigned long madt_end;
313 unsigned int i;
314
315 if (!handler)
316 return -EINVAL;
317
318 /* Locate the MADT (if exists). There should only be one. */
319
320 for (i = 0; i < sdt_count; i++) {
321 if (sdt_entry[i].id != id)
322 continue;
323 madt = (void *)
324 __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
325 if (!madt) {
326 printk(KERN_WARNING PREFIX "Unable to map %s\n",
327 acpi_table_signatures[id]);
328 return -ENODEV;
329 }
330 break;
331 }
332
333 if (!madt) {
334 printk(KERN_WARNING PREFIX "%s not present\n",
335 acpi_table_signatures[id]);
336 return -ENODEV;
337 }
338
339 madt_end = (unsigned long) madt + sdt_entry[i].size;
340
341 /* Parse all entries looking for a match. */
342
343 entry = (acpi_table_entry_header *)
344 ((unsigned long) madt + madt_size);
345
346 while (((unsigned long) entry) + sizeof(acpi_table_entry_header) < madt_end) {
347 if (entry->type == entry_id &&
348 (!max_entries || count++ < max_entries))
349 if (handler(entry, madt_end))
350 return -EINVAL;
351
352 entry = (acpi_table_entry_header *)
353 ((unsigned long) entry + entry->length);
354 }
355 if (max_entries && count > max_entries) {
356 printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of "
357 "%i found\n", acpi_table_signatures[id], entry_id,
358 count - max_entries, count);
359 }
360
361 return count;
362}
363
364
365int __init
366acpi_table_parse_madt (
367 enum acpi_madt_entry_id id,
368 acpi_madt_entry_handler handler,
369 unsigned int max_entries)
370{
371 return acpi_table_parse_madt_family(ACPI_APIC, sizeof(struct acpi_table_madt),
372 id, handler, max_entries);
373}
374
375
376int __init
377acpi_table_parse (
378 enum acpi_table_id id,
379 acpi_table_handler handler)
380{
381 int count = 0;
382 unsigned int i = 0;
383
384 if (!handler)
385 return -EINVAL;
386
387 for (i = 0; i < sdt_count; i++) {
388 if (sdt_entry[i].id != id)
389 continue;
390 count++;
391 if (count == 1)
392 handler(sdt_entry[i].pa, sdt_entry[i].size);
393
394 else
395 printk(KERN_WARNING PREFIX "%d duplicate %s table ignored.\n",
396 count, acpi_table_signatures[id]);
397 }
398
399 return count;
400}
401
402
403static int __init
404acpi_table_get_sdt (
405 struct acpi_table_rsdp *rsdp)
406{
407 struct acpi_table_header *header = NULL;
408 unsigned int i, id = 0;
409
410 if (!rsdp)
411 return -EINVAL;
412
413 /* First check XSDT (but only on ACPI 2.0-compatible systems) */
414
415 if ((rsdp->revision >= 2) &&
416 (((struct acpi20_table_rsdp*)rsdp)->xsdt_address)) {
417
418 struct acpi_table_xsdt *mapped_xsdt = NULL;
419
420 sdt_pa = ((struct acpi20_table_rsdp*)rsdp)->xsdt_address;
421
422 /* map in just the header */
423 header = (struct acpi_table_header *)
424 __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
425
426 if (!header) {
427 printk(KERN_WARNING PREFIX "Unable to map XSDT header\n");
428 return -ENODEV;
429 }
430
431 /* remap in the entire table before processing */
432 mapped_xsdt = (struct acpi_table_xsdt *)
433 __acpi_map_table(sdt_pa, header->length);
434 if (!mapped_xsdt) {
435 printk(KERN_WARNING PREFIX "Unable to map XSDT\n");
436 return -ENODEV;
437 }
438 header = &mapped_xsdt->header;
439
440 if (strncmp(header->signature, "XSDT", 4)) {
441 printk(KERN_WARNING PREFIX "XSDT signature incorrect\n");
442 return -ENODEV;
443 }
444
445 if (acpi_table_compute_checksum(header, header->length)) {
446 printk(KERN_WARNING PREFIX "Invalid XSDT checksum\n");
447 return -ENODEV;
448 }
449
450 sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 3;
451 if (sdt_count > ACPI_MAX_TABLES) {
452 printk(KERN_WARNING PREFIX "Truncated %lu XSDT entries\n",
453 (sdt_count - ACPI_MAX_TABLES));
454 sdt_count = ACPI_MAX_TABLES;
455 }
456
457 for (i = 0; i < sdt_count; i++)
458 sdt_entry[i].pa = (unsigned long) mapped_xsdt->entry[i];
459 }
460
461 /* Then check RSDT */
462
463 else if (rsdp->rsdt_address) {
464
465 struct acpi_table_rsdt *mapped_rsdt = NULL;
466
467 sdt_pa = rsdp->rsdt_address;
468
469 /* map in just the header */
470 header = (struct acpi_table_header *)
471 __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
472 if (!header) {
473 printk(KERN_WARNING PREFIX "Unable to map RSDT header\n");
474 return -ENODEV;
475 }
476
477 /* remap in the entire table before processing */
478 mapped_rsdt = (struct acpi_table_rsdt *)
479 __acpi_map_table(sdt_pa, header->length);
480 if (!mapped_rsdt) {
481 printk(KERN_WARNING PREFIX "Unable to map RSDT\n");
482 return -ENODEV;
483 }
484 header = &mapped_rsdt->header;
485
486 if (strncmp(header->signature, "RSDT", 4)) {
487 printk(KERN_WARNING PREFIX "RSDT signature incorrect\n");
488 return -ENODEV;
489 }
490
491 if (acpi_table_compute_checksum(header, header->length)) {
492 printk(KERN_WARNING PREFIX "Invalid RSDT checksum\n");
493 return -ENODEV;
494 }
495
496 sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 2;
497 if (sdt_count > ACPI_MAX_TABLES) {
498 printk(KERN_WARNING PREFIX "Truncated %lu RSDT entries\n",
499 (sdt_count - ACPI_MAX_TABLES));
500 sdt_count = ACPI_MAX_TABLES;
501 }
502
503 for (i = 0; i < sdt_count; i++)
504 sdt_entry[i].pa = (unsigned long) mapped_rsdt->entry[i];
505 }
506
507 else {
508 printk(KERN_WARNING PREFIX "No System Description Table (RSDT/XSDT) specified in RSDP\n");
509 return -ENODEV;
510 }
511
512 acpi_table_print(header, sdt_pa);
513
514 for (i = 0; i < sdt_count; i++) {
515
516 /* map in just the header */
517 header = (struct acpi_table_header *)
518 __acpi_map_table(sdt_entry[i].pa,
519 sizeof(struct acpi_table_header));
520 if (!header)
521 continue;
522
523 /* remap in the entire table before processing */
524 header = (struct acpi_table_header *)
525 __acpi_map_table(sdt_entry[i].pa,
526 header->length);
527 if (!header)
528 continue;
529
530 acpi_table_print(header, sdt_entry[i].pa);
531
532 if (acpi_table_compute_checksum(header, header->length)) {
533 printk(KERN_WARNING " >>> ERROR: Invalid checksum\n");
534 continue;
535 }
536
537 sdt_entry[i].size = header->length;
538
539 for (id = 0; id < ACPI_TABLE_COUNT; id++) {
540 if (!strncmp((char *) &header->signature,
541 acpi_table_signatures[id],
542 sizeof(header->signature))) {
543 sdt_entry[i].id = id;
544 }
545 }
546 }
547
548 /*
549 * The DSDT is *not* in the RSDT (why not? no idea.) but we want
550 * to print its info, because this is what people usually blacklist
551 * against. Unfortunately, we don't know the phys_addr, so just
552 * print 0. Maybe no one will notice.
553 */
554 if(!acpi_get_table_header_early(ACPI_DSDT, &header))
555 acpi_table_print(header, 0);
556
557 return 0;
558}
559
560/*
561 * acpi_table_init()
562 *
563 * find RSDP, find and checksum SDT/XSDT.
564 * checksum all tables, print SDT/XSDT
565 *
566 * result: sdt_entry[] is initialized
567 */
568
569int __init
570acpi_table_init (void)
571{
572 struct acpi_table_rsdp *rsdp = NULL;
573 unsigned long rsdp_phys = 0;
574 int result = 0;
575
576 /* Locate and map the Root System Description Table (RSDP) */
577
578 rsdp_phys = acpi_find_rsdp();
579 if (!rsdp_phys) {
580 printk(KERN_ERR PREFIX "Unable to locate RSDP\n");
581 return -ENODEV;
582 }
583
584 rsdp = (struct acpi_table_rsdp *) __va(rsdp_phys);
585 if (!rsdp) {
586 printk(KERN_WARNING PREFIX "Unable to map RSDP\n");
587 return -ENODEV;
588 }
589
590 printk(KERN_DEBUG PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n",
591 rsdp->revision, rsdp->oem_id, (void *) rsdp_phys);
592
593 if (rsdp->revision < 2)
594 result = acpi_table_compute_checksum(rsdp, sizeof(struct acpi_table_rsdp));
595 else
596 result = acpi_table_compute_checksum(rsdp, ((struct acpi20_table_rsdp *)rsdp)->length);
597
598 if (result) {
599 printk(KERN_WARNING " >>> ERROR: Invalid checksum\n");
600 return -ENODEV;
601 }
602
603 /* Locate and map the System Description table (RSDT/XSDT) */
604
605 if (acpi_table_get_sdt(rsdp))
606 return -ENODEV;
607
608 return 0;
609}
diff --git a/drivers/acpi/tables/Makefile b/drivers/acpi/tables/Makefile
new file mode 100644
index 000000000000..aa4c69594d97
--- /dev/null
+++ b/drivers/acpi/tables/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for all Linux ACPI interpreter subdirectories
3#
4
5obj-y := tbconvrt.o tbget.o tbrsdt.o tbxface.o \
6 tbgetall.o tbinstal.o tbutils.o tbxfroot.o
7
8EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c
new file mode 100644
index 000000000000..334327c1f66f
--- /dev/null
+++ b/drivers/acpi/tables/tbconvrt.c
@@ -0,0 +1,564 @@
1/******************************************************************************
2 *
3 * Module Name: tbconvrt - ACPI Table conversion utilities
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <linux/module.h>
45
46#include <acpi/acpi.h>
47#include <acpi/actables.h>
48
49
50#define _COMPONENT ACPI_TABLES
51 ACPI_MODULE_NAME ("tbconvrt")
52
53
54u8 acpi_fadt_is_v1;
55EXPORT_SYMBOL(acpi_fadt_is_v1);
56
57/*******************************************************************************
58 *
59 * FUNCTION: acpi_tb_get_table_count
60 *
61 * PARAMETERS: RSDP - Pointer to the RSDP
62 * RSDT - Pointer to the RSDT/XSDT
63 *
64 * RETURN: The number of tables pointed to by the RSDT or XSDT.
65 *
66 * DESCRIPTION: Calculate the number of tables. Automatically handles either
67 * an RSDT or XSDT.
68 *
69 ******************************************************************************/
70
71u32
72acpi_tb_get_table_count (
73 struct rsdp_descriptor *RSDP,
74 struct acpi_table_header *RSDT)
75{
76 u32 pointer_size;
77
78
79 ACPI_FUNCTION_ENTRY ();
80
81
82 if (RSDP->revision < 2) {
83 pointer_size = sizeof (u32);
84 }
85 else {
86 pointer_size = sizeof (u64);
87 }
88
89 /*
90 * Determine the number of tables pointed to by the RSDT/XSDT.
91 * This is defined by the ACPI Specification to be the number of
92 * pointers contained within the RSDT/XSDT. The size of the pointers
93 * is architecture-dependent.
94 */
95 return ((RSDT->length - sizeof (struct acpi_table_header)) / pointer_size);
96}
97
98
99/*******************************************************************************
100 *
101 * FUNCTION: acpi_tb_convert_to_xsdt
102 *
103 * PARAMETERS: table_info - Info about the RSDT
104 *
105 * RETURN: Status
106 *
107 * DESCRIPTION: Convert an RSDT to an XSDT (internal common format)
108 *
109 ******************************************************************************/
110
111acpi_status
112acpi_tb_convert_to_xsdt (
113 struct acpi_table_desc *table_info)
114{
115 acpi_size table_size;
116 u32 i;
117 XSDT_DESCRIPTOR *new_table;
118
119
120 ACPI_FUNCTION_ENTRY ();
121
122
123 /* Compute size of the converted XSDT */
124
125 table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof (u64)) +
126 sizeof (struct acpi_table_header);
127
128 /* Allocate an XSDT */
129
130 new_table = ACPI_MEM_CALLOCATE (table_size);
131 if (!new_table) {
132 return (AE_NO_MEMORY);
133 }
134
135 /* Copy the header and set the length */
136
137 ACPI_MEMCPY (new_table, table_info->pointer, sizeof (struct acpi_table_header));
138 new_table->length = (u32) table_size;
139
140 /* Copy the table pointers */
141
142 for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
143 if (acpi_gbl_RSDP->revision < 2) {
144 ACPI_STORE_ADDRESS (new_table->table_offset_entry[i],
145 (ACPI_CAST_PTR (struct rsdt_descriptor_rev1, table_info->pointer))->table_offset_entry[i]);
146 }
147 else {
148 new_table->table_offset_entry[i] =
149 (ACPI_CAST_PTR (XSDT_DESCRIPTOR, table_info->pointer))->table_offset_entry[i];
150 }
151 }
152
153 /* Delete the original table (either mapped or in a buffer) */
154
155 acpi_tb_delete_single_table (table_info);
156
157 /* Point the table descriptor to the new table */
158
159 table_info->pointer = ACPI_CAST_PTR (struct acpi_table_header, new_table);
160 table_info->length = table_size;
161 table_info->allocation = ACPI_MEM_ALLOCATED;
162
163 return (AE_OK);
164}
165
166
167/******************************************************************************
168 *
169 * FUNCTION: acpi_tb_init_generic_address
170 *
171 * PARAMETERS: new_gas_struct - GAS struct to be initialized
172 * register_bit_width - Width of this register
173 * Address - Address of the register
174 *
175 * RETURN: None
176 *
177 * DESCRIPTION: Initialize a GAS structure.
178 *
179 ******************************************************************************/
180
181static void
182acpi_tb_init_generic_address (
183 struct acpi_generic_address *new_gas_struct,
184 u8 register_bit_width,
185 acpi_physical_address address)
186{
187
188 ACPI_STORE_ADDRESS (new_gas_struct->address, address);
189
190 new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO;
191 new_gas_struct->register_bit_width = register_bit_width;
192 new_gas_struct->register_bit_offset = 0;
193 new_gas_struct->access_width = 0;
194}
195
196
197/*******************************************************************************
198 *
199 * FUNCTION: acpi_tb_convert_fadt1
200 *
201 * PARAMETERS: local_fadt - Pointer to new FADT
202 * original_fadt - Pointer to old FADT
203 *
204 * RETURN: Populates local_fadt
205 *
206 * DESCRIPTION: Convert an ACPI 1.0 FADT to common internal format
207 *
208 ******************************************************************************/
209
210static void
211acpi_tb_convert_fadt1 (
212 struct fadt_descriptor_rev2 *local_fadt,
213 struct fadt_descriptor_rev1 *original_fadt)
214{
215
216
217 /* ACPI 1.0 FACS */
218 /* The BIOS stored FADT should agree with Revision 1.0 */
219 acpi_fadt_is_v1 = 1;
220
221 /*
222 * Copy the table header and the common part of the tables.
223 *
224 * The 2.0 table is an extension of the 1.0 table, so the entire 1.0
225 * table can be copied first, then expand some fields to 64 bits.
226 */
227 ACPI_MEMCPY (local_fadt, original_fadt, sizeof (struct fadt_descriptor_rev1));
228
229 /* Convert table pointers to 64-bit fields */
230
231 ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl, local_fadt->V1_firmware_ctrl);
232 ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt);
233
234 /*
235 * System Interrupt Model isn't used in ACPI 2.0 (local_fadt->Reserved1 = 0;)
236 */
237
238 /*
239 * This field is set by the OEM to convey the preferred power management
240 * profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't
241 * know what kind of 32-bit system this is, we will use "unspecified".
242 */
243 local_fadt->prefer_PM_profile = PM_UNSPECIFIED;
244
245 /*
246 * Processor Performance State Control. This is the value OSPM writes to
247 * the SMI_CMD register to assume processor performance state control
248 * responsibility. There isn't any equivalence in 1.0, but as many 1.x
249 * ACPI tables contain _PCT and _PSS we also keep this value, unless
250 * acpi_strict is set.
251 */
252 if (acpi_strict)
253 local_fadt->pstate_cnt = 0;
254
255 /*
256 * Support for the _CST object and C States change notification.
257 * This data item hasn't any 1.0 equivalence so leave it zero.
258 */
259 local_fadt->cst_cnt = 0;
260
261 /*
262 * FADT Rev 2 was an interim FADT released between ACPI 1.0 and ACPI 2.0.
263 * It primarily adds the FADT reset mechanism.
264 */
265 if ((original_fadt->revision == 2) &&
266 (original_fadt->length == sizeof (struct fadt_descriptor_rev2_minus))) {
267 /*
268 * Grab the entire generic address struct, plus the 1-byte reset value
269 * that immediately follows.
270 */
271 ACPI_MEMCPY (&local_fadt->reset_register,
272 &(ACPI_CAST_PTR (struct fadt_descriptor_rev2_minus, original_fadt))->reset_register,
273 sizeof (struct acpi_generic_address) + 1);
274 }
275 else {
276 /*
277 * Since there isn't any equivalence in 1.0 and since it is highly
278 * likely that a 1.0 system has legacy support.
279 */
280 local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES;
281 }
282
283 /*
284 * Convert the V1.0 block addresses to V2.0 GAS structures
285 */
286 acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk, local_fadt->pm1_evt_len,
287 (acpi_physical_address) local_fadt->V1_pm1a_evt_blk);
288 acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk, local_fadt->pm1_evt_len,
289 (acpi_physical_address) local_fadt->V1_pm1b_evt_blk);
290 acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk, local_fadt->pm1_cnt_len,
291 (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk);
292 acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk, local_fadt->pm1_cnt_len,
293 (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk);
294 acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk, local_fadt->pm2_cnt_len,
295 (acpi_physical_address) local_fadt->V1_pm2_cnt_blk);
296 acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk, local_fadt->pm_tm_len,
297 (acpi_physical_address) local_fadt->V1_pm_tmr_blk);
298 acpi_tb_init_generic_address (&local_fadt->xgpe0_blk, 0,
299 (acpi_physical_address) local_fadt->V1_gpe0_blk);
300 acpi_tb_init_generic_address (&local_fadt->xgpe1_blk, 0,
301 (acpi_physical_address) local_fadt->V1_gpe1_blk);
302
303 /* Create separate GAS structs for the PM1 Enable registers */
304
305 acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable,
306 (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
307 (acpi_physical_address) (local_fadt->xpm1a_evt_blk.address +
308 ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
309
310 /* PM1B is optional; leave null if not present */
311
312 if (local_fadt->xpm1b_evt_blk.address) {
313 acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable,
314 (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
315 (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address +
316 ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
317 }
318}
319
320
321/*******************************************************************************
322 *
323 * FUNCTION: acpi_tb_convert_fadt2
324 *
325 * PARAMETERS: local_fadt - Pointer to new FADT
326 * original_fadt - Pointer to old FADT
327 *
328 * RETURN: Populates local_fadt
329 *
330 * DESCRIPTION: Convert an ACPI 2.0 FADT to common internal format.
331 * Handles optional "X" fields.
332 *
333 ******************************************************************************/
334
335static void
336acpi_tb_convert_fadt2 (
337 struct fadt_descriptor_rev2 *local_fadt,
338 struct fadt_descriptor_rev2 *original_fadt)
339{
340
341 /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */
342
343 ACPI_MEMCPY (local_fadt, original_fadt, sizeof (struct fadt_descriptor_rev2));
344
345 /*
346 * "X" fields are optional extensions to the original V1.0 fields, so
347 * we must selectively expand V1.0 fields if the corresponding X field
348 * is zero.
349 */
350 if (!(local_fadt->xfirmware_ctrl)) {
351 ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl, local_fadt->V1_firmware_ctrl);
352 }
353
354 if (!(local_fadt->Xdsdt)) {
355 ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt);
356 }
357
358 if (!(local_fadt->xpm1a_evt_blk.address)) {
359 acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk,
360 local_fadt->pm1_evt_len, (acpi_physical_address) local_fadt->V1_pm1a_evt_blk);
361 }
362
363 if (!(local_fadt->xpm1b_evt_blk.address)) {
364 acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk,
365 local_fadt->pm1_evt_len, (acpi_physical_address) local_fadt->V1_pm1b_evt_blk);
366 }
367
368 if (!(local_fadt->xpm1a_cnt_blk.address)) {
369 acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk,
370 local_fadt->pm1_cnt_len, (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk);
371 }
372
373 if (!(local_fadt->xpm1b_cnt_blk.address)) {
374 acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk,
375 local_fadt->pm1_cnt_len, (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk);
376 }
377
378 if (!(local_fadt->xpm2_cnt_blk.address)) {
379 acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk,
380 local_fadt->pm2_cnt_len, (acpi_physical_address) local_fadt->V1_pm2_cnt_blk);
381 }
382
383 if (!(local_fadt->xpm_tmr_blk.address)) {
384 acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk,
385 local_fadt->pm_tm_len, (acpi_physical_address) local_fadt->V1_pm_tmr_blk);
386 }
387
388 if (!(local_fadt->xgpe0_blk.address)) {
389 acpi_tb_init_generic_address (&local_fadt->xgpe0_blk,
390 0, (acpi_physical_address) local_fadt->V1_gpe0_blk);
391 }
392
393 if (!(local_fadt->xgpe1_blk.address)) {
394 acpi_tb_init_generic_address (&local_fadt->xgpe1_blk,
395 0, (acpi_physical_address) local_fadt->V1_gpe1_blk);
396 }
397
398 /* Create separate GAS structs for the PM1 Enable registers */
399
400 acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable,
401 (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
402 (acpi_physical_address) (local_fadt->xpm1a_evt_blk.address +
403 ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
404 acpi_gbl_xpm1a_enable.address_space_id = local_fadt->xpm1a_evt_blk.address_space_id;
405
406 /* PM1B is optional; leave null if not present */
407
408 if (local_fadt->xpm1b_evt_blk.address) {
409 acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable,
410 (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
411 (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address +
412 ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
413 acpi_gbl_xpm1b_enable.address_space_id = local_fadt->xpm1b_evt_blk.address_space_id;
414 }
415}
416
417
418/*******************************************************************************
419 *
420 * FUNCTION: acpi_tb_convert_table_fadt
421 *
422 * PARAMETERS: None
423 *
424 * RETURN: Status
425 *
426 * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local
427 * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply
428 * copied to the local FADT. The ACPI CA software uses this
429 * local FADT. Thus a significant amount of special #ifdef
430 * type codeing is saved.
431 *
432 ******************************************************************************/
433
434acpi_status
435acpi_tb_convert_table_fadt (void)
436{
437 struct fadt_descriptor_rev2 *local_fadt;
438 struct acpi_table_desc *table_desc;
439
440
441 ACPI_FUNCTION_TRACE ("tb_convert_table_fadt");
442
443
444 /*
445 * acpi_gbl_FADT is valid. Validate the FADT length. The table must be
446 * at least as long as the version 1.0 FADT
447 */
448 if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev1)) {
449 ACPI_REPORT_ERROR (("FADT is invalid, too short: 0x%X\n", acpi_gbl_FADT->length));
450 return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
451 }
452
453 /* Allocate buffer for the ACPI 2.0(+) FADT */
454
455 local_fadt = ACPI_MEM_CALLOCATE (sizeof (struct fadt_descriptor_rev2));
456 if (!local_fadt) {
457 return_ACPI_STATUS (AE_NO_MEMORY);
458 }
459
460 if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) {
461 if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev2)) {
462 /* Length is too short to be a V2.0 table */
463
464 ACPI_REPORT_WARNING (("Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n",
465 acpi_gbl_FADT->length, acpi_gbl_FADT->revision));
466
467 acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT);
468 }
469 else {
470 /* Valid V2.0 table */
471
472 acpi_tb_convert_fadt2 (local_fadt, acpi_gbl_FADT);
473 }
474 }
475 else {
476 /* Valid V1.0 table */
477
478 acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT);
479 }
480
481 /*
482 * Global FADT pointer will point to the new common V2.0 FADT
483 */
484 acpi_gbl_FADT = local_fadt;
485 acpi_gbl_FADT->length = sizeof (FADT_DESCRIPTOR);
486
487 /* Free the original table */
488
489 table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next;
490 acpi_tb_delete_single_table (table_desc);
491
492 /* Install the new table */
493
494 table_desc->pointer = ACPI_CAST_PTR (struct acpi_table_header, acpi_gbl_FADT);
495 table_desc->allocation = ACPI_MEM_ALLOCATED;
496 table_desc->length = sizeof (struct fadt_descriptor_rev2);
497
498 /* Dump the entire FADT */
499
500 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
501 "Hex dump of common internal FADT, size %d (%X)\n",
502 acpi_gbl_FADT->length, acpi_gbl_FADT->length));
503 ACPI_DUMP_BUFFER ((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->length);
504
505 return_ACPI_STATUS (AE_OK);
506}
507
508
509/*******************************************************************************
510 *
511 * FUNCTION: acpi_tb_convert_table_facs
512 *
513 * PARAMETERS: table_info - Info for currently installed FACS
514 *
515 * RETURN: Status
516 *
517 * DESCRIPTION: Convert ACPI 1.0 and ACPI 2.0 FACS to a common internal
518 * table format.
519 *
520 ******************************************************************************/
521
522acpi_status
523acpi_tb_build_common_facs (
524 struct acpi_table_desc *table_info)
525{
526
527 ACPI_FUNCTION_TRACE ("tb_build_common_facs");
528
529
530 /* Absolute minimum length is 24, but the ACPI spec says 64 */
531
532 if (acpi_gbl_FACS->length < 24) {
533 ACPI_REPORT_ERROR (("Invalid FACS table length: 0x%X\n", acpi_gbl_FACS->length));
534 return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
535 }
536
537 if (acpi_gbl_FACS->length < 64) {
538 ACPI_REPORT_WARNING (("FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n",
539 acpi_gbl_FACS->length));
540 }
541
542 /* Copy fields to the new FACS */
543
544 acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock);
545
546 if ((acpi_gbl_RSDP->revision < 2) ||
547 (acpi_gbl_FACS->length < 32) ||
548 (!(acpi_gbl_FACS->xfirmware_waking_vector))) {
549 /* ACPI 1.0 FACS or short table or optional X_ field is zero */
550
551 acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR (u64, &(acpi_gbl_FACS->firmware_waking_vector));
552 acpi_gbl_common_fACS.vector_width = 32;
553 }
554 else {
555 /* ACPI 2.0 FACS with valid X_ field */
556
557 acpi_gbl_common_fACS.firmware_waking_vector = &acpi_gbl_FACS->xfirmware_waking_vector;
558 acpi_gbl_common_fACS.vector_width = 64;
559 }
560
561 return_ACPI_STATUS (AE_OK);
562}
563
564
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
new file mode 100644
index 000000000000..896f3ddda62e
--- /dev/null
+++ b/drivers/acpi/tables/tbget.c
@@ -0,0 +1,493 @@
1/******************************************************************************
2 *
3 * Module Name: tbget - ACPI Table get* routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/actables.h>
47
48
49#define _COMPONENT ACPI_TABLES
50 ACPI_MODULE_NAME ("tbget")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_tb_get_table
56 *
57 * PARAMETERS: Address - Address of table to retrieve. Can be
58 * Logical or Physical
59 * table_info - Where table info is returned
60 *
61 * RETURN: None
62 *
63 * DESCRIPTION: Get entire table of unknown size.
64 *
65 ******************************************************************************/
66
67acpi_status
68acpi_tb_get_table (
69 struct acpi_pointer *address,
70 struct acpi_table_desc *table_info)
71{
72 acpi_status status;
73 struct acpi_table_header header;
74
75
76 ACPI_FUNCTION_TRACE ("tb_get_table");
77
78
79 /*
80 * Get the header in order to get signature and table size
81 */
82 status = acpi_tb_get_table_header (address, &header);
83 if (ACPI_FAILURE (status)) {
84 return_ACPI_STATUS (status);
85 }
86
87 /* Get the entire table */
88
89 status = acpi_tb_get_table_body (address, &header, table_info);
90 if (ACPI_FAILURE (status)) {
91 ACPI_REPORT_ERROR (("Could not get ACPI table (size %X), %s\n",
92 header.length, acpi_format_exception (status)));
93 return_ACPI_STATUS (status);
94 }
95
96 return_ACPI_STATUS (AE_OK);
97}
98
99
100/*******************************************************************************
101 *
102 * FUNCTION: acpi_tb_get_table_header
103 *
104 * PARAMETERS: Address - Address of table to retrieve. Can be
105 * Logical or Physical
106 * return_header - Where the table header is returned
107 *
108 * RETURN: Status
109 *
110 * DESCRIPTION: Get an ACPI table header. Works in both physical or virtual
111 * addressing mode. Works with both physical or logical pointers.
112 * Table is either copied or mapped, depending on the pointer
113 * type and mode of the processor.
114 *
115 ******************************************************************************/
116
117acpi_status
118acpi_tb_get_table_header (
119 struct acpi_pointer *address,
120 struct acpi_table_header *return_header)
121{
122 acpi_status status = AE_OK;
123 struct acpi_table_header *header = NULL;
124
125
126 ACPI_FUNCTION_TRACE ("tb_get_table_header");
127
128
129 /*
130 * Flags contains the current processor mode (Virtual or Physical addressing)
131 * The pointer_type is either Logical or Physical
132 */
133 switch (address->pointer_type) {
134 case ACPI_PHYSMODE_PHYSPTR:
135 case ACPI_LOGMODE_LOGPTR:
136
137 /* Pointer matches processor mode, copy the header */
138
139 ACPI_MEMCPY (return_header, address->pointer.logical, sizeof (struct acpi_table_header));
140 break;
141
142
143 case ACPI_LOGMODE_PHYSPTR:
144
145 /* Create a logical address for the physical pointer*/
146
147 status = acpi_os_map_memory (address->pointer.physical, sizeof (struct acpi_table_header),
148 (void *) &header);
149 if (ACPI_FAILURE (status)) {
150 ACPI_REPORT_ERROR (("Could not map memory at %8.8X%8.8X for length %X\n",
151 ACPI_FORMAT_UINT64 (address->pointer.physical),
152 sizeof (struct acpi_table_header)));
153 return_ACPI_STATUS (status);
154 }
155
156 /* Copy header and delete mapping */
157
158 ACPI_MEMCPY (return_header, header, sizeof (struct acpi_table_header));
159 acpi_os_unmap_memory (header, sizeof (struct acpi_table_header));
160 break;
161
162
163 default:
164
165 ACPI_REPORT_ERROR (("Invalid address flags %X\n",
166 address->pointer_type));
167 return_ACPI_STATUS (AE_BAD_PARAMETER);
168 }
169
170 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n",
171 return_header->signature));
172
173 return_ACPI_STATUS (AE_OK);
174}
175
176
177/*******************************************************************************
178 *
179 * FUNCTION: acpi_tb_get_table_body
180 *
181 * PARAMETERS: Address - Address of table to retrieve. Can be
182 * Logical or Physical
183 * Header - Header of the table to retrieve
184 * table_info - Where the table info is returned
185 *
186 * RETURN: Status
187 *
188 * DESCRIPTION: Get an entire ACPI table with support to allow the host OS to
189 * replace the table with a newer version (table override.)
190 * Works in both physical or virtual
191 * addressing mode. Works with both physical or logical pointers.
192 * Table is either copied or mapped, depending on the pointer
193 * type and mode of the processor.
194 *
195 ******************************************************************************/
196
197acpi_status
198acpi_tb_get_table_body (
199 struct acpi_pointer *address,
200 struct acpi_table_header *header,
201 struct acpi_table_desc *table_info)
202{
203 acpi_status status;
204
205
206 ACPI_FUNCTION_TRACE ("tb_get_table_body");
207
208
209 if (!table_info || !address) {
210 return_ACPI_STATUS (AE_BAD_PARAMETER);
211 }
212
213 /*
214 * Attempt table override.
215 */
216 status = acpi_tb_table_override (header, table_info);
217 if (ACPI_SUCCESS (status)) {
218 /* Table was overridden by the host OS */
219
220 return_ACPI_STATUS (status);
221 }
222
223 /* No override, get the original table */
224
225 status = acpi_tb_get_this_table (address, header, table_info);
226 return_ACPI_STATUS (status);
227}
228
229
230/*******************************************************************************
231 *
232 * FUNCTION: acpi_tb_table_override
233 *
234 * PARAMETERS: Header - Pointer to table header
235 * table_info - Return info if table is overridden
236 *
237 * RETURN: None
238 *
239 * DESCRIPTION: Attempts override of current table with a new one if provided
240 * by the host OS.
241 *
242 ******************************************************************************/
243
244acpi_status
245acpi_tb_table_override (
246 struct acpi_table_header *header,
247 struct acpi_table_desc *table_info)
248{
249 struct acpi_table_header *new_table;
250 acpi_status status;
251 struct acpi_pointer address;
252
253
254 ACPI_FUNCTION_TRACE ("tb_table_override");
255
256
257 /*
258 * The OSL will examine the header and decide whether to override this
259 * table. If it decides to override, a table will be returned in new_table,
260 * which we will then copy.
261 */
262 status = acpi_os_table_override (header, &new_table);
263 if (ACPI_FAILURE (status)) {
264 /* Some severe error from the OSL, but we basically ignore it */
265
266 ACPI_REPORT_ERROR (("Could not override ACPI table, %s\n",
267 acpi_format_exception (status)));
268 return_ACPI_STATUS (status);
269 }
270
271 if (!new_table) {
272 /* No table override */
273
274 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
275 }
276
277 /*
278 * We have a new table to override the old one. Get a copy of
279 * the new one. We know that the new table has a logical pointer.
280 */
281 address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
282 address.pointer.logical = new_table;
283
284 status = acpi_tb_get_this_table (&address, new_table, table_info);
285 if (ACPI_FAILURE (status)) {
286 ACPI_REPORT_ERROR (("Could not copy override ACPI table, %s\n",
287 acpi_format_exception (status)));
288 return_ACPI_STATUS (status);
289 }
290
291 /* Copy the table info */
292
293 ACPI_REPORT_INFO (("Table [%4.4s] replaced by host OS\n",
294 table_info->pointer->signature));
295
296 return_ACPI_STATUS (AE_OK);
297}
298
299
300/*******************************************************************************
301 *
302 * FUNCTION: acpi_tb_get_this_table
303 *
304 * PARAMETERS: Address - Address of table to retrieve. Can be
305 * Logical or Physical
306 * Header - Header of the table to retrieve
307 * table_info - Where the table info is returned
308 *
309 * RETURN: Status
310 *
311 * DESCRIPTION: Get an entire ACPI table. Works in both physical or virtual
312 * addressing mode. Works with both physical or logical pointers.
313 * Table is either copied or mapped, depending on the pointer
314 * type and mode of the processor.
315 *
316 ******************************************************************************/
317
318acpi_status
319acpi_tb_get_this_table (
320 struct acpi_pointer *address,
321 struct acpi_table_header *header,
322 struct acpi_table_desc *table_info)
323{
324 struct acpi_table_header *full_table = NULL;
325 u8 allocation;
326 acpi_status status = AE_OK;
327
328
329 ACPI_FUNCTION_TRACE ("tb_get_this_table");
330
331
332 /*
333 * Flags contains the current processor mode (Virtual or Physical addressing)
334 * The pointer_type is either Logical or Physical
335 */
336 switch (address->pointer_type) {
337 case ACPI_PHYSMODE_PHYSPTR:
338 case ACPI_LOGMODE_LOGPTR:
339
340 /* Pointer matches processor mode, copy the table to a new buffer */
341
342 full_table = ACPI_MEM_ALLOCATE (header->length);
343 if (!full_table) {
344 ACPI_REPORT_ERROR (("Could not allocate table memory for [%4.4s] length %X\n",
345 header->signature, header->length));
346 return_ACPI_STATUS (AE_NO_MEMORY);
347 }
348
349 /* Copy the entire table (including header) to the local buffer */
350
351 ACPI_MEMCPY (full_table, address->pointer.logical, header->length);
352
353 /* Save allocation type */
354
355 allocation = ACPI_MEM_ALLOCATED;
356 break;
357
358
359 case ACPI_LOGMODE_PHYSPTR:
360
361 /*
362 * Just map the table's physical memory
363 * into our address space.
364 */
365 status = acpi_os_map_memory (address->pointer.physical, (acpi_size) header->length,
366 (void *) &full_table);
367 if (ACPI_FAILURE (status)) {
368 ACPI_REPORT_ERROR (("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n",
369 header->signature,
370 ACPI_FORMAT_UINT64 (address->pointer.physical), header->length));
371 return (status);
372 }
373
374 /* Save allocation type */
375
376 allocation = ACPI_MEM_MAPPED;
377 break;
378
379
380 default:
381
382 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid address flags %X\n",
383 address->pointer_type));
384 return_ACPI_STATUS (AE_BAD_PARAMETER);
385 }
386
387 /*
388 * Validate checksum for _most_ tables,
389 * even the ones whose signature we don't recognize
390 */
391 if (table_info->type != ACPI_TABLE_FACS) {
392 status = acpi_tb_verify_table_checksum (full_table);
393
394#if (!ACPI_CHECKSUM_ABORT)
395 if (ACPI_FAILURE (status)) {
396 /* Ignore the error if configuration says so */
397
398 status = AE_OK;
399 }
400#endif
401 }
402
403 /* Return values */
404
405 table_info->pointer = full_table;
406 table_info->length = (acpi_size) header->length;
407 table_info->allocation = allocation;
408
409 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
410 "Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n",
411 full_table->signature,
412 ACPI_FORMAT_UINT64 (address->pointer.physical), full_table));
413
414 return_ACPI_STATUS (status);
415}
416
417
418/*******************************************************************************
419 *
420 * FUNCTION: acpi_tb_get_table_ptr
421 *
422 * PARAMETERS: table_type - one of the defined table types
423 * Instance - Which table of this type
424 * table_ptr_loc - pointer to location to place the pointer for
425 * return
426 *
427 * RETURN: Status
428 *
429 * DESCRIPTION: This function is called to get the pointer to an ACPI table.
430 *
431 ******************************************************************************/
432
433acpi_status
434acpi_tb_get_table_ptr (
435 acpi_table_type table_type,
436 u32 instance,
437 struct acpi_table_header **table_ptr_loc)
438{
439 struct acpi_table_desc *table_desc;
440 u32 i;
441
442
443 ACPI_FUNCTION_TRACE ("tb_get_table_ptr");
444
445
446 if (!acpi_gbl_DSDT) {
447 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
448 }
449
450 if (table_type > ACPI_TABLE_MAX) {
451 return_ACPI_STATUS (AE_BAD_PARAMETER);
452 }
453
454 /*
455 * For all table types (Single/Multiple), the first
456 * instance is always in the list head.
457 */
458 if (instance == 1) {
459 /* Get the first */
460
461 *table_ptr_loc = NULL;
462 if (acpi_gbl_table_lists[table_type].next) {
463 *table_ptr_loc = acpi_gbl_table_lists[table_type].next->pointer;
464 }
465 return_ACPI_STATUS (AE_OK);
466 }
467
468 /*
469 * Check for instance out of range
470 */
471 if (instance > acpi_gbl_table_lists[table_type].count) {
472 return_ACPI_STATUS (AE_NOT_EXIST);
473 }
474
475 /* Walk the list to get the desired table
476 * Since the if (Instance == 1) check above checked for the
477 * first table, setting table_desc equal to the .Next member
478 * is actually pointing to the second table. Therefore, we
479 * need to walk from the 2nd table until we reach the Instance
480 * that the user is looking for and return its table pointer.
481 */
482 table_desc = acpi_gbl_table_lists[table_type].next;
483 for (i = 2; i < instance; i++) {
484 table_desc = table_desc->next;
485 }
486
487 /* We are now pointing to the requested table's descriptor */
488
489 *table_ptr_loc = table_desc->pointer;
490
491 return_ACPI_STATUS (AE_OK);
492}
493
diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c
new file mode 100644
index 000000000000..adc4270988bc
--- /dev/null
+++ b/drivers/acpi/tables/tbgetall.c
@@ -0,0 +1,313 @@
1/******************************************************************************
2 *
3 * Module Name: tbgetall - Get all required ACPI tables
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/actables.h>
47
48
49#define _COMPONENT ACPI_TABLES
50 ACPI_MODULE_NAME ("tbgetall")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_tb_get_primary_table
56 *
57 * PARAMETERS: Address - Physical address of table to retrieve
58 * *table_info - Where the table info is returned
59 *
60 * RETURN: Status
61 *
62 * DESCRIPTION: Maps the physical address of table into a logical address
63 *
64 ******************************************************************************/
65
66acpi_status
67acpi_tb_get_primary_table (
68 struct acpi_pointer *address,
69 struct acpi_table_desc *table_info)
70{
71 acpi_status status;
72 struct acpi_table_header header;
73
74
75 ACPI_FUNCTION_TRACE ("tb_get_primary_table");
76
77
78 /* Ignore a NULL address in the RSDT */
79
80 if (!address->pointer.value) {
81 return_ACPI_STATUS (AE_OK);
82 }
83
84 /*
85 * Get the header in order to get signature and table size
86 */
87 status = acpi_tb_get_table_header (address, &header);
88 if (ACPI_FAILURE (status)) {
89 return_ACPI_STATUS (status);
90 }
91
92 /* Clear the table_info */
93
94 ACPI_MEMSET (table_info, 0, sizeof (struct acpi_table_desc));
95
96 /*
97 * Check the table signature and make sure it is recognized.
98 * Also checks the header checksum
99 */
100 table_info->pointer = &header;
101 status = acpi_tb_recognize_table (table_info, ACPI_TABLE_PRIMARY);
102 if (ACPI_FAILURE (status)) {
103 return_ACPI_STATUS (status);
104 }
105
106 /* Get the entire table */
107
108 status = acpi_tb_get_table_body (address, &header, table_info);
109 if (ACPI_FAILURE (status)) {
110 return_ACPI_STATUS (status);
111 }
112
113 /* Install the table */
114
115 status = acpi_tb_install_table (table_info);
116 return_ACPI_STATUS (status);
117}
118
119
120/*******************************************************************************
121 *
122 * FUNCTION: acpi_tb_get_secondary_table
123 *
124 * PARAMETERS: Address - Physical address of table to retrieve
125 * *table_info - Where the table info is returned
126 *
127 * RETURN: Status
128 *
129 * DESCRIPTION: Maps the physical address of table into a logical address
130 *
131 ******************************************************************************/
132
133acpi_status
134acpi_tb_get_secondary_table (
135 struct acpi_pointer *address,
136 acpi_string signature,
137 struct acpi_table_desc *table_info)
138{
139 acpi_status status;
140 struct acpi_table_header header;
141
142
143 ACPI_FUNCTION_TRACE_STR ("tb_get_secondary_table", signature);
144
145
146 /* Get the header in order to match the signature */
147
148 status = acpi_tb_get_table_header (address, &header);
149 if (ACPI_FAILURE (status)) {
150 return_ACPI_STATUS (status);
151 }
152
153 /* Signature must match request */
154
155 if (ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) {
156 ACPI_REPORT_ERROR (("Incorrect table signature - wanted [%s] found [%4.4s]\n",
157 signature, header.signature));
158 return_ACPI_STATUS (AE_BAD_SIGNATURE);
159 }
160
161 /*
162 * Check the table signature and make sure it is recognized.
163 * Also checks the header checksum
164 */
165 table_info->pointer = &header;
166 status = acpi_tb_recognize_table (table_info, ACPI_TABLE_SECONDARY);
167 if (ACPI_FAILURE (status)) {
168 return_ACPI_STATUS (status);
169 }
170
171 /* Get the entire table */
172
173 status = acpi_tb_get_table_body (address, &header, table_info);
174 if (ACPI_FAILURE (status)) {
175 return_ACPI_STATUS (status);
176 }
177
178 /* Install the table */
179
180 status = acpi_tb_install_table (table_info);
181 return_ACPI_STATUS (status);
182}
183
184
185/*******************************************************************************
186 *
187 * FUNCTION: acpi_tb_get_required_tables
188 *
189 * PARAMETERS: None
190 *
191 * RETURN: Status
192 *
193 * DESCRIPTION: Load and validate tables other than the RSDT. The RSDT must
194 * already be loaded and validated.
195 *
196 * Get the minimum set of ACPI tables, namely:
197 *
198 * 1) FADT (via RSDT in loop below)
199 * 2) FACS (via FADT)
200 * 3) DSDT (via FADT)
201 *
202 ******************************************************************************/
203
204acpi_status
205acpi_tb_get_required_tables (
206 void)
207{
208 acpi_status status = AE_OK;
209 u32 i;
210 struct acpi_table_desc table_info;
211 struct acpi_pointer address;
212
213
214 ACPI_FUNCTION_TRACE ("tb_get_required_tables");
215
216 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%d ACPI tables in RSDT\n",
217 acpi_gbl_rsdt_table_count));
218
219
220 address.pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
221
222 /*
223 * Loop through all table pointers found in RSDT.
224 * This will NOT include the FACS and DSDT - we must get
225 * them after the loop.
226 *
227 * The only tables we are interested in getting here is the FADT and
228 * any SSDTs.
229 */
230 for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
231 /* Get the table address from the common internal XSDT */
232
233 address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i];
234
235 /*
236 * Get the tables needed by this subsystem (FADT and any SSDTs).
237 * NOTE: All other tables are completely ignored at this time.
238 */
239 status = acpi_tb_get_primary_table (&address, &table_info);
240 if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) {
241 ACPI_REPORT_WARNING (("%s, while getting table at %8.8X%8.8X\n",
242 acpi_format_exception (status),
243 ACPI_FORMAT_UINT64 (address.pointer.value)));
244 }
245 }
246
247 /* We must have a FADT to continue */
248
249 if (!acpi_gbl_FADT) {
250 ACPI_REPORT_ERROR (("No FADT present in RSDT/XSDT\n"));
251 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
252 }
253
254 /*
255 * Convert the FADT to a common format. This allows earlier revisions of the
256 * table to coexist with newer versions, using common access code.
257 */
258 status = acpi_tb_convert_table_fadt ();
259 if (ACPI_FAILURE (status)) {
260 ACPI_REPORT_ERROR (("Could not convert FADT to internal common format\n"));
261 return_ACPI_STATUS (status);
262 }
263
264 /*
265 * Get the FACS (Pointed to by the FADT)
266 */
267 address.pointer.value = acpi_gbl_FADT->xfirmware_ctrl;
268
269 status = acpi_tb_get_secondary_table (&address, FACS_SIG, &table_info);
270 if (ACPI_FAILURE (status)) {
271 ACPI_REPORT_ERROR (("Could not get/install the FACS, %s\n",
272 acpi_format_exception (status)));
273 return_ACPI_STATUS (status);
274 }
275
276 /*
277 * Create the common FACS pointer table
278 * (Contains pointers to the original table)
279 */
280 status = acpi_tb_build_common_facs (&table_info);
281 if (ACPI_FAILURE (status)) {
282 return_ACPI_STATUS (status);
283 }
284
285 /*
286 * Get/install the DSDT (Pointed to by the FADT)
287 */
288 address.pointer.value = acpi_gbl_FADT->Xdsdt;
289
290 status = acpi_tb_get_secondary_table (&address, DSDT_SIG, &table_info);
291 if (ACPI_FAILURE (status)) {
292 ACPI_REPORT_ERROR (("Could not get/install the DSDT\n"));
293 return_ACPI_STATUS (status);
294 }
295
296 /* Set Integer Width (32/64) based upon DSDT revision */
297
298 acpi_ut_set_integer_width (acpi_gbl_DSDT->revision);
299
300 /* Dump the entire DSDT */
301
302 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
303 "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n",
304 acpi_gbl_DSDT->length, acpi_gbl_DSDT->length, acpi_gbl_integer_bit_width));
305 ACPI_DUMP_BUFFER ((u8 *) acpi_gbl_DSDT, acpi_gbl_DSDT->length);
306
307 /* Always delete the RSDP mapping, we are done with it */
308
309 acpi_tb_delete_tables_by_type (ACPI_TABLE_RSDP);
310 return_ACPI_STATUS (status);
311}
312
313
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
new file mode 100644
index 000000000000..85d5bb01022c
--- /dev/null
+++ b/drivers/acpi/tables/tbinstal.c
@@ -0,0 +1,553 @@
1/******************************************************************************
2 *
3 * Module Name: tbinstal - ACPI table installation and removal
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/actables.h>
47
48
49#define _COMPONENT ACPI_TABLES
50 ACPI_MODULE_NAME ("tbinstal")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_tb_match_signature
56 *
57 * PARAMETERS: Signature - Table signature to match
58 * table_info - Return data
59 *
60 * RETURN: Status
61 *
62 * DESCRIPTION: Compare signature against the list of "ACPI-subsystem-owned"
63 * tables (DSDT/FADT/SSDT, etc.) Returns the table_type_iD on match.
64 *
65 ******************************************************************************/
66
67acpi_status
68acpi_tb_match_signature (
69 char *signature,
70 struct acpi_table_desc *table_info,
71 u8 search_type)
72{
73 acpi_native_uint i;
74
75
76 ACPI_FUNCTION_TRACE ("tb_match_signature");
77
78
79 /*
80 * Search for a signature match among the known table types
81 */
82 for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) {
83 if (!(acpi_gbl_table_data[i].flags & search_type)) {
84 continue;
85 }
86
87 if (!ACPI_STRNCMP (signature, acpi_gbl_table_data[i].signature,
88 acpi_gbl_table_data[i].sig_length)) {
89 /* Found a signature match, return index if requested */
90
91 if (table_info) {
92 table_info->type = (u8) i;
93 }
94
95 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
96 "Table [%4.4s] is an ACPI table consumed by the core subsystem\n",
97 (char *) acpi_gbl_table_data[i].signature));
98
99 return_ACPI_STATUS (AE_OK);
100 }
101 }
102
103 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
104 "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n",
105 (char *) signature));
106
107 return_ACPI_STATUS (AE_TABLE_NOT_SUPPORTED);
108}
109
110
111/*******************************************************************************
112 *
113 * FUNCTION: acpi_tb_install_table
114 *
115 * PARAMETERS: table_info - Return value from acpi_tb_get_table_body
116 *
117 * RETURN: Status
118 *
119 * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must
120 * already be loaded and validated.
121 * Install the table into the global data structs.
122 *
123 ******************************************************************************/
124
125acpi_status
126acpi_tb_install_table (
127 struct acpi_table_desc *table_info)
128{
129 acpi_status status;
130
131 ACPI_FUNCTION_TRACE ("tb_install_table");
132
133
134 /* Lock tables while installing */
135
136 status = acpi_ut_acquire_mutex (ACPI_MTX_TABLES);
137 if (ACPI_FAILURE (status)) {
138 ACPI_REPORT_ERROR (("Could not acquire table mutex for [%4.4s], %s\n",
139 table_info->pointer->signature, acpi_format_exception (status)));
140 return_ACPI_STATUS (status);
141 }
142
143 /* Install the table into the global data structure */
144
145 status = acpi_tb_init_table_descriptor (table_info->type, table_info);
146 if (ACPI_FAILURE (status)) {
147 ACPI_REPORT_ERROR (("Could not install ACPI table [%4.4s], %s\n",
148 table_info->pointer->signature, acpi_format_exception (status)));
149 }
150
151 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s located at %p\n",
152 acpi_gbl_table_data[table_info->type].name, table_info->pointer));
153
154 (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
155 return_ACPI_STATUS (status);
156}
157
158
159/*******************************************************************************
160 *
161 * FUNCTION: acpi_tb_recognize_table
162 *
163 * PARAMETERS: table_info - Return value from acpi_tb_get_table_body
164 *
165 * RETURN: Status
166 *
167 * DESCRIPTION: Check a table signature for a match against known table types
168 *
169 * NOTE: All table pointers are validated as follows:
170 * 1) Table pointer must point to valid physical memory
171 * 2) Signature must be 4 ASCII chars, even if we don't recognize the
172 * name
173 * 3) Table must be readable for length specified in the header
174 * 4) Table checksum must be valid (with the exception of the FACS
175 * which has no checksum for some odd reason)
176 *
177 ******************************************************************************/
178
179acpi_status
180acpi_tb_recognize_table (
181 struct acpi_table_desc *table_info,
182 u8 search_type)
183{
184 struct acpi_table_header *table_header;
185 acpi_status status;
186
187
188 ACPI_FUNCTION_TRACE ("tb_recognize_table");
189
190
191 /* Ensure that we have a valid table pointer */
192
193 table_header = (struct acpi_table_header *) table_info->pointer;
194 if (!table_header) {
195 return_ACPI_STATUS (AE_BAD_PARAMETER);
196 }
197
198 /*
199 * We only "recognize" a limited number of ACPI tables -- namely, the
200 * ones that are used by the subsystem (DSDT, FADT, etc.)
201 *
202 * An AE_TABLE_NOT_SUPPORTED means that the table was not recognized.
203 * This can be any one of many valid ACPI tables, it just isn't one of
204 * the tables that is consumed by the core subsystem
205 */
206 status = acpi_tb_match_signature (table_header->signature, table_info, search_type);
207 if (ACPI_FAILURE (status)) {
208 return_ACPI_STATUS (status);
209 }
210
211 status = acpi_tb_validate_table_header (table_header);
212 if (ACPI_FAILURE (status)) {
213 return_ACPI_STATUS (status);
214 }
215
216 /* Return the table type and length via the info struct */
217
218 table_info->length = (acpi_size) table_header->length;
219
220 return_ACPI_STATUS (status);
221}
222
223
224/*******************************************************************************
225 *
226 * FUNCTION: acpi_tb_init_table_descriptor
227 *
228 * PARAMETERS: table_type - The type of the table
229 * table_info - A table info struct
230 *
231 * RETURN: None.
232 *
233 * DESCRIPTION: Install a table into the global data structs.
234 *
235 ******************************************************************************/
236
237acpi_status
238acpi_tb_init_table_descriptor (
239 acpi_table_type table_type,
240 struct acpi_table_desc *table_info)
241{
242 struct acpi_table_list *list_head;
243 struct acpi_table_desc *table_desc;
244
245
246 ACPI_FUNCTION_TRACE_U32 ("tb_init_table_descriptor", table_type);
247
248
249 /* Allocate a descriptor for this table */
250
251 table_desc = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc));
252 if (!table_desc) {
253 return_ACPI_STATUS (AE_NO_MEMORY);
254 }
255
256 /*
257 * Install the table into the global data structure
258 */
259 list_head = &acpi_gbl_table_lists[table_type];
260
261 /*
262 * Two major types of tables: 1) Only one instance is allowed. This
263 * includes most ACPI tables such as the DSDT. 2) Multiple instances of
264 * the table are allowed. This includes SSDT and PSDTs.
265 */
266 if (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags)) {
267 /*
268 * Only one table allowed, and a table has alread been installed
269 * at this location, so return an error.
270 */
271 if (list_head->next) {
272 ACPI_MEM_FREE (table_desc);
273 return_ACPI_STATUS (AE_ALREADY_EXISTS);
274 }
275
276 table_desc->next = list_head->next;
277 list_head->next = table_desc;
278
279 if (table_desc->next) {
280 table_desc->next->prev = table_desc;
281 }
282
283 list_head->count++;
284 }
285 else {
286 /*
287 * Link the new table in to the list of tables of this type.
288 * Insert at the end of the list, order IS IMPORTANT.
289 *
290 * table_desc->Prev & Next are already NULL from calloc()
291 */
292 list_head->count++;
293
294 if (!list_head->next) {
295 list_head->next = table_desc;
296 }
297 else {
298 table_desc->next = list_head->next;
299
300 while (table_desc->next->next) {
301 table_desc->next = table_desc->next->next;
302 }
303
304 table_desc->next->next = table_desc;
305 table_desc->prev = table_desc->next;
306 table_desc->next = NULL;
307 }
308 }
309
310 /* Finish initialization of the table descriptor */
311
312 table_desc->type = (u8) table_type;
313 table_desc->pointer = table_info->pointer;
314 table_desc->length = table_info->length;
315 table_desc->allocation = table_info->allocation;
316 table_desc->aml_start = (u8 *) (table_desc->pointer + 1),
317 table_desc->aml_length = (u32) (table_desc->length -
318 (u32) sizeof (struct acpi_table_header));
319 table_desc->table_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_TABLE);
320 table_desc->loaded_into_namespace = FALSE;
321
322 /*
323 * Set the appropriate global pointer (if there is one) to point to the
324 * newly installed table
325 */
326 if (acpi_gbl_table_data[table_type].global_ptr) {
327 *(acpi_gbl_table_data[table_type].global_ptr) = table_info->pointer;
328 }
329
330 /* Return Data */
331
332 table_info->table_id = table_desc->table_id;
333 table_info->installed_desc = table_desc;
334
335 return_ACPI_STATUS (AE_OK);
336}
337
338
339/*******************************************************************************
340 *
341 * FUNCTION: acpi_tb_delete_all_tables
342 *
343 * PARAMETERS: None.
344 *
345 * RETURN: None.
346 *
347 * DESCRIPTION: Delete all internal ACPI tables
348 *
349 ******************************************************************************/
350
351void
352acpi_tb_delete_all_tables (void)
353{
354 acpi_table_type type;
355
356
357 /*
358 * Free memory allocated for ACPI tables
359 * Memory can either be mapped or allocated
360 */
361 for (type = 0; type < NUM_ACPI_TABLE_TYPES; type++) {
362 acpi_tb_delete_tables_by_type (type);
363 }
364}
365
366
367/*******************************************************************************
368 *
369 * FUNCTION: acpi_tb_delete_tables_by_type
370 *
371 * PARAMETERS: Type - The table type to be deleted
372 *
373 * RETURN: None.
374 *
375 * DESCRIPTION: Delete an internal ACPI table
376 * Locks the ACPI table mutex
377 *
378 ******************************************************************************/
379
380void
381acpi_tb_delete_tables_by_type (
382 acpi_table_type type)
383{
384 struct acpi_table_desc *table_desc;
385 u32 count;
386 u32 i;
387
388
389 ACPI_FUNCTION_TRACE_U32 ("tb_delete_tables_by_type", type);
390
391
392 if (type > ACPI_TABLE_MAX) {
393 return_VOID;
394 }
395
396 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_TABLES))) {
397 return;
398 }
399
400 /* Clear the appropriate "typed" global table pointer */
401
402 switch (type) {
403 case ACPI_TABLE_RSDP:
404 acpi_gbl_RSDP = NULL;
405 break;
406
407 case ACPI_TABLE_DSDT:
408 acpi_gbl_DSDT = NULL;
409 break;
410
411 case ACPI_TABLE_FADT:
412 acpi_gbl_FADT = NULL;
413 break;
414
415 case ACPI_TABLE_FACS:
416 acpi_gbl_FACS = NULL;
417 break;
418
419 case ACPI_TABLE_XSDT:
420 acpi_gbl_XSDT = NULL;
421 break;
422
423 case ACPI_TABLE_SSDT:
424 case ACPI_TABLE_PSDT:
425 default:
426 break;
427 }
428
429 /*
430 * Free the table
431 * 1) Get the head of the list
432 */
433 table_desc = acpi_gbl_table_lists[type].next;
434 count = acpi_gbl_table_lists[type].count;
435
436 /*
437 * 2) Walk the entire list, deleting both the allocated tables
438 * and the table descriptors
439 */
440 for (i = 0; i < count; i++) {
441 table_desc = acpi_tb_uninstall_table (table_desc);
442 }
443
444 (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
445 return_VOID;
446}
447
448
449/*******************************************************************************
450 *
451 * FUNCTION: acpi_tb_delete_single_table
452 *
453 * PARAMETERS: table_info - A table info struct
454 *
455 * RETURN: None.
456 *
457 * DESCRIPTION: Low-level free for a single ACPI table. Handles cases where
458 * the table was allocated a buffer or was mapped.
459 *
460 ******************************************************************************/
461
462void
463acpi_tb_delete_single_table (
464 struct acpi_table_desc *table_desc)
465{
466
467 /* Must have a valid table descriptor and pointer */
468
469 if ((!table_desc) ||
470 (!table_desc->pointer)) {
471 return;
472 }
473
474 /* Valid table, determine type of memory allocation */
475
476 switch (table_desc->allocation) {
477 case ACPI_MEM_NOT_ALLOCATED:
478 break;
479
480 case ACPI_MEM_ALLOCATED:
481
482 ACPI_MEM_FREE (table_desc->pointer);
483 break;
484
485 case ACPI_MEM_MAPPED:
486
487 acpi_os_unmap_memory (table_desc->pointer, table_desc->length);
488 break;
489
490 default:
491 break;
492 }
493}
494
495
496/*******************************************************************************
497 *
498 * FUNCTION: acpi_tb_uninstall_table
499 *
500 * PARAMETERS: table_info - A table info struct
501 *
502 * RETURN: Pointer to the next table in the list (of same type)
503 *
504 * DESCRIPTION: Free the memory associated with an internal ACPI table that
505 * is either installed or has never been installed.
506 * Table mutex should be locked.
507 *
508 ******************************************************************************/
509
510struct acpi_table_desc *
511acpi_tb_uninstall_table (
512 struct acpi_table_desc *table_desc)
513{
514 struct acpi_table_desc *next_desc;
515
516
517 ACPI_FUNCTION_TRACE_PTR ("tb_uninstall_table", table_desc);
518
519
520 if (!table_desc) {
521 return_PTR (NULL);
522 }
523
524 /* Unlink the descriptor from the doubly linked list */
525
526 if (table_desc->prev) {
527 table_desc->prev->next = table_desc->next;
528 }
529 else {
530 /* Is first on list, update list head */
531
532 acpi_gbl_table_lists[table_desc->type].next = table_desc->next;
533 }
534
535 if (table_desc->next) {
536 table_desc->next->prev = table_desc->prev;
537 }
538
539 /* Free the memory allocated for the table itself */
540
541 acpi_tb_delete_single_table (table_desc);
542
543 /* Free the table descriptor */
544
545 next_desc = table_desc->next;
546 ACPI_MEM_FREE (table_desc);
547
548 /* Return pointer to the next descriptor */
549
550 return_PTR (next_desc);
551}
552
553
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c
new file mode 100644
index 000000000000..9c6913238d52
--- /dev/null
+++ b/drivers/acpi/tables/tbrsdt.c
@@ -0,0 +1,324 @@
1/******************************************************************************
2 *
3 * Module Name: tbrsdt - ACPI RSDT table utilities
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/actables.h>
47
48
49#define _COMPONENT ACPI_TABLES
50 ACPI_MODULE_NAME ("tbrsdt")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_tb_verify_rsdp
56 *
57 * PARAMETERS: Address - RSDP (Pointer to RSDT)
58 *
59 * RETURN: Status
60 *
61 * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table)
62 *
63 ******************************************************************************/
64
65acpi_status
66acpi_tb_verify_rsdp (
67 struct acpi_pointer *address)
68{
69 struct acpi_table_desc table_info;
70 acpi_status status;
71 struct rsdp_descriptor *rsdp;
72
73
74 ACPI_FUNCTION_TRACE ("tb_verify_rsdp");
75
76
77 switch (address->pointer_type) {
78 case ACPI_LOGICAL_POINTER:
79
80 rsdp = address->pointer.logical;
81 break;
82
83 case ACPI_PHYSICAL_POINTER:
84 /*
85 * Obtain access to the RSDP structure
86 */
87 status = acpi_os_map_memory (address->pointer.physical, sizeof (struct rsdp_descriptor),
88 (void *) &rsdp);
89 if (ACPI_FAILURE (status)) {
90 return_ACPI_STATUS (status);
91 }
92 break;
93
94 default:
95 return_ACPI_STATUS (AE_BAD_PARAMETER);
96 }
97
98 /*
99 * The signature and checksum must both be correct
100 */
101 if (ACPI_STRNCMP ((char *) rsdp, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
102 /* Nope, BAD Signature */
103
104 status = AE_BAD_SIGNATURE;
105 goto cleanup;
106 }
107
108 /* Check the standard checksum */
109
110 if (acpi_tb_checksum (rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
111 status = AE_BAD_CHECKSUM;
112 goto cleanup;
113 }
114
115 /* Check extended checksum if table version >= 2 */
116
117 if (rsdp->revision >= 2) {
118 if (acpi_tb_checksum (rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) {
119 status = AE_BAD_CHECKSUM;
120 goto cleanup;
121 }
122 }
123
124 /* The RSDP supplied is OK */
125
126 table_info.pointer = ACPI_CAST_PTR (struct acpi_table_header, rsdp);
127 table_info.length = sizeof (struct rsdp_descriptor);
128 table_info.allocation = ACPI_MEM_MAPPED;
129
130 /* Save the table pointers and allocation info */
131
132 status = acpi_tb_init_table_descriptor (ACPI_TABLE_RSDP, &table_info);
133 if (ACPI_FAILURE (status)) {
134 goto cleanup;
135 }
136
137 /* Save the RSDP in a global for easy access */
138
139 acpi_gbl_RSDP = ACPI_CAST_PTR (struct rsdp_descriptor, table_info.pointer);
140 return_ACPI_STATUS (status);
141
142
143 /* Error exit */
144cleanup:
145
146 if (acpi_gbl_table_flags & ACPI_PHYSICAL_POINTER) {
147 acpi_os_unmap_memory (rsdp, sizeof (struct rsdp_descriptor));
148 }
149 return_ACPI_STATUS (status);
150}
151
152
153/*******************************************************************************
154 *
155 * FUNCTION: acpi_tb_get_rsdt_address
156 *
157 * PARAMETERS: None
158 *
159 * RETURN: RSDT physical address
160 *
161 * DESCRIPTION: Extract the address of the RSDT or XSDT, depending on the
162 * version of the RSDP
163 *
164 ******************************************************************************/
165
166void
167acpi_tb_get_rsdt_address (
168 struct acpi_pointer *out_address)
169{
170
171 ACPI_FUNCTION_ENTRY ();
172
173
174 out_address->pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
175
176 /*
177 * For RSDP revision 0 or 1, we use the RSDT.
178 * For RSDP revision 2 (and above), we use the XSDT
179 */
180 if (acpi_gbl_RSDP->revision < 2) {
181 out_address->pointer.value = acpi_gbl_RSDP->rsdt_physical_address;
182 }
183 else {
184 out_address->pointer.value = acpi_gbl_RSDP->xsdt_physical_address;
185 }
186}
187
188
189/*******************************************************************************
190 *
191 * FUNCTION: acpi_tb_validate_rsdt
192 *
193 * PARAMETERS: table_ptr - Addressable pointer to the RSDT.
194 *
195 * RETURN: Status
196 *
197 * DESCRIPTION: Validate signature for the RSDT or XSDT
198 *
199 ******************************************************************************/
200
201acpi_status
202acpi_tb_validate_rsdt (
203 struct acpi_table_header *table_ptr)
204{
205 int no_match;
206
207
208 ACPI_FUNCTION_NAME ("tb_validate_rsdt");
209
210
211 /*
212 * For RSDP revision 0 or 1, we use the RSDT.
213 * For RSDP revision 2 and above, we use the XSDT
214 */
215 if (acpi_gbl_RSDP->revision < 2) {
216 no_match = ACPI_STRNCMP ((char *) table_ptr, RSDT_SIG,
217 sizeof (RSDT_SIG) -1);
218 }
219 else {
220 no_match = ACPI_STRNCMP ((char *) table_ptr, XSDT_SIG,
221 sizeof (XSDT_SIG) -1);
222 }
223
224 if (no_match) {
225 /* Invalid RSDT or XSDT signature */
226
227 ACPI_REPORT_ERROR (("Invalid signature where RSDP indicates RSDT/XSDT should be located\n"));
228
229 ACPI_DUMP_BUFFER (acpi_gbl_RSDP, 20);
230
231 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR,
232 "RSDT/XSDT signature at %X (%p) is invalid\n",
233 acpi_gbl_RSDP->rsdt_physical_address,
234 (void *) (acpi_native_uint) acpi_gbl_RSDP->rsdt_physical_address));
235
236 if (acpi_gbl_RSDP->revision < 2) {
237 ACPI_REPORT_ERROR (("Looking for RSDT (RSDP->Rev < 2)\n"))
238 }
239 else {
240 ACPI_REPORT_ERROR (("Looking for XSDT (RSDP->Rev >= 2)\n"))
241 }
242
243 ACPI_DUMP_BUFFER ((char *) table_ptr, 48);
244
245 return (AE_BAD_SIGNATURE);
246 }
247
248 return (AE_OK);
249}
250
251
252/*******************************************************************************
253 *
254 * FUNCTION: acpi_tb_get_table_rsdt
255 *
256 * PARAMETERS: None
257 *
258 * RETURN: Status
259 *
260 * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table)
261 *
262 ******************************************************************************/
263
264acpi_status
265acpi_tb_get_table_rsdt (
266 void)
267{
268 struct acpi_table_desc table_info;
269 acpi_status status;
270 struct acpi_pointer address;
271
272
273 ACPI_FUNCTION_TRACE ("tb_get_table_rsdt");
274
275
276 /* Get the RSDT/XSDT via the RSDP */
277
278 acpi_tb_get_rsdt_address (&address);
279
280 table_info.type = ACPI_TABLE_XSDT;
281 status = acpi_tb_get_table (&address, &table_info);
282 if (ACPI_FAILURE (status)) {
283 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not get the RSDT/XSDT, %s\n",
284 acpi_format_exception (status)));
285 return_ACPI_STATUS (status);
286 }
287
288 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
289 "RSDP located at %p, points to RSDT physical=%8.8X%8.8X \n",
290 acpi_gbl_RSDP,
291 ACPI_FORMAT_UINT64 (address.pointer.value)));
292
293 /* Check the RSDT or XSDT signature */
294
295 status = acpi_tb_validate_rsdt (table_info.pointer);
296 if (ACPI_FAILURE (status)) {
297 return_ACPI_STATUS (status);
298 }
299
300 /* Get the number of tables defined in the RSDT or XSDT */
301
302 acpi_gbl_rsdt_table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, table_info.pointer);
303
304 /* Convert and/or copy to an XSDT structure */
305
306 status = acpi_tb_convert_to_xsdt (&table_info);
307 if (ACPI_FAILURE (status)) {
308 return_ACPI_STATUS (status);
309 }
310
311 /* Save the table pointers and allocation info */
312
313 status = acpi_tb_init_table_descriptor (ACPI_TABLE_XSDT, &table_info);
314 if (ACPI_FAILURE (status)) {
315 return_ACPI_STATUS (status);
316 }
317
318 acpi_gbl_XSDT = ACPI_CAST_PTR (XSDT_DESCRIPTOR, table_info.pointer);
319
320 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT));
321 return_ACPI_STATUS (status);
322}
323
324
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
new file mode 100644
index 000000000000..fede5804c783
--- /dev/null
+++ b/drivers/acpi/tables/tbutils.c
@@ -0,0 +1,240 @@
1/******************************************************************************
2 *
3 * Module Name: tbutils - Table manipulation utilities
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/actables.h>
47
48
49#define _COMPONENT ACPI_TABLES
50 ACPI_MODULE_NAME ("tbutils")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_tb_handle_to_object
56 *
57 * PARAMETERS: table_id - Id for which the function is searching
58 * table_desc - Pointer to return the matching table
59 * descriptor.
60 *
61 * RETURN: Search the tables to find one with a matching table_id and
62 * return a pointer to that table descriptor.
63 *
64 ******************************************************************************/
65#ifdef ACPI_FUTURE_USAGE
66acpi_status
67acpi_tb_handle_to_object (
68 u16 table_id,
69 struct acpi_table_desc **return_table_desc)
70{
71 u32 i;
72 struct acpi_table_desc *table_desc;
73
74
75 ACPI_FUNCTION_NAME ("tb_handle_to_object");
76
77
78 for (i = 0; i < ACPI_TABLE_MAX; i++) {
79 table_desc = acpi_gbl_table_lists[i].next;
80 while (table_desc) {
81 if (table_desc->table_id == table_id) {
82 *return_table_desc = table_desc;
83 return (AE_OK);
84 }
85
86 table_desc = table_desc->next;
87 }
88 }
89
90 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "table_id=%X does not exist\n", table_id));
91 return (AE_BAD_PARAMETER);
92}
93#endif /* ACPI_FUTURE_USAGE */
94
95
96/*******************************************************************************
97 *
98 * FUNCTION: acpi_tb_validate_table_header
99 *
100 * PARAMETERS: table_header - Logical pointer to the table
101 *
102 * RETURN: Status
103 *
104 * DESCRIPTION: Check an ACPI table header for validity
105 *
106 * NOTE: Table pointers are validated as follows:
107 * 1) Table pointer must point to valid physical memory
108 * 2) Signature must be 4 ASCII chars, even if we don't recognize the
109 * name
110 * 3) Table must be readable for length specified in the header
111 * 4) Table checksum must be valid (with the exception of the FACS
112 * which has no checksum because it contains variable fields)
113 *
114 ******************************************************************************/
115
116acpi_status
117acpi_tb_validate_table_header (
118 struct acpi_table_header *table_header)
119{
120 acpi_name signature;
121
122
123 ACPI_FUNCTION_NAME ("tb_validate_table_header");
124
125
126 /* Verify that this is a valid address */
127
128 if (!acpi_os_readable (table_header, sizeof (struct acpi_table_header))) {
129 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
130 "Cannot read table header at %p\n", table_header));
131 return (AE_BAD_ADDRESS);
132 }
133
134 /* Ensure that the signature is 4 ASCII characters */
135
136 ACPI_MOVE_32_TO_32 (&signature, table_header->signature);
137 if (!acpi_ut_valid_acpi_name (signature)) {
138 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
139 "Table signature at %p [%p] has invalid characters\n",
140 table_header, &signature));
141
142 ACPI_REPORT_WARNING (("Invalid table signature found: [%4.4s]\n",
143 (char *) &signature));
144 ACPI_DUMP_BUFFER (table_header, sizeof (struct acpi_table_header));
145 return (AE_BAD_SIGNATURE);
146 }
147
148 /* Validate the table length */
149
150 if (table_header->length < sizeof (struct acpi_table_header)) {
151 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
152 "Invalid length in table header %p name %4.4s\n",
153 table_header, (char *) &signature));
154
155 ACPI_REPORT_WARNING (("Invalid table header length (0x%X) found\n",
156 (u32) table_header->length));
157 ACPI_DUMP_BUFFER (table_header, sizeof (struct acpi_table_header));
158 return (AE_BAD_HEADER);
159 }
160
161 return (AE_OK);
162}
163
164
165/*******************************************************************************
166 *
167 * FUNCTION: acpi_tb_verify_table_checksum
168 *
169 * PARAMETERS: *table_header - ACPI table to verify
170 *
171 * RETURN: 8 bit checksum of table
172 *
173 * DESCRIPTION: Does an 8 bit checksum of table and returns status. A correct
174 * table should have a checksum of 0.
175 *
176 ******************************************************************************/
177
178acpi_status
179acpi_tb_verify_table_checksum (
180 struct acpi_table_header *table_header)
181{
182 u8 checksum;
183 acpi_status status = AE_OK;
184
185
186 ACPI_FUNCTION_TRACE ("tb_verify_table_checksum");
187
188
189 /* Compute the checksum on the table */
190
191 checksum = acpi_tb_checksum (table_header, table_header->length);
192
193 /* Return the appropriate exception */
194
195 if (checksum) {
196 ACPI_REPORT_WARNING (("Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)\n",
197 table_header->signature, (u32) table_header->checksum, (u32) checksum));
198
199 status = AE_BAD_CHECKSUM;
200 }
201 return_ACPI_STATUS (status);
202}
203
204
205/*******************************************************************************
206 *
207 * FUNCTION: acpi_tb_checksum
208 *
209 * PARAMETERS: Buffer - Buffer to checksum
210 * Length - Size of the buffer
211 *
212 * RETURNS 8 bit checksum of buffer
213 *
214 * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it.
215 *
216 ******************************************************************************/
217
218u8
219acpi_tb_checksum (
220 void *buffer,
221 u32 length)
222{
223 const u8 *limit;
224 const u8 *rover;
225 u8 sum = 0;
226
227
228 if (buffer && length) {
229 /* Buffer and Length are valid */
230
231 limit = (u8 *) buffer + length;
232
233 for (rover = buffer; rover < limit; rover++) {
234 sum = (u8) (sum + *rover);
235 }
236 }
237 return (sum);
238}
239
240
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
new file mode 100644
index 000000000000..7715043461c4
--- /dev/null
+++ b/drivers/acpi/tables/tbxface.c
@@ -0,0 +1,448 @@
1/******************************************************************************
2 *
3 * Module Name: tbxface - Public interfaces to the ACPI subsystem
4 * ACPI table oriented interfaces
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <linux/module.h>
46
47#include <acpi/acpi.h>
48#include <acpi/acnamesp.h>
49#include <acpi/actables.h>
50
51
52#define _COMPONENT ACPI_TABLES
53 ACPI_MODULE_NAME ("tbxface")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_load_tables
59 *
60 * PARAMETERS: None
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: This function is called to load the ACPI tables from the
65 * provided RSDT
66 *
67 ******************************************************************************/
68
69acpi_status
70acpi_load_tables (void)
71{
72 struct acpi_pointer rsdp_address;
73 acpi_status status;
74
75
76 ACPI_FUNCTION_TRACE ("acpi_load_tables");
77
78
79 /* Get the RSDP */
80
81 status = acpi_os_get_root_pointer (ACPI_LOGICAL_ADDRESSING,
82 &rsdp_address);
83 if (ACPI_FAILURE (status)) {
84 ACPI_REPORT_ERROR (("acpi_load_tables: Could not get RSDP, %s\n",
85 acpi_format_exception (status)));
86 goto error_exit;
87 }
88
89 /* Map and validate the RSDP */
90
91 acpi_gbl_table_flags = rsdp_address.pointer_type;
92
93 status = acpi_tb_verify_rsdp (&rsdp_address);
94 if (ACPI_FAILURE (status)) {
95 ACPI_REPORT_ERROR (("acpi_load_tables: RSDP Failed validation: %s\n",
96 acpi_format_exception (status)));
97 goto error_exit;
98 }
99
100 /* Get the RSDT via the RSDP */
101
102 status = acpi_tb_get_table_rsdt ();
103 if (ACPI_FAILURE (status)) {
104 ACPI_REPORT_ERROR (("acpi_load_tables: Could not load RSDT: %s\n",
105 acpi_format_exception (status)));
106 goto error_exit;
107 }
108
109 /* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */
110
111 status = acpi_tb_get_required_tables ();
112 if (ACPI_FAILURE (status)) {
113 ACPI_REPORT_ERROR (("acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n",
114 acpi_format_exception (status)));
115 goto error_exit;
116 }
117
118 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
119
120
121 /* Load the namespace from the tables */
122
123 status = acpi_ns_load_namespace ();
124 if (ACPI_FAILURE (status)) {
125 ACPI_REPORT_ERROR (("acpi_load_tables: Could not load namespace: %s\n",
126 acpi_format_exception (status)));
127 goto error_exit;
128 }
129
130 return_ACPI_STATUS (AE_OK);
131
132
133error_exit:
134 ACPI_REPORT_ERROR (("acpi_load_tables: Could not load tables: %s\n",
135 acpi_format_exception (status)));
136
137 return_ACPI_STATUS (status);
138}
139
140
141#ifdef ACPI_FUTURE_USAGE
142
143/*******************************************************************************
144 *
145 * FUNCTION: acpi_load_table
146 *
147 * PARAMETERS: table_ptr - pointer to a buffer containing the entire
148 * table to be loaded
149 *
150 * RETURN: Status
151 *
152 * DESCRIPTION: This function is called to load a table from the caller's
153 * buffer. The buffer must contain an entire ACPI Table including
154 * a valid header. The header fields will be verified, and if it
155 * is determined that the table is invalid, the call will fail.
156 *
157 ******************************************************************************/
158
159acpi_status
160acpi_load_table (
161 struct acpi_table_header *table_ptr)
162{
163 acpi_status status;
164 struct acpi_table_desc table_info;
165 struct acpi_pointer address;
166
167
168 ACPI_FUNCTION_TRACE ("acpi_load_table");
169
170
171 if (!table_ptr) {
172 return_ACPI_STATUS (AE_BAD_PARAMETER);
173 }
174
175 /* Copy the table to a local buffer */
176
177 address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
178 address.pointer.logical = table_ptr;
179
180 status = acpi_tb_get_table_body (&address, table_ptr, &table_info);
181 if (ACPI_FAILURE (status)) {
182 return_ACPI_STATUS (status);
183 }
184
185 /* Install the new table into the local data structures */
186
187 status = acpi_tb_install_table (&table_info);
188 if (ACPI_FAILURE (status)) {
189 /* Free table allocated by acpi_tb_get_table_body */
190
191 acpi_tb_delete_single_table (&table_info);
192 return_ACPI_STATUS (status);
193 }
194
195 /* Convert the table to common format if necessary */
196
197 switch (table_info.type) {
198 case ACPI_TABLE_FADT:
199
200 status = acpi_tb_convert_table_fadt ();
201 break;
202
203 case ACPI_TABLE_FACS:
204
205 status = acpi_tb_build_common_facs (&table_info);
206 break;
207
208 default:
209 /* Load table into namespace if it contains executable AML */
210
211 status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node);
212 break;
213 }
214
215 if (ACPI_FAILURE (status)) {
216 /* Uninstall table and free the buffer */
217
218 (void) acpi_tb_uninstall_table (table_info.installed_desc);
219 }
220
221 return_ACPI_STATUS (status);
222}
223
224
225/*******************************************************************************
226 *
227 * FUNCTION: acpi_unload_table
228 *
229 * PARAMETERS: table_type - Type of table to be unloaded
230 *
231 * RETURN: Status
232 *
233 * DESCRIPTION: This routine is used to force the unload of a table
234 *
235 ******************************************************************************/
236
237acpi_status
238acpi_unload_table (
239 acpi_table_type table_type)
240{
241 struct acpi_table_desc *table_desc;
242
243
244 ACPI_FUNCTION_TRACE ("acpi_unload_table");
245
246
247 /* Parameter validation */
248
249 if (table_type > ACPI_TABLE_MAX) {
250 return_ACPI_STATUS (AE_BAD_PARAMETER);
251 }
252
253
254 /* Find all tables of the requested type */
255
256 table_desc = acpi_gbl_table_lists[table_type].next;
257 while (table_desc) {
258 /*
259 * Delete all namespace entries owned by this table. Note that these
260 * entries can appear anywhere in the namespace by virtue of the AML
261 * "Scope" operator. Thus, we need to track ownership by an ID, not
262 * simply a position within the hierarchy
263 */
264 acpi_ns_delete_namespace_by_owner (table_desc->table_id);
265
266 table_desc = table_desc->next;
267 }
268
269 /* Delete (or unmap) all tables of this type */
270
271 acpi_tb_delete_tables_by_type (table_type);
272 return_ACPI_STATUS (AE_OK);
273}
274
275
276/*******************************************************************************
277 *
278 * FUNCTION: acpi_get_table_header
279 *
280 * PARAMETERS: table_type - one of the defined table types
281 * Instance - the non zero instance of the table, allows
282 * support for multiple tables of the same type
283 * see acpi_gbl_acpi_table_flag
284 * out_table_header - pointer to the struct acpi_table_header if successful
285 *
286 * DESCRIPTION: This function is called to get an ACPI table header. The caller
287 * supplies an pointer to a data area sufficient to contain an ACPI
288 * struct acpi_table_header structure.
289 *
290 * The header contains a length field that can be used to determine
291 * the size of the buffer needed to contain the entire table. This
292 * function is not valid for the RSD PTR table since it does not
293 * have a standard header and is fixed length.
294 *
295 ******************************************************************************/
296
297acpi_status
298acpi_get_table_header (
299 acpi_table_type table_type,
300 u32 instance,
301 struct acpi_table_header *out_table_header)
302{
303 struct acpi_table_header *tbl_ptr;
304 acpi_status status;
305
306
307 ACPI_FUNCTION_TRACE ("acpi_get_table_header");
308
309
310 if ((instance == 0) ||
311 (table_type == ACPI_TABLE_RSDP) ||
312 (!out_table_header)) {
313 return_ACPI_STATUS (AE_BAD_PARAMETER);
314 }
315
316 /* Check the table type and instance */
317
318 if ((table_type > ACPI_TABLE_MAX) ||
319 (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) &&
320 instance > 1)) {
321 return_ACPI_STATUS (AE_BAD_PARAMETER);
322 }
323
324
325 /* Get a pointer to the entire table */
326
327 status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr);
328 if (ACPI_FAILURE (status)) {
329 return_ACPI_STATUS (status);
330 }
331
332 /*
333 * The function will return a NULL pointer if the table is not loaded
334 */
335 if (tbl_ptr == NULL) {
336 return_ACPI_STATUS (AE_NOT_EXIST);
337 }
338
339 /*
340 * Copy the header to the caller's buffer
341 */
342 ACPI_MEMCPY ((void *) out_table_header, (void *) tbl_ptr,
343 sizeof (struct acpi_table_header));
344
345 return_ACPI_STATUS (status);
346}
347
348
349#endif /* ACPI_FUTURE_USAGE */
350
351/*******************************************************************************
352 *
353 * FUNCTION: acpi_get_table
354 *
355 * PARAMETERS: table_type - one of the defined table types
356 * Instance - the non zero instance of the table, allows
357 * support for multiple tables of the same type
358 * see acpi_gbl_acpi_table_flag
359 * ret_buffer - pointer to a structure containing a buffer to
360 * receive the table
361 *
362 * RETURN: Status
363 *
364 * DESCRIPTION: This function is called to get an ACPI table. The caller
365 * supplies an out_buffer large enough to contain the entire ACPI
366 * table. The caller should call the acpi_get_table_header function
367 * first to determine the buffer size needed. Upon completion
368 * the out_buffer->Length field will indicate the number of bytes
369 * copied into the out_buffer->buf_ptr buffer. This table will be
370 * a complete table including the header.
371 *
372 ******************************************************************************/
373
374acpi_status
375acpi_get_table (
376 acpi_table_type table_type,
377 u32 instance,
378 struct acpi_buffer *ret_buffer)
379{
380 struct acpi_table_header *tbl_ptr;
381 acpi_status status;
382 acpi_size table_length;
383
384
385 ACPI_FUNCTION_TRACE ("acpi_get_table");
386
387
388 /* Parameter validation */
389
390 if (instance == 0) {
391 return_ACPI_STATUS (AE_BAD_PARAMETER);
392 }
393
394 status = acpi_ut_validate_buffer (ret_buffer);
395 if (ACPI_FAILURE (status)) {
396 return_ACPI_STATUS (status);
397 }
398
399 /* Check the table type and instance */
400
401 if ((table_type > ACPI_TABLE_MAX) ||
402 (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) &&
403 instance > 1)) {
404 return_ACPI_STATUS (AE_BAD_PARAMETER);
405 }
406
407
408 /* Get a pointer to the entire table */
409
410 status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr);
411 if (ACPI_FAILURE (status)) {
412 return_ACPI_STATUS (status);
413 }
414
415 /*
416 * acpi_tb_get_table_ptr will return a NULL pointer if the
417 * table is not loaded.
418 */
419 if (tbl_ptr == NULL) {
420 return_ACPI_STATUS (AE_NOT_EXIST);
421 }
422
423 /* Get the table length */
424
425 if (table_type == ACPI_TABLE_RSDP) {
426 /*
427 * RSD PTR is the only "table" without a header
428 */
429 table_length = sizeof (struct rsdp_descriptor);
430 }
431 else {
432 table_length = (acpi_size) tbl_ptr->length;
433 }
434
435 /* Validate/Allocate/Clear caller buffer */
436
437 status = acpi_ut_initialize_buffer (ret_buffer, table_length);
438 if (ACPI_FAILURE (status)) {
439 return_ACPI_STATUS (status);
440 }
441
442 /* Copy the table to the buffer */
443
444 ACPI_MEMCPY ((void *) ret_buffer->pointer, (void *) tbl_ptr, table_length);
445 return_ACPI_STATUS (AE_OK);
446}
447EXPORT_SYMBOL(acpi_get_table);
448
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
new file mode 100644
index 000000000000..6e8072ebbac6
--- /dev/null
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -0,0 +1,606 @@
1/******************************************************************************
2 *
3 * Module Name: tbxfroot - Find the root ACPI table (RSDT)
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <linux/module.h>
45
46#include <acpi/acpi.h>
47#include <acpi/actables.h>
48
49
50#define _COMPONENT ACPI_TABLES
51 ACPI_MODULE_NAME ("tbxfroot")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_tb_find_table
57 *
58 * PARAMETERS: Signature - String with ACPI table signature
59 * oem_id - String with the table OEM ID
60 * oem_table_id - String with the OEM Table ID.
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the
65 * Signature, OEM ID and OEM Table ID.
66 *
67 ******************************************************************************/
68
69acpi_status
70acpi_tb_find_table (
71 char *signature,
72 char *oem_id,
73 char *oem_table_id,
74 struct acpi_table_header **table_ptr)
75{
76 acpi_status status;
77 struct acpi_table_header *table;
78
79
80 ACPI_FUNCTION_TRACE ("tb_find_table");
81
82
83 /* Validate string lengths */
84
85 if ((ACPI_STRLEN (signature) > ACPI_NAME_SIZE) ||
86 (ACPI_STRLEN (oem_id) > sizeof (table->oem_id)) ||
87 (ACPI_STRLEN (oem_table_id) > sizeof (table->oem_table_id))) {
88 return_ACPI_STATUS (AE_AML_STRING_LIMIT);
89 }
90
91 if (!ACPI_STRNCMP (signature, DSDT_SIG, ACPI_NAME_SIZE)) {
92 /*
93 * The DSDT pointer is contained in the FADT, not the RSDT.
94 * This code should suffice, because the only code that would perform
95 * a "find" on the DSDT is the data_table_region() AML opcode -- in
96 * which case, the DSDT is guaranteed to be already loaded.
97 * If this becomes insufficient, the FADT will have to be found first.
98 */
99 if (!acpi_gbl_DSDT) {
100 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
101 }
102
103 table = acpi_gbl_DSDT;
104 }
105 else {
106 /* Find the table */
107
108 status = acpi_get_firmware_table (signature, 1,
109 ACPI_LOGICAL_ADDRESSING, &table);
110 if (ACPI_FAILURE (status)) {
111 return_ACPI_STATUS (status);
112 }
113 }
114
115 /* Check oem_id and oem_table_id */
116
117 if ((oem_id[0] && ACPI_STRNCMP (
118 oem_id, table->oem_id, sizeof (table->oem_id))) ||
119 (oem_table_id[0] && ACPI_STRNCMP (
120 oem_table_id, table->oem_table_id, sizeof (table->oem_table_id)))) {
121 return_ACPI_STATUS (AE_AML_NAME_NOT_FOUND);
122 }
123
124 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Found table [%4.4s]\n", table->signature));
125 *table_ptr = table;
126 return_ACPI_STATUS (AE_OK);
127}
128
129
130/*******************************************************************************
131 *
132 * FUNCTION: acpi_get_firmware_table
133 *
134 * PARAMETERS: Signature - Any ACPI table signature
135 * Instance - the non zero instance of the table, allows
136 * support for multiple tables of the same type
137 * Flags - Physical/Virtual support
138 * table_pointer - Where a buffer containing the table is
139 * returned
140 *
141 * RETURN: Status
142 *
143 * DESCRIPTION: This function is called to get an ACPI table. A buffer is
144 * allocated for the table and returned in table_pointer.
145 * This table will be a complete table including the header.
146 *
147 ******************************************************************************/
148
149acpi_status
150acpi_get_firmware_table (
151 acpi_string signature,
152 u32 instance,
153 u32 flags,
154 struct acpi_table_header **table_pointer)
155{
156 acpi_status status;
157 struct acpi_pointer address;
158 struct acpi_table_header *header = NULL;
159 struct acpi_table_desc *table_info = NULL;
160 struct acpi_table_desc *rsdt_info;
161 u32 table_count;
162 u32 i;
163 u32 j;
164
165
166 ACPI_FUNCTION_TRACE ("acpi_get_firmware_table");
167
168
169 /*
170 * Ensure that at least the table manager is initialized. We don't
171 * require that the entire ACPI subsystem is up for this interface.
172 * If we have a buffer, we must have a length too
173 */
174 if ((instance == 0) ||
175 (!signature) ||
176 (!table_pointer)) {
177 return_ACPI_STATUS (AE_BAD_PARAMETER);
178 }
179
180 /* Ensure that we have a RSDP */
181
182 if (!acpi_gbl_RSDP) {
183 /* Get the RSDP */
184
185 status = acpi_os_get_root_pointer (flags, &address);
186 if (ACPI_FAILURE (status)) {
187 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n"));
188 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
189 }
190
191 /* Map and validate the RSDP */
192
193 if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
194 status = acpi_os_map_memory (address.pointer.physical, sizeof (struct rsdp_descriptor),
195 (void *) &acpi_gbl_RSDP);
196 if (ACPI_FAILURE (status)) {
197 return_ACPI_STATUS (status);
198 }
199 }
200 else {
201 acpi_gbl_RSDP = address.pointer.logical;
202 }
203
204 /* The signature and checksum must both be correct */
205
206 if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
207 /* Nope, BAD Signature */
208
209 return_ACPI_STATUS (AE_BAD_SIGNATURE);
210 }
211
212 if (acpi_tb_checksum (acpi_gbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
213 /* Nope, BAD Checksum */
214
215 return_ACPI_STATUS (AE_BAD_CHECKSUM);
216 }
217 }
218
219 /* Get the RSDT address via the RSDP */
220
221 acpi_tb_get_rsdt_address (&address);
222 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
223 "RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
224 acpi_gbl_RSDP,
225 ACPI_FORMAT_UINT64 (address.pointer.value)));
226
227 /* Insert processor_mode flags */
228
229 address.pointer_type |= flags;
230
231 /* Get and validate the RSDT */
232
233 rsdt_info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc));
234 if (!rsdt_info) {
235 return_ACPI_STATUS (AE_NO_MEMORY);
236 }
237
238 status = acpi_tb_get_table (&address, rsdt_info);
239 if (ACPI_FAILURE (status)) {
240 goto cleanup;
241 }
242
243 status = acpi_tb_validate_rsdt (rsdt_info->pointer);
244 if (ACPI_FAILURE (status)) {
245 goto cleanup;
246 }
247
248 /* Allocate a scratch table header and table descriptor */
249
250 header = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_header));
251 if (!header) {
252 status = AE_NO_MEMORY;
253 goto cleanup;
254 }
255
256 table_info = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_desc));
257 if (!table_info) {
258 status = AE_NO_MEMORY;
259 goto cleanup;
260 }
261
262 /* Get the number of table pointers within the RSDT */
263
264 table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info->pointer);
265 address.pointer_type = acpi_gbl_table_flags | flags;
266
267 /*
268 * Search the RSDT/XSDT for the correct instance of the
269 * requested table
270 */
271 for (i = 0, j = 0; i < table_count; i++) {
272 /* Get the next table pointer, handle RSDT vs. XSDT */
273
274 if (acpi_gbl_RSDP->revision < 2) {
275 address.pointer.value = (ACPI_CAST_PTR (
276 RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
277 }
278 else {
279 address.pointer.value = (ACPI_CAST_PTR (
280 XSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
281 }
282
283 /* Get the table header */
284
285 status = acpi_tb_get_table_header (&address, header);
286 if (ACPI_FAILURE (status)) {
287 goto cleanup;
288 }
289
290 /* Compare table signatures and table instance */
291
292 if (!ACPI_STRNCMP (header->signature, signature, ACPI_NAME_SIZE)) {
293 /* An instance of the table was found */
294
295 j++;
296 if (j >= instance) {
297 /* Found the correct instance, get the entire table */
298
299 status = acpi_tb_get_table_body (&address, header, table_info);
300 if (ACPI_FAILURE (status)) {
301 goto cleanup;
302 }
303
304 *table_pointer = table_info->pointer;
305 goto cleanup;
306 }
307 }
308 }
309
310 /* Did not find the table */
311
312 status = AE_NOT_EXIST;
313
314
315cleanup:
316 acpi_os_unmap_memory (rsdt_info->pointer, (acpi_size) rsdt_info->pointer->length);
317 ACPI_MEM_FREE (rsdt_info);
318
319 if (header) {
320 ACPI_MEM_FREE (header);
321 }
322 if (table_info) {
323 ACPI_MEM_FREE (table_info);
324 }
325 return_ACPI_STATUS (status);
326}
327EXPORT_SYMBOL(acpi_get_firmware_table);
328
329
330/* TBD: Move to a new file */
331
332#if ACPI_MACHINE_WIDTH != 16
333
334/*******************************************************************************
335 *
336 * FUNCTION: acpi_find_root_pointer
337 *
338 * PARAMETERS: **rsdp_address - Where to place the RSDP address
339 * Flags - Logical/Physical addressing
340 *
341 * RETURN: Status, Physical address of the RSDP
342 *
343 * DESCRIPTION: Find the RSDP
344 *
345 ******************************************************************************/
346
347acpi_status
348acpi_find_root_pointer (
349 u32 flags,
350 struct acpi_pointer *rsdp_address)
351{
352 struct acpi_table_desc table_info;
353 acpi_status status;
354
355
356 ACPI_FUNCTION_TRACE ("acpi_find_root_pointer");
357
358
359 /* Get the RSDP */
360
361 status = acpi_tb_find_rsdp (&table_info, flags);
362 if (ACPI_FAILURE (status)) {
363 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
364 "RSDP structure not found, %s Flags=%X\n",
365 acpi_format_exception (status), flags));
366 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
367 }
368
369 rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER;
370 rsdp_address->pointer.physical = table_info.physical_address;
371 return_ACPI_STATUS (AE_OK);
372}
373
374
375/*******************************************************************************
376 *
377 * FUNCTION: acpi_tb_scan_memory_for_rsdp
378 *
379 * PARAMETERS: start_address - Starting pointer for search
380 * Length - Maximum length to search
381 *
382 * RETURN: Pointer to the RSDP if found, otherwise NULL.
383 *
384 * DESCRIPTION: Search a block of memory for the RSDP signature
385 *
386 ******************************************************************************/
387
388u8 *
389acpi_tb_scan_memory_for_rsdp (
390 u8 *start_address,
391 u32 length)
392{
393 u8 *mem_rover;
394 u8 *end_address;
395 u8 checksum;
396
397
398 ACPI_FUNCTION_TRACE ("tb_scan_memory_for_rsdp");
399
400
401 end_address = start_address + length;
402
403 /* Search from given start address for the requested length */
404
405 for (mem_rover = start_address; mem_rover < end_address;
406 mem_rover += ACPI_RSDP_SCAN_STEP) {
407 /* The signature and checksum must both be correct */
408
409 if (ACPI_STRNCMP ((char *) mem_rover, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
410 /* No signature match, keep looking */
411
412 continue;
413 }
414
415 /* Signature matches, check the appropriate checksum */
416
417 if ((ACPI_CAST_PTR (struct rsdp_descriptor, mem_rover))->revision < 2) {
418 /* ACPI version 1.0 */
419
420 checksum = acpi_tb_checksum (mem_rover, ACPI_RSDP_CHECKSUM_LENGTH);
421 }
422 else {
423 /* Post ACPI 1.0, use extended_checksum */
424
425 checksum = acpi_tb_checksum (mem_rover, ACPI_RSDP_XCHECKSUM_LENGTH);
426 }
427
428 if (checksum == 0) {
429 /* Checksum valid, we have found a valid RSDP */
430
431 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
432 "RSDP located at physical address %p\n", mem_rover));
433 return_PTR (mem_rover);
434 }
435
436 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
437 "Found an RSDP at physical address %p, but it has a bad checksum\n",
438 mem_rover));
439 }
440
441 /* Searched entire block, no RSDP was found */
442
443 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
444 "Searched entire block, no valid RSDP was found.\n"));
445 return_PTR (NULL);
446}
447
448
449/*******************************************************************************
450 *
451 * FUNCTION: acpi_tb_find_rsdp
452 *
453 * PARAMETERS: *table_info - Where the table info is returned
454 * Flags - Current memory mode (logical vs.
455 * physical addressing)
456 *
457 * RETURN: Status, RSDP physical address
458 *
459 * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor
460 * pointer structure. If it is found, set *RSDP to point to it.
461 *
462 * NOTE1: The RSDp must be either in the first 1_k of the Extended
463 * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
464 * Only a 32-bit physical address is necessary.
465 *
466 * NOTE2: This function is always available, regardless of the
467 * initialization state of the rest of ACPI.
468 *
469 ******************************************************************************/
470
471acpi_status
472acpi_tb_find_rsdp (
473 struct acpi_table_desc *table_info,
474 u32 flags)
475{
476 u8 *table_ptr;
477 u8 *mem_rover;
478 u32 physical_address;
479 acpi_status status;
480
481
482 ACPI_FUNCTION_TRACE ("tb_find_rsdp");
483
484
485 /*
486 * Scan supports either 1) Logical addressing or 2) Physical addressing
487 */
488 if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
489 /*
490 * 1a) Get the location of the EBDA
491 */
492 status = acpi_os_map_memory ((acpi_physical_address) ACPI_EBDA_PTR_LOCATION,
493 ACPI_EBDA_PTR_LENGTH,
494 (void *) &table_ptr);
495 if (ACPI_FAILURE (status)) {
496 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
497 "Could not map memory at %8.8X for length %X\n",
498 ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
499 return_ACPI_STATUS (status);
500 }
501
502 ACPI_MOVE_16_TO_32 (&physical_address, table_ptr);
503 physical_address <<= 4; /* Convert segment to physical address */
504 acpi_os_unmap_memory (table_ptr, ACPI_EBDA_PTR_LENGTH);
505
506 /* EBDA present? */
507
508 if (physical_address > 0x400) {
509 /*
510 * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length)
511 */
512 status = acpi_os_map_memory ((acpi_physical_address) physical_address,
513 ACPI_EBDA_WINDOW_SIZE,
514 (void *) &table_ptr);
515 if (ACPI_FAILURE (status)) {
516 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
517 "Could not map memory at %8.8X for length %X\n",
518 physical_address, ACPI_EBDA_WINDOW_SIZE));
519 return_ACPI_STATUS (status);
520 }
521
522 mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_EBDA_WINDOW_SIZE);
523 acpi_os_unmap_memory (table_ptr, ACPI_EBDA_WINDOW_SIZE);
524
525 if (mem_rover) {
526 /* Found it, return the physical address */
527
528 physical_address += ACPI_PTR_DIFF (mem_rover, table_ptr);
529
530 table_info->physical_address = (acpi_physical_address) physical_address;
531 return_ACPI_STATUS (AE_OK);
532 }
533 }
534
535 /*
536 * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
537 */
538 status = acpi_os_map_memory ((acpi_physical_address) ACPI_HI_RSDP_WINDOW_BASE,
539 ACPI_HI_RSDP_WINDOW_SIZE,
540 (void *) &table_ptr);
541 if (ACPI_FAILURE (status)) {
542 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
543 "Could not map memory at %8.8X for length %X\n",
544 ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE));
545 return_ACPI_STATUS (status);
546 }
547
548 mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
549 acpi_os_unmap_memory (table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
550
551 if (mem_rover) {
552 /* Found it, return the physical address */
553
554 physical_address = ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (mem_rover, table_ptr);
555
556 table_info->physical_address = (acpi_physical_address) physical_address;
557 return_ACPI_STATUS (AE_OK);
558 }
559 }
560
561 /*
562 * Physical addressing
563 */
564 else {
565 /*
566 * 1a) Get the location of the EBDA
567 */
568 ACPI_MOVE_16_TO_32 (&physical_address, ACPI_EBDA_PTR_LOCATION);
569 physical_address <<= 4; /* Convert segment to physical address */
570
571 /* EBDA present? */
572
573 if (physical_address > 0x400) {
574 /*
575 * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length)
576 */
577 mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (physical_address),
578 ACPI_EBDA_WINDOW_SIZE);
579 if (mem_rover) {
580 /* Found it, return the physical address */
581
582 table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
583 return_ACPI_STATUS (AE_OK);
584 }
585 }
586
587 /*
588 * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
589 */
590 mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_HI_RSDP_WINDOW_BASE),
591 ACPI_HI_RSDP_WINDOW_SIZE);
592 if (mem_rover) {
593 /* Found it, return the physical address */
594
595 table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
596 return_ACPI_STATUS (AE_OK);
597 }
598 }
599
600 /* RSDP signature was not found */
601
602 return_ACPI_STATUS (AE_NOT_FOUND);
603}
604
605#endif
606
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
new file mode 100644
index 000000000000..79c3a686bc44
--- /dev/null
+++ b/drivers/acpi/thermal.c
@@ -0,0 +1,1445 @@
1/*
2 * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 41 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 *
25 * This driver fully implements the ACPI thermal policy as described in the
26 * ACPI 2.0 Specification.
27 *
28 * TBD: 1. Implement passive cooling hysteresis.
29 * 2. Enhance passive cooling (CPU) states/limit interface to support
30 * concepts of 'multiple limiters', upper/lower limits, etc.
31 *
32 */
33
34#include <linux/kernel.h>
35#include <linux/module.h>
36#include <linux/init.h>
37#include <linux/types.h>
38#include <linux/proc_fs.h>
39#include <linux/sched.h>
40#include <linux/kmod.h>
41#include <linux/seq_file.h>
42#include <asm/uaccess.h>
43
44#include <acpi/acpi_bus.h>
45#include <acpi/acpi_drivers.h>
46
47#define ACPI_THERMAL_COMPONENT 0x04000000
48#define ACPI_THERMAL_CLASS "thermal_zone"
49#define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver"
50#define ACPI_THERMAL_DEVICE_NAME "Thermal Zone"
51#define ACPI_THERMAL_FILE_STATE "state"
52#define ACPI_THERMAL_FILE_TEMPERATURE "temperature"
53#define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points"
54#define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode"
55#define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency"
56#define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
57#define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81
58#define ACPI_THERMAL_NOTIFY_DEVICES 0x82
59#define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0
60#define ACPI_THERMAL_NOTIFY_HOT 0xF1
61#define ACPI_THERMAL_MODE_ACTIVE 0x00
62#define ACPI_THERMAL_MODE_PASSIVE 0x01
63#define ACPI_THERMAL_MODE_CRITICAL 0xff
64#define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff"
65
66#define ACPI_THERMAL_MAX_ACTIVE 10
67#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
68
69#define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732>=0) ? ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
70#define CELSIUS_TO_KELVIN(t) ((t+273)*10)
71
72#define _COMPONENT ACPI_THERMAL_COMPONENT
73ACPI_MODULE_NAME ("acpi_thermal")
74
75MODULE_AUTHOR("Paul Diefenbaugh");
76MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
77MODULE_LICENSE("GPL");
78
79static int tzp;
80module_param(tzp, int, 0);
81MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
82
83
84static int acpi_thermal_add (struct acpi_device *device);
85static int acpi_thermal_remove (struct acpi_device *device, int type);
86static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
87static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
88static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
89static ssize_t acpi_thermal_write_trip_points (struct file*,const char __user *,size_t,loff_t *);
90static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
91static ssize_t acpi_thermal_write_cooling_mode (struct file*,const char __user *,size_t,loff_t *);
92static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
93static ssize_t acpi_thermal_write_polling(struct file*,const char __user *,size_t,loff_t *);
94
95static struct acpi_driver acpi_thermal_driver = {
96 .name = ACPI_THERMAL_DRIVER_NAME,
97 .class = ACPI_THERMAL_CLASS,
98 .ids = ACPI_THERMAL_HID,
99 .ops = {
100 .add = acpi_thermal_add,
101 .remove = acpi_thermal_remove,
102 },
103};
104
105struct acpi_thermal_state {
106 u8 critical:1;
107 u8 hot:1;
108 u8 passive:1;
109 u8 active:1;
110 u8 reserved:4;
111 int active_index;
112};
113
114struct acpi_thermal_state_flags {
115 u8 valid:1;
116 u8 enabled:1;
117 u8 reserved:6;
118};
119
120struct acpi_thermal_critical {
121 struct acpi_thermal_state_flags flags;
122 unsigned long temperature;
123};
124
125struct acpi_thermal_hot {
126 struct acpi_thermal_state_flags flags;
127 unsigned long temperature;
128};
129
130struct acpi_thermal_passive {
131 struct acpi_thermal_state_flags flags;
132 unsigned long temperature;
133 unsigned long tc1;
134 unsigned long tc2;
135 unsigned long tsp;
136 struct acpi_handle_list devices;
137};
138
139struct acpi_thermal_active {
140 struct acpi_thermal_state_flags flags;
141 unsigned long temperature;
142 struct acpi_handle_list devices;
143};
144
145struct acpi_thermal_trips {
146 struct acpi_thermal_critical critical;
147 struct acpi_thermal_hot hot;
148 struct acpi_thermal_passive passive;
149 struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
150};
151
152struct acpi_thermal_flags {
153 u8 cooling_mode:1; /* _SCP */
154 u8 devices:1; /* _TZD */
155 u8 reserved:6;
156};
157
158struct acpi_thermal {
159 acpi_handle handle;
160 acpi_bus_id name;
161 unsigned long temperature;
162 unsigned long last_temperature;
163 unsigned long polling_frequency;
164 u8 cooling_mode;
165 volatile u8 zombie;
166 struct acpi_thermal_flags flags;
167 struct acpi_thermal_state state;
168 struct acpi_thermal_trips trips;
169 struct acpi_handle_list devices;
170 struct timer_list timer;
171};
172
173static struct file_operations acpi_thermal_state_fops = {
174 .open = acpi_thermal_state_open_fs,
175 .read = seq_read,
176 .llseek = seq_lseek,
177 .release = single_release,
178};
179
180static struct file_operations acpi_thermal_temp_fops = {
181 .open = acpi_thermal_temp_open_fs,
182 .read = seq_read,
183 .llseek = seq_lseek,
184 .release = single_release,
185};
186
187static struct file_operations acpi_thermal_trip_fops = {
188 .open = acpi_thermal_trip_open_fs,
189 .read = seq_read,
190 .write = acpi_thermal_write_trip_points,
191 .llseek = seq_lseek,
192 .release = single_release,
193};
194
195static struct file_operations acpi_thermal_cooling_fops = {
196 .open = acpi_thermal_cooling_open_fs,
197 .read = seq_read,
198 .write = acpi_thermal_write_cooling_mode,
199 .llseek = seq_lseek,
200 .release = single_release,
201};
202
203static struct file_operations acpi_thermal_polling_fops = {
204 .open = acpi_thermal_polling_open_fs,
205 .read = seq_read,
206 .write = acpi_thermal_write_polling,
207 .llseek = seq_lseek,
208 .release = single_release,
209};
210
211/* --------------------------------------------------------------------------
212 Thermal Zone Management
213 -------------------------------------------------------------------------- */
214
215static int
216acpi_thermal_get_temperature (
217 struct acpi_thermal *tz)
218{
219 acpi_status status = AE_OK;
220
221 ACPI_FUNCTION_TRACE("acpi_thermal_get_temperature");
222
223 if (!tz)
224 return_VALUE(-EINVAL);
225
226 tz->last_temperature = tz->temperature;
227
228 status = acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature);
229 if (ACPI_FAILURE(status))
230 return_VALUE(-ENODEV);
231
232 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", tz->temperature));
233
234 return_VALUE(0);
235}
236
237
238static int
239acpi_thermal_get_polling_frequency (
240 struct acpi_thermal *tz)
241{
242 acpi_status status = AE_OK;
243
244 ACPI_FUNCTION_TRACE("acpi_thermal_get_polling_frequency");
245
246 if (!tz)
247 return_VALUE(-EINVAL);
248
249 status = acpi_evaluate_integer(tz->handle, "_TZP", NULL, &tz->polling_frequency);
250 if (ACPI_FAILURE(status))
251 return_VALUE(-ENODEV);
252
253 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n", tz->polling_frequency));
254
255 return_VALUE(0);
256}
257
258
259static int
260acpi_thermal_set_polling (
261 struct acpi_thermal *tz,
262 int seconds)
263{
264 ACPI_FUNCTION_TRACE("acpi_thermal_set_polling");
265
266 if (!tz)
267 return_VALUE(-EINVAL);
268
269 tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */
270
271 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency set to %lu seconds\n", tz->polling_frequency));
272
273 return_VALUE(0);
274}
275
276
277static int
278acpi_thermal_set_cooling_mode (
279 struct acpi_thermal *tz,
280 int mode)
281{
282 acpi_status status = AE_OK;
283 union acpi_object arg0 = {ACPI_TYPE_INTEGER};
284 struct acpi_object_list arg_list = {1, &arg0};
285 acpi_handle handle = NULL;
286
287 ACPI_FUNCTION_TRACE("acpi_thermal_set_cooling_mode");
288
289 if (!tz)
290 return_VALUE(-EINVAL);
291
292 status = acpi_get_handle(tz->handle, "_SCP", &handle);
293 if (ACPI_FAILURE(status)) {
294 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
295 return_VALUE(-ENODEV);
296 }
297
298 arg0.integer.value = mode;
299
300 status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
301 if (ACPI_FAILURE(status))
302 return_VALUE(-ENODEV);
303
304 tz->cooling_mode = mode;
305
306 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n",
307 mode?"passive":"active"));
308
309 return_VALUE(0);
310}
311
312
313static int
314acpi_thermal_get_trip_points (
315 struct acpi_thermal *tz)
316{
317 acpi_status status = AE_OK;
318 int i = 0;
319
320 ACPI_FUNCTION_TRACE("acpi_thermal_get_trip_points");
321
322 if (!tz)
323 return_VALUE(-EINVAL);
324
325 /* Critical Shutdown (required) */
326
327 status = acpi_evaluate_integer(tz->handle, "_CRT", NULL,
328 &tz->trips.critical.temperature);
329 if (ACPI_FAILURE(status)) {
330 tz->trips.critical.flags.valid = 0;
331 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n"));
332 return_VALUE(-ENODEV);
333 }
334 else {
335 tz->trips.critical.flags.valid = 1;
336 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found critical threshold [%lu]\n", tz->trips.critical.temperature));
337 }
338
339 /* Critical Sleep (optional) */
340
341 status = acpi_evaluate_integer(tz->handle, "_HOT", NULL, &tz->trips.hot.temperature);
342 if (ACPI_FAILURE(status)) {
343 tz->trips.hot.flags.valid = 0;
344 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n"));
345 }
346 else {
347 tz->trips.hot.flags.valid = 1;
348 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n", tz->trips.hot.temperature));
349 }
350
351 /* Passive: Processors (optional) */
352
353 status = acpi_evaluate_integer(tz->handle, "_PSV", NULL, &tz->trips.passive.temperature);
354 if (ACPI_FAILURE(status)) {
355 tz->trips.passive.flags.valid = 0;
356 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n"));
357 }
358 else {
359 tz->trips.passive.flags.valid = 1;
360
361 status = acpi_evaluate_integer(tz->handle, "_TC1", NULL, &tz->trips.passive.tc1);
362 if (ACPI_FAILURE(status))
363 tz->trips.passive.flags.valid = 0;
364
365 status = acpi_evaluate_integer(tz->handle, "_TC2", NULL, &tz->trips.passive.tc2);
366 if (ACPI_FAILURE(status))
367 tz->trips.passive.flags.valid = 0;
368
369 status = acpi_evaluate_integer(tz->handle, "_TSP", NULL, &tz->trips.passive.tsp);
370 if (ACPI_FAILURE(status))
371 tz->trips.passive.flags.valid = 0;
372
373 status = acpi_evaluate_reference(tz->handle, "_PSL", NULL, &tz->trips.passive.devices);
374 if (ACPI_FAILURE(status))
375 tz->trips.passive.flags.valid = 0;
376
377 if (!tz->trips.passive.flags.valid)
378 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid passive threshold\n"));
379 else
380 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found passive threshold [%lu]\n", tz->trips.passive.temperature));
381 }
382
383 /* Active: Fans, etc. (optional) */
384
385 for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
386
387 char name[5] = {'_','A','C',('0'+i),'\0'};
388
389 status = acpi_evaluate_integer(tz->handle, name, NULL, &tz->trips.active[i].temperature);
390 if (ACPI_FAILURE(status))
391 break;
392
393 name[2] = 'L';
394 status = acpi_evaluate_reference(tz->handle, name, NULL, &tz->trips.active[i].devices);
395 if (ACPI_SUCCESS(status)) {
396 tz->trips.active[i].flags.valid = 1;
397 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found active threshold [%d]:[%lu]\n", i, tz->trips.active[i].temperature));
398 }
399 else
400 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid active threshold [%d]\n", i));
401 }
402
403 return_VALUE(0);
404}
405
406
407static int
408acpi_thermal_get_devices (
409 struct acpi_thermal *tz)
410{
411 acpi_status status = AE_OK;
412
413 ACPI_FUNCTION_TRACE("acpi_thermal_get_devices");
414
415 if (!tz)
416 return_VALUE(-EINVAL);
417
418 status = acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices);
419 if (ACPI_FAILURE(status))
420 return_VALUE(-ENODEV);
421
422 return_VALUE(0);
423}
424
425
426static int
427acpi_thermal_call_usermode (
428 char *path)
429{
430 char *argv[2] = {NULL, NULL};
431 char *envp[3] = {NULL, NULL, NULL};
432
433 ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode");
434
435 if (!path)
436 return_VALUE(-EINVAL);
437
438 argv[0] = path;
439
440 /* minimal command environment */
441 envp[0] = "HOME=/";
442 envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
443
444 call_usermodehelper(argv[0], argv, envp, 0);
445
446 return_VALUE(0);
447}
448
449
450static int
451acpi_thermal_critical (
452 struct acpi_thermal *tz)
453{
454 int result = 0;
455 struct acpi_device *device = NULL;
456
457 ACPI_FUNCTION_TRACE("acpi_thermal_critical");
458
459 if (!tz || !tz->trips.critical.flags.valid)
460 return_VALUE(-EINVAL);
461
462 if (tz->temperature >= tz->trips.critical.temperature) {
463 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Critical trip point\n"));
464 tz->trips.critical.flags.enabled = 1;
465 }
466 else if (tz->trips.critical.flags.enabled)
467 tz->trips.critical.flags.enabled = 0;
468
469 result = acpi_bus_get_device(tz->handle, &device);
470 if (result)
471 return_VALUE(result);
472
473 printk(KERN_EMERG "Critical temperature reached (%ld C), shutting down.\n", KELVIN_TO_CELSIUS(tz->temperature));
474 acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled);
475
476 acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF);
477
478 return_VALUE(0);
479}
480
481
482static int
483acpi_thermal_hot (
484 struct acpi_thermal *tz)
485{
486 int result = 0;
487 struct acpi_device *device = NULL;
488
489 ACPI_FUNCTION_TRACE("acpi_thermal_hot");
490
491 if (!tz || !tz->trips.hot.flags.valid)
492 return_VALUE(-EINVAL);
493
494 if (tz->temperature >= tz->trips.hot.temperature) {
495 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Hot trip point\n"));
496 tz->trips.hot.flags.enabled = 1;
497 }
498 else if (tz->trips.hot.flags.enabled)
499 tz->trips.hot.flags.enabled = 0;
500
501 result = acpi_bus_get_device(tz->handle, &device);
502 if (result)
503 return_VALUE(result);
504
505 acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled);
506
507 /* TBD: Call user-mode "sleep(S4)" function */
508
509 return_VALUE(0);
510}
511
512
513static int
514acpi_thermal_passive (
515 struct acpi_thermal *tz)
516{
517 int result = 0;
518 struct acpi_thermal_passive *passive = NULL;
519 int trend = 0;
520 int i = 0;
521
522 ACPI_FUNCTION_TRACE("acpi_thermal_passive");
523
524 if (!tz || !tz->trips.passive.flags.valid)
525 return_VALUE(-EINVAL);
526
527 passive = &(tz->trips.passive);
528
529 /*
530 * Above Trip?
531 * -----------
532 * Calculate the thermal trend (using the passive cooling equation)
533 * and modify the performance limit for all passive cooling devices
534 * accordingly. Note that we assume symmetry.
535 */
536 if (tz->temperature >= passive->temperature) {
537 trend = (passive->tc1 * (tz->temperature - tz->last_temperature)) + (passive->tc2 * (tz->temperature - passive->temperature));
538 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
539 "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n",
540 trend, passive->tc1, tz->temperature,
541 tz->last_temperature, passive->tc2,
542 tz->temperature, passive->temperature));
543 tz->trips.passive.flags.enabled = 1;
544 /* Heating up? */
545 if (trend > 0)
546 for (i=0; i<passive->devices.count; i++)
547 acpi_processor_set_thermal_limit(
548 passive->devices.handles[i],
549 ACPI_PROCESSOR_LIMIT_INCREMENT);
550 /* Cooling off? */
551 else if (trend < 0)
552 for (i=0; i<passive->devices.count; i++)
553 acpi_processor_set_thermal_limit(
554 passive->devices.handles[i],
555 ACPI_PROCESSOR_LIMIT_DECREMENT);
556 }
557
558 /*
559 * Below Trip?
560 * -----------
561 * Implement passive cooling hysteresis to slowly increase performance
562 * and avoid thrashing around the passive trip point. Note that we
563 * assume symmetry.
564 */
565 else if (tz->trips.passive.flags.enabled) {
566 for (i=0; i<passive->devices.count; i++)
567 result = acpi_processor_set_thermal_limit(
568 passive->devices.handles[i],
569 ACPI_PROCESSOR_LIMIT_DECREMENT);
570 if (result == 1) {
571 tz->trips.passive.flags.enabled = 0;
572 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
573 "Disabling passive cooling (zone is cool)\n"));
574 }
575 }
576
577 return_VALUE(0);
578}
579
580
581static int
582acpi_thermal_active (
583 struct acpi_thermal *tz)
584{
585 int result = 0;
586 struct acpi_thermal_active *active = NULL;
587 int i = 0;
588 int j = 0;
589 unsigned long maxtemp = 0;
590
591 ACPI_FUNCTION_TRACE("acpi_thermal_active");
592
593 if (!tz)
594 return_VALUE(-EINVAL);
595
596 for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
597
598 active = &(tz->trips.active[i]);
599 if (!active || !active->flags.valid)
600 break;
601
602 /*
603 * Above Threshold?
604 * ----------------
605 * If not already enabled, turn ON all cooling devices
606 * associated with this active threshold.
607 */
608 if (tz->temperature >= active->temperature) {
609 if (active->temperature > maxtemp)
610 tz->state.active_index = i, maxtemp = active->temperature;
611 if (!active->flags.enabled) {
612 for (j = 0; j < active->devices.count; j++) {
613 result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D0);
614 if (result) {
615 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'on'\n", active->devices.handles[j]));
616 continue;
617 }
618 active->flags.enabled = 1;
619 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'on'\n", active->devices.handles[j]));
620 }
621 }
622 }
623 /*
624 * Below Threshold?
625 * ----------------
626 * Turn OFF all cooling devices associated with this
627 * threshold.
628 */
629 else if (active->flags.enabled) {
630 for (j = 0; j < active->devices.count; j++) {
631 result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D3);
632 if (result) {
633 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'off'\n", active->devices.handles[j]));
634 continue;
635 }
636 active->flags.enabled = 0;
637 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'off'\n", active->devices.handles[j]));
638 }
639 }
640 }
641
642 return_VALUE(0);
643}
644
645
646static void acpi_thermal_check (void *context);
647
648static void
649acpi_thermal_run (
650 unsigned long data)
651{
652 struct acpi_thermal *tz = (struct acpi_thermal *)data;
653 if (!tz->zombie)
654 acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
655 acpi_thermal_check, (void *) data);
656}
657
658
659static void
660acpi_thermal_check (
661 void *data)
662{
663 int result = 0;
664 struct acpi_thermal *tz = (struct acpi_thermal *) data;
665 unsigned long sleep_time = 0;
666 int i = 0;
667 struct acpi_thermal_state state;
668
669 ACPI_FUNCTION_TRACE("acpi_thermal_check");
670
671 if (!tz) {
672 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
673 return_VOID;
674 }
675
676 state = tz->state;
677
678 result = acpi_thermal_get_temperature(tz);
679 if (result)
680 return_VOID;
681
682 memset(&tz->state, 0, sizeof(tz->state));
683
684 /*
685 * Check Trip Points
686 * -----------------
687 * Compare the current temperature to the trip point values to see
688 * if we've entered one of the thermal policy states. Note that
689 * this function determines when a state is entered, but the
690 * individual policy decides when it is exited (e.g. hysteresis).
691 */
692 if (tz->trips.critical.flags.valid)
693 state.critical |= (tz->temperature >= tz->trips.critical.temperature);
694 if (tz->trips.hot.flags.valid)
695 state.hot |= (tz->temperature >= tz->trips.hot.temperature);
696 if (tz->trips.passive.flags.valid)
697 state.passive |= (tz->temperature >= tz->trips.passive.temperature);
698 for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++)
699 if (tz->trips.active[i].flags.valid)
700 state.active |= (tz->temperature >= tz->trips.active[i].temperature);
701
702 /*
703 * Invoke Policy
704 * -------------
705 * Separated from the above check to allow individual policy to
706 * determine when to exit a given state.
707 */
708 if (state.critical)
709 acpi_thermal_critical(tz);
710 if (state.hot)
711 acpi_thermal_hot(tz);
712 if (state.passive)
713 acpi_thermal_passive(tz);
714 if (state.active)
715 acpi_thermal_active(tz);
716
717 /*
718 * Calculate State
719 * ---------------
720 * Again, separated from the above two to allow independent policy
721 * decisions.
722 */
723 if (tz->trips.critical.flags.enabled)
724 tz->state.critical = 1;
725 if (tz->trips.hot.flags.enabled)
726 tz->state.hot = 1;
727 if (tz->trips.passive.flags.enabled)
728 tz->state.passive = 1;
729 for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++)
730 if (tz->trips.active[i].flags.enabled)
731 tz->state.active = 1;
732
733 /*
734 * Calculate Sleep Time
735 * --------------------
736 * If we're in the passive state, use _TSP's value. Otherwise
737 * use the default polling frequency (e.g. _TZP). If no polling
738 * frequency is specified then we'll wait forever (at least until
739 * a thermal event occurs). Note that _TSP and _TZD values are
740 * given in 1/10th seconds (we must covert to milliseconds).
741 */
742 if (tz->state.passive)
743 sleep_time = tz->trips.passive.tsp * 100;
744 else if (tz->polling_frequency > 0)
745 sleep_time = tz->polling_frequency * 100;
746
747 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n",
748 tz->name, tz->temperature, sleep_time));
749
750 /*
751 * Schedule Next Poll
752 * ------------------
753 */
754 if (!sleep_time) {
755 if (timer_pending(&(tz->timer)))
756 del_timer(&(tz->timer));
757 }
758 else {
759 if (timer_pending(&(tz->timer)))
760 mod_timer(&(tz->timer), (HZ * sleep_time) / 1000);
761 else {
762 tz->timer.data = (unsigned long) tz;
763 tz->timer.function = acpi_thermal_run;
764 tz->timer.expires = jiffies + (HZ * sleep_time) / 1000;
765 add_timer(&(tz->timer));
766 }
767 }
768
769 return_VOID;
770}
771
772
773/* --------------------------------------------------------------------------
774 FS Interface (/proc)
775 -------------------------------------------------------------------------- */
776
777static struct proc_dir_entry *acpi_thermal_dir;
778
779static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
780{
781 struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
782
783 ACPI_FUNCTION_TRACE("acpi_thermal_state_seq_show");
784
785 if (!tz)
786 goto end;
787
788 seq_puts(seq, "state: ");
789
790 if (!tz->state.critical && !tz->state.hot && !tz->state.passive && !tz->state.active)
791 seq_puts(seq, "ok\n");
792 else {
793 if (tz->state.critical)
794 seq_puts(seq, "critical ");
795 if (tz->state.hot)
796 seq_puts(seq, "hot ");
797 if (tz->state.passive)
798 seq_puts(seq, "passive ");
799 if (tz->state.active)
800 seq_printf(seq, "active[%d]", tz->state.active_index);
801 seq_puts(seq, "\n");
802 }
803
804end:
805 return_VALUE(0);
806}
807
808static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
809{
810 return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data);
811}
812
813
814static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
815{
816 int result = 0;
817 struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
818
819 ACPI_FUNCTION_TRACE("acpi_thermal_temp_seq_show");
820
821 if (!tz)
822 goto end;
823
824 result = acpi_thermal_get_temperature(tz);
825 if (result)
826 goto end;
827
828 seq_printf(seq, "temperature: %ld C\n",
829 KELVIN_TO_CELSIUS(tz->temperature));
830
831end:
832 return_VALUE(0);
833}
834
835static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
836{
837 return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data);
838}
839
840
841static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
842{
843 struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
844 int i = 0;
845 int j = 0;
846
847 ACPI_FUNCTION_TRACE("acpi_thermal_trip_seq_show");
848
849 if (!tz)
850 goto end;
851
852 if (tz->trips.critical.flags.valid)
853 seq_printf(seq, "critical (S5): %ld C\n",
854 KELVIN_TO_CELSIUS(tz->trips.critical.temperature));
855
856 if (tz->trips.hot.flags.valid)
857 seq_printf(seq, "hot (S4): %ld C\n",
858 KELVIN_TO_CELSIUS(tz->trips.hot.temperature));
859
860 if (tz->trips.passive.flags.valid) {
861 seq_printf(seq, "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
862 KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
863 tz->trips.passive.tc1,
864 tz->trips.passive.tc2,
865 tz->trips.passive.tsp);
866 for (j=0; j<tz->trips.passive.devices.count; j++) {
867
868 seq_printf(seq, "0x%p ", tz->trips.passive.devices.handles[j]);
869 }
870 seq_puts(seq, "\n");
871 }
872
873 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
874 if (!(tz->trips.active[i].flags.valid))
875 break;
876 seq_printf(seq, "active[%d]: %ld C: devices=",
877 i, KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
878 for (j = 0; j < tz->trips.active[i].devices.count; j++)
879 seq_printf(seq, "0x%p ",
880 tz->trips.active[i].devices.handles[j]);
881 seq_puts(seq, "\n");
882 }
883
884end:
885 return_VALUE(0);
886}
887
888static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file)
889{
890 return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data);
891}
892
893static ssize_t
894acpi_thermal_write_trip_points (
895 struct file *file,
896 const char __user *buffer,
897 size_t count,
898 loff_t *ppos)
899{
900 struct seq_file *m = (struct seq_file *)file->private_data;
901 struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
902
903 char *limit_string;
904 int num, critical, hot, passive;
905 int *active;
906 int i = 0;
907
908 ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points");
909
910 limit_string = kmalloc(ACPI_THERMAL_MAX_LIMIT_STR_LEN, GFP_KERNEL);
911 if(!limit_string)
912 return_VALUE(-ENOMEM);
913
914 memset(limit_string, 0, ACPI_THERMAL_MAX_LIMIT_STR_LEN);
915
916 active = kmalloc(ACPI_THERMAL_MAX_ACTIVE *sizeof(int), GFP_KERNEL);
917 if(!active)
918 return_VALUE(-ENOMEM);
919
920 if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) {
921 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n"));
922 count = -EINVAL;
923 goto end;
924 }
925
926 if (copy_from_user(limit_string, buffer, count)) {
927 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
928 count = -EFAULT;
929 goto end;
930 }
931
932 limit_string[count] = '\0';
933
934 num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
935 &critical, &hot, &passive,
936 &active[0], &active[1], &active[2], &active[3], &active[4],
937 &active[5], &active[6], &active[7], &active[8], &active[9]);
938 if(!(num >=5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) {
939 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
940 count = -EINVAL;
941 goto end;
942 }
943
944 tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical);
945 tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot);
946 tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive);
947 for (i = 0; i < num - 3; i++) {
948 if (!(tz->trips.active[i].flags.valid))
949 break;
950 tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]);
951 }
952
953end:
954 kfree(active);
955 kfree(limit_string);
956 return_VALUE(count);
957}
958
959
960static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
961{
962 struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
963
964 ACPI_FUNCTION_TRACE("acpi_thermal_cooling_seq_show");
965
966 if (!tz)
967 goto end;
968
969 if (!tz->flags.cooling_mode) {
970 seq_puts(seq, "<setting not supported>\n");
971 }
972
973 if ( tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL )
974 seq_printf(seq, "cooling mode: critical\n");
975 else
976 seq_printf(seq, "cooling mode: %s\n",
977 tz->cooling_mode?"passive":"active");
978
979end:
980 return_VALUE(0);
981}
982
983static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file)
984{
985 return single_open(file, acpi_thermal_cooling_seq_show,
986 PDE(inode)->data);
987}
988
989static ssize_t
990acpi_thermal_write_cooling_mode (
991 struct file *file,
992 const char __user *buffer,
993 size_t count,
994 loff_t *ppos)
995{
996 struct seq_file *m = (struct seq_file *)file->private_data;
997 struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
998 int result = 0;
999 char mode_string[12] = {'\0'};
1000
1001 ACPI_FUNCTION_TRACE("acpi_thermal_write_cooling_mode");
1002
1003 if (!tz || (count > sizeof(mode_string) - 1))
1004 return_VALUE(-EINVAL);
1005
1006 if (!tz->flags.cooling_mode)
1007 return_VALUE(-ENODEV);
1008
1009 if (copy_from_user(mode_string, buffer, count))
1010 return_VALUE(-EFAULT);
1011
1012 mode_string[count] = '\0';
1013
1014 result = acpi_thermal_set_cooling_mode(tz,
1015 simple_strtoul(mode_string, NULL, 0));
1016 if (result)
1017 return_VALUE(result);
1018
1019 acpi_thermal_check(tz);
1020
1021 return_VALUE(count);
1022}
1023
1024
1025static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
1026{
1027 struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
1028
1029 ACPI_FUNCTION_TRACE("acpi_thermal_polling_seq_show");
1030
1031 if (!tz)
1032 goto end;
1033
1034 if (!tz->polling_frequency) {
1035 seq_puts(seq, "<polling disabled>\n");
1036 goto end;
1037 }
1038
1039 seq_printf(seq, "polling frequency: %lu seconds\n",
1040 (tz->polling_frequency / 10));
1041
1042end:
1043 return_VALUE(0);
1044}
1045
1046static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file)
1047{
1048 return single_open(file, acpi_thermal_polling_seq_show,
1049 PDE(inode)->data);
1050}
1051
1052static ssize_t
1053acpi_thermal_write_polling (
1054 struct file *file,
1055 const char __user *buffer,
1056 size_t count,
1057 loff_t *ppos)
1058{
1059 struct seq_file *m = (struct seq_file *)file->private_data;
1060 struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
1061 int result = 0;
1062 char polling_string[12] = {'\0'};
1063 int seconds = 0;
1064
1065 ACPI_FUNCTION_TRACE("acpi_thermal_write_polling");
1066
1067 if (!tz || (count > sizeof(polling_string) - 1))
1068 return_VALUE(-EINVAL);
1069
1070 if (copy_from_user(polling_string, buffer, count))
1071 return_VALUE(-EFAULT);
1072
1073 polling_string[count] = '\0';
1074
1075 seconds = simple_strtoul(polling_string, NULL, 0);
1076
1077 result = acpi_thermal_set_polling(tz, seconds);
1078 if (result)
1079 return_VALUE(result);
1080
1081 acpi_thermal_check(tz);
1082
1083 return_VALUE(count);
1084}
1085
1086
1087static int
1088acpi_thermal_add_fs (
1089 struct acpi_device *device)
1090{
1091 struct proc_dir_entry *entry = NULL;
1092
1093 ACPI_FUNCTION_TRACE("acpi_thermal_add_fs");
1094
1095 if (!acpi_device_dir(device)) {
1096 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1097 acpi_thermal_dir);
1098 if (!acpi_device_dir(device))
1099 return_VALUE(-ENODEV);
1100 acpi_device_dir(device)->owner = THIS_MODULE;
1101 }
1102
1103 /* 'state' [R] */
1104 entry = create_proc_entry(ACPI_THERMAL_FILE_STATE,
1105 S_IRUGO, acpi_device_dir(device));
1106 if (!entry)
1107 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1108 "Unable to create '%s' fs entry\n",
1109 ACPI_THERMAL_FILE_STATE));
1110 else {
1111 entry->proc_fops = &acpi_thermal_state_fops;
1112 entry->data = acpi_driver_data(device);
1113 entry->owner = THIS_MODULE;
1114 }
1115
1116 /* 'temperature' [R] */
1117 entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
1118 S_IRUGO, acpi_device_dir(device));
1119 if (!entry)
1120 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1121 "Unable to create '%s' fs entry\n",
1122 ACPI_THERMAL_FILE_TEMPERATURE));
1123 else {
1124 entry->proc_fops = &acpi_thermal_temp_fops;
1125 entry->data = acpi_driver_data(device);
1126 entry->owner = THIS_MODULE;
1127 }
1128
1129 /* 'trip_points' [R/W] */
1130 entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
1131 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
1132 if (!entry)
1133 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1134 "Unable to create '%s' fs entry\n",
1135 ACPI_THERMAL_FILE_TRIP_POINTS));
1136 else {
1137 entry->proc_fops = &acpi_thermal_trip_fops;
1138 entry->data = acpi_driver_data(device);
1139 entry->owner = THIS_MODULE;
1140 }
1141
1142 /* 'cooling_mode' [R/W] */
1143 entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
1144 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
1145 if (!entry)
1146 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1147 "Unable to create '%s' fs entry\n",
1148 ACPI_THERMAL_FILE_COOLING_MODE));
1149 else {
1150 entry->proc_fops = &acpi_thermal_cooling_fops;
1151 entry->data = acpi_driver_data(device);
1152 entry->owner = THIS_MODULE;
1153 }
1154
1155 /* 'polling_frequency' [R/W] */
1156 entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
1157 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
1158 if (!entry)
1159 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1160 "Unable to create '%s' fs entry\n",
1161 ACPI_THERMAL_FILE_POLLING_FREQ));
1162 else {
1163 entry->proc_fops = &acpi_thermal_polling_fops;
1164 entry->data = acpi_driver_data(device);
1165 entry->owner = THIS_MODULE;
1166 }
1167
1168 return_VALUE(0);
1169}
1170
1171
1172static int
1173acpi_thermal_remove_fs (
1174 struct acpi_device *device)
1175{
1176 ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs");
1177
1178 if (acpi_device_dir(device)) {
1179 remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
1180 acpi_device_dir(device));
1181 remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
1182 acpi_device_dir(device));
1183 remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
1184 acpi_device_dir(device));
1185 remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
1186 acpi_device_dir(device));
1187 remove_proc_entry(ACPI_THERMAL_FILE_STATE,
1188 acpi_device_dir(device));
1189 remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir);
1190 acpi_device_dir(device) = NULL;
1191 }
1192
1193 return_VALUE(0);
1194}
1195
1196
1197/* --------------------------------------------------------------------------
1198 Driver Interface
1199 -------------------------------------------------------------------------- */
1200
1201static void
1202acpi_thermal_notify (
1203 acpi_handle handle,
1204 u32 event,
1205 void *data)
1206{
1207 struct acpi_thermal *tz = (struct acpi_thermal *) data;
1208 struct acpi_device *device = NULL;
1209
1210 ACPI_FUNCTION_TRACE("acpi_thermal_notify");
1211
1212 if (!tz)
1213 return_VOID;
1214
1215 if (acpi_bus_get_device(tz->handle, &device))
1216 return_VOID;
1217
1218 switch (event) {
1219 case ACPI_THERMAL_NOTIFY_TEMPERATURE:
1220 acpi_thermal_check(tz);
1221 break;
1222 case ACPI_THERMAL_NOTIFY_THRESHOLDS:
1223 acpi_thermal_get_trip_points(tz);
1224 acpi_thermal_check(tz);
1225 acpi_bus_generate_event(device, event, 0);
1226 break;
1227 case ACPI_THERMAL_NOTIFY_DEVICES:
1228 if (tz->flags.devices)
1229 acpi_thermal_get_devices(tz);
1230 acpi_bus_generate_event(device, event, 0);
1231 break;
1232 default:
1233 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1234 "Unsupported event [0x%x]\n", event));
1235 break;
1236 }
1237
1238 return_VOID;
1239}
1240
1241
1242static int
1243acpi_thermal_get_info (
1244 struct acpi_thermal *tz)
1245{
1246 int result = 0;
1247
1248 ACPI_FUNCTION_TRACE("acpi_thermal_get_info");
1249
1250 if (!tz)
1251 return_VALUE(-EINVAL);
1252
1253 /* Get temperature [_TMP] (required) */
1254 result = acpi_thermal_get_temperature(tz);
1255 if (result)
1256 return_VALUE(result);
1257
1258 /* Get trip points [_CRT, _PSV, etc.] (required) */
1259 result = acpi_thermal_get_trip_points(tz);
1260 if (result)
1261 return_VALUE(result);
1262
1263 /* Set the cooling mode [_SCP] to active cooling (default) */
1264 result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
1265 if (!result)
1266 tz->flags.cooling_mode = 1;
1267 else {
1268 /* Oh,we have not _SCP method.
1269 Generally show cooling_mode by _ACx, _PSV,spec 12.2*/
1270 tz->flags.cooling_mode = 0;
1271 if ( tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
1272 if ( tz->trips.passive.temperature > tz->trips.active[0].temperature )
1273 tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
1274 else
1275 tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
1276 } else if ( !tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
1277 tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
1278 } else if ( tz->trips.active[0].flags.valid && !tz->trips.passive.flags.valid ) {
1279 tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
1280 } else {
1281 /* _ACx and _PSV are optional, but _CRT is required */
1282 tz->cooling_mode = ACPI_THERMAL_MODE_CRITICAL;
1283 }
1284 }
1285
1286 /* Get default polling frequency [_TZP] (optional) */
1287 if (tzp)
1288 tz->polling_frequency = tzp;
1289 else
1290 acpi_thermal_get_polling_frequency(tz);
1291
1292 /* Get devices in this thermal zone [_TZD] (optional) */
1293 result = acpi_thermal_get_devices(tz);
1294 if (!result)
1295 tz->flags.devices = 1;
1296
1297 return_VALUE(0);
1298}
1299
1300
1301static int
1302acpi_thermal_add (
1303 struct acpi_device *device)
1304{
1305 int result = 0;
1306 acpi_status status = AE_OK;
1307 struct acpi_thermal *tz = NULL;
1308
1309 ACPI_FUNCTION_TRACE("acpi_thermal_add");
1310
1311 if (!device)
1312 return_VALUE(-EINVAL);
1313
1314 tz = kmalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
1315 if (!tz)
1316 return_VALUE(-ENOMEM);
1317 memset(tz, 0, sizeof(struct acpi_thermal));
1318
1319 tz->handle = device->handle;
1320 strcpy(tz->name, device->pnp.bus_id);
1321 strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
1322 strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
1323 acpi_driver_data(device) = tz;
1324
1325 result = acpi_thermal_get_info(tz);
1326 if (result)
1327 goto end;
1328
1329 result = acpi_thermal_add_fs(device);
1330 if (result)
1331 return_VALUE(result);
1332
1333 init_timer(&tz->timer);
1334
1335 acpi_thermal_check(tz);
1336
1337 status = acpi_install_notify_handler(tz->handle,
1338 ACPI_DEVICE_NOTIFY, acpi_thermal_notify, tz);
1339 if (ACPI_FAILURE(status)) {
1340 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1341 "Error installing notify handler\n"));
1342 result = -ENODEV;
1343 goto end;
1344 }
1345
1346 printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
1347 acpi_device_name(device), acpi_device_bid(device),
1348 KELVIN_TO_CELSIUS(tz->temperature));
1349
1350end:
1351 if (result) {
1352 acpi_thermal_remove_fs(device);
1353 kfree(tz);
1354 }
1355
1356 return_VALUE(result);
1357}
1358
1359
1360static int
1361acpi_thermal_remove (
1362 struct acpi_device *device,
1363 int type)
1364{
1365 acpi_status status = AE_OK;
1366 struct acpi_thermal *tz = NULL;
1367
1368 ACPI_FUNCTION_TRACE("acpi_thermal_remove");
1369
1370 if (!device || !acpi_driver_data(device))
1371 return_VALUE(-EINVAL);
1372
1373 tz = (struct acpi_thermal *) acpi_driver_data(device);
1374
1375 /* avoid timer adding new defer task */
1376 tz->zombie = 1;
1377 /* wait for running timer (on other CPUs) finish */
1378 del_timer_sync(&(tz->timer));
1379 /* synchronize deferred task */
1380 acpi_os_wait_events_complete(NULL);
1381 /* deferred task may reinsert timer */
1382 del_timer_sync(&(tz->timer));
1383
1384 status = acpi_remove_notify_handler(tz->handle,
1385 ACPI_DEVICE_NOTIFY, acpi_thermal_notify);
1386 if (ACPI_FAILURE(status))
1387 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1388 "Error removing notify handler\n"));
1389
1390 /* Terminate policy */
1391 if (tz->trips.passive.flags.valid
1392 && tz->trips.passive.flags.enabled) {
1393 tz->trips.passive.flags.enabled = 0;
1394 acpi_thermal_passive(tz);
1395 }
1396 if (tz->trips.active[0].flags.valid
1397 && tz->trips.active[0].flags.enabled) {
1398 tz->trips.active[0].flags.enabled = 0;
1399 acpi_thermal_active(tz);
1400 }
1401
1402 acpi_thermal_remove_fs(device);
1403
1404 kfree(tz);
1405 return_VALUE(0);
1406}
1407
1408
1409static int __init
1410acpi_thermal_init (void)
1411{
1412 int result = 0;
1413
1414 ACPI_FUNCTION_TRACE("acpi_thermal_init");
1415
1416 acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
1417 if (!acpi_thermal_dir)
1418 return_VALUE(-ENODEV);
1419 acpi_thermal_dir->owner = THIS_MODULE;
1420
1421 result = acpi_bus_register_driver(&acpi_thermal_driver);
1422 if (result < 0) {
1423 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
1424 return_VALUE(-ENODEV);
1425 }
1426
1427 return_VALUE(0);
1428}
1429
1430
1431static void __exit
1432acpi_thermal_exit (void)
1433{
1434 ACPI_FUNCTION_TRACE("acpi_thermal_exit");
1435
1436 acpi_bus_unregister_driver(&acpi_thermal_driver);
1437
1438 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
1439
1440 return_VOID;
1441}
1442
1443
1444module_init(acpi_thermal_init);
1445module_exit(acpi_thermal_exit);
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
new file mode 100644
index 000000000000..c84997c9f964
--- /dev/null
+++ b/drivers/acpi/toshiba_acpi.c
@@ -0,0 +1,575 @@
1/*
2 * toshiba_acpi.c - Toshiba Laptop ACPI Extras
3 *
4 *
5 * Copyright (C) 2002-2004 John Belmonte
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 *
22 * The devolpment page for this driver is located at
23 * http://memebeam.org/toys/ToshibaAcpiDriver.
24 *
25 * Credits:
26 * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse
27 * engineering the Windows drivers
28 * Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
29 * Rob Miller - TV out and hotkeys help
30 *
31 *
32 * TODO
33 *
34 */
35
36#define TOSHIBA_ACPI_VERSION "0.18"
37#define PROC_INTERFACE_VERSION 1
38
39#include <linux/kernel.h>
40#include <linux/module.h>
41#include <linux/init.h>
42#include <linux/types.h>
43#include <linux/proc_fs.h>
44#include <asm/uaccess.h>
45
46#include <acpi/acpi_drivers.h>
47
48MODULE_AUTHOR("John Belmonte");
49MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
50MODULE_LICENSE("GPL");
51
52#define MY_LOGPREFIX "toshiba_acpi: "
53#define MY_ERR KERN_ERR MY_LOGPREFIX
54#define MY_NOTICE KERN_NOTICE MY_LOGPREFIX
55#define MY_INFO KERN_INFO MY_LOGPREFIX
56
57/* Toshiba ACPI method paths */
58#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
59#define METHOD_HCI_1 "\\_SB_.VALD.GHCI"
60#define METHOD_HCI_2 "\\_SB_.VALZ.GHCI"
61#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
62
63/* Toshiba HCI interface definitions
64 *
65 * HCI is Toshiba's "Hardware Control Interface" which is supposed to
66 * be uniform across all their models. Ideally we would just call
67 * dedicated ACPI methods instead of using this primitive interface.
68 * However the ACPI methods seem to be incomplete in some areas (for
69 * example they allow setting, but not reading, the LCD brightness value),
70 * so this is still useful.
71 */
72
73#define HCI_WORDS 6
74
75/* operations */
76#define HCI_SET 0xff00
77#define HCI_GET 0xfe00
78
79/* return codes */
80#define HCI_SUCCESS 0x0000
81#define HCI_FAILURE 0x1000
82#define HCI_NOT_SUPPORTED 0x8000
83#define HCI_EMPTY 0x8c00
84
85/* registers */
86#define HCI_FAN 0x0004
87#define HCI_SYSTEM_EVENT 0x0016
88#define HCI_VIDEO_OUT 0x001c
89#define HCI_HOTKEY_EVENT 0x001e
90#define HCI_LCD_BRIGHTNESS 0x002a
91
92/* field definitions */
93#define HCI_LCD_BRIGHTNESS_BITS 3
94#define HCI_LCD_BRIGHTNESS_SHIFT (16-HCI_LCD_BRIGHTNESS_BITS)
95#define HCI_LCD_BRIGHTNESS_LEVELS (1 << HCI_LCD_BRIGHTNESS_BITS)
96#define HCI_VIDEO_OUT_LCD 0x1
97#define HCI_VIDEO_OUT_CRT 0x2
98#define HCI_VIDEO_OUT_TV 0x4
99
100/* utility
101 */
102
103static __inline__ void
104_set_bit(u32* word, u32 mask, int value)
105{
106 *word = (*word & ~mask) | (mask * value);
107}
108
109/* acpi interface wrappers
110 */
111
112static int
113is_valid_acpi_path(const char* methodName)
114{
115 acpi_handle handle;
116 acpi_status status;
117
118 status = acpi_get_handle(NULL, (char*)methodName, &handle);
119 return !ACPI_FAILURE(status);
120}
121
122static int
123write_acpi_int(const char* methodName, int val)
124{
125 struct acpi_object_list params;
126 union acpi_object in_objs[1];
127 acpi_status status;
128
129 params.count = sizeof(in_objs)/sizeof(in_objs[0]);
130 params.pointer = in_objs;
131 in_objs[0].type = ACPI_TYPE_INTEGER;
132 in_objs[0].integer.value = val;
133
134 status = acpi_evaluate_object(NULL, (char*)methodName, &params, NULL);
135 return (status == AE_OK);
136}
137
138#if 0
139static int
140read_acpi_int(const char* methodName, int* pVal)
141{
142 struct acpi_buffer results;
143 union acpi_object out_objs[1];
144 acpi_status status;
145
146 results.length = sizeof(out_objs);
147 results.pointer = out_objs;
148
149 status = acpi_evaluate_object(0, (char*)methodName, 0, &results);
150 *pVal = out_objs[0].integer.value;
151
152 return (status == AE_OK) && (out_objs[0].type == ACPI_TYPE_INTEGER);
153}
154#endif
155
156static const char* method_hci /*= 0*/;
157
158/* Perform a raw HCI call. Here we don't care about input or output buffer
159 * format.
160 */
161static acpi_status
162hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
163{
164 struct acpi_object_list params;
165 union acpi_object in_objs[HCI_WORDS];
166 struct acpi_buffer results;
167 union acpi_object out_objs[HCI_WORDS+1];
168 acpi_status status;
169 int i;
170
171 params.count = HCI_WORDS;
172 params.pointer = in_objs;
173 for (i = 0; i < HCI_WORDS; ++i) {
174 in_objs[i].type = ACPI_TYPE_INTEGER;
175 in_objs[i].integer.value = in[i];
176 }
177
178 results.length = sizeof(out_objs);
179 results.pointer = out_objs;
180
181 status = acpi_evaluate_object(NULL, (char*)method_hci, &params,
182 &results);
183 if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
184 for (i = 0; i < out_objs->package.count; ++i) {
185 out[i] = out_objs->package.elements[i].integer.value;
186 }
187 }
188
189 return status;
190}
191
192/* common hci tasks (get or set one value)
193 *
194 * In addition to the ACPI status, the HCI system returns a result which
195 * may be useful (such as "not supported").
196 */
197
198static acpi_status
199hci_write1(u32 reg, u32 in1, u32* result)
200{
201 u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
202 u32 out[HCI_WORDS];
203 acpi_status status = hci_raw(in, out);
204 *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
205 return status;
206}
207
208static acpi_status
209hci_read1(u32 reg, u32* out1, u32* result)
210{
211 u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
212 u32 out[HCI_WORDS];
213 acpi_status status = hci_raw(in, out);
214 *out1 = out[2];
215 *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
216 return status;
217}
218
219static struct proc_dir_entry* toshiba_proc_dir /*= 0*/;
220static int force_fan;
221static int last_key_event;
222static int key_event_valid;
223
224typedef struct _ProcItem
225{
226 const char* name;
227 char* (*read_func)(char*);
228 unsigned long (*write_func)(const char*, unsigned long);
229} ProcItem;
230
231/* proc file handlers
232 */
233
234static int
235dispatch_read(char* page, char** start, off_t off, int count, int* eof,
236 ProcItem* item)
237{
238 char* p = page;
239 int len;
240
241 if (off == 0)
242 p = item->read_func(p);
243
244 /* ISSUE: I don't understand this code */
245 len = (p - page);
246 if (len <= off+count) *eof = 1;
247 *start = page + off;
248 len -= off;
249 if (len>count) len = count;
250 if (len<0) len = 0;
251 return len;
252}
253
254static int
255dispatch_write(struct file* file, const char __user * buffer,
256 unsigned long count, ProcItem* item)
257{
258 int result;
259 char* tmp_buffer;
260
261 /* Arg buffer points to userspace memory, which can't be accessed
262 * directly. Since we're making a copy, zero-terminate the
263 * destination so that sscanf can be used on it safely.
264 */
265 tmp_buffer = kmalloc(count + 1, GFP_KERNEL);
266 if (copy_from_user(tmp_buffer, buffer, count)) {
267 result = -EFAULT;
268 }
269 else {
270 tmp_buffer[count] = 0;
271 result = item->write_func(tmp_buffer, count);
272 }
273 kfree(tmp_buffer);
274 return result;
275}
276
277static char*
278read_lcd(char* p)
279{
280 u32 hci_result;
281 u32 value;
282
283 hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result);
284 if (hci_result == HCI_SUCCESS) {
285 value = value >> HCI_LCD_BRIGHTNESS_SHIFT;
286 p += sprintf(p, "brightness: %d\n", value);
287 p += sprintf(p, "brightness_levels: %d\n",
288 HCI_LCD_BRIGHTNESS_LEVELS);
289 } else {
290 printk(MY_ERR "Error reading LCD brightness\n");
291 }
292
293 return p;
294}
295
296static unsigned long
297write_lcd(const char* buffer, unsigned long count)
298{
299 int value;
300 u32 hci_result;
301
302 if (sscanf(buffer, " brightness : %i", &value) == 1 &&
303 value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
304 value = value << HCI_LCD_BRIGHTNESS_SHIFT;
305 hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
306 if (hci_result != HCI_SUCCESS)
307 return -EFAULT;
308 } else {
309 return -EINVAL;
310 }
311
312 return count;
313}
314
315static char*
316read_video(char* p)
317{
318 u32 hci_result;
319 u32 value;
320
321 hci_read1(HCI_VIDEO_OUT, &value, &hci_result);
322 if (hci_result == HCI_SUCCESS) {
323 int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
324 int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
325 int is_tv = (value & HCI_VIDEO_OUT_TV ) ? 1 : 0;
326 p += sprintf(p, "lcd_out: %d\n", is_lcd);
327 p += sprintf(p, "crt_out: %d\n", is_crt);
328 p += sprintf(p, "tv_out: %d\n", is_tv);
329 } else {
330 printk(MY_ERR "Error reading video out status\n");
331 }
332
333 return p;
334}
335
336static unsigned long
337write_video(const char* buffer, unsigned long count)
338{
339 int value;
340 int remain = count;
341 int lcd_out = -1;
342 int crt_out = -1;
343 int tv_out = -1;
344 u32 hci_result;
345 int video_out;
346
347 /* scan expression. Multiple expressions may be delimited with ;
348 *
349 * NOTE: to keep scanning simple, invalid fields are ignored
350 */
351 while (remain) {
352 if (sscanf(buffer, " lcd_out : %i", &value) == 1)
353 lcd_out = value & 1;
354 else if (sscanf(buffer, " crt_out : %i", &value) == 1)
355 crt_out = value & 1;
356 else if (sscanf(buffer, " tv_out : %i", &value) == 1)
357 tv_out = value & 1;
358 /* advance to one character past the next ; */
359 do {
360 ++buffer;
361 --remain;
362 }
363 while (remain && *(buffer-1) != ';');
364 }
365
366 hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
367 if (hci_result == HCI_SUCCESS) {
368 int new_video_out = video_out;
369 if (lcd_out != -1)
370 _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
371 if (crt_out != -1)
372 _set_bit(&new_video_out, HCI_VIDEO_OUT_CRT, crt_out);
373 if (tv_out != -1)
374 _set_bit(&new_video_out, HCI_VIDEO_OUT_TV, tv_out);
375 /* To avoid unnecessary video disruption, only write the new
376 * video setting if something changed. */
377 if (new_video_out != video_out)
378 write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
379 } else {
380 return -EFAULT;
381 }
382
383 return count;
384}
385
386static char*
387read_fan(char* p)
388{
389 u32 hci_result;
390 u32 value;
391
392 hci_read1(HCI_FAN, &value, &hci_result);
393 if (hci_result == HCI_SUCCESS) {
394 p += sprintf(p, "running: %d\n", (value > 0));
395 p += sprintf(p, "force_on: %d\n", force_fan);
396 } else {
397 printk(MY_ERR "Error reading fan status\n");
398 }
399
400 return p;
401}
402
403static unsigned long
404write_fan(const char* buffer, unsigned long count)
405{
406 int value;
407 u32 hci_result;
408
409 if (sscanf(buffer, " force_on : %i", &value) == 1 &&
410 value >= 0 && value <= 1) {
411 hci_write1(HCI_FAN, value, &hci_result);
412 if (hci_result != HCI_SUCCESS)
413 return -EFAULT;
414 else
415 force_fan = value;
416 } else {
417 return -EINVAL;
418 }
419
420 return count;
421}
422
423static char*
424read_keys(char* p)
425{
426 u32 hci_result;
427 u32 value;
428
429 if (!key_event_valid) {
430 hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
431 if (hci_result == HCI_SUCCESS) {
432 key_event_valid = 1;
433 last_key_event = value;
434 } else if (hci_result == HCI_EMPTY) {
435 /* better luck next time */
436 } else if (hci_result == HCI_NOT_SUPPORTED) {
437 /* This is a workaround for an unresolved issue on
438 * some machines where system events sporadically
439 * become disabled. */
440 hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
441 printk(MY_NOTICE "Re-enabled hotkeys\n");
442 } else {
443 printk(MY_ERR "Error reading hotkey status\n");
444 goto end;
445 }
446 }
447
448 p += sprintf(p, "hotkey_ready: %d\n", key_event_valid);
449 p += sprintf(p, "hotkey: 0x%04x\n", last_key_event);
450
451end:
452 return p;
453}
454
455static unsigned long
456write_keys(const char* buffer, unsigned long count)
457{
458 int value;
459
460 if (sscanf(buffer, " hotkey_ready : %i", &value) == 1 &&
461 value == 0) {
462 key_event_valid = 0;
463 } else {
464 return -EINVAL;
465 }
466
467 return count;
468}
469
470static char*
471read_version(char* p)
472{
473 p += sprintf(p, "driver: %s\n", TOSHIBA_ACPI_VERSION);
474 p += sprintf(p, "proc_interface: %d\n",
475 PROC_INTERFACE_VERSION);
476 return p;
477}
478
479/* proc and module init
480 */
481
482#define PROC_TOSHIBA "toshiba"
483
484static ProcItem proc_items[] =
485{
486 { "lcd" , read_lcd , write_lcd },
487 { "video" , read_video , write_video },
488 { "fan" , read_fan , write_fan },
489 { "keys" , read_keys , write_keys },
490 { "version" , read_version , NULL },
491 { NULL }
492};
493
494static acpi_status __init
495add_device(void)
496{
497 struct proc_dir_entry* proc;
498 ProcItem* item;
499
500 for (item = proc_items; item->name; ++item)
501 {
502 proc = create_proc_read_entry(item->name,
503 S_IFREG | S_IRUGO | S_IWUSR,
504 toshiba_proc_dir, (read_proc_t*)dispatch_read, item);
505 if (proc)
506 proc->owner = THIS_MODULE;
507 if (proc && item->write_func)
508 proc->write_proc = (write_proc_t*)dispatch_write;
509 }
510
511 return AE_OK;
512}
513
514static acpi_status __exit
515remove_device(void)
516{
517 ProcItem* item;
518
519 for (item = proc_items; item->name; ++item)
520 remove_proc_entry(item->name, toshiba_proc_dir);
521 return AE_OK;
522}
523
524static int __init
525toshiba_acpi_init(void)
526{
527 acpi_status status = AE_OK;
528 u32 hci_result;
529
530 if (acpi_disabled)
531 return -ENODEV;
532 /* simple device detection: look for HCI method */
533 if (is_valid_acpi_path(METHOD_HCI_1))
534 method_hci = METHOD_HCI_1;
535 else if (is_valid_acpi_path(METHOD_HCI_2))
536 method_hci = METHOD_HCI_2;
537 else
538 return -ENODEV;
539
540 printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n",
541 TOSHIBA_ACPI_VERSION);
542 printk(MY_INFO " HCI method: %s\n", method_hci);
543
544 force_fan = 0;
545 key_event_valid = 0;
546
547 /* enable event fifo */
548 hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
549
550 toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
551 if (!toshiba_proc_dir) {
552 status = AE_ERROR;
553 } else {
554 toshiba_proc_dir->owner = THIS_MODULE;
555 status = add_device();
556 if (ACPI_FAILURE(status))
557 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
558 }
559
560 return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
561}
562
563static void __exit
564toshiba_acpi_exit(void)
565{
566 remove_device();
567
568 if (toshiba_proc_dir)
569 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
570
571 return;
572}
573
574module_init(toshiba_acpi_init);
575module_exit(toshiba_acpi_exit);
diff --git a/drivers/acpi/utilities/Makefile b/drivers/acpi/utilities/Makefile
new file mode 100644
index 000000000000..939c447dd52a
--- /dev/null
+++ b/drivers/acpi/utilities/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for all Linux ACPI interpreter subdirectories
3#
4
5obj-y := utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
6 utcopy.o utdelete.o utglobal.o utmath.o utobject.o
7
8EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
new file mode 100644
index 000000000000..3313439c4bc7
--- /dev/null
+++ b/drivers/acpi/utilities/utalloc.c
@@ -0,0 +1,988 @@
1/******************************************************************************
2 *
3 * Module Name: utalloc - local cache and memory allocation routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46
47#define _COMPONENT ACPI_UTILITIES
48 ACPI_MODULE_NAME ("utalloc")
49
50
51/******************************************************************************
52 *
53 * FUNCTION: acpi_ut_release_to_cache
54 *
55 * PARAMETERS: list_id - Memory list/cache ID
56 * Object - The object to be released
57 *
58 * RETURN: None
59 *
60 * DESCRIPTION: Release an object to the specified cache. If cache is full,
61 * the object is deleted.
62 *
63 ******************************************************************************/
64
65void
66acpi_ut_release_to_cache (
67 u32 list_id,
68 void *object)
69{
70 struct acpi_memory_list *cache_info;
71
72
73 ACPI_FUNCTION_ENTRY ();
74
75
76 cache_info = &acpi_gbl_memory_lists[list_id];
77
78#ifdef ACPI_ENABLE_OBJECT_CACHE
79
80 /* If walk cache is full, just free this wallkstate object */
81
82 if (cache_info->cache_depth >= cache_info->max_cache_depth) {
83 ACPI_MEM_FREE (object);
84 ACPI_MEM_TRACKING (cache_info->total_freed++);
85 }
86
87 /* Otherwise put this object back into the cache */
88
89 else {
90 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) {
91 return;
92 }
93
94 /* Mark the object as cached */
95
96 ACPI_MEMSET (object, 0xCA, cache_info->object_size);
97 ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_CACHED);
98
99 /* Put the object at the head of the cache list */
100
101 * (ACPI_CAST_INDIRECT_PTR (char, &(((char *) object)[cache_info->link_offset]))) = cache_info->list_head;
102 cache_info->list_head = object;
103 cache_info->cache_depth++;
104
105 (void) acpi_ut_release_mutex (ACPI_MTX_CACHES);
106 }
107
108#else
109
110 /* Object cache is disabled; just free the object */
111
112 ACPI_MEM_FREE (object);
113 ACPI_MEM_TRACKING (cache_info->total_freed++);
114#endif
115}
116
117
118/******************************************************************************
119 *
120 * FUNCTION: acpi_ut_acquire_from_cache
121 *
122 * PARAMETERS: list_id - Memory list ID
123 *
124 * RETURN: A requested object. NULL if the object could not be
125 * allocated.
126 *
127 * DESCRIPTION: Get an object from the specified cache. If cache is empty,
128 * the object is allocated.
129 *
130 ******************************************************************************/
131
132void *
133acpi_ut_acquire_from_cache (
134 u32 list_id)
135{
136 struct acpi_memory_list *cache_info;
137 void *object;
138
139
140 ACPI_FUNCTION_NAME ("ut_acquire_from_cache");
141
142
143 cache_info = &acpi_gbl_memory_lists[list_id];
144
145#ifdef ACPI_ENABLE_OBJECT_CACHE
146
147 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) {
148 return (NULL);
149 }
150
151 ACPI_MEM_TRACKING (cache_info->cache_requests++);
152
153 /* Check the cache first */
154
155 if (cache_info->list_head) {
156 /* There is an object available, use it */
157
158 object = cache_info->list_head;
159 cache_info->list_head = *(ACPI_CAST_INDIRECT_PTR (char, &(((char *) object)[cache_info->link_offset])));
160
161 ACPI_MEM_TRACKING (cache_info->cache_hits++);
162 cache_info->cache_depth--;
163
164#ifdef ACPI_DBG_TRACK_ALLOCATIONS
165 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p from %s\n",
166 object, acpi_gbl_memory_lists[list_id].list_name));
167#endif
168
169 if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) {
170 return (NULL);
171 }
172
173 /* Clear (zero) the previously used Object */
174
175 ACPI_MEMSET (object, 0, cache_info->object_size);
176 }
177
178 else {
179 /* The cache is empty, create a new object */
180
181 /* Avoid deadlock with ACPI_MEM_CALLOCATE */
182
183 if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) {
184 return (NULL);
185 }
186
187 object = ACPI_MEM_CALLOCATE (cache_info->object_size);
188 ACPI_MEM_TRACKING (cache_info->total_allocated++);
189 }
190
191#else
192
193 /* Object cache is disabled; just allocate the object */
194
195 object = ACPI_MEM_CALLOCATE (cache_info->object_size);
196 ACPI_MEM_TRACKING (cache_info->total_allocated++);
197#endif
198
199 return (object);
200}
201
202
203#ifdef ACPI_ENABLE_OBJECT_CACHE
204/******************************************************************************
205 *
206 * FUNCTION: acpi_ut_delete_generic_cache
207 *
208 * PARAMETERS: list_id - Memory list ID
209 *
210 * RETURN: None
211 *
212 * DESCRIPTION: Free all objects within the requested cache.
213 *
214 ******************************************************************************/
215
216void
217acpi_ut_delete_generic_cache (
218 u32 list_id)
219{
220 struct acpi_memory_list *cache_info;
221 char *next;
222
223
224 ACPI_FUNCTION_ENTRY ();
225
226
227 cache_info = &acpi_gbl_memory_lists[list_id];
228 while (cache_info->list_head) {
229 /* Delete one cached state object */
230
231 next = *(ACPI_CAST_INDIRECT_PTR (char, &(((char *) cache_info->list_head)[cache_info->link_offset])));
232 ACPI_MEM_FREE (cache_info->list_head);
233
234 cache_info->list_head = next;
235 cache_info->cache_depth--;
236 }
237}
238#endif
239
240
241/*******************************************************************************
242 *
243 * FUNCTION: acpi_ut_validate_buffer
244 *
245 * PARAMETERS: Buffer - Buffer descriptor to be validated
246 *
247 * RETURN: Status
248 *
249 * DESCRIPTION: Perform parameter validation checks on an struct acpi_buffer
250 *
251 ******************************************************************************/
252
253acpi_status
254acpi_ut_validate_buffer (
255 struct acpi_buffer *buffer)
256{
257
258 /* Obviously, the structure pointer must be valid */
259
260 if (!buffer) {
261 return (AE_BAD_PARAMETER);
262 }
263
264 /* Special semantics for the length */
265
266 if ((buffer->length == ACPI_NO_BUFFER) ||
267 (buffer->length == ACPI_ALLOCATE_BUFFER) ||
268 (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) {
269 return (AE_OK);
270 }
271
272 /* Length is valid, the buffer pointer must be also */
273
274 if (!buffer->pointer) {
275 return (AE_BAD_PARAMETER);
276 }
277
278 return (AE_OK);
279}
280
281
282/*******************************************************************************
283 *
284 * FUNCTION: acpi_ut_initialize_buffer
285 *
286 * PARAMETERS: Buffer - Buffer to be validated
287 * required_length - Length needed
288 *
289 * RETURN: Status
290 *
291 * DESCRIPTION: Validate that the buffer is of the required length or
292 * allocate a new buffer. Returned buffer is always zeroed.
293 *
294 ******************************************************************************/
295
296acpi_status
297acpi_ut_initialize_buffer (
298 struct acpi_buffer *buffer,
299 acpi_size required_length)
300{
301 acpi_status status = AE_OK;
302
303
304 switch (buffer->length) {
305 case ACPI_NO_BUFFER:
306
307 /* Set the exception and returned the required length */
308
309 status = AE_BUFFER_OVERFLOW;
310 break;
311
312
313 case ACPI_ALLOCATE_BUFFER:
314
315 /* Allocate a new buffer */
316
317 buffer->pointer = acpi_os_allocate (required_length);
318 if (!buffer->pointer) {
319 return (AE_NO_MEMORY);
320 }
321
322 /* Clear the buffer */
323
324 ACPI_MEMSET (buffer->pointer, 0, required_length);
325 break;
326
327
328 case ACPI_ALLOCATE_LOCAL_BUFFER:
329
330 /* Allocate a new buffer with local interface to allow tracking */
331
332 buffer->pointer = ACPI_MEM_CALLOCATE (required_length);
333 if (!buffer->pointer) {
334 return (AE_NO_MEMORY);
335 }
336 break;
337
338
339 default:
340
341 /* Existing buffer: Validate the size of the buffer */
342
343 if (buffer->length < required_length) {
344 status = AE_BUFFER_OVERFLOW;
345 break;
346 }
347
348 /* Clear the buffer */
349
350 ACPI_MEMSET (buffer->pointer, 0, required_length);
351 break;
352 }
353
354 buffer->length = required_length;
355 return (status);
356}
357
358
359/*******************************************************************************
360 *
361 * FUNCTION: acpi_ut_allocate
362 *
363 * PARAMETERS: Size - Size of the allocation
364 * Component - Component type of caller
365 * Module - Source file name of caller
366 * Line - Line number of caller
367 *
368 * RETURN: Address of the allocated memory on success, NULL on failure.
369 *
370 * DESCRIPTION: The subsystem's equivalent of malloc.
371 *
372 ******************************************************************************/
373
374void *
375acpi_ut_allocate (
376 acpi_size size,
377 u32 component,
378 char *module,
379 u32 line)
380{
381 void *allocation;
382
383
384 ACPI_FUNCTION_TRACE_U32 ("ut_allocate", size);
385
386
387 /* Check for an inadvertent size of zero bytes */
388
389 if (!size) {
390 _ACPI_REPORT_ERROR (module, line, component,
391 ("ut_allocate: Attempt to allocate zero bytes\n"));
392 size = 1;
393 }
394
395 allocation = acpi_os_allocate (size);
396 if (!allocation) {
397 /* Report allocation error */
398
399 _ACPI_REPORT_ERROR (module, line, component,
400 ("ut_allocate: Could not allocate size %X\n", (u32) size));
401
402 return_PTR (NULL);
403 }
404
405 return_PTR (allocation);
406}
407
408
409/*******************************************************************************
410 *
411 * FUNCTION: acpi_ut_callocate
412 *
413 * PARAMETERS: Size - Size of the allocation
414 * Component - Component type of caller
415 * Module - Source file name of caller
416 * Line - Line number of caller
417 *
418 * RETURN: Address of the allocated memory on success, NULL on failure.
419 *
420 * DESCRIPTION: Subsystem equivalent of calloc.
421 *
422 ******************************************************************************/
423
424void *
425acpi_ut_callocate (
426 acpi_size size,
427 u32 component,
428 char *module,
429 u32 line)
430{
431 void *allocation;
432
433
434 ACPI_FUNCTION_TRACE_U32 ("ut_callocate", size);
435
436
437 /* Check for an inadvertent size of zero bytes */
438
439 if (!size) {
440 _ACPI_REPORT_ERROR (module, line, component,
441 ("ut_callocate: Attempt to allocate zero bytes\n"));
442 return_PTR (NULL);
443 }
444
445 allocation = acpi_os_allocate (size);
446 if (!allocation) {
447 /* Report allocation error */
448
449 _ACPI_REPORT_ERROR (module, line, component,
450 ("ut_callocate: Could not allocate size %X\n", (u32) size));
451 return_PTR (NULL);
452 }
453
454 /* Clear the memory block */
455
456 ACPI_MEMSET (allocation, 0, size);
457 return_PTR (allocation);
458}
459
460
461#ifdef ACPI_DBG_TRACK_ALLOCATIONS
462/*
463 * These procedures are used for tracking memory leaks in the subsystem, and
464 * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
465 *
466 * Each memory allocation is tracked via a doubly linked list. Each
467 * element contains the caller's component, module name, function name, and
468 * line number. acpi_ut_allocate and acpi_ut_callocate call
469 * acpi_ut_track_allocation to add an element to the list; deletion
470 * occurs in the body of acpi_ut_free.
471 */
472
473
474/*******************************************************************************
475 *
476 * FUNCTION: acpi_ut_allocate_and_track
477 *
478 * PARAMETERS: Size - Size of the allocation
479 * Component - Component type of caller
480 * Module - Source file name of caller
481 * Line - Line number of caller
482 *
483 * RETURN: Address of the allocated memory on success, NULL on failure.
484 *
485 * DESCRIPTION: The subsystem's equivalent of malloc.
486 *
487 ******************************************************************************/
488
489void *
490acpi_ut_allocate_and_track (
491 acpi_size size,
492 u32 component,
493 char *module,
494 u32 line)
495{
496 struct acpi_debug_mem_block *allocation;
497 acpi_status status;
498
499
500 allocation = acpi_ut_allocate (size + sizeof (struct acpi_debug_mem_header), component,
501 module, line);
502 if (!allocation) {
503 return (NULL);
504 }
505
506 status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size,
507 ACPI_MEM_MALLOC, component, module, line);
508 if (ACPI_FAILURE (status)) {
509 acpi_os_free (allocation);
510 return (NULL);
511 }
512
513 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++;
514 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size;
515
516 return ((void *) &allocation->user_space);
517}
518
519
520/*******************************************************************************
521 *
522 * FUNCTION: acpi_ut_callocate_and_track
523 *
524 * PARAMETERS: Size - Size of the allocation
525 * Component - Component type of caller
526 * Module - Source file name of caller
527 * Line - Line number of caller
528 *
529 * RETURN: Address of the allocated memory on success, NULL on failure.
530 *
531 * DESCRIPTION: Subsystem equivalent of calloc.
532 *
533 ******************************************************************************/
534
535void *
536acpi_ut_callocate_and_track (
537 acpi_size size,
538 u32 component,
539 char *module,
540 u32 line)
541{
542 struct acpi_debug_mem_block *allocation;
543 acpi_status status;
544
545
546 allocation = acpi_ut_callocate (size + sizeof (struct acpi_debug_mem_header), component,
547 module, line);
548 if (!allocation) {
549 /* Report allocation error */
550
551 _ACPI_REPORT_ERROR (module, line, component,
552 ("ut_callocate: Could not allocate size %X\n", (u32) size));
553 return (NULL);
554 }
555
556 status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size,
557 ACPI_MEM_CALLOC, component, module, line);
558 if (ACPI_FAILURE (status)) {
559 acpi_os_free (allocation);
560 return (NULL);
561 }
562
563 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++;
564 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size;
565
566 return ((void *) &allocation->user_space);
567}
568
569
570/*******************************************************************************
571 *
572 * FUNCTION: acpi_ut_free_and_track
573 *
574 * PARAMETERS: Allocation - Address of the memory to deallocate
575 * Component - Component type of caller
576 * Module - Source file name of caller
577 * Line - Line number of caller
578 *
579 * RETURN: None
580 *
581 * DESCRIPTION: Frees the memory at Allocation
582 *
583 ******************************************************************************/
584
585void
586acpi_ut_free_and_track (
587 void *allocation,
588 u32 component,
589 char *module,
590 u32 line)
591{
592 struct acpi_debug_mem_block *debug_block;
593 acpi_status status;
594
595
596 ACPI_FUNCTION_TRACE_PTR ("ut_free", allocation);
597
598
599 if (NULL == allocation) {
600 _ACPI_REPORT_ERROR (module, line, component,
601 ("acpi_ut_free: Attempt to delete a NULL address\n"));
602
603 return_VOID;
604 }
605
606 debug_block = ACPI_CAST_PTR (struct acpi_debug_mem_block,
607 (((char *) allocation) - sizeof (struct acpi_debug_mem_header)));
608
609 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_freed++;
610 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size -= debug_block->size;
611
612 status = acpi_ut_remove_allocation (ACPI_MEM_LIST_GLOBAL, debug_block,
613 component, module, line);
614 if (ACPI_FAILURE (status)) {
615 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not free memory, %s\n",
616 acpi_format_exception (status)));
617 }
618
619 acpi_os_free (debug_block);
620
621 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
622
623 return_VOID;
624}
625
626
627/*******************************************************************************
628 *
629 * FUNCTION: acpi_ut_find_allocation
630 *
631 * PARAMETERS: list_id - Memory list to search
632 * Allocation - Address of allocated memory
633 *
634 * RETURN: A list element if found; NULL otherwise.
635 *
636 * DESCRIPTION: Searches for an element in the global allocation tracking list.
637 *
638 ******************************************************************************/
639
640struct acpi_debug_mem_block *
641acpi_ut_find_allocation (
642 u32 list_id,
643 void *allocation)
644{
645 struct acpi_debug_mem_block *element;
646
647
648 ACPI_FUNCTION_ENTRY ();
649
650
651 if (list_id > ACPI_MEM_LIST_MAX) {
652 return (NULL);
653 }
654
655 element = acpi_gbl_memory_lists[list_id].list_head;
656
657 /* Search for the address. */
658
659 while (element) {
660 if (element == allocation) {
661 return (element);
662 }
663
664 element = element->next;
665 }
666
667 return (NULL);
668}
669
670
671/*******************************************************************************
672 *
673 * FUNCTION: acpi_ut_track_allocation
674 *
675 * PARAMETERS: list_id - Memory list to search
676 * Allocation - Address of allocated memory
677 * Size - Size of the allocation
678 * alloc_type - MEM_MALLOC or MEM_CALLOC
679 * Component - Component type of caller
680 * Module - Source file name of caller
681 * Line - Line number of caller
682 *
683 * RETURN: None.
684 *
685 * DESCRIPTION: Inserts an element into the global allocation tracking list.
686 *
687 ******************************************************************************/
688
689acpi_status
690acpi_ut_track_allocation (
691 u32 list_id,
692 struct acpi_debug_mem_block *allocation,
693 acpi_size size,
694 u8 alloc_type,
695 u32 component,
696 char *module,
697 u32 line)
698{
699 struct acpi_memory_list *mem_list;
700 struct acpi_debug_mem_block *element;
701 acpi_status status = AE_OK;
702
703
704 ACPI_FUNCTION_TRACE_PTR ("ut_track_allocation", allocation);
705
706
707 if (list_id > ACPI_MEM_LIST_MAX) {
708 return_ACPI_STATUS (AE_BAD_PARAMETER);
709 }
710
711 mem_list = &acpi_gbl_memory_lists[list_id];
712 status = acpi_ut_acquire_mutex (ACPI_MTX_MEMORY);
713 if (ACPI_FAILURE (status)) {
714 return_ACPI_STATUS (status);
715 }
716
717 /*
718 * Search list for this address to make sure it is not already on the list.
719 * This will catch several kinds of problems.
720 */
721
722 element = acpi_ut_find_allocation (list_id, allocation);
723 if (element) {
724 ACPI_REPORT_ERROR (("ut_track_allocation: Allocation already present in list! (%p)\n",
725 allocation));
726
727 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Element %p Address %p\n", element, allocation));
728
729 goto unlock_and_exit;
730 }
731
732 /* Fill in the instance data. */
733
734 allocation->size = (u32) size;
735 allocation->alloc_type = alloc_type;
736 allocation->component = component;
737 allocation->line = line;
738
739 ACPI_STRNCPY (allocation->module, module, ACPI_MAX_MODULE_NAME);
740 allocation->module[ACPI_MAX_MODULE_NAME-1] = 0;
741
742 /* Insert at list head */
743
744 if (mem_list->list_head) {
745 ((struct acpi_debug_mem_block *)(mem_list->list_head))->previous = allocation;
746 }
747
748 allocation->next = mem_list->list_head;
749 allocation->previous = NULL;
750
751 mem_list->list_head = allocation;
752
753
754unlock_and_exit:
755 status = acpi_ut_release_mutex (ACPI_MTX_MEMORY);
756 return_ACPI_STATUS (status);
757}
758
759
760/*******************************************************************************
761 *
762 * FUNCTION: acpi_ut_remove_allocation
763 *
764 * PARAMETERS: list_id - Memory list to search
765 * Allocation - Address of allocated memory
766 * Component - Component type of caller
767 * Module - Source file name of caller
768 * Line - Line number of caller
769 *
770 * RETURN:
771 *
772 * DESCRIPTION: Deletes an element from the global allocation tracking list.
773 *
774 ******************************************************************************/
775
776acpi_status
777acpi_ut_remove_allocation (
778 u32 list_id,
779 struct acpi_debug_mem_block *allocation,
780 u32 component,
781 char *module,
782 u32 line)
783{
784 struct acpi_memory_list *mem_list;
785 acpi_status status;
786
787
788 ACPI_FUNCTION_TRACE ("ut_remove_allocation");
789
790
791 if (list_id > ACPI_MEM_LIST_MAX) {
792 return_ACPI_STATUS (AE_BAD_PARAMETER);
793 }
794
795 mem_list = &acpi_gbl_memory_lists[list_id];
796 if (NULL == mem_list->list_head) {
797 /* No allocations! */
798
799 _ACPI_REPORT_ERROR (module, line, component,
800 ("ut_remove_allocation: Empty allocation list, nothing to free!\n"));
801
802 return_ACPI_STATUS (AE_OK);
803 }
804
805 status = acpi_ut_acquire_mutex (ACPI_MTX_MEMORY);
806 if (ACPI_FAILURE (status)) {
807 return_ACPI_STATUS (status);
808 }
809
810 /* Unlink */
811
812 if (allocation->previous) {
813 (allocation->previous)->next = allocation->next;
814 }
815 else {
816 mem_list->list_head = allocation->next;
817 }
818
819 if (allocation->next) {
820 (allocation->next)->previous = allocation->previous;
821 }
822
823 /* Mark the segment as deleted */
824
825 ACPI_MEMSET (&allocation->user_space, 0xEA, allocation->size);
826
827 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n", allocation->size));
828
829 status = acpi_ut_release_mutex (ACPI_MTX_MEMORY);
830 return_ACPI_STATUS (status);
831}
832
833
834/*******************************************************************************
835 *
836 * FUNCTION: acpi_ut_dump_allocation_info
837 *
838 * PARAMETERS:
839 *
840 * RETURN: None
841 *
842 * DESCRIPTION: Print some info about the outstanding allocations.
843 *
844 ******************************************************************************/
845#ifdef ACPI_FUTURE_USAGE
846void
847acpi_ut_dump_allocation_info (
848 void)
849{
850/*
851 struct acpi_memory_list *mem_list;
852*/
853
854 ACPI_FUNCTION_TRACE ("ut_dump_allocation_info");
855
856/*
857 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
858 ("%30s: %4d (%3d Kb)\n", "Current allocations",
859 mem_list->current_count,
860 ROUND_UP_TO_1K (mem_list->current_size)));
861
862 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
863 ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
864 mem_list->max_concurrent_count,
865 ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
866
867
868 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
869 ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
870 running_object_count,
871 ROUND_UP_TO_1K (running_object_size)));
872
873 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
874 ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
875 running_alloc_count,
876 ROUND_UP_TO_1K (running_alloc_size)));
877
878
879 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
880 ("%30s: %4d (%3d Kb)\n", "Current Nodes",
881 acpi_gbl_current_node_count,
882 ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
883
884 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
885 ("%30s: %4d (%3d Kb)\n", "Max Nodes",
886 acpi_gbl_max_concurrent_node_count,
887 ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count * sizeof (struct acpi_namespace_node)))));
888*/
889 return_VOID;
890}
891#endif /* ACPI_FUTURE_USAGE */
892
893
894/*******************************************************************************
895 *
896 * FUNCTION: acpi_ut_dump_allocations
897 *
898 * PARAMETERS: Component - Component(s) to dump info for.
899 * Module - Module to dump info for. NULL means all.
900 *
901 * RETURN: None
902 *
903 * DESCRIPTION: Print a list of all outstanding allocations.
904 *
905 ******************************************************************************/
906
907void
908acpi_ut_dump_allocations (
909 u32 component,
910 char *module)
911{
912 struct acpi_debug_mem_block *element;
913 union acpi_descriptor *descriptor;
914 u32 num_outstanding = 0;
915
916
917 ACPI_FUNCTION_TRACE ("ut_dump_allocations");
918
919
920 /*
921 * Walk the allocation list.
922 */
923 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_MEMORY))) {
924 return;
925 }
926
927 element = acpi_gbl_memory_lists[0].list_head;
928 while (element) {
929 if ((element->component & component) &&
930 ((module == NULL) || (0 == ACPI_STRCMP (module, element->module)))) {
931 /* Ignore allocated objects that are in a cache */
932
933 descriptor = ACPI_CAST_PTR (union acpi_descriptor, &element->user_space);
934 if (descriptor->descriptor_id != ACPI_DESC_TYPE_CACHED) {
935 acpi_os_printf ("%p Len %04X %9.9s-%d [%s] ",
936 descriptor, element->size, element->module,
937 element->line, acpi_ut_get_descriptor_name (descriptor));
938
939 /* Most of the elements will be Operand objects. */
940
941 switch (ACPI_GET_DESCRIPTOR_TYPE (descriptor)) {
942 case ACPI_DESC_TYPE_OPERAND:
943 acpi_os_printf ("%12.12s R%hd",
944 acpi_ut_get_type_name (descriptor->object.common.type),
945 descriptor->object.common.reference_count);
946 break;
947
948 case ACPI_DESC_TYPE_PARSER:
949 acpi_os_printf ("aml_opcode %04hX",
950 descriptor->op.asl.aml_opcode);
951 break;
952
953 case ACPI_DESC_TYPE_NAMED:
954 acpi_os_printf ("%4.4s",
955 acpi_ut_get_node_name (&descriptor->node));
956 break;
957
958 default:
959 break;
960 }
961
962 acpi_os_printf ( "\n");
963 num_outstanding++;
964 }
965 }
966 element = element->next;
967 }
968
969 (void) acpi_ut_release_mutex (ACPI_MTX_MEMORY);
970
971 /* Print summary */
972
973 if (!num_outstanding) {
974 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
975 "No outstanding allocations.\n"));
976 }
977 else {
978 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
979 "%d(%X) Outstanding allocations\n",
980 num_outstanding, num_outstanding));
981 }
982
983 return_VOID;
984}
985
986
987#endif /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */
988
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
new file mode 100644
index 000000000000..0fcd98bde0d1
--- /dev/null
+++ b/drivers/acpi/utilities/utcopy.c
@@ -0,0 +1,930 @@
1/******************************************************************************
2 *
3 * Module Name: utcopy - Internal to external object translation utilities
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/amlcode.h>
47
48
49#define _COMPONENT ACPI_UTILITIES
50 ACPI_MODULE_NAME ("utcopy")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ut_copy_isimple_to_esimple
56 *
57 * PARAMETERS: *internal_object - Pointer to the object we are examining
58 * *Buffer - Where the object is returned
59 * *space_used - Where the data length is returned
60 *
61 * RETURN: Status
62 *
63 * DESCRIPTION: This function is called to place a simple object in a user
64 * buffer.
65 *
66 * The buffer is assumed to have sufficient space for the object.
67 *
68 ******************************************************************************/
69
70static acpi_status
71acpi_ut_copy_isimple_to_esimple (
72 union acpi_operand_object *internal_object,
73 union acpi_object *external_object,
74 u8 *data_space,
75 acpi_size *buffer_space_used)
76{
77 acpi_status status = AE_OK;
78
79
80 ACPI_FUNCTION_TRACE ("ut_copy_isimple_to_esimple");
81
82
83 *buffer_space_used = 0;
84
85 /*
86 * Check for NULL object case (could be an uninitialized
87 * package element)
88 */
89 if (!internal_object) {
90 return_ACPI_STATUS (AE_OK);
91 }
92
93 /* Always clear the external object */
94
95 ACPI_MEMSET (external_object, 0, sizeof (union acpi_object));
96
97 /*
98 * In general, the external object will be the same type as
99 * the internal object
100 */
101 external_object->type = ACPI_GET_OBJECT_TYPE (internal_object);
102
103 /* However, only a limited number of external types are supported */
104
105 switch (ACPI_GET_OBJECT_TYPE (internal_object)) {
106 case ACPI_TYPE_STRING:
107
108 external_object->string.pointer = (char *) data_space;
109 external_object->string.length = internal_object->string.length;
110 *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD ((acpi_size) internal_object->string.length + 1);
111
112 ACPI_MEMCPY ((void *) data_space, (void *) internal_object->string.pointer,
113 (acpi_size) internal_object->string.length + 1);
114 break;
115
116
117 case ACPI_TYPE_BUFFER:
118
119 external_object->buffer.pointer = data_space;
120 external_object->buffer.length = internal_object->buffer.length;
121 *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD (internal_object->string.length);
122
123 ACPI_MEMCPY ((void *) data_space, (void *) internal_object->buffer.pointer,
124 internal_object->buffer.length);
125 break;
126
127
128 case ACPI_TYPE_INTEGER:
129
130 external_object->integer.value = internal_object->integer.value;
131 break;
132
133
134 case ACPI_TYPE_LOCAL_REFERENCE:
135
136 /*
137 * This is an object reference. Attempt to dereference it.
138 */
139 switch (internal_object->reference.opcode) {
140 case AML_INT_NAMEPATH_OP:
141
142 /* For namepath, return the object handle ("reference") */
143
144 default:
145 /*
146 * Use the object type of "Any" to indicate a reference
147 * to object containing a handle to an ACPI named object.
148 */
149 external_object->type = ACPI_TYPE_ANY;
150 external_object->reference.handle = internal_object->reference.node;
151 break;
152 }
153 break;
154
155
156 case ACPI_TYPE_PROCESSOR:
157
158 external_object->processor.proc_id = internal_object->processor.proc_id;
159 external_object->processor.pblk_address = internal_object->processor.address;
160 external_object->processor.pblk_length = internal_object->processor.length;
161 break;
162
163
164 case ACPI_TYPE_POWER:
165
166 external_object->power_resource.system_level =
167 internal_object->power_resource.system_level;
168
169 external_object->power_resource.resource_order =
170 internal_object->power_resource.resource_order;
171 break;
172
173
174 default:
175 /*
176 * There is no corresponding external object type
177 */
178 return_ACPI_STATUS (AE_SUPPORT);
179 }
180
181 return_ACPI_STATUS (status);
182}
183
184
185/*******************************************************************************
186 *
187 * FUNCTION: acpi_ut_copy_ielement_to_eelement
188 *
189 * PARAMETERS: acpi_pkg_callback
190 *
191 * RETURN: Status
192 *
193 * DESCRIPTION: Copy one package element to another package element
194 *
195 ******************************************************************************/
196
197acpi_status
198acpi_ut_copy_ielement_to_eelement (
199 u8 object_type,
200 union acpi_operand_object *source_object,
201 union acpi_generic_state *state,
202 void *context)
203{
204 acpi_status status = AE_OK;
205 struct acpi_pkg_info *info = (struct acpi_pkg_info *) context;
206 acpi_size object_space;
207 u32 this_index;
208 union acpi_object *target_object;
209
210
211 ACPI_FUNCTION_ENTRY ();
212
213
214 this_index = state->pkg.index;
215 target_object = (union acpi_object *)
216 &((union acpi_object *)(state->pkg.dest_object))->package.elements[this_index];
217
218 switch (object_type) {
219 case ACPI_COPY_TYPE_SIMPLE:
220
221 /*
222 * This is a simple or null object
223 */
224 status = acpi_ut_copy_isimple_to_esimple (source_object,
225 target_object, info->free_space, &object_space);
226 if (ACPI_FAILURE (status)) {
227 return (status);
228 }
229 break;
230
231
232 case ACPI_COPY_TYPE_PACKAGE:
233
234 /*
235 * Build the package object
236 */
237 target_object->type = ACPI_TYPE_PACKAGE;
238 target_object->package.count = source_object->package.count;
239 target_object->package.elements = ACPI_CAST_PTR (union acpi_object, info->free_space);
240
241 /*
242 * Pass the new package object back to the package walk routine
243 */
244 state->pkg.this_target_obj = target_object;
245
246 /*
247 * Save space for the array of objects (Package elements)
248 * update the buffer length counter
249 */
250 object_space = ACPI_ROUND_UP_TO_NATIVE_WORD (
251 (acpi_size) target_object->package.count * sizeof (union acpi_object));
252 break;
253
254
255 default:
256 return (AE_BAD_PARAMETER);
257 }
258
259 info->free_space += object_space;
260 info->length += object_space;
261 return (status);
262}
263
264
265/*******************************************************************************
266 *
267 * FUNCTION: acpi_ut_copy_ipackage_to_epackage
268 *
269 * PARAMETERS: *internal_object - Pointer to the object we are returning
270 * *Buffer - Where the object is returned
271 * *space_used - Where the object length is returned
272 *
273 * RETURN: Status
274 *
275 * DESCRIPTION: This function is called to place a package object in a user
276 * buffer. A package object by definition contains other objects.
277 *
278 * The buffer is assumed to have sufficient space for the object.
279 * The caller must have verified the buffer length needed using the
280 * acpi_ut_get_object_size function before calling this function.
281 *
282 ******************************************************************************/
283
284static acpi_status
285acpi_ut_copy_ipackage_to_epackage (
286 union acpi_operand_object *internal_object,
287 u8 *buffer,
288 acpi_size *space_used)
289{
290 union acpi_object *external_object;
291 acpi_status status;
292 struct acpi_pkg_info info;
293
294
295 ACPI_FUNCTION_TRACE ("ut_copy_ipackage_to_epackage");
296
297
298 /*
299 * First package at head of the buffer
300 */
301 external_object = ACPI_CAST_PTR (union acpi_object, buffer);
302
303 /*
304 * Free space begins right after the first package
305 */
306 info.length = ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object));
307 info.free_space = buffer + ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object));
308 info.object_space = 0;
309 info.num_packages = 1;
310
311 external_object->type = ACPI_GET_OBJECT_TYPE (internal_object);
312 external_object->package.count = internal_object->package.count;
313 external_object->package.elements = ACPI_CAST_PTR (union acpi_object, info.free_space);
314
315 /*
316 * Leave room for an array of ACPI_OBJECTS in the buffer
317 * and move the free space past it
318 */
319 info.length += (acpi_size) external_object->package.count *
320 ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object));
321 info.free_space += external_object->package.count *
322 ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object));
323
324 status = acpi_ut_walk_package_tree (internal_object, external_object,
325 acpi_ut_copy_ielement_to_eelement, &info);
326
327 *space_used = info.length;
328 return_ACPI_STATUS (status);
329}
330
331
332/*******************************************************************************
333 *
334 * FUNCTION: acpi_ut_copy_iobject_to_eobject
335 *
336 * PARAMETERS: *internal_object - The internal object to be converted
337 * *buffer_ptr - Where the object is returned
338 *
339 * RETURN: Status
340 *
341 * DESCRIPTION: This function is called to build an API object to be returned to
342 * the caller.
343 *
344 ******************************************************************************/
345
346acpi_status
347acpi_ut_copy_iobject_to_eobject (
348 union acpi_operand_object *internal_object,
349 struct acpi_buffer *ret_buffer)
350{
351 acpi_status status;
352
353
354 ACPI_FUNCTION_TRACE ("ut_copy_iobject_to_eobject");
355
356
357 if (ACPI_GET_OBJECT_TYPE (internal_object) == ACPI_TYPE_PACKAGE) {
358 /*
359 * Package object: Copy all subobjects (including
360 * nested packages)
361 */
362 status = acpi_ut_copy_ipackage_to_epackage (internal_object,
363 ret_buffer->pointer, &ret_buffer->length);
364 }
365 else {
366 /*
367 * Build a simple object (no nested objects)
368 */
369 status = acpi_ut_copy_isimple_to_esimple (internal_object,
370 (union acpi_object *) ret_buffer->pointer,
371 ((u8 *) ret_buffer->pointer +
372 ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object))),
373 &ret_buffer->length);
374 /*
375 * build simple does not include the object size in the length
376 * so we add it in here
377 */
378 ret_buffer->length += sizeof (union acpi_object);
379 }
380
381 return_ACPI_STATUS (status);
382}
383
384
385/*******************************************************************************
386 *
387 * FUNCTION: acpi_ut_copy_esimple_to_isimple
388 *
389 * PARAMETERS: *external_object - The external object to be converted
390 * *internal_object - Where the internal object is returned
391 *
392 * RETURN: Status
393 *
394 * DESCRIPTION: This function copies an external object to an internal one.
395 * NOTE: Pointers can be copied, we don't need to copy data.
396 * (The pointers have to be valid in our address space no matter
397 * what we do with them!)
398 *
399 ******************************************************************************/
400
401acpi_status
402acpi_ut_copy_esimple_to_isimple (
403 union acpi_object *external_object,
404 union acpi_operand_object **ret_internal_object)
405{
406 union acpi_operand_object *internal_object;
407
408
409 ACPI_FUNCTION_TRACE ("ut_copy_esimple_to_isimple");
410
411
412 /*
413 * Simple types supported are: String, Buffer, Integer
414 */
415 switch (external_object->type) {
416 case ACPI_TYPE_STRING:
417 case ACPI_TYPE_BUFFER:
418 case ACPI_TYPE_INTEGER:
419
420 internal_object = acpi_ut_create_internal_object ((u8) external_object->type);
421 if (!internal_object) {
422 return_ACPI_STATUS (AE_NO_MEMORY);
423 }
424 break;
425
426 default:
427 /* All other types are not supported */
428
429 return_ACPI_STATUS (AE_SUPPORT);
430 }
431
432
433 /* Must COPY string and buffer contents */
434
435 switch (external_object->type) {
436 case ACPI_TYPE_STRING:
437
438 internal_object->string.pointer =
439 ACPI_MEM_CALLOCATE ((acpi_size) external_object->string.length + 1);
440 if (!internal_object->string.pointer) {
441 goto error_exit;
442 }
443
444 ACPI_MEMCPY (internal_object->string.pointer,
445 external_object->string.pointer,
446 external_object->string.length);
447
448 internal_object->string.length = external_object->string.length;
449 break;
450
451
452 case ACPI_TYPE_BUFFER:
453
454 internal_object->buffer.pointer =
455 ACPI_MEM_CALLOCATE (external_object->buffer.length);
456 if (!internal_object->buffer.pointer) {
457 goto error_exit;
458 }
459
460 ACPI_MEMCPY (internal_object->buffer.pointer,
461 external_object->buffer.pointer,
462 external_object->buffer.length);
463
464 internal_object->buffer.length = external_object->buffer.length;
465 break;
466
467
468 case ACPI_TYPE_INTEGER:
469
470 internal_object->integer.value = external_object->integer.value;
471 break;
472
473 default:
474 /* Other types can't get here */
475 break;
476 }
477
478 *ret_internal_object = internal_object;
479 return_ACPI_STATUS (AE_OK);
480
481
482error_exit:
483 acpi_ut_remove_reference (internal_object);
484 return_ACPI_STATUS (AE_NO_MEMORY);
485}
486
487
488#ifdef ACPI_FUTURE_IMPLEMENTATION
489
490/* Code to convert packages that are parameters to control methods */
491
492/*******************************************************************************
493 *
494 * FUNCTION: acpi_ut_copy_epackage_to_ipackage
495 *
496 * PARAMETERS: *internal_object - Pointer to the object we are returning
497 * *Buffer - Where the object is returned
498 * *space_used - Where the length of the object is returned
499 *
500 * RETURN: Status
501 *
502 * DESCRIPTION: This function is called to place a package object in a user
503 * buffer. A package object by definition contains other objects.
504 *
505 * The buffer is assumed to have sufficient space for the object.
506 * The caller must have verified the buffer length needed using the
507 * acpi_ut_get_object_size function before calling this function.
508 *
509 ******************************************************************************/
510
511static acpi_status
512acpi_ut_copy_epackage_to_ipackage (
513 union acpi_operand_object *internal_object,
514 u8 *buffer,
515 u32 *space_used)
516{
517 u8 *free_space;
518 union acpi_object *external_object;
519 u32 length = 0;
520 u32 this_index;
521 u32 object_space = 0;
522 union acpi_operand_object *this_internal_obj;
523 union acpi_object *this_external_obj;
524
525
526 ACPI_FUNCTION_TRACE ("ut_copy_epackage_to_ipackage");
527
528
529 /*
530 * First package at head of the buffer
531 */
532 external_object = (union acpi_object *)buffer;
533
534 /*
535 * Free space begins right after the first package
536 */
537 free_space = buffer + sizeof(union acpi_object);
538
539
540 external_object->type = ACPI_GET_OBJECT_TYPE (internal_object);
541 external_object->package.count = internal_object->package.count;
542 external_object->package.elements = (union acpi_object *)free_space;
543
544 /*
545 * Build an array of ACPI_OBJECTS in the buffer
546 * and move the free space past it
547 */
548 free_space += external_object->package.count * sizeof(union acpi_object);
549
550
551 /* Call walk_package */
552
553}
554
555#endif /* Future implementation */
556
557
558/*******************************************************************************
559 *
560 * FUNCTION: acpi_ut_copy_eobject_to_iobject
561 *
562 * PARAMETERS: *internal_object - The external object to be converted
563 * *buffer_ptr - Where the internal object is returned
564 *
565 * RETURN: Status - the status of the call
566 *
567 * DESCRIPTION: Converts an external object to an internal object.
568 *
569 ******************************************************************************/
570
571acpi_status
572acpi_ut_copy_eobject_to_iobject (
573 union acpi_object *external_object,
574 union acpi_operand_object **internal_object)
575{
576 acpi_status status;
577
578
579 ACPI_FUNCTION_TRACE ("ut_copy_eobject_to_iobject");
580
581
582 if (external_object->type == ACPI_TYPE_PACKAGE) {
583 /*
584 * Packages as external input to control methods are not supported,
585 */
586 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
587 "Packages as parameters not implemented!\n"));
588
589 return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
590 }
591
592 else {
593 /*
594 * Build a simple object (no nested objects)
595 */
596 status = acpi_ut_copy_esimple_to_isimple (external_object, internal_object);
597 }
598
599 return_ACPI_STATUS (status);
600}
601
602
603/*******************************************************************************
604 *
605 * FUNCTION: acpi_ut_copy_simple_object
606 *
607 * PARAMETERS: source_desc - The internal object to be copied
608 * dest_desc - New target object
609 *
610 * RETURN: Status
611 *
612 * DESCRIPTION: Simple copy of one internal object to another. Reference count
613 * of the destination object is preserved.
614 *
615 ******************************************************************************/
616
617acpi_status
618acpi_ut_copy_simple_object (
619 union acpi_operand_object *source_desc,
620 union acpi_operand_object *dest_desc)
621{
622 u16 reference_count;
623 union acpi_operand_object *next_object;
624
625
626 /* Save fields from destination that we don't want to overwrite */
627
628 reference_count = dest_desc->common.reference_count;
629 next_object = dest_desc->common.next_object;
630
631 /* Copy the entire source object over the destination object*/
632
633 ACPI_MEMCPY ((char *) dest_desc, (char *) source_desc,
634 sizeof (union acpi_operand_object));
635
636 /* Restore the saved fields */
637
638 dest_desc->common.reference_count = reference_count;
639 dest_desc->common.next_object = next_object;
640
641 /* Handle the objects with extra data */
642
643 switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
644 case ACPI_TYPE_BUFFER:
645
646 dest_desc->buffer.node = NULL;
647 dest_desc->common.flags = source_desc->common.flags;
648
649 /*
650 * Allocate and copy the actual buffer if and only if:
651 * 1) There is a valid buffer pointer
652 * 2) The buffer is not static (not in an ACPI table) (in this case,
653 * the actual pointer was already copied above)
654 */
655 if ((source_desc->buffer.pointer) &&
656 (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
657 dest_desc->buffer.pointer = NULL;
658
659 /* Create an actual buffer only if length > 0 */
660
661 if (source_desc->buffer.length) {
662 dest_desc->buffer.pointer =
663 ACPI_MEM_ALLOCATE (source_desc->buffer.length);
664 if (!dest_desc->buffer.pointer) {
665 return (AE_NO_MEMORY);
666 }
667
668 /* Copy the actual buffer data */
669
670 ACPI_MEMCPY (dest_desc->buffer.pointer,
671 source_desc->buffer.pointer,
672 source_desc->buffer.length);
673 }
674 }
675 break;
676
677 case ACPI_TYPE_STRING:
678
679 /*
680 * Allocate and copy the actual string if and only if:
681 * 1) There is a valid string pointer
682 * 2) The string is not static (not in an ACPI table) (in this case,
683 * the actual pointer was already copied above)
684 */
685 if ((source_desc->string.pointer) &&
686 (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
687 dest_desc->string.pointer =
688 ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1);
689 if (!dest_desc->string.pointer) {
690 return (AE_NO_MEMORY);
691 }
692
693 ACPI_MEMCPY (dest_desc->string.pointer, source_desc->string.pointer,
694 (acpi_size) source_desc->string.length + 1);
695 }
696 break;
697
698 case ACPI_TYPE_LOCAL_REFERENCE:
699 /*
700 * We copied the reference object, so we now must add a reference
701 * to the object pointed to by the reference
702 */
703 acpi_ut_add_reference (source_desc->reference.object);
704 break;
705
706 default:
707 /* Nothing to do for other simple objects */
708 break;
709 }
710
711 return (AE_OK);
712}
713
714
715/*******************************************************************************
716 *
717 * FUNCTION: acpi_ut_copy_ielement_to_ielement
718 *
719 * PARAMETERS: acpi_pkg_callback
720 *
721 * RETURN: Status
722 *
723 * DESCRIPTION: Copy one package element to another package element
724 *
725 ******************************************************************************/
726
727acpi_status
728acpi_ut_copy_ielement_to_ielement (
729 u8 object_type,
730 union acpi_operand_object *source_object,
731 union acpi_generic_state *state,
732 void *context)
733{
734 acpi_status status = AE_OK;
735 u32 this_index;
736 union acpi_operand_object **this_target_ptr;
737 union acpi_operand_object *target_object;
738
739
740 ACPI_FUNCTION_ENTRY ();
741
742
743 this_index = state->pkg.index;
744 this_target_ptr = (union acpi_operand_object **)
745 &state->pkg.dest_object->package.elements[this_index];
746
747 switch (object_type) {
748 case ACPI_COPY_TYPE_SIMPLE:
749
750 /* A null source object indicates a (legal) null package element */
751
752 if (source_object) {
753 /*
754 * This is a simple object, just copy it
755 */
756 target_object = acpi_ut_create_internal_object (
757 ACPI_GET_OBJECT_TYPE (source_object));
758 if (!target_object) {
759 return (AE_NO_MEMORY);
760 }
761
762 status = acpi_ut_copy_simple_object (source_object, target_object);
763 if (ACPI_FAILURE (status)) {
764 goto error_exit;
765 }
766
767 *this_target_ptr = target_object;
768 }
769 else {
770 /* Pass through a null element */
771
772 *this_target_ptr = NULL;
773 }
774 break;
775
776
777 case ACPI_COPY_TYPE_PACKAGE:
778
779 /*
780 * This object is a package - go down another nesting level
781 * Create and build the package object
782 */
783 target_object = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
784 if (!target_object) {
785 return (AE_NO_MEMORY);
786 }
787
788 target_object->package.count = source_object->package.count;
789 target_object->common.flags = source_object->common.flags;
790
791 /*
792 * Create the object array
793 */
794 target_object->package.elements =
795 ACPI_MEM_CALLOCATE (((acpi_size) source_object->package.count + 1) *
796 sizeof (void *));
797 if (!target_object->package.elements) {
798 status = AE_NO_MEMORY;
799 goto error_exit;
800 }
801
802 /*
803 * Pass the new package object back to the package walk routine
804 */
805 state->pkg.this_target_obj = target_object;
806
807 /*
808 * Store the object pointer in the parent package object
809 */
810 *this_target_ptr = target_object;
811 break;
812
813
814 default:
815 return (AE_BAD_PARAMETER);
816 }
817
818 return (status);
819
820error_exit:
821 acpi_ut_remove_reference (target_object);
822 return (status);
823}
824
825
826/*******************************************************************************
827 *
828 * FUNCTION: acpi_ut_copy_ipackage_to_ipackage
829 *
830 * PARAMETERS: *source_obj - Pointer to the source package object
831 * *dest_obj - Where the internal object is returned
832 *
833 * RETURN: Status - the status of the call
834 *
835 * DESCRIPTION: This function is called to copy an internal package object
836 * into another internal package object.
837 *
838 ******************************************************************************/
839
840acpi_status
841acpi_ut_copy_ipackage_to_ipackage (
842 union acpi_operand_object *source_obj,
843 union acpi_operand_object *dest_obj,
844 struct acpi_walk_state *walk_state)
845{
846 acpi_status status = AE_OK;
847
848
849 ACPI_FUNCTION_TRACE ("ut_copy_ipackage_to_ipackage");
850
851
852 dest_obj->common.type = ACPI_GET_OBJECT_TYPE (source_obj);
853 dest_obj->common.flags = source_obj->common.flags;
854 dest_obj->package.count = source_obj->package.count;
855
856 /*
857 * Create the object array and walk the source package tree
858 */
859 dest_obj->package.elements = ACPI_MEM_CALLOCATE (
860 ((acpi_size) source_obj->package.count + 1) *
861 sizeof (void *));
862 if (!dest_obj->package.elements) {
863 ACPI_REPORT_ERROR (
864 ("aml_build_copy_internal_package_object: Package allocation failure\n"));
865 return_ACPI_STATUS (AE_NO_MEMORY);
866 }
867
868 /*
869 * Copy the package element-by-element by walking the package "tree".
870 * This handles nested packages of arbitrary depth.
871 */
872 status = acpi_ut_walk_package_tree (source_obj, dest_obj,
873 acpi_ut_copy_ielement_to_ielement, walk_state);
874 if (ACPI_FAILURE (status)) {
875 /* On failure, delete the destination package object */
876
877 acpi_ut_remove_reference (dest_obj);
878 }
879
880 return_ACPI_STATUS (status);
881}
882
883
884/*******************************************************************************
885 *
886 * FUNCTION: acpi_ut_copy_iobject_to_iobject
887 *
888 * PARAMETERS: walk_state - Current walk state
889 * source_desc - The internal object to be copied
890 * dest_desc - Where the copied object is returned
891 *
892 * RETURN: Status
893 *
894 * DESCRIPTION: Copy an internal object to a new internal object
895 *
896 ******************************************************************************/
897
898acpi_status
899acpi_ut_copy_iobject_to_iobject (
900 union acpi_operand_object *source_desc,
901 union acpi_operand_object **dest_desc,
902 struct acpi_walk_state *walk_state)
903{
904 acpi_status status = AE_OK;
905
906
907 ACPI_FUNCTION_TRACE ("ut_copy_iobject_to_iobject");
908
909
910 /* Create the top level object */
911
912 *dest_desc = acpi_ut_create_internal_object (ACPI_GET_OBJECT_TYPE (source_desc));
913 if (!*dest_desc) {
914 return_ACPI_STATUS (AE_NO_MEMORY);
915 }
916
917 /* Copy the object and possible subobjects */
918
919 if (ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_PACKAGE) {
920 status = acpi_ut_copy_ipackage_to_ipackage (source_desc, *dest_desc,
921 walk_state);
922 }
923 else {
924 status = acpi_ut_copy_simple_object (source_desc, *dest_desc);
925 }
926
927 return_ACPI_STATUS (status);
928}
929
930
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
new file mode 100644
index 000000000000..985c5d045b78
--- /dev/null
+++ b/drivers/acpi/utilities/utdebug.c
@@ -0,0 +1,624 @@
1/******************************************************************************
2 *
3 * Module Name: utdebug - Debug print routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <linux/module.h>
45
46#include <acpi/acpi.h>
47
48#define _COMPONENT ACPI_UTILITIES
49 ACPI_MODULE_NAME ("utdebug")
50
51
52#ifdef ACPI_DEBUG_OUTPUT
53
54static u32 acpi_gbl_prev_thread_id = 0xFFFFFFFF;
55static char *acpi_gbl_fn_entry_str = "----Entry";
56static char *acpi_gbl_fn_exit_str = "----Exit-";
57
58
59/*****************************************************************************
60 *
61 * FUNCTION: acpi_ut_init_stack_ptr_trace
62 *
63 * PARAMETERS: None
64 *
65 * RETURN: None
66 *
67 * DESCRIPTION: Save the current stack pointer
68 *
69 ****************************************************************************/
70
71void
72acpi_ut_init_stack_ptr_trace (
73 void)
74{
75 u32 current_sp;
76
77
78 acpi_gbl_entry_stack_pointer = ACPI_PTR_DIFF (&current_sp, NULL);
79}
80
81
82/*****************************************************************************
83 *
84 * FUNCTION: acpi_ut_track_stack_ptr
85 *
86 * PARAMETERS: None
87 *
88 * RETURN: None
89 *
90 * DESCRIPTION: Save the current stack pointer
91 *
92 ****************************************************************************/
93
94void
95acpi_ut_track_stack_ptr (
96 void)
97{
98 acpi_size current_sp;
99
100
101 current_sp = ACPI_PTR_DIFF (&current_sp, NULL);
102
103 if (current_sp < acpi_gbl_lowest_stack_pointer) {
104 acpi_gbl_lowest_stack_pointer = current_sp;
105 }
106
107 if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) {
108 acpi_gbl_deepest_nesting = acpi_gbl_nesting_level;
109 }
110}
111
112
113/*****************************************************************************
114 *
115 * FUNCTION: acpi_ut_debug_print
116 *
117 * PARAMETERS: debug_level - Requested debug print level
118 * proc_name - Caller's procedure name
119 * module_name - Caller's module name (for error output)
120 * line_number - Caller's line number (for error output)
121 * component_id - Caller's component ID (for error output)
122 *
123 * Format - Printf format field
124 * ... - Optional printf arguments
125 *
126 * RETURN: None
127 *
128 * DESCRIPTION: Print error message with prefix consisting of the module name,
129 * line number, and component ID.
130 *
131 ****************************************************************************/
132
133void ACPI_INTERNAL_VAR_XFACE
134acpi_ut_debug_print (
135 u32 requested_debug_level,
136 u32 line_number,
137 struct acpi_debug_print_info *dbg_info,
138 char *format,
139 ...)
140{
141 u32 thread_id;
142 va_list args;
143
144
145 /*
146 * Stay silent if the debug level or component ID is disabled
147 */
148 if (!(requested_debug_level & acpi_dbg_level) ||
149 !(dbg_info->component_id & acpi_dbg_layer)) {
150 return;
151 }
152
153 /*
154 * Thread tracking and context switch notification
155 */
156 thread_id = acpi_os_get_thread_id ();
157
158 if (thread_id != acpi_gbl_prev_thread_id) {
159 if (ACPI_LV_THREADS & acpi_dbg_level) {
160 acpi_os_printf ("\n**** Context Switch from TID %X to TID %X ****\n\n",
161 acpi_gbl_prev_thread_id, thread_id);
162 }
163
164 acpi_gbl_prev_thread_id = thread_id;
165 }
166
167 /*
168 * Display the module name, current line number, thread ID (if requested),
169 * current procedure nesting level, and the current procedure name
170 */
171 acpi_os_printf ("%8s-%04ld ", dbg_info->module_name, line_number);
172
173 if (ACPI_LV_THREADS & acpi_dbg_level) {
174 acpi_os_printf ("[%04lX] ", thread_id);
175 }
176
177 acpi_os_printf ("[%02ld] %-22.22s: ", acpi_gbl_nesting_level, dbg_info->proc_name);
178
179 va_start (args, format);
180 acpi_os_vprintf (format, args);
181}
182EXPORT_SYMBOL(acpi_ut_debug_print);
183
184
185/*****************************************************************************
186 *
187 * FUNCTION: acpi_ut_debug_print_raw
188 *
189 * PARAMETERS: requested_debug_level - Requested debug print level
190 * line_number - Caller's line number
191 * dbg_info - Contains:
192 * proc_name - Caller's procedure name
193 * module_name - Caller's module name
194 * component_id - Caller's component ID
195 * Format - Printf format field
196 * ... - Optional printf arguments
197 *
198 * RETURN: None
199 *
200 * DESCRIPTION: Print message with no headers. Has same interface as
201 * debug_print so that the same macros can be used.
202 *
203 ****************************************************************************/
204
205void ACPI_INTERNAL_VAR_XFACE
206acpi_ut_debug_print_raw (
207 u32 requested_debug_level,
208 u32 line_number,
209 struct acpi_debug_print_info *dbg_info,
210 char *format,
211 ...)
212{
213 va_list args;
214
215
216 if (!(requested_debug_level & acpi_dbg_level) ||
217 !(dbg_info->component_id & acpi_dbg_layer)) {
218 return;
219 }
220
221 va_start (args, format);
222 acpi_os_vprintf (format, args);
223}
224EXPORT_SYMBOL(acpi_ut_debug_print_raw);
225
226
227/*****************************************************************************
228 *
229 * FUNCTION: acpi_ut_trace
230 *
231 * PARAMETERS: line_number - Caller's line number
232 * dbg_info - Contains:
233 * proc_name - Caller's procedure name
234 * module_name - Caller's module name
235 * component_id - Caller's component ID
236 *
237 * RETURN: None
238 *
239 * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
240 * set in debug_level
241 *
242 ****************************************************************************/
243
244void
245acpi_ut_trace (
246 u32 line_number,
247 struct acpi_debug_print_info *dbg_info)
248{
249
250 acpi_gbl_nesting_level++;
251 acpi_ut_track_stack_ptr ();
252
253 acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
254 "%s\n", acpi_gbl_fn_entry_str);
255}
256EXPORT_SYMBOL(acpi_ut_trace);
257
258
259/*****************************************************************************
260 *
261 * FUNCTION: acpi_ut_trace_ptr
262 *
263 * PARAMETERS: line_number - Caller's line number
264 * dbg_info - Contains:
265 * proc_name - Caller's procedure name
266 * module_name - Caller's module name
267 * component_id - Caller's component ID
268 * Pointer - Pointer to display
269 *
270 * RETURN: None
271 *
272 * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
273 * set in debug_level
274 *
275 ****************************************************************************/
276
277void
278acpi_ut_trace_ptr (
279 u32 line_number,
280 struct acpi_debug_print_info *dbg_info,
281 void *pointer)
282{
283 acpi_gbl_nesting_level++;
284 acpi_ut_track_stack_ptr ();
285
286 acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
287 "%s %p\n", acpi_gbl_fn_entry_str, pointer);
288}
289
290
291/*****************************************************************************
292 *
293 * FUNCTION: acpi_ut_trace_str
294 *
295 * PARAMETERS: line_number - Caller's line number
296 * dbg_info - Contains:
297 * proc_name - Caller's procedure name
298 * module_name - Caller's module name
299 * component_id - Caller's component ID
300 * String - Additional string to display
301 *
302 * RETURN: None
303 *
304 * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
305 * set in debug_level
306 *
307 ****************************************************************************/
308
309void
310acpi_ut_trace_str (
311 u32 line_number,
312 struct acpi_debug_print_info *dbg_info,
313 char *string)
314{
315
316 acpi_gbl_nesting_level++;
317 acpi_ut_track_stack_ptr ();
318
319 acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
320 "%s %s\n", acpi_gbl_fn_entry_str, string);
321}
322
323
324/*****************************************************************************
325 *
326 * FUNCTION: acpi_ut_trace_u32
327 *
328 * PARAMETERS: line_number - Caller's line number
329 * dbg_info - Contains:
330 * proc_name - Caller's procedure name
331 * module_name - Caller's module name
332 * component_id - Caller's component ID
333 * Integer - Integer to display
334 *
335 * RETURN: None
336 *
337 * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
338 * set in debug_level
339 *
340 ****************************************************************************/
341
342void
343acpi_ut_trace_u32 (
344 u32 line_number,
345 struct acpi_debug_print_info *dbg_info,
346 u32 integer)
347{
348
349 acpi_gbl_nesting_level++;
350 acpi_ut_track_stack_ptr ();
351
352 acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
353 "%s %08X\n", acpi_gbl_fn_entry_str, integer);
354}
355
356
357/*****************************************************************************
358 *
359 * FUNCTION: acpi_ut_exit
360 *
361 * PARAMETERS: line_number - Caller's line number
362 * dbg_info - Contains:
363 * proc_name - Caller's procedure name
364 * module_name - Caller's module name
365 * component_id - Caller's component ID
366 *
367 * RETURN: None
368 *
369 * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
370 * set in debug_level
371 *
372 ****************************************************************************/
373
374void
375acpi_ut_exit (
376 u32 line_number,
377 struct acpi_debug_print_info *dbg_info)
378{
379
380 acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
381 "%s\n", acpi_gbl_fn_exit_str);
382
383 acpi_gbl_nesting_level--;
384}
385EXPORT_SYMBOL(acpi_ut_exit);
386
387
388/*****************************************************************************
389 *
390 * FUNCTION: acpi_ut_status_exit
391 *
392 * PARAMETERS: line_number - Caller's line number
393 * dbg_info - Contains:
394 * proc_name - Caller's procedure name
395 * module_name - Caller's module name
396 * component_id - Caller's component ID
397 * Status - Exit status code
398 *
399 * RETURN: None
400 *
401 * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
402 * set in debug_level. Prints exit status also.
403 *
404 ****************************************************************************/
405
406void
407acpi_ut_status_exit (
408 u32 line_number,
409 struct acpi_debug_print_info *dbg_info,
410 acpi_status status)
411{
412
413 if (ACPI_SUCCESS (status)) {
414 acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
415 "%s %s\n", acpi_gbl_fn_exit_str,
416 acpi_format_exception (status));
417 }
418 else {
419 acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
420 "%s ****Exception****: %s\n", acpi_gbl_fn_exit_str,
421 acpi_format_exception (status));
422 }
423
424 acpi_gbl_nesting_level--;
425}
426EXPORT_SYMBOL(acpi_ut_status_exit);
427
428
429/*****************************************************************************
430 *
431 * FUNCTION: acpi_ut_value_exit
432 *
433 * PARAMETERS: line_number - Caller's line number
434 * dbg_info - Contains:
435 * proc_name - Caller's procedure name
436 * module_name - Caller's module name
437 * component_id - Caller's component ID
438 * Value - Value to be printed with exit msg
439 *
440 * RETURN: None
441 *
442 * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
443 * set in debug_level. Prints exit value also.
444 *
445 ****************************************************************************/
446
447void
448acpi_ut_value_exit (
449 u32 line_number,
450 struct acpi_debug_print_info *dbg_info,
451 acpi_integer value)
452{
453
454 acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
455 "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str,
456 ACPI_FORMAT_UINT64 (value));
457
458 acpi_gbl_nesting_level--;
459}
460EXPORT_SYMBOL(acpi_ut_value_exit);
461
462
463/*****************************************************************************
464 *
465 * FUNCTION: acpi_ut_ptr_exit
466 *
467 * PARAMETERS: line_number - Caller's line number
468 * dbg_info - Contains:
469 * proc_name - Caller's procedure name
470 * module_name - Caller's module name
471 * component_id - Caller's component ID
472 * Value - Value to be printed with exit msg
473 *
474 * RETURN: None
475 *
476 * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
477 * set in debug_level. Prints exit value also.
478 *
479 ****************************************************************************/
480
481void
482acpi_ut_ptr_exit (
483 u32 line_number,
484 struct acpi_debug_print_info *dbg_info,
485 u8 *ptr)
486{
487
488 acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
489 "%s %p\n", acpi_gbl_fn_exit_str, ptr);
490
491 acpi_gbl_nesting_level--;
492}
493
494#endif
495
496
497/*****************************************************************************
498 *
499 * FUNCTION: acpi_ut_dump_buffer
500 *
501 * PARAMETERS: Buffer - Buffer to dump
502 * Count - Amount to dump, in bytes
503 * Display - BYTE, WORD, DWORD, or QWORD display
504 * component_iD - Caller's component ID
505 *
506 * RETURN: None
507 *
508 * DESCRIPTION: Generic dump buffer in both hex and ascii.
509 *
510 ****************************************************************************/
511
512void
513acpi_ut_dump_buffer (
514 u8 *buffer,
515 u32 count,
516 u32 display,
517 u32 component_id)
518{
519 acpi_native_uint i = 0;
520 acpi_native_uint j;
521 u32 temp32;
522 u8 buf_char;
523
524
525 /* Only dump the buffer if tracing is enabled */
526
527 if (!((ACPI_LV_TABLES & acpi_dbg_level) &&
528 (component_id & acpi_dbg_layer))) {
529 return;
530 }
531
532 if ((count < 4) || (count & 0x01)) {
533 display = DB_BYTE_DISPLAY;
534 }
535
536 acpi_os_printf ("\nOffset Value\n");
537
538 /*
539 * Nasty little dump buffer routine!
540 */
541 while (i < count) {
542 /* Print current offset */
543
544 acpi_os_printf ("%05X ", (u32) i);
545
546 /* Print 16 hex chars */
547
548 for (j = 0; j < 16;) {
549 if (i + j >= count) {
550 acpi_os_printf ("\n");
551 return;
552 }
553
554 /* Make sure that the s8 doesn't get sign-extended! */
555
556 switch (display) {
557 /* Default is BYTE display */
558
559 default:
560
561 acpi_os_printf ("%02X ",
562 *((u8 *) &buffer[i + j]));
563 j += 1;
564 break;
565
566
567 case DB_WORD_DISPLAY:
568
569 ACPI_MOVE_16_TO_32 (&temp32, &buffer[i + j]);
570 acpi_os_printf ("%04X ", temp32);
571 j += 2;
572 break;
573
574
575 case DB_DWORD_DISPLAY:
576
577 ACPI_MOVE_32_TO_32 (&temp32, &buffer[i + j]);
578 acpi_os_printf ("%08X ", temp32);
579 j += 4;
580 break;
581
582
583 case DB_QWORD_DISPLAY:
584
585 ACPI_MOVE_32_TO_32 (&temp32, &buffer[i + j]);
586 acpi_os_printf ("%08X", temp32);
587
588 ACPI_MOVE_32_TO_32 (&temp32, &buffer[i + j + 4]);
589 acpi_os_printf ("%08X ", temp32);
590 j += 8;
591 break;
592 }
593 }
594
595 /*
596 * Print the ASCII equivalent characters
597 * But watch out for the bad unprintable ones...
598 */
599 for (j = 0; j < 16; j++) {
600 if (i + j >= count) {
601 acpi_os_printf ("\n");
602 return;
603 }
604
605 buf_char = buffer[i + j];
606 if ((buf_char > 0x1F && buf_char < 0x2E) ||
607 (buf_char > 0x2F && buf_char < 0x61) ||
608 (buf_char > 0x60 && buf_char < 0x7F)) {
609 acpi_os_printf ("%c", buf_char);
610 }
611 else {
612 acpi_os_printf (".");
613 }
614 }
615
616 /* Done with that line. */
617
618 acpi_os_printf ("\n");
619 i += 16;
620 }
621
622 return;
623}
624
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
new file mode 100644
index 000000000000..9a52ad52a23a
--- /dev/null
+++ b/drivers/acpi/utilities/utdelete.c
@@ -0,0 +1,700 @@
1/*******************************************************************************
2 *
3 * Module Name: utdelete - object deletion and reference count utilities
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acinterp.h>
47#include <acpi/acnamesp.h>
48#include <acpi/acevents.h>
49#include <acpi/amlcode.h>
50
51#define _COMPONENT ACPI_UTILITIES
52 ACPI_MODULE_NAME ("utdelete")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION: acpi_ut_delete_internal_obj
58 *
59 * PARAMETERS: *Object - Pointer to the list to be deleted
60 *
61 * RETURN: None
62 *
63 * DESCRIPTION: Low level object deletion, after reference counts have been
64 * updated (All reference counts, including sub-objects!)
65 *
66 ******************************************************************************/
67
68void
69acpi_ut_delete_internal_obj (
70 union acpi_operand_object *object)
71{
72 void *obj_pointer = NULL;
73 union acpi_operand_object *handler_desc;
74 union acpi_operand_object *second_desc;
75 union acpi_operand_object *next_desc;
76
77
78 ACPI_FUNCTION_TRACE_PTR ("ut_delete_internal_obj", object);
79
80
81 if (!object) {
82 return_VOID;
83 }
84
85 /*
86 * Must delete or free any pointers within the object that are not
87 * actual ACPI objects (for example, a raw buffer pointer).
88 */
89 switch (ACPI_GET_OBJECT_TYPE (object)) {
90 case ACPI_TYPE_STRING:
91
92 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n",
93 object, object->string.pointer));
94
95 /* Free the actual string buffer */
96
97 if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) {
98 /* But only if it is NOT a pointer into an ACPI table */
99
100 obj_pointer = object->string.pointer;
101 }
102 break;
103
104
105 case ACPI_TYPE_BUFFER:
106
107 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n",
108 object, object->buffer.pointer));
109
110 /* Free the actual buffer */
111
112 if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) {
113 /* But only if it is NOT a pointer into an ACPI table */
114
115 obj_pointer = object->buffer.pointer;
116 }
117 break;
118
119
120 case ACPI_TYPE_PACKAGE:
121
122 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n",
123 object->package.count));
124
125 /*
126 * Elements of the package are not handled here, they are deleted
127 * separately
128 */
129
130 /* Free the (variable length) element pointer array */
131
132 obj_pointer = object->package.elements;
133 break;
134
135
136 case ACPI_TYPE_DEVICE:
137
138 if (object->device.gpe_block) {
139 (void) acpi_ev_delete_gpe_block (object->device.gpe_block);
140 }
141
142 /* Walk the handler list for this device */
143
144 handler_desc = object->device.handler;
145 while (handler_desc) {
146 next_desc = handler_desc->address_space.next;
147 acpi_ut_remove_reference (handler_desc);
148 handler_desc = next_desc;
149 }
150 break;
151
152
153 case ACPI_TYPE_MUTEX:
154
155 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Mutex %p, Semaphore %p\n",
156 object, object->mutex.semaphore));
157
158 acpi_ex_unlink_mutex (object);
159 (void) acpi_os_delete_semaphore (object->mutex.semaphore);
160 break;
161
162
163 case ACPI_TYPE_EVENT:
164
165 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Event %p, Semaphore %p\n",
166 object, object->event.semaphore));
167
168 (void) acpi_os_delete_semaphore (object->event.semaphore);
169 object->event.semaphore = NULL;
170 break;
171
172
173 case ACPI_TYPE_METHOD:
174
175 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Method %p\n", object));
176
177 /* Delete the method semaphore if it exists */
178
179 if (object->method.semaphore) {
180 (void) acpi_os_delete_semaphore (object->method.semaphore);
181 object->method.semaphore = NULL;
182 }
183 break;
184
185
186 case ACPI_TYPE_REGION:
187
188 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Region %p\n", object));
189
190 second_desc = acpi_ns_get_secondary_object (object);
191 if (second_desc) {
192 /*
193 * Free the region_context if and only if the handler is one of the
194 * default handlers -- and therefore, we created the context object
195 * locally, it was not created by an external caller.
196 */
197 handler_desc = object->region.handler;
198 if (handler_desc) {
199 if (handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
200 obj_pointer = second_desc->extra.region_context;
201 }
202
203 acpi_ut_remove_reference (handler_desc);
204 }
205
206 /* Now we can free the Extra object */
207
208 acpi_ut_delete_object_desc (second_desc);
209 }
210 break;
211
212
213 case ACPI_TYPE_BUFFER_FIELD:
214
215 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Buffer Field %p\n", object));
216
217 second_desc = acpi_ns_get_secondary_object (object);
218 if (second_desc) {
219 acpi_ut_delete_object_desc (second_desc);
220 }
221 break;
222
223
224 default:
225 break;
226 }
227
228 /* Free any allocated memory (pointer within the object) found above */
229
230 if (obj_pointer) {
231 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n",
232 obj_pointer));
233 ACPI_MEM_FREE (obj_pointer);
234 }
235
236 /* Now the object can be safely deleted */
237
238 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
239 object, acpi_ut_get_object_type_name (object)));
240
241 acpi_ut_delete_object_desc (object);
242 return_VOID;
243}
244
245
246/*******************************************************************************
247 *
248 * FUNCTION: acpi_ut_delete_internal_object_list
249 *
250 * PARAMETERS: *obj_list - Pointer to the list to be deleted
251 *
252 * RETURN: None
253 *
254 * DESCRIPTION: This function deletes an internal object list, including both
255 * simple objects and package objects
256 *
257 ******************************************************************************/
258
259void
260acpi_ut_delete_internal_object_list (
261 union acpi_operand_object **obj_list)
262{
263 union acpi_operand_object **internal_obj;
264
265
266 ACPI_FUNCTION_TRACE ("ut_delete_internal_object_list");
267
268
269 /* Walk the null-terminated internal list */
270
271 for (internal_obj = obj_list; *internal_obj; internal_obj++) {
272 acpi_ut_remove_reference (*internal_obj);
273 }
274
275 /* Free the combined parameter pointer list and object array */
276
277 ACPI_MEM_FREE (obj_list);
278 return_VOID;
279}
280
281
282/*******************************************************************************
283 *
284 * FUNCTION: acpi_ut_update_ref_count
285 *
286 * PARAMETERS: *Object - Object whose ref count is to be updated
287 * Action - What to do
288 *
289 * RETURN: New ref count
290 *
291 * DESCRIPTION: Modify the ref count and return it.
292 *
293 ******************************************************************************/
294
295static void
296acpi_ut_update_ref_count (
297 union acpi_operand_object *object,
298 u32 action)
299{
300 u16 count;
301 u16 new_count;
302
303
304 ACPI_FUNCTION_NAME ("ut_update_ref_count");
305
306
307 if (!object) {
308 return;
309 }
310
311 count = object->common.reference_count;
312 new_count = count;
313
314 /*
315 * Perform the reference count action (increment, decrement, or force delete)
316 */
317 switch (action) {
318
319 case REF_INCREMENT:
320
321 new_count++;
322 object->common.reference_count = new_count;
323
324 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, [Incremented]\n",
325 object, new_count));
326 break;
327
328
329 case REF_DECREMENT:
330
331 if (count < 1) {
332 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, can't decrement! (Set to 0)\n",
333 object, new_count));
334
335 new_count = 0;
336 }
337 else {
338 new_count--;
339
340 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, [Decremented]\n",
341 object, new_count));
342 }
343
344 if (ACPI_GET_OBJECT_TYPE (object) == ACPI_TYPE_METHOD) {
345 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Method Obj %p Refs=%X, [Decremented]\n",
346 object, new_count));
347 }
348
349 object->common.reference_count = new_count;
350 if (new_count == 0) {
351 acpi_ut_delete_internal_obj (object);
352 }
353
354 break;
355
356
357 case REF_FORCE_DELETE:
358
359 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, Force delete! (Set to 0)\n",
360 object, count));
361
362 new_count = 0;
363 object->common.reference_count = new_count;
364 acpi_ut_delete_internal_obj (object);
365 break;
366
367
368 default:
369
370 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown action (%X)\n", action));
371 break;
372 }
373
374 /*
375 * Sanity check the reference count, for debug purposes only.
376 * (A deleted object will have a huge reference count)
377 */
378 if (count > ACPI_MAX_REFERENCE_COUNT) {
379
380 ACPI_DEBUG_PRINT ((ACPI_DB_WARN,
381 "**** Warning **** Large Reference Count (%X) in object %p\n\n",
382 count, object));
383 }
384
385 return;
386}
387
388
389/*******************************************************************************
390 *
391 * FUNCTION: acpi_ut_update_object_reference
392 *
393 * PARAMETERS: *Object - Increment ref count for this object
394 * and all sub-objects
395 * Action - Either REF_INCREMENT or REF_DECREMENT or
396 * REF_FORCE_DELETE
397 *
398 * RETURN: Status
399 *
400 * DESCRIPTION: Increment the object reference count
401 *
402 * Object references are incremented when:
403 * 1) An object is attached to a Node (namespace object)
404 * 2) An object is copied (all subobjects must be incremented)
405 *
406 * Object references are decremented when:
407 * 1) An object is detached from an Node
408 *
409 ******************************************************************************/
410
411acpi_status
412acpi_ut_update_object_reference (
413 union acpi_operand_object *object,
414 u16 action)
415{
416 acpi_status status;
417 u32 i;
418 union acpi_generic_state *state_list = NULL;
419 union acpi_generic_state *state;
420 union acpi_operand_object *tmp;
421
422 ACPI_FUNCTION_TRACE_PTR ("ut_update_object_reference", object);
423
424
425 /* Ignore a null object ptr */
426
427 if (!object) {
428 return_ACPI_STATUS (AE_OK);
429 }
430
431 /* Make sure that this isn't a namespace handle */
432
433 if (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) {
434 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p is NS handle\n", object));
435 return_ACPI_STATUS (AE_OK);
436 }
437
438 state = acpi_ut_create_update_state (object, action);
439
440 while (state) {
441 object = state->update.object;
442 action = state->update.value;
443 acpi_ut_delete_generic_state (state);
444
445 /*
446 * All sub-objects must have their reference count incremented also.
447 * Different object types have different subobjects.
448 */
449 switch (ACPI_GET_OBJECT_TYPE (object)) {
450 case ACPI_TYPE_DEVICE:
451
452 tmp = object->device.system_notify;
453 if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
454 object->device.system_notify = NULL;
455 acpi_ut_update_ref_count (tmp, action);
456
457 tmp = object->device.device_notify;
458 if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
459 object->device.device_notify = NULL;
460 acpi_ut_update_ref_count (tmp, action);
461
462 break;
463
464
465 case ACPI_TYPE_PACKAGE:
466
467 /*
468 * We must update all the sub-objects of the package
469 * (Each of whom may have their own sub-objects, etc.
470 */
471 for (i = 0; i < object->package.count; i++) {
472 /*
473 * Push each element onto the stack for later processing.
474 * Note: There can be null elements within the package,
475 * these are simply ignored
476 */
477 status = acpi_ut_create_update_state_and_push (
478 object->package.elements[i], action, &state_list);
479 if (ACPI_FAILURE (status)) {
480 goto error_exit;
481 }
482
483 tmp = object->package.elements[i];
484 if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
485 object->package.elements[i] = NULL;
486 }
487 break;
488
489
490 case ACPI_TYPE_BUFFER_FIELD:
491
492 status = acpi_ut_create_update_state_and_push (
493 object->buffer_field.buffer_obj, action, &state_list);
494 if (ACPI_FAILURE (status)) {
495 goto error_exit;
496 }
497
498 tmp = object->buffer_field.buffer_obj;
499 if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
500 object->buffer_field.buffer_obj = NULL;
501 break;
502
503
504 case ACPI_TYPE_LOCAL_REGION_FIELD:
505
506 status = acpi_ut_create_update_state_and_push (
507 object->field.region_obj, action, &state_list);
508 if (ACPI_FAILURE (status)) {
509 goto error_exit;
510 }
511
512 tmp = object->field.region_obj;
513 if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
514 object->field.region_obj = NULL;
515 break;
516
517
518 case ACPI_TYPE_LOCAL_BANK_FIELD:
519
520 status = acpi_ut_create_update_state_and_push (
521 object->bank_field.bank_obj, action, &state_list);
522 if (ACPI_FAILURE (status)) {
523 goto error_exit;
524 }
525
526 tmp = object->bank_field.bank_obj;
527 if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
528 object->bank_field.bank_obj = NULL;
529
530 status = acpi_ut_create_update_state_and_push (
531 object->bank_field.region_obj, action, &state_list);
532 if (ACPI_FAILURE (status)) {
533 goto error_exit;
534 }
535
536 tmp = object->bank_field.region_obj;
537 if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
538 object->bank_field.region_obj = NULL;
539 break;
540
541
542 case ACPI_TYPE_LOCAL_INDEX_FIELD:
543
544 status = acpi_ut_create_update_state_and_push (
545 object->index_field.index_obj, action, &state_list);
546 if (ACPI_FAILURE (status)) {
547 goto error_exit;
548 }
549
550 tmp = object->index_field.index_obj;
551 if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
552 object->index_field.index_obj = NULL;
553
554 status = acpi_ut_create_update_state_and_push (
555 object->index_field.data_obj, action, &state_list);
556 if (ACPI_FAILURE (status)) {
557 goto error_exit;
558 }
559
560 tmp = object->index_field.data_obj;
561 if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
562 object->index_field.data_obj = NULL;
563 break;
564
565
566 case ACPI_TYPE_LOCAL_REFERENCE:
567
568 /*
569 * The target of an Index (a package, string, or buffer) must track
570 * changes to the ref count of the index.
571 */
572 if (object->reference.opcode == AML_INDEX_OP) {
573 status = acpi_ut_create_update_state_and_push (
574 object->reference.object, action, &state_list);
575 if (ACPI_FAILURE (status)) {
576 goto error_exit;
577 }
578 }
579 break;
580
581
582 case ACPI_TYPE_REGION:
583 default:
584
585 /* No subobjects */
586 break;
587 }
588
589 /*
590 * Now we can update the count in the main object. This can only
591 * happen after we update the sub-objects in case this causes the
592 * main object to be deleted.
593 */
594 acpi_ut_update_ref_count (object, action);
595
596 /* Move on to the next object to be updated */
597
598 state = acpi_ut_pop_generic_state (&state_list);
599 }
600
601 return_ACPI_STATUS (AE_OK);
602
603
604error_exit:
605
606 ACPI_REPORT_ERROR (("Could not update object reference count, %s\n",
607 acpi_format_exception (status)));
608
609 return_ACPI_STATUS (status);
610}
611
612
613/*******************************************************************************
614 *
615 * FUNCTION: acpi_ut_add_reference
616 *
617 * PARAMETERS: *Object - Object whose reference count is to be
618 * incremented
619 *
620 * RETURN: None
621 *
622 * DESCRIPTION: Add one reference to an ACPI object
623 *
624 ******************************************************************************/
625
626void
627acpi_ut_add_reference (
628 union acpi_operand_object *object)
629{
630
631 ACPI_FUNCTION_TRACE_PTR ("ut_add_reference", object);
632
633
634 /* Ensure that we have a valid object */
635
636 if (!acpi_ut_valid_internal_object (object)) {
637 return_VOID;
638 }
639
640 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
641 "Obj %p Current Refs=%X [To Be Incremented]\n",
642 object, object->common.reference_count));
643
644 /* Increment the reference count */
645
646 (void) acpi_ut_update_object_reference (object, REF_INCREMENT);
647 return_VOID;
648}
649
650
651/*******************************************************************************
652 *
653 * FUNCTION: acpi_ut_remove_reference
654 *
655 * PARAMETERS: *Object - Object whose ref count will be decremented
656 *
657 * RETURN: None
658 *
659 * DESCRIPTION: Decrement the reference count of an ACPI internal object
660 *
661 ******************************************************************************/
662
663void
664acpi_ut_remove_reference (
665 union acpi_operand_object *object)
666{
667
668 ACPI_FUNCTION_TRACE_PTR ("ut_remove_reference", object);
669
670
671 /*
672 * Allow a NULL pointer to be passed in, just ignore it. This saves
673 * each caller from having to check. Also, ignore NS nodes.
674 *
675 */
676 if (!object ||
677 (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED)) {
678 return_VOID;
679 }
680
681 /* Ensure that we have a valid object */
682
683 if (!acpi_ut_valid_internal_object (object)) {
684 return_VOID;
685 }
686
687 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
688 "Obj %p Current Refs=%X [To Be Decremented]\n",
689 object, object->common.reference_count));
690
691 /*
692 * Decrement the reference count, and only actually delete the object
693 * if the reference count becomes 0. (Must also decrement the ref count
694 * of all subobjects!)
695 */
696 (void) acpi_ut_update_object_reference (object, REF_DECREMENT);
697 return_VOID;
698}
699
700
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
new file mode 100644
index 000000000000..ead27d2c4d18
--- /dev/null
+++ b/drivers/acpi/utilities/uteval.c
@@ -0,0 +1,696 @@
1/******************************************************************************
2 *
3 * Module Name: uteval - Object evaluation
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acinterp.h>
48
49
50#define _COMPONENT ACPI_UTILITIES
51 ACPI_MODULE_NAME ("uteval")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ut_osi_implementation
57 *
58 * PARAMETERS: walk_state - Current walk state
59 *
60 * RETURN: Status
61 *
62 * DESCRIPTION: Implementation of _OSI predefined control method
63 * Supported = _OSI (String)
64 *
65 ******************************************************************************/
66
67acpi_status
68acpi_ut_osi_implementation (
69 struct acpi_walk_state *walk_state)
70{
71 union acpi_operand_object *string_desc;
72 union acpi_operand_object *return_desc;
73 acpi_native_uint i;
74
75
76 ACPI_FUNCTION_TRACE ("ut_osi_implementation");
77
78
79 /* Validate the string input argument */
80
81 string_desc = walk_state->arguments[0].object;
82 if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
83 return_ACPI_STATUS (AE_TYPE);
84 }
85
86 /* Create a return object (Default value = 0) */
87
88 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
89 if (!return_desc) {
90 return_ACPI_STATUS (AE_NO_MEMORY);
91 }
92
93 /* Compare input string to table of supported strings */
94
95 for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) {
96 if (!ACPI_STRCMP (string_desc->string.pointer,
97 (char *) acpi_gbl_valid_osi_strings[i])) {
98 /* This string is supported */
99
100 return_desc->integer.value = 0xFFFFFFFF;
101 break;
102 }
103 }
104
105 walk_state->return_desc = return_desc;
106 return_ACPI_STATUS (AE_CTRL_TERMINATE);
107}
108
109
110/*******************************************************************************
111 *
112 * FUNCTION: acpi_ut_evaluate_object
113 *
114 * PARAMETERS: prefix_node - Starting node
115 * Path - Path to object from starting node
116 * expected_return_types - Bitmap of allowed return types
117 * return_desc - Where a return value is stored
118 *
119 * RETURN: Status
120 *
121 * DESCRIPTION: Evaluates a namespace object and verifies the type of the
122 * return object. Common code that simplifies accessing objects
123 * that have required return objects of fixed types.
124 *
125 * NOTE: Internal function, no parameter validation
126 *
127 ******************************************************************************/
128
129acpi_status
130acpi_ut_evaluate_object (
131 struct acpi_namespace_node *prefix_node,
132 char *path,
133 u32 expected_return_btypes,
134 union acpi_operand_object **return_desc)
135{
136 struct acpi_parameter_info info;
137 acpi_status status;
138 u32 return_btype;
139
140
141 ACPI_FUNCTION_TRACE ("ut_evaluate_object");
142
143
144 info.node = prefix_node;
145 info.parameters = NULL;
146 info.parameter_type = ACPI_PARAM_ARGS;
147
148 /* Evaluate the object/method */
149
150 status = acpi_ns_evaluate_relative (path, &info);
151 if (ACPI_FAILURE (status)) {
152 if (status == AE_NOT_FOUND) {
153 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n",
154 acpi_ut_get_node_name (prefix_node), path));
155 }
156 else {
157 ACPI_REPORT_METHOD_ERROR ("Method execution failed",
158 prefix_node, path, status);
159 }
160
161 return_ACPI_STATUS (status);
162 }
163
164 /* Did we get a return object? */
165
166 if (!info.return_object) {
167 if (expected_return_btypes) {
168 ACPI_REPORT_METHOD_ERROR ("No object was returned from",
169 prefix_node, path, AE_NOT_EXIST);
170
171 return_ACPI_STATUS (AE_NOT_EXIST);
172 }
173
174 return_ACPI_STATUS (AE_OK);
175 }
176
177 /* Map the return object type to the bitmapped type */
178
179 switch (ACPI_GET_OBJECT_TYPE (info.return_object)) {
180 case ACPI_TYPE_INTEGER:
181 return_btype = ACPI_BTYPE_INTEGER;
182 break;
183
184 case ACPI_TYPE_BUFFER:
185 return_btype = ACPI_BTYPE_BUFFER;
186 break;
187
188 case ACPI_TYPE_STRING:
189 return_btype = ACPI_BTYPE_STRING;
190 break;
191
192 case ACPI_TYPE_PACKAGE:
193 return_btype = ACPI_BTYPE_PACKAGE;
194 break;
195
196 default:
197 return_btype = 0;
198 break;
199 }
200
201 if ((acpi_gbl_enable_interpreter_slack) &&
202 (!expected_return_btypes)) {
203 /*
204 * We received a return object, but one was not expected. This can
205 * happen frequently if the "implicit return" feature is enabled.
206 * Just delete the return object and return AE_OK.
207 */
208 acpi_ut_remove_reference (info.return_object);
209 return_ACPI_STATUS (AE_OK);
210 }
211
212 /* Is the return object one of the expected types? */
213
214 if (!(expected_return_btypes & return_btype)) {
215 ACPI_REPORT_METHOD_ERROR ("Return object type is incorrect",
216 prefix_node, path, AE_TYPE);
217
218 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
219 "Type returned from %s was incorrect: %s, expected Btypes: %X\n",
220 path, acpi_ut_get_object_type_name (info.return_object),
221 expected_return_btypes));
222
223 /* On error exit, we must delete the return object */
224
225 acpi_ut_remove_reference (info.return_object);
226 return_ACPI_STATUS (AE_TYPE);
227 }
228
229 /* Object type is OK, return it */
230
231 *return_desc = info.return_object;
232 return_ACPI_STATUS (AE_OK);
233}
234
235
236/*******************************************************************************
237 *
238 * FUNCTION: acpi_ut_evaluate_numeric_object
239 *
240 * PARAMETERS: *object_name - Object name to be evaluated
241 * device_node - Node for the device
242 * *Address - Where the value is returned
243 *
244 * RETURN: Status
245 *
246 * DESCRIPTION: Evaluates a numeric namespace object for a selected device
247 * and stores result in *Address.
248 *
249 * NOTE: Internal function, no parameter validation
250 *
251 ******************************************************************************/
252
253acpi_status
254acpi_ut_evaluate_numeric_object (
255 char *object_name,
256 struct acpi_namespace_node *device_node,
257 acpi_integer *address)
258{
259 union acpi_operand_object *obj_desc;
260 acpi_status status;
261
262
263 ACPI_FUNCTION_TRACE ("ut_evaluate_numeric_object");
264
265
266 status = acpi_ut_evaluate_object (device_node, object_name,
267 ACPI_BTYPE_INTEGER, &obj_desc);
268 if (ACPI_FAILURE (status)) {
269 return_ACPI_STATUS (status);
270 }
271
272 /* Get the returned Integer */
273
274 *address = obj_desc->integer.value;
275
276 /* On exit, we must delete the return object */
277
278 acpi_ut_remove_reference (obj_desc);
279 return_ACPI_STATUS (status);
280}
281
282
283/*******************************************************************************
284 *
285 * FUNCTION: acpi_ut_copy_id_string
286 *
287 * PARAMETERS: Destination - Where to copy the string
288 * Source - Source string
289 * max_length - Length of the destination buffer
290 *
291 * RETURN: None
292 *
293 * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods.
294 * Performs removal of a leading asterisk if present -- workaround
295 * for a known issue on a bunch of machines.
296 *
297 ******************************************************************************/
298
299static void
300acpi_ut_copy_id_string (
301 char *destination,
302 char *source,
303 acpi_size max_length)
304{
305
306
307 /*
308 * Workaround for ID strings that have a leading asterisk. This construct
309 * is not allowed by the ACPI specification (ID strings must be
310 * alphanumeric), but enough existing machines have this embedded in their
311 * ID strings that the following code is useful.
312 */
313 if (*source == '*') {
314 source++;
315 }
316
317 /* Do the actual copy */
318
319 ACPI_STRNCPY (destination, source, max_length);
320}
321
322
323/*******************************************************************************
324 *
325 * FUNCTION: acpi_ut_execute_HID
326 *
327 * PARAMETERS: device_node - Node for the device
328 * *Hid - Where the HID is returned
329 *
330 * RETURN: Status
331 *
332 * DESCRIPTION: Executes the _HID control method that returns the hardware
333 * ID of the device.
334 *
335 * NOTE: Internal function, no parameter validation
336 *
337 ******************************************************************************/
338
339acpi_status
340acpi_ut_execute_HID (
341 struct acpi_namespace_node *device_node,
342 struct acpi_device_id *hid)
343{
344 union acpi_operand_object *obj_desc;
345 acpi_status status;
346
347
348 ACPI_FUNCTION_TRACE ("ut_execute_HID");
349
350
351 status = acpi_ut_evaluate_object (device_node, METHOD_NAME__HID,
352 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &obj_desc);
353 if (ACPI_FAILURE (status)) {
354 return_ACPI_STATUS (status);
355 }
356
357 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
358 /* Convert the Numeric HID to string */
359
360 acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, hid->value);
361 }
362 else {
363 /* Copy the String HID from the returned object */
364
365 acpi_ut_copy_id_string (hid->value, obj_desc->string.pointer,
366 sizeof (hid->value));
367 }
368
369 /* On exit, we must delete the return object */
370
371 acpi_ut_remove_reference (obj_desc);
372 return_ACPI_STATUS (status);
373}
374
375
376/*******************************************************************************
377 *
378 * FUNCTION: acpi_ut_translate_one_cid
379 *
380 * PARAMETERS: obj_desc - _CID object, must be integer or string
381 * one_cid - Where the CID string is returned
382 *
383 * RETURN: Status
384 *
385 * DESCRIPTION: Return a numeric or string _CID value as a string.
386 * (Compatible ID)
387 *
388 * NOTE: Assumes a maximum _CID string length of
389 * ACPI_MAX_CID_LENGTH.
390 *
391 ******************************************************************************/
392
393static acpi_status
394acpi_ut_translate_one_cid (
395 union acpi_operand_object *obj_desc,
396 struct acpi_compatible_id *one_cid)
397{
398
399
400 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
401 case ACPI_TYPE_INTEGER:
402
403 /* Convert the Numeric CID to string */
404
405 acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, one_cid->value);
406 return (AE_OK);
407
408 case ACPI_TYPE_STRING:
409
410 if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) {
411 return (AE_AML_STRING_LIMIT);
412 }
413
414 /* Copy the String CID from the returned object */
415
416 acpi_ut_copy_id_string (one_cid->value, obj_desc->string.pointer,
417 ACPI_MAX_CID_LENGTH);
418 return (AE_OK);
419
420 default:
421
422 return (AE_TYPE);
423 }
424}
425
426
427/*******************************************************************************
428 *
429 * FUNCTION: acpi_ut_execute_CID
430 *
431 * PARAMETERS: device_node - Node for the device
432 * *Cid - Where the CID is returned
433 *
434 * RETURN: Status
435 *
436 * DESCRIPTION: Executes the _CID control method that returns one or more
437 * compatible hardware IDs for the device.
438 *
439 * NOTE: Internal function, no parameter validation
440 *
441 ******************************************************************************/
442
443acpi_status
444acpi_ut_execute_CID (
445 struct acpi_namespace_node *device_node,
446 struct acpi_compatible_id_list **return_cid_list)
447{
448 union acpi_operand_object *obj_desc;
449 acpi_status status;
450 u32 count;
451 u32 size;
452 struct acpi_compatible_id_list *cid_list;
453 acpi_native_uint i;
454
455
456 ACPI_FUNCTION_TRACE ("ut_execute_CID");
457
458
459 /* Evaluate the _CID method for this device */
460
461 status = acpi_ut_evaluate_object (device_node, METHOD_NAME__CID,
462 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE,
463 &obj_desc);
464 if (ACPI_FAILURE (status)) {
465 return_ACPI_STATUS (status);
466 }
467
468 /* Get the number of _CIDs returned */
469
470 count = 1;
471 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
472 count = obj_desc->package.count;
473 }
474
475 /* Allocate a worst-case buffer for the _CIDs */
476
477 size = (((count - 1) * sizeof (struct acpi_compatible_id)) +
478 sizeof (struct acpi_compatible_id_list));
479
480 cid_list = ACPI_MEM_CALLOCATE ((acpi_size) size);
481 if (!cid_list) {
482 return_ACPI_STATUS (AE_NO_MEMORY);
483 }
484
485 /* Init CID list */
486
487 cid_list->count = count;
488 cid_list->size = size;
489
490 /*
491 * A _CID can return either a single compatible ID or a package of compatible
492 * IDs. Each compatible ID can be one of the following:
493 * -- Number (32 bit compressed EISA ID) or
494 * -- String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss").
495 */
496
497 /* The _CID object can be either a single CID or a package (list) of CIDs */
498
499 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
500 /* Translate each package element */
501
502 for (i = 0; i < count; i++) {
503 status = acpi_ut_translate_one_cid (obj_desc->package.elements[i],
504 &cid_list->id[i]);
505 if (ACPI_FAILURE (status)) {
506 break;
507 }
508 }
509 }
510 else {
511 /* Only one CID, translate to a string */
512
513 status = acpi_ut_translate_one_cid (obj_desc, cid_list->id);
514 }
515
516 /* Cleanup on error */
517
518 if (ACPI_FAILURE (status)) {
519 ACPI_MEM_FREE (cid_list);
520 }
521 else {
522 *return_cid_list = cid_list;
523 }
524
525 /* On exit, we must delete the _CID return object */
526
527 acpi_ut_remove_reference (obj_desc);
528 return_ACPI_STATUS (status);
529}
530
531
532/*******************************************************************************
533 *
534 * FUNCTION: acpi_ut_execute_UID
535 *
536 * PARAMETERS: device_node - Node for the device
537 * *Uid - Where the UID is returned
538 *
539 * RETURN: Status
540 *
541 * DESCRIPTION: Executes the _UID control method that returns the hardware
542 * ID of the device.
543 *
544 * NOTE: Internal function, no parameter validation
545 *
546 ******************************************************************************/
547
548acpi_status
549acpi_ut_execute_UID (
550 struct acpi_namespace_node *device_node,
551 struct acpi_device_id *uid)
552{
553 union acpi_operand_object *obj_desc;
554 acpi_status status;
555
556
557 ACPI_FUNCTION_TRACE ("ut_execute_UID");
558
559
560 status = acpi_ut_evaluate_object (device_node, METHOD_NAME__UID,
561 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &obj_desc);
562 if (ACPI_FAILURE (status)) {
563 return_ACPI_STATUS (status);
564 }
565
566 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
567 /* Convert the Numeric UID to string */
568
569 acpi_ex_unsigned_integer_to_string (obj_desc->integer.value, uid->value);
570 }
571 else {
572 /* Copy the String UID from the returned object */
573
574 acpi_ut_copy_id_string (uid->value, obj_desc->string.pointer,
575 sizeof (uid->value));
576 }
577
578 /* On exit, we must delete the return object */
579
580 acpi_ut_remove_reference (obj_desc);
581 return_ACPI_STATUS (status);
582}
583
584
585/*******************************************************************************
586 *
587 * FUNCTION: acpi_ut_execute_STA
588 *
589 * PARAMETERS: device_node - Node for the device
590 * *Flags - Where the status flags are returned
591 *
592 * RETURN: Status
593 *
594 * DESCRIPTION: Executes _STA for selected device and stores results in
595 * *Flags.
596 *
597 * NOTE: Internal function, no parameter validation
598 *
599 ******************************************************************************/
600
601acpi_status
602acpi_ut_execute_STA (
603 struct acpi_namespace_node *device_node,
604 u32 *flags)
605{
606 union acpi_operand_object *obj_desc;
607 acpi_status status;
608
609
610 ACPI_FUNCTION_TRACE ("ut_execute_STA");
611
612
613 status = acpi_ut_evaluate_object (device_node, METHOD_NAME__STA,
614 ACPI_BTYPE_INTEGER, &obj_desc);
615 if (ACPI_FAILURE (status)) {
616 if (AE_NOT_FOUND == status) {
617 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
618 "_STA on %4.4s was not found, assuming device is present\n",
619 acpi_ut_get_node_name (device_node)));
620
621 *flags = 0x0F;
622 status = AE_OK;
623 }
624
625 return_ACPI_STATUS (status);
626 }
627
628 /* Extract the status flags */
629
630 *flags = (u32) obj_desc->integer.value;
631
632 /* On exit, we must delete the return object */
633
634 acpi_ut_remove_reference (obj_desc);
635 return_ACPI_STATUS (status);
636}
637
638
639/*******************************************************************************
640 *
641 * FUNCTION: acpi_ut_execute_Sxds
642 *
643 * PARAMETERS: device_node - Node for the device
644 * *Flags - Where the status flags are returned
645 *
646 * RETURN: Status
647 *
648 * DESCRIPTION: Executes _STA for selected device and stores results in
649 * *Flags.
650 *
651 * NOTE: Internal function, no parameter validation
652 *
653 ******************************************************************************/
654
655acpi_status
656acpi_ut_execute_sxds (
657 struct acpi_namespace_node *device_node,
658 u8 *highest)
659{
660 union acpi_operand_object *obj_desc;
661 acpi_status status;
662 u32 i;
663
664
665 ACPI_FUNCTION_TRACE ("ut_execute_Sxds");
666
667
668 for (i = 0; i < 4; i++) {
669 highest[i] = 0xFF;
670 status = acpi_ut_evaluate_object (device_node,
671 (char *) acpi_gbl_highest_dstate_names[i],
672 ACPI_BTYPE_INTEGER, &obj_desc);
673 if (ACPI_FAILURE (status)) {
674 if (status != AE_NOT_FOUND) {
675 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
676 "%s on Device %4.4s, %s\n",
677 (char *) acpi_gbl_highest_dstate_names[i],
678 acpi_ut_get_node_name (device_node),
679 acpi_format_exception (status)));
680
681 return_ACPI_STATUS (status);
682 }
683 }
684 else {
685 /* Extract the Dstate value */
686
687 highest[i] = (u8) obj_desc->integer.value;
688
689 /* Delete the return object */
690
691 acpi_ut_remove_reference (obj_desc);
692 }
693 }
694
695 return_ACPI_STATUS (AE_OK);
696}
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
new file mode 100644
index 000000000000..25b0f8ae1bc6
--- /dev/null
+++ b/drivers/acpi/utilities/utglobal.c
@@ -0,0 +1,935 @@
1/******************************************************************************
2 *
3 * Module Name: utglobal - Global variables for the ACPI subsystem
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#define DEFINE_ACPI_GLOBALS
45
46#include <linux/module.h>
47
48#include <acpi/acpi.h>
49#include <acpi/acnamesp.h>
50
51#define _COMPONENT ACPI_UTILITIES
52 ACPI_MODULE_NAME ("utglobal")
53
54
55/******************************************************************************
56 *
57 * FUNCTION: acpi_format_exception
58 *
59 * PARAMETERS: Status - The acpi_status code to be formatted
60 *
61 * RETURN: A string containing the exception text
62 *
63 * DESCRIPTION: This function translates an ACPI exception into an ASCII string.
64 *
65 ******************************************************************************/
66
67const char *
68acpi_format_exception (
69 acpi_status status)
70{
71 const char *exception = "UNKNOWN_STATUS_CODE";
72 acpi_status sub_status;
73
74
75 ACPI_FUNCTION_NAME ("format_exception");
76
77
78 sub_status = (status & ~AE_CODE_MASK);
79
80 switch (status & AE_CODE_MASK) {
81 case AE_CODE_ENVIRONMENTAL:
82
83 if (sub_status <= AE_CODE_ENV_MAX) {
84 exception = acpi_gbl_exception_names_env [sub_status];
85 break;
86 }
87 goto unknown;
88
89 case AE_CODE_PROGRAMMER:
90
91 if (sub_status <= AE_CODE_PGM_MAX) {
92 exception = acpi_gbl_exception_names_pgm [sub_status -1];
93 break;
94 }
95 goto unknown;
96
97 case AE_CODE_ACPI_TABLES:
98
99 if (sub_status <= AE_CODE_TBL_MAX) {
100 exception = acpi_gbl_exception_names_tbl [sub_status -1];
101 break;
102 }
103 goto unknown;
104
105 case AE_CODE_AML:
106
107 if (sub_status <= AE_CODE_AML_MAX) {
108 exception = acpi_gbl_exception_names_aml [sub_status -1];
109 break;
110 }
111 goto unknown;
112
113 case AE_CODE_CONTROL:
114
115 if (sub_status <= AE_CODE_CTRL_MAX) {
116 exception = acpi_gbl_exception_names_ctrl [sub_status -1];
117 break;
118 }
119 goto unknown;
120
121 default:
122 goto unknown;
123 }
124
125
126 return ((const char *) exception);
127
128unknown:
129
130 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown exception code: 0x%8.8X\n", status));
131 return ((const char *) exception);
132}
133
134
135/******************************************************************************
136 *
137 * Static global variable initialization.
138 *
139 ******************************************************************************/
140
141/*
142 * We want the debug switches statically initialized so they
143 * are already set when the debugger is entered.
144 */
145
146/* Debug switch - level and trace mask */
147u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
148EXPORT_SYMBOL(acpi_dbg_level);
149
150/* Debug switch - layer (component) mask */
151
152u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
153EXPORT_SYMBOL(acpi_dbg_layer);
154u32 acpi_gbl_nesting_level = 0;
155
156
157/* Debugger globals */
158
159u8 acpi_gbl_db_terminate_threads = FALSE;
160u8 acpi_gbl_abort_method = FALSE;
161u8 acpi_gbl_method_executing = FALSE;
162
163/* System flags */
164
165u32 acpi_gbl_startup_flags = 0;
166
167/* System starts uninitialized */
168
169u8 acpi_gbl_shutdown = TRUE;
170
171const u8 acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128};
172
173const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] =
174{
175 "\\_S0_",
176 "\\_S1_",
177 "\\_S2_",
178 "\\_S3_",
179 "\\_S4_",
180 "\\_S5_"
181};
182
183const char *acpi_gbl_highest_dstate_names[4] =
184{
185 "_S1D",
186 "_S2D",
187 "_S3D",
188 "_S4D"
189};
190
191/*
192 * Strings supported by the _OSI predefined (internal) method.
193 * When adding strings, be sure to update ACPI_NUM_OSI_STRINGS.
194 */
195const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] =
196{
197 /* Operating System Vendor Strings */
198
199 "Linux",
200 "Windows 2000",
201 "Windows 2001",
202 "Windows 2001.1",
203 "Windows 2001 SP0",
204 "Windows 2001 SP1",
205 "Windows 2001 SP2",
206 "Windows 2001 SP3",
207 "Windows 2001 SP4",
208
209 /* Feature Group Strings */
210
211 "Extended Address Space Descriptor"
212};
213
214
215/******************************************************************************
216 *
217 * Namespace globals
218 *
219 ******************************************************************************/
220
221
222/*
223 * Predefined ACPI Names (Built-in to the Interpreter)
224 *
225 * NOTES:
226 * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run
227 * during the initialization sequence.
228 * 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to
229 * perform a Notify() operation on it.
230 */
231const struct acpi_predefined_names acpi_gbl_pre_defined_names[] =
232{ {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
233 {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
234 {"_SB_", ACPI_TYPE_DEVICE, NULL},
235 {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
236 {"_TZ_", ACPI_TYPE_THERMAL, NULL},
237 {"_REV", ACPI_TYPE_INTEGER, (char *) ACPI_CA_SUPPORT_LEVEL},
238 {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
239 {"_GL_", ACPI_TYPE_MUTEX, (char *) 1},
240
241#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
242 {"_OSI", ACPI_TYPE_METHOD, (char *) 1},
243#endif
244 {NULL, ACPI_TYPE_ANY, NULL} /* Table terminator */
245};
246
247
248/*
249 * Properties of the ACPI Object Types, both internal and external.
250 * The table is indexed by values of acpi_object_type
251 */
252const u8 acpi_gbl_ns_properties[] =
253{
254 ACPI_NS_NORMAL, /* 00 Any */
255 ACPI_NS_NORMAL, /* 01 Number */
256 ACPI_NS_NORMAL, /* 02 String */
257 ACPI_NS_NORMAL, /* 03 Buffer */
258 ACPI_NS_NORMAL, /* 04 Package */
259 ACPI_NS_NORMAL, /* 05 field_unit */
260 ACPI_NS_NEWSCOPE, /* 06 Device */
261 ACPI_NS_NORMAL, /* 07 Event */
262 ACPI_NS_NEWSCOPE, /* 08 Method */
263 ACPI_NS_NORMAL, /* 09 Mutex */
264 ACPI_NS_NORMAL, /* 10 Region */
265 ACPI_NS_NEWSCOPE, /* 11 Power */
266 ACPI_NS_NEWSCOPE, /* 12 Processor */
267 ACPI_NS_NEWSCOPE, /* 13 Thermal */
268 ACPI_NS_NORMAL, /* 14 buffer_field */
269 ACPI_NS_NORMAL, /* 15 ddb_handle */
270 ACPI_NS_NORMAL, /* 16 Debug Object */
271 ACPI_NS_NORMAL, /* 17 def_field */
272 ACPI_NS_NORMAL, /* 18 bank_field */
273 ACPI_NS_NORMAL, /* 19 index_field */
274 ACPI_NS_NORMAL, /* 20 Reference */
275 ACPI_NS_NORMAL, /* 21 Alias */
276 ACPI_NS_NORMAL, /* 22 method_alias */
277 ACPI_NS_NORMAL, /* 23 Notify */
278 ACPI_NS_NORMAL, /* 24 Address Handler */
279 ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */
280 ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */
281 ACPI_NS_NEWSCOPE, /* 27 Scope */
282 ACPI_NS_NORMAL, /* 28 Extra */
283 ACPI_NS_NORMAL, /* 29 Data */
284 ACPI_NS_NORMAL /* 30 Invalid */
285};
286
287
288/* Hex to ASCII conversion table */
289
290static const char acpi_gbl_hex_to_ascii[] =
291 {'0','1','2','3','4','5','6','7',
292 '8','9','A','B','C','D','E','F'};
293
294/*****************************************************************************
295 *
296 * FUNCTION: acpi_ut_hex_to_ascii_char
297 *
298 * PARAMETERS: Integer - Contains the hex digit
299 * Position - bit position of the digit within the
300 * integer
301 *
302 * RETURN: Ascii character
303 *
304 * DESCRIPTION: Convert a hex digit to an ascii character
305 *
306 ****************************************************************************/
307
308char
309acpi_ut_hex_to_ascii_char (
310 acpi_integer integer,
311 u32 position)
312{
313
314 return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]);
315}
316
317
318/******************************************************************************
319 *
320 * Table name globals
321 *
322 * NOTE: This table includes ONLY the ACPI tables that the subsystem consumes.
323 * it is NOT an exhaustive list of all possible ACPI tables. All ACPI tables
324 * that are not used by the subsystem are simply ignored.
325 *
326 * Do NOT add any table to this list that is not consumed directly by this
327 * subsystem.
328 *
329 ******************************************************************************/
330
331struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES];
332
333struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] =
334{
335 /*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */
336
337 /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof (RSDP_SIG)-1, ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE},
338 /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, (void *) &acpi_gbl_DSDT, sizeof (DSDT_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE | ACPI_TABLE_EXECUTABLE},
339 /* FADT 2 */ {FADT_SIG, FADT_SIG, (void *) &acpi_gbl_FADT, sizeof (FADT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE},
340 /* FACS 3 */ {FACS_SIG, FACS_SIG, (void *) &acpi_gbl_FACS, sizeof (FACS_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE},
341 /* PSDT 4 */ {PSDT_SIG, PSDT_SIG, NULL, sizeof (PSDT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE},
342 /* SSDT 5 */ {SSDT_SIG, SSDT_SIG, NULL, sizeof (SSDT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE},
343 /* XSDT 6 */ {XSDT_SIG, XSDT_SIG, NULL, sizeof (RSDT_SIG)-1, ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE},
344};
345
346
347/******************************************************************************
348 *
349 * Event and Hardware globals
350 *
351 ******************************************************************************/
352
353struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] =
354{
355 /* Name Parent Register Register Bit Position Register Bit Mask */
356
357 /* ACPI_BITREG_TIMER_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_TIMER_STATUS, ACPI_BITMASK_TIMER_STATUS},
358 /* ACPI_BITREG_BUS_MASTER_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_BUS_MASTER_STATUS, ACPI_BITMASK_BUS_MASTER_STATUS},
359 /* ACPI_BITREG_GLOBAL_LOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_GLOBAL_LOCK_STATUS, ACPI_BITMASK_GLOBAL_LOCK_STATUS},
360 /* ACPI_BITREG_POWER_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_POWER_BUTTON_STATUS, ACPI_BITMASK_POWER_BUTTON_STATUS},
361 /* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_STATUS},
362 /* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_STATUS},
363 /* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_WAKE_STATUS, ACPI_BITMASK_WAKE_STATUS},
364 /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_PCIEXP_WAKE_STATUS, ACPI_BITMASK_PCIEXP_WAKE_STATUS},
365
366 /* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_TIMER_ENABLE, ACPI_BITMASK_TIMER_ENABLE},
367 /* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
368 /* ACPI_BITREG_POWER_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_POWER_BUTTON_ENABLE, ACPI_BITMASK_POWER_BUTTON_ENABLE},
369 /* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
370 /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_ENABLE},
371 /* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0},
372 /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, ACPI_BITMASK_PCIEXP_WAKE_DISABLE},
373
374 /* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SCI_ENABLE, ACPI_BITMASK_SCI_ENABLE},
375 /* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_BUS_MASTER_RLD, ACPI_BITMASK_BUS_MASTER_RLD},
376 /* ACPI_BITREG_GLOBAL_LOCK_RELEASE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE, ACPI_BITMASK_GLOBAL_LOCK_RELEASE},
377 /* ACPI_BITREG_SLEEP_TYPE_A */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_TYPE_X, ACPI_BITMASK_SLEEP_TYPE_X},
378 /* ACPI_BITREG_SLEEP_TYPE_B */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_TYPE_X, ACPI_BITMASK_SLEEP_TYPE_X},
379 /* ACPI_BITREG_SLEEP_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_ENABLE, ACPI_BITMASK_SLEEP_ENABLE},
380
381 /* ACPI_BITREG_ARB_DIS */ {ACPI_REGISTER_PM2_CONTROL, ACPI_BITPOSITION_ARB_DISABLE, ACPI_BITMASK_ARB_DISABLE}
382};
383
384
385struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] =
386{
387 /* ACPI_EVENT_PMTIMER */ {ACPI_BITREG_TIMER_STATUS, ACPI_BITREG_TIMER_ENABLE, ACPI_BITMASK_TIMER_STATUS, ACPI_BITMASK_TIMER_ENABLE},
388 /* ACPI_EVENT_GLOBAL */ {ACPI_BITREG_GLOBAL_LOCK_STATUS, ACPI_BITREG_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_STATUS, ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
389 /* ACPI_EVENT_POWER_BUTTON */ {ACPI_BITREG_POWER_BUTTON_STATUS, ACPI_BITREG_POWER_BUTTON_ENABLE, ACPI_BITMASK_POWER_BUTTON_STATUS, ACPI_BITMASK_POWER_BUTTON_ENABLE},
390 /* ACPI_EVENT_SLEEP_BUTTON */ {ACPI_BITREG_SLEEP_BUTTON_STATUS, ACPI_BITREG_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
391 /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS, ACPI_BITREG_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_ENABLE},
392};
393
394/*****************************************************************************
395 *
396 * FUNCTION: acpi_ut_get_region_name
397 *
398 * PARAMETERS: None.
399 *
400 * RETURN: Status
401 *
402 * DESCRIPTION: Translate a Space ID into a name string (Debug only)
403 *
404 ****************************************************************************/
405
406/* Region type decoding */
407
408const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] =
409{
410/*! [Begin] no source code translation (keep these ASL Keywords as-is) */
411 "SystemMemory",
412 "SystemIO",
413 "PCI_Config",
414 "EmbeddedControl",
415 "SMBus",
416 "CMOS",
417 "PCIBARTarget",
418 "DataTable"
419/*! [End] no source code translation !*/
420};
421
422
423char *
424acpi_ut_get_region_name (
425 u8 space_id)
426{
427
428 if (space_id >= ACPI_USER_REGION_BEGIN)
429 {
430 return ("user_defined_region");
431 }
432
433 else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS)
434 {
435 return ("invalid_space_id");
436 }
437
438 return ((char *) acpi_gbl_region_types[space_id]);
439}
440
441
442/*****************************************************************************
443 *
444 * FUNCTION: acpi_ut_get_event_name
445 *
446 * PARAMETERS: None.
447 *
448 * RETURN: Status
449 *
450 * DESCRIPTION: Translate a Event ID into a name string (Debug only)
451 *
452 ****************************************************************************/
453
454/* Event type decoding */
455
456static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] =
457{
458 "PM_Timer",
459 "global_lock",
460 "power_button",
461 "sleep_button",
462 "real_time_clock",
463};
464
465
466char *
467acpi_ut_get_event_name (
468 u32 event_id)
469{
470
471 if (event_id > ACPI_EVENT_MAX)
472 {
473 return ("invalid_event_iD");
474 }
475
476 return ((char *) acpi_gbl_event_types[event_id]);
477}
478
479
480/*****************************************************************************
481 *
482 * FUNCTION: acpi_ut_get_type_name
483 *
484 * PARAMETERS: None.
485 *
486 * RETURN: Status
487 *
488 * DESCRIPTION: Translate a Type ID into a name string (Debug only)
489 *
490 ****************************************************************************/
491
492/*
493 * Elements of acpi_gbl_ns_type_names below must match
494 * one-to-one with values of acpi_object_type
495 *
496 * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; when
497 * stored in a table it really means that we have thus far seen no evidence to
498 * indicate what type is actually going to be stored for this entry.
499 */
500static const char acpi_gbl_bad_type[] = "UNDEFINED";
501#define TYPE_NAME_LENGTH 12 /* Maximum length of each string */
502
503static const char *acpi_gbl_ns_type_names[] = /* printable names of ACPI types */
504{
505 /* 00 */ "Untyped",
506 /* 01 */ "Integer",
507 /* 02 */ "String",
508 /* 03 */ "Buffer",
509 /* 04 */ "Package",
510 /* 05 */ "field_unit",
511 /* 06 */ "Device",
512 /* 07 */ "Event",
513 /* 08 */ "Method",
514 /* 09 */ "Mutex",
515 /* 10 */ "Region",
516 /* 11 */ "Power",
517 /* 12 */ "Processor",
518 /* 13 */ "Thermal",
519 /* 14 */ "buffer_field",
520 /* 15 */ "ddb_handle",
521 /* 16 */ "debug_object",
522 /* 17 */ "region_field",
523 /* 18 */ "bank_field",
524 /* 19 */ "index_field",
525 /* 20 */ "Reference",
526 /* 21 */ "Alias",
527 /* 22 */ "method_alias",
528 /* 23 */ "Notify",
529 /* 24 */ "addr_handler",
530 /* 25 */ "resource_desc",
531 /* 26 */ "resource_fld",
532 /* 27 */ "Scope",
533 /* 28 */ "Extra",
534 /* 29 */ "Data",
535 /* 30 */ "Invalid"
536};
537
538
539char *
540acpi_ut_get_type_name (
541 acpi_object_type type)
542{
543
544 if (type > ACPI_TYPE_INVALID)
545 {
546 return ((char *) acpi_gbl_bad_type);
547 }
548
549 return ((char *) acpi_gbl_ns_type_names[type]);
550}
551
552
553char *
554acpi_ut_get_object_type_name (
555 union acpi_operand_object *obj_desc)
556{
557
558 if (!obj_desc)
559 {
560 return ("[NULL Object Descriptor]");
561 }
562
563 return (acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (obj_desc)));
564}
565
566
567/*****************************************************************************
568 *
569 * FUNCTION: acpi_ut_get_node_name
570 *
571 * PARAMETERS: Object - A namespace node
572 *
573 * RETURN: Pointer to a string
574 *
575 * DESCRIPTION: Validate the node and return the node's ACPI name.
576 *
577 ****************************************************************************/
578
579char *
580acpi_ut_get_node_name (
581 void *object)
582{
583 struct acpi_namespace_node *node = (struct acpi_namespace_node *) object;
584
585
586 /* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */
587
588 if (!object)
589 {
590 return ("NULL");
591 }
592
593 /* Check for Root node */
594
595 if ((object == ACPI_ROOT_OBJECT) ||
596 (object == acpi_gbl_root_node))
597 {
598 return ("\"\\\" ");
599 }
600
601 /* Descriptor must be a namespace node */
602
603 if (node->descriptor != ACPI_DESC_TYPE_NAMED)
604 {
605 return ("####");
606 }
607
608 /* Name must be a valid ACPI name */
609
610 if (!acpi_ut_valid_acpi_name (* (u32 *) node->name.ascii))
611 {
612 return ("????");
613 }
614
615 /* Return the name */
616
617 return (node->name.ascii);
618}
619
620
621/*****************************************************************************
622 *
623 * FUNCTION: acpi_ut_get_descriptor_name
624 *
625 * PARAMETERS: Object - An ACPI object
626 *
627 * RETURN: Pointer to a string
628 *
629 * DESCRIPTION: Validate object and return the descriptor type
630 *
631 ****************************************************************************/
632
633static const char *acpi_gbl_desc_type_names[] = /* printable names of descriptor types */
634{
635 /* 00 */ "Invalid",
636 /* 01 */ "Cached",
637 /* 02 */ "State-Generic",
638 /* 03 */ "State-Update",
639 /* 04 */ "State-Package",
640 /* 05 */ "State-Control",
641 /* 06 */ "State-root_parse_scope",
642 /* 07 */ "State-parse_scope",
643 /* 08 */ "State-walk_scope",
644 /* 09 */ "State-Result",
645 /* 10 */ "State-Notify",
646 /* 11 */ "State-Thread",
647 /* 12 */ "Walk",
648 /* 13 */ "Parser",
649 /* 14 */ "Operand",
650 /* 15 */ "Node"
651};
652
653
654char *
655acpi_ut_get_descriptor_name (
656 void *object)
657{
658
659 if (!object)
660 {
661 return ("NULL OBJECT");
662 }
663
664 if (ACPI_GET_DESCRIPTOR_TYPE (object) > ACPI_DESC_TYPE_MAX)
665 {
666 return ((char *) acpi_gbl_bad_type);
667 }
668
669 return ((char *) acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE (object)]);
670
671}
672
673
674#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
675/*
676 * Strings and procedures used for debug only
677 */
678
679/*****************************************************************************
680 *
681 * FUNCTION: acpi_ut_get_mutex_name
682 *
683 * PARAMETERS: None.
684 *
685 * RETURN: Status
686 *
687 * DESCRIPTION: Translate a mutex ID into a name string (Debug only)
688 *
689 ****************************************************************************/
690
691char *
692acpi_ut_get_mutex_name (
693 u32 mutex_id)
694{
695
696 if (mutex_id > MAX_MUTEX)
697 {
698 return ("Invalid Mutex ID");
699 }
700
701 return (acpi_gbl_mutex_names[mutex_id]);
702}
703
704#endif
705
706
707/*****************************************************************************
708 *
709 * FUNCTION: acpi_ut_valid_object_type
710 *
711 * PARAMETERS: Type - Object type to be validated
712 *
713 * RETURN: TRUE if valid object type
714 *
715 * DESCRIPTION: Validate an object type
716 *
717 ****************************************************************************/
718
719u8
720acpi_ut_valid_object_type (
721 acpi_object_type type)
722{
723
724 if (type > ACPI_TYPE_LOCAL_MAX)
725 {
726 /* Note: Assumes all TYPEs are contiguous (external/local) */
727
728 return (FALSE);
729 }
730
731 return (TRUE);
732}
733
734
735/****************************************************************************
736 *
737 * FUNCTION: acpi_ut_allocate_owner_id
738 *
739 * PARAMETERS: id_type - Type of ID (method or table)
740 *
741 * DESCRIPTION: Allocate a table or method owner id
742 *
743 ***************************************************************************/
744
745acpi_owner_id
746acpi_ut_allocate_owner_id (
747 u32 id_type)
748{
749 acpi_owner_id owner_id = 0xFFFF;
750
751
752 ACPI_FUNCTION_TRACE ("ut_allocate_owner_id");
753
754
755 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES)))
756 {
757 return (0);
758 }
759
760 switch (id_type)
761 {
762 case ACPI_OWNER_TYPE_TABLE:
763
764 owner_id = acpi_gbl_next_table_owner_id;
765 acpi_gbl_next_table_owner_id++;
766
767 /* Check for wraparound */
768
769 if (acpi_gbl_next_table_owner_id == ACPI_FIRST_METHOD_ID)
770 {
771 acpi_gbl_next_table_owner_id = ACPI_FIRST_TABLE_ID;
772 ACPI_REPORT_WARNING (("Table owner ID wraparound\n"));
773 }
774 break;
775
776
777 case ACPI_OWNER_TYPE_METHOD:
778
779 owner_id = acpi_gbl_next_method_owner_id;
780 acpi_gbl_next_method_owner_id++;
781
782 if (acpi_gbl_next_method_owner_id == ACPI_FIRST_TABLE_ID)
783 {
784 /* Check for wraparound */
785
786 acpi_gbl_next_method_owner_id = ACPI_FIRST_METHOD_ID;
787 }
788 break;
789
790 default:
791 break;
792 }
793
794 (void) acpi_ut_release_mutex (ACPI_MTX_CACHES);
795 return_VALUE (owner_id);
796}
797
798
799/****************************************************************************
800 *
801 * FUNCTION: acpi_ut_init_globals
802 *
803 * PARAMETERS: none
804 *
805 * DESCRIPTION: Init library globals. All globals that require specific
806 * initialization should be initialized here!
807 *
808 ***************************************************************************/
809
810void
811acpi_ut_init_globals (
812 void)
813{
814 u32 i;
815
816
817 ACPI_FUNCTION_TRACE ("ut_init_globals");
818
819
820 /* Memory allocation and cache lists */
821
822 ACPI_MEMSET (acpi_gbl_memory_lists, 0, sizeof (struct acpi_memory_list) * ACPI_NUM_MEM_LISTS);
823
824 acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_generic_state *) NULL)->common.next), NULL);
825 acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_parse_object *) NULL)->common.next), NULL);
826 acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_parse_object *) NULL)->common.next), NULL);
827 acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_operand_object *) NULL)->cache.next), NULL);
828 acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].link_offset = (u16) ACPI_PTR_DIFF (&(((struct acpi_walk_state *) NULL)->next), NULL);
829
830 acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].object_size = sizeof (struct acpi_namespace_node);
831 acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].object_size = sizeof (union acpi_generic_state);
832 acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].object_size = sizeof (struct acpi_parse_obj_common);
833 acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].object_size = sizeof (struct acpi_parse_obj_named);
834 acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].object_size = sizeof (union acpi_operand_object);
835 acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].object_size = sizeof (struct acpi_walk_state);
836
837 acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].max_cache_depth = ACPI_MAX_STATE_CACHE_DEPTH;
838 acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].max_cache_depth = ACPI_MAX_PARSE_CACHE_DEPTH;
839 acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].max_cache_depth = ACPI_MAX_EXTPARSE_CACHE_DEPTH;
840 acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].max_cache_depth = ACPI_MAX_OBJECT_CACHE_DEPTH;
841 acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].max_cache_depth = ACPI_MAX_WALK_CACHE_DEPTH;
842
843 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].list_name = "Global Memory Allocation");
844 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].list_name = "Namespace Nodes");
845 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].list_name = "State Object Cache");
846 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].list_name = "Parse Node Cache");
847 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].list_name = "Extended Parse Node Cache");
848 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].list_name = "Operand Object Cache");
849 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].list_name = "Tree Walk Node Cache");
850
851 /* ACPI table structure */
852
853 for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++)
854 {
855 acpi_gbl_table_lists[i].next = NULL;
856 acpi_gbl_table_lists[i].count = 0;
857 }
858
859 /* Mutex locked flags */
860
861 for (i = 0; i < NUM_MUTEX; i++)
862 {
863 acpi_gbl_mutex_info[i].mutex = NULL;
864 acpi_gbl_mutex_info[i].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
865 acpi_gbl_mutex_info[i].use_count = 0;
866 }
867
868 /* GPE support */
869
870 acpi_gbl_gpe_xrupt_list_head = NULL;
871 acpi_gbl_gpe_fadt_blocks[0] = NULL;
872 acpi_gbl_gpe_fadt_blocks[1] = NULL;
873
874 /* Global notify handlers */
875
876 acpi_gbl_system_notify.handler = NULL;
877 acpi_gbl_device_notify.handler = NULL;
878 acpi_gbl_exception_handler = NULL;
879 acpi_gbl_init_handler = NULL;
880
881 /* Global "typed" ACPI table pointers */
882
883 acpi_gbl_RSDP = NULL;
884 acpi_gbl_XSDT = NULL;
885 acpi_gbl_FACS = NULL;
886 acpi_gbl_FADT = NULL;
887 acpi_gbl_DSDT = NULL;
888
889 /* Global Lock support */
890
891 acpi_gbl_global_lock_acquired = FALSE;
892 acpi_gbl_global_lock_thread_count = 0;
893 acpi_gbl_global_lock_handle = 0;
894
895 /* Miscellaneous variables */
896
897 acpi_gbl_table_flags = ACPI_PHYSICAL_POINTER;
898 acpi_gbl_rsdp_original_location = 0;
899 acpi_gbl_cm_single_step = FALSE;
900 acpi_gbl_db_terminate_threads = FALSE;
901 acpi_gbl_shutdown = FALSE;
902 acpi_gbl_ns_lookup_count = 0;
903 acpi_gbl_ps_find_count = 0;
904 acpi_gbl_acpi_hardware_present = TRUE;
905 acpi_gbl_next_table_owner_id = ACPI_FIRST_TABLE_ID;
906 acpi_gbl_next_method_owner_id = ACPI_FIRST_METHOD_ID;
907 acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
908 acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
909
910 /* Hardware oriented */
911
912 acpi_gbl_events_initialized = FALSE;
913 acpi_gbl_system_awake_and_running = TRUE;
914
915 /* Namespace */
916
917 acpi_gbl_root_node = NULL;
918
919 acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
920 acpi_gbl_root_node_struct.descriptor = ACPI_DESC_TYPE_NAMED;
921 acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
922 acpi_gbl_root_node_struct.child = NULL;
923 acpi_gbl_root_node_struct.peer = NULL;
924 acpi_gbl_root_node_struct.object = NULL;
925 acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST;
926
927
928#ifdef ACPI_DEBUG_OUTPUT
929 acpi_gbl_lowest_stack_pointer = ACPI_SIZE_MAX;
930#endif
931
932 return_VOID;
933}
934
935
diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c
new file mode 100644
index 000000000000..bdbadaf48d29
--- /dev/null
+++ b/drivers/acpi/utilities/utinit.c
@@ -0,0 +1,266 @@
1/******************************************************************************
2 *
3 * Module Name: utinit - Common ACPI subsystem initialization
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acevents.h>
48
49#define _COMPONENT ACPI_UTILITIES
50 ACPI_MODULE_NAME ("utinit")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ut_fadt_register_error
56 *
57 * PARAMETERS: *register_name - Pointer to string identifying register
58 * Value - Actual register contents value
59 * acpi_test_spec_section - TDS section containing assertion
60 * acpi_assertion - Assertion number being tested
61 *
62 * RETURN: AE_BAD_VALUE
63 *
64 * DESCRIPTION: Display failure message and link failure to TDS assertion
65 *
66 ******************************************************************************/
67
68static void
69acpi_ut_fadt_register_error (
70 char *register_name,
71 u32 value,
72 acpi_size offset)
73{
74
75 ACPI_REPORT_WARNING (
76 ("Invalid FADT value %s=%X at offset %X FADT=%p\n",
77 register_name, value, (u32) offset, acpi_gbl_FADT));
78}
79
80
81/******************************************************************************
82 *
83 * FUNCTION: acpi_ut_validate_fadt
84 *
85 * PARAMETERS: None
86 *
87 * RETURN: Status
88 *
89 * DESCRIPTION: Validate various ACPI registers in the FADT
90 *
91 ******************************************************************************/
92
93acpi_status
94acpi_ut_validate_fadt (
95 void)
96{
97
98 /*
99 * Verify Fixed ACPI Description Table fields,
100 * but don't abort on any problems, just display error
101 */
102 if (acpi_gbl_FADT->pm1_evt_len < 4) {
103 acpi_ut_fadt_register_error ("PM1_EVT_LEN",
104 (u32) acpi_gbl_FADT->pm1_evt_len,
105 ACPI_FADT_OFFSET (pm1_evt_len));
106 }
107
108 if (!acpi_gbl_FADT->pm1_cnt_len) {
109 acpi_ut_fadt_register_error ("PM1_CNT_LEN", 0,
110 ACPI_FADT_OFFSET (pm1_cnt_len));
111 }
112
113 if (!acpi_gbl_FADT->xpm1a_evt_blk.address) {
114 acpi_ut_fadt_register_error ("X_PM1a_EVT_BLK", 0,
115 ACPI_FADT_OFFSET (xpm1a_evt_blk.address));
116 }
117
118 if (!acpi_gbl_FADT->xpm1a_cnt_blk.address) {
119 acpi_ut_fadt_register_error ("X_PM1a_CNT_BLK", 0,
120 ACPI_FADT_OFFSET (xpm1a_cnt_blk.address));
121 }
122
123 if (!acpi_gbl_FADT->xpm_tmr_blk.address) {
124 acpi_ut_fadt_register_error ("X_PM_TMR_BLK", 0,
125 ACPI_FADT_OFFSET (xpm_tmr_blk.address));
126 }
127
128 if ((acpi_gbl_FADT->xpm2_cnt_blk.address &&
129 !acpi_gbl_FADT->pm2_cnt_len)) {
130 acpi_ut_fadt_register_error ("PM2_CNT_LEN",
131 (u32) acpi_gbl_FADT->pm2_cnt_len,
132 ACPI_FADT_OFFSET (pm2_cnt_len));
133 }
134
135 if (acpi_gbl_FADT->pm_tm_len < 4) {
136 acpi_ut_fadt_register_error ("PM_TM_LEN",
137 (u32) acpi_gbl_FADT->pm_tm_len,
138 ACPI_FADT_OFFSET (pm_tm_len));
139 }
140
141 /* Length of GPE blocks must be a multiple of 2 */
142
143 if (acpi_gbl_FADT->xgpe0_blk.address &&
144 (acpi_gbl_FADT->gpe0_blk_len & 1)) {
145 acpi_ut_fadt_register_error ("(x)GPE0_BLK_LEN",
146 (u32) acpi_gbl_FADT->gpe0_blk_len,
147 ACPI_FADT_OFFSET (gpe0_blk_len));
148 }
149
150 if (acpi_gbl_FADT->xgpe1_blk.address &&
151 (acpi_gbl_FADT->gpe1_blk_len & 1)) {
152 acpi_ut_fadt_register_error ("(x)GPE1_BLK_LEN",
153 (u32) acpi_gbl_FADT->gpe1_blk_len,
154 ACPI_FADT_OFFSET (gpe1_blk_len));
155 }
156
157 return (AE_OK);
158}
159
160
161/******************************************************************************
162 *
163 * FUNCTION: acpi_ut_terminate
164 *
165 * PARAMETERS: none
166 *
167 * RETURN: none
168 *
169 * DESCRIPTION: free global memory
170 *
171 ******************************************************************************/
172
173void
174acpi_ut_terminate (void)
175{
176 struct acpi_gpe_block_info *gpe_block;
177 struct acpi_gpe_block_info *next_gpe_block;
178 struct acpi_gpe_xrupt_info *gpe_xrupt_info;
179 struct acpi_gpe_xrupt_info *next_gpe_xrupt_info;
180
181
182 ACPI_FUNCTION_TRACE ("ut_terminate");
183
184
185 /* Free global tables, etc. */
186
187
188 /* Free global GPE blocks and related info structures */
189
190 gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
191 while (gpe_xrupt_info) {
192 gpe_block = gpe_xrupt_info->gpe_block_list_head;
193 while (gpe_block) {
194 next_gpe_block = gpe_block->next;
195 ACPI_MEM_FREE (gpe_block->event_info);
196 ACPI_MEM_FREE (gpe_block->register_info);
197 ACPI_MEM_FREE (gpe_block);
198
199 gpe_block = next_gpe_block;
200 }
201 next_gpe_xrupt_info = gpe_xrupt_info->next;
202 ACPI_MEM_FREE (gpe_xrupt_info);
203 gpe_xrupt_info = next_gpe_xrupt_info;
204 }
205
206 return_VOID;
207}
208
209
210/*******************************************************************************
211 *
212 * FUNCTION: acpi_ut_subsystem_shutdown
213 *
214 * PARAMETERS: none
215 *
216 * RETURN: none
217 *
218 * DESCRIPTION: Shutdown the various subsystems. Don't delete the mutex
219 * objects here -- because the AML debugger may be still running.
220 *
221 ******************************************************************************/
222
223void
224acpi_ut_subsystem_shutdown (void)
225{
226
227 ACPI_FUNCTION_TRACE ("ut_subsystem_shutdown");
228
229 /* Just exit if subsystem is already shutdown */
230
231 if (acpi_gbl_shutdown) {
232 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "ACPI Subsystem is already terminated\n"));
233 return_VOID;
234 }
235
236 /* Subsystem appears active, go ahead and shut it down */
237
238 acpi_gbl_shutdown = TRUE;
239 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Shutting down ACPI Subsystem...\n"));
240
241 /* Close the acpi_event Handling */
242
243 acpi_ev_terminate ();
244
245 /* Close the Namespace */
246
247 acpi_ns_terminate ();
248
249 /* Close the globals */
250
251 acpi_ut_terminate ();
252
253 /* Purge the local caches */
254
255 (void) acpi_purge_cached_objects ();
256
257 /* Debug only - display leftover memory allocation, if any */
258
259#ifdef ACPI_DBG_TRACK_ALLOCATIONS
260 acpi_ut_dump_allocations (ACPI_UINT32_MAX, NULL);
261#endif
262
263 return_VOID;
264}
265
266
diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c
new file mode 100644
index 000000000000..2525c1a93547
--- /dev/null
+++ b/drivers/acpi/utilities/utmath.c
@@ -0,0 +1,333 @@
1/*******************************************************************************
2 *
3 * Module Name: utmath - Integer math support routines
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46
47
48#define _COMPONENT ACPI_UTILITIES
49 ACPI_MODULE_NAME ("utmath")
50
51/*
52 * Support for double-precision integer divide. This code is included here
53 * in order to support kernel environments where the double-precision math
54 * library is not available.
55 */
56
57#ifndef ACPI_USE_NATIVE_DIVIDE
58/*******************************************************************************
59 *
60 * FUNCTION: acpi_ut_short_divide
61 *
62 * PARAMETERS: Dividend - 64-bit dividend
63 * Divisor - 32-bit divisor
64 * out_quotient - Pointer to where the quotient is returned
65 * out_remainder - Pointer to where the remainder is returned
66 *
67 * RETURN: Status (Checks for divide-by-zero)
68 *
69 * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
70 * divide and modulo. The result is a 64-bit quotient and a
71 * 32-bit remainder.
72 *
73 ******************************************************************************/
74
75acpi_status
76acpi_ut_short_divide (
77 acpi_integer dividend,
78 u32 divisor,
79 acpi_integer *out_quotient,
80 u32 *out_remainder)
81{
82 union uint64_overlay dividend_ovl;
83 union uint64_overlay quotient;
84 u32 remainder32;
85
86
87 ACPI_FUNCTION_TRACE ("ut_short_divide");
88
89
90 /* Always check for a zero divisor */
91
92 if (divisor == 0) {
93 ACPI_REPORT_ERROR (("acpi_ut_short_divide: Divide by zero\n"));
94 return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
95 }
96
97 dividend_ovl.full = dividend;
98
99 /*
100 * The quotient is 64 bits, the remainder is always 32 bits,
101 * and is generated by the second divide.
102 */
103 ACPI_DIV_64_BY_32 (0, dividend_ovl.part.hi, divisor,
104 quotient.part.hi, remainder32);
105 ACPI_DIV_64_BY_32 (remainder32, dividend_ovl.part.lo, divisor,
106 quotient.part.lo, remainder32);
107
108 /* Return only what was requested */
109
110 if (out_quotient) {
111 *out_quotient = quotient.full;
112 }
113 if (out_remainder) {
114 *out_remainder = remainder32;
115 }
116
117 return_ACPI_STATUS (AE_OK);
118}
119
120
121/*******************************************************************************
122 *
123 * FUNCTION: acpi_ut_divide
124 *
125 * PARAMETERS: in_dividend - Dividend
126 * in_divisor - Divisor
127 * out_quotient - Pointer to where the quotient is returned
128 * out_remainder - Pointer to where the remainder is returned
129 *
130 * RETURN: Status (Checks for divide-by-zero)
131 *
132 * DESCRIPTION: Perform a divide and modulo.
133 *
134 ******************************************************************************/
135
136acpi_status
137acpi_ut_divide (
138 acpi_integer in_dividend,
139 acpi_integer in_divisor,
140 acpi_integer *out_quotient,
141 acpi_integer *out_remainder)
142{
143 union uint64_overlay dividend;
144 union uint64_overlay divisor;
145 union uint64_overlay quotient;
146 union uint64_overlay remainder;
147 union uint64_overlay normalized_dividend;
148 union uint64_overlay normalized_divisor;
149 u32 partial1;
150 union uint64_overlay partial2;
151 union uint64_overlay partial3;
152
153
154 ACPI_FUNCTION_TRACE ("ut_divide");
155
156
157 /* Always check for a zero divisor */
158
159 if (in_divisor == 0) {
160 ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n"));
161 return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
162 }
163
164 divisor.full = in_divisor;
165 dividend.full = in_dividend;
166 if (divisor.part.hi == 0) {
167 /*
168 * 1) Simplest case is where the divisor is 32 bits, we can
169 * just do two divides
170 */
171 remainder.part.hi = 0;
172
173 /*
174 * The quotient is 64 bits, the remainder is always 32 bits,
175 * and is generated by the second divide.
176 */
177 ACPI_DIV_64_BY_32 (0, dividend.part.hi, divisor.part.lo,
178 quotient.part.hi, partial1);
179 ACPI_DIV_64_BY_32 (partial1, dividend.part.lo, divisor.part.lo,
180 quotient.part.lo, remainder.part.lo);
181 }
182
183 else {
184 /*
185 * 2) The general case where the divisor is a full 64 bits
186 * is more difficult
187 */
188 quotient.part.hi = 0;
189 normalized_dividend = dividend;
190 normalized_divisor = divisor;
191
192 /* Normalize the operands (shift until the divisor is < 32 bits) */
193
194 do {
195 ACPI_SHIFT_RIGHT_64 (normalized_divisor.part.hi,
196 normalized_divisor.part.lo);
197 ACPI_SHIFT_RIGHT_64 (normalized_dividend.part.hi,
198 normalized_dividend.part.lo);
199
200 } while (normalized_divisor.part.hi != 0);
201
202 /* Partial divide */
203
204 ACPI_DIV_64_BY_32 (normalized_dividend.part.hi,
205 normalized_dividend.part.lo,
206 normalized_divisor.part.lo,
207 quotient.part.lo, partial1);
208
209 /*
210 * The quotient is always 32 bits, and simply requires adjustment.
211 * The 64-bit remainder must be generated.
212 */
213 partial1 = quotient.part.lo * divisor.part.hi;
214 partial2.full = (acpi_integer) quotient.part.lo * divisor.part.lo;
215 partial3.full = (acpi_integer) partial2.part.hi + partial1;
216
217 remainder.part.hi = partial3.part.lo;
218 remainder.part.lo = partial2.part.lo;
219
220 if (partial3.part.hi == 0) {
221 if (partial3.part.lo >= dividend.part.hi) {
222 if (partial3.part.lo == dividend.part.hi) {
223 if (partial2.part.lo > dividend.part.lo) {
224 quotient.part.lo--;
225 remainder.full -= divisor.full;
226 }
227 }
228 else {
229 quotient.part.lo--;
230 remainder.full -= divisor.full;
231 }
232 }
233
234 remainder.full = remainder.full - dividend.full;
235 remainder.part.hi = (u32) -((s32) remainder.part.hi);
236 remainder.part.lo = (u32) -((s32) remainder.part.lo);
237
238 if (remainder.part.lo) {
239 remainder.part.hi--;
240 }
241 }
242 }
243
244 /* Return only what was requested */
245
246 if (out_quotient) {
247 *out_quotient = quotient.full;
248 }
249 if (out_remainder) {
250 *out_remainder = remainder.full;
251 }
252
253 return_ACPI_STATUS (AE_OK);
254}
255
256#else
257
258/*******************************************************************************
259 *
260 * FUNCTION: acpi_ut_short_divide, acpi_ut_divide
261 *
262 * DESCRIPTION: Native versions of the ut_divide functions. Use these if either
263 * 1) The target is a 64-bit platform and therefore 64-bit
264 * integer math is supported directly by the machine.
265 * 2) The target is a 32-bit or 16-bit platform, and the
266 * double-precision integer math library is available to
267 * perform the divide.
268 *
269 ******************************************************************************/
270
271acpi_status
272acpi_ut_short_divide (
273 acpi_integer in_dividend,
274 u32 divisor,
275 acpi_integer *out_quotient,
276 u32 *out_remainder)
277{
278
279 ACPI_FUNCTION_TRACE ("ut_short_divide");
280
281
282 /* Always check for a zero divisor */
283
284 if (divisor == 0) {
285 ACPI_REPORT_ERROR (("acpi_ut_short_divide: Divide by zero\n"));
286 return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
287 }
288
289 /* Return only what was requested */
290
291 if (out_quotient) {
292 *out_quotient = in_dividend / divisor;
293 }
294 if (out_remainder) {
295 *out_remainder = (u32) in_dividend % divisor;
296 }
297
298 return_ACPI_STATUS (AE_OK);
299}
300
301acpi_status
302acpi_ut_divide (
303 acpi_integer in_dividend,
304 acpi_integer in_divisor,
305 acpi_integer *out_quotient,
306 acpi_integer *out_remainder)
307{
308 ACPI_FUNCTION_TRACE ("ut_divide");
309
310
311 /* Always check for a zero divisor */
312
313 if (in_divisor == 0) {
314 ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n"));
315 return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
316 }
317
318
319 /* Return only what was requested */
320
321 if (out_quotient) {
322 *out_quotient = in_dividend / in_divisor;
323 }
324 if (out_remainder) {
325 *out_remainder = in_dividend % in_divisor;
326 }
327
328 return_ACPI_STATUS (AE_OK);
329}
330
331#endif
332
333
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
new file mode 100644
index 000000000000..f6598547389b
--- /dev/null
+++ b/drivers/acpi/utilities/utmisc.c
@@ -0,0 +1,1516 @@
1/*******************************************************************************
2 *
3 * Module Name: utmisc - common utility procedures
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47
48
49#define _COMPONENT ACPI_UTILITIES
50 ACPI_MODULE_NAME ("utmisc")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ut_print_string
56 *
57 * PARAMETERS: String - Null terminated ASCII string
58 *
59 * RETURN: None
60 *
61 * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape
62 * sequences.
63 *
64 ******************************************************************************/
65
66void
67acpi_ut_print_string (
68 char *string,
69 u8 max_length)
70{
71 u32 i;
72
73
74 if (!string) {
75 acpi_os_printf ("<\"NULL STRING PTR\">");
76 return;
77 }
78
79 acpi_os_printf ("\"");
80 for (i = 0; string[i] && (i < max_length); i++) {
81 /* Escape sequences */
82
83 switch (string[i]) {
84 case 0x07:
85 acpi_os_printf ("\\a"); /* BELL */
86 break;
87
88 case 0x08:
89 acpi_os_printf ("\\b"); /* BACKSPACE */
90 break;
91
92 case 0x0C:
93 acpi_os_printf ("\\f"); /* FORMFEED */
94 break;
95
96 case 0x0A:
97 acpi_os_printf ("\\n"); /* LINEFEED */
98 break;
99
100 case 0x0D:
101 acpi_os_printf ("\\r"); /* CARRIAGE RETURN*/
102 break;
103
104 case 0x09:
105 acpi_os_printf ("\\t"); /* HORIZONTAL TAB */
106 break;
107
108 case 0x0B:
109 acpi_os_printf ("\\v"); /* VERTICAL TAB */
110 break;
111
112 case '\'': /* Single Quote */
113 case '\"': /* Double Quote */
114 case '\\': /* Backslash */
115 acpi_os_printf ("\\%c", (int) string[i]);
116 break;
117
118 default:
119
120 /* Check for printable character or hex escape */
121
122 if (ACPI_IS_PRINT (string[i]))
123 {
124 /* This is a normal character */
125
126 acpi_os_printf ("%c", (int) string[i]);
127 }
128 else
129 {
130 /* All others will be Hex escapes */
131
132 acpi_os_printf ("\\x%2.2X", (s32) string[i]);
133 }
134 break;
135 }
136 }
137 acpi_os_printf ("\"");
138
139 if (i == max_length && string[i]) {
140 acpi_os_printf ("...");
141 }
142}
143
144
145/*******************************************************************************
146 *
147 * FUNCTION: acpi_ut_dword_byte_swap
148 *
149 * PARAMETERS: Value - Value to be converted
150 *
151 * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
152 *
153 ******************************************************************************/
154
155u32
156acpi_ut_dword_byte_swap (
157 u32 value)
158{
159 union {
160 u32 value;
161 u8 bytes[4];
162 } out;
163
164 union {
165 u32 value;
166 u8 bytes[4];
167 } in;
168
169
170 ACPI_FUNCTION_ENTRY ();
171
172
173 in.value = value;
174
175 out.bytes[0] = in.bytes[3];
176 out.bytes[1] = in.bytes[2];
177 out.bytes[2] = in.bytes[1];
178 out.bytes[3] = in.bytes[0];
179
180 return (out.value);
181}
182
183
184/*******************************************************************************
185 *
186 * FUNCTION: acpi_ut_set_integer_width
187 *
188 * PARAMETERS: Revision From DSDT header
189 *
190 * RETURN: None
191 *
192 * DESCRIPTION: Set the global integer bit width based upon the revision
193 * of the DSDT. For Revision 1 and 0, Integers are 32 bits.
194 * For Revision 2 and above, Integers are 64 bits. Yes, this
195 * makes a difference.
196 *
197 ******************************************************************************/
198
199void
200acpi_ut_set_integer_width (
201 u8 revision)
202{
203
204 if (revision <= 1) {
205 acpi_gbl_integer_bit_width = 32;
206 acpi_gbl_integer_nybble_width = 8;
207 acpi_gbl_integer_byte_width = 4;
208 }
209 else {
210 acpi_gbl_integer_bit_width = 64;
211 acpi_gbl_integer_nybble_width = 16;
212 acpi_gbl_integer_byte_width = 8;
213 }
214}
215
216
217#ifdef ACPI_DEBUG_OUTPUT
218/*******************************************************************************
219 *
220 * FUNCTION: acpi_ut_display_init_pathname
221 *
222 * PARAMETERS: obj_handle - Handle whose pathname will be displayed
223 * Path - Additional path string to be appended.
224 * (NULL if no extra path)
225 *
226 * RETURN: acpi_status
227 *
228 * DESCRIPTION: Display full pathname of an object, DEBUG ONLY
229 *
230 ******************************************************************************/
231
232void
233acpi_ut_display_init_pathname (
234 u8 type,
235 struct acpi_namespace_node *obj_handle,
236 char *path)
237{
238 acpi_status status;
239 struct acpi_buffer buffer;
240
241
242 ACPI_FUNCTION_ENTRY ();
243
244
245 /* Only print the path if the appropriate debug level is enabled */
246
247 if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
248 return;
249 }
250
251 /* Get the full pathname to the node */
252
253 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
254 status = acpi_ns_handle_to_pathname (obj_handle, &buffer);
255 if (ACPI_FAILURE (status)) {
256 return;
257 }
258
259 /* Print what we're doing */
260
261 switch (type) {
262 case ACPI_TYPE_METHOD:
263 acpi_os_printf ("Executing ");
264 break;
265
266 default:
267 acpi_os_printf ("Initializing ");
268 break;
269 }
270
271 /* Print the object type and pathname */
272
273 acpi_os_printf ("%-12s %s", acpi_ut_get_type_name (type), (char *) buffer.pointer);
274
275 /* Extra path is used to append names like _STA, _INI, etc. */
276
277 if (path) {
278 acpi_os_printf (".%s", path);
279 }
280 acpi_os_printf ("\n");
281
282 ACPI_MEM_FREE (buffer.pointer);
283}
284#endif
285
286
287/*******************************************************************************
288 *
289 * FUNCTION: acpi_ut_valid_acpi_name
290 *
291 * PARAMETERS: Character - The character to be examined
292 *
293 * RETURN: 1 if Character may appear in a name, else 0
294 *
295 * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
296 * 1) Upper case alpha
297 * 2) numeric
298 * 3) underscore
299 *
300 ******************************************************************************/
301
302u8
303acpi_ut_valid_acpi_name (
304 u32 name)
305{
306 char *name_ptr = (char *) &name;
307 char character;
308 acpi_native_uint i;
309
310
311 ACPI_FUNCTION_ENTRY ();
312
313
314 for (i = 0; i < ACPI_NAME_SIZE; i++) {
315 character = *name_ptr;
316 name_ptr++;
317
318 if (!((character == '_') ||
319 (character >= 'A' && character <= 'Z') ||
320 (character >= '0' && character <= '9'))) {
321 return (FALSE);
322 }
323 }
324
325 return (TRUE);
326}
327
328
329/*******************************************************************************
330 *
331 * FUNCTION: acpi_ut_valid_acpi_character
332 *
333 * PARAMETERS: Character - The character to be examined
334 *
335 * RETURN: 1 if Character may appear in a name, else 0
336 *
337 * DESCRIPTION: Check for a printable character
338 *
339 ******************************************************************************/
340
341u8
342acpi_ut_valid_acpi_character (
343 char character)
344{
345
346 ACPI_FUNCTION_ENTRY ();
347
348 return ((u8) ((character == '_') ||
349 (character >= 'A' && character <= 'Z') ||
350 (character >= '0' && character <= '9')));
351}
352
353
354/*******************************************************************************
355 *
356 * FUNCTION: acpi_ut_strtoul64
357 *
358 * PARAMETERS: String - Null terminated string
359 * Base - Radix of the string: 10, 16, or ACPI_ANY_BASE
360 * ret_integer - Where the converted integer is returned
361 *
362 * RETURN: Status and Converted value
363 *
364 * DESCRIPTION: Convert a string into an unsigned value.
365 * NOTE: Does not support Octal strings, not needed.
366 *
367 ******************************************************************************/
368
369acpi_status
370acpi_ut_strtoul64 (
371 char *string,
372 u32 base,
373 acpi_integer *ret_integer)
374{
375 u32 this_digit = 0;
376 acpi_integer return_value = 0;
377 acpi_integer quotient;
378
379
380 ACPI_FUNCTION_TRACE ("ut_stroul64");
381
382
383 if ((!string) || !(*string)) {
384 goto error_exit;
385 }
386
387 switch (base) {
388 case ACPI_ANY_BASE:
389 case 10:
390 case 16:
391 break;
392
393 default:
394 /* Invalid Base */
395 return_ACPI_STATUS (AE_BAD_PARAMETER);
396 }
397
398 /* Skip over any white space in the buffer */
399
400 while (ACPI_IS_SPACE (*string) || *string == '\t') {
401 string++;
402 }
403
404 /*
405 * If the input parameter Base is zero, then we need to
406 * determine if it is decimal or hexadecimal:
407 */
408 if (base == 0) {
409 if ((*string == '0') &&
410 (ACPI_TOLOWER (*(string + 1)) == 'x')) {
411 base = 16;
412 string += 2;
413 }
414 else {
415 base = 10;
416 }
417 }
418
419 /*
420 * For hexadecimal base, skip over the leading
421 * 0 or 0x, if they are present.
422 */
423 if ((base == 16) &&
424 (*string == '0') &&
425 (ACPI_TOLOWER (*(string + 1)) == 'x')) {
426 string += 2;
427 }
428
429 /* Any string left? */
430
431 if (!(*string)) {
432 goto error_exit;
433 }
434
435 /* Main loop: convert the string to a 64-bit integer */
436
437 while (*string) {
438 if (ACPI_IS_DIGIT (*string)) {
439 /* Convert ASCII 0-9 to Decimal value */
440
441 this_digit = ((u8) *string) - '0';
442 }
443 else {
444 if (base == 10) {
445 /* Digit is out of range */
446
447 goto error_exit;
448 }
449
450 this_digit = (u8) ACPI_TOUPPER (*string);
451 if (ACPI_IS_XDIGIT ((char) this_digit)) {
452 /* Convert ASCII Hex char to value */
453
454 this_digit = this_digit - 'A' + 10;
455 }
456 else {
457 /*
458 * We allow non-hex chars, just stop now, same as end-of-string.
459 * See ACPI spec, string-to-integer conversion.
460 */
461 break;
462 }
463 }
464
465 /* Divide the digit into the correct position */
466
467 (void) acpi_ut_short_divide ((ACPI_INTEGER_MAX - (acpi_integer) this_digit),
468 base, &quotient, NULL);
469 if (return_value > quotient) {
470 goto error_exit;
471 }
472
473 return_value *= base;
474 return_value += this_digit;
475 string++;
476 }
477
478 /* All done, normal exit */
479
480 *ret_integer = return_value;
481 return_ACPI_STATUS (AE_OK);
482
483
484error_exit:
485 /* Base was set/validated above */
486
487 if (base == 10) {
488 return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT);
489 }
490 else {
491 return_ACPI_STATUS (AE_BAD_HEX_CONSTANT);
492 }
493}
494
495
496/*******************************************************************************
497 *
498 * FUNCTION: acpi_ut_strupr
499 *
500 * PARAMETERS: src_string - The source string to convert to
501 *
502 * RETURN: src_string
503 *
504 * DESCRIPTION: Convert string to uppercase
505 *
506 ******************************************************************************/
507#ifdef ACPI_FUTURE_USAGE
508char *
509acpi_ut_strupr (
510 char *src_string)
511{
512 char *string;
513
514
515 ACPI_FUNCTION_ENTRY ();
516
517
518 /* Walk entire string, uppercasing the letters */
519
520 for (string = src_string; *string; ) {
521 *string = (char) ACPI_TOUPPER (*string);
522 string++;
523 }
524
525 return (src_string);
526}
527#endif /* ACPI_FUTURE_USAGE */
528
529
530/*******************************************************************************
531 *
532 * FUNCTION: acpi_ut_mutex_initialize
533 *
534 * PARAMETERS: None.
535 *
536 * RETURN: Status
537 *
538 * DESCRIPTION: Create the system mutex objects.
539 *
540 ******************************************************************************/
541
542acpi_status
543acpi_ut_mutex_initialize (
544 void)
545{
546 u32 i;
547 acpi_status status;
548
549
550 ACPI_FUNCTION_TRACE ("ut_mutex_initialize");
551
552
553 /*
554 * Create each of the predefined mutex objects
555 */
556 for (i = 0; i < NUM_MUTEX; i++) {
557 status = acpi_ut_create_mutex (i);
558 if (ACPI_FAILURE (status)) {
559 return_ACPI_STATUS (status);
560 }
561 }
562
563 status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
564 return_ACPI_STATUS (status);
565}
566
567
568/*******************************************************************************
569 *
570 * FUNCTION: acpi_ut_mutex_terminate
571 *
572 * PARAMETERS: None.
573 *
574 * RETURN: None.
575 *
576 * DESCRIPTION: Delete all of the system mutex objects.
577 *
578 ******************************************************************************/
579
580void
581acpi_ut_mutex_terminate (
582 void)
583{
584 u32 i;
585
586
587 ACPI_FUNCTION_TRACE ("ut_mutex_terminate");
588
589
590 /*
591 * Delete each predefined mutex object
592 */
593 for (i = 0; i < NUM_MUTEX; i++) {
594 (void) acpi_ut_delete_mutex (i);
595 }
596
597 acpi_os_delete_lock (acpi_gbl_gpe_lock);
598 return_VOID;
599}
600
601
602/*******************************************************************************
603 *
604 * FUNCTION: acpi_ut_create_mutex
605 *
606 * PARAMETERS: mutex_iD - ID of the mutex to be created
607 *
608 * RETURN: Status
609 *
610 * DESCRIPTION: Create a mutex object.
611 *
612 ******************************************************************************/
613
614acpi_status
615acpi_ut_create_mutex (
616 acpi_mutex_handle mutex_id)
617{
618 acpi_status status = AE_OK;
619
620
621 ACPI_FUNCTION_TRACE_U32 ("ut_create_mutex", mutex_id);
622
623
624 if (mutex_id > MAX_MUTEX) {
625 return_ACPI_STATUS (AE_BAD_PARAMETER);
626 }
627
628 if (!acpi_gbl_mutex_info[mutex_id].mutex) {
629 status = acpi_os_create_semaphore (1, 1,
630 &acpi_gbl_mutex_info[mutex_id].mutex);
631 acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
632 acpi_gbl_mutex_info[mutex_id].use_count = 0;
633 }
634
635 return_ACPI_STATUS (status);
636}
637
638
639/*******************************************************************************
640 *
641 * FUNCTION: acpi_ut_delete_mutex
642 *
643 * PARAMETERS: mutex_iD - ID of the mutex to be deleted
644 *
645 * RETURN: Status
646 *
647 * DESCRIPTION: Delete a mutex object.
648 *
649 ******************************************************************************/
650
651acpi_status
652acpi_ut_delete_mutex (
653 acpi_mutex_handle mutex_id)
654{
655 acpi_status status;
656
657
658 ACPI_FUNCTION_TRACE_U32 ("ut_delete_mutex", mutex_id);
659
660
661 if (mutex_id > MAX_MUTEX) {
662 return_ACPI_STATUS (AE_BAD_PARAMETER);
663 }
664
665 status = acpi_os_delete_semaphore (acpi_gbl_mutex_info[mutex_id].mutex);
666
667 acpi_gbl_mutex_info[mutex_id].mutex = NULL;
668 acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
669
670 return_ACPI_STATUS (status);
671}
672
673
674/*******************************************************************************
675 *
676 * FUNCTION: acpi_ut_acquire_mutex
677 *
678 * PARAMETERS: mutex_iD - ID of the mutex to be acquired
679 *
680 * RETURN: Status
681 *
682 * DESCRIPTION: Acquire a mutex object.
683 *
684 ******************************************************************************/
685
686acpi_status
687acpi_ut_acquire_mutex (
688 acpi_mutex_handle mutex_id)
689{
690 acpi_status status;
691 u32 this_thread_id;
692
693
694 ACPI_FUNCTION_NAME ("ut_acquire_mutex");
695
696
697 if (mutex_id > MAX_MUTEX) {
698 return (AE_BAD_PARAMETER);
699 }
700
701 this_thread_id = acpi_os_get_thread_id ();
702
703#ifdef ACPI_MUTEX_DEBUG
704 {
705 u32 i;
706 /*
707 * Mutex debug code, for internal debugging only.
708 *
709 * Deadlock prevention. Check if this thread owns any mutexes of value
710 * greater than or equal to this one. If so, the thread has violated
711 * the mutex ordering rule. This indicates a coding error somewhere in
712 * the ACPI subsystem code.
713 */
714 for (i = mutex_id; i < MAX_MUTEX; i++) {
715 if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
716 if (i == mutex_id) {
717 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
718 "Mutex [%s] already acquired by this thread [%X]\n",
719 acpi_ut_get_mutex_name (mutex_id), this_thread_id));
720
721 return (AE_ALREADY_ACQUIRED);
722 }
723
724 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
725 "Invalid acquire order: Thread %X owns [%s], wants [%s]\n",
726 this_thread_id, acpi_ut_get_mutex_name (i),
727 acpi_ut_get_mutex_name (mutex_id)));
728
729 return (AE_ACQUIRE_DEADLOCK);
730 }
731 }
732 }
733#endif
734
735 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
736 "Thread %X attempting to acquire Mutex [%s]\n",
737 this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
738
739 status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex,
740 1, ACPI_WAIT_FOREVER);
741 if (ACPI_SUCCESS (status)) {
742 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n",
743 this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
744
745 acpi_gbl_mutex_info[mutex_id].use_count++;
746 acpi_gbl_mutex_info[mutex_id].owner_id = this_thread_id;
747 }
748 else {
749 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not acquire Mutex [%s] %s\n",
750 this_thread_id, acpi_ut_get_mutex_name (mutex_id),
751 acpi_format_exception (status)));
752 }
753
754 return (status);
755}
756
757
758/*******************************************************************************
759 *
760 * FUNCTION: acpi_ut_release_mutex
761 *
762 * PARAMETERS: mutex_iD - ID of the mutex to be released
763 *
764 * RETURN: Status
765 *
766 * DESCRIPTION: Release a mutex object.
767 *
768 ******************************************************************************/
769
770acpi_status
771acpi_ut_release_mutex (
772 acpi_mutex_handle mutex_id)
773{
774 acpi_status status;
775 u32 i;
776 u32 this_thread_id;
777
778
779 ACPI_FUNCTION_NAME ("ut_release_mutex");
780
781
782 this_thread_id = acpi_os_get_thread_id ();
783 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
784 "Thread %X releasing Mutex [%s]\n", this_thread_id,
785 acpi_ut_get_mutex_name (mutex_id)));
786
787 if (mutex_id > MAX_MUTEX) {
788 return (AE_BAD_PARAMETER);
789 }
790
791 /*
792 * Mutex must be acquired in order to release it!
793 */
794 if (acpi_gbl_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) {
795 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
796 "Mutex [%s] is not acquired, cannot release\n",
797 acpi_ut_get_mutex_name (mutex_id)));
798
799 return (AE_NOT_ACQUIRED);
800 }
801
802 /*
803 * Deadlock prevention. Check if this thread owns any mutexes of value
804 * greater than this one. If so, the thread has violated the mutex
805 * ordering rule. This indicates a coding error somewhere in
806 * the ACPI subsystem code.
807 */
808 for (i = mutex_id; i < MAX_MUTEX; i++) {
809 if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
810 if (i == mutex_id) {
811 continue;
812 }
813
814 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
815 "Invalid release order: owns [%s], releasing [%s]\n",
816 acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id)));
817
818 return (AE_RELEASE_DEADLOCK);
819 }
820 }
821
822 /* Mark unlocked FIRST */
823
824 acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
825
826 status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1);
827
828 if (ACPI_FAILURE (status)) {
829 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not release Mutex [%s] %s\n",
830 this_thread_id, acpi_ut_get_mutex_name (mutex_id),
831 acpi_format_exception (status)));
832 }
833 else {
834 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n",
835 this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
836 }
837
838 return (status);
839}
840
841
842/*******************************************************************************
843 *
844 * FUNCTION: acpi_ut_create_update_state_and_push
845 *
846 * PARAMETERS: *Object - Object to be added to the new state
847 * Action - Increment/Decrement
848 * state_list - List the state will be added to
849 *
850 * RETURN: None
851 *
852 * DESCRIPTION: Create a new state and push it
853 *
854 ******************************************************************************/
855
856acpi_status
857acpi_ut_create_update_state_and_push (
858 union acpi_operand_object *object,
859 u16 action,
860 union acpi_generic_state **state_list)
861{
862 union acpi_generic_state *state;
863
864
865 ACPI_FUNCTION_ENTRY ();
866
867
868 /* Ignore null objects; these are expected */
869
870 if (!object) {
871 return (AE_OK);
872 }
873
874 state = acpi_ut_create_update_state (object, action);
875 if (!state) {
876 return (AE_NO_MEMORY);
877 }
878
879 acpi_ut_push_generic_state (state_list, state);
880 return (AE_OK);
881}
882
883
884/*******************************************************************************
885 *
886 * FUNCTION: acpi_ut_create_pkg_state_and_push
887 *
888 * PARAMETERS: *Object - Object to be added to the new state
889 * Action - Increment/Decrement
890 * state_list - List the state will be added to
891 *
892 * RETURN: None
893 *
894 * DESCRIPTION: Create a new state and push it
895 *
896 ******************************************************************************/
897#ifdef ACPI_FUTURE_USAGE
898acpi_status
899acpi_ut_create_pkg_state_and_push (
900 void *internal_object,
901 void *external_object,
902 u16 index,
903 union acpi_generic_state **state_list)
904{
905 union acpi_generic_state *state;
906
907
908 ACPI_FUNCTION_ENTRY ();
909
910
911 state = acpi_ut_create_pkg_state (internal_object, external_object, index);
912 if (!state) {
913 return (AE_NO_MEMORY);
914 }
915
916 acpi_ut_push_generic_state (state_list, state);
917 return (AE_OK);
918}
919#endif /* ACPI_FUTURE_USAGE */
920
921/*******************************************************************************
922 *
923 * FUNCTION: acpi_ut_push_generic_state
924 *
925 * PARAMETERS: list_head - Head of the state stack
926 * State - State object to push
927 *
928 * RETURN: Status
929 *
930 * DESCRIPTION: Push a state object onto a state stack
931 *
932 ******************************************************************************/
933
934void
935acpi_ut_push_generic_state (
936 union acpi_generic_state **list_head,
937 union acpi_generic_state *state)
938{
939 ACPI_FUNCTION_TRACE ("ut_push_generic_state");
940
941
942 /* Push the state object onto the front of the list (stack) */
943
944 state->common.next = *list_head;
945 *list_head = state;
946
947 return_VOID;
948}
949
950
951/*******************************************************************************
952 *
953 * FUNCTION: acpi_ut_pop_generic_state
954 *
955 * PARAMETERS: list_head - Head of the state stack
956 *
957 * RETURN: Status
958 *
959 * DESCRIPTION: Pop a state object from a state stack
960 *
961 ******************************************************************************/
962
963union acpi_generic_state *
964acpi_ut_pop_generic_state (
965 union acpi_generic_state **list_head)
966{
967 union acpi_generic_state *state;
968
969
970 ACPI_FUNCTION_TRACE ("ut_pop_generic_state");
971
972
973 /* Remove the state object at the head of the list (stack) */
974
975 state = *list_head;
976 if (state) {
977 /* Update the list head */
978
979 *list_head = state->common.next;
980 }
981
982 return_PTR (state);
983}
984
985
986/*******************************************************************************
987 *
988 * FUNCTION: acpi_ut_create_generic_state
989 *
990 * PARAMETERS: None
991 *
992 * RETURN: Status
993 *
994 * DESCRIPTION: Create a generic state object. Attempt to obtain one from
995 * the global state cache; If none available, create a new one.
996 *
997 ******************************************************************************/
998
999union acpi_generic_state *
1000acpi_ut_create_generic_state (void)
1001{
1002 union acpi_generic_state *state;
1003
1004
1005 ACPI_FUNCTION_ENTRY ();
1006
1007
1008 state = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_STATE);
1009
1010 /* Initialize */
1011
1012 if (state) {
1013 state->common.data_type = ACPI_DESC_TYPE_STATE;
1014 }
1015
1016 return (state);
1017}
1018
1019
1020/*******************************************************************************
1021 *
1022 * FUNCTION: acpi_ut_create_thread_state
1023 *
1024 * PARAMETERS: None
1025 *
1026 * RETURN: Thread State
1027 *
1028 * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used
1029 * to track per-thread info during method execution
1030 *
1031 ******************************************************************************/
1032
1033struct acpi_thread_state *
1034acpi_ut_create_thread_state (
1035 void)
1036{
1037 union acpi_generic_state *state;
1038
1039
1040 ACPI_FUNCTION_TRACE ("ut_create_thread_state");
1041
1042
1043 /* Create the generic state object */
1044
1045 state = acpi_ut_create_generic_state ();
1046 if (!state) {
1047 return_PTR (NULL);
1048 }
1049
1050 /* Init fields specific to the update struct */
1051
1052 state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD;
1053 state->thread.thread_id = acpi_os_get_thread_id ();
1054
1055 return_PTR ((struct acpi_thread_state *) state);
1056}
1057
1058
1059/*******************************************************************************
1060 *
1061 * FUNCTION: acpi_ut_create_update_state
1062 *
1063 * PARAMETERS: Object - Initial Object to be installed in the
1064 * state
1065 * Action - Update action to be performed
1066 *
1067 * RETURN: Status
1068 *
1069 * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
1070 * to update reference counts and delete complex objects such
1071 * as packages.
1072 *
1073 ******************************************************************************/
1074
1075union acpi_generic_state *
1076acpi_ut_create_update_state (
1077 union acpi_operand_object *object,
1078 u16 action)
1079{
1080 union acpi_generic_state *state;
1081
1082
1083 ACPI_FUNCTION_TRACE_PTR ("ut_create_update_state", object);
1084
1085
1086 /* Create the generic state object */
1087
1088 state = acpi_ut_create_generic_state ();
1089 if (!state) {
1090 return_PTR (NULL);
1091 }
1092
1093 /* Init fields specific to the update struct */
1094
1095 state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE;
1096 state->update.object = object;
1097 state->update.value = action;
1098
1099 return_PTR (state);
1100}
1101
1102
1103/*******************************************************************************
1104 *
1105 * FUNCTION: acpi_ut_create_pkg_state
1106 *
1107 * PARAMETERS: Object - Initial Object to be installed in the
1108 * state
1109 * Action - Update action to be performed
1110 *
1111 * RETURN: Status
1112 *
1113 * DESCRIPTION: Create a "Package State"
1114 *
1115 ******************************************************************************/
1116
1117union acpi_generic_state *
1118acpi_ut_create_pkg_state (
1119 void *internal_object,
1120 void *external_object,
1121 u16 index)
1122{
1123 union acpi_generic_state *state;
1124
1125
1126 ACPI_FUNCTION_TRACE_PTR ("ut_create_pkg_state", internal_object);
1127
1128
1129 /* Create the generic state object */
1130
1131 state = acpi_ut_create_generic_state ();
1132 if (!state) {
1133 return_PTR (NULL);
1134 }
1135
1136 /* Init fields specific to the update struct */
1137
1138 state->common.data_type = ACPI_DESC_TYPE_STATE_PACKAGE;
1139 state->pkg.source_object = (union acpi_operand_object *) internal_object;
1140 state->pkg.dest_object = external_object;
1141 state->pkg.index = index;
1142 state->pkg.num_packages = 1;
1143
1144 return_PTR (state);
1145}
1146
1147
1148/*******************************************************************************
1149 *
1150 * FUNCTION: acpi_ut_create_control_state
1151 *
1152 * PARAMETERS: None
1153 *
1154 * RETURN: Status
1155 *
1156 * DESCRIPTION: Create a "Control State" - a flavor of the generic state used
1157 * to support nested IF/WHILE constructs in the AML.
1158 *
1159 ******************************************************************************/
1160
1161union acpi_generic_state *
1162acpi_ut_create_control_state (
1163 void)
1164{
1165 union acpi_generic_state *state;
1166
1167
1168 ACPI_FUNCTION_TRACE ("ut_create_control_state");
1169
1170
1171 /* Create the generic state object */
1172
1173 state = acpi_ut_create_generic_state ();
1174 if (!state) {
1175 return_PTR (NULL);
1176 }
1177
1178 /* Init fields specific to the control struct */
1179
1180 state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL;
1181 state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING;
1182
1183 return_PTR (state);
1184}
1185
1186
1187/*******************************************************************************
1188 *
1189 * FUNCTION: acpi_ut_delete_generic_state
1190 *
1191 * PARAMETERS: State - The state object to be deleted
1192 *
1193 * RETURN: Status
1194 *
1195 * DESCRIPTION: Put a state object back into the global state cache. The object
1196 * is not actually freed at this time.
1197 *
1198 ******************************************************************************/
1199
1200void
1201acpi_ut_delete_generic_state (
1202 union acpi_generic_state *state)
1203{
1204 ACPI_FUNCTION_TRACE ("ut_delete_generic_state");
1205
1206
1207 acpi_ut_release_to_cache (ACPI_MEM_LIST_STATE, state);
1208 return_VOID;
1209}
1210
1211
1212#ifdef ACPI_ENABLE_OBJECT_CACHE
1213/*******************************************************************************
1214 *
1215 * FUNCTION: acpi_ut_delete_generic_state_cache
1216 *
1217 * PARAMETERS: None
1218 *
1219 * RETURN: Status
1220 *
1221 * DESCRIPTION: Purge the global state object cache. Used during subsystem
1222 * termination.
1223 *
1224 ******************************************************************************/
1225
1226void
1227acpi_ut_delete_generic_state_cache (
1228 void)
1229{
1230 ACPI_FUNCTION_TRACE ("ut_delete_generic_state_cache");
1231
1232
1233 acpi_ut_delete_generic_cache (ACPI_MEM_LIST_STATE);
1234 return_VOID;
1235}
1236#endif
1237
1238
1239/*******************************************************************************
1240 *
1241 * FUNCTION: acpi_ut_walk_package_tree
1242 *
1243 * PARAMETERS: obj_desc - The Package object on which to resolve refs
1244 *
1245 * RETURN: Status
1246 *
1247 * DESCRIPTION: Walk through a package
1248 *
1249 ******************************************************************************/
1250
1251acpi_status
1252acpi_ut_walk_package_tree (
1253 union acpi_operand_object *source_object,
1254 void *target_object,
1255 acpi_pkg_callback walk_callback,
1256 void *context)
1257{
1258 acpi_status status = AE_OK;
1259 union acpi_generic_state *state_list = NULL;
1260 union acpi_generic_state *state;
1261 u32 this_index;
1262 union acpi_operand_object *this_source_obj;
1263
1264
1265 ACPI_FUNCTION_TRACE ("ut_walk_package_tree");
1266
1267
1268 state = acpi_ut_create_pkg_state (source_object, target_object, 0);
1269 if (!state) {
1270 return_ACPI_STATUS (AE_NO_MEMORY);
1271 }
1272
1273 while (state) {
1274 /* Get one element of the package */
1275
1276 this_index = state->pkg.index;
1277 this_source_obj = (union acpi_operand_object *)
1278 state->pkg.source_object->package.elements[this_index];
1279
1280 /*
1281 * Check for:
1282 * 1) An uninitialized package element. It is completely
1283 * legal to declare a package and leave it uninitialized
1284 * 2) Not an internal object - can be a namespace node instead
1285 * 3) Any type other than a package. Packages are handled in else
1286 * case below.
1287 */
1288 if ((!this_source_obj) ||
1289 (ACPI_GET_DESCRIPTOR_TYPE (this_source_obj) != ACPI_DESC_TYPE_OPERAND) ||
1290 (ACPI_GET_OBJECT_TYPE (this_source_obj) != ACPI_TYPE_PACKAGE)) {
1291 status = walk_callback (ACPI_COPY_TYPE_SIMPLE, this_source_obj,
1292 state, context);
1293 if (ACPI_FAILURE (status)) {
1294 return_ACPI_STATUS (status);
1295 }
1296
1297 state->pkg.index++;
1298 while (state->pkg.index >= state->pkg.source_object->package.count) {
1299 /*
1300 * We've handled all of the objects at this level, This means
1301 * that we have just completed a package. That package may
1302 * have contained one or more packages itself.
1303 *
1304 * Delete this state and pop the previous state (package).
1305 */
1306 acpi_ut_delete_generic_state (state);
1307 state = acpi_ut_pop_generic_state (&state_list);
1308
1309 /* Finished when there are no more states */
1310
1311 if (!state) {
1312 /*
1313 * We have handled all of the objects in the top level
1314 * package just add the length of the package objects
1315 * and exit
1316 */
1317 return_ACPI_STATUS (AE_OK);
1318 }
1319
1320 /*
1321 * Go back up a level and move the index past the just
1322 * completed package object.
1323 */
1324 state->pkg.index++;
1325 }
1326 }
1327 else {
1328 /* This is a subobject of type package */
1329
1330 status = walk_callback (ACPI_COPY_TYPE_PACKAGE, this_source_obj,
1331 state, context);
1332 if (ACPI_FAILURE (status)) {
1333 return_ACPI_STATUS (status);
1334 }
1335
1336 /*
1337 * Push the current state and create a new one
1338 * The callback above returned a new target package object.
1339 */
1340 acpi_ut_push_generic_state (&state_list, state);
1341 state = acpi_ut_create_pkg_state (this_source_obj,
1342 state->pkg.this_target_obj, 0);
1343 if (!state) {
1344 return_ACPI_STATUS (AE_NO_MEMORY);
1345 }
1346 }
1347 }
1348
1349 /* We should never get here */
1350
1351 return_ACPI_STATUS (AE_AML_INTERNAL);
1352}
1353
1354
1355/*******************************************************************************
1356 *
1357 * FUNCTION: acpi_ut_generate_checksum
1358 *
1359 * PARAMETERS: Buffer - Buffer to be scanned
1360 * Length - number of bytes to examine
1361 *
1362 * RETURN: checksum
1363 *
1364 * DESCRIPTION: Generate a checksum on a raw buffer
1365 *
1366 ******************************************************************************/
1367
1368u8
1369acpi_ut_generate_checksum (
1370 u8 *buffer,
1371 u32 length)
1372{
1373 u32 i;
1374 signed char sum = 0;
1375
1376
1377 for (i = 0; i < length; i++) {
1378 sum = (signed char) (sum + buffer[i]);
1379 }
1380
1381 return ((u8) (0 - sum));
1382}
1383
1384
1385/*******************************************************************************
1386 *
1387 * FUNCTION: acpi_ut_get_resource_end_tag
1388 *
1389 * PARAMETERS: obj_desc - The resource template buffer object
1390 *
1391 * RETURN: Pointer to the end tag
1392 *
1393 * DESCRIPTION: Find the END_TAG resource descriptor in a resource template
1394 *
1395 ******************************************************************************/
1396
1397
1398u8 *
1399acpi_ut_get_resource_end_tag (
1400 union acpi_operand_object *obj_desc)
1401{
1402 u8 buffer_byte;
1403 u8 *buffer;
1404 u8 *end_buffer;
1405
1406
1407 buffer = obj_desc->buffer.pointer;
1408 end_buffer = buffer + obj_desc->buffer.length;
1409
1410 while (buffer < end_buffer) {
1411 buffer_byte = *buffer;
1412 if (buffer_byte & ACPI_RDESC_TYPE_MASK) {
1413 /* Large Descriptor - Length is next 2 bytes */
1414
1415 buffer += ((*(buffer+1) | (*(buffer+2) << 8)) + 3);
1416 }
1417 else {
1418 /* Small Descriptor. End Tag will be found here */
1419
1420 if ((buffer_byte & ACPI_RDESC_SMALL_MASK) == ACPI_RDESC_TYPE_END_TAG) {
1421 /* Found the end tag descriptor, all done. */
1422
1423 return (buffer);
1424 }
1425
1426 /* Length is in the header */
1427
1428 buffer += ((buffer_byte & 0x07) + 1);
1429 }
1430 }
1431
1432 /* End tag not found */
1433
1434 return (NULL);
1435}
1436
1437
1438/*******************************************************************************
1439 *
1440 * FUNCTION: acpi_ut_report_error
1441 *
1442 * PARAMETERS: module_name - Caller's module name (for error output)
1443 * line_number - Caller's line number (for error output)
1444 * component_id - Caller's component ID (for error output)
1445 * Message - Error message to use on failure
1446 *
1447 * RETURN: None
1448 *
1449 * DESCRIPTION: Print error message
1450 *
1451 ******************************************************************************/
1452
1453void
1454acpi_ut_report_error (
1455 char *module_name,
1456 u32 line_number,
1457 u32 component_id)
1458{
1459
1460
1461 acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number);
1462}
1463
1464
1465/*******************************************************************************
1466 *
1467 * FUNCTION: acpi_ut_report_warning
1468 *
1469 * PARAMETERS: module_name - Caller's module name (for error output)
1470 * line_number - Caller's line number (for error output)
1471 * component_id - Caller's component ID (for error output)
1472 * Message - Error message to use on failure
1473 *
1474 * RETURN: None
1475 *
1476 * DESCRIPTION: Print warning message
1477 *
1478 ******************************************************************************/
1479
1480void
1481acpi_ut_report_warning (
1482 char *module_name,
1483 u32 line_number,
1484 u32 component_id)
1485{
1486
1487 acpi_os_printf ("%8s-%04d: *** Warning: ", module_name, line_number);
1488}
1489
1490
1491/*******************************************************************************
1492 *
1493 * FUNCTION: acpi_ut_report_info
1494 *
1495 * PARAMETERS: module_name - Caller's module name (for error output)
1496 * line_number - Caller's line number (for error output)
1497 * component_id - Caller's component ID (for error output)
1498 * Message - Error message to use on failure
1499 *
1500 * RETURN: None
1501 *
1502 * DESCRIPTION: Print information message
1503 *
1504 ******************************************************************************/
1505
1506void
1507acpi_ut_report_info (
1508 char *module_name,
1509 u32 line_number,
1510 u32 component_id)
1511{
1512
1513 acpi_os_printf ("%8s-%04d: *** Info: ", module_name, line_number);
1514}
1515
1516
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
new file mode 100644
index 000000000000..9ee40a484e07
--- /dev/null
+++ b/drivers/acpi/utilities/utobject.c
@@ -0,0 +1,671 @@
1/******************************************************************************
2 *
3 * Module Name: utobject - ACPI object create/delete/size/cache routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/amlcode.h>
48
49
50#define _COMPONENT ACPI_UTILITIES
51 ACPI_MODULE_NAME ("utobject")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ut_create_internal_object_dbg
57 *
58 * PARAMETERS: module_name - Source file name of caller
59 * line_number - Line number of caller
60 * component_id - Component type of caller
61 * Type - ACPI Type of the new object
62 *
63 * RETURN: Object - The new object. Null on failure
64 *
65 * DESCRIPTION: Create and initialize a new internal object.
66 *
67 * NOTE: We always allocate the worst-case object descriptor because
68 * these objects are cached, and we want them to be
69 * one-size-satisifies-any-request. This in itself may not be
70 * the most memory efficient, but the efficiency of the object
71 * cache should more than make up for this!
72 *
73 ******************************************************************************/
74
75union acpi_operand_object *
76acpi_ut_create_internal_object_dbg (
77 char *module_name,
78 u32 line_number,
79 u32 component_id,
80 acpi_object_type type)
81{
82 union acpi_operand_object *object;
83 union acpi_operand_object *second_object;
84
85
86 ACPI_FUNCTION_TRACE_STR ("ut_create_internal_object_dbg", acpi_ut_get_type_name (type));
87
88
89 /* Allocate the raw object descriptor */
90
91 object = acpi_ut_allocate_object_desc_dbg (module_name, line_number, component_id);
92 if (!object) {
93 return_PTR (NULL);
94 }
95
96 switch (type) {
97 case ACPI_TYPE_REGION:
98 case ACPI_TYPE_BUFFER_FIELD:
99
100 /* These types require a secondary object */
101
102 second_object = acpi_ut_allocate_object_desc_dbg (module_name, line_number, component_id);
103 if (!second_object) {
104 acpi_ut_delete_object_desc (object);
105 return_PTR (NULL);
106 }
107
108 second_object->common.type = ACPI_TYPE_LOCAL_EXTRA;
109 second_object->common.reference_count = 1;
110
111 /* Link the second object to the first */
112
113 object->common.next_object = second_object;
114 break;
115
116 default:
117 /* All others have no secondary object */
118 break;
119 }
120
121 /* Save the object type in the object descriptor */
122
123 object->common.type = (u8) type;
124
125 /* Init the reference count */
126
127 object->common.reference_count = 1;
128
129 /* Any per-type initialization should go here */
130
131 return_PTR (object);
132}
133
134
135/*******************************************************************************
136 *
137 * FUNCTION: acpi_ut_create_buffer_object
138 *
139 * PARAMETERS: buffer_size - Size of buffer to be created
140 *
141 * RETURN: Pointer to a new Buffer object
142 *
143 * DESCRIPTION: Create a fully initialized buffer object
144 *
145 ******************************************************************************/
146
147union acpi_operand_object *
148acpi_ut_create_buffer_object (
149 acpi_size buffer_size)
150{
151 union acpi_operand_object *buffer_desc;
152 u8 *buffer = NULL;
153
154
155 ACPI_FUNCTION_TRACE_U32 ("ut_create_buffer_object", buffer_size);
156
157
158 /* Create a new Buffer object */
159
160 buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
161 if (!buffer_desc) {
162 return_PTR (NULL);
163 }
164
165 /* Create an actual buffer only if size > 0 */
166
167 if (buffer_size > 0) {
168 /* Allocate the actual buffer */
169
170 buffer = ACPI_MEM_CALLOCATE (buffer_size);
171 if (!buffer) {
172 ACPI_REPORT_ERROR (("create_buffer: could not allocate size %X\n",
173 (u32) buffer_size));
174 acpi_ut_remove_reference (buffer_desc);
175 return_PTR (NULL);
176 }
177 }
178
179 /* Complete buffer object initialization */
180
181 buffer_desc->buffer.flags |= AOPOBJ_DATA_VALID;
182 buffer_desc->buffer.pointer = buffer;
183 buffer_desc->buffer.length = (u32) buffer_size;
184
185 /* Return the new buffer descriptor */
186
187 return_PTR (buffer_desc);
188}
189
190
191/*******************************************************************************
192 *
193 * FUNCTION: acpi_ut_create_string_object
194 *
195 * PARAMETERS: string_size - Size of string to be created. Does not
196 * include NULL terminator, this is added
197 * automatically.
198 *
199 * RETURN: Pointer to a new String object
200 *
201 * DESCRIPTION: Create a fully initialized string object
202 *
203 ******************************************************************************/
204
205union acpi_operand_object *
206acpi_ut_create_string_object (
207 acpi_size string_size)
208{
209 union acpi_operand_object *string_desc;
210 char *string;
211
212
213 ACPI_FUNCTION_TRACE_U32 ("ut_create_string_object", string_size);
214
215
216 /* Create a new String object */
217
218 string_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
219 if (!string_desc) {
220 return_PTR (NULL);
221 }
222
223 /*
224 * Allocate the actual string buffer -- (Size + 1) for NULL terminator.
225 * NOTE: Zero-length strings are NULL terminated
226 */
227 string = ACPI_MEM_CALLOCATE (string_size + 1);
228 if (!string) {
229 ACPI_REPORT_ERROR (("create_string: could not allocate size %X\n",
230 (u32) string_size));
231 acpi_ut_remove_reference (string_desc);
232 return_PTR (NULL);
233 }
234
235 /* Complete string object initialization */
236
237 string_desc->string.pointer = string;
238 string_desc->string.length = (u32) string_size;
239
240 /* Return the new string descriptor */
241
242 return_PTR (string_desc);
243}
244
245
246/*******************************************************************************
247 *
248 * FUNCTION: acpi_ut_valid_internal_object
249 *
250 * PARAMETERS: Object - Object to be validated
251 *
252 * RETURN: Validate a pointer to be an union acpi_operand_object
253 *
254 ******************************************************************************/
255
256u8
257acpi_ut_valid_internal_object (
258 void *object)
259{
260
261 ACPI_FUNCTION_NAME ("ut_valid_internal_object");
262
263
264 /* Check for a null pointer */
265
266 if (!object) {
267 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Null Object Ptr\n"));
268 return (FALSE);
269 }
270
271 /* Check the descriptor type field */
272
273 switch (ACPI_GET_DESCRIPTOR_TYPE (object)) {
274 case ACPI_DESC_TYPE_OPERAND:
275
276 /* The object appears to be a valid union acpi_operand_object */
277
278 return (TRUE);
279
280 default:
281 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
282 "%p is not not an ACPI operand obj [%s]\n",
283 object, acpi_ut_get_descriptor_name (object)));
284 break;
285 }
286
287 return (FALSE);
288}
289
290
291/*******************************************************************************
292 *
293 * FUNCTION: acpi_ut_allocate_object_desc_dbg
294 *
295 * PARAMETERS: module_name - Caller's module name (for error output)
296 * line_number - Caller's line number (for error output)
297 * component_id - Caller's component ID (for error output)
298 *
299 * RETURN: Pointer to newly allocated object descriptor. Null on error
300 *
301 * DESCRIPTION: Allocate a new object descriptor. Gracefully handle
302 * error conditions.
303 *
304 ******************************************************************************/
305
306void *
307acpi_ut_allocate_object_desc_dbg (
308 char *module_name,
309 u32 line_number,
310 u32 component_id)
311{
312 union acpi_operand_object *object;
313
314
315 ACPI_FUNCTION_TRACE ("ut_allocate_object_desc_dbg");
316
317
318 object = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_OPERAND);
319 if (!object) {
320 _ACPI_REPORT_ERROR (module_name, line_number, component_id,
321 ("Could not allocate an object descriptor\n"));
322
323 return_PTR (NULL);
324 }
325
326 /* Mark the descriptor type */
327
328 ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_OPERAND);
329
330 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p Size %X\n",
331 object, (u32) sizeof (union acpi_operand_object)));
332
333 return_PTR (object);
334}
335
336
337/*******************************************************************************
338 *
339 * FUNCTION: acpi_ut_delete_object_desc
340 *
341 * PARAMETERS: Object - An Acpi internal object to be deleted
342 *
343 * RETURN: None.
344 *
345 * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache
346 *
347 ******************************************************************************/
348
349void
350acpi_ut_delete_object_desc (
351 union acpi_operand_object *object)
352{
353 ACPI_FUNCTION_TRACE_PTR ("ut_delete_object_desc", object);
354
355
356 /* Object must be an union acpi_operand_object */
357
358 if (ACPI_GET_DESCRIPTOR_TYPE (object) != ACPI_DESC_TYPE_OPERAND) {
359 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
360 "%p is not an ACPI Operand object [%s]\n", object,
361 acpi_ut_get_descriptor_name (object)));
362 return_VOID;
363 }
364
365 acpi_ut_release_to_cache (ACPI_MEM_LIST_OPERAND, object);
366
367 return_VOID;
368}
369
370
371#ifdef ACPI_ENABLE_OBJECT_CACHE
372/*******************************************************************************
373 *
374 * FUNCTION: acpi_ut_delete_object_cache
375 *
376 * PARAMETERS: None
377 *
378 * RETURN: None
379 *
380 * DESCRIPTION: Purge the global state object cache. Used during subsystem
381 * termination.
382 *
383 ******************************************************************************/
384
385void
386acpi_ut_delete_object_cache (
387 void)
388{
389 ACPI_FUNCTION_TRACE ("ut_delete_object_cache");
390
391
392 acpi_ut_delete_generic_cache (ACPI_MEM_LIST_OPERAND);
393 return_VOID;
394}
395#endif
396
397
398/*******************************************************************************
399 *
400 * FUNCTION: acpi_ut_get_simple_object_size
401 *
402 * PARAMETERS: *internal_object - Pointer to the object we are examining
403 * *obj_length - Where the length is returned
404 *
405 * RETURN: Status
406 *
407 * DESCRIPTION: This function is called to determine the space required to
408 * contain a simple object for return to an external user.
409 *
410 * The length includes the object structure plus any additional
411 * needed space.
412 *
413 ******************************************************************************/
414
415acpi_status
416acpi_ut_get_simple_object_size (
417 union acpi_operand_object *internal_object,
418 acpi_size *obj_length)
419{
420 acpi_size length;
421 acpi_status status = AE_OK;
422
423
424 ACPI_FUNCTION_TRACE_PTR ("ut_get_simple_object_size", internal_object);
425
426
427 /* Handle a null object (Could be a uninitialized package element -- which is legal) */
428
429 if (!internal_object) {
430 *obj_length = 0;
431 return_ACPI_STATUS (AE_OK);
432 }
433
434 /* Start with the length of the Acpi object */
435
436 length = sizeof (union acpi_object);
437
438 if (ACPI_GET_DESCRIPTOR_TYPE (internal_object) == ACPI_DESC_TYPE_NAMED) {
439 /* Object is a named object (reference), just return the length */
440
441 *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD (length);
442 return_ACPI_STATUS (status);
443 }
444
445 /*
446 * The final length depends on the object type
447 * Strings and Buffers are packed right up against the parent object and
448 * must be accessed bytewise or there may be alignment problems on
449 * certain processors
450 */
451 switch (ACPI_GET_OBJECT_TYPE (internal_object)) {
452 case ACPI_TYPE_STRING:
453
454 length += (acpi_size) internal_object->string.length + 1;
455 break;
456
457
458 case ACPI_TYPE_BUFFER:
459
460 length += (acpi_size) internal_object->buffer.length;
461 break;
462
463
464 case ACPI_TYPE_INTEGER:
465 case ACPI_TYPE_PROCESSOR:
466 case ACPI_TYPE_POWER:
467
468 /*
469 * No extra data for these types
470 */
471 break;
472
473
474 case ACPI_TYPE_LOCAL_REFERENCE:
475
476 switch (internal_object->reference.opcode) {
477 case AML_INT_NAMEPATH_OP:
478
479 /*
480 * Get the actual length of the full pathname to this object.
481 * The reference will be converted to the pathname to the object
482 */
483 length += ACPI_ROUND_UP_TO_NATIVE_WORD (acpi_ns_get_pathname_length (internal_object->reference.node));
484 break;
485
486 default:
487
488 /*
489 * No other reference opcodes are supported.
490 * Notably, Locals and Args are not supported, but this may be
491 * required eventually.
492 */
493 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
494 "Unsupported Reference opcode=%X in object %p\n",
495 internal_object->reference.opcode, internal_object));
496 status = AE_TYPE;
497 break;
498 }
499 break;
500
501
502 default:
503
504 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported type=%X in object %p\n",
505 ACPI_GET_OBJECT_TYPE (internal_object), internal_object));
506 status = AE_TYPE;
507 break;
508 }
509
510 /*
511 * Account for the space required by the object rounded up to the next
512 * multiple of the machine word size. This keeps each object aligned
513 * on a machine word boundary. (preventing alignment faults on some
514 * machines.)
515 */
516 *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD (length);
517 return_ACPI_STATUS (status);
518}
519
520
521/*******************************************************************************
522 *
523 * FUNCTION: acpi_ut_get_element_length
524 *
525 * PARAMETERS: acpi_pkg_callback
526 *
527 * RETURN: Status
528 *
529 * DESCRIPTION: Get the length of one package element.
530 *
531 ******************************************************************************/
532
533acpi_status
534acpi_ut_get_element_length (
535 u8 object_type,
536 union acpi_operand_object *source_object,
537 union acpi_generic_state *state,
538 void *context)
539{
540 acpi_status status = AE_OK;
541 struct acpi_pkg_info *info = (struct acpi_pkg_info *) context;
542 acpi_size object_space;
543
544
545 switch (object_type) {
546 case ACPI_COPY_TYPE_SIMPLE:
547
548 /*
549 * Simple object - just get the size (Null object/entry is handled
550 * here also) and sum it into the running package length
551 */
552 status = acpi_ut_get_simple_object_size (source_object, &object_space);
553 if (ACPI_FAILURE (status)) {
554 return (status);
555 }
556
557 info->length += object_space;
558 break;
559
560
561 case ACPI_COPY_TYPE_PACKAGE:
562
563 /* Package object - nothing much to do here, let the walk handle it */
564
565 info->num_packages++;
566 state->pkg.this_target_obj = NULL;
567 break;
568
569
570 default:
571
572 /* No other types allowed */
573
574 return (AE_BAD_PARAMETER);
575 }
576
577 return (status);
578}
579
580
581/*******************************************************************************
582 *
583 * FUNCTION: acpi_ut_get_package_object_size
584 *
585 * PARAMETERS: *internal_object - Pointer to the object we are examining
586 * *obj_length - Where the length is returned
587 *
588 * RETURN: Status
589 *
590 * DESCRIPTION: This function is called to determine the space required to
591 * contain a package object for return to an external user.
592 *
593 * This is moderately complex since a package contains other
594 * objects including packages.
595 *
596 ******************************************************************************/
597
598acpi_status
599acpi_ut_get_package_object_size (
600 union acpi_operand_object *internal_object,
601 acpi_size *obj_length)
602{
603 acpi_status status;
604 struct acpi_pkg_info info;
605
606
607 ACPI_FUNCTION_TRACE_PTR ("ut_get_package_object_size", internal_object);
608
609
610 info.length = 0;
611 info.object_space = 0;
612 info.num_packages = 1;
613
614 status = acpi_ut_walk_package_tree (internal_object, NULL,
615 acpi_ut_get_element_length, &info);
616 if (ACPI_FAILURE (status)) {
617 return_ACPI_STATUS (status);
618 }
619
620 /*
621 * We have handled all of the objects in all levels of the package.
622 * just add the length of the package objects themselves.
623 * Round up to the next machine word.
624 */
625 info.length += ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object)) *
626 (acpi_size) info.num_packages;
627
628 /* Return the total package length */
629
630 *obj_length = info.length;
631 return_ACPI_STATUS (status);
632}
633
634
635/*******************************************************************************
636 *
637 * FUNCTION: acpi_ut_get_object_size
638 *
639 * PARAMETERS: *internal_object - Pointer to the object we are examining
640 * *obj_length - Where the length will be returned
641 *
642 * RETURN: Status
643 *
644 * DESCRIPTION: This function is called to determine the space required to
645 * contain an object for return to an API user.
646 *
647 ******************************************************************************/
648
649acpi_status
650acpi_ut_get_object_size(
651 union acpi_operand_object *internal_object,
652 acpi_size *obj_length)
653{
654 acpi_status status;
655
656
657 ACPI_FUNCTION_ENTRY ();
658
659
660 if ((ACPI_GET_DESCRIPTOR_TYPE (internal_object) == ACPI_DESC_TYPE_OPERAND) &&
661 (ACPI_GET_OBJECT_TYPE (internal_object) == ACPI_TYPE_PACKAGE)) {
662 status = acpi_ut_get_package_object_size (internal_object, obj_length);
663 }
664 else {
665 status = acpi_ut_get_simple_object_size (internal_object, obj_length);
666 }
667
668 return (status);
669}
670
671
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
new file mode 100644
index 000000000000..97a91f3f06f0
--- /dev/null
+++ b/drivers/acpi/utilities/utxface.c
@@ -0,0 +1,525 @@
1/******************************************************************************
2 *
3 * Module Name: utxface - External interfaces for "global" ACPI functions
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <linux/module.h>
45
46#include <acpi/acpi.h>
47#include <acpi/acevents.h>
48#include <acpi/acnamesp.h>
49#include <acpi/acparser.h>
50#include <acpi/acdispat.h>
51#include <acpi/acdebug.h>
52
53#define _COMPONENT ACPI_UTILITIES
54 ACPI_MODULE_NAME ("utxface")
55
56
57/*******************************************************************************
58 *
59 * FUNCTION: acpi_initialize_subsystem
60 *
61 * PARAMETERS: None
62 *
63 * RETURN: Status
64 *
65 * DESCRIPTION: Initializes all global variables. This is the first function
66 * called, so any early initialization belongs here.
67 *
68 ******************************************************************************/
69
70acpi_status
71acpi_initialize_subsystem (
72 void)
73{
74 acpi_status status;
75
76 ACPI_FUNCTION_TRACE ("acpi_initialize_subsystem");
77
78
79 ACPI_DEBUG_EXEC (acpi_ut_init_stack_ptr_trace ());
80
81
82 /* Initialize all globals used by the subsystem */
83
84 acpi_ut_init_globals ();
85
86 /* Initialize the OS-Dependent layer */
87
88 status = acpi_os_initialize ();
89 if (ACPI_FAILURE (status)) {
90 ACPI_REPORT_ERROR (("OSD failed to initialize, %s\n",
91 acpi_format_exception (status)));
92 return_ACPI_STATUS (status);
93 }
94
95 /* Create the default mutex objects */
96
97 status = acpi_ut_mutex_initialize ();
98 if (ACPI_FAILURE (status)) {
99 ACPI_REPORT_ERROR (("Global mutex creation failure, %s\n",
100 acpi_format_exception (status)));
101 return_ACPI_STATUS (status);
102 }
103
104 /*
105 * Initialize the namespace manager and
106 * the root of the namespace tree
107 */
108
109 status = acpi_ns_root_initialize ();
110 if (ACPI_FAILURE (status)) {
111 ACPI_REPORT_ERROR (("Namespace initialization failure, %s\n",
112 acpi_format_exception (status)));
113 return_ACPI_STATUS (status);
114 }
115
116
117 /* If configured, initialize the AML debugger */
118
119 ACPI_DEBUGGER_EXEC (status = acpi_db_initialize ());
120
121 return_ACPI_STATUS (status);
122}
123
124
125/*******************************************************************************
126 *
127 * FUNCTION: acpi_enable_subsystem
128 *
129 * PARAMETERS: Flags - Init/enable Options
130 *
131 * RETURN: Status
132 *
133 * DESCRIPTION: Completes the subsystem initialization including hardware.
134 * Puts system into ACPI mode if it isn't already.
135 *
136 ******************************************************************************/
137
138acpi_status
139acpi_enable_subsystem (
140 u32 flags)
141{
142 acpi_status status = AE_OK;
143
144
145 ACPI_FUNCTION_TRACE ("acpi_enable_subsystem");
146
147
148 /*
149 * We must initialize the hardware before we can enable ACPI.
150 * The values from the FADT are validated here.
151 */
152 if (!(flags & ACPI_NO_HARDWARE_INIT)) {
153 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI hardware\n"));
154
155 status = acpi_hw_initialize ();
156 if (ACPI_FAILURE (status)) {
157 return_ACPI_STATUS (status);
158 }
159 }
160
161 /* Enable ACPI mode */
162
163 if (!(flags & ACPI_NO_ACPI_ENABLE)) {
164 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n"));
165
166 acpi_gbl_original_mode = acpi_hw_get_mode();
167
168 status = acpi_enable ();
169 if (ACPI_FAILURE (status)) {
170 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "acpi_enable failed.\n"));
171 return_ACPI_STATUS (status);
172 }
173 }
174
175 /*
176 * Install the default op_region handlers. These are installed unless
177 * other handlers have already been installed via the
178 * install_address_space_handler interface.
179 */
180 if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
181 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n"));
182
183 status = acpi_ev_install_region_handlers ();
184 if (ACPI_FAILURE (status)) {
185 return_ACPI_STATUS (status);
186 }
187 }
188
189 /*
190 * Initialize ACPI Event handling (Fixed and General Purpose)
191 *
192 * NOTE: We must have the hardware AND events initialized before we can execute
193 * ANY control methods SAFELY. Any control method can require ACPI hardware
194 * support, so the hardware MUST be initialized before execution!
195 */
196 if (!(flags & ACPI_NO_EVENT_INIT)) {
197 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI events\n"));
198
199 status = acpi_ev_initialize_events ();
200 if (ACPI_FAILURE (status)) {
201 return_ACPI_STATUS (status);
202 }
203 }
204
205 /* Install the SCI handler and Global Lock handler */
206
207 if (!(flags & ACPI_NO_HANDLER_INIT)) {
208 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL handlers\n"));
209
210 status = acpi_ev_install_xrupt_handlers ();
211 if (ACPI_FAILURE (status)) {
212 return_ACPI_STATUS (status);
213 }
214 }
215
216 return_ACPI_STATUS (status);
217}
218
219/*******************************************************************************
220 *
221 * FUNCTION: acpi_initialize_objects
222 *
223 * PARAMETERS: Flags - Init/enable Options
224 *
225 * RETURN: Status
226 *
227 * DESCRIPTION: Completes namespace initialization by initializing device
228 * objects and executing AML code for Regions, buffers, etc.
229 *
230 ******************************************************************************/
231
232acpi_status
233acpi_initialize_objects (
234 u32 flags)
235{
236 acpi_status status = AE_OK;
237
238
239 ACPI_FUNCTION_TRACE ("acpi_initialize_objects");
240
241
242 /*
243 * Run all _REG methods
244 *
245 * NOTE: Any objects accessed
246 * by the _REG methods will be automatically initialized, even if they
247 * contain executable AML (see call to acpi_ns_initialize_objects below).
248 */
249 if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
250 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Executing _REG op_region methods\n"));
251
252 status = acpi_ev_initialize_op_regions ();
253 if (ACPI_FAILURE (status)) {
254 return_ACPI_STATUS (status);
255 }
256 }
257
258 /*
259 * Initialize the objects that remain uninitialized. This
260 * runs the executable AML that may be part of the declaration of these
261 * objects: operation_regions, buffer_fields, Buffers, and Packages.
262 */
263 if (!(flags & ACPI_NO_OBJECT_INIT)) {
264 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Completing Initialization of ACPI Objects\n"));
265
266 status = acpi_ns_initialize_objects ();
267 if (ACPI_FAILURE (status)) {
268 return_ACPI_STATUS (status);
269 }
270 }
271
272 /*
273 * Initialize all device objects in the namespace
274 * This runs the _STA and _INI methods.
275 */
276 if (!(flags & ACPI_NO_DEVICE_INIT)) {
277 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Devices\n"));
278
279 status = acpi_ns_initialize_devices ();
280 if (ACPI_FAILURE (status)) {
281 return_ACPI_STATUS (status);
282 }
283 }
284
285 /*
286 * Empty the caches (delete the cached objects) on the assumption that
287 * the table load filled them up more than they will be at runtime --
288 * thus wasting non-paged memory.
289 */
290 status = acpi_purge_cached_objects ();
291
292 acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK;
293 return_ACPI_STATUS (status);
294}
295
296
297/*******************************************************************************
298 *
299 * FUNCTION: acpi_terminate
300 *
301 * PARAMETERS: None
302 *
303 * RETURN: Status
304 *
305 * DESCRIPTION: Shutdown the ACPI subsystem. Release all resources.
306 *
307 ******************************************************************************/
308
309acpi_status
310acpi_terminate (void)
311{
312 acpi_status status;
313
314
315 ACPI_FUNCTION_TRACE ("acpi_terminate");
316
317
318 /* Terminate the AML Debugger if present */
319
320 ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE);
321
322 /* Shutdown and free all resources */
323
324 acpi_ut_subsystem_shutdown ();
325
326
327 /* Free the mutex objects */
328
329 acpi_ut_mutex_terminate ();
330
331
332#ifdef ACPI_DEBUGGER
333
334 /* Shut down the debugger */
335
336 acpi_db_terminate ();
337#endif
338
339 /* Now we can shutdown the OS-dependent layer */
340
341 status = acpi_os_terminate ();
342 return_ACPI_STATUS (status);
343}
344
345
346#ifdef ACPI_FUTURE_USAGE
347
348/*****************************************************************************
349 *
350 * FUNCTION: acpi_subsystem_status
351 *
352 * PARAMETERS: None
353 *
354 * RETURN: Status of the ACPI subsystem
355 *
356 * DESCRIPTION: Other drivers that use the ACPI subsystem should call this
357 * before making any other calls, to ensure the subsystem initial-
358 * ized successfully.
359 *
360 ****************************************************************************/
361
362acpi_status
363acpi_subsystem_status (void)
364{
365 if (acpi_gbl_startup_flags & ACPI_INITIALIZED_OK) {
366 return (AE_OK);
367 }
368 else {
369 return (AE_ERROR);
370 }
371}
372
373
374/******************************************************************************
375 *
376 * FUNCTION: acpi_get_system_info
377 *
378 * PARAMETERS: out_buffer - a pointer to a buffer to receive the
379 * resources for the device
380 * buffer_length - the number of bytes available in the buffer
381 *
382 * RETURN: Status - the status of the call
383 *
384 * DESCRIPTION: This function is called to get information about the current
385 * state of the ACPI subsystem. It will return system information
386 * in the out_buffer.
387 *
388 * If the function fails an appropriate status will be returned
389 * and the value of out_buffer is undefined.
390 *
391 ******************************************************************************/
392
393acpi_status
394acpi_get_system_info (
395 struct acpi_buffer *out_buffer)
396{
397 struct acpi_system_info *info_ptr;
398 u32 i;
399 acpi_status status;
400
401
402 ACPI_FUNCTION_TRACE ("acpi_get_system_info");
403
404
405 /* Parameter validation */
406
407 status = acpi_ut_validate_buffer (out_buffer);
408 if (ACPI_FAILURE (status)) {
409 return_ACPI_STATUS (status);
410 }
411
412 /* Validate/Allocate/Clear caller buffer */
413
414 status = acpi_ut_initialize_buffer (out_buffer, sizeof (struct acpi_system_info));
415 if (ACPI_FAILURE (status)) {
416 return_ACPI_STATUS (status);
417 }
418
419 /*
420 * Populate the return buffer
421 */
422 info_ptr = (struct acpi_system_info *) out_buffer->pointer;
423
424 info_ptr->acpi_ca_version = ACPI_CA_VERSION;
425
426 /* System flags (ACPI capabilities) */
427
428 info_ptr->flags = ACPI_SYS_MODE_ACPI;
429
430 /* Timer resolution - 24 or 32 bits */
431
432 if (!acpi_gbl_FADT) {
433 info_ptr->timer_resolution = 0;
434 }
435 else if (acpi_gbl_FADT->tmr_val_ext == 0) {
436 info_ptr->timer_resolution = 24;
437 }
438 else {
439 info_ptr->timer_resolution = 32;
440 }
441
442 /* Clear the reserved fields */
443
444 info_ptr->reserved1 = 0;
445 info_ptr->reserved2 = 0;
446
447 /* Current debug levels */
448
449 info_ptr->debug_layer = acpi_dbg_layer;
450 info_ptr->debug_level = acpi_dbg_level;
451
452 /* Current status of the ACPI tables, per table type */
453
454 info_ptr->num_table_types = NUM_ACPI_TABLE_TYPES;
455 for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) {
456 info_ptr->table_info[i].count = acpi_gbl_table_lists[i].count;
457 }
458
459 return_ACPI_STATUS (AE_OK);
460}
461EXPORT_SYMBOL(acpi_get_system_info);
462
463
464/*****************************************************************************
465 *
466 * FUNCTION: acpi_install_initialization_handler
467 *
468 * PARAMETERS: Handler - Callback procedure
469 *
470 * RETURN: Status
471 *
472 * DESCRIPTION: Install an initialization handler
473 *
474 * TBD: When a second function is added, must save the Function also.
475 *
476 ****************************************************************************/
477
478acpi_status
479acpi_install_initialization_handler (
480 acpi_init_handler handler,
481 u32 function)
482{
483
484 if (!handler) {
485 return (AE_BAD_PARAMETER);
486 }
487
488 if (acpi_gbl_init_handler) {
489 return (AE_ALREADY_EXISTS);
490 }
491
492 acpi_gbl_init_handler = handler;
493 return AE_OK;
494}
495
496#endif /* ACPI_FUTURE_USAGE */
497
498
499/*****************************************************************************
500 *
501 * FUNCTION: acpi_purge_cached_objects
502 *
503 * PARAMETERS: None
504 *
505 * RETURN: Status
506 *
507 * DESCRIPTION: Empty all caches (delete the cached objects)
508 *
509 ****************************************************************************/
510
511acpi_status
512acpi_purge_cached_objects (void)
513{
514 ACPI_FUNCTION_TRACE ("acpi_purge_cached_objects");
515
516
517#ifdef ACPI_ENABLE_OBJECT_CACHE
518 acpi_ut_delete_generic_state_cache ();
519 acpi_ut_delete_object_cache ();
520 acpi_ds_delete_walk_state_cache ();
521 acpi_ps_delete_parse_cache ();
522#endif
523
524 return_ACPI_STATUS (AE_OK);
525}
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
new file mode 100644
index 000000000000..1ce2047c3804
--- /dev/null
+++ b/drivers/acpi/utils.c
@@ -0,0 +1,423 @@
1/*
2 * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/types.h>
30#include <acpi/acpi_bus.h>
31#include <acpi/acpi_drivers.h>
32
33
34#define _COMPONENT ACPI_BUS_COMPONENT
35ACPI_MODULE_NAME ("acpi_utils")
36
37
38/* --------------------------------------------------------------------------
39 Object Evaluation Helpers
40 -------------------------------------------------------------------------- */
41
42#ifdef ACPI_DEBUG_OUTPUT
43#define acpi_util_eval_error(h,p,s) {\
44 char prefix[80] = {'\0'};\
45 struct acpi_buffer buffer = {sizeof(prefix), prefix};\
46 acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
47 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",\
48 (char *) prefix, p, acpi_format_exception(s))); }
49#else
50#define acpi_util_eval_error(h,p,s)
51#endif
52
53
54acpi_status
55acpi_extract_package (
56 union acpi_object *package,
57 struct acpi_buffer *format,
58 struct acpi_buffer *buffer)
59{
60 u32 size_required = 0;
61 u32 tail_offset = 0;
62 char *format_string = NULL;
63 u32 format_count = 0;
64 u32 i = 0;
65 u8 *head = NULL;
66 u8 *tail = NULL;
67
68 ACPI_FUNCTION_TRACE("acpi_extract_package");
69
70 if (!package || (package->type != ACPI_TYPE_PACKAGE) || (package->package.count < 1)) {
71 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'package' argument\n"));
72 return_ACPI_STATUS(AE_BAD_PARAMETER);
73 }
74
75 if (!format || !format->pointer || (format->length < 1)) {
76 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'format' argument\n"));
77 return_ACPI_STATUS(AE_BAD_PARAMETER);
78 }
79
80 if (!buffer) {
81 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'buffer' argument\n"));
82 return_ACPI_STATUS(AE_BAD_PARAMETER);
83 }
84
85 format_count = (format->length/sizeof(char)) - 1;
86 if (format_count > package->package.count) {
87 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Format specifies more objects [%d] than exist in package [%d].", format_count, package->package.count));
88 return_ACPI_STATUS(AE_BAD_DATA);
89 }
90
91 format_string = (char*)format->pointer;
92
93 /*
94 * Calculate size_required.
95 */
96 for (i=0; i<format_count; i++) {
97
98 union acpi_object *element = &(package->package.elements[i]);
99
100 if (!element) {
101 return_ACPI_STATUS(AE_BAD_DATA);
102 }
103
104 switch (element->type) {
105
106 case ACPI_TYPE_INTEGER:
107 switch (format_string[i]) {
108 case 'N':
109 size_required += sizeof(acpi_integer);
110 tail_offset += sizeof(acpi_integer);
111 break;
112 case 'S':
113 size_required += sizeof(char*) + sizeof(acpi_integer) + sizeof(char);
114 tail_offset += sizeof(char*);
115 break;
116 default:
117 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d]: got number, expecing [%c].\n", i, format_string[i]));
118 return_ACPI_STATUS(AE_BAD_DATA);
119 break;
120 }
121 break;
122
123 case ACPI_TYPE_STRING:
124 case ACPI_TYPE_BUFFER:
125 switch (format_string[i]) {
126 case 'S':
127 size_required += sizeof(char*) + (element->string.length * sizeof(char)) + sizeof(char);
128 tail_offset += sizeof(char*);
129 break;
130 case 'B':
131 size_required += sizeof(u8*) + (element->buffer.length * sizeof(u8));
132 tail_offset += sizeof(u8*);
133 break;
134 default:
135 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d] got string/buffer, expecing [%c].\n", i, format_string[i]));
136 return_ACPI_STATUS(AE_BAD_DATA);
137 break;
138 }
139 break;
140
141 case ACPI_TYPE_PACKAGE:
142 default:
143 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unsupported element at index=%d\n", i));
144 /* TBD: handle nested packages... */
145 return_ACPI_STATUS(AE_SUPPORT);
146 break;
147 }
148 }
149
150 /*
151 * Validate output buffer.
152 */
153 if (buffer->length < size_required) {
154 buffer->length = size_required;
155 return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
156 }
157 else if (buffer->length != size_required || !buffer->pointer) {
158 return_ACPI_STATUS(AE_BAD_PARAMETER);
159 }
160
161 head = buffer->pointer;
162 tail = buffer->pointer + tail_offset;
163
164 /*
165 * Extract package data.
166 */
167 for (i=0; i<format_count; i++) {
168
169 u8 **pointer = NULL;
170 union acpi_object *element = &(package->package.elements[i]);
171
172 if (!element) {
173 return_ACPI_STATUS(AE_BAD_DATA);
174 }
175
176 switch (element->type) {
177
178 case ACPI_TYPE_INTEGER:
179 switch (format_string[i]) {
180 case 'N':
181 *((acpi_integer*)head) = element->integer.value;
182 head += sizeof(acpi_integer);
183 break;
184 case 'S':
185 pointer = (u8**)head;
186 *pointer = tail;
187 *((acpi_integer*)tail) = element->integer.value;
188 head += sizeof(acpi_integer*);
189 tail += sizeof(acpi_integer);
190 /* NULL terminate string */
191 *tail = (char)0;
192 tail += sizeof(char);
193 break;
194 default:
195 /* Should never get here */
196 break;
197 }
198 break;
199
200 case ACPI_TYPE_STRING:
201 case ACPI_TYPE_BUFFER:
202 switch (format_string[i]) {
203 case 'S':
204 pointer = (u8**)head;
205 *pointer = tail;
206 memcpy(tail, element->string.pointer, element->string.length);
207 head += sizeof(char*);
208 tail += element->string.length * sizeof(char);
209 /* NULL terminate string */
210 *tail = (char)0;
211 tail += sizeof(char);
212 break;
213 case 'B':
214 pointer = (u8**)head;
215 *pointer = tail;
216 memcpy(tail, element->buffer.pointer, element->buffer.length);
217 head += sizeof(u8*);
218 tail += element->buffer.length * sizeof(u8);
219 break;
220 default:
221 /* Should never get here */
222 break;
223 }
224 break;
225
226 case ACPI_TYPE_PACKAGE:
227 /* TBD: handle nested packages... */
228 default:
229 /* Should never get here */
230 break;
231 }
232 }
233
234 return_ACPI_STATUS(AE_OK);
235}
236EXPORT_SYMBOL(acpi_extract_package);
237
238
239acpi_status
240acpi_evaluate_integer (
241 acpi_handle handle,
242 acpi_string pathname,
243 struct acpi_object_list *arguments,
244 unsigned long *data)
245{
246 acpi_status status = AE_OK;
247 union acpi_object *element;
248 struct acpi_buffer buffer = {0,NULL};
249
250 ACPI_FUNCTION_TRACE("acpi_evaluate_integer");
251
252 if (!data)
253 return_ACPI_STATUS(AE_BAD_PARAMETER);
254
255 element = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
256 if(!element)
257 return_ACPI_STATUS(AE_NO_MEMORY);
258
259 memset(element, 0, sizeof(union acpi_object));
260 buffer.length = sizeof(union acpi_object);
261 buffer.pointer = element;
262 status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
263 if (ACPI_FAILURE(status)) {
264 acpi_util_eval_error(handle, pathname, status);
265 return_ACPI_STATUS(status);
266 }
267
268 if (element->type != ACPI_TYPE_INTEGER) {
269 acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
270 return_ACPI_STATUS(AE_BAD_DATA);
271 }
272
273 *data = element->integer.value;
274 kfree(element);
275
276 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data));
277
278 return_ACPI_STATUS(AE_OK);
279}
280EXPORT_SYMBOL(acpi_evaluate_integer);
281
282
283#if 0
284acpi_status
285acpi_evaluate_string (
286 acpi_handle handle,
287 acpi_string pathname,
288 acpi_object_list *arguments,
289 acpi_string *data)
290{
291 acpi_status status = AE_OK;
292 acpi_object *element = NULL;
293 acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
294
295 ACPI_FUNCTION_TRACE("acpi_evaluate_string");
296
297 if (!data)
298 return_ACPI_STATUS(AE_BAD_PARAMETER);
299
300 status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
301 if (ACPI_FAILURE(status)) {
302 acpi_util_eval_error(handle, pathname, status);
303 return_ACPI_STATUS(status);
304 }
305
306 element = (acpi_object *) buffer.pointer;
307
308 if ((element->type != ACPI_TYPE_STRING)
309 || (element->type != ACPI_TYPE_BUFFER)
310 || !element->string.length) {
311 acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
312 return_ACPI_STATUS(AE_BAD_DATA);
313 }
314
315 *data = kmalloc(element->string.length + 1, GFP_KERNEL);
316 if (!data) {
317 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Memory allocation error\n"));
318 return_VALUE(-ENOMEM);
319 }
320 memset(*data, 0, element->string.length + 1);
321
322 memcpy(*data, element->string.pointer, element->string.length);
323
324 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data));
325
326 acpi_os_free(buffer.pointer);
327
328 return_ACPI_STATUS(AE_OK);
329}
330#endif
331
332
333acpi_status
334acpi_evaluate_reference (
335 acpi_handle handle,
336 acpi_string pathname,
337 struct acpi_object_list *arguments,
338 struct acpi_handle_list *list)
339{
340 acpi_status status = AE_OK;
341 union acpi_object *package = NULL;
342 union acpi_object *element = NULL;
343 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
344 u32 i = 0;
345
346 ACPI_FUNCTION_TRACE("acpi_evaluate_reference");
347
348 if (!list) {
349 return_ACPI_STATUS(AE_BAD_PARAMETER);
350 }
351
352 /* Evaluate object. */
353
354 status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
355 if (ACPI_FAILURE(status))
356 goto end;
357
358 package = (union acpi_object *) buffer.pointer;
359
360 if ((buffer.length == 0) || !package) {
361 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
362 "No return object (len %X ptr %p)\n",
363 (unsigned)buffer.length, package));
364 status = AE_BAD_DATA;
365 acpi_util_eval_error(handle, pathname, status);
366 goto end;
367 }
368 if (package->type != ACPI_TYPE_PACKAGE) {
369 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
370 "Expecting a [Package], found type %X\n",
371 package->type));
372 status = AE_BAD_DATA;
373 acpi_util_eval_error(handle, pathname, status);
374 goto end;
375 }
376 if (!package->package.count) {
377 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
378 "[Package] has zero elements (%p)\n",
379 package));
380 status = AE_BAD_DATA;
381 acpi_util_eval_error(handle, pathname, status);
382 goto end;
383 }
384
385 if (package->package.count > ACPI_MAX_HANDLES) {
386 return_ACPI_STATUS(AE_NO_MEMORY);
387 }
388 list->count = package->package.count;
389
390 /* Extract package data. */
391
392 for (i = 0; i < list->count; i++) {
393
394 element = &(package->package.elements[i]);
395
396 if (element->type != ACPI_TYPE_ANY) {
397 status = AE_BAD_DATA;
398 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
399 "Expecting a [Reference] package element, found type %X\n",
400 element->type));
401 acpi_util_eval_error(handle, pathname, status);
402 break;
403 }
404
405 /* Get the acpi_handle. */
406
407 list->handles[i] = element->reference.handle;
408 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n",
409 list->handles[i]));
410 }
411
412end:
413 if (ACPI_FAILURE(status)) {
414 list->count = 0;
415 //kfree(list->handles);
416 }
417
418 acpi_os_free(buffer.pointer);
419
420 return_ACPI_STATUS(status);
421}
422EXPORT_SYMBOL(acpi_evaluate_reference);
423
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
new file mode 100644
index 000000000000..71fa1011715f
--- /dev/null
+++ b/drivers/acpi/video.c
@@ -0,0 +1,1989 @@
1/*
2 * video.c - ACPI Video Driver ($Revision:$)
3 *
4 * Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
5 * Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/types.h>
30#include <linux/list.h>
31#include <linux/proc_fs.h>
32#include <linux/seq_file.h>
33
34#include <asm/uaccess.h>
35
36#include <acpi/acpi_bus.h>
37#include <acpi/acpi_drivers.h>
38
39#define ACPI_VIDEO_COMPONENT 0x08000000
40#define ACPI_VIDEO_CLASS "video"
41#define ACPI_VIDEO_DRIVER_NAME "ACPI Video Driver"
42#define ACPI_VIDEO_BUS_NAME "Video Bus"
43#define ACPI_VIDEO_DEVICE_NAME "Video Device"
44#define ACPI_VIDEO_NOTIFY_SWITCH 0x80
45#define ACPI_VIDEO_NOTIFY_PROBE 0x81
46#define ACPI_VIDEO_NOTIFY_CYCLE 0x82
47#define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83
48#define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84
49
50#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x82
51#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x83
52#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x84
53#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x85
54#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x86
55
56
57#define ACPI_VIDEO_HEAD_INVALID (~0u - 1)
58#define ACPI_VIDEO_HEAD_END (~0u)
59
60
61#define _COMPONENT ACPI_VIDEO_COMPONENT
62ACPI_MODULE_NAME ("acpi_video")
63
64MODULE_AUTHOR("Bruno Ducrot");
65MODULE_DESCRIPTION(ACPI_VIDEO_DRIVER_NAME);
66MODULE_LICENSE("GPL");
67
68static int acpi_video_bus_add (struct acpi_device *device);
69static int acpi_video_bus_remove (struct acpi_device *device, int type);
70static int acpi_video_bus_match (struct acpi_device *device, struct acpi_driver *driver);
71
72static struct acpi_driver acpi_video_bus = {
73 .name = ACPI_VIDEO_DRIVER_NAME,
74 .class = ACPI_VIDEO_CLASS,
75 .ops = {
76 .add = acpi_video_bus_add,
77 .remove = acpi_video_bus_remove,
78 .match = acpi_video_bus_match,
79 },
80};
81
82struct acpi_video_bus_flags {
83 u8 multihead:1; /* can switch video heads */
84 u8 rom:1; /* can retrieve a video rom */
85 u8 post:1; /* can configure the head to */
86 u8 reserved:5;
87};
88
89struct acpi_video_bus_cap {
90 u8 _DOS:1; /*Enable/Disable output switching*/
91 u8 _DOD:1; /*Enumerate all devices attached to display adapter*/
92 u8 _ROM:1; /*Get ROM Data*/
93 u8 _GPD:1; /*Get POST Device*/
94 u8 _SPD:1; /*Set POST Device*/
95 u8 _VPO:1; /*Video POST Options*/
96 u8 reserved:2;
97};
98
99struct acpi_video_device_attrib{
100 u32 display_index:4; /* A zero-based instance of the Display*/
101 u32 display_port_attachment:4; /*This field differenates displays type*/
102 u32 display_type:4; /*Describe the specific type in use*/
103 u32 vendor_specific:4; /*Chipset Vendor Specifi*/
104 u32 bios_can_detect:1; /*BIOS can detect the device*/
105 u32 depend_on_vga:1; /*Non-VGA output device whose power is related to
106 the VGA device.*/
107 u32 pipe_id:3; /*For VGA multiple-head devices.*/
108 u32 reserved:10; /*Must be 0*/
109 u32 device_id_scheme:1; /*Device ID Scheme*/
110};
111
112struct acpi_video_enumerated_device {
113 union {
114 u32 int_val;
115 struct acpi_video_device_attrib attrib;
116 } value;
117 struct acpi_video_device *bind_info;
118};
119
120struct acpi_video_bus {
121 acpi_handle handle;
122 u8 dos_setting;
123 struct acpi_video_enumerated_device *attached_array;
124 u8 attached_count;
125 struct acpi_video_bus_cap cap;
126 struct acpi_video_bus_flags flags;
127 struct semaphore sem;
128 struct list_head video_device_list;
129 struct proc_dir_entry *dir;
130};
131
132struct acpi_video_device_flags {
133 u8 crt:1;
134 u8 lcd:1;
135 u8 tvout:1;
136 u8 bios:1;
137 u8 unknown:1;
138 u8 reserved:3;
139};
140
141struct acpi_video_device_cap {
142 u8 _ADR:1; /*Return the unique ID */
143 u8 _BCL:1; /*Query list of brightness control levels supported*/
144 u8 _BCM:1; /*Set the brightness level*/
145 u8 _DDC:1; /*Return the EDID for this device*/
146 u8 _DCS:1; /*Return status of output device*/
147 u8 _DGS:1; /*Query graphics state*/
148 u8 _DSS:1; /*Device state set*/
149 u8 _reserved:1;
150};
151
152struct acpi_video_device_brightness {
153 int curr;
154 int count;
155 int *levels;
156};
157
158struct acpi_video_device {
159 acpi_handle handle;
160 unsigned long device_id;
161 struct acpi_video_device_flags flags;
162 struct acpi_video_device_cap cap;
163 struct list_head entry;
164 struct acpi_video_bus *video;
165 struct acpi_device *dev;
166 struct acpi_video_device_brightness *brightness;
167};
168
169
170/* bus */
171static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
172static struct file_operations acpi_video_bus_info_fops = {
173 .open = acpi_video_bus_info_open_fs,
174 .read = seq_read,
175 .llseek = seq_lseek,
176 .release = single_release,
177};
178
179static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
180static struct file_operations acpi_video_bus_ROM_fops = {
181 .open = acpi_video_bus_ROM_open_fs,
182 .read = seq_read,
183 .llseek = seq_lseek,
184 .release = single_release,
185};
186
187static int acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file);
188static struct file_operations acpi_video_bus_POST_info_fops = {
189 .open = acpi_video_bus_POST_info_open_fs,
190 .read = seq_read,
191 .llseek = seq_lseek,
192 .release = single_release,
193};
194
195static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
196static struct file_operations acpi_video_bus_POST_fops = {
197 .open = acpi_video_bus_POST_open_fs,
198 .read = seq_read,
199 .llseek = seq_lseek,
200 .release = single_release,
201};
202
203
204static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
205static struct file_operations acpi_video_bus_DOS_fops = {
206 .open = acpi_video_bus_DOS_open_fs,
207 .read = seq_read,
208 .llseek = seq_lseek,
209 .release = single_release,
210};
211
212/* device */
213static int acpi_video_device_info_open_fs(struct inode *inode, struct file *file);
214static struct file_operations acpi_video_device_info_fops = {
215 .open = acpi_video_device_info_open_fs,
216 .read = seq_read,
217 .llseek = seq_lseek,
218 .release = single_release,
219};
220
221static int acpi_video_device_state_open_fs(struct inode *inode, struct file *file);
222static struct file_operations acpi_video_device_state_fops = {
223 .open = acpi_video_device_state_open_fs,
224 .read = seq_read,
225 .llseek = seq_lseek,
226 .release = single_release,
227};
228
229static int acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file);
230static struct file_operations acpi_video_device_brightness_fops = {
231 .open = acpi_video_device_brightness_open_fs,
232 .read = seq_read,
233 .llseek = seq_lseek,
234 .release = single_release,
235};
236
237static int acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file);
238static struct file_operations acpi_video_device_EDID_fops = {
239 .open = acpi_video_device_EDID_open_fs,
240 .read = seq_read,
241 .llseek = seq_lseek,
242 .release = single_release,
243};
244
245static char device_decode[][30] = {
246 "motherboard VGA device",
247 "PCI VGA device",
248 "AGP VGA device",
249 "UNKNOWN",
250};
251
252static void acpi_video_device_notify ( acpi_handle handle, u32 event, void *data);
253static void acpi_video_device_rebind( struct acpi_video_bus *video);
254static void acpi_video_device_bind( struct acpi_video_bus *video, struct acpi_video_device *device);
255static int acpi_video_device_enumerate(struct acpi_video_bus *video);
256static int acpi_video_switch_output( struct acpi_video_bus *video, int event);
257static int acpi_video_get_next_level( struct acpi_video_device *device, u32 level_current,u32 event);
258static void acpi_video_switch_brightness ( struct acpi_video_device *device, int event);
259
260
261/* --------------------------------------------------------------------------
262 Video Management
263 -------------------------------------------------------------------------- */
264
265/* device */
266
267static int
268acpi_video_device_query (
269 struct acpi_video_device *device,
270 unsigned long *state)
271{
272 int status;
273 ACPI_FUNCTION_TRACE("acpi_video_device_query");
274 status = acpi_evaluate_integer(device->handle, "_DGS", NULL, state);
275
276 return_VALUE(status);
277}
278
279static int
280acpi_video_device_get_state (
281 struct acpi_video_device *device,
282 unsigned long *state)
283{
284 int status;
285
286 ACPI_FUNCTION_TRACE("acpi_video_device_get_state");
287
288 status = acpi_evaluate_integer(device->handle, "_DCS", NULL, state);
289
290 return_VALUE(status);
291}
292
293static int
294acpi_video_device_set_state (
295 struct acpi_video_device *device,
296 int state)
297{
298 int status;
299 union acpi_object arg0 = {ACPI_TYPE_INTEGER};
300 struct acpi_object_list args = {1, &arg0};
301
302 ACPI_FUNCTION_TRACE("acpi_video_device_set_state");
303
304 arg0.integer.value = state;
305 status = acpi_evaluate_integer(device->handle, "_DSS", &args, NULL);
306
307 return_VALUE(status);
308}
309
310static int
311acpi_video_device_lcd_query_levels (
312 struct acpi_video_device *device,
313 union acpi_object **levels)
314{
315 int status;
316 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
317 union acpi_object *obj;
318
319
320 ACPI_FUNCTION_TRACE("acpi_video_device_lcd_query_levels");
321
322 *levels = NULL;
323
324 status = acpi_evaluate_object(device->handle, "_BCL", NULL, &buffer);
325 if (!ACPI_SUCCESS(status))
326 return_VALUE(status);
327 obj = (union acpi_object *) buffer.pointer;
328 if (!obj && (obj->type != ACPI_TYPE_PACKAGE)) {
329 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _BCL data\n"));
330 status = -EFAULT;
331 goto err;
332 }
333
334 *levels = obj;
335
336 return_VALUE(0);
337
338err:
339 if (buffer.pointer)
340 kfree(buffer.pointer);
341
342 return_VALUE(status);
343}
344
345static int
346acpi_video_device_lcd_set_level (
347 struct acpi_video_device *device,
348 int level)
349{
350 int status;
351 union acpi_object arg0 = {ACPI_TYPE_INTEGER};
352 struct acpi_object_list args = {1, &arg0};
353
354 ACPI_FUNCTION_TRACE("acpi_video_device_lcd_set_level");
355
356 arg0.integer.value = level;
357 status = acpi_evaluate_object(device->handle, "_BCM", &args, NULL);
358
359 printk(KERN_DEBUG "set_level status: %x\n", status);
360 return_VALUE(status);
361}
362
363static int
364acpi_video_device_lcd_get_level_current (
365 struct acpi_video_device *device,
366 unsigned long *level)
367{
368 int status;
369 ACPI_FUNCTION_TRACE("acpi_video_device_lcd_get_level_current");
370
371 status = acpi_evaluate_integer(device->handle, "_BQC", NULL, level);
372
373 return_VALUE(status);
374}
375
376static int
377acpi_video_device_EDID (
378 struct acpi_video_device *device,
379 union acpi_object **edid,
380 ssize_t length)
381{
382 int status;
383 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
384 union acpi_object *obj;
385 union acpi_object arg0 = {ACPI_TYPE_INTEGER};
386 struct acpi_object_list args = {1, &arg0};
387
388 ACPI_FUNCTION_TRACE("acpi_video_device_get_EDID");
389
390 *edid = NULL;
391
392 if (!device)
393 return_VALUE(-ENODEV);
394 if (length == 128)
395 arg0.integer.value = 1;
396 else if (length == 256)
397 arg0.integer.value = 2;
398 else
399 return_VALUE(-EINVAL);
400
401 status = acpi_evaluate_object(device->handle, "_DDC", &args, &buffer);
402 if (ACPI_FAILURE(status))
403 return_VALUE(-ENODEV);
404
405 obj = (union acpi_object *) buffer.pointer;
406
407 if (obj && obj->type == ACPI_TYPE_BUFFER)
408 *edid = obj;
409 else {
410 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DDC data\n"));
411 status = -EFAULT;
412 kfree(obj);
413 }
414
415 return_VALUE(status);
416}
417
418
419/* bus */
420
421static int
422acpi_video_bus_set_POST (
423 struct acpi_video_bus *video,
424 unsigned long option)
425{
426 int status;
427 unsigned long tmp;
428 union acpi_object arg0 = {ACPI_TYPE_INTEGER};
429 struct acpi_object_list args = {1, &arg0};
430
431 ACPI_FUNCTION_TRACE("acpi_video_bus_set_POST");
432
433 arg0.integer.value = option;
434
435 status = acpi_evaluate_integer(video->handle, "_SPD", &args, &tmp);
436 if (ACPI_SUCCESS(status))
437 status = tmp ? (-EINVAL):(AE_OK);
438
439 return_VALUE(status);
440}
441
442static int
443acpi_video_bus_get_POST (
444 struct acpi_video_bus *video,
445 unsigned long *id)
446{
447 int status;
448
449 ACPI_FUNCTION_TRACE("acpi_video_bus_get_POST");
450
451 status = acpi_evaluate_integer(video->handle, "_GPD", NULL, id);
452
453 return_VALUE(status);
454}
455
456static int
457acpi_video_bus_POST_options (
458 struct acpi_video_bus *video,
459 unsigned long *options)
460{
461 int status;
462 ACPI_FUNCTION_TRACE("acpi_video_bus_POST_options");
463
464 status = acpi_evaluate_integer(video->handle, "_VPO", NULL, options);
465 *options &= 3;
466
467 return_VALUE(status);
468}
469
470/*
471 * Arg:
472 * video : video bus device pointer
473 * bios_flag :
474 * 0. The system BIOS should NOT automatically switch(toggle)
475 * the active display output.
476 * 1. The system BIOS should automatically switch (toggle) the
477 * active display output. No swich event.
478 * 2. The _DGS value should be locked.
479 * 3. The system BIOS should not automatically switch (toggle) the
480 * active display output, but instead generate the display switch
481 * event notify code.
482 * lcd_flag :
483 * 0. The system BIOS should automatically control the brightness level
484 * of the LCD, when the power changes from AC to DC
485 * 1. The system BIOS should NOT automatically control the brightness
486 * level of the LCD, when the power changes from AC to DC.
487 * Return Value:
488 * -1 wrong arg.
489 */
490
491static int
492acpi_video_bus_DOS(
493 struct acpi_video_bus *video,
494 int bios_flag,
495 int lcd_flag)
496{
497 acpi_integer status = 0;
498 union acpi_object arg0 = {ACPI_TYPE_INTEGER};
499 struct acpi_object_list args = {1, &arg0};
500
501 ACPI_FUNCTION_TRACE("acpi_video_bus_DOS");
502
503 if (bios_flag < 0 || bios_flag >3 || lcd_flag < 0 || lcd_flag > 1){
504 status = -1;
505 goto Failed;
506 }
507 arg0.integer.value = (lcd_flag << 2) | bios_flag;
508 video->dos_setting = arg0.integer.value;
509 acpi_evaluate_object(video->handle, "_DOS", &args, NULL);
510
511Failed:
512 return_VALUE(status);
513}
514
515/*
516 * Arg:
517 * device : video output device (LCD, CRT, ..)
518 *
519 * Return Value:
520 * None
521 *
522 * Find out all required AML method defined under the output
523 * device.
524 */
525
526static void
527acpi_video_device_find_cap (struct acpi_video_device *device)
528{
529 acpi_integer status;
530 acpi_handle h_dummy1;
531 int i;
532 union acpi_object *obj = NULL;
533 struct acpi_video_device_brightness *br = NULL;
534
535 ACPI_FUNCTION_TRACE("acpi_video_device_find_cap");
536
537 memset( &device->cap, 0, 4);
538
539 if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_ADR", &h_dummy1))) {
540 device->cap._ADR = 1;
541 }
542 if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCL", &h_dummy1))) {
543 device->cap._BCL= 1;
544 }
545 if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCM", &h_dummy1))) {
546 device->cap._BCM= 1;
547 }
548 if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DDC", &h_dummy1))) {
549 device->cap._DDC= 1;
550 }
551 if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DCS", &h_dummy1))) {
552 device->cap._DCS = 1;
553 }
554 if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DGS", &h_dummy1))) {
555 device->cap._DGS = 1;
556 }
557 if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DSS", &h_dummy1))) {
558 device->cap._DSS = 1;
559 }
560
561 status = acpi_video_device_lcd_query_levels(device, &obj);
562
563 if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count >= 2) {
564 int count = 0;
565 union acpi_object *o;
566
567 br = kmalloc(sizeof &br, GFP_KERNEL);
568 if (!br) {
569 printk(KERN_ERR "can't allocate memory\n");
570 } else {
571 memset(br, 0, sizeof &br);
572 br->levels = kmalloc(obj->package.count * sizeof &br->levels, GFP_KERNEL);
573 if (!br->levels)
574 goto out;
575
576 for (i = 0; i < obj->package.count; i++) {
577 o = (union acpi_object *) &obj->package.elements[i];
578 if (o->type != ACPI_TYPE_INTEGER) {
579 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
580 continue;
581 }
582 br->levels[count] = (u32) o->integer.value;
583 count++;
584 }
585out:
586 if (count < 2) {
587 if (br->levels)
588 kfree(br->levels);
589 kfree(br);
590 } else {
591 br->count = count;
592 device->brightness = br;
593 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count));
594 }
595 }
596 }
597
598 if (obj)
599 kfree(obj);
600
601 return_VOID;
602}
603
604/*
605 * Arg:
606 * device : video output device (VGA)
607 *
608 * Return Value:
609 * None
610 *
611 * Find out all required AML method defined under the video bus device.
612 */
613
614static void
615acpi_video_bus_find_cap (struct acpi_video_bus *video)
616{
617 acpi_handle h_dummy1;
618
619 memset(&video->cap ,0, 4);
620 if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOS", &h_dummy1))) {
621 video->cap._DOS = 1;
622 }
623 if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOD", &h_dummy1))) {
624 video->cap._DOD = 1;
625 }
626 if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_ROM", &h_dummy1))) {
627 video->cap._ROM = 1;
628 }
629 if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_GPD", &h_dummy1))) {
630 video->cap._GPD = 1;
631 }
632 if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_SPD", &h_dummy1))) {
633 video->cap._SPD = 1;
634 }
635 if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_VPO", &h_dummy1))) {
636 video->cap._VPO = 1;
637 }
638}
639
640/*
641 * Check whether the video bus device has required AML method to
642 * support the desired features
643 */
644
645static int
646acpi_video_bus_check (
647 struct acpi_video_bus *video)
648{
649 acpi_status status = -ENOENT;
650
651
652 ACPI_FUNCTION_TRACE("acpi_video_bus_check");
653
654 if (!video)
655 return_VALUE(-EINVAL);
656
657 /* Since there is no HID, CID and so on for VGA driver, we have
658 * to check well known required nodes.
659 */
660
661 /* Does this device able to support video switching ? */
662 if(video->cap._DOS){
663 video->flags.multihead = 1;
664 status = 0;
665 }
666
667 /* Does this device able to retrieve a retrieve a video ROM ? */
668 if(video->cap._ROM){
669 video->flags.rom = 1;
670 status = 0;
671 }
672
673 /* Does this device able to configure which video device to POST ? */
674 if(video->cap._GPD && video->cap._SPD && video->cap._VPO){
675 video->flags.post = 1;
676 status = 0;
677 }
678
679 return_VALUE(status);
680}
681
682/* --------------------------------------------------------------------------
683 FS Interface (/proc)
684 -------------------------------------------------------------------------- */
685
686static struct proc_dir_entry *acpi_video_dir;
687
688/* video devices */
689
690static int
691acpi_video_device_info_seq_show (
692 struct seq_file *seq,
693 void *offset)
694{
695 struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
696
697 ACPI_FUNCTION_TRACE("acpi_video_device_info_seq_show");
698
699 if (!dev)
700 goto end;
701
702 seq_printf(seq, "device_id: 0x%04x\n", (u32) dev->device_id);
703 seq_printf(seq, "type: ");
704 if (dev->flags.crt)
705 seq_printf(seq, "CRT\n");
706 else if (dev->flags.lcd)
707 seq_printf(seq, "LCD\n");
708 else if (dev->flags.tvout)
709 seq_printf(seq, "TVOUT\n");
710 else
711 seq_printf(seq, "UNKNOWN\n");
712
713 seq_printf(seq,"known by bios: %s\n",
714 dev->flags.bios ? "yes":"no");
715
716end:
717 return_VALUE(0);
718}
719
720static int
721acpi_video_device_info_open_fs (
722 struct inode *inode,
723 struct file *file)
724{
725 return single_open(file, acpi_video_device_info_seq_show,
726 PDE(inode)->data);
727}
728
729static int
730acpi_video_device_state_seq_show (
731 struct seq_file *seq,
732 void *offset)
733{
734 int status;
735 struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
736 unsigned long state;
737
738 ACPI_FUNCTION_TRACE("acpi_video_device_state_seq_show");
739
740 if (!dev)
741 goto end;
742
743 status = acpi_video_device_get_state(dev, &state);
744 seq_printf(seq, "state: ");
745 if (ACPI_SUCCESS(status))
746 seq_printf(seq, "0x%02lx\n", state);
747 else
748 seq_printf(seq, "<not supported>\n");
749
750 status = acpi_video_device_query(dev, &state);
751 seq_printf(seq, "query: ");
752 if (ACPI_SUCCESS(status))
753 seq_printf(seq, "0x%02lx\n", state);
754 else
755 seq_printf(seq, "<not supported>\n");
756
757end:
758 return_VALUE(0);
759}
760
761static int
762acpi_video_device_state_open_fs (
763 struct inode *inode,
764 struct file *file)
765{
766 return single_open(file, acpi_video_device_state_seq_show,
767 PDE(inode)->data);
768}
769
770static ssize_t
771acpi_video_device_write_state (
772 struct file *file,
773 const char __user *buffer,
774 size_t count,
775 loff_t *data)
776{
777 int status;
778 struct seq_file *m = (struct seq_file *) file->private_data;
779 struct acpi_video_device *dev = (struct acpi_video_device *) m->private;
780 char str[12] = {0};
781 u32 state = 0;
782
783 ACPI_FUNCTION_TRACE("acpi_video_device_write_state");
784
785 if (!dev || count + 1 > sizeof str)
786 return_VALUE(-EINVAL);
787
788 if (copy_from_user(str, buffer, count))
789 return_VALUE(-EFAULT);
790
791 str[count] = 0;
792 state = simple_strtoul(str, NULL, 0);
793 state &= ((1ul<<31) | (1ul<<30) | (1ul<<0));
794
795 status = acpi_video_device_set_state(dev, state);
796
797 if (status)
798 return_VALUE(-EFAULT);
799
800 return_VALUE(count);
801}
802
803static int
804acpi_video_device_brightness_seq_show (
805 struct seq_file *seq,
806 void *offset)
807{
808 struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
809 int i;
810
811 ACPI_FUNCTION_TRACE("acpi_video_device_brightness_seq_show");
812
813 if (!dev || !dev->brightness) {
814 seq_printf(seq, "<not supported>\n");
815 return_VALUE(0);
816 }
817
818 seq_printf(seq, "levels: ");
819 for (i = 0; i < dev->brightness->count; i++)
820 seq_printf(seq, " %d", dev->brightness->levels[i]);
821 seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
822
823 return_VALUE(0);
824}
825
826static int
827acpi_video_device_brightness_open_fs (
828 struct inode *inode,
829 struct file *file)
830{
831 return single_open(file, acpi_video_device_brightness_seq_show,
832 PDE(inode)->data);
833}
834
835static ssize_t
836acpi_video_device_write_brightness (
837 struct file *file,
838 const char __user *buffer,
839 size_t count,
840 loff_t *data)
841{
842 struct seq_file *m = (struct seq_file *) file->private_data;
843 struct acpi_video_device *dev = (struct acpi_video_device *) m->private;
844 char str[4] = {0};
845 unsigned int level = 0;
846 int i;
847
848 ACPI_FUNCTION_TRACE("acpi_video_device_write_brightness");
849
850 if (!dev || count + 1 > sizeof str)
851 return_VALUE(-EINVAL);
852
853 if (copy_from_user(str, buffer, count))
854 return_VALUE(-EFAULT);
855
856 str[count] = 0;
857 level = simple_strtoul(str, NULL, 0);
858
859 if (level > 100)
860 return_VALUE(-EFAULT);
861
862 /* validate though the list of available levels */
863 for (i = 0; i < dev->brightness->count; i++)
864 if (level == dev->brightness->levels[i]) {
865 if (ACPI_SUCCESS(acpi_video_device_lcd_set_level(dev, level)))
866 dev->brightness->curr = level;
867 break;
868 }
869
870 return_VALUE(count);
871}
872
873static int
874acpi_video_device_EDID_seq_show (
875 struct seq_file *seq,
876 void *offset)
877{
878 struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
879 int status;
880 int i;
881 union acpi_object *edid = NULL;
882
883 ACPI_FUNCTION_TRACE("acpi_video_device_EDID_seq_show");
884
885 if (!dev)
886 goto out;
887
888 status = acpi_video_device_EDID (dev, &edid, 128);
889 if (ACPI_FAILURE(status)) {
890 status = acpi_video_device_EDID (dev, &edid, 256);
891 }
892
893 if (ACPI_FAILURE(status)) {
894 goto out;
895 }
896
897 if (edid && edid->type == ACPI_TYPE_BUFFER) {
898 for (i = 0; i < edid->buffer.length; i++)
899 seq_putc(seq, edid->buffer.pointer[i]);
900 }
901
902out:
903 if (!edid)
904 seq_printf(seq, "<not supported>\n");
905 else
906 kfree(edid);
907
908 return_VALUE(0);
909}
910
911static int
912acpi_video_device_EDID_open_fs (
913 struct inode *inode,
914 struct file *file)
915{
916 return single_open(file, acpi_video_device_EDID_seq_show,
917 PDE(inode)->data);
918}
919
920
921static int
922acpi_video_device_add_fs (
923 struct acpi_device *device)
924{
925 struct proc_dir_entry *entry = NULL;
926 struct acpi_video_device *vid_dev;
927
928 ACPI_FUNCTION_TRACE("acpi_video_device_add_fs");
929
930 if (!device)
931 return_VALUE(-ENODEV);
932
933 vid_dev = (struct acpi_video_device *) acpi_driver_data(device);
934 if (!vid_dev)
935 return_VALUE(-ENODEV);
936
937 if (!acpi_device_dir(device)) {
938 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
939 vid_dev->video->dir);
940 if (!acpi_device_dir(device))
941 return_VALUE(-ENODEV);
942 acpi_device_dir(device)->owner = THIS_MODULE;
943 }
944
945 /* 'info' [R] */
946 entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
947 if (!entry)
948 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
949 "Unable to create 'info' fs entry\n"));
950 else {
951 entry->proc_fops = &acpi_video_device_info_fops;
952 entry->data = acpi_driver_data(device);
953 entry->owner = THIS_MODULE;
954 }
955
956 /* 'state' [R/W] */
957 entry = create_proc_entry("state", S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
958 if (!entry)
959 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
960 "Unable to create 'state' fs entry\n"));
961 else {
962 entry->proc_fops = &acpi_video_device_state_fops;
963 entry->proc_fops->write = acpi_video_device_write_state;
964 entry->data = acpi_driver_data(device);
965 entry->owner = THIS_MODULE;
966 }
967
968 /* 'brightness' [R/W] */
969 entry = create_proc_entry("brightness", S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
970 if (!entry)
971 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
972 "Unable to create 'brightness' fs entry\n"));
973 else {
974 entry->proc_fops = &acpi_video_device_brightness_fops;
975 entry->proc_fops->write = acpi_video_device_write_brightness;
976 entry->data = acpi_driver_data(device);
977 entry->owner = THIS_MODULE;
978 }
979
980 /* 'EDID' [R] */
981 entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device));
982 if (!entry)
983 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
984 "Unable to create 'brightness' fs entry\n"));
985 else {
986 entry->proc_fops = &acpi_video_device_EDID_fops;
987 entry->data = acpi_driver_data(device);
988 entry->owner = THIS_MODULE;
989 }
990
991 return_VALUE(0);
992}
993
994static int
995acpi_video_device_remove_fs (
996 struct acpi_device *device)
997{
998 struct acpi_video_device *vid_dev;
999 ACPI_FUNCTION_TRACE("acpi_video_device_remove_fs");
1000
1001 vid_dev = (struct acpi_video_device *) acpi_driver_data(device);
1002 if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
1003 return_VALUE(-ENODEV);
1004
1005 if (acpi_device_dir(device)) {
1006 remove_proc_entry("info", acpi_device_dir(device));
1007 remove_proc_entry("state", acpi_device_dir(device));
1008 remove_proc_entry("brightness", acpi_device_dir(device));
1009 remove_proc_entry("EDID", acpi_device_dir(device));
1010 remove_proc_entry(acpi_device_bid(device),
1011 vid_dev->video->dir);
1012 acpi_device_dir(device) = NULL;
1013 }
1014
1015 return_VALUE(0);
1016}
1017
1018
1019/* video bus */
1020static int
1021acpi_video_bus_info_seq_show (
1022 struct seq_file *seq,
1023 void *offset)
1024{
1025 struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
1026
1027 ACPI_FUNCTION_TRACE("acpi_video_bus_info_seq_show");
1028
1029 if (!video)
1030 goto end;
1031
1032 seq_printf(seq, "Switching heads: %s\n",
1033 video->flags.multihead ? "yes":"no");
1034 seq_printf(seq, "Video ROM: %s\n",
1035 video->flags.rom ? "yes":"no");
1036 seq_printf(seq, "Device to be POSTed on boot: %s\n",
1037 video->flags.post ? "yes":"no");
1038
1039end:
1040 return_VALUE(0);
1041}
1042
1043static int
1044acpi_video_bus_info_open_fs (
1045 struct inode *inode,
1046 struct file *file)
1047{
1048 return single_open(file, acpi_video_bus_info_seq_show, PDE(inode)->data);
1049}
1050
1051static int
1052acpi_video_bus_ROM_seq_show (
1053 struct seq_file *seq,
1054 void *offset)
1055{
1056 struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
1057
1058 ACPI_FUNCTION_TRACE("acpi_video_bus_ROM_seq_show");
1059
1060 if (!video)
1061 goto end;
1062
1063 printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__);
1064 seq_printf(seq, "<TODO>\n");
1065
1066end:
1067 return_VALUE(0);
1068}
1069
1070static int
1071acpi_video_bus_ROM_open_fs (
1072 struct inode *inode,
1073 struct file *file)
1074{
1075 return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data);
1076}
1077
1078static int
1079acpi_video_bus_POST_info_seq_show (
1080 struct seq_file *seq,
1081 void *offset)
1082{
1083 struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
1084 unsigned long options;
1085 int status;
1086
1087 ACPI_FUNCTION_TRACE("acpi_video_bus_POST_info_seq_show");
1088
1089 if (!video)
1090 goto end;
1091
1092 status = acpi_video_bus_POST_options(video, &options);
1093 if (ACPI_SUCCESS(status)) {
1094 if (!(options & 1)) {
1095 printk(KERN_WARNING PREFIX "The motherboard VGA device is not listed as a possible POST device.\n");
1096 printk(KERN_WARNING PREFIX "This indicate a BIOS bug. Please contact the manufacturer.\n");
1097 }
1098 printk("%lx\n", options);
1099 seq_printf(seq, "can POST: <intgrated video>");
1100 if (options & 2)
1101 seq_printf(seq, " <PCI video>");
1102 if (options & 4)
1103 seq_printf(seq, " <AGP video>");
1104 seq_putc(seq, '\n');
1105 } else
1106 seq_printf(seq, "<not supported>\n");
1107end:
1108 return_VALUE(0);
1109}
1110
1111static int
1112acpi_video_bus_POST_info_open_fs (
1113 struct inode *inode,
1114 struct file *file)
1115{
1116 return single_open(file, acpi_video_bus_POST_info_seq_show, PDE(inode)->data);
1117}
1118
1119static int
1120acpi_video_bus_POST_seq_show (
1121 struct seq_file *seq,
1122 void *offset)
1123{
1124 struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
1125 int status;
1126 unsigned long id;
1127
1128 ACPI_FUNCTION_TRACE("acpi_video_bus_POST_seq_show");
1129
1130 if (!video)
1131 goto end;
1132
1133 status = acpi_video_bus_get_POST (video, &id);
1134 if (!ACPI_SUCCESS(status)) {
1135 seq_printf(seq, "<not supported>\n");
1136 goto end;
1137 }
1138 seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]);
1139
1140end:
1141 return_VALUE(0);
1142}
1143
1144static int
1145acpi_video_bus_DOS_seq_show (
1146 struct seq_file *seq,
1147 void *offset)
1148{
1149 struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
1150
1151 ACPI_FUNCTION_TRACE("acpi_video_bus_DOS_seq_show");
1152
1153 seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting );
1154
1155 return_VALUE(0);
1156}
1157
1158static int
1159acpi_video_bus_POST_open_fs (
1160 struct inode *inode,
1161 struct file *file)
1162{
1163 return single_open(file, acpi_video_bus_POST_seq_show, PDE(inode)->data);
1164}
1165
1166static int
1167acpi_video_bus_DOS_open_fs (
1168 struct inode *inode,
1169 struct file *file)
1170{
1171 return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data);
1172}
1173
1174static ssize_t
1175acpi_video_bus_write_POST (
1176 struct file *file,
1177 const char __user *buffer,
1178 size_t count,
1179 loff_t *data)
1180{
1181 int status;
1182 struct seq_file *m = (struct seq_file *) file->private_data;
1183 struct acpi_video_bus *video = (struct acpi_video_bus *) m->private;
1184 char str[12] = {0};
1185 unsigned long opt, options;
1186
1187 ACPI_FUNCTION_TRACE("acpi_video_bus_write_POST");
1188
1189
1190 if (!video || count + 1 > sizeof str)
1191 return_VALUE(-EINVAL);
1192
1193 status = acpi_video_bus_POST_options(video, &options);
1194 if (!ACPI_SUCCESS(status))
1195 return_VALUE(-EINVAL);
1196
1197 if (copy_from_user(str, buffer, count))
1198 return_VALUE(-EFAULT);
1199
1200 str[count] = 0;
1201 opt = strtoul(str, NULL, 0);
1202 if (opt > 3)
1203 return_VALUE(-EFAULT);
1204
1205 /* just in case an OEM 'forget' the motherboard... */
1206 options |= 1;
1207
1208 if (options & (1ul << opt)) {
1209 status = acpi_video_bus_set_POST (video, opt);
1210 if (!ACPI_SUCCESS(status))
1211 return_VALUE(-EFAULT);
1212
1213 }
1214
1215
1216 return_VALUE(count);
1217}
1218
1219static ssize_t
1220acpi_video_bus_write_DOS (
1221 struct file *file,
1222 const char __user *buffer,
1223 size_t count,
1224 loff_t *data)
1225{
1226 int status;
1227 struct seq_file *m = (struct seq_file *) file->private_data;
1228 struct acpi_video_bus *video = (struct acpi_video_bus *) m->private;
1229 char str[12] = {0};
1230 unsigned long opt;
1231
1232 ACPI_FUNCTION_TRACE("acpi_video_bus_write_DOS");
1233
1234
1235 if (!video || count + 1 > sizeof str)
1236 return_VALUE(-EINVAL);
1237
1238 if (copy_from_user(str, buffer, count))
1239 return_VALUE(-EFAULT);
1240
1241 str[count] = 0;
1242 opt = strtoul(str, NULL, 0);
1243 if (opt > 7)
1244 return_VALUE(-EFAULT);
1245
1246 status = acpi_video_bus_DOS (video, opt & 0x3, (opt & 0x4)>>2);
1247
1248 if (!ACPI_SUCCESS(status))
1249 return_VALUE(-EFAULT);
1250
1251 return_VALUE(count);
1252}
1253
1254static int
1255acpi_video_bus_add_fs (
1256 struct acpi_device *device)
1257{
1258 struct proc_dir_entry *entry = NULL;
1259 struct acpi_video_bus *video;
1260
1261 ACPI_FUNCTION_TRACE("acpi_video_bus_add_fs");
1262
1263 video = (struct acpi_video_bus *) acpi_driver_data(device);
1264
1265 if (!acpi_device_dir(device)) {
1266 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1267 acpi_video_dir);
1268 if (!acpi_device_dir(device))
1269 return_VALUE(-ENODEV);
1270 video->dir = acpi_device_dir(device);
1271 acpi_device_dir(device)->owner = THIS_MODULE;
1272 }
1273
1274 /* 'info' [R] */
1275 entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
1276 if (!entry)
1277 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'info' fs entry\n"));
1278 else {
1279 entry->proc_fops = &acpi_video_bus_info_fops;
1280 entry->data = acpi_driver_data(device);
1281 entry->owner = THIS_MODULE;
1282 }
1283
1284 /* 'ROM' [R] */
1285 entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device));
1286 if (!entry)
1287 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'ROM' fs entry\n"));
1288 else {
1289 entry->proc_fops = &acpi_video_bus_ROM_fops;
1290 entry->data = acpi_driver_data(device);
1291 entry->owner = THIS_MODULE;
1292 }
1293
1294 /* 'POST_info' [R] */
1295 entry = create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
1296 if (!entry)
1297 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'POST_info' fs entry\n"));
1298 else {
1299 entry->proc_fops = &acpi_video_bus_POST_info_fops;
1300 entry->data = acpi_driver_data(device);
1301 entry->owner = THIS_MODULE;
1302 }
1303
1304 /* 'POST' [R/W] */
1305 entry = create_proc_entry("POST", S_IFREG|S_IRUGO|S_IRUSR, acpi_device_dir(device));
1306 if (!entry)
1307 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'POST' fs entry\n"));
1308 else {
1309 entry->proc_fops = &acpi_video_bus_POST_fops;
1310 entry->proc_fops->write = acpi_video_bus_write_POST;
1311 entry->data = acpi_driver_data(device);
1312 entry->owner = THIS_MODULE;
1313 }
1314
1315 /* 'DOS' [R/W] */
1316 entry = create_proc_entry("DOS", S_IFREG|S_IRUGO|S_IRUSR, acpi_device_dir(device));
1317 if (!entry)
1318 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'DOS' fs entry\n"));
1319 else {
1320 entry->proc_fops = &acpi_video_bus_DOS_fops;
1321 entry->proc_fops->write = acpi_video_bus_write_DOS;
1322 entry->data = acpi_driver_data(device);
1323 entry->owner = THIS_MODULE;
1324 }
1325
1326 return_VALUE(0);
1327}
1328
1329static int
1330acpi_video_bus_remove_fs (
1331 struct acpi_device *device)
1332{
1333 struct acpi_video_bus *video;
1334
1335 ACPI_FUNCTION_TRACE("acpi_video_bus_remove_fs");
1336
1337 video = (struct acpi_video_bus *) acpi_driver_data(device);
1338
1339 if (acpi_device_dir(device)) {
1340 remove_proc_entry("info", acpi_device_dir(device));
1341 remove_proc_entry("ROM", acpi_device_dir(device));
1342 remove_proc_entry("POST_info", acpi_device_dir(device));
1343 remove_proc_entry("POST", acpi_device_dir(device));
1344 remove_proc_entry("DOS", acpi_device_dir(device));
1345 remove_proc_entry(acpi_device_bid(device),
1346 acpi_video_dir);
1347 acpi_device_dir(device) = NULL;
1348 }
1349
1350 return_VALUE(0);
1351}
1352
1353/* --------------------------------------------------------------------------
1354 Driver Interface
1355 -------------------------------------------------------------------------- */
1356
1357/* device interface */
1358
1359static int
1360acpi_video_bus_get_one_device (
1361 struct acpi_device *device,
1362 struct acpi_video_bus *video)
1363{
1364 unsigned long device_id;
1365 int status, result;
1366 struct acpi_video_device *data;
1367
1368 ACPI_FUNCTION_TRACE("acpi_video_bus_get_one_device");
1369
1370 if (!device || !video)
1371 return_VALUE(-EINVAL);
1372
1373 status = acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
1374 if (ACPI_SUCCESS(status)) {
1375
1376 data = kmalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
1377 if (!data)
1378 return_VALUE(-ENOMEM);
1379
1380 memset(data, 0, sizeof(struct acpi_video_device));
1381
1382 data->handle = device->handle;
1383 strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
1384 strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
1385 acpi_driver_data(device) = data;
1386
1387 data->device_id = device_id;
1388 data->video = video;
1389 data->dev = device;
1390
1391 switch (device_id & 0xffff) {
1392 case 0x0100:
1393 data->flags.crt = 1;
1394 break;
1395 case 0x0400:
1396 data->flags.lcd = 1;
1397 break;
1398 case 0x0200:
1399 data->flags.tvout = 1;
1400 break;
1401 default:
1402 data->flags.unknown = 1;
1403 break;
1404 }
1405
1406 acpi_video_device_bind(video, data);
1407 acpi_video_device_find_cap(data);
1408
1409 status = acpi_install_notify_handler(data->handle,
1410 ACPI_DEVICE_NOTIFY, acpi_video_device_notify, data);
1411 if (ACPI_FAILURE(status)) {
1412 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1413 "Error installing notify handler\n"));
1414 result = -ENODEV;
1415 goto end;
1416 }
1417
1418 down(&video->sem);
1419 list_add_tail(&data->entry, &video->video_device_list);
1420 up(&video->sem);
1421
1422 acpi_video_device_add_fs(device);
1423
1424 return_VALUE(0);
1425 }
1426
1427end:
1428 return_VALUE(-ENOENT);
1429}
1430
1431/*
1432 * Arg:
1433 * video : video bus device
1434 *
1435 * Return:
1436 * none
1437 *
1438 * Enumerate the video device list of the video bus,
1439 * bind the ids with the corresponding video devices
1440 * under the video bus.
1441 */
1442
1443static void
1444acpi_video_device_rebind( struct acpi_video_bus *video)
1445{
1446 struct list_head * node, * next;
1447 list_for_each_safe(node, next, &video->video_device_list) {
1448 struct acpi_video_device * dev = container_of(node, struct acpi_video_device, entry);
1449 acpi_video_device_bind( video, dev);
1450 }
1451}
1452
1453/*
1454 * Arg:
1455 * video : video bus device
1456 * device : video output device under the video
1457 * bus
1458 *
1459 * Return:
1460 * none
1461 *
1462 * Bind the ids with the corresponding video devices
1463 * under the video bus.
1464 */
1465
1466static void
1467acpi_video_device_bind( struct acpi_video_bus *video,
1468 struct acpi_video_device *device)
1469{
1470 int i;
1471 ACPI_FUNCTION_TRACE("acpi_video_device_bind");
1472
1473#define IDS_VAL(i) video->attached_array[i].value.int_val
1474#define IDS_BIND(i) video->attached_array[i].bind_info
1475
1476 for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID &&
1477 i < video->attached_count; i++) {
1478 if (device->device_id == (IDS_VAL(i)& 0xffff)) {
1479 IDS_BIND(i) = device;
1480 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i));
1481 }
1482 }
1483#undef IDS_VAL
1484#undef IDS_BIND
1485}
1486
1487/*
1488 * Arg:
1489 * video : video bus device
1490 *
1491 * Return:
1492 * < 0 : error
1493 *
1494 * Call _DOD to enumerate all devices attached to display adapter
1495 *
1496 */
1497
1498static int acpi_video_device_enumerate(struct acpi_video_bus *video)
1499{
1500 int status;
1501 int count;
1502 int i;
1503 struct acpi_video_enumerated_device *active_device_list;
1504 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
1505 union acpi_object *dod = NULL;
1506 union acpi_object *obj;
1507
1508 ACPI_FUNCTION_TRACE("acpi_video_device_enumerate");
1509
1510 status = acpi_evaluate_object(video->handle, "_DOD", NULL, &buffer);
1511 if (!ACPI_SUCCESS(status)) {
1512 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _DOD\n"));
1513 return_VALUE(status);
1514 }
1515
1516 dod = (union acpi_object *) buffer.pointer;
1517 if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) {
1518 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DOD data\n"));
1519 status = -EFAULT;
1520 goto out;
1521 }
1522
1523 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n",
1524 dod->package.count));
1525
1526 active_device_list= kmalloc(
1527 (1+dod->package.count)*sizeof(struct acpi_video_enumerated_device),
1528 GFP_KERNEL);
1529
1530 if (!active_device_list) {
1531 status = -ENOMEM;
1532 goto out;
1533 }
1534
1535 count = 0;
1536 for (i = 0; i < dod->package.count; i++) {
1537 obj = (union acpi_object *) &dod->package.elements[i];
1538
1539 if (obj->type != ACPI_TYPE_INTEGER) {
1540 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DOD data\n"));
1541 active_device_list[i].value.int_val = ACPI_VIDEO_HEAD_INVALID;
1542 }
1543 active_device_list[i].value.int_val = obj->integer.value;
1544 active_device_list[i].bind_info = NULL;
1545 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, (int) obj->integer.value));
1546 count++;
1547 }
1548 active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END;
1549
1550 if(video->attached_array)
1551 kfree(video->attached_array);
1552
1553 video->attached_array = active_device_list;
1554 video->attached_count = count;
1555out:
1556 acpi_os_free(buffer.pointer);
1557 return_VALUE(status);
1558}
1559
1560/*
1561 * Arg:
1562 * video : video bus device
1563 * event : Nontify Event
1564 *
1565 * Return:
1566 * < 0 : error
1567 *
1568 * 1. Find out the current active output device.
1569 * 2. Identify the next output device to switch
1570 * 3. call _DSS to do actual switch.
1571 */
1572
1573static int
1574acpi_video_switch_output(
1575 struct acpi_video_bus *video,
1576 int event)
1577{
1578 struct list_head * node, * next;
1579 struct acpi_video_device *dev=NULL;
1580 struct acpi_video_device *dev_next=NULL;
1581 struct acpi_video_device *dev_prev=NULL;
1582 unsigned long state;
1583 int status = 0;
1584
1585 ACPI_FUNCTION_TRACE("acpi_video_switch_output");
1586
1587 list_for_each_safe(node, next, &video->video_device_list) {
1588 struct acpi_video_device * dev = container_of(node, struct acpi_video_device, entry);
1589 status = acpi_video_device_get_state(dev, &state);
1590 if (state & 0x2){
1591 dev_next = container_of(node->next, struct acpi_video_device, entry);
1592 dev_prev = container_of(node->prev, struct acpi_video_device, entry);
1593 goto out;
1594 }
1595 }
1596 dev_next = container_of(node->next, struct acpi_video_device, entry);
1597 dev_prev = container_of(node->prev, struct acpi_video_device, entry);
1598out:
1599 switch (event) {
1600 case ACPI_VIDEO_NOTIFY_CYCLE:
1601 case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
1602 acpi_video_device_set_state(dev, 0);
1603 acpi_video_device_set_state(dev_next, 0x80000001);
1604 break;
1605 case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:
1606 acpi_video_device_set_state(dev, 0);
1607 acpi_video_device_set_state(dev_prev, 0x80000001);
1608 default:
1609 break;
1610 }
1611
1612 return_VALUE(status);
1613}
1614
1615static int
1616acpi_video_get_next_level(
1617 struct acpi_video_device *device,
1618 u32 level_current,
1619 u32 event)
1620{
1621 /*Fix me*/
1622 return level_current;
1623}
1624
1625
1626static void
1627acpi_video_switch_brightness (
1628 struct acpi_video_device *device,
1629 int event)
1630{
1631 unsigned long level_current, level_next;
1632 acpi_video_device_lcd_get_level_current(device, &level_current);
1633 level_next = acpi_video_get_next_level(device, level_current, event);
1634 acpi_video_device_lcd_set_level(device, level_next);
1635}
1636
1637static int
1638acpi_video_bus_get_devices (
1639 struct acpi_video_bus *video,
1640 struct acpi_device *device)
1641{
1642 int status = 0;
1643 struct list_head *node, *next;
1644
1645 ACPI_FUNCTION_TRACE("acpi_video_get_devices");
1646
1647 acpi_video_device_enumerate(video);
1648
1649 list_for_each_safe(node, next, &device->children) {
1650 struct acpi_device *dev = list_entry(node, struct acpi_device, node);
1651
1652 if (!dev)
1653 continue;
1654
1655 status = acpi_video_bus_get_one_device(dev, video);
1656 if (ACPI_FAILURE(status)) {
1657 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Cant attach device\n"));
1658 continue;
1659 }
1660
1661 }
1662 return_VALUE(status);
1663}
1664
1665static int
1666acpi_video_bus_put_one_device(
1667 struct acpi_video_device *device)
1668{
1669 struct acpi_video_bus *video;
1670
1671 ACPI_FUNCTION_TRACE("acpi_video_bus_put_one_device");
1672
1673 if (!device || !device->video)
1674 return_VALUE(-ENOENT);
1675
1676 video = device->video;
1677
1678 down(&video->sem);
1679 list_del(&device->entry);
1680 up(&video->sem);
1681 acpi_video_device_remove_fs(device->dev);
1682
1683 return_VALUE(0);
1684}
1685
1686static int
1687acpi_video_bus_put_devices (
1688 struct acpi_video_bus *video)
1689{
1690 int status;
1691 struct list_head *node, *next;
1692
1693 ACPI_FUNCTION_TRACE("acpi_video_bus_put_devices");
1694
1695 list_for_each_safe(node, next, &video->video_device_list) {
1696 struct acpi_video_device *data = list_entry(node, struct acpi_video_device, entry);
1697 if (!data)
1698 continue;
1699
1700 status = acpi_video_bus_put_one_device(data);
1701 if(ACPI_FAILURE(status))
1702 printk(KERN_WARNING PREFIX "hhuuhhuu bug in acpi video driver.\n");
1703
1704 if (data->brightness)
1705 kfree(data->brightness);
1706
1707 kfree(data);
1708 }
1709
1710 return_VALUE(0);
1711}
1712
1713/* acpi_video interface */
1714
1715static int
1716acpi_video_bus_start_devices(
1717 struct acpi_video_bus *video)
1718{
1719 return acpi_video_bus_DOS(video, 1, 0);
1720}
1721
1722static int
1723acpi_video_bus_stop_devices(
1724 struct acpi_video_bus *video)
1725{
1726 return acpi_video_bus_DOS(video, 0, 1);
1727}
1728
1729static void
1730acpi_video_bus_notify (
1731 acpi_handle handle,
1732 u32 event,
1733 void *data)
1734{
1735 struct acpi_video_bus *video = (struct acpi_video_bus *) data;
1736 struct acpi_device *device = NULL;
1737
1738 ACPI_FUNCTION_TRACE("acpi_video_bus_notify");
1739 printk("video bus notify\n");
1740
1741 if (!video)
1742 return_VOID;
1743
1744 if (acpi_bus_get_device(handle, &device))
1745 return_VOID;
1746
1747 switch (event) {
1748 case ACPI_VIDEO_NOTIFY_SWITCH: /* User request that a switch occur,
1749 * most likely via hotkey. */
1750 acpi_bus_generate_event(device, event, 0);
1751 break;
1752
1753 case ACPI_VIDEO_NOTIFY_PROBE: /* User plug or remove a video
1754 * connector. */
1755 acpi_video_device_enumerate(video);
1756 acpi_video_device_rebind(video);
1757 acpi_video_switch_output(video, event);
1758 acpi_bus_generate_event(device, event, 0);
1759 break;
1760
1761 case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed.*/
1762 case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */
1763 case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */
1764 acpi_video_switch_output(video, event);
1765 acpi_bus_generate_event(device, event, 0);
1766 break;
1767
1768 default:
1769 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1770 "Unsupported event [0x%x]\n", event));
1771 break;
1772 }
1773
1774 return_VOID;
1775}
1776
1777static void
1778acpi_video_device_notify (
1779 acpi_handle handle,
1780 u32 event,
1781 void *data)
1782{
1783 struct acpi_video_device *video_device = (struct acpi_video_device *) data;
1784 struct acpi_device *device = NULL;
1785
1786 ACPI_FUNCTION_TRACE("acpi_video_device_notify");
1787
1788 printk("video device notify\n");
1789 if (!video_device)
1790 return_VOID;
1791
1792 if (acpi_bus_get_device(handle, &device))
1793 return_VOID;
1794
1795 switch (event) {
1796 case ACPI_VIDEO_NOTIFY_SWITCH: /* change in status (cycle output device) */
1797 case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device status) */
1798 acpi_bus_generate_event(device, event, 0);
1799 break;
1800 case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
1801 case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
1802 case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
1803 case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
1804 case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
1805 acpi_video_switch_brightness (video_device, event);
1806 acpi_bus_generate_event(device, event, 0);
1807 break;
1808 default:
1809 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1810 "Unsupported event [0x%x]\n", event));
1811 break;
1812 }
1813 return_VOID;
1814}
1815
1816static int
1817acpi_video_bus_add (
1818 struct acpi_device *device)
1819{
1820 int result = 0;
1821 acpi_status status = 0;
1822 struct acpi_video_bus *video = NULL;
1823
1824 ACPI_FUNCTION_TRACE("acpi_video_bus_add");
1825
1826 if (!device)
1827 return_VALUE(-EINVAL);
1828
1829 video = kmalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
1830 if (!video)
1831 return_VALUE(-ENOMEM);
1832 memset(video, 0, sizeof(struct acpi_video_bus));
1833
1834 video->handle = device->handle;
1835 strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
1836 strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
1837 acpi_driver_data(device) = video;
1838
1839 acpi_video_bus_find_cap(video);
1840 result = acpi_video_bus_check(video);
1841 if (result)
1842 goto end;
1843
1844 result = acpi_video_bus_add_fs(device);
1845 if (result)
1846 goto end;
1847
1848 init_MUTEX(&video->sem);
1849 INIT_LIST_HEAD(&video->video_device_list);
1850
1851 acpi_video_bus_get_devices(video, device);
1852 acpi_video_bus_start_devices(video);
1853
1854 status = acpi_install_notify_handler(video->handle,
1855 ACPI_DEVICE_NOTIFY, acpi_video_bus_notify, video);
1856 if (ACPI_FAILURE(status)) {
1857 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1858 "Error installing notify handler\n"));
1859 result = -ENODEV;
1860 goto end;
1861 }
1862
1863 printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
1864 ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
1865 video->flags.multihead ? "yes":"no",
1866 video->flags.rom ? "yes":"no",
1867 video->flags.post ? "yes":"no");
1868
1869end:
1870 if (result) {
1871 acpi_video_bus_remove_fs(device);
1872 kfree(video);
1873 }
1874
1875 return_VALUE(result);
1876}
1877
1878static int
1879acpi_video_bus_remove (
1880 struct acpi_device *device,
1881 int type)
1882{
1883 acpi_status status = 0;
1884 struct acpi_video_bus *video = NULL;
1885
1886 ACPI_FUNCTION_TRACE("acpi_video_bus_remove");
1887
1888 if (!device || !acpi_driver_data(device))
1889 return_VALUE(-EINVAL);
1890
1891 video = (struct acpi_video_bus *) acpi_driver_data(device);
1892
1893 acpi_video_bus_stop_devices(video);
1894
1895 status = acpi_remove_notify_handler(video->handle,
1896 ACPI_DEVICE_NOTIFY, acpi_video_bus_notify);
1897 if (ACPI_FAILURE(status))
1898 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1899 "Error removing notify handler\n"));
1900
1901 acpi_video_bus_put_devices(video);
1902 acpi_video_bus_remove_fs(device);
1903
1904 if (video->attached_array)
1905 kfree(video->attached_array);
1906 kfree(video);
1907
1908 return_VALUE(0);
1909}
1910
1911
1912static int
1913acpi_video_bus_match (
1914 struct acpi_device *device,
1915 struct acpi_driver *driver)
1916{
1917 acpi_handle h_dummy1;
1918 acpi_handle h_dummy2;
1919 acpi_handle h_dummy3;
1920
1921 ACPI_FUNCTION_TRACE("acpi_video_bus_match");
1922
1923 if (!device || !driver)
1924 return_VALUE(-EINVAL);
1925
1926 /* Since there is no HID, CID for ACPI Video drivers, we have
1927 * to check well known required nodes for each feature we support.
1928 */
1929
1930 /* Does this device able to support video switching ? */
1931 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) &&
1932 ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2)))
1933 return_VALUE(0);
1934
1935 /* Does this device able to retrieve a video ROM ? */
1936 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1)))
1937 return_VALUE(0);
1938
1939 /* Does this device able to configure which video head to be POSTed ? */
1940 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) &&
1941 ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) &&
1942 ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3)))
1943 return_VALUE(0);
1944
1945
1946 return_VALUE(-ENODEV);
1947}
1948
1949
1950static int __init
1951acpi_video_init (void)
1952{
1953 int result = 0;
1954
1955 ACPI_FUNCTION_TRACE("acpi_video_init");
1956
1957 /*
1958 acpi_dbg_level = 0xFFFFFFFF;
1959 acpi_dbg_layer = 0x08000000;
1960 */
1961
1962 acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
1963 if (!acpi_video_dir)
1964 return_VALUE(-ENODEV);
1965 acpi_video_dir->owner = THIS_MODULE;
1966
1967 result = acpi_bus_register_driver(&acpi_video_bus);
1968 if (result < 0) {
1969 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
1970 return_VALUE(-ENODEV);
1971 }
1972
1973 return_VALUE(0);
1974}
1975
1976static void __exit
1977acpi_video_exit (void)
1978{
1979 ACPI_FUNCTION_TRACE("acpi_video_exit");
1980
1981 acpi_bus_unregister_driver(&acpi_video_bus);
1982
1983 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
1984
1985 return_VOID;
1986}
1987
1988module_init(acpi_video_init);
1989module_exit(acpi_video_exit);